1/* BEGIN_HEADER */
2#include "mbedtls/dhm.h"
3
4int check_get_value( const mbedtls_dhm_context *ctx,
5                     mbedtls_dhm_parameter param,
6                     const mbedtls_mpi *expected )
7{
8    mbedtls_mpi actual;
9    int ok = 0;
10    mbedtls_mpi_init( &actual );
11
12    TEST_ASSERT( mbedtls_dhm_get_value( ctx, param, &actual ) == 0 );
13    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual, expected ) == 0 );
14    ok = 1;
15
16exit:
17    mbedtls_mpi_free( &actual );
18    return( ok );
19}
20
21/* Sanity checks on a Diffie-Hellman parameter: check the length-value
22 * syntax and check that the value is the expected one (taken from the
23 * DHM context by the caller). */
24static int check_dhm_param_output( const mbedtls_mpi *expected,
25                                   const unsigned char *buffer,
26                                   size_t size,
27                                   size_t *offset )
28{
29    size_t n;
30    mbedtls_mpi actual;
31    int ok = 0;
32    mbedtls_mpi_init( &actual );
33
34    ++mbedtls_test_info.step;
35
36    TEST_ASSERT( size >= *offset + 2 );
37    n = ( buffer[*offset] << 8 ) | buffer[*offset + 1];
38    *offset += 2;
39    /* The DHM param output from Mbed TLS has leading zeros stripped, as
40     * permitted but not required by RFC 5246 \S4.4. */
41    TEST_EQUAL( n, mbedtls_mpi_size( expected ) );
42    TEST_ASSERT( size >= *offset + n );
43    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &actual, buffer + *offset, n ) );
44    TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( expected, &actual ) );
45    *offset += n;
46
47    ok = 1;
48exit:
49    mbedtls_mpi_free( &actual );
50    return( ok );
51}
52
53/* Sanity checks on Diffie-Hellman parameters: syntax, range, and comparison
54 * against the context. */
55static int check_dhm_params( const mbedtls_dhm_context *ctx,
56                             size_t x_size,
57                             const unsigned char *ske, size_t ske_len )
58{
59    size_t offset = 0;
60
61    /* Check that ctx->X and ctx->GX are within range. */
62    TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->X, 1 ) > 0 );
63    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) < 0 );
64    TEST_ASSERT( mbedtls_mpi_size( &ctx->X ) <= x_size );
65    TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->GX, 1 ) > 0 );
66    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->GX, &ctx->P ) < 0 );
67
68    /* Check ske: it must contain P, G and G^X, each prefixed with a
69     * 2-byte size. */
70    if( !check_dhm_param_output( &ctx->P, ske, ske_len, &offset ) )
71        goto exit;
72    if( !check_dhm_param_output( &ctx->G, ske, ske_len, &offset ) )
73        goto exit;
74    if( !check_dhm_param_output( &ctx->GX, ske, ske_len, &offset ) )
75        goto exit;
76    TEST_EQUAL( offset, ske_len );
77
78    return( 1 );
79exit:
80    return( 0 );
81}
82
83/* END_HEADER */
84
85/* BEGIN_DEPENDENCIES
86 * depends_on:MBEDTLS_DHM_C:MBEDTLS_BIGNUM_C
87 * END_DEPENDENCIES
88 */
89
90/* BEGIN_CASE */
91void dhm_do_dhm( int radix_P, char *input_P, int x_size,
92                 int radix_G, char *input_G, int result )
93{
94    mbedtls_dhm_context ctx_srv;
95    mbedtls_dhm_context ctx_cli;
96    unsigned char ske[1000];
97    unsigned char *p = ske;
98    unsigned char pub_cli[1000];
99    unsigned char sec_srv[1000];
100    unsigned char sec_cli[1000];
101    size_t ske_len = 0;
102    size_t pub_cli_len = 0;
103    size_t sec_srv_len;
104    size_t sec_cli_len;
105    int i;
106    mbedtls_test_rnd_pseudo_info rnd_info;
107
108    mbedtls_dhm_init( &ctx_srv );
109    mbedtls_dhm_init( &ctx_cli );
110    memset( ske, 0x00, 1000 );
111    memset( pub_cli, 0x00, 1000 );
112    memset( sec_srv, 0x00, 1000 );
113    memset( sec_cli, 0x00, 1000 );
114    memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) );
115
116    /*
117     * Set params
118     */
119    TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.P, radix_P, input_P ) == 0 );
120    TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.G, radix_G, input_G ) == 0 );
121    pub_cli_len = mbedtls_mpi_size( &ctx_srv.P );
122    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_P, &ctx_srv.P ) );
123    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_G, &ctx_srv.G ) );
124
125    /*
126     * First key exchange
127     */
128    mbedtls_test_set_step( 10 );
129    TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
130                                          &mbedtls_test_rnd_pseudo_rand,
131                                          &rnd_info ) == result );
132    if ( result != 0 )
133        goto exit;
134    if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
135        goto exit;
136
137    ske[ske_len++] = 0;
138    ske[ske_len++] = 0;
139    TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
140    /* The domain parameters must be the same on both side. */
141    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_P, &ctx_srv.P ) );
142    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_G, &ctx_srv.G ) );
143
144    TEST_ASSERT( mbedtls_dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len,
145                                          &mbedtls_test_rnd_pseudo_rand,
146                                          &rnd_info ) == 0 );
147    TEST_ASSERT( mbedtls_dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
148
149    TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv, sizeof( sec_srv ),
150                                          &sec_srv_len,
151                                          &mbedtls_test_rnd_pseudo_rand,
152                                          &rnd_info ) == 0 );
153    TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_cli, sec_cli, sizeof( sec_cli ),
154                                          &sec_cli_len,
155                                          &mbedtls_test_rnd_pseudo_rand,
156                                          &rnd_info ) == 0 );
157
158    TEST_ASSERT( sec_srv_len == sec_cli_len );
159    TEST_ASSERT( sec_srv_len != 0 );
160    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
161
162    /* Internal value checks */
163    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_X, &ctx_cli.X ) );
164    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_X, &ctx_srv.X ) );
165    /* Cross-checks */
166    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_GX, &ctx_srv.GY ) );
167    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_GY, &ctx_srv.GX ) );
168    TEST_ASSERT( check_get_value( &ctx_cli, MBEDTLS_DHM_PARAM_K, &ctx_srv.K ) );
169    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_GX, &ctx_cli.GY ) );
170    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_GY, &ctx_cli.GX ) );
171    TEST_ASSERT( check_get_value( &ctx_srv, MBEDTLS_DHM_PARAM_K, &ctx_cli.K ) );
172
173    /* Re-do calc_secret on server a few times to test update of blinding values */
174    for( i = 0; i < 3; i++ )
175    {
176        mbedtls_test_set_step( 20 + i );
177        sec_srv_len = 1000;
178        TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv,
179                                              sizeof( sec_srv ), &sec_srv_len,
180                                              &mbedtls_test_rnd_pseudo_rand,
181                                              &rnd_info ) == 0 );
182
183        TEST_ASSERT( sec_srv_len == sec_cli_len );
184        TEST_ASSERT( sec_srv_len != 0 );
185        TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
186    }
187
188    /*
189     * Second key exchange to test change of blinding values on server
190     */
191    p = ske;
192
193    mbedtls_test_set_step( 30 );
194    TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
195                                          &mbedtls_test_rnd_pseudo_rand,
196                                          &rnd_info ) == 0 );
197    if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
198        goto exit;
199    ske[ske_len++] = 0;
200    ske[ske_len++] = 0;
201    TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
202
203    TEST_ASSERT( mbedtls_dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len,
204                                          &mbedtls_test_rnd_pseudo_rand,
205                                          &rnd_info ) == 0 );
206    TEST_ASSERT( mbedtls_dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
207
208    TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv, sizeof( sec_srv ),
209                                          &sec_srv_len,
210                                          &mbedtls_test_rnd_pseudo_rand,
211                                          &rnd_info ) == 0 );
212    TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_cli, sec_cli, sizeof( sec_cli ),
213                                          &sec_cli_len,
214                                          &mbedtls_test_rnd_pseudo_rand,
215                                          &rnd_info ) == 0 );
216
217    TEST_ASSERT( sec_srv_len == sec_cli_len );
218    TEST_ASSERT( sec_srv_len != 0 );
219    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
220
221exit:
222    mbedtls_dhm_free( &ctx_srv );
223    mbedtls_dhm_free( &ctx_cli );
224}
225/* END_CASE */
226
227/* BEGIN_CASE */
228void dhm_make_public( int P_bytes, int radix_G, char *input_G, int result )
229{
230    mbedtls_mpi P, G;
231    mbedtls_dhm_context ctx;
232    unsigned char output[MBEDTLS_MPI_MAX_SIZE];
233
234    mbedtls_mpi_init( &P );
235    mbedtls_mpi_init( &G );
236    mbedtls_dhm_init( &ctx );
237
238    TEST_ASSERT( mbedtls_mpi_lset( &P, 1 ) == 0 );
239    TEST_ASSERT( mbedtls_mpi_shift_l( &P, ( P_bytes * 8 ) - 1 ) == 0 );
240    TEST_ASSERT( mbedtls_mpi_set_bit( &P, 0, 1 ) == 0 );
241
242    TEST_ASSERT( mbedtls_test_read_mpi( &G, radix_G, input_G ) == 0 );
243
244    TEST_ASSERT( mbedtls_dhm_set_group( &ctx, &P, &G ) == 0 );
245    TEST_ASSERT( mbedtls_dhm_make_public( &ctx, (int) mbedtls_mpi_size( &P ),
246                                          output, sizeof(output),
247                                          &mbedtls_test_rnd_pseudo_rand,
248                                          NULL ) == result );
249
250exit:
251    mbedtls_mpi_free( &P );
252    mbedtls_mpi_free( &G );
253    mbedtls_dhm_free( &ctx );
254}
255/* END_CASE */
256
257/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
258void dhm_file( char * filename, char * p, char * g, int len )
259{
260    mbedtls_dhm_context ctx;
261    mbedtls_mpi P, G;
262
263    mbedtls_dhm_init( &ctx );
264    mbedtls_mpi_init( &P ); mbedtls_mpi_init( &G );
265
266    TEST_ASSERT( mbedtls_test_read_mpi( &P, 16, p ) == 0 );
267    TEST_ASSERT( mbedtls_test_read_mpi( &G, 16, g ) == 0 );
268
269    TEST_ASSERT( mbedtls_dhm_parse_dhmfile( &ctx, filename ) == 0 );
270
271    TEST_EQUAL( mbedtls_dhm_get_len( &ctx ), (size_t) len );
272    TEST_EQUAL( mbedtls_dhm_get_bitlen( &ctx ), mbedtls_mpi_bitlen( &P ) );
273    TEST_ASSERT( check_get_value( &ctx, MBEDTLS_DHM_PARAM_P, &P ) );
274    TEST_ASSERT( check_get_value( &ctx, MBEDTLS_DHM_PARAM_G, &G ) );
275
276exit:
277    mbedtls_mpi_free( &P ); mbedtls_mpi_free( &G );
278    mbedtls_dhm_free( &ctx );
279}
280/* END_CASE */
281
282/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
283void dhm_selftest(  )
284{
285    TEST_ASSERT( mbedtls_dhm_self_test( 1 ) == 0 );
286}
287/* END_CASE */
288