blob: 922be205f684c00bf7580bc06f44dc8b5b62835a [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +020023 * We implement EC-JPAKE as defined in Chapter 7.4 of the Thread v1.0
24 * Specification. References below are to this document.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020025 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_ECJPAKE_C)
34
35#include "mbedtls/ecjpake.h"
36
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020037#include <string.h>
38
39/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020040 * Initialize context
41 */
42void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
43{
44 if( ctx == NULL )
45 return;
46
47 ctx->md_info = NULL;
48 mbedtls_ecp_group_init( &ctx->grp );
49
50 mbedtls_ecp_point_init( &ctx->X1 );
51 mbedtls_ecp_point_init( &ctx->X2 );
52 mbedtls_ecp_point_init( &ctx->X3 );
53 mbedtls_ecp_point_init( &ctx->X4 );
54
55 mbedtls_mpi_init( &ctx->xa );
56 mbedtls_mpi_init( &ctx->xb );
57}
58
59/*
60 * Free context
61 */
62void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
63{
64 if( ctx == NULL )
65 return;
66
67 ctx->md_info = NULL;
68 mbedtls_ecp_group_free( &ctx->grp );
69
70 mbedtls_ecp_point_free( &ctx->X1 );
71 mbedtls_ecp_point_free( &ctx->X2 );
72 mbedtls_ecp_point_free( &ctx->X3 );
73 mbedtls_ecp_point_free( &ctx->X4 );
74
75 mbedtls_mpi_free( &ctx->xa );
76 mbedtls_mpi_free( &ctx->xb );
77}
78
79/*
80 * Setup context
81 */
82int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
83 mbedtls_md_type_t hash,
84 mbedtls_ecp_group_id curve )
85{
86 int ret;
87
88 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
89 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
90
91 if( ( ret = mbedtls_ecp_group_load( &ctx->grp, curve ) ) != 0 )
92 return( ret );
93
94 return( 0 );
95}
96
97/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020098 * Write a point plus its length to a buffer
99 */
100static int ecjpake_write_len_point( unsigned char **p,
101 const unsigned char *end,
102 const mbedtls_ecp_group *grp,
103 const mbedtls_ecp_point *P )
104{
105 int ret;
106 size_t len;
107
108 /* Need at least 4 for length plus 1 for point */
109 if( end < *p || end - *p < 5 )
110 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
111
112 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
113 &len, *p + 4, end - ( *p + 4 ) );
114 if( ret != 0 )
115 return( ret );
116
117 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
118 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
119 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
120 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
121
122 *p += 4 + len;
123
124 return( 0 );
125}
126
127/*
128 * Size of the temporary buffer for ecjpake_hash:
129 * 3 EC points plus their length, plus ID (6 bytes)
130 */
131#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
132
133/*
134 * Compute hash for ZKP (7.4.2.2.2.1)
135 */
136static int ecjpake_hash( const mbedtls_md_info_t *md_info,
137 const mbedtls_ecp_group *grp,
138 const mbedtls_ecp_point *G,
139 const mbedtls_ecp_point *V,
140 const mbedtls_ecp_point *X,
141 const char *id,
142 mbedtls_mpi *h )
143{
144 int ret;
145 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
146 unsigned char *p = buf;
147 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200148 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200149 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
150
151 /* Write things to temporary buffer */
152 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
153 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
154 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
155
156 if( end < p || (size_t)( end - p ) < id_len )
157 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
158
159 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
160 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
161 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
162 *p++ = (unsigned char)( ( id_len ) & 0xFF );
163
164 memcpy( p, id, id_len );
165 p += id_len;
166
167 /* Compute hash */
168 mbedtls_md( md_info, buf, p - buf, hash );
169
170 /* Turn it into an integer mod n */
171 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
172 mbedtls_md_get_size( md_info ) ) );
173 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
174
175cleanup:
176 return( ret );
177}
178
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200179/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200180 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
181 */
182static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
183 const mbedtls_ecp_group *grp,
184 const mbedtls_ecp_point *G,
185 const mbedtls_ecp_point *X,
186 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200187 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200188 const unsigned char *end )
189{
190 int ret;
191 mbedtls_ecp_point V, VV;
192 mbedtls_mpi r, h;
193 size_t r_len;
194
195 mbedtls_ecp_point_init( &V );
196 mbedtls_ecp_point_init( &VV );
197 mbedtls_mpi_init( &r );
198 mbedtls_mpi_init( &h );
199
200 /*
201 * struct {
202 * ECPoint V;
203 * opaque r<1..2^8-1>;
204 * } ECSchnorrZKP;
205 */
206 if( end < *p )
207 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
208
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200209 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200210
211 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200212 {
213 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
214 goto cleanup;
215 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200216
217 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200218
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200219 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200220 {
221 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
222 goto cleanup;
223 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200224
225 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
226 *p += r_len;
227
228 /*
229 * Verification
230 */
231 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
232 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
233 &VV, &h, X, &r, G ) );
234
235 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200236 {
237 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
238 goto cleanup;
239 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200240
241cleanup:
242 mbedtls_ecp_point_free( &V );
243 mbedtls_ecp_point_free( &VV );
244 mbedtls_mpi_free( &r );
245 mbedtls_mpi_free( &h );
246
247 return( ret );
248}
249
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200250/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200251 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
252 */
253static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
254 const mbedtls_ecp_group *grp,
255 const mbedtls_ecp_point *G,
256 const mbedtls_mpi *x,
257 const mbedtls_ecp_point *X,
258 const char *id,
259 unsigned char **p,
260 const unsigned char *end,
261 int (*f_rng)(void *, unsigned char *, size_t),
262 void *p_rng )
263{
264 int ret;
265 mbedtls_ecp_point V;
266 mbedtls_mpi v;
267 mbedtls_mpi h; /* later recycled to hold r */
268 size_t len;
269
270 if( end < *p )
271 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
272
273 mbedtls_ecp_point_init( &V );
274 mbedtls_mpi_init( &v );
275 mbedtls_mpi_init( &h );
276
277 /* Compute signature */
278 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
279 G, &v, &V, f_rng, p_rng ) );
280 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
281 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
282 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
283 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
284
285 /* Write it out */
286 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
287 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
288 *p += len;
289
290 len = mbedtls_mpi_size( &h ); /* actually r */
291 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
292 {
293 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
294 goto cleanup;
295 }
296
297 *(*p)++ = (unsigned char)( len & 0xFF );
298 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
299 *p += len;
300
301cleanup:
302 mbedtls_ecp_point_free( &V );
303 mbedtls_mpi_free( &v );
304 mbedtls_mpi_free( &h );
305
306 return( ret );
307}
308
309/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200310 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
311 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200312 */
313static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
314 const mbedtls_ecp_group *grp,
315 const mbedtls_ecp_point *G,
316 mbedtls_ecp_point *X,
317 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200318 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200319 const unsigned char *end )
320{
321 int ret;
322
323 if( end < *p )
324 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
325
326 /*
327 * struct {
328 * ECPoint X;
329 * ECSchnorrZKP zkp;
330 * } ECJPAKEKeyKP;
331 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200332 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200333 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
334
335cleanup:
336 return( ret );
337}
338
339/*
340 * Generate an ECJPAKEKeyKP
341 * Output: the serialized structure, plus private/public key pair
342 */
343static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
344 const mbedtls_ecp_group *grp,
345 const mbedtls_ecp_point *G,
346 mbedtls_mpi *x,
347 mbedtls_ecp_point *X,
348 const char *id,
349 unsigned char **p,
350 const unsigned char *end,
351 int (*f_rng)(void *, unsigned char *, size_t),
352 void *p_rng )
353{
354 int ret;
355 size_t len;
356
357 if( end < *p )
358 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
359
360 /* Generate key (7.4.2.3.1) and write it out */
361 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
362 f_rng, p_rng ) );
363 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
364 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
365 *p += len;
366
367 /* Generate and write proof */
368 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
369 p, end, f_rng, p_rng ) );
370
371cleanup:
372 return( ret );
373}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200374
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200375/*
376 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
377 * Ouputs: verified peer public keys Xa, Xb
378 */
379static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
380 const mbedtls_ecp_group *grp,
381 const mbedtls_ecp_point *G,
382 mbedtls_ecp_point *Xa,
383 mbedtls_ecp_point *Xb,
384 const char *id,
385 const unsigned char *buf,
386 size_t len )
387{
388 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200389 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200390 const unsigned char *end = buf + len;
391
392 /*
393 * struct {
394 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
395 * } ECJPAKEKeyKPPairList;
396 */
397 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
398 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
399
400 if( p != end )
401 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
402
403cleanup:
404 return( ret );
405}
406
407/*
408 * Generate a ECJPAKEKeyKPPairList
409 * Outputs: the serialized structure, plus two private/public key pairs
410 */
411static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
412 const mbedtls_ecp_group *grp,
413 const mbedtls_ecp_point *G,
414 mbedtls_mpi *xa,
415 mbedtls_ecp_point *Xa,
416 mbedtls_mpi *xb,
417 mbedtls_ecp_point *Xb,
418 const char *id,
419 unsigned char *buf,
420 size_t len,
421 size_t *olen,
422 int (*f_rng)(void *, unsigned char *, size_t),
423 void *p_rng )
424{
425 int ret;
426 unsigned char *p = buf;
427 const unsigned char *end = buf + len;
428
429 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
430 &p, end, f_rng, p_rng ) );
431 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
432 &p, end, f_rng, p_rng ) );
433
434 *olen = p - buf;
435
436cleanup:
437 return( ret );
438}
439
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200440/*
441 * Read the contents of the ClientHello extension
442 */
443int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
444 const unsigned char *buf,
445 size_t len )
446{
447 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
448 &ctx->X1, &ctx->X2, "client",
449 buf, len ) );
450}
451
452/*
453 * Read the contents of the ServerHello extension
454 */
455int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
456 const unsigned char *buf,
457 size_t len )
458{
459 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
460 &ctx->X3, &ctx->X4, "server",
461 buf, len ) );
462}
463
464/*
465 * Generate the contents of the ClientHello extension
466 */
467int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
468 unsigned char *buf, size_t len, size_t *olen,
469 int (*f_rng)(void *, unsigned char *, size_t),
470 void *p_rng )
471{
472 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
473 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
474 "client", buf, len, olen, f_rng, p_rng ) );
475}
476
477/*
478 * Generate the contents of the ServerHello extension
479 */
480int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
481 unsigned char *buf, size_t len, size_t *olen,
482 int (*f_rng)(void *, unsigned char *, size_t),
483 void *p_rng )
484{
485 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
486 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
487 "server", buf, len, olen, f_rng, p_rng ) );
488}
489
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200490#if defined(MBEDTLS_SELF_TEST)
491
492#if defined(MBEDTLS_PLATFORM_C)
493#include "mbedtls/platform.h"
494#else
495#include <stdio.h>
496#define mbedtls_printf printf
497#endif
498
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200499#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
500 !defined(MBEDTLS_SHA256_C)
501int mbedtls_ecjpake_self_test( int verbose )
502{
503 (void) verbose;
504 return( 0 );
505}
506#else
507
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200508static const unsigned char ecjpake_test_kkpp[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200509 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
510 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
511 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
512 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
513 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
514 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
515 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
516 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
517 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
518 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
519 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
520 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
521 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200522 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
523 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
524 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
525 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
526 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
527 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
528 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
529 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
530 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
531 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
532 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
533 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
534 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
535 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
536 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200537};
538
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200539/* For tests we don't need a secure RNG;
540 * use the LGC from Numerical Recipes for simplicity */
541static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
542{
543 static uint32_t x = 42;
544 (void) p;
545
546 while( len > 0 )
547 {
548 size_t use_len = len > 4 ? 4 : len;
549 x = 1664525 * x + 1013904223;
550 memcpy( out, &x, use_len );
551 out += use_len;
552 len -= use_len;
553 }
554
555 return( 0 );
556}
557
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200558#define TEST_ASSERT( x ) \
559 do { \
560 if( x ) \
561 ret = 0; \
562 else \
563 { \
564 ret = 1; \
565 goto cleanup; \
566 } \
567 } while( 0 )
568
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200569/*
570 * Checkup routine
571 */
572int mbedtls_ecjpake_self_test( int verbose )
573{
574 int ret;
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200575 mbedtls_ecjpake_context ctx;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200576 unsigned char buf[1000];
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200577 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200578
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200579 mbedtls_ecjpake_init( &ctx );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200580
581 /* Common to all tests */
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200582 TEST_ASSERT( mbedtls_ecjpake_setup( &ctx, MBEDTLS_MD_SHA256,
583 MBEDTLS_ECP_DP_SECP256R1 ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200584
585 if( verbose != 0 )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200586 mbedtls_printf( " ECJPAKE test #1 (client ext read): " );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200587
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200588 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200589 ecjpake_test_kkpp,
590 sizeof( ecjpake_test_kkpp ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200591
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200592 /* Corrupt message */
593 memcpy( buf, ecjpake_test_kkpp, sizeof( ecjpake_test_kkpp ) );
594 buf[sizeof( ecjpake_test_kkpp ) - 1]--;
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200595 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200596 buf, sizeof( ecjpake_test_kkpp ) )
597 == MBEDTLS_ERR_ECP_VERIFY_FAILED );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200598
599 if( verbose != 0 )
600 mbedtls_printf( "passed\n" );
601
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200602 if( verbose != 0 )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200603 mbedtls_printf( " ECJPAKE test #2 (client ext write/read): " );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200604
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200605 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200606 buf, sizeof( buf ), &len,
607 ecjpake_lgc, NULL ) == 0 );
608
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200609 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx, buf, len ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200610
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200611 if( verbose != 0 )
612 mbedtls_printf( "passed\n" );
613
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200614cleanup:
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200615 mbedtls_ecjpake_free( &ctx );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200616
617 if( ret != 0 )
618 {
619 if( verbose != 0 )
620 mbedtls_printf( "failed\n" );
621
622 ret = 1;
623 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200624
625 if( verbose != 0 )
626 mbedtls_printf( "\n" );
627
628 return( ret );
629}
630
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200631#undef TEST_ASSERT
632
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200633#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
634
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200635#endif /* MBEDTLS_SELF_TEST */
636
637#endif /* MBEDTLS_ECJPAKE_C */