test_protocomm.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089
  1. // Copyright 2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <stdbool.h>
  17. #include <esp_err.h>
  18. #include <esp_log.h>
  19. #include <esp_system.h>
  20. #include <sys/random.h>
  21. #include <unity.h>
  22. #include <mbedtls/aes.h>
  23. #include <mbedtls/sha256.h>
  24. #include <mbedtls/entropy.h>
  25. #include <mbedtls/ctr_drbg.h>
  26. #include <mbedtls/ecdh.h>
  27. #include <mbedtls/error.h>
  28. #include <mbedtls/ssl_internal.h>
  29. #include <protocomm.h>
  30. #include <protocomm_security.h>
  31. #include <protocomm_security0.h>
  32. #include <protocomm_security1.h>
  33. #include "session.pb-c.h"
  34. #ifdef DO_HEAP_TRACING
  35. #include <esp_heap_trace.h>
  36. #define NUM_RECORDS 100
  37. static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
  38. #endif
  39. #define PUBLIC_KEY_LEN 32
  40. #define SZ_RANDOM 16
  41. typedef struct {
  42. uint32_t id;
  43. uint8_t sec_ver;
  44. uint8_t weak;
  45. const protocomm_security_pop_t *pop;
  46. uint8_t device_pubkey[PUBLIC_KEY_LEN];
  47. uint8_t client_pubkey[PUBLIC_KEY_LEN];
  48. uint8_t sym_key[PUBLIC_KEY_LEN];
  49. uint8_t rand[SZ_RANDOM];
  50. /* mbedtls context data for Curve25519 */
  51. mbedtls_ecdh_context ctx_client;
  52. mbedtls_entropy_context entropy;
  53. mbedtls_ctr_drbg_context ctr_drbg;
  54. /* mbedtls context data for AES */
  55. mbedtls_aes_context ctx_aes;
  56. unsigned char stb[16];
  57. size_t nc_off;
  58. } session_t;
  59. static const char *TAG = "protocomm_test";
  60. static protocomm_t *test_pc = NULL;
  61. static const protocomm_security_t *test_sec = NULL;
  62. static uint32_t test_priv_data = 1234;
  63. static void flip_endian(uint8_t *data, size_t len)
  64. {
  65. uint8_t swp_buf;
  66. for (int i = 0; i < len/2; i++) {
  67. swp_buf = data[i];
  68. data[i] = data[len - i - 1];
  69. data[len - i - 1] = swp_buf;
  70. }
  71. }
  72. static void hexdump(const char *msg, uint8_t *buf, int len)
  73. {
  74. ESP_LOGI(TAG, "%s:", msg);
  75. ESP_LOG_BUFFER_HEX(TAG, buf, len);
  76. }
  77. static esp_err_t prepare_command0(session_t *session, SessionData *req)
  78. {
  79. Sec1Payload *in = (Sec1Payload *) malloc(sizeof(Sec1Payload));
  80. if (in == NULL) {
  81. ESP_LOGE(TAG, "Error allocating memory for request");
  82. return ESP_ERR_NO_MEM;
  83. }
  84. SessionCmd0 *in_req = (SessionCmd0 *) malloc(sizeof(SessionCmd0));
  85. if (in_req == NULL) {
  86. ESP_LOGE(TAG, "Error allocating memory for request");
  87. free(in);
  88. return ESP_ERR_NO_MEM;
  89. }
  90. sec1_payload__init(in);
  91. session_cmd0__init(in_req);
  92. in_req->client_pubkey.data = session->client_pubkey;
  93. in_req->client_pubkey.len = PUBLIC_KEY_LEN;
  94. in->msg = SEC1_MSG_TYPE__Session_Command0;
  95. in->payload_case = SEC1_PAYLOAD__PAYLOAD_SC0;
  96. in->sc0 = in_req;
  97. req->proto_case = SESSION_DATA__PROTO_SEC1;
  98. req->sec_ver = protocomm_security1.ver;
  99. req->sec1 = in;
  100. return ESP_OK;
  101. }
  102. static void cleanup_command0(SessionData *req)
  103. {
  104. free(req->sec1->sc0);
  105. free(req->sec1);
  106. }
  107. static esp_err_t verify_response0(session_t *session, SessionData *resp)
  108. {
  109. if ((resp->proto_case != SESSION_DATA__PROTO_SEC1) ||
  110. (resp->sec1->msg != SEC1_MSG_TYPE__Session_Response0)) {
  111. ESP_LOGE(TAG, "Invalid response type");
  112. return ESP_ERR_INVALID_ARG;
  113. }
  114. int ret;
  115. Sec1Payload *in = (Sec1Payload *) resp->sec1;
  116. if (in->sr0->device_pubkey.len != PUBLIC_KEY_LEN) {
  117. ESP_LOGE(TAG, "Device public key length as not as expected");
  118. return ESP_FAIL;
  119. }
  120. if (in->sr0->device_random.len != SZ_RANDOM) {
  121. ESP_LOGE(TAG, "Device random data length is not as expected");
  122. return ESP_FAIL;
  123. }
  124. uint8_t *cli_pubkey = session->client_pubkey;
  125. uint8_t *dev_pubkey = session->device_pubkey;
  126. memcpy(session->device_pubkey, in->sr0->device_pubkey.data, in->sr0->device_pubkey.len);
  127. hexdump("Device pubkey", dev_pubkey, PUBLIC_KEY_LEN);
  128. hexdump("Client pubkey", cli_pubkey, PUBLIC_KEY_LEN);
  129. ret = mbedtls_mpi_lset(&session->ctx_client.Qp.Z, 1);
  130. if (ret != 0) {
  131. ESP_LOGE(TAG, "Failed at mbedtls_mpi_lset with error code : %d", ret);
  132. return ESP_FAIL;
  133. }
  134. flip_endian(session->device_pubkey, PUBLIC_KEY_LEN);
  135. ret = mbedtls_mpi_read_binary(&session->ctx_client.Qp.X, dev_pubkey, PUBLIC_KEY_LEN);
  136. flip_endian(session->device_pubkey, PUBLIC_KEY_LEN);
  137. if (ret != 0) {
  138. ESP_LOGE(TAG, "Failed at mbedtls_mpi_read_binary with error code : %d", ret);
  139. return ESP_FAIL;
  140. }
  141. ret = mbedtls_ecdh_compute_shared(&session->ctx_client.grp,
  142. &session->ctx_client.z,
  143. &session->ctx_client.Qp,
  144. &session->ctx_client.d,
  145. mbedtls_ctr_drbg_random,
  146. &session->ctr_drbg);
  147. if (ret != 0) {
  148. ESP_LOGE(TAG, "Failed at mbedtls_ecdh_compute_shared with error code : %d", ret);
  149. return ESP_FAIL;
  150. }
  151. ret = mbedtls_mpi_write_binary(&session->ctx_client.z, session->sym_key, PUBLIC_KEY_LEN);
  152. if (ret != 0) {
  153. ESP_LOGE(TAG, "Failed at mbedtls_mpi_write_binary with error code : %d", ret);
  154. return ESP_FAIL;
  155. }
  156. flip_endian(session->sym_key, PUBLIC_KEY_LEN);
  157. const protocomm_security_pop_t *pop = session->pop;
  158. if (pop != NULL && pop->data != NULL && pop->len != 0) {
  159. ESP_LOGD(TAG, "Adding proof of possession");
  160. uint8_t sha_out[PUBLIC_KEY_LEN];
  161. ret = mbedtls_sha256_ret((const unsigned char *) pop->data, pop->len, sha_out, 0);
  162. if (ret != 0) {
  163. ESP_LOGE(TAG, "Failed at mbedtls_sha256_ret with error code : %d", ret);
  164. return ESP_FAIL;
  165. }
  166. for (int i = 0; i < PUBLIC_KEY_LEN; i++) {
  167. session->sym_key[i] ^= sha_out[i];
  168. }
  169. }
  170. hexdump("Shared key", session->sym_key, PUBLIC_KEY_LEN);
  171. memcpy(session->rand, in->sr0->device_random.data, in->sr0->device_random.len);
  172. hexdump("Dev random", session->rand, sizeof(session->rand));
  173. return ESP_OK;
  174. }
  175. static esp_err_t prepare_command1(session_t *session, SessionData *req)
  176. {
  177. int ret;
  178. uint8_t *outbuf = (uint8_t *) malloc(PUBLIC_KEY_LEN);
  179. if (!outbuf) {
  180. ESP_LOGE(TAG, "Error allocating ciphertext buffer");
  181. return ESP_ERR_NO_MEM;
  182. }
  183. /* Initialise crypto context */
  184. mbedtls_aes_init(&session->ctx_aes);
  185. memset(session->stb, 0, sizeof(session->stb));
  186. session->nc_off = 0;
  187. ret = mbedtls_aes_setkey_enc(&session->ctx_aes, session->sym_key,
  188. sizeof(session->sym_key)*8);
  189. if (ret != 0) {
  190. ESP_LOGE(TAG, "Failed at mbedtls_aes_setkey_enc with erro code : %d", ret);
  191. free(outbuf);
  192. return ESP_FAIL;
  193. }
  194. ret = mbedtls_aes_crypt_ctr(&session->ctx_aes, PUBLIC_KEY_LEN,
  195. &session->nc_off, session->rand,
  196. session->stb, session->device_pubkey, outbuf);
  197. if (ret != 0) {
  198. ESP_LOGE(TAG, "Failed at mbedtls_aes_crypt_ctr with erro code : %d", ret);
  199. free(outbuf);
  200. return ESP_FAIL;
  201. }
  202. Sec1Payload *out = (Sec1Payload *) malloc(sizeof(Sec1Payload));
  203. if (!out) {
  204. ESP_LOGE(TAG, "Error allocating out buffer");
  205. free(outbuf);
  206. return ESP_ERR_NO_MEM;
  207. }
  208. sec1_payload__init(out);
  209. SessionCmd1 *out_req = (SessionCmd1 *) malloc(sizeof(SessionCmd1));
  210. if (!out_req) {
  211. ESP_LOGE(TAG, "Error allocating out_req buffer");
  212. free(outbuf);
  213. free(out);
  214. return ESP_ERR_NO_MEM;
  215. }
  216. session_cmd1__init(out_req);
  217. out_req->client_verify_data.data = outbuf;
  218. out_req->client_verify_data.len = PUBLIC_KEY_LEN;
  219. hexdump("Client verify data", outbuf, PUBLIC_KEY_LEN);
  220. out->msg = SEC1_MSG_TYPE__Session_Command1;
  221. out->payload_case = SEC1_PAYLOAD__PAYLOAD_SC1;
  222. out->sc1 = out_req;
  223. req->proto_case = SESSION_DATA__PROTO_SEC1;
  224. req->sec_ver = protocomm_security1.ver;
  225. req->sec1 = out;
  226. return ESP_OK;
  227. }
  228. static void cleanup_command1(SessionData *req)
  229. {
  230. free(req->sec1->sc1->client_verify_data.data);
  231. free(req->sec1->sc1);
  232. free(req->sec1);
  233. }
  234. static esp_err_t verify_response1(session_t *session, SessionData *resp)
  235. {
  236. uint8_t *cli_pubkey = session->client_pubkey;
  237. uint8_t *dev_pubkey = session->device_pubkey;
  238. hexdump("Device pubkey", dev_pubkey, PUBLIC_KEY_LEN);
  239. hexdump("Client pubkey", cli_pubkey, PUBLIC_KEY_LEN);
  240. if ((resp->proto_case != SESSION_DATA__PROTO_SEC1) ||
  241. (resp->sec1->msg != SEC1_MSG_TYPE__Session_Response1)) {
  242. ESP_LOGE(TAG, "Invalid response type");
  243. return ESP_ERR_INVALID_ARG;
  244. }
  245. uint8_t check_buf[PUBLIC_KEY_LEN];
  246. Sec1Payload *in = (Sec1Payload *) resp->sec1;
  247. int ret = mbedtls_aes_crypt_ctr(&session->ctx_aes, PUBLIC_KEY_LEN,
  248. &session->nc_off, session->rand, session->stb,
  249. in->sr1->device_verify_data.data, check_buf);
  250. if (ret != 0) {
  251. ESP_LOGE(TAG, "Failed at mbedtls_aes_crypt_ctr with erro code : %d", ret);
  252. return ESP_FAIL;
  253. }
  254. hexdump("Dec Device verifier", check_buf, sizeof(check_buf));
  255. if (memcmp(check_buf, session->client_pubkey, sizeof(session->client_pubkey)) != 0) {
  256. ESP_LOGE(TAG, "Key mismatch. Close connection");
  257. return ESP_FAIL;
  258. }
  259. return ESP_OK;
  260. }
  261. static esp_err_t test_new_session(session_t *session)
  262. {
  263. if (session->sec_ver == 0) {
  264. return ESP_OK;
  265. }
  266. if (!test_sec || !test_sec->new_transport_session) {
  267. return ESP_ERR_INVALID_STATE;
  268. }
  269. uint32_t session_id = session->id;
  270. if (test_sec->new_transport_session(session_id) != ESP_OK) {
  271. ESP_LOGE(TAG, "Failed to launch new transport session");
  272. return ESP_FAIL;
  273. }
  274. return ESP_OK;
  275. }
  276. static esp_err_t test_sec_endpoint(session_t *session)
  277. {
  278. if (session->sec_ver == 0) {
  279. return ESP_OK;
  280. }
  281. uint32_t session_id = session->id;
  282. int ret = ESP_FAIL;
  283. SessionData req;
  284. SessionData *resp;
  285. ssize_t inlen = 0;
  286. uint8_t *inbuf = NULL;
  287. ssize_t outlen = 0;
  288. uint8_t *outbuf = NULL;
  289. mbedtls_ecdh_init(&session->ctx_client);
  290. mbedtls_ctr_drbg_init(&session->ctr_drbg);
  291. mbedtls_entropy_init(&session->entropy);
  292. ret = mbedtls_ctr_drbg_seed(&session->ctr_drbg, mbedtls_entropy_func,
  293. &session->entropy, NULL, 0);
  294. if (ret != 0) {
  295. ESP_LOGE(TAG, "Failed at mbedtls_ctr_drbg_seed with error code : %d", ret);
  296. goto abort_test_sec_endpoint;
  297. }
  298. ret = mbedtls_ecp_group_load(&session->ctx_client.grp, MBEDTLS_ECP_DP_CURVE25519);
  299. if (ret != 0) {
  300. ESP_LOGE(TAG, "Failed at mbedtls_ecp_group_load with error code : %d", ret);
  301. goto abort_test_sec_endpoint;
  302. }
  303. ret = mbedtls_ecdh_gen_public(&session->ctx_client.grp,
  304. &session->ctx_client.d,
  305. &session->ctx_client.Q,
  306. mbedtls_ctr_drbg_random,
  307. &session->ctr_drbg);
  308. if (ret != 0) {
  309. ESP_LOGE(TAG, "Failed at mbedtls_ecdh_gen_public with error code : %d", ret);
  310. goto abort_test_sec_endpoint;
  311. }
  312. if (session->weak) {
  313. /* Read zero client public key */
  314. ret = mbedtls_mpi_read_binary(&session->ctx_client.Q.X,
  315. session->client_pubkey,
  316. PUBLIC_KEY_LEN);
  317. if (ret != 0) {
  318. ESP_LOGE(TAG, "Failed at mbedtls_mpi_read_binary with error code : %d", ret);
  319. goto abort_test_sec_endpoint;
  320. }
  321. }
  322. ret = mbedtls_mpi_write_binary(&session->ctx_client.Q.X,
  323. session->client_pubkey,
  324. PUBLIC_KEY_LEN);
  325. if (ret != 0) {
  326. ESP_LOGE(TAG, "Failed at mbedtls_mpi_write_binary with error code : %d", ret);
  327. goto abort_test_sec_endpoint;
  328. }
  329. flip_endian(session->client_pubkey, PUBLIC_KEY_LEN);
  330. /*********** Transaction0 = SessionCmd0 + SessionResp0 ****************/
  331. session_data__init(&req);
  332. if (prepare_command0(session, &req) != ESP_OK) {
  333. ESP_LOGE(TAG, "Failed in prepare_command0");
  334. goto abort_test_sec_endpoint;
  335. }
  336. inlen = session_data__get_packed_size(&req);
  337. inbuf = (uint8_t *) malloc(inlen);
  338. if (!inbuf) {
  339. ESP_LOGE(TAG, "Failed to allocate inbuf");
  340. goto abort_test_sec_endpoint;
  341. }
  342. session_data__pack(&req, inbuf);
  343. cleanup_command0(&req);
  344. outlen = 0;
  345. outbuf = NULL;
  346. ret = protocomm_req_handle(test_pc, "test-sec", session_id,
  347. inbuf, inlen, &outbuf, &outlen);
  348. free(inbuf);
  349. if (ret != ESP_OK) {
  350. ESP_LOGE(TAG, "test-sec handler failed");
  351. free(outbuf);
  352. goto abort_test_sec_endpoint;
  353. }
  354. resp = session_data__unpack(NULL, outlen, outbuf);
  355. free(outbuf);
  356. if (!resp) {
  357. ESP_LOGE(TAG, "Unable to unpack SessionResp0");
  358. goto abort_test_sec_endpoint;
  359. }
  360. if (verify_response0(session, resp) != ESP_OK) {
  361. ESP_LOGE(TAG, "Invalid response 0");
  362. session_data__free_unpacked(resp, NULL);
  363. goto abort_test_sec_endpoint;
  364. }
  365. session_data__free_unpacked(resp, NULL);
  366. /*********** Transaction1 = SessionCmd1 + SessionResp1 ****************/
  367. session_data__init(&req);
  368. if (prepare_command1(session, &req) != ESP_OK) {
  369. ESP_LOGE(TAG, "Failed in prepare_command1");
  370. goto abort_test_sec_endpoint;
  371. }
  372. inlen = session_data__get_packed_size(&req);
  373. inbuf = (uint8_t *) malloc(inlen);
  374. if (!inbuf) {
  375. ESP_LOGE(TAG, "Failed to allocate inbuf");
  376. goto abort_test_sec_endpoint;
  377. }
  378. session_data__pack(&req, inbuf);
  379. cleanup_command1(&req);
  380. outlen = 0;
  381. outbuf = NULL;
  382. ret = protocomm_req_handle(test_pc, "test-sec", session_id,
  383. inbuf, inlen, &outbuf, &outlen);
  384. free(inbuf);
  385. if (ret != ESP_OK) {
  386. ESP_LOGE(TAG, "test-sec handler failed");
  387. free(outbuf);
  388. goto abort_test_sec_endpoint;
  389. }
  390. resp = session_data__unpack(NULL, outlen, outbuf);
  391. free(outbuf);
  392. if (!resp) {
  393. ESP_LOGE(TAG, "Unable to unpack SessionResp0");
  394. goto abort_test_sec_endpoint;
  395. }
  396. if (verify_response1(session, resp) != ESP_OK) {
  397. ESP_LOGE(TAG, "Invalid response 1");
  398. session_data__free_unpacked(resp, NULL);
  399. goto abort_test_sec_endpoint;
  400. }
  401. session_data__free_unpacked(resp, NULL);
  402. mbedtls_ecdh_free(&session->ctx_client);
  403. mbedtls_ctr_drbg_free(&session->ctr_drbg);
  404. mbedtls_entropy_free(&session->entropy);
  405. return ESP_OK;
  406. abort_test_sec_endpoint:
  407. mbedtls_ecdh_free(&session->ctx_client);
  408. mbedtls_ctr_drbg_free(&session->ctr_drbg);
  409. mbedtls_entropy_free(&session->entropy);
  410. return ESP_FAIL;
  411. }
  412. static esp_err_t test_req_endpoint(session_t *session)
  413. {
  414. uint32_t session_id = session->id;
  415. uint8_t rand_test_data[512], enc_test_data[512];
  416. getrandom(rand_test_data, sizeof(rand_test_data), 0);
  417. if (session->sec_ver == 0) {
  418. memcpy(enc_test_data, rand_test_data, sizeof(rand_test_data));
  419. }
  420. else if (session->sec_ver == 1) {
  421. mbedtls_aes_crypt_ctr(&session->ctx_aes, sizeof(rand_test_data), &session->nc_off,
  422. session->rand, session->stb, rand_test_data, enc_test_data);
  423. }
  424. ssize_t verify_data_len = 0;
  425. uint8_t *enc_verify_data = NULL;
  426. esp_err_t ret = protocomm_req_handle(test_pc, "test-ep", session_id,
  427. enc_test_data, sizeof(enc_test_data),
  428. &enc_verify_data, &verify_data_len);
  429. if (ret != ESP_OK) {
  430. ESP_LOGE(TAG, "test-ep handler failed");
  431. return ESP_FAIL;
  432. }
  433. uint8_t *verify_data = malloc(verify_data_len);
  434. if (!verify_data) {
  435. ESP_LOGE(TAG, "error allocating memory for decrypted data");
  436. free(enc_verify_data);
  437. return ESP_FAIL;
  438. }
  439. if (session->sec_ver == 0) {
  440. memcpy(verify_data, enc_verify_data, verify_data_len);
  441. }
  442. else if (session->sec_ver == 1) {
  443. mbedtls_aes_crypt_ctr(&session->ctx_aes, verify_data_len, &session->nc_off,
  444. session->rand, session->stb, enc_verify_data, verify_data);
  445. }
  446. free(enc_verify_data);
  447. hexdump("Sent data", rand_test_data, sizeof(rand_test_data));
  448. hexdump("Recv data", verify_data, verify_data_len);
  449. ESP_LOGI(TAG, "verify data len : %d", verify_data_len);
  450. ESP_LOGI(TAG, "expected data len : %d", sizeof(rand_test_data));
  451. if (verify_data_len != sizeof(rand_test_data)) {
  452. ESP_LOGE(TAG, "incorrect response length from test-ep");
  453. free(verify_data);
  454. return ESP_FAIL;
  455. }
  456. if (memcmp(rand_test_data, verify_data, verify_data_len)) {
  457. ESP_LOGE(TAG, "incorrect response data from test-ep");
  458. free(verify_data);
  459. return ESP_FAIL;
  460. }
  461. free(verify_data);
  462. return ESP_OK;
  463. }
  464. esp_err_t test_req_handler (uint32_t session_id,
  465. const uint8_t *inbuf, ssize_t inlen,
  466. uint8_t **outbuf, ssize_t *outlen,
  467. void *priv_data)
  468. {
  469. *outbuf = malloc(inlen);
  470. if (*outbuf) {
  471. *outlen = inlen;
  472. memcpy(*outbuf, inbuf, inlen);
  473. } else {
  474. ESP_LOGE(TAG, "Error allocating response outbuf");
  475. *outbuf = NULL;
  476. *outlen = 0;
  477. }
  478. uint32_t *priv = (uint32_t *) priv_data;
  479. if ((&test_priv_data != priv) || (test_priv_data != *priv)) {
  480. ESP_LOGE(TAG, "Handler private data doesn't match");
  481. return ESP_FAIL;
  482. }
  483. return ESP_OK;
  484. }
  485. static esp_err_t start_test_service(uint8_t sec_ver, const protocomm_security_pop_t *pop)
  486. {
  487. test_pc = protocomm_new();
  488. if (test_pc == NULL) {
  489. ESP_LOGE(TAG, "Failed to create new protocomm instance");
  490. return ESP_FAIL;
  491. }
  492. if (sec_ver == 0) {
  493. if (protocomm_set_security(test_pc, "test-sec", &protocomm_security0, NULL) != ESP_OK) {
  494. ESP_LOGE(TAG, "Failed to set Security0");
  495. return ESP_FAIL;
  496. }
  497. test_sec = &protocomm_security0;
  498. } else if (sec_ver == 1) {
  499. if (protocomm_set_security(test_pc, "test-sec", &protocomm_security1, pop) != ESP_OK) {
  500. ESP_LOGE(TAG, "Failed to set Security1");
  501. return ESP_FAIL;
  502. }
  503. test_sec = &protocomm_security1;
  504. }
  505. if (protocomm_add_endpoint(test_pc, "test-ep",
  506. test_req_handler,
  507. (void *) &test_priv_data) != ESP_OK) {
  508. ESP_LOGE(TAG, "Failed to set test-ep endpoint handler");
  509. return ESP_FAIL;
  510. }
  511. return ESP_OK;
  512. }
  513. static void stop_test_service(void)
  514. {
  515. protocomm_remove_endpoint(test_pc, "test-ep");
  516. protocomm_unset_security(test_pc, "test-sec");
  517. test_sec = NULL;
  518. protocomm_delete(test_pc);
  519. test_pc = NULL;
  520. }
  521. static esp_err_t test_security1_no_encryption (void)
  522. {
  523. ESP_LOGI(TAG, "Starting Security 1 no encryption test");
  524. const char *pop_data = "test pop";
  525. protocomm_security_pop_t pop = {
  526. .data = (const uint8_t *)pop_data,
  527. .len = strlen(pop_data)
  528. };
  529. session_t *session = calloc(1, sizeof(session_t));
  530. if (session == NULL) {
  531. ESP_LOGE(TAG, "Error allocating session");
  532. return ESP_ERR_NO_MEM;
  533. }
  534. session->id = 1;
  535. session->sec_ver = 1;
  536. session->pop = &pop;
  537. // Start protocomm service
  538. if (start_test_service(1, &pop) != ESP_OK) {
  539. ESP_LOGE(TAG, "Error starting test");
  540. free(session);
  541. return ESP_ERR_INVALID_STATE;
  542. }
  543. // Intialise protocomm session with zero public keys
  544. if (test_new_session(session) != ESP_OK) {
  545. ESP_LOGE(TAG, "Error creating new session");
  546. stop_test_service();
  547. free(session);
  548. return ESP_FAIL;
  549. }
  550. // Perform 25519 security handshake to set public keys
  551. if (test_sec_endpoint(session) != ESP_OK) {
  552. ESP_LOGE(TAG, "Error testing security endpoint");
  553. stop_test_service();
  554. free(session);
  555. return ESP_FAIL;
  556. }
  557. // Force endpoint with un-encrypted data
  558. session->sec_ver = 0;
  559. // Send unencrypted request data to echo endpoint.
  560. // Response would be encrypted causing echoed back
  561. // data to not match that which was sent, hence failing.
  562. if (test_req_endpoint(session) == ESP_OK) {
  563. ESP_LOGE(TAG, "Error testing request endpoint");
  564. stop_test_service();
  565. free(session);
  566. return ESP_FAIL;
  567. }
  568. stop_test_service();
  569. free(session);
  570. ESP_LOGI(TAG, "Protocomm test successful");
  571. return ESP_OK;
  572. }
  573. static esp_err_t test_security1_session_overflow (void)
  574. {
  575. ESP_LOGI(TAG, "Starting Security 1 session overflow test");
  576. const char *pop_data = "test pop";
  577. protocomm_security_pop_t pop = {
  578. .data = (const uint8_t *)pop_data,
  579. .len = strlen(pop_data)
  580. };
  581. session_t *session1 = calloc(1, sizeof(session_t));
  582. if (session1 == NULL) {
  583. ESP_LOGE(TAG, "Error allocating session");
  584. return ESP_ERR_NO_MEM;
  585. }
  586. session1->id = 2;
  587. session1->sec_ver = 1;
  588. session1->pop = &pop;
  589. session_t *session2 = calloc(1, sizeof(session_t));
  590. if (session2 == NULL) {
  591. ESP_LOGE(TAG, "Error allocating session");
  592. free(session1);
  593. return ESP_ERR_NO_MEM;
  594. }
  595. session2->id = 3;
  596. session2->sec_ver = 1;
  597. session2->pop = NULL;
  598. // Start protocomm service
  599. if (start_test_service(1, &pop) != ESP_OK) {
  600. ESP_LOGE(TAG, "Error starting test");
  601. free(session1);
  602. free(session2);
  603. return ESP_FAIL;
  604. }
  605. // Intialise protocomm session with zero public keys
  606. if (test_new_session(session1) != ESP_OK) {
  607. ESP_LOGE(TAG, "Error creating new session");
  608. stop_test_service();
  609. free(session1);
  610. free(session2);
  611. return ESP_FAIL;
  612. }
  613. // Perform 25519 security handshake to set public keys
  614. if (test_sec_endpoint(session1) != ESP_OK) {
  615. ESP_LOGE(TAG, "Error testing security endpoint");
  616. stop_test_service();
  617. free(session1);
  618. free(session2);
  619. return ESP_FAIL;
  620. }
  621. // Try to perform security handshake again with different
  622. // session ID without registering new session, hence failing
  623. if (test_sec_endpoint(session2) == ESP_OK) {
  624. ESP_LOGE(TAG, "Error testing security endpoint");
  625. stop_test_service();
  626. free(session1);
  627. free(session2);
  628. return ESP_FAIL;
  629. }
  630. stop_test_service();
  631. free(session1);
  632. free(session2);
  633. ESP_LOGI(TAG, "Protocomm test successful");
  634. return ESP_OK;
  635. }
  636. static esp_err_t test_security1_wrong_pop (void)
  637. {
  638. ESP_LOGI(TAG, "Starting Security 1 wrong auth test");
  639. const char *pop_data = "test pop";
  640. protocomm_security_pop_t pop = {
  641. .data = (const uint8_t *)pop_data,
  642. .len = strlen(pop_data)
  643. };
  644. session_t *session = calloc(1, sizeof(session_t));
  645. if (session == NULL) {
  646. ESP_LOGE(TAG, "Error allocating session");
  647. return ESP_ERR_NO_MEM;
  648. }
  649. session->id = 4;
  650. session->sec_ver = 1;
  651. session->pop = &pop;
  652. // Start protocomm service
  653. if (start_test_service(1, &pop) != ESP_OK) {
  654. ESP_LOGE(TAG, "Error starting test");
  655. free(session);
  656. return ESP_FAIL;
  657. }
  658. // Intialise protocomm session with zero public keys
  659. if (test_new_session(session) != ESP_OK) {
  660. ESP_LOGE(TAG, "Error creating new session");
  661. stop_test_service();
  662. free(session);
  663. return ESP_FAIL;
  664. }
  665. const char *wrong_pop_data = "wrong pop";
  666. protocomm_security_pop_t wrong_pop = {
  667. .data = (const uint8_t *)wrong_pop_data,
  668. .len = strlen(wrong_pop_data)
  669. };
  670. // Force wrong pop during authentication
  671. session->pop = &wrong_pop;
  672. // Perform 25519 security handshake with
  673. // wrong pop, hence failing
  674. if (test_sec_endpoint(session) == ESP_OK) {
  675. ESP_LOGE(TAG, "Error testing security endpoint");
  676. stop_test_service();
  677. free(session);
  678. return ESP_FAIL;
  679. }
  680. stop_test_service();
  681. free(session);
  682. ESP_LOGI(TAG, "Protocomm test successful");
  683. return ESP_OK;
  684. }
  685. static esp_err_t test_security1_insecure_client (void)
  686. {
  687. ESP_LOGI(TAG, "Starting Security 1 insecure client test");
  688. const char *pop_data = "test pop";
  689. protocomm_security_pop_t pop = {
  690. .data = (const uint8_t *)pop_data,
  691. .len = strlen(pop_data)
  692. };
  693. session_t *session = calloc(1, sizeof(session_t));
  694. if (session == NULL) {
  695. ESP_LOGE(TAG, "Error allocating session");
  696. return ESP_ERR_NO_MEM;
  697. }
  698. session->id = 5;
  699. session->sec_ver = 1;
  700. session->pop = &pop;
  701. // Start protocomm service
  702. if (start_test_service(1, &pop) != ESP_OK) {
  703. ESP_LOGE(TAG, "Error starting test");
  704. free(session);
  705. return ESP_FAIL;
  706. }
  707. // Perform 25519 security handshake without
  708. // initialising session, hence failing
  709. if (test_sec_endpoint(session) == ESP_OK) {
  710. ESP_LOGE(TAG, "Error testing security endpoint");
  711. stop_test_service();
  712. free(session);
  713. return ESP_FAIL;
  714. }
  715. // Communicating with request endpoint without
  716. // initialising session, hence failing
  717. if (test_req_endpoint(session) == ESP_OK) {
  718. ESP_LOGE(TAG, "Error testing request endpoint");
  719. stop_test_service();
  720. free(session);
  721. return ESP_FAIL;
  722. }
  723. stop_test_service();
  724. free(session);
  725. ESP_LOGI(TAG, "Protocomm test successful");
  726. return ESP_OK;
  727. }
  728. static esp_err_t test_security1_weak_session (void)
  729. {
  730. ESP_LOGI(TAG, "Starting Security 1 weak session test");
  731. const char *pop_data = "test pop";
  732. protocomm_security_pop_t pop = {
  733. .data = (const uint8_t *)pop_data,
  734. .len = strlen(pop_data)
  735. };
  736. session_t *session = calloc(1, sizeof(session_t));
  737. if (session == NULL) {
  738. ESP_LOGE(TAG, "Error allocating session");
  739. return ESP_ERR_NO_MEM;
  740. }
  741. session->id = 6;
  742. session->sec_ver = 1;
  743. session->pop = &pop;
  744. session->weak = 1;
  745. // Start protocomm service
  746. if (start_test_service(1, &pop) != ESP_OK) {
  747. ESP_LOGE(TAG, "Error starting test");
  748. free(session);
  749. return ESP_FAIL;
  750. }
  751. // Intialise protocomm session with zero public keys
  752. if (test_new_session(session) != ESP_OK) {
  753. ESP_LOGE(TAG, "Error creating new session");
  754. stop_test_service();
  755. free(session);
  756. return ESP_FAIL;
  757. }
  758. // Perform 25519 security handshake with weak (zero)
  759. // client public key, hence failing
  760. if (test_sec_endpoint(session) == ESP_OK) {
  761. ESP_LOGE(TAG, "Error testing security endpoint");
  762. stop_test_service();
  763. free(session);
  764. return ESP_FAIL;
  765. }
  766. // Sending request data to echo endpoint encrypted with zero
  767. // public keys on both client and server side should pass
  768. if (test_req_endpoint(session) != ESP_OK) {
  769. ESP_LOGE(TAG, "Error testing request endpoint");
  770. stop_test_service();
  771. free(session);
  772. return ESP_FAIL;
  773. }
  774. stop_test_service();
  775. free(session);
  776. ESP_LOGI(TAG, "Protocomm test successful");
  777. return ESP_OK;
  778. }
  779. static esp_err_t test_protocomm (session_t *session)
  780. {
  781. ESP_LOGI(TAG, "Starting Protocomm test");
  782. // Start protocomm service
  783. if (start_test_service(session->sec_ver, session->pop) != ESP_OK) {
  784. ESP_LOGE(TAG, "Error starting test");
  785. return ESP_FAIL;
  786. }
  787. // Intialise protocomm session with zero public keys
  788. if (test_new_session(session) != ESP_OK) {
  789. ESP_LOGE(TAG, "Error creating new session");
  790. stop_test_service();
  791. return ESP_FAIL;
  792. }
  793. // Perform 25519 security handshake to set public keys
  794. if (test_sec_endpoint(session) != ESP_OK) {
  795. ESP_LOGE(TAG, "Error testing security endpoint");
  796. stop_test_service();
  797. return ESP_FAIL;
  798. }
  799. // Send request data to echo endpoint encrypted with
  800. // the set public keys on both client and server side
  801. if (test_req_endpoint(session) != ESP_OK) {
  802. ESP_LOGE(TAG, "Error testing request endpoint");
  803. stop_test_service();
  804. return ESP_FAIL;
  805. }
  806. // Stop protocomm service
  807. stop_test_service();
  808. ESP_LOGI(TAG, "Protocomm test successful");
  809. return ESP_OK;
  810. }
  811. static esp_err_t test_security1 (void)
  812. {
  813. ESP_LOGI(TAG, "Starting Sec1 test");
  814. const char *pop_data = "test pop";
  815. protocomm_security_pop_t pop = {
  816. .data = (const uint8_t *)pop_data,
  817. .len = strlen(pop_data)
  818. };
  819. session_t *session = calloc(1, sizeof(session_t));
  820. if (session == NULL) {
  821. ESP_LOGE(TAG, "Error allocating session");
  822. return ESP_ERR_NO_MEM;
  823. }
  824. session->id = 7;
  825. session->sec_ver = 1;
  826. session->pop = &pop;
  827. if (test_protocomm (session) != ESP_OK) {
  828. ESP_LOGE(TAG, "Sec1 test failed");
  829. free(session);
  830. return ESP_FAIL;
  831. }
  832. ESP_LOGI(TAG, "Sec1 test successful");
  833. free(session);
  834. return ESP_OK;
  835. }
  836. static esp_err_t test_security0 (void)
  837. {
  838. ESP_LOGI(TAG, "Starting Sec0 test");
  839. session_t *session = calloc(1, sizeof(session_t));
  840. if (session == NULL) {
  841. ESP_LOGE(TAG, "Error allocating session");
  842. return ESP_ERR_NO_MEM;
  843. }
  844. session->id = 8;
  845. session->sec_ver = 0;
  846. session->pop = NULL;
  847. if (test_protocomm (session) != ESP_OK) {
  848. ESP_LOGE(TAG, "Sec0 test failed");
  849. free(session);
  850. return ESP_FAIL;
  851. }
  852. ESP_LOGI(TAG, "Sec0 test successful");
  853. free(session);
  854. return ESP_OK;
  855. }
  856. TEST_CASE("leak test", "[PROTOCOMM]")
  857. {
  858. #ifdef DO_HEAP_TRACING
  859. heap_trace_init_standalone(trace_record, NUM_RECORDS);
  860. #endif
  861. unsigned pre_start_mem = esp_get_free_heap_size();
  862. #ifdef DO_HEAP_TRACING
  863. heap_trace_start(HEAP_TRACE_LEAKS);
  864. #endif
  865. test_security0();
  866. test_security1();
  867. #ifdef DO_HEAP_TRACING
  868. heap_trace_stop();
  869. heap_trace_dump();
  870. #endif
  871. unsigned post_stop_mem = esp_get_free_heap_size();
  872. if (pre_start_mem != post_stop_mem) {
  873. ESP_LOGE(TAG, "Mismatch in free heap size");
  874. }
  875. #ifdef DO_HEAP_TRACING
  876. TEST_ASSERT(pre_start_mem != post_stop_mem);
  877. #endif
  878. }
  879. TEST_CASE("security 0 basic test", "[PROTOCOMM]")
  880. {
  881. TEST_ASSERT(test_security0() == ESP_OK);
  882. }
  883. TEST_CASE("security 1 basic test", "[PROTOCOMM]")
  884. {
  885. TEST_ASSERT(test_security1() == ESP_OK);
  886. }
  887. TEST_CASE("security 1 no encryption test", "[PROTOCOMM]")
  888. {
  889. TEST_ASSERT(test_security1_no_encryption() == ESP_OK);
  890. }
  891. TEST_CASE("security 1 session overflow test", "[PROTOCOMM]")
  892. {
  893. TEST_ASSERT(test_security1_session_overflow() == ESP_OK);
  894. }
  895. TEST_CASE("security 1 wrong pop test", "[PROTOCOMM]")
  896. {
  897. TEST_ASSERT(test_security1_wrong_pop() == ESP_OK);
  898. }
  899. TEST_CASE("security 1 insecure client test", "[PROTOCOMM]")
  900. {
  901. TEST_ASSERT(test_security1_insecure_client() == ESP_OK);
  902. }
  903. TEST_CASE("security 1 weak session test", "[PROTOCOMM]")
  904. {
  905. TEST_ASSERT(test_security1_weak_session() == ESP_OK);
  906. }