diff options
Diffstat (limited to 'unit')
-rw-r--r-- | unit/test-mesh-crypto.c | 2000 |
1 files changed, 2000 insertions, 0 deletions
diff --git a/unit/test-mesh-crypto.c b/unit/test-mesh-crypto.c new file mode 100644 index 000000000..6acb9c0b6 --- /dev/null +++ b/unit/test-mesh-crypto.c @@ -0,0 +1,2000 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#include "client/display.h" + +#include "mesh/crypto.c" + +struct mesh_crypto_test { + const char *name; + + const char *dev_key; + const char *app_key; + const char *net_key; + const char *uuid; + uint32_t iv_index; + + uint8_t net_nid; + uint8_t key_aid; + bool md[32]; + bool szmic; + bool frnd; + bool ctl; + bool segmented; + bool relay; + bool akf; + bool kr; + bool ivu; + bool network_only; + uint8_t seg_max; + uint8_t seg_num; + uint8_t opcode; + uint8_t net_ttl; + uint16_t seqZero; + uint32_t app_seq; + uint32_t net_seq[32]; + uint16_t net_src; + uint16_t net_dst; + const char *app_msg; + + const char *ikm; + const char *okm; + const char *info; + const char *salt; + const char *salt_out; + const char *nid; + const char *lpn_addr; + const char *lpn_cntr; + const char *fn_addr; + const char *fn_cntr; + const char *p; + const char *short_net_id; + const char *net_key_id; + const char *aid; + + const char *enc_key; + const char *net_id; + const char *net_nonce[32]; + const char *app_nonce; + const char *priv_key; + const char *priv_rand[32]; + + const char *enc_msg; + uint32_t app_mic32; + uint64_t app_mic64; + + const char *trans_pkt[32]; + const char *net_msg[32]; + uint32_t net_mic32[32]; + uint64_t net_mic64; + + const char *packet[32]; + + uint8_t beacon_type; + uint8_t beacon_flags; + const char *beacon_cmac; + const char *beacon; + + const char *rand; + const char *ident_res_key; + const char *hash_input; + const char *mesh_id_hash; + const char *identity_hash; +}; + +static const struct mesh_crypto_test s8_1_1 = { + .name = "8.1.1 s1 SALT generation function", + .salt = "test", + .salt_out = "b73cefbd641ef2ea598c2b6efb62f79c", +}; + +static const struct mesh_crypto_test s8_1_2 = { + .name = "8.1.2 k1 function", + .ikm = "3216d1509884b533248541792b877f98", + .salt = "salt", + .info = "info", + .okm = "f6ed15a8934afbe7d83e8dcb57fcf5d7", +}; + +static const struct mesh_crypto_test s8_1_3 = { + .name = "8.1.3 k2 function (master)", + .net_key = "f7a2a44f8e8a8029064f173ddc1e2b00", + .p = "00", + .nid = "7f", + .enc_key = "9f589181a0f50de73c8070c7a6d27f46", + .priv_key = "4c715bd4a64b938f99b453351653124f", +}; + +static const struct mesh_crypto_test s8_1_4 = { + .name = "8.1.4 k2 function (friendship)", + .frnd = true, + .lpn_addr = "0203", + .fn_addr = "0405", + .lpn_cntr = "0607", + .fn_cntr = "0809", + .net_key = "f7a2a44f8e8a8029064f173ddc1e2b00", + .p = "010203040506070809", + .nid = "73", + .enc_key = "11efec0642774992510fb5929646df49", + .priv_key = "d4d7cc0dfa772d836a8df9df5510d7a7", +}; + +static const struct mesh_crypto_test s8_1_5 = { + .name = "8.1.5 k3 function", + .net_key = "f7a2a44f8e8a8029064f173ddc1e2b00", + .salt = "smk3", + .info = "id64\01", + .short_net_id = "ff046958233db014", +}; + +static const struct mesh_crypto_test s8_1_6 = { + .name = "8.1.6 k4 function", + .app_key = "3216d1509884b533248541792b877f98", + .salt = "smk4", + .info = "id6\01", + .aid = "38", +}; + + +static const struct mesh_crypto_test s8_2_1 = { + .name = "8.2.1 Application key AID", + .app_key = "63964771734fbd76e3b40519d1d94a48", + .salt = "smk4", + .info = "id6\01", + .aid = "26", +}; + +static const struct mesh_crypto_test s8_2_2 = { + .name = "8.2.2 Encryption and privacy keys (Master)", + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .p = "00", + .nid = "68", + .enc_key = "0953fa93e7caac9638f58820220a398e", + .priv_key = "8b84eedec100067d670971dd2aa700cf", +}; + +static const struct mesh_crypto_test s8_2_3 = { + .name = "8.2.3 Encryption and privacy keys (Friendship)", + .frnd = true, + .lpn_addr = "1201", + .fn_addr = "2345", + .lpn_cntr = "0000", + .fn_cntr = "072f", + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .p = "01120123450000072f", + .nid = "5e", + .enc_key = "be635105434859f484fc798e043ce40e", + .priv_key = "5d396d4b54d3cbafe943e051fe9a4eb8", +}; + +static const struct mesh_crypto_test s8_2_4 = { + .name = "8.2.4 Network ID", + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .salt = "smk3", + .info = "id64\01", + .short_net_id = "3ecaff672f673370", +}; + +static const struct mesh_crypto_test s8_2_5 = { + .name = "8.2.5 Identity Key", + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .salt = "nkik", + .info = "id128\01", + .enc_key = "84396c435ac48560b5965385253e210c", +}; + +static const struct mesh_crypto_test s8_2_6 = { + .name = "8.2.6 Beacon Key", + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .salt = "nkbk", + .info = "id128\01", + .enc_key = "5423d967da639a99cb02231a83f7d254", +}; + +static const struct mesh_crypto_test s8_3_1 = { + .name = "8.3.1 Message #1", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_ttl = 0x00, + .net_seq = {0x000001}, + .net_src = 0x1201, + .net_dst = 0xfffd, + .opcode = NET_OP_FRND_REQUEST, + .trans_pkt = {"034b50057e400000010000"}, + .net_nid = 0x68, + + + .ctl = true, + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"00800000011201000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + .priv_rand = {"000000000012345678b5e5bfdacbaf6c"}, + + .net_msg = {"b5e5bfdacbaf6cb7fb6bff871f"}, + .net_mic64 = 0x035444ce83a670df, + + .packet = {"68eca487516765b5e5bfdacbaf6cb7fb6bff871f035444ce83a670df"}, +}; + +static const struct mesh_crypto_test s8_3_2 = { + .name = "8.3.2 Message #2", + + .iv_index = 0x12345678, + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + + .ctl = true, + .net_ttl = 0x00, + .net_seq = {0x014820}, + .net_src = 0x2345, + .net_dst = 0x1201, + .trans_pkt = {"04320308ba072f"}, + .net_nid = 0x68, + + + .opcode = NET_OP_FRND_OFFER, + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"00800148202345000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + + .net_msg = {"79d7dbc0c9b4d43eeb"}, + .net_mic64 = 0xec129d20a620d01e, + + .priv_rand = {"00000000001234567879d7dbc0c9b4d4"}, + .packet = {"68d4c826296d7979d7dbc0c9b4d43eebec129d20a620d01e"}, +}; + +static const struct mesh_crypto_test s8_3_3 = { + .name = "8.3.3 Message #3", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .ctl = true, + .net_ttl = 0x00, + .net_seq = {0x2b3832}, + .net_dst = 0x1201, + .net_src = 0x2fe3, + .trans_pkt = {"04fa0205a6000a"}, + .net_nid = 0x68, + + + .opcode = NET_OP_FRND_OFFER, + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"00802b38322fe3000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + .priv_rand = {"00000000001234567853273086b8c5ee"}, + + .net_msg = {"53273086b8c5ee00bd"}, + .net_mic64 = 0xd9cfcc62a2ddf572, + + .packet = {"68da062bc96df253273086b8c5ee00bdd9cfcc62a2ddf572"}, +}; + +static const struct mesh_crypto_test s8_3_4 = { + .name = "8.3.4 Message #4", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_nid = 0x5e, + .net_ttl = 0x00, + .net_seq = {0x000002}, + .net_dst = 0x2345, + .net_src = 0x1201, + .trans_pkt = {"0100"}, + + .frnd = true, + .lpn_addr = "1201", + .fn_addr = "2345", + .lpn_cntr = "0000", + .fn_cntr = "072f", + .p = "01120123450000072f", + + .ctl = true, + .opcode = NET_OP_FRND_POLL, + .enc_key = "be635105434859f484fc798e043ce40e", + .net_nonce = {"00800000021201000012345678"}, + .priv_key = "5d396d4b54d3cbafe943e051fe9a4eb8", + .priv_rand = {"000000000012345678b0e5d0ad970d57"}, + + .net_msg = {"b0e5d0ad"}, + .net_mic64 = 0x970d579a4e88051c, + + .packet = {"5e84eba092380fb0e5d0ad970d579a4e88051c"}, +}; + +static const struct mesh_crypto_test s8_3_5 = { + .name = "8.3.5 Message #5", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_nid = 0x5e, + .net_ttl = 0x00, + .net_seq = {0x014834}, + .net_src = 0x2345, + .net_dst = 0x1201, + .trans_pkt = {"02001234567800"}, + + .frnd = true, + .lpn_addr = "1201", + .fn_addr = "2345", + .lpn_cntr = "0000", + .fn_cntr = "072f", + .p = "01120123450000072f", + + .ctl = true, + .opcode = NET_OP_FRND_UPDATE, + .enc_key = "be635105434859f484fc798e043ce40e", + .net_nonce = {"00800148342345000012345678"}, + .priv_key = "5d396d4b54d3cbafe943e051fe9a4eb8", + .priv_rand = {"0000000000123456785c39da1792b1fe"}, + + .net_msg = {"5c39da1792b1fee9ec"}, + .net_mic64 = 0x74b786c56d3a9dee, + + .packet = {"5eafd6f53c43db5c39da1792b1fee9ec74b786c56d3a9dee"}, +}; + +static const struct mesh_crypto_test s8_3_6 = { + .name = "8.3.6 Message #6", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .dev_key = "9d6dd0e96eb25dc19a40ed9914f8f03f", + .iv_index = 0x12345678, + + .segmented = true, + .net_nid = 0x68, + .net_ttl = 0x04, + .app_seq = 0x3129ab, + .net_seq = {0x3129ab, + 0x3129ac}, + .net_src = 0x0003, + .net_dst = 0x1201, + .app_msg = "0056341263964771734fbd76e3b40519d1d94a48", + .enc_msg = "ee9dddfd2169326d23f3afdfcfdc18c52fdef772", + .app_mic32 = 0xe0e17308, + + .enc_key = "0953fa93e7caac9638f58820220a398e", + .app_nonce = "02003129ab0003120112345678", + + .priv_key = "8b84eedec100067d670971dd2aa700cf", + + .net_nonce = {"00043129ab0003000012345678", + "00043129ac0003000012345678"}, + + .priv_rand = {"0000000000123456780afba8c63d4e68", + "0000000000123456786cae0c032bf074"}, + + .trans_pkt = {"8026ac01ee9dddfd2169326d23f3afdf", + "8026ac21cfdc18c52fdef772e0e17308"}, + + .net_msg = {"0afba8c63d4e686364979deaf4fd40961145", + "6cae0c032bf0746f44f1b8cc8ce5edc57e55"}, + + .net_mic32 = {0x939cda0e, + 0xbeed49c0}, + + .packet = {"68cab5c5348a230afba8c63d4e686364979deaf4fd40961145939cda0e", + "681615b5dd4a846cae0c032bf0746f44f1b8cc8ce5edc57e55beed49c0"}, +}; + +static const struct mesh_crypto_test s8_3_7 = { + .name = "8.3.7 Message #7", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_nid = 0x68, + .relay = true, + .ctl = true, + .net_ttl = 0x0b, + .net_seq = {0x014835}, + .net_src = 0x2345, + .net_dst = 0x0003, + .opcode = NET_OP_SEG_ACKNOWLEDGE, + .seqZero = 0x09ab, + .trans_pkt = {"00a6ac00000002"}, + + + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"008b0148352345000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + .priv_rand = {"0000000000123456780d0d730f94d7f3"}, + + .net_msg = {"0d0d730f94d7f3509d"}, + .net_mic64 = 0xf987bb417eb7c05f, + + .packet = {"68e476b5579c980d0d730f94d7f3509df987bb417eb7c05f"}, +}; + +static const struct mesh_crypto_test s8_3_8 = { + .name = "8.3.8 Message #8", + .network_only = true, /* Test has incomplete Access Payload */ + .seg_max = 1, + .seg_num = 0, + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_nid = 0x68, + .relay = true, + .net_ttl = 0x04, + .net_seq = {0x3129ad}, + .net_src = 0x0003, + .net_dst = 0x1201, + .segmented = true, + .seqZero = 0x09ab, + .trans_pkt = {"8026ac01ee9dddfd2169326d23f3afdf"}, + + + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"00043129ad0003000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + .priv_rand = {"0000000000123456780e2f91add6f06e"}, + + .net_msg = {"0e2f91add6f06e66006844cec97f973105ae"}, + .net_mic32 = {0x2534f958}, + + .packet = {"684daa6267c2cf0e2f91add6f06e66006844cec97f973105ae2534f958"}, +}; + + +static const struct mesh_crypto_test s8_3_9 = { + .name = "8.3.9 Message #9", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .net_nid = 0x68, + .relay = true, + .ctl = true, + .net_ttl = 0x0b, + .net_seq = {0x014836}, + .net_src = 0x2345, + .net_dst = 0x0003, + .opcode = NET_OP_SEG_ACKNOWLEDGE, + .seqZero = 0x09ab, + .trans_pkt = {"00a6ac00000003"}, + + + .enc_key = "0953fa93e7caac9638f58820220a398e", + .net_nonce = {"008b0148362345000012345678"}, + .priv_key = "8b84eedec100067d670971dd2aa700cf", + .priv_rand = {"000000000012345678d85d806bbed248"}, + + .net_msg = {"d85d806bbed248614f"}, + .net_mic64 = 0x938067b0d983bb7b, + + .packet = {"68aec467ed4901d85d806bbed248614f938067b0d983bb7b"}, +}; + +static const struct mesh_crypto_test s8_3_10 = { + .name = "8.3.10 Message #10", + + .iv_index = 0x12345678, + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + + .net_nid = 0x5e, + .net_ttl = 0x00, + .net_seq = {0x000003}, + .net_src = 0x1201, + .net_dst = 0x2345, + .trans_pkt = {"0101"}, + + .frnd = true, + .lpn_addr = "1201", + .fn_addr = "2345", + .lpn_cntr = "0000", + .fn_cntr = "072f", + .p = "01120123450000072f", + + .ctl = true, + .opcode = NET_OP_FRND_POLL, + .enc_key = "be635105434859f484fc798e043ce40e", + .net_nonce = {"00800000031201000012345678"}, + .priv_key = "5d396d4b54d3cbafe943e051fe9a4eb8", + .priv_rand = {"0000000000123456787777ed355afaf6"}, + + .net_msg = {"7777ed35"}, + .net_mic64 = 0x5afaf66d899c1e3d, + + .packet = {"5e7b786568759f7777ed355afaf66d899c1e3d"}, +}; + +static const struct mesh_crypto_test s8_3_11 = { + .name = "8.3.11 Message #11", + + /* Test has incomplete Access Payload */ + .network_only = true, + .seg_max = 1, + .seg_num = 0, + + .frnd = true, + .lpn_addr = "1201", + .fn_addr = "2345", + .lpn_cntr = "0000", + .fn_cntr = "072f", + .p = "01120123450000072f", + + .iv_index = 0x12345678, + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + + .net_nid = 0x5e, + .net_ttl = 0x03, + .net_seq = {0x3129ad}, + .net_src = 0x0003, + .net_dst = 0x1201, + .akf = true, + .key_aid = 0x00, + .segmented = true, + .seqZero = 0x09ab, + .trans_pkt = {"c026ac01ee9dddfd2169326d23f3afdf"}, + + .enc_key = "be635105434859f484fc798e043ce40e", + .net_nonce = {"00033129ad0003000012345678"}, + .priv_key = "5d396d4b54d3cbafe943e051fe9a4eb8", + .priv_rand = {"000000000012345678d5e748a20ecfd9"}, + + .net_msg = {"d5e748a20ecfd98ddfd32de80befb400213d"}, + .net_mic32 = {0x113813b5}, + + .packet = {"5e6ebfc021edf5d5e748a20ecfd98ddfd32de80befb400213d113813b5"}, +}; + +static const struct mesh_crypto_test s8_4_3 = { + .name = "8.4.3 Secure Network Beacon", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .iv_index = 0x12345678, + + .enc_key = "5423d967da639a99cb02231a83f7d254", + .net_id = "3ecaff672f673370", + + .beacon_type = 0x01, + .beacon_flags = 0x00, + .beacon_cmac = "8ea261582f364f6f", + .beacon = "01003ecaff672f673370123456788ea261582f364f6f", +}; + +static const struct mesh_crypto_test s8_6_2 = { + .name = "8.6.2 Service Data using Node Identity", + + .net_key = "7dd7364cd842ad18c17c2b820c84c3d6", + .net_src = 0x1201, + .rand = "34ae608fbbc1f2c6", + .ident_res_key = "84396c435ac48560b5965385253e210c", + + .hash_input = "00000000000034ae608fbbc1f2c61201", + .identity_hash = "00861765aefcc57b", + .beacon = "0100861765aefcc57b34ae608fbbc1f2c6", +}; + +#define PASS COLOR_GREEN "PASS" COLOR_OFF +#define FAIL COLOR_RED "FAIL" COLOR_OFF +#define INVAL COLOR_YELLOW "INVALID" COLOR_OFF + +#define EVALCMP(a, b, l) memcmp((a), (b), (l)) ? FAIL : PASS +#define EVALSTR(a, b) (a) && (b) ? (strcmp((a), (b)) ? FAIL : PASS) : INVAL +#define EVALNUM(a, b) a == b ? PASS : FAIL +#define EVALBOOLNOTBOTH(a, b) !(a && b) ? PASS : FAIL + +static void verify_data(const char *label, unsigned int indent, + const char *sample, const uint8_t *data, size_t size) +{ + char *str; + + str = l_util_hexstring(data, size); + l_info("%-20s =%*c%s", label, 1 + (indent * 2), ' ', sample); + l_info("%-20s %*c%s => %s", "", 1 + (indent * 2), ' ', str, + EVALSTR(sample, str)); + l_free(str); +} + +static void verify_bool_not_both(const char *label, unsigned int indent, + bool sample, bool data) +{ + l_info("%-20s =%*c%s", label, 1 + (indent * 2), ' ', + sample ? "true" : "false"); + l_info("%-20s %*c%s => %s", "", 1 + (indent * 2), ' ', + data ? "true" : "false", + EVALBOOLNOTBOTH(sample, data)); +} + +static void verify_uint8(const char *label, unsigned int indent, + uint8_t sample, uint8_t data) +{ + l_info("%-20s =%*c%02x", label, 1 + (indent * 2), ' ', sample); + l_info("%-20s %*c%02x => %s", "", 1 + (indent * 2), ' ', data, + EVALNUM(sample, data)); +} + +static void verify_uint16(const char *label, unsigned int indent, + uint16_t sample, uint16_t data) +{ + l_info("%-20s =%*c%04x", label, 1 + (indent * 2), ' ', sample); + l_info("%-20s %*c%04x => %s", "", 1 + (indent * 2), ' ', data, + EVALNUM(sample, data)); +} + +static void verify_uint24(const char *label, unsigned int indent, + uint32_t sample, uint32_t data) +{ + l_info("%-20s =%*c%06x", label, 1 + (indent * 2), ' ', sample); + l_info("%-20s %*c%06x => %s", "", 1 + (indent * 2), ' ', data, + EVALNUM(sample, data)); +} + +static void verify_uint32(const char *label, unsigned int indent, + uint32_t sample, uint32_t data) +{ + l_info("%-20s =%*c%08x", label, 1 + (indent * 2), ' ', sample); + l_info("%-20s %*c%08x => %s", "", 1 + (indent * 2), ' ', data, + EVALNUM(sample, data)); +} + +static void verify_uint64(const char *label, unsigned int indent, + uint64_t sample, uint64_t data) +{ + l_info("%-20s =%*c%16llx", label, 1 + (indent * 2), ' ', + (long long unsigned int) sample); + l_info("%-20s %*c%16llx => %s", "", 1 + (indent * 2), ' ', + (long long unsigned int) data, + EVALNUM(sample, data)); +} + +static void show_str(const char *label, unsigned int indent, + const char *sample) +{ + char *printable = l_malloc(strlen(sample) + 1); + char *tmp = printable; + + while (*sample) { + if (l_ascii_isprint(*sample)) + *tmp++ = *sample++; + else { + *tmp++ = '?'; + sample++; + } + } + + *tmp = '\0'; + + l_info("%-20s =%*c%s", label, 1 + (indent * 2), ' ', printable); + l_free(printable); +} + +static void show_data(const char *label, unsigned int indent, + const void *data, size_t size) +{ + char *str; + + str = l_util_hexstring(data, size); + l_info("%-20s =%*c%s", label, 1 + (indent * 2), ' ', str); + l_free(str); +} + +static void show_uint8(const char *label, unsigned int indent, uint8_t data) +{ + l_info("%-20s =%*c%2.2x", label, 1 + (indent * 2), ' ', data); +} + +static void show_uint32(const char *label, unsigned int indent, uint32_t data) +{ + l_info("%-20s =%*c%8.8x", label, 1 + (indent * 2), ' ', data); +} + + +static void check_encrypt_segment(const struct mesh_crypto_test *keys, + uint16_t seg, uint16_t seg_max, + uint8_t *enc_msg, size_t len, + uint8_t *enc_key, uint8_t *priv_key, + uint8_t nid) +{ + uint8_t net_nonce[13]; + uint8_t priv_rand[16]; + uint8_t packet[29]; + uint8_t packet_len; + uint64_t net_mic64; + uint32_t hdr, net_mic32; + size_t net_msg_len; + uint8_t key_aid = keys->key_aid | (keys->akf ? KEY_ID_AKF : 0x00); + + if (keys->ctl) { + mesh_crypto_packet_build(keys->ctl, keys->net_ttl, + keys->net_seq[0], + keys->net_src, keys->net_dst, + keys->opcode, + keys->segmented, key_aid, + keys->szmic, keys->relay, keys->seqZero, + seg, seg_max, + enc_msg, len, + packet, &packet_len); + } else { + mesh_crypto_packet_build(keys->ctl, keys->net_ttl, + keys->net_seq[0], + keys->net_src, keys->net_dst, + keys->opcode, + keys->segmented, key_aid, + keys->szmic, keys->relay, keys->seqZero, + seg, seg_max, + enc_msg, len, + packet, &packet_len); + } + + l_info(COLOR_YELLOW "Segment-%d" COLOR_OFF, seg); + + hdr = l_get_be32(packet + 9); + verify_uint8("SEG", 9, keys->segmented << (SEG_HDR_SHIFT % 8), + packet[9] & (1 << (SEG_HDR_SHIFT % 8))); + + if (keys->ctl) { + verify_uint8("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT % 8), + (packet[9] & OPCODE_MASK) << + (OPCODE_HDR_SHIFT % 8)); + } else { + verify_uint8("AKF", 9, keys->akf << (AKF_HDR_SHIFT % 8), + packet[9] & (1 << (AKF_HDR_SHIFT % 8))); + verify_uint8("AID", 9, + keys->key_aid << (KEY_HDR_SHIFT % 8), + (packet[9] & KEY_AID_MASK) << + (KEY_HDR_SHIFT % 8)); + } + + verify_uint8("SZMIC", 10, + keys->szmic << (SZMIC_HDR_SHIFT % 8), + packet[10] & (1 << (SZMIC_HDR_SHIFT % 8))); + + /* Awkward shift-by-two for correct display */ + verify_uint16("SeqZero", 10, + (keys->seqZero & SEQ_ZERO_MASK) << 2, + ((hdr >> SEQ_ZERO_HDR_SHIFT) & SEQ_ZERO_MASK) + << 2); + verify_uint16("SegO", 11, + (seg & SEG_MASK) << SEGO_HDR_SHIFT, + hdr & (SEG_MASK << SEGO_HDR_SHIFT)); + verify_uint8("SegN", 12, + (seg_max & SEG_MASK) << SEGN_HDR_SHIFT, + hdr & (SEG_MASK << SEGN_HDR_SHIFT)); + show_data("Payload", 13, enc_msg, len); + len += 4; + + + mesh_crypto_network_nonce(keys->ctl, keys->net_ttl, + keys->net_seq[0], keys->net_src, + keys->iv_index, net_nonce); + + verify_data("TransportData", 9, keys->trans_pkt[0], + packet + 9, len); + + verify_uint16("DST", 7, keys->net_dst, l_get_be16(packet + 7)); + net_msg_len = len + 2; + show_data("TransportPayload", 7, packet + 7, net_msg_len); + + mesh_crypto_network_encrypt(keys->ctl, + keys->net_ttl, keys->net_seq[0], + keys->net_src, + keys->iv_index, enc_key, + packet + 7, len + 2, packet + 7, + keys->ctl ? (void *)&net_mic64 : + (void *)&net_mic32); + + mesh_crypto_privacy_counter(keys->iv_index, packet + 7, priv_rand); + + l_info(""); + show_uint32("IVindex", 0, keys->iv_index); + verify_data("NetworkNonce", 0, keys->net_nonce[0], net_nonce, 13); + verify_data("PrivacyRandom", 0, keys->priv_rand[0], priv_rand, 16); + + show_uint8("INI", 0, (keys->iv_index & 0x01) << 7); + verify_uint8("NID", 0, keys->net_nid, nid); + verify_uint8("CTL", 1, keys->ctl << 7, packet[1] & 0x80); + verify_uint8("TTL", 1, keys->net_ttl, packet[1] & 0x7f); + verify_uint24("SEQ", 2, keys->net_seq[0], + l_get_be32(packet + 1) & SEQ_MASK); + verify_uint16("SRC", 5, keys->net_src, l_get_be16(packet + 5)); + + verify_data("EncNetworkPayload", 7, keys->net_msg[0], + packet + 7, net_msg_len); + if (keys->ctl) { + verify_uint64("NetworkMIC", 7 + net_msg_len, + keys->net_mic64, net_mic64); + net_msg_len += 8; + } else { + verify_uint32("NetworkMIC", 7 + net_msg_len, + keys->net_mic32[0], net_mic32); + net_msg_len += 4; + } + + show_data("PreObsPayload", 1, packet + 1, 6 + net_msg_len); + mesh_crypto_network_obfuscate(priv_key, priv_rand, + keys->ctl, + keys->net_ttl, keys->net_seq[0], + keys->net_src, packet + 1); + show_data("PostObsPayload", 1, packet + 1, 6 + net_msg_len); + + packet[0] = (keys->iv_index & 0x01) << 7 | nid; + packet_len = 7 + net_msg_len; + + verify_data("Packet", 0, keys->packet[0], packet, packet_len); + l_info(""); + +} + +static void check_encrypt(const struct mesh_crypto_test *keys) +{ + uint8_t *dev_key; + uint8_t *app_key; + uint8_t *net_key; + uint8_t nid; + uint8_t enc_key[16]; + uint8_t priv_key[16]; + uint8_t net_nonce[13]; + uint8_t app_nonce[13]; + uint8_t priv_rand[16]; + uint8_t p[9]; + size_t p_len; + size_t aad_len = 0; + uint8_t *aad; + size_t app_msg_len; + uint8_t *app_msg = NULL; + uint8_t *enc_msg; + uint32_t app_mic32; + uint64_t app_mic64; + size_t net_msg_len; + uint32_t net_mic32; + uint64_t net_mic64; + uint8_t key_aid; + uint8_t packet[29]; + uint8_t packet_len; + uint16_t i, seg_max, seg_len = 0; + uint32_t seqZero, hdr; + + l_info(COLOR_BLUE "[Encrypt %s]" COLOR_OFF, keys->name); + verify_bool_not_both("CTL && Segmented", 0, keys->ctl, keys->segmented); + + dev_key = l_util_from_hexstring(keys->dev_key, NULL); + app_key = l_util_from_hexstring(keys->app_key, NULL); + net_key = l_util_from_hexstring(keys->net_key, NULL); + aad = l_util_from_hexstring(keys->uuid, &aad_len); + + show_data("NetworkKey", 0, net_key, 16); + + if (keys->akf) { + mesh_crypto_k4(app_key, &key_aid); + key_aid |= KEY_ID_AKF; + } else { + key_aid = 0; + } + + if (keys->frnd) { + uint8_t *lpn_addr, *fn_addr, *lpn_cntr, *fn_cntr; + + lpn_addr = l_util_from_hexstring(keys->lpn_addr, NULL); + fn_addr = l_util_from_hexstring(keys->fn_addr, NULL); + lpn_cntr = l_util_from_hexstring(keys->lpn_cntr, NULL); + fn_cntr = l_util_from_hexstring(keys->fn_cntr, NULL); + + show_data("LPN Address", 0, lpn_addr, 2); + show_data("Friend Address", 0, fn_addr, 2); + show_data("LPN Counter", 0, lpn_cntr, 2); + show_data("Friend Counter", 0, fn_cntr, 2); + l_info(""); + + p[0] = 1; + l_put_be16(l_get_be16(lpn_addr), p + 1); + l_put_be16(l_get_be16(fn_addr), p + 3); + l_put_be16(l_get_be16(lpn_cntr), p + 5); + l_put_be16(l_get_be16(fn_cntr), p + 7); + p_len = 9; + + l_free(fn_cntr); + l_free(lpn_cntr); + l_free(fn_addr); + l_free(lpn_addr); + } else { + p[0] = 0; + p_len = 1; + } + + if (p_len > 1) verify_data("P", 0, keys->p, p, p_len); + + mesh_crypto_k2(net_key, p, p_len, &nid, enc_key, priv_key); + + verify_data("EncryptionKey", 0, keys->enc_key, enc_key, + sizeof(enc_key)); + verify_data("PrivacyKey", 0, keys->priv_key, priv_key, + sizeof(priv_key)); + verify_uint8("NID", 0, keys->net_nid, nid); + + if (keys->network_only) { + enc_msg = l_util_from_hexstring(keys->trans_pkt[0], + &app_msg_len); + check_encrypt_segment(keys, keys->seg_num, keys->seg_max, + enc_msg + 4, app_msg_len - 4, + enc_key, priv_key, nid); + goto done; + } + + if (keys->akf) + mesh_crypto_application_nonce(keys->app_seq, keys->net_src, + keys->net_dst, keys->iv_index, + keys->szmic, app_nonce); + else + mesh_crypto_device_nonce(keys->app_seq, keys->net_src, + keys->net_dst, keys->iv_index, + keys->szmic, app_nonce); + + seqZero = keys->app_seq; + + if (!keys->ctl) { + app_msg = l_util_from_hexstring(keys->app_msg, &app_msg_len); + + if (keys->szmic) { + seg_max = SEG_MAX(app_msg_len + 8); + enc_msg = l_malloc(app_msg_len + 8); + mesh_crypto_application_encrypt(key_aid, keys->app_seq, + keys->net_src, keys->net_dst, + keys->iv_index, + keys->akf ? app_key : dev_key, + aad, aad_len, + app_msg, app_msg_len, + enc_msg, &app_mic64, sizeof(app_mic64)); + l_put_be64(app_mic64, enc_msg + app_msg_len); + } else { + seg_max = SEG_MAX(app_msg_len + 4); + enc_msg = l_malloc(app_msg_len + 4); + mesh_crypto_application_encrypt(key_aid, keys->app_seq, + keys->net_src, keys->net_dst, + keys->iv_index, + keys->akf ? app_key : dev_key, + aad, aad_len, + app_msg, app_msg_len, + enc_msg, &app_mic32, sizeof(app_mic32)); + l_put_be32(app_mic32, enc_msg + app_msg_len); + } + + if (keys->dev_key && !keys->akf) + show_data("DeviceKey", 0, dev_key, 16); + + if (keys->app_key && keys->akf) + show_data("ApplicationKey", 0, app_key, 16); + + if (aad) show_data("UUID", 0, aad, 16); + + verify_data("EncryptionKey", 0, keys->enc_key, enc_key, 16); + verify_data("ApplicationNonce", 0, keys->app_nonce, + app_nonce, 13); + verify_data("PrivacyKey", 0, keys->priv_key, priv_key, 16); + + show_data("AppPayload", 0, app_msg, app_msg_len); + verify_data("EncryptedAppPayload", 0, keys->enc_msg, enc_msg, + app_msg_len); + if (keys->szmic) { + verify_uint64("ApplicationMIC", app_msg_len, + keys->app_mic64, app_mic64); + app_msg_len += 8; + } else { + verify_uint32("ApplicationMIC", app_msg_len, + keys->app_mic32, app_mic32); + app_msg_len += 4; + } + } else { + enc_msg = l_util_from_hexstring(keys->trans_pkt[0], + &app_msg_len); + seg_max = 0; + app_msg_len--; + } + + for (i = 0; i <= seg_max; i++) { + if (seg_max) { + if (i < seg_max || !(app_msg_len % 12)) + seg_len = 12; + else + seg_len = app_msg_len % 12; + } else { + seg_len = app_msg_len; + } + + if (keys->ctl) { + mesh_crypto_packet_build(keys->ctl, keys->net_ttl, + keys->net_seq[i], + keys->net_src, keys->net_dst, + keys->opcode, + keys->segmented, key_aid, + keys->szmic, keys->relay, keys->seqZero, + i, seg_max, + enc_msg + 1, seg_len, + packet, &packet_len); + } else { + mesh_crypto_packet_build(keys->ctl, keys->net_ttl, + keys->net_seq[i], + keys->net_src, keys->net_dst, + keys->opcode, + keys->segmented, key_aid, + keys->szmic, keys->relay, seqZero, + i, seg_max, + enc_msg + (i * 12), seg_len, + packet, &packet_len); + } + + if (seg_max) l_info(COLOR_YELLOW "Segment-%d" COLOR_OFF, i); + + hdr = l_get_be32(packet + 9); + verify_uint8("SEG", 9, keys->segmented << (SEG_HDR_SHIFT % 8), + packet[9] & (1 << (SEG_HDR_SHIFT % 8))); + + if (keys->ctl) { + verify_uint8("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT % 8), + (packet[9] & OPCODE_MASK) << + (OPCODE_HDR_SHIFT % 8)); + } else { + verify_uint8("AKF", 9, keys->akf << (AKF_HDR_SHIFT % 8), + packet[9] & (1 << (AKF_HDR_SHIFT % 8))); + verify_uint8("AID", 9, + keys->key_aid << (KEY_HDR_SHIFT % 8), + (packet[9] & KEY_AID_MASK) << + (KEY_HDR_SHIFT % 8)); + } + + if (seg_max == 0) { + if (!keys->ctl) { + show_data("Payload", 10, app_msg, seg_len - 4); + show_data("EncryptedPayload", 10, packet + 10, + seg_len); + } else if (keys->opcode == NET_OP_SEG_ACKNOWLEDGE) { + verify_uint8("Relay", 10, + keys->relay << (RELAY_HDR_SHIFT % 8), + packet[10] & + (1 << (RELAY_HDR_SHIFT % 8))); + + /* Awkward shift-by-two for correct display */ + verify_uint16("SeqZero", 10, + (keys->seqZero & SEQ_ZERO_MASK) << 2, + ((hdr >> SEQ_ZERO_HDR_SHIFT) & + SEQ_ZERO_MASK) << 2); + + show_data("Payload", 12, packet + 12, seg_len); + } else { + show_data("Payload", 10, packet + 10, seg_len); + } + seg_len += 1; + } else { + + verify_uint8("SZMIC", 10, + keys->szmic << (SZMIC_HDR_SHIFT % 8), + packet[10] & (1 << (SZMIC_HDR_SHIFT % 8))); + + /* Awkward shift-by-two for correct display */ + verify_uint16("SeqZero", 10, + (keys->app_seq & SEQ_ZERO_MASK) << 2, + ((hdr >> SEQ_ZERO_HDR_SHIFT) & SEQ_ZERO_MASK) + << 2); + verify_uint16("SegO", 11, + (i & SEG_MASK) << SEGO_HDR_SHIFT, + hdr & (SEG_MASK << SEGO_HDR_SHIFT)); + verify_uint8("SegN", 12, + (seg_max & SEG_MASK) << SEGN_HDR_SHIFT, + hdr & (SEG_MASK << SEGN_HDR_SHIFT)); + show_data("Payload", 13, enc_msg + (i * 12), seg_len); + seg_len += 4; + } + + + mesh_crypto_network_nonce(keys->ctl, keys->net_ttl, + keys->net_seq[i], keys->net_src, + keys->iv_index, net_nonce); + + verify_data("TransportData", 9, keys->trans_pkt[i], + packet + 9, seg_len); + + verify_uint16("DST", 7, keys->net_dst, l_get_be16(packet + 7)); + net_msg_len = seg_len + 2; + show_data("TransportPayload", 7, packet + 7, net_msg_len); + + mesh_crypto_network_encrypt(keys->ctl, + keys->net_ttl, keys->net_seq[i], + keys->net_src, + keys->iv_index, enc_key, + packet + 7, seg_len + 2, packet + 7, + keys->ctl ? (void *)&net_mic64 : + (void *)&net_mic32); + + mesh_crypto_privacy_counter(keys->iv_index, packet + 7, + priv_rand); + + l_info(""); + show_uint32("IVindex", 0, keys->iv_index); + verify_data("NetworkNonce", 0, keys->net_nonce[i], + net_nonce, 13); + verify_data("PrivacyRandom", 0, keys->priv_rand[i], + priv_rand, 16); + + show_uint8("INI", 0, (keys->iv_index & 0x01) << 7); + verify_uint8("NID", 0, keys->net_nid, nid); + verify_uint8("CTL", 1, keys->ctl << 7, packet[1] & 0x80); + verify_uint8("TTL", 1, keys->net_ttl, packet[1] & 0x7f); + verify_uint24("SEQ", 2, keys->net_seq[i], + l_get_be32(packet + 1) & SEQ_MASK); + verify_uint16("SRC", 5, keys->net_src, l_get_be16(packet + 5)); + + verify_data("EncNetworkPayload", 7, keys->net_msg[i], + packet + 7, net_msg_len); + if (keys->ctl) { + verify_uint64("NetworkMIC", 7 + net_msg_len, + keys->net_mic64, net_mic64); + net_msg_len += 8; + } else { + verify_uint32("NetworkMIC", 7 + net_msg_len, + keys->net_mic32[i], net_mic32); + net_msg_len += 4; + } + + show_data("PreObsPayload", 1, packet + 1, 6 + net_msg_len); + mesh_crypto_network_obfuscate(priv_key, priv_rand, + keys->ctl, + keys->net_ttl, keys->net_seq[i], + keys->net_src, packet + 1); + show_data("PostObsPayload", 1, packet + 1, 6 + net_msg_len); + + packet[0] = (keys->iv_index & 0x01) << 7 | nid; + packet_len = 7 + net_msg_len; + + verify_data("Packet", 0, keys->packet[i], packet, packet_len); + l_info(""); + } + +done: + l_free(dev_key); + l_free(app_key); + l_free(aad); + l_free(net_key); + l_free(app_msg); + l_free(enc_msg); +} + +static void check_decrypt_segment(const struct mesh_crypto_test *keys, + uint16_t seg, uint16_t seg_max, + const uint8_t *pkt, uint8_t pkt_len, + const uint8_t *msg, uint8_t msg_len, + uint8_t *enc_key, uint8_t *priv_key, + uint8_t nid) +{ + uint8_t net_clr[29]; + uint64_t net_mic64, calc_net_mic64; + uint32_t hdr, net_mic32, calc_net_mic32; + bool ctl, segmented, relay, szmic, key_akf; + uint8_t ttl, opcode, key_aid, segO, segN; + uint32_t seq; + uint16_t src, dst, seqZero; + + memcpy(net_clr, pkt, pkt_len); + show_data("NetworkMessage", 0, pkt, pkt_len); + mesh_crypto_packet_decode(pkt, pkt_len, + false, net_clr, keys->iv_index, + enc_key, priv_key); + show_data("Decoded", 0, net_clr, pkt_len); + + mesh_crypto_packet_parse(net_clr, pkt_len, + &ctl, &ttl, &seq, + &src, &dst, + NULL, &opcode, + &segmented, &key_aid, + &szmic, &relay, &seqZero, + &segO, &segN, + &msg, &msg_len); + + if (ctl) { + net_mic64 = l_get_be64(pkt + pkt_len - 8); + show_data("EncryptedPayload", 7, pkt + 7, pkt_len - 7 - 8); + mesh_crypto_network_decrypt(ctl, ttl, seq, + src, keys->iv_index, enc_key, + pkt + 7, pkt_len - 7, net_clr + 7, + &calc_net_mic64, + sizeof(calc_net_mic64)); + verify_uint64("NetworkMIC", pkt_len - 8, net_mic64, + calc_net_mic64); + show_data("DecryptedPayload", 7, net_clr + 7, pkt_len - 7 - 8); + } else { + net_mic32 = l_get_be32(pkt + pkt_len - 4); + show_data("EncryptedPayload", 7, pkt + 7, pkt_len - 7 - 4); + + mesh_crypto_network_decrypt(ctl, ttl, seq, + src, keys->iv_index, enc_key, + pkt + 7, pkt_len - 7, net_clr + 7, + &calc_net_mic32, + sizeof(calc_net_mic32)); + + verify_uint32("NetworkMIC", pkt_len - 4, net_mic32, + calc_net_mic32); + show_data("DecryptedPayload", 7, net_clr + 7, pkt_len - 7 - 4); + } + + hdr = l_get_be32(net_clr + 9); + + segmented = !!((hdr >> SEG_HDR_SHIFT) & 1); + if (ctl) { + opcode = (hdr >> OPCODE_HDR_SHIFT) & OPCODE_MASK; + if (opcode == NET_OP_SEG_ACKNOWLEDGE) { + relay = !!((hdr >> RELAY_HDR_SHIFT) & 1); + seqZero = (hdr >> SEQ_ZERO_HDR_SHIFT) & SEQ_ZERO_MASK; + verify_uint24("SeqZero", 9, + ((keys->seqZero) & SEQ_ZERO_MASK) + << (SEQ_ZERO_HDR_SHIFT - 8), + seqZero << (SEQ_ZERO_HDR_SHIFT - 8)); + verify_uint24("Relay", 9, + keys->relay << (RELAY_HDR_SHIFT - 8), + relay << (RELAY_HDR_SHIFT - 8)); + verify_uint24("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT - 8), + opcode << (OPCODE_HDR_SHIFT - 8)); + verify_uint24("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT - 8), + segmented << (SEG_HDR_SHIFT - 8)); + } else { + verify_uint8("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT % 8), + opcode << (OPCODE_HDR_SHIFT % 8)); + verify_uint8("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT % 8), + segmented << (SEG_HDR_SHIFT % 8)); + } + } else { + key_akf = !!((hdr >> AKF_HDR_SHIFT) & 1); + key_aid = (hdr >> KEY_HDR_SHIFT) & KEY_AID_MASK; + if (segmented) { + show_data("EncryptedApp", 13, net_clr + 13, + pkt_len - 13 - 4); + segN = (hdr >> SEGN_HDR_SHIFT) & SEG_MASK; + segO = (hdr >> SEGO_HDR_SHIFT) & SEG_MASK; + seqZero = ((hdr >> SEQ_ZERO_HDR_SHIFT) & + SEQ_ZERO_MASK); + + verify_uint32("SegN", 9, + seg_max << SEGN_HDR_SHIFT, + segN << SEGN_HDR_SHIFT); + verify_uint32("SegO", 9, seg << SEGO_HDR_SHIFT, + segO << SEGO_HDR_SHIFT); + verify_uint32("SeqZero", 9, + (keys->seqZero & SEQ_ZERO_MASK) + << SEQ_ZERO_HDR_SHIFT, + (seqZero & SEQ_ZERO_MASK) + << SEQ_ZERO_HDR_SHIFT); + verify_uint32("AID", 9, + keys->key_aid << KEY_HDR_SHIFT, + key_aid << KEY_HDR_SHIFT); + verify_uint32("AKF", 9, + keys->akf << AKF_HDR_SHIFT, + key_akf << AKF_HDR_SHIFT); + verify_uint32("SEGMENTED", 9, + keys->segmented << SEG_HDR_SHIFT, + segmented << SEG_HDR_SHIFT); + } else { + show_data("EncryptedApp", 10, msg + 3, pkt_len - 3); + verify_uint8("AID", 9, + keys->key_aid << (KEY_HDR_SHIFT % 8), + key_aid << (KEY_HDR_SHIFT % 8)); + verify_uint8("AKF", 9, + keys->akf << (AKF_HDR_SHIFT % 8), + key_aid << (AKF_HDR_SHIFT % 8)); + verify_uint8("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT % 8), + segmented << (SEG_HDR_SHIFT % 8)); + } + } + + dst = l_get_be16(net_clr + 7); + + verify_uint16("DST", 7, keys->net_dst, dst); + verify_uint16("SRC", 5, keys->net_src, src); + verify_uint24("SEQ", 2, keys->net_seq[0], seq); + verify_uint8("TTL", 1, keys->net_ttl, ttl); + verify_uint8("CTL", 1, keys->ctl << 7, ctl << 7); + verify_uint8("NID", 0, keys->net_nid, net_clr[0] & 0x7f); + verify_uint8("INI", 0, (keys->iv_index & 0x01) << 7, net_clr[0] & 0x80); +} + +static void check_decrypt(const struct mesh_crypto_test *keys) +{ + uint8_t *dev_key; + uint8_t *app_key; + uint8_t *net_key; + uint8_t enc_key[16]; + uint8_t net_nonce[13]; + uint8_t app_nonce[13]; + uint8_t priv_key[16]; + uint8_t priv_rand[16]; + uint8_t p[9]; + size_t p_len; + uint8_t *packet; + size_t packet_len; + const uint8_t *net_hdr; + uint8_t *net_msg; + uint8_t net_msg_len; + uint16_t app_msg_len = 0; + uint32_t calc_net_mic32, net_mic32 = 0; + uint64_t calc_net_mic64, net_mic64 = 0; + bool net_ctl, net_segmented, net_rly, net_akf; + uint8_t net_aid, net_ttl, nid, net_segO, net_segN = 0; + uint32_t net_seq, hdr, seqZero = 0; + uint16_t net_src, net_dst; + uint32_t calc_app_mic32; + uint64_t calc_app_mic64; + uint32_t app_mic32; + uint64_t app_mic64; + uint8_t *app_msg; + uint8_t *aad; + uint8_t *payload; + size_t trans_msg_len, payload_len, aad_len = 0; + uint8_t pkt_len, hdr_len, net_op = 0; + uint16_t i, seg_max; + uint8_t keys_aid = 0; + + l_info(COLOR_BLUE "[Decrypt %s]" COLOR_OFF, keys->name); + verify_bool_not_both("CTL && Segmented", 0, keys->ctl, keys->segmented); + dev_key = l_util_from_hexstring(keys->dev_key, NULL); + app_key = l_util_from_hexstring(keys->app_key, NULL); + net_key = l_util_from_hexstring(keys->net_key, NULL); + aad = l_util_from_hexstring(keys->uuid, &aad_len); + + if (keys->frnd) { + uint8_t *lpn_addr, *fn_addr, *lpn_cntr, *fn_cntr; + + lpn_addr = l_util_from_hexstring(keys->lpn_addr, NULL); + fn_addr = l_util_from_hexstring(keys->fn_addr, NULL); + lpn_cntr = l_util_from_hexstring(keys->lpn_cntr, NULL); + fn_cntr = l_util_from_hexstring(keys->fn_cntr, NULL); + + show_data("LPN Address", 0, lpn_addr, 2); + show_data("Friend Address", 0, fn_addr, 2); + show_data("LPN Counter", 0, lpn_cntr, 2); + show_data("Friend Counter", 0, fn_cntr, 2); + l_info(""); + + p[0] = 1; + l_put_be16(l_get_be16(lpn_addr), p + 1); + l_put_be16(l_get_be16(fn_addr), p + 3); + l_put_be16(l_get_be16(lpn_cntr), p + 5); + l_put_be16(l_get_be16(fn_cntr), p + 7); + p_len = 9; + + l_free(fn_cntr); + l_free(lpn_cntr); + l_free(fn_addr); + l_free(lpn_addr); + } else { + p[0] = 0; + p_len = 1; + } + + if (p_len > 1) verify_data("P", 0, keys->p, p, p_len); + mesh_crypto_k2(net_key, p, p_len, &nid, enc_key, priv_key); + + + if (keys->network_only) { + app_msg = l_util_from_hexstring(keys->trans_pkt[0], + &trans_msg_len); + packet = l_util_from_hexstring(keys->packet[0], &packet_len); + check_decrypt_segment(keys, keys->seg_num, keys->seg_max, + packet, packet_len, + app_msg + 4, trans_msg_len - 4, + enc_key, priv_key, nid); + goto done; + } + + mesh_crypto_application_nonce(keys->app_seq, keys->net_src, + keys->net_dst, keys->iv_index, + keys->szmic, app_nonce); + app_msg = l_malloc(384); + + seg_max = (sizeof(keys->packet) / sizeof(keys->packet[0])) - 1; + + /* Calculate number of segments in sample data */ + while (keys->packet[seg_max] == NULL && seg_max) seg_max--; + + for (i = 0; i <= seg_max; i++) { + if (keys->segmented) + l_info(COLOR_YELLOW "Segment-%d" COLOR_OFF, i); + + mesh_crypto_network_nonce(keys->frnd, keys->net_ttl, + keys->net_seq[i], keys->net_src, keys->iv_index, + net_nonce); + packet = l_util_from_hexstring(keys->packet[i], &packet_len); + + net_hdr = packet + 1; + net_msg = packet + 7; + net_msg_len = packet_len - 7; + + mesh_crypto_privacy_counter(keys->iv_index, net_msg, priv_rand); + + mesh_crypto_network_clarify(priv_key, priv_rand, net_hdr, + &net_ctl, &net_ttl, &net_seq, &net_src); + + show_str("Packet", 0, keys->packet[i]); + + if (net_ctl) { + net_mic64 = l_get_be64(packet + packet_len - 8); + show_data("NetworkMessage", 7, net_msg, + net_msg_len - 8); + mesh_crypto_network_decrypt(net_ctl, net_ttl, net_seq, + net_src, keys->iv_index, enc_key, + net_msg, net_msg_len, net_msg, + &calc_net_mic64, + sizeof(calc_net_mic64)); + net_msg_len -= 8; + verify_uint64("NetworkMIC", 7 + net_msg_len, net_mic64, + calc_net_mic64); + show_data("DecryptedNetwork", 7, net_msg, net_msg_len); + } else { + net_mic32 = l_get_be32(packet + packet_len - 4); + show_data("NetworkMessage", 7, net_msg, + net_msg_len - 4); + + mesh_crypto_network_decrypt(net_ctl, net_ttl, net_seq, + net_src, keys->iv_index, enc_key, + net_msg, net_msg_len, net_msg, + &calc_net_mic32, + sizeof(calc_net_mic32)); + + net_msg_len -= 4; + verify_uint32("NetworkMIC", 7 + net_msg_len, net_mic32, + calc_net_mic32); + show_data("DecryptedNetwork", 7, net_msg, net_msg_len); + } + + + hdr = l_get_be32(packet + 9); + + net_segmented = !!((hdr >> SEG_HDR_SHIFT) & 1); + if (net_ctl) { + net_op = (hdr >> OPCODE_HDR_SHIFT) & OPCODE_MASK; + hdr_len = 1; + if (net_op == NET_OP_SEG_ACKNOWLEDGE) { + net_rly = !!((hdr >> RELAY_HDR_SHIFT) & 1); + seqZero = (hdr >> SEQ_ZERO_HDR_SHIFT) & + SEQ_ZERO_MASK; + verify_uint24("SeqZero", 9, + ((keys->seqZero) & SEQ_ZERO_MASK) + << (SEQ_ZERO_HDR_SHIFT - 8), + seqZero << (SEQ_ZERO_HDR_SHIFT - 8)); + verify_uint24("Relay", 9, + keys->relay << (RELAY_HDR_SHIFT - 8), + net_rly << (RELAY_HDR_SHIFT - 8)); + verify_uint24("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT - 8), + net_op << (OPCODE_HDR_SHIFT - 8)); + verify_uint24("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT - 8), + net_segmented << (SEG_HDR_SHIFT - 8)); + } else { + verify_uint8("Opcode", 9, + keys->opcode << (OPCODE_HDR_SHIFT % 8), + net_op << (OPCODE_HDR_SHIFT % 8)); + verify_uint8("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT % 8), + net_segmented << (SEG_HDR_SHIFT % 8)); + } + } else { + net_akf = !!((hdr >> AKF_HDR_SHIFT) & 1); + net_aid = (hdr >> KEY_HDR_SHIFT) & KEY_AID_MASK; + if (net_segmented) { + hdr_len = 4; + show_data("EncryptedApp", 13, net_msg + 6, + net_msg_len - 6); + memcpy(app_msg + (12 * i), net_msg + 6, + net_msg_len - 6); + app_msg_len += net_msg_len - 6; + net_segN = (hdr >> SEGN_HDR_SHIFT) & SEG_MASK; + net_segO = (hdr >> SEGO_HDR_SHIFT) & SEG_MASK; + seqZero = ((hdr >> SEQ_ZERO_HDR_SHIFT) + & SEQ_ZERO_MASK) | + (net_seq & ~SEQ_ZERO_MASK); + + if (seqZero > net_seq) seqZero -= + (SEQ_ZERO_MASK + 1); + verify_uint32("SegN", 9, + seg_max << SEGN_HDR_SHIFT, + net_segN << SEGN_HDR_SHIFT); + verify_uint32("SegO", 9, i << SEGO_HDR_SHIFT, + net_segO << SEGO_HDR_SHIFT); + verify_uint32("SeqZero", 9, + (keys->app_seq & SEQ_ZERO_MASK) + << SEQ_ZERO_HDR_SHIFT, + (seqZero & SEQ_ZERO_MASK) + << SEQ_ZERO_HDR_SHIFT); + verify_uint32("AID", 9, + keys->key_aid << KEY_HDR_SHIFT, + net_aid << KEY_HDR_SHIFT); + verify_uint32("AKF", 9, + keys->akf << AKF_HDR_SHIFT, + net_akf << AKF_HDR_SHIFT); + verify_uint32("SEGMENTED", 9, + keys->segmented << SEG_HDR_SHIFT, + net_segmented << SEG_HDR_SHIFT); + } else { + hdr_len = 1; + show_data("EncryptedApp", 10, net_msg + 3, + net_msg_len - 3); + memcpy(app_msg + (12 * i), net_msg + 3, + net_msg_len - 3); + app_msg_len += net_msg_len - 3; + seqZero = net_seq; + verify_uint8("AID", 9, + keys->key_aid << (KEY_HDR_SHIFT % 8), + net_aid << (KEY_HDR_SHIFT % 8)); + verify_uint8("AKF", 9, + keys->akf << (AKF_HDR_SHIFT % 8), + net_akf << (AKF_HDR_SHIFT % 8)); + verify_uint8("SEGMENTED", 9, + keys->segmented << (SEG_HDR_SHIFT % 8), + net_segmented << (SEG_HDR_SHIFT % 8)); + } + } + + net_dst = l_get_be16(net_msg); + + verify_uint16("DST", 7, keys->net_dst, net_dst); + verify_uint16("SRC", 5, keys->net_src, net_src); + verify_uint24("SEQ", 2, keys->net_seq[i], net_seq); + verify_uint8("TTL", 1, keys->net_ttl, net_ttl); + verify_uint8("CTL", 1, keys->ctl << 7, net_ctl << 7); + verify_uint8("NID", 0, keys->net_nid, nid); + verify_uint8("INI", 0, (keys->iv_index & 0x01) << 7, + packet[0] & 0x80); + + payload = l_util_from_hexstring(keys->trans_pkt[i], + &payload_len); + memset(packet, 0, packet_len); + + mesh_crypto_packet_build(keys->ctl, keys->net_ttl, + keys->net_seq[i], keys->net_src, + keys->net_dst, net_op, + keys->segmented, + keys->key_aid | (keys->akf ? KEY_ID_AKF : 0), + keys->szmic, keys->relay, seqZero, + i, seg_max, + payload + hdr_len, payload_len - hdr_len, + packet, &pkt_len); + verify_data("TransportData", 9, keys->trans_pkt[i], packet + 9, + payload_len); + mesh_crypto_packet_encode(packet, pkt_len, enc_key, + keys->iv_index, priv_key); + mesh_crypto_packet_label(packet, pkt_len, keys->iv_index, nid); + + verify_data("Encoded-Packet", 0, keys->packet[i], packet, + pkt_len); + + l_free(payload); + + l_info(""); + mesh_crypto_packet_decode(packet, pkt_len, false, packet, + keys->iv_index, enc_key, priv_key); + show_data("Decoded-Packet", 0, packet, pkt_len); + l_info(""); + } + + if (keys->segmented && keys->szmic) { + verify_data("EncryptedPayload", 0, keys->enc_msg, app_msg, + app_msg_len - 8); + app_mic64 = l_get_be64(app_msg + app_msg_len - 8); + + mesh_crypto_application_decrypt( + keys_aid | (keys->akf ? KEY_ID_AKF : 0), + seqZero, net_src, + net_dst, keys->iv_index, + keys->akf ? app_key : dev_key, + aad, aad_len, + app_msg, app_msg_len, + app_msg, &calc_app_mic64, + sizeof(calc_app_mic64)); + + verify_data("Payload", 0, keys->app_msg, app_msg, + app_msg_len - 8); + verify_uint64("ApplicationMIC", app_msg_len - 8, app_mic64, + calc_app_mic64); + } else if (!keys->ctl) { + verify_data("EncryptedPayload", 0, keys->enc_msg, app_msg, + app_msg_len - 4); + app_mic32 = l_get_be32(app_msg + app_msg_len - 4); + + mesh_crypto_application_decrypt( + keys_aid | (keys->akf ? KEY_ID_AKF : 0), + seqZero, net_src, + net_dst, keys->iv_index, + keys->akf ? app_key : dev_key, + aad, aad_len, + app_msg, app_msg_len, + app_msg, &calc_app_mic32, + sizeof(calc_app_mic32)); + + verify_data("Payload", 0, keys->app_msg, app_msg, + app_msg_len - 4); + verify_uint32("ApplicationMIC", app_msg_len - 4, app_mic32, + calc_app_mic32); + } + +done: + + l_info(""); + + l_free(dev_key); + l_free(aad); + l_free(app_key); + l_free(net_key); + l_free(app_msg); + l_free(packet); +} + +static void check_beacon(const struct mesh_crypto_test *keys) +{ + uint8_t *net_key; + uint8_t *beacon_cmac; + uint8_t beacon[22]; + uint8_t enc_key[16]; + uint8_t net_id[8]; + uint8_t cmac[8]; + uint64_t cmac_tmp; + + net_key = l_util_from_hexstring(keys->net_key, NULL); + beacon_cmac = l_util_from_hexstring(keys->beacon_cmac, NULL); + + mesh_crypto_nkbk(net_key, enc_key); + mesh_crypto_k3(net_key, net_id); + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + verify_data("NetworkKey", 0, keys->net_key, net_key, 16); + show_uint32("IVindex", 0, keys->iv_index); + + verify_data("BeaconKey", 0, keys->enc_key, enc_key, 16); + verify_data("NetworkID", 0, keys->net_id, net_id, 8); + + beacon[0] = keys->beacon_type; + beacon[1] = keys->beacon_flags; + memcpy(beacon + 2, net_id, 8); + l_put_be32(keys->iv_index, beacon + 10); + mesh_crypto_beacon_cmac(enc_key, net_id, keys->iv_index, + !!(keys->beacon_flags & 0x01), + !!(keys->beacon_flags & 0x02), + &cmac_tmp); + + l_put_be64(cmac_tmp, cmac); + l_put_be64(cmac_tmp, beacon + 14); + verify_data("BeaconCMAC", 0, keys->beacon_cmac, cmac, 8); + verify_data("Beacon", 0, keys->beacon, beacon, sizeof(beacon)); + + l_info(""); + + l_free(beacon_cmac); + l_free(net_key); +} + +static void check_id_beacon(const struct mesh_crypto_test *keys) +{ + uint8_t *net_key; + uint8_t *rand; + uint8_t identity_key[16]; + uint8_t hash_input[16]; + uint8_t hash[16]; + uint8_t beacon[17]; + + net_key = l_util_from_hexstring(keys->net_key, NULL); + rand = l_util_from_hexstring(keys->rand, NULL); + + mesh_crypto_nkik(net_key, identity_key); + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + verify_data("ID Resolving Key", 0, keys->ident_res_key, + identity_key, 16); + memset(hash_input, 0, 6); + memcpy(hash_input + 6, rand, 8); + l_put_be16(keys->net_src, hash_input + 6 + 8); + + verify_data("Hash Input", 0, keys->hash_input, hash_input, 16); + aes_ecb_one(identity_key, hash_input, hash); + + verify_data("Hash", 0, keys->identity_hash, hash + 8, 8); + + beacon[0] = 0x01; + memcpy(beacon + 1, hash + 8, 8); + memcpy(beacon + 9, rand, 8); + + verify_data("Mesh ID Beacon", 0, keys->beacon, beacon, 17); + + l_info(""); + + l_free(net_key); +} + +static void check_s1(const struct mesh_crypto_test *keys) +{ + uint8_t salt_out[16]; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + show_str("Salt Input", 0, keys->salt); + show_data("Salt Input", 0, keys->salt, strlen(keys->salt)); + mesh_crypto_s1(keys->salt, strlen(keys->salt), salt_out); + + verify_data("s1(Salt)", 0, keys->salt_out, salt_out, 16); + l_info(""); +} + +static void check_k128(const struct mesh_crypto_test *keys) +{ + uint8_t salt[16]; + uint8_t t[16]; + uint8_t enc_key[16]; + uint8_t *net_key; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + net_key = l_util_from_hexstring(keys->net_key, NULL); + show_data("NetKey", 0, net_key, 16); + l_info(""); + + show_str("Salt Input", 0, keys->salt); + show_data("Salt Input", 0, keys->salt, strlen(keys->salt)); + mesh_crypto_s1(keys->salt, strlen(keys->salt), salt); + show_data("s1(Salt)", 0, salt, 16); + l_info(""); + + show_str("Info", 0, keys->info); + show_data("Info", 0, keys->info, strlen(keys->info)); + l_info(""); + + mesh_crypto_aes_cmac(salt, net_key, 16, t); + show_data("T", 0, t, 16); + l_info(""); + + if (memcmp(keys->salt, "nkbk", 4) == 0) + mesh_crypto_nkbk(net_key, enc_key); + else if (memcmp(keys->salt, "nkpk", 4) == 0) + mesh_crypto_nkpk(net_key, enc_key); + else if (memcmp(keys->salt, "nkik", 4) == 0) + mesh_crypto_nkik(net_key, enc_key); + + verify_data("k1(N, salt, info)", 0, keys->enc_key, enc_key, 16); + + l_info(""); +} + +static void check_k1(const struct mesh_crypto_test *keys) +{ + uint8_t salt[16]; + uint8_t info[16]; + uint8_t t[16]; + uint8_t okm[16]; + uint8_t *ikm; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + ikm = l_util_from_hexstring(keys->ikm, NULL); + show_data("IKM", 0, ikm, 16); + l_info(""); + + show_str("Salt Input", 0, keys->salt); + show_data("Salt Input", 0, keys->salt, strlen(keys->salt)); + mesh_crypto_s1(keys->salt, strlen(keys->salt), salt); + show_data("s1(Salt)", 0, salt, 16); + l_info(""); + + show_str("Info Input", 0, keys->info); + show_data("Info Input", 0, keys->info, strlen(keys->info)); + mesh_crypto_s1(keys->info, strlen(keys->info), info); + show_data("s1(Info)", 0, info, 16); + l_info(""); + + mesh_crypto_aes_cmac(salt, ikm, 16, t); + show_data("T", 0, t, 16); + l_info(""); + + mesh_crypto_k1(ikm, salt, info, 16, okm); + + verify_data("k1(ikm, salt, info)", 0, keys->okm, okm, 16); + + l_free(ikm); + l_info(""); +} + +static void check_k2(const struct mesh_crypto_test *keys) +{ + uint8_t *net_key; + uint8_t p[9]; + size_t p_len; + uint8_t nid; + uint8_t enc_key[16]; + uint8_t priv_key[16]; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + net_key = l_util_from_hexstring(keys->net_key, NULL); + show_data("NetKey", 0, net_key, 16); + l_info(""); + + if (keys->frnd) { + uint8_t *lpn_addr, *fn_addr, *lpn_cntr, *fn_cntr; + + lpn_addr = l_util_from_hexstring(keys->lpn_addr, NULL); + fn_addr = l_util_from_hexstring(keys->fn_addr, NULL); + lpn_cntr = l_util_from_hexstring(keys->lpn_cntr, NULL); + fn_cntr = l_util_from_hexstring(keys->fn_cntr, NULL); + + show_data("LPN Address", 0, lpn_addr, 2); + show_data("Friend Address", 0, fn_addr, 2); + show_data("LPN Counter", 0, lpn_cntr, 2); + show_data("Friend Counter", 0, fn_cntr, 2); + l_info(""); + + p[0] = 1; + l_put_be16(l_get_be16(lpn_addr), p + 1); + l_put_be16(l_get_be16(fn_addr), p + 3); + l_put_be16(l_get_be16(lpn_cntr), p + 5); + l_put_be16(l_get_be16(fn_cntr), p + 7); + p_len = 9; + + l_free(fn_cntr); + l_free(lpn_cntr); + l_free(fn_addr); + l_free(lpn_addr); + } else { + p[0] = 0; + p_len = 1; + } + + mesh_crypto_k2(net_key, p, p_len, &nid, enc_key, priv_key); + verify_data("P", 0, keys->p, p, p_len); + l_info(""); + verify_data("NID", 0, keys->nid, &nid, 1); + verify_data("EncryptionKey", 0, keys->enc_key, enc_key, 16); + verify_data("PrivacyKey", 0, keys->priv_key, priv_key, 16); + l_free(net_key); + l_info(""); +} + +static void check_k3(const struct mesh_crypto_test *keys) +{ + uint8_t *net_key; + uint8_t tmp[16]; + uint8_t short_net_id[8]; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + net_key = l_util_from_hexstring(keys->net_key, NULL); + + show_data("NetKey", 0, net_key, 16); + l_info(""); + + show_str("Salt Input", 0, keys->salt); + show_data("Salt Input", 0, keys->salt, strlen(keys->salt)); + mesh_crypto_s1(keys->salt, strlen(keys->salt), tmp); + show_data("s1(Salt)", 0, tmp, 16); + l_info(""); + + show_str("Info", 0, keys->info); + show_data("Info", 0, keys->info, strlen(keys->info)); + l_info(""); + + mesh_crypto_aes_cmac(tmp, net_key, 16, tmp); + show_data("T", 0, tmp, 16); + l_info(""); + + mesh_crypto_k3(net_key, short_net_id); + verify_data("k3(NetKey)", 0, keys->short_net_id, short_net_id, 8); + l_free(net_key); + l_info(""); +} + +static void check_k4(const struct mesh_crypto_test *keys) +{ + uint8_t *app_key; + uint8_t tmp[16]; + uint8_t aid; + + l_info(COLOR_BLUE "[%s]" COLOR_OFF, keys->name); + + app_key = l_util_from_hexstring(keys->app_key, NULL); + + show_data("AppKey", 0, app_key, 16); + l_info(""); + + show_str("Salt Input", 0, keys->salt); + show_data("Salt Input", 0, keys->salt, strlen(keys->salt)); + mesh_crypto_s1(keys->salt, strlen(keys->salt), tmp); + show_data("s1(Salt)", 0, tmp, 16); + l_info(""); + + show_str("Info", 0, keys->info); + show_data("Info", 0, keys->info, strlen(keys->info)); + l_info(""); + + mesh_crypto_aes_cmac(tmp, app_key, 16, tmp); + show_data("T", 0, tmp, 16); + l_info(""); + + mesh_crypto_k4(app_key, &aid); + verify_data("k4(AppKey)", 0, keys->aid, &aid, 1); + l_free(app_key); + l_info(""); +} + +int main(int argc, char *argv[]) +{ + l_log_set_stderr(); + + /* Section 8.1 Sample Data Tests */ + check_s1(&s8_1_1); + check_k1(&s8_1_2); + check_k2(&s8_1_3); + check_k2(&s8_1_4); + check_k3(&s8_1_5); + check_k4(&s8_1_6); + + /* Section 8.2 Sample Data Tests */ + check_k4(&s8_2_1); + check_k2(&s8_2_2); + check_k2(&s8_2_3); + check_k3(&s8_2_4); + check_k128(&s8_2_5); + check_k128(&s8_2_6); + + /* Section 8.3 Sample Data Tests */ + check_encrypt(&s8_3_1); + check_decrypt(&s8_3_1); + check_encrypt(&s8_3_2); + check_decrypt(&s8_3_2); + check_encrypt(&s8_3_3); + check_decrypt(&s8_3_3); + check_encrypt(&s8_3_4); + check_decrypt(&s8_3_4); + check_encrypt(&s8_3_5); + check_decrypt(&s8_3_5); + check_encrypt(&s8_3_6); + check_decrypt(&s8_3_6); + check_encrypt(&s8_3_7); + check_decrypt(&s8_3_7); + check_encrypt(&s8_3_8); /* Single segment tester unavailable */ + check_decrypt(&s8_3_8); /* Single segment tester unavailable */ + check_encrypt(&s8_3_9); + check_decrypt(&s8_3_9); + check_encrypt(&s8_3_10); + check_decrypt(&s8_3_10); + check_encrypt(&s8_3_11); /* Single segment tester unavailable */ + check_decrypt(&s8_3_11); /* Single segment tester unavailable */ + + /* Section 8.4 Beacon Sample Data */ + check_beacon(&s8_4_3); + + /* Section 8.6 Mesh Proxy Service sample data */ + check_id_beacon(&s8_6_2); + + return 0; +} |