blob: 47779fc090889b4da9d5a115354ac7193fcc57a1 [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 );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020057 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020058}
59
60/*
61 * Free context
62 */
63void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
64{
65 if( ctx == NULL )
66 return;
67
68 ctx->md_info = NULL;
69 mbedtls_ecp_group_free( &ctx->grp );
70
71 mbedtls_ecp_point_free( &ctx->X1 );
72 mbedtls_ecp_point_free( &ctx->X2 );
73 mbedtls_ecp_point_free( &ctx->X3 );
74 mbedtls_ecp_point_free( &ctx->X4 );
75
76 mbedtls_mpi_free( &ctx->xa );
77 mbedtls_mpi_free( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020078 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020079}
80
81/*
82 * Setup context
83 */
84int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
85 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020086 mbedtls_ecp_group_id curve,
87 const unsigned char *secret,
88 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020089{
90 int ret;
91
92 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
93 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
94
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020095 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020096
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020097 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
98 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->s, &ctx->s, &ctx->grp.N ) );
99
100cleanup:
101 if( ret != 0 )
102 mbedtls_ecjpake_free( ctx );
103
104 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200105}
106
107/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200108 * Write a point plus its length to a buffer
109 */
110static int ecjpake_write_len_point( unsigned char **p,
111 const unsigned char *end,
112 const mbedtls_ecp_group *grp,
113 const mbedtls_ecp_point *P )
114{
115 int ret;
116 size_t len;
117
118 /* Need at least 4 for length plus 1 for point */
119 if( end < *p || end - *p < 5 )
120 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
121
122 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
123 &len, *p + 4, end - ( *p + 4 ) );
124 if( ret != 0 )
125 return( ret );
126
127 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
128 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
129 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
130 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
131
132 *p += 4 + len;
133
134 return( 0 );
135}
136
137/*
138 * Size of the temporary buffer for ecjpake_hash:
139 * 3 EC points plus their length, plus ID (6 bytes)
140 */
141#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
142
143/*
144 * Compute hash for ZKP (7.4.2.2.2.1)
145 */
146static int ecjpake_hash( const mbedtls_md_info_t *md_info,
147 const mbedtls_ecp_group *grp,
148 const mbedtls_ecp_point *G,
149 const mbedtls_ecp_point *V,
150 const mbedtls_ecp_point *X,
151 const char *id,
152 mbedtls_mpi *h )
153{
154 int ret;
155 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
156 unsigned char *p = buf;
157 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200158 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200159 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
160
161 /* Write things to temporary buffer */
162 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
163 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
164 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
165
166 if( end < p || (size_t)( end - p ) < id_len )
167 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
168
169 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
170 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
171 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
172 *p++ = (unsigned char)( ( id_len ) & 0xFF );
173
174 memcpy( p, id, id_len );
175 p += id_len;
176
177 /* Compute hash */
178 mbedtls_md( md_info, buf, p - buf, hash );
179
180 /* Turn it into an integer mod n */
181 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
182 mbedtls_md_get_size( md_info ) ) );
183 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
184
185cleanup:
186 return( ret );
187}
188
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200189/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200190 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
191 */
192static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
193 const mbedtls_ecp_group *grp,
194 const mbedtls_ecp_point *G,
195 const mbedtls_ecp_point *X,
196 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200197 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200198 const unsigned char *end )
199{
200 int ret;
201 mbedtls_ecp_point V, VV;
202 mbedtls_mpi r, h;
203 size_t r_len;
204
205 mbedtls_ecp_point_init( &V );
206 mbedtls_ecp_point_init( &VV );
207 mbedtls_mpi_init( &r );
208 mbedtls_mpi_init( &h );
209
210 /*
211 * struct {
212 * ECPoint V;
213 * opaque r<1..2^8-1>;
214 * } ECSchnorrZKP;
215 */
216 if( end < *p )
217 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
218
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200219 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200220
221 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200222 {
223 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
224 goto cleanup;
225 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200226
227 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200228
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200229 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200230 {
231 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
232 goto cleanup;
233 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200234
235 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
236 *p += r_len;
237
238 /*
239 * Verification
240 */
241 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
242 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
243 &VV, &h, X, &r, G ) );
244
245 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200246 {
247 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
248 goto cleanup;
249 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250
251cleanup:
252 mbedtls_ecp_point_free( &V );
253 mbedtls_ecp_point_free( &VV );
254 mbedtls_mpi_free( &r );
255 mbedtls_mpi_free( &h );
256
257 return( ret );
258}
259
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200260/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200261 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
262 */
263static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
264 const mbedtls_ecp_group *grp,
265 const mbedtls_ecp_point *G,
266 const mbedtls_mpi *x,
267 const mbedtls_ecp_point *X,
268 const char *id,
269 unsigned char **p,
270 const unsigned char *end,
271 int (*f_rng)(void *, unsigned char *, size_t),
272 void *p_rng )
273{
274 int ret;
275 mbedtls_ecp_point V;
276 mbedtls_mpi v;
277 mbedtls_mpi h; /* later recycled to hold r */
278 size_t len;
279
280 if( end < *p )
281 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
282
283 mbedtls_ecp_point_init( &V );
284 mbedtls_mpi_init( &v );
285 mbedtls_mpi_init( &h );
286
287 /* Compute signature */
288 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
289 G, &v, &V, f_rng, p_rng ) );
290 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
291 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
292 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
293 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
294
295 /* Write it out */
296 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
297 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
298 *p += len;
299
300 len = mbedtls_mpi_size( &h ); /* actually r */
301 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
302 {
303 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
304 goto cleanup;
305 }
306
307 *(*p)++ = (unsigned char)( len & 0xFF );
308 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
309 *p += len;
310
311cleanup:
312 mbedtls_ecp_point_free( &V );
313 mbedtls_mpi_free( &v );
314 mbedtls_mpi_free( &h );
315
316 return( ret );
317}
318
319/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200320 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
321 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200322 */
323static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
324 const mbedtls_ecp_group *grp,
325 const mbedtls_ecp_point *G,
326 mbedtls_ecp_point *X,
327 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200328 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200329 const unsigned char *end )
330{
331 int ret;
332
333 if( end < *p )
334 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
335
336 /*
337 * struct {
338 * ECPoint X;
339 * ECSchnorrZKP zkp;
340 * } ECJPAKEKeyKP;
341 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200342 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200343 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
344
345cleanup:
346 return( ret );
347}
348
349/*
350 * Generate an ECJPAKEKeyKP
351 * Output: the serialized structure, plus private/public key pair
352 */
353static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
354 const mbedtls_ecp_group *grp,
355 const mbedtls_ecp_point *G,
356 mbedtls_mpi *x,
357 mbedtls_ecp_point *X,
358 const char *id,
359 unsigned char **p,
360 const unsigned char *end,
361 int (*f_rng)(void *, unsigned char *, size_t),
362 void *p_rng )
363{
364 int ret;
365 size_t len;
366
367 if( end < *p )
368 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
369
370 /* Generate key (7.4.2.3.1) and write it out */
371 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
372 f_rng, p_rng ) );
373 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
374 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
375 *p += len;
376
377 /* Generate and write proof */
378 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
379 p, end, f_rng, p_rng ) );
380
381cleanup:
382 return( ret );
383}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200384
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200385/*
386 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
387 * Ouputs: verified peer public keys Xa, Xb
388 */
389static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
390 const mbedtls_ecp_group *grp,
391 const mbedtls_ecp_point *G,
392 mbedtls_ecp_point *Xa,
393 mbedtls_ecp_point *Xb,
394 const char *id,
395 const unsigned char *buf,
396 size_t len )
397{
398 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200399 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200400 const unsigned char *end = buf + len;
401
402 /*
403 * struct {
404 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
405 * } ECJPAKEKeyKPPairList;
406 */
407 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
408 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
409
410 if( p != end )
411 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
412
413cleanup:
414 return( ret );
415}
416
417/*
418 * Generate a ECJPAKEKeyKPPairList
419 * Outputs: the serialized structure, plus two private/public key pairs
420 */
421static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
422 const mbedtls_ecp_group *grp,
423 const mbedtls_ecp_point *G,
424 mbedtls_mpi *xa,
425 mbedtls_ecp_point *Xa,
426 mbedtls_mpi *xb,
427 mbedtls_ecp_point *Xb,
428 const char *id,
429 unsigned char *buf,
430 size_t len,
431 size_t *olen,
432 int (*f_rng)(void *, unsigned char *, size_t),
433 void *p_rng )
434{
435 int ret;
436 unsigned char *p = buf;
437 const unsigned char *end = buf + len;
438
439 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
440 &p, end, f_rng, p_rng ) );
441 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
442 &p, end, f_rng, p_rng ) );
443
444 *olen = p - buf;
445
446cleanup:
447 return( ret );
448}
449
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200450/*
451 * Read the contents of the ClientHello extension
452 */
453int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
454 const unsigned char *buf,
455 size_t len )
456{
457 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
458 &ctx->X1, &ctx->X2, "client",
459 buf, len ) );
460}
461
462/*
463 * Read the contents of the ServerHello extension
464 */
465int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
466 const unsigned char *buf,
467 size_t len )
468{
469 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
470 &ctx->X3, &ctx->X4, "server",
471 buf, len ) );
472}
473
474/*
475 * Generate the contents of the ClientHello extension
476 */
477int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
478 unsigned char *buf, size_t len, size_t *olen,
479 int (*f_rng)(void *, unsigned char *, size_t),
480 void *p_rng )
481{
482 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
483 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
484 "client", buf, len, olen, f_rng, p_rng ) );
485}
486
487/*
488 * Generate the contents of the ServerHello extension
489 */
490int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
491 unsigned char *buf, size_t len, size_t *olen,
492 int (*f_rng)(void *, unsigned char *, size_t),
493 void *p_rng )
494{
495 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
496 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
497 "server", buf, len, olen, f_rng, p_rng ) );
498}
499
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200500#if defined(MBEDTLS_SELF_TEST)
501
502#if defined(MBEDTLS_PLATFORM_C)
503#include "mbedtls/platform.h"
504#else
505#include <stdio.h>
506#define mbedtls_printf printf
507#endif
508
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200509#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
510 !defined(MBEDTLS_SHA256_C)
511int mbedtls_ecjpake_self_test( int verbose )
512{
513 (void) verbose;
514 return( 0 );
515}
516#else
517
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200518static const unsigned char ecjpake_test_kkpp[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200519 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
520 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
521 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
522 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
523 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
524 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
525 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
526 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
527 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
528 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
529 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
530 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
531 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200532 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
533 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
534 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
535 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
536 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
537 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
538 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
539 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
540 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
541 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
542 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
543 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
544 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
545 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
546 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200547};
548
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200549/* For tests we don't need a secure RNG;
550 * use the LGC from Numerical Recipes for simplicity */
551static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
552{
553 static uint32_t x = 42;
554 (void) p;
555
556 while( len > 0 )
557 {
558 size_t use_len = len > 4 ? 4 : len;
559 x = 1664525 * x + 1013904223;
560 memcpy( out, &x, use_len );
561 out += use_len;
562 len -= use_len;
563 }
564
565 return( 0 );
566}
567
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200568#define TEST_ASSERT( x ) \
569 do { \
570 if( x ) \
571 ret = 0; \
572 else \
573 { \
574 ret = 1; \
575 goto cleanup; \
576 } \
577 } while( 0 )
578
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200579/*
580 * Checkup routine
581 */
582int mbedtls_ecjpake_self_test( int verbose )
583{
584 int ret;
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200585 mbedtls_ecjpake_context ctx;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200586 unsigned char buf[1000];
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200587 size_t len;
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200588 char secret[] = "test passphrase";
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200589
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200590 mbedtls_ecjpake_init( &ctx );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200591
592 /* Common to all tests */
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200593 TEST_ASSERT( mbedtls_ecjpake_setup( &ctx,
594 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
595 (const unsigned char *) secret,
596 sizeof( secret ) - 1 ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200597
598 if( verbose != 0 )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200599 mbedtls_printf( " ECJPAKE test #1 (client ext read): " );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200600
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200601 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200602 ecjpake_test_kkpp,
603 sizeof( ecjpake_test_kkpp ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200604
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200605 /* Corrupt message */
606 memcpy( buf, ecjpake_test_kkpp, sizeof( ecjpake_test_kkpp ) );
607 buf[sizeof( ecjpake_test_kkpp ) - 1]--;
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200608 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200609 buf, sizeof( ecjpake_test_kkpp ) )
610 == MBEDTLS_ERR_ECP_VERIFY_FAILED );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200611
612 if( verbose != 0 )
613 mbedtls_printf( "passed\n" );
614
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200615 if( verbose != 0 )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200616 mbedtls_printf( " ECJPAKE test #2 (client ext write/read): " );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200617
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200618 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &ctx,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200619 buf, sizeof( buf ), &len,
620 ecjpake_lgc, NULL ) == 0 );
621
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200622 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx, buf, len ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200623
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200624 if( verbose != 0 )
625 mbedtls_printf( "passed\n" );
626
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200627cleanup:
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200628 mbedtls_ecjpake_free( &ctx );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200629
630 if( ret != 0 )
631 {
632 if( verbose != 0 )
633 mbedtls_printf( "failed\n" );
634
635 ret = 1;
636 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200637
638 if( verbose != 0 )
639 mbedtls_printf( "\n" );
640
641 return( ret );
642}
643
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200644#undef TEST_ASSERT
645
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200646#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
647
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200648#endif /* MBEDTLS_SELF_TEST */
649
650#endif /* MBEDTLS_ECJPAKE_C */