ecjpake.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. /*
  2. * Elliptic curve J-PAKE
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. /*
  8. * References in the code are to the Thread v1.0 Specification,
  9. * available to members of the Thread Group http://threadgroup.org/
  10. */
  11. #include "common.h"
  12. #if defined(MBEDTLS_ECJPAKE_C)
  13. #include "mbedtls/ecjpake.h"
  14. #include "mbedtls/platform_util.h"
  15. #include "mbedtls/error.h"
  16. #include <string.h>
  17. #if !defined(MBEDTLS_ECJPAKE_ALT)
  18. /*
  19. * Convert a mbedtls_ecjpake_role to identifier string
  20. */
  21. static const char * const ecjpake_id[] = {
  22. "client",
  23. "server"
  24. };
  25. #define ID_MINE (ecjpake_id[ctx->role])
  26. #define ID_PEER (ecjpake_id[1 - ctx->role])
  27. /**
  28. * Helper to Compute a hash from md_type
  29. */
  30. static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
  31. const unsigned char *input, size_t ilen,
  32. unsigned char *output)
  33. {
  34. return mbedtls_md(mbedtls_md_info_from_type(md_type),
  35. input, ilen, output);
  36. }
  37. /*
  38. * Initialize context
  39. */
  40. void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
  41. {
  42. ctx->md_type = MBEDTLS_MD_NONE;
  43. mbedtls_ecp_group_init(&ctx->grp);
  44. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  45. mbedtls_ecp_point_init(&ctx->Xm1);
  46. mbedtls_ecp_point_init(&ctx->Xm2);
  47. mbedtls_ecp_point_init(&ctx->Xp1);
  48. mbedtls_ecp_point_init(&ctx->Xp2);
  49. mbedtls_ecp_point_init(&ctx->Xp);
  50. mbedtls_mpi_init(&ctx->xm1);
  51. mbedtls_mpi_init(&ctx->xm2);
  52. mbedtls_mpi_init(&ctx->s);
  53. }
  54. /*
  55. * Free context
  56. */
  57. void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
  58. {
  59. if (ctx == NULL) {
  60. return;
  61. }
  62. ctx->md_type = MBEDTLS_MD_NONE;
  63. mbedtls_ecp_group_free(&ctx->grp);
  64. mbedtls_ecp_point_free(&ctx->Xm1);
  65. mbedtls_ecp_point_free(&ctx->Xm2);
  66. mbedtls_ecp_point_free(&ctx->Xp1);
  67. mbedtls_ecp_point_free(&ctx->Xp2);
  68. mbedtls_ecp_point_free(&ctx->Xp);
  69. mbedtls_mpi_free(&ctx->xm1);
  70. mbedtls_mpi_free(&ctx->xm2);
  71. mbedtls_mpi_free(&ctx->s);
  72. }
  73. /*
  74. * Setup context
  75. */
  76. int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
  77. mbedtls_ecjpake_role role,
  78. mbedtls_md_type_t hash,
  79. mbedtls_ecp_group_id curve,
  80. const unsigned char *secret,
  81. size_t len)
  82. {
  83. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  84. if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
  85. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  86. }
  87. ctx->role = role;
  88. if ((mbedtls_md_info_from_type(hash)) == NULL) {
  89. return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
  90. }
  91. ctx->md_type = hash;
  92. MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
  93. MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
  94. cleanup:
  95. if (ret != 0) {
  96. mbedtls_ecjpake_free(ctx);
  97. }
  98. return ret;
  99. }
  100. int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
  101. int point_format)
  102. {
  103. switch (point_format) {
  104. case MBEDTLS_ECP_PF_UNCOMPRESSED:
  105. case MBEDTLS_ECP_PF_COMPRESSED:
  106. ctx->point_format = point_format;
  107. return 0;
  108. default:
  109. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  110. }
  111. }
  112. /*
  113. * Check if context is ready for use
  114. */
  115. int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
  116. {
  117. if (ctx->md_type == MBEDTLS_MD_NONE ||
  118. ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
  119. ctx->s.p == NULL) {
  120. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  121. }
  122. return 0;
  123. }
  124. /*
  125. * Write a point plus its length to a buffer
  126. */
  127. static int ecjpake_write_len_point(unsigned char **p,
  128. const unsigned char *end,
  129. const mbedtls_ecp_group *grp,
  130. const int pf,
  131. const mbedtls_ecp_point *P)
  132. {
  133. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  134. size_t len;
  135. /* Need at least 4 for length plus 1 for point */
  136. if (end < *p || end - *p < 5) {
  137. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  138. }
  139. ret = mbedtls_ecp_point_write_binary(grp, P, pf,
  140. &len, *p + 4, (size_t) (end - (*p + 4)));
  141. if (ret != 0) {
  142. return ret;
  143. }
  144. MBEDTLS_PUT_UINT32_BE(len, *p, 0);
  145. *p += 4 + len;
  146. return 0;
  147. }
  148. /*
  149. * Size of the temporary buffer for ecjpake_hash:
  150. * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
  151. */
  152. #define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
  153. /*
  154. * Compute hash for ZKP (7.4.2.2.2.1)
  155. */
  156. static int ecjpake_hash(const mbedtls_md_type_t md_type,
  157. const mbedtls_ecp_group *grp,
  158. const int pf,
  159. const mbedtls_ecp_point *G,
  160. const mbedtls_ecp_point *V,
  161. const mbedtls_ecp_point *X,
  162. const char *id,
  163. mbedtls_mpi *h)
  164. {
  165. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  166. unsigned char buf[ECJPAKE_HASH_BUF_LEN];
  167. unsigned char *p = buf;
  168. const unsigned char *end = buf + sizeof(buf);
  169. const size_t id_len = strlen(id);
  170. unsigned char hash[MBEDTLS_MD_MAX_SIZE];
  171. /* Write things to temporary buffer */
  172. MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
  173. MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
  174. MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
  175. if (end - p < 4) {
  176. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  177. }
  178. MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
  179. p += 4;
  180. if (end < p || (size_t) (end - p) < id_len) {
  181. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  182. }
  183. memcpy(p, id, id_len);
  184. p += id_len;
  185. /* Compute hash */
  186. MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
  187. buf, (size_t) (p - buf), hash));
  188. /* Turn it into an integer mod n */
  189. MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
  190. mbedtls_md_get_size_from_type(md_type)));
  191. MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
  192. cleanup:
  193. return ret;
  194. }
  195. /*
  196. * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
  197. */
  198. static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
  199. const mbedtls_ecp_group *grp,
  200. const int pf,
  201. const mbedtls_ecp_point *G,
  202. const mbedtls_ecp_point *X,
  203. const char *id,
  204. const unsigned char **p,
  205. const unsigned char *end)
  206. {
  207. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  208. mbedtls_ecp_point V, VV;
  209. mbedtls_mpi r, h;
  210. size_t r_len;
  211. mbedtls_ecp_point_init(&V);
  212. mbedtls_ecp_point_init(&VV);
  213. mbedtls_mpi_init(&r);
  214. mbedtls_mpi_init(&h);
  215. /*
  216. * struct {
  217. * ECPoint V;
  218. * opaque r<1..2^8-1>;
  219. * } ECSchnorrZKP;
  220. */
  221. if (end < *p) {
  222. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  223. }
  224. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
  225. if (end < *p || (size_t) (end - *p) < 1) {
  226. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  227. goto cleanup;
  228. }
  229. r_len = *(*p)++;
  230. if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
  231. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  232. goto cleanup;
  233. }
  234. MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
  235. *p += r_len;
  236. /*
  237. * Verification
  238. */
  239. MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
  240. MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
  241. &VV, &h, X, &r, G));
  242. if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
  243. ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
  244. goto cleanup;
  245. }
  246. cleanup:
  247. mbedtls_ecp_point_free(&V);
  248. mbedtls_ecp_point_free(&VV);
  249. mbedtls_mpi_free(&r);
  250. mbedtls_mpi_free(&h);
  251. return ret;
  252. }
  253. /*
  254. * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
  255. */
  256. static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
  257. const mbedtls_ecp_group *grp,
  258. const int pf,
  259. const mbedtls_ecp_point *G,
  260. const mbedtls_mpi *x,
  261. const mbedtls_ecp_point *X,
  262. const char *id,
  263. unsigned char **p,
  264. const unsigned char *end,
  265. int (*f_rng)(void *, unsigned char *, size_t),
  266. void *p_rng)
  267. {
  268. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  269. mbedtls_ecp_point V;
  270. mbedtls_mpi v;
  271. mbedtls_mpi h; /* later recycled to hold r */
  272. size_t len;
  273. if (end < *p) {
  274. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  275. }
  276. mbedtls_ecp_point_init(&V);
  277. mbedtls_mpi_init(&v);
  278. mbedtls_mpi_init(&h);
  279. /* Compute signature */
  280. MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
  281. G, &v, &V, f_rng, p_rng));
  282. MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
  283. MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
  284. MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
  285. MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
  286. /* Write it out */
  287. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
  288. pf, &len, *p, (size_t) (end - *p)));
  289. *p += len;
  290. len = mbedtls_mpi_size(&h); /* actually r */
  291. if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
  292. ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  293. goto cleanup;
  294. }
  295. *(*p)++ = MBEDTLS_BYTE_0(len);
  296. MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
  297. *p += len;
  298. cleanup:
  299. mbedtls_ecp_point_free(&V);
  300. mbedtls_mpi_free(&v);
  301. mbedtls_mpi_free(&h);
  302. return ret;
  303. }
  304. /*
  305. * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
  306. * Output: verified public key X
  307. */
  308. static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
  309. const mbedtls_ecp_group *grp,
  310. const int pf,
  311. const mbedtls_ecp_point *G,
  312. mbedtls_ecp_point *X,
  313. const char *id,
  314. const unsigned char **p,
  315. const unsigned char *end)
  316. {
  317. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  318. if (end < *p) {
  319. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  320. }
  321. /*
  322. * struct {
  323. * ECPoint X;
  324. * ECSchnorrZKP zkp;
  325. * } ECJPAKEKeyKP;
  326. */
  327. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
  328. if (mbedtls_ecp_is_zero(X)) {
  329. ret = MBEDTLS_ERR_ECP_INVALID_KEY;
  330. goto cleanup;
  331. }
  332. MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
  333. cleanup:
  334. return ret;
  335. }
  336. /*
  337. * Generate an ECJPAKEKeyKP
  338. * Output: the serialized structure, plus private/public key pair
  339. */
  340. static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
  341. const mbedtls_ecp_group *grp,
  342. const int pf,
  343. const mbedtls_ecp_point *G,
  344. mbedtls_mpi *x,
  345. mbedtls_ecp_point *X,
  346. const char *id,
  347. unsigned char **p,
  348. const unsigned char *end,
  349. int (*f_rng)(void *, unsigned char *, size_t),
  350. void *p_rng)
  351. {
  352. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  353. size_t len;
  354. if (end < *p) {
  355. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  356. }
  357. /* Generate key (7.4.2.3.1) and write it out */
  358. MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
  359. f_rng, p_rng));
  360. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
  361. pf, &len, *p, (size_t) (end - *p)));
  362. *p += len;
  363. /* Generate and write proof */
  364. MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
  365. p, end, f_rng, p_rng));
  366. cleanup:
  367. return ret;
  368. }
  369. /*
  370. * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
  371. * Outputs: verified peer public keys Xa, Xb
  372. */
  373. static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
  374. const mbedtls_ecp_group *grp,
  375. const int pf,
  376. const mbedtls_ecp_point *G,
  377. mbedtls_ecp_point *Xa,
  378. mbedtls_ecp_point *Xb,
  379. const char *id,
  380. const unsigned char *buf,
  381. size_t len)
  382. {
  383. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  384. const unsigned char *p = buf;
  385. const unsigned char *end = buf + len;
  386. /*
  387. * struct {
  388. * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
  389. * } ECJPAKEKeyKPPairList;
  390. */
  391. MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
  392. MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
  393. if (p != end) {
  394. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  395. }
  396. cleanup:
  397. return ret;
  398. }
  399. /*
  400. * Generate a ECJPAKEKeyKPPairList
  401. * Outputs: the serialized structure, plus two private/public key pairs
  402. */
  403. static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
  404. const mbedtls_ecp_group *grp,
  405. const int pf,
  406. const mbedtls_ecp_point *G,
  407. mbedtls_mpi *xm1,
  408. mbedtls_ecp_point *Xa,
  409. mbedtls_mpi *xm2,
  410. mbedtls_ecp_point *Xb,
  411. const char *id,
  412. unsigned char *buf,
  413. size_t len,
  414. size_t *olen,
  415. int (*f_rng)(void *, unsigned char *, size_t),
  416. void *p_rng)
  417. {
  418. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  419. unsigned char *p = buf;
  420. const unsigned char *end = buf + len;
  421. MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
  422. &p, end, f_rng, p_rng));
  423. MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
  424. &p, end, f_rng, p_rng));
  425. *olen = (size_t) (p - buf);
  426. cleanup:
  427. return ret;
  428. }
  429. /*
  430. * Read and process the first round message
  431. */
  432. int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
  433. const unsigned char *buf,
  434. size_t len)
  435. {
  436. return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
  437. &ctx->grp.G,
  438. &ctx->Xp1, &ctx->Xp2, ID_PEER,
  439. buf, len);
  440. }
  441. /*
  442. * Generate and write the first round message
  443. */
  444. int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
  445. unsigned char *buf, size_t len, size_t *olen,
  446. int (*f_rng)(void *, unsigned char *, size_t),
  447. void *p_rng)
  448. {
  449. return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
  450. &ctx->grp.G,
  451. &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
  452. ID_MINE, buf, len, olen, f_rng, p_rng);
  453. }
  454. /*
  455. * Compute the sum of three points R = A + B + C
  456. */
  457. static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
  458. const mbedtls_ecp_point *A,
  459. const mbedtls_ecp_point *B,
  460. const mbedtls_ecp_point *C)
  461. {
  462. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  463. mbedtls_mpi one;
  464. mbedtls_mpi_init(&one);
  465. MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
  466. MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
  467. MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
  468. cleanup:
  469. mbedtls_mpi_free(&one);
  470. return ret;
  471. }
  472. /*
  473. * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
  474. */
  475. int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
  476. const unsigned char *buf,
  477. size_t len)
  478. {
  479. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  480. const unsigned char *p = buf;
  481. const unsigned char *end = buf + len;
  482. mbedtls_ecp_group grp;
  483. mbedtls_ecp_point G; /* C: GB, S: GA */
  484. mbedtls_ecp_group_init(&grp);
  485. mbedtls_ecp_point_init(&G);
  486. /*
  487. * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
  488. * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
  489. * Unified: G = Xm1 + Xm2 + Xp1
  490. * We need that before parsing in order to check Xp as we read it
  491. */
  492. MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
  493. &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
  494. /*
  495. * struct {
  496. * ECParameters curve_params; // only client reading server msg
  497. * ECJPAKEKeyKP ecjpake_key_kp;
  498. * } Client/ServerECJPAKEParams;
  499. */
  500. if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
  501. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
  502. if (grp.id != ctx->grp.id) {
  503. ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
  504. goto cleanup;
  505. }
  506. }
  507. MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
  508. ctx->point_format,
  509. &G, &ctx->Xp, ID_PEER, &p, end));
  510. if (p != end) {
  511. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  512. goto cleanup;
  513. }
  514. cleanup:
  515. mbedtls_ecp_group_free(&grp);
  516. mbedtls_ecp_point_free(&G);
  517. return ret;
  518. }
  519. /*
  520. * Compute R = +/- X * S mod N, taking care not to leak S
  521. */
  522. static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
  523. const mbedtls_mpi *X,
  524. const mbedtls_mpi *S,
  525. const mbedtls_mpi *N,
  526. int (*f_rng)(void *, unsigned char *, size_t),
  527. void *p_rng)
  528. {
  529. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  530. mbedtls_mpi b; /* Blinding value, then s + N * blinding */
  531. mbedtls_mpi_init(&b);
  532. /* b = s + rnd-128-bit * N */
  533. MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
  534. MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
  535. MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
  536. /* R = sign * X * b mod N */
  537. MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
  538. R->s *= sign;
  539. MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
  540. cleanup:
  541. mbedtls_mpi_free(&b);
  542. return ret;
  543. }
  544. /*
  545. * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
  546. */
  547. int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
  548. unsigned char *buf, size_t len, size_t *olen,
  549. int (*f_rng)(void *, unsigned char *, size_t),
  550. void *p_rng)
  551. {
  552. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  553. mbedtls_ecp_point G; /* C: GA, S: GB */
  554. mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
  555. mbedtls_mpi xm; /* C: xc, S: xs */
  556. unsigned char *p = buf;
  557. const unsigned char *end = buf + len;
  558. size_t ec_len;
  559. mbedtls_ecp_point_init(&G);
  560. mbedtls_ecp_point_init(&Xm);
  561. mbedtls_mpi_init(&xm);
  562. /*
  563. * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
  564. *
  565. * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
  566. * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
  567. * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
  568. */
  569. MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
  570. &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
  571. MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
  572. &ctx->grp.N, f_rng, p_rng));
  573. MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
  574. /*
  575. * Now write things out
  576. *
  577. * struct {
  578. * ECParameters curve_params; // only server writing its message
  579. * ECJPAKEKeyKP ecjpake_key_kp;
  580. * } Client/ServerECJPAKEParams;
  581. */
  582. if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
  583. if (end < p) {
  584. ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  585. goto cleanup;
  586. }
  587. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
  588. p, (size_t) (end - p)));
  589. p += ec_len;
  590. }
  591. if (end < p) {
  592. ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  593. goto cleanup;
  594. }
  595. MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
  596. ctx->point_format, &ec_len, p, (size_t) (end - p)));
  597. p += ec_len;
  598. MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
  599. ctx->point_format,
  600. &G, &xm, &Xm, ID_MINE,
  601. &p, end, f_rng, p_rng));
  602. *olen = (size_t) (p - buf);
  603. cleanup:
  604. mbedtls_ecp_point_free(&G);
  605. mbedtls_ecp_point_free(&Xm);
  606. mbedtls_mpi_free(&xm);
  607. return ret;
  608. }
  609. /*
  610. * Derive PMS (7.4.2.7 / 7.4.2.8)
  611. */
  612. static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
  613. mbedtls_ecp_point *K,
  614. int (*f_rng)(void *, unsigned char *, size_t),
  615. void *p_rng)
  616. {
  617. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  618. mbedtls_mpi m_xm2_s, one;
  619. mbedtls_mpi_init(&m_xm2_s);
  620. mbedtls_mpi_init(&one);
  621. MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
  622. /*
  623. * Client: K = ( Xs - X4 * x2 * s ) * x2
  624. * Server: K = ( Xc - X2 * x4 * s ) * x4
  625. * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
  626. */
  627. MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
  628. &ctx->grp.N, f_rng, p_rng));
  629. MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
  630. &one, &ctx->Xp,
  631. &m_xm2_s, &ctx->Xp2));
  632. MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
  633. f_rng, p_rng));
  634. cleanup:
  635. mbedtls_mpi_free(&m_xm2_s);
  636. mbedtls_mpi_free(&one);
  637. return ret;
  638. }
  639. int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
  640. unsigned char *buf, size_t len, size_t *olen,
  641. int (*f_rng)(void *, unsigned char *, size_t),
  642. void *p_rng)
  643. {
  644. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  645. mbedtls_ecp_point K;
  646. unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
  647. size_t x_bytes;
  648. *olen = mbedtls_md_get_size_from_type(ctx->md_type);
  649. if (len < *olen) {
  650. return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
  651. }
  652. mbedtls_ecp_point_init(&K);
  653. ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
  654. if (ret) {
  655. goto cleanup;
  656. }
  657. /* PMS = SHA-256( K.X ) */
  658. x_bytes = (ctx->grp.pbits + 7) / 8;
  659. MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
  660. MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
  661. kx, x_bytes, buf));
  662. cleanup:
  663. mbedtls_ecp_point_free(&K);
  664. return ret;
  665. }
  666. int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
  667. unsigned char *buf, size_t len, size_t *olen,
  668. int (*f_rng)(void *, unsigned char *, size_t),
  669. void *p_rng)
  670. {
  671. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  672. mbedtls_ecp_point K;
  673. mbedtls_ecp_point_init(&K);
  674. ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
  675. if (ret) {
  676. goto cleanup;
  677. }
  678. ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
  679. olen, buf, len);
  680. if (ret != 0) {
  681. goto cleanup;
  682. }
  683. cleanup:
  684. mbedtls_ecp_point_free(&K);
  685. return ret;
  686. }
  687. #undef ID_MINE
  688. #undef ID_PEER
  689. #endif /* ! MBEDTLS_ECJPAKE_ALT */
  690. #if defined(MBEDTLS_SELF_TEST)
  691. #include "mbedtls/platform.h"
  692. #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
  693. !defined(MBEDTLS_MD_CAN_SHA256)
  694. int mbedtls_ecjpake_self_test(int verbose)
  695. {
  696. (void) verbose;
  697. return 0;
  698. }
  699. #else
  700. static const unsigned char ecjpake_test_password[] = {
  701. 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
  702. 0x65, 0x73, 0x74
  703. };
  704. #if !defined(MBEDTLS_ECJPAKE_ALT)
  705. static const unsigned char ecjpake_test_x1[] = {
  706. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
  707. 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
  708. 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
  709. };
  710. static const unsigned char ecjpake_test_x2[] = {
  711. 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
  712. 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  713. 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
  714. };
  715. static const unsigned char ecjpake_test_x3[] = {
  716. 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
  717. 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  718. 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
  719. };
  720. static const unsigned char ecjpake_test_x4[] = {
  721. 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
  722. 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
  723. 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
  724. };
  725. static const unsigned char ecjpake_test_cli_one[] = {
  726. 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
  727. 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
  728. 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
  729. 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
  730. 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
  731. 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
  732. 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
  733. 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
  734. 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
  735. 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
  736. 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
  737. 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
  738. 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
  739. 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
  740. 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
  741. 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
  742. 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
  743. 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
  744. 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
  745. 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
  746. 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
  747. 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
  748. 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
  749. 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
  750. 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
  751. 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
  752. 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
  753. 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
  754. };
  755. static const unsigned char ecjpake_test_srv_one[] = {
  756. 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
  757. 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
  758. 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
  759. 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
  760. 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
  761. 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
  762. 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
  763. 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
  764. 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
  765. 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
  766. 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
  767. 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
  768. 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
  769. 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
  770. 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
  771. 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
  772. 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
  773. 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
  774. 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
  775. 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
  776. 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
  777. 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
  778. 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
  779. 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
  780. 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
  781. 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
  782. 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
  783. 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
  784. };
  785. static const unsigned char ecjpake_test_srv_two[] = {
  786. 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
  787. 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
  788. 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
  789. 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
  790. 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
  791. 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
  792. 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
  793. 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
  794. 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
  795. 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
  796. 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
  797. 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
  798. 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
  799. 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
  800. };
  801. static const unsigned char ecjpake_test_cli_two[] = {
  802. 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
  803. 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
  804. 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
  805. 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
  806. 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
  807. 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
  808. 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
  809. 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
  810. 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
  811. 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
  812. 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
  813. 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
  814. 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
  815. 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
  816. };
  817. static const unsigned char ecjpake_test_shared_key[] = {
  818. 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
  819. 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
  820. 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
  821. 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
  822. 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
  823. 0x17, 0xc3, 0xde, 0x27, 0xb4,
  824. };
  825. static const unsigned char ecjpake_test_pms[] = {
  826. 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
  827. 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
  828. 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
  829. };
  830. /*
  831. * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
  832. *
  833. * This is the linear congruential generator from numerical recipes,
  834. * except we only use the low byte as the output. See
  835. * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
  836. */
  837. static int self_test_rng(void *ctx, unsigned char *out, size_t len)
  838. {
  839. static uint32_t state = 42;
  840. (void) ctx;
  841. for (size_t i = 0; i < len; i++) {
  842. state = state * 1664525u + 1013904223u;
  843. out[i] = (unsigned char) state;
  844. }
  845. return 0;
  846. }
  847. /* Load my private keys and generate the corresponding public keys */
  848. static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
  849. const unsigned char *xm1, size_t len1,
  850. const unsigned char *xm2, size_t len2)
  851. {
  852. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  853. MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
  854. MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
  855. MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
  856. &ctx->grp.G, self_test_rng, NULL));
  857. MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
  858. &ctx->grp.G, self_test_rng, NULL));
  859. cleanup:
  860. return ret;
  861. }
  862. #endif /* ! MBEDTLS_ECJPAKE_ALT */
  863. /* For tests we don't need a secure RNG;
  864. * use the LGC from Numerical Recipes for simplicity */
  865. static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
  866. {
  867. static uint32_t x = 42;
  868. (void) p;
  869. while (len > 0) {
  870. size_t use_len = len > 4 ? 4 : len;
  871. x = 1664525 * x + 1013904223;
  872. memcpy(out, &x, use_len);
  873. out += use_len;
  874. len -= use_len;
  875. }
  876. return 0;
  877. }
  878. #define TEST_ASSERT(x) \
  879. do { \
  880. if (x) \
  881. ret = 0; \
  882. else \
  883. { \
  884. ret = 1; \
  885. goto cleanup; \
  886. } \
  887. } while (0)
  888. /*
  889. * Checkup routine
  890. */
  891. int mbedtls_ecjpake_self_test(int verbose)
  892. {
  893. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  894. mbedtls_ecjpake_context cli;
  895. mbedtls_ecjpake_context srv;
  896. unsigned char buf[512], pms[32];
  897. size_t len, pmslen;
  898. mbedtls_ecjpake_init(&cli);
  899. mbedtls_ecjpake_init(&srv);
  900. if (verbose != 0) {
  901. mbedtls_printf(" ECJPAKE test #0 (setup): ");
  902. }
  903. TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
  904. MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
  905. ecjpake_test_password,
  906. sizeof(ecjpake_test_password)) == 0);
  907. TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
  908. MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
  909. ecjpake_test_password,
  910. sizeof(ecjpake_test_password)) == 0);
  911. if (verbose != 0) {
  912. mbedtls_printf("passed\n");
  913. }
  914. if (verbose != 0) {
  915. mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
  916. }
  917. TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
  918. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  919. TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
  920. TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
  921. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  922. TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
  923. TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
  924. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  925. TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
  926. TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
  927. pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
  928. TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
  929. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  930. TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
  931. TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
  932. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  933. TEST_ASSERT(len == pmslen);
  934. TEST_ASSERT(memcmp(buf, pms, len) == 0);
  935. if (verbose != 0) {
  936. mbedtls_printf("passed\n");
  937. }
  938. #if !defined(MBEDTLS_ECJPAKE_ALT)
  939. /* 'reference handshake' tests can only be run against implementations
  940. * for which we have 100% control over how the random ephemeral keys
  941. * are generated. This is only the case for the internal Mbed TLS
  942. * implementation, so these tests are skipped in case the internal
  943. * implementation is swapped out for an alternative one. */
  944. if (verbose != 0) {
  945. mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
  946. }
  947. /* Simulate generation of round one */
  948. MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
  949. ecjpake_test_x1, sizeof(ecjpake_test_x1),
  950. ecjpake_test_x2, sizeof(ecjpake_test_x2)));
  951. MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
  952. ecjpake_test_x3, sizeof(ecjpake_test_x3),
  953. ecjpake_test_x4, sizeof(ecjpake_test_x4)));
  954. /* Read round one */
  955. TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
  956. ecjpake_test_cli_one,
  957. sizeof(ecjpake_test_cli_one)) == 0);
  958. TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
  959. ecjpake_test_srv_one,
  960. sizeof(ecjpake_test_srv_one)) == 0);
  961. /* Skip generation of round two, read round two */
  962. TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
  963. ecjpake_test_srv_two,
  964. sizeof(ecjpake_test_srv_two)) == 0);
  965. TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
  966. ecjpake_test_cli_two,
  967. sizeof(ecjpake_test_cli_two)) == 0);
  968. /* Server derives PMS */
  969. TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
  970. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  971. TEST_ASSERT(len == sizeof(ecjpake_test_pms));
  972. TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
  973. /* Server derives K as unsigned binary data */
  974. TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
  975. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  976. TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
  977. TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
  978. memset(buf, 0, len); /* Avoid interferences with next step */
  979. /* Client derives PMS */
  980. TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
  981. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  982. TEST_ASSERT(len == sizeof(ecjpake_test_pms));
  983. TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
  984. /* Client derives K as unsigned binary data */
  985. TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
  986. buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
  987. TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
  988. TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
  989. if (verbose != 0) {
  990. mbedtls_printf("passed\n");
  991. }
  992. #endif /* ! MBEDTLS_ECJPAKE_ALT */
  993. cleanup:
  994. mbedtls_ecjpake_free(&cli);
  995. mbedtls_ecjpake_free(&srv);
  996. if (ret != 0) {
  997. if (verbose != 0) {
  998. mbedtls_printf("failed\n");
  999. }
  1000. ret = 1;
  1001. }
  1002. if (verbose != 0) {
  1003. mbedtls_printf("\n");
  1004. }
  1005. return ret;
  1006. }
  1007. #undef TEST_ASSERT
  1008. #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
  1009. #endif /* MBEDTLS_SELF_TEST */
  1010. #endif /* MBEDTLS_ECJPAKE_C */