blob: 678112c57b7c5d91cb5da96156690315f167b9ad [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é-Gonnard4d8685b2015-08-05 15:44:42 +0200440#if defined(MBEDTLS_SELF_TEST)
441
442#if defined(MBEDTLS_PLATFORM_C)
443#include "mbedtls/platform.h"
444#else
445#include <stdio.h>
446#define mbedtls_printf printf
447#endif
448
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200449#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
450 !defined(MBEDTLS_SHA256_C)
451int mbedtls_ecjpake_self_test( int verbose )
452{
453 (void) verbose;
454 return( 0 );
455}
456#else
457
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200458static const unsigned char ecjpake_test_kkpp[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200459 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
460 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
461 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
462 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
463 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
464 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
465 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
466 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
467 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
468 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
469 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
470 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
471 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
473 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
474 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
475 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
476 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
477 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
478 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
479 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
480 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
481 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
482 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
483 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
484 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
485 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
486 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200487};
488
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200489/* For tests we don't need a secure RNG;
490 * use the LGC from Numerical Recipes for simplicity */
491static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
492{
493 static uint32_t x = 42;
494 (void) p;
495
496 while( len > 0 )
497 {
498 size_t use_len = len > 4 ? 4 : len;
499 x = 1664525 * x + 1013904223;
500 memcpy( out, &x, use_len );
501 out += use_len;
502 len -= use_len;
503 }
504
505 return( 0 );
506}
507
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200508#define TEST_ASSERT( x ) \
509 do { \
510 if( x ) \
511 ret = 0; \
512 else \
513 { \
514 ret = 1; \
515 goto cleanup; \
516 } \
517 } while( 0 )
518
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200519/*
520 * Checkup routine
521 */
522int mbedtls_ecjpake_self_test( int verbose )
523{
524 int ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200525 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200526 mbedtls_ecp_point Xa, Xb;
527 mbedtls_mpi xa, xb;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200528 const mbedtls_md_info_t *md_info;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200529 unsigned char buf[1000];
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200530 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200531
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200532 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200533 mbedtls_ecp_point_init( &Xa );
534 mbedtls_ecp_point_init( &Xb );
535 mbedtls_mpi_init( &xa );
536 mbedtls_mpi_init( &xb );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200537
538 /* Common to all tests */
539 md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
540 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP256R1 ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200541
542 if( verbose != 0 )
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200543 mbedtls_printf( " ECJPAKE test #1 (kkpp read): " );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200544
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200545 TEST_ASSERT( ecjpake_kkpp_read( md_info, &grp, &grp.G,
546 &Xa, &Xb, "client",
547 ecjpake_test_kkpp,
548 sizeof( ecjpake_test_kkpp ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200549
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200550 /* Corrupt message */
551 memcpy( buf, ecjpake_test_kkpp, sizeof( ecjpake_test_kkpp ) );
552 buf[sizeof( ecjpake_test_kkpp ) - 1]--;
553 TEST_ASSERT( ecjpake_kkpp_read( md_info, &grp, &grp.G,
554 &Xa, &Xb, "client",
555 buf, sizeof( ecjpake_test_kkpp ) )
556 == MBEDTLS_ERR_ECP_VERIFY_FAILED );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200557
558 if( verbose != 0 )
559 mbedtls_printf( "passed\n" );
560
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200561 if( verbose != 0 )
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200562 mbedtls_printf( " ECJPAKE test #2 (kkpp write/read): " );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200563
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200564 TEST_ASSERT( ecjpake_kkpp_write( md_info, &grp, &grp.G,
565 &xa, &Xa, &xb, &Xb, "client",
566 buf, sizeof( buf ), &len,
567 ecjpake_lgc, NULL ) == 0 );
568
569 TEST_ASSERT( ecjpake_kkpp_read( md_info, &grp, &grp.G,
570 &Xa, &Xb, "client",
571 buf, len ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200572
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200573 if( verbose != 0 )
574 mbedtls_printf( "passed\n" );
575
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200576cleanup:
577 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200578 mbedtls_ecp_point_free( &Xa );
579 mbedtls_ecp_point_free( &Xb );
580 mbedtls_mpi_free( &xa );
581 mbedtls_mpi_free( &xb );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200582
583 if( ret != 0 )
584 {
585 if( verbose != 0 )
586 mbedtls_printf( "failed\n" );
587
588 ret = 1;
589 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200590
591 if( verbose != 0 )
592 mbedtls_printf( "\n" );
593
594 return( ret );
595}
596
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200597#undef TEST_ASSERT
598
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200599#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
600
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200601#endif /* MBEDTLS_SELF_TEST */
602
603#endif /* MBEDTLS_ECJPAKE_C */