Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 1
/*
2
 *  Diffie-Hellman-Merkle key exchange
3
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *  SPDX-License-Identifier: GPL-2.0
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License along
18
 *  with this program; if not, write to the Free Software Foundation, Inc.,
19
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 *
21
 *  This file is part of mbed TLS (https://tls.mbed.org)
22
 */
23
/*
24
 *  The following sources were referenced in the design of this implementation
25
 *  of the Diffie-Hellman-Merkle algorithm:
26
 *
27
 *  [1] Handbook of Applied Cryptography - 1997, Chapter 12
28
 *      Menezes, van Oorschot and Vanstone
29
 *
30
 */
31
 
32
#if !defined(MBEDTLS_CONFIG_FILE)
33
#include "mbedtls/config.h"
34
#else
35
#include MBEDTLS_CONFIG_FILE
36
#endif
37
 
38
#if defined(MBEDTLS_DHM_C)
39
 
40
#include "mbedtls/dhm.h"
41
#include "mbedtls/platform_util.h"
42
 
43
#include 
44
 
45
#if defined(MBEDTLS_PEM_PARSE_C)
46
#include "mbedtls/pem.h"
47
#endif
48
 
49
#if defined(MBEDTLS_ASN1_PARSE_C)
50
#include "mbedtls/asn1.h"
51
#endif
52
 
53
#if defined(MBEDTLS_PLATFORM_C)
54
#include "mbedtls/platform.h"
55
#else
56
#include 
57
#include 
58
#define mbedtls_printf     printf
59
#define mbedtls_calloc    calloc
60
#define mbedtls_free       free
61
#endif
62
 
63
#if !defined(MBEDTLS_DHM_ALT)
64
 
65
#define DHM_VALIDATE_RET( cond )    \
66
    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
67
#define DHM_VALIDATE( cond )        \
68
    MBEDTLS_INTERNAL_VALIDATE( cond )
69
 
70
/*
71
 * helper to validate the mbedtls_mpi size and import it
72
 */
73
static int dhm_read_bignum( mbedtls_mpi *X,
74
                            unsigned char **p,
75
                            const unsigned char *end )
76
{
77
    int ret, n;
78
 
79
    if( end - *p < 2 )
80
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
81
 
82
    n = ( (*p)[0] << 8 ) | (*p)[1];
83
    (*p) += 2;
84
 
85
    if( (int)( end - *p ) < n )
86
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
87
 
88
    if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
89
        return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
90
 
91
    (*p) += n;
92
 
93
    return( 0 );
94
}
95
 
96
/*
97
 * Verify sanity of parameter with regards to P
98
 *
99
 * Parameter should be: 2 <= public_param <= P - 2
100
 *
101
 * This means that we need to return an error if
102
 *              public_param < 2 or public_param > P-2
103
 *
104
 * For more information on the attack, see:
105
 *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
106
 *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
107
 */
108
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
109
{
110
    mbedtls_mpi L, U;
111
    int ret = 0;
112
 
113
    mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
114
 
115
    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
116
    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
117
 
118
    if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
119
        mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
120
    {
121
        ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
122
    }
123
 
124
cleanup:
125
    mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
126
    return( ret );
127
}
128
 
129
void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
130
{
131
    DHM_VALIDATE( ctx != NULL );
132
    memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
133
}
134
 
135
/*
136
 * Parse the ServerKeyExchange parameters
137
 */
138
int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
139
                     unsigned char **p,
140
                     const unsigned char *end )
141
{
142
    int ret;
143
    DHM_VALIDATE_RET( ctx != NULL );
144
    DHM_VALIDATE_RET( p != NULL && *p != NULL );
145
    DHM_VALIDATE_RET( end != NULL );
146
 
147
    if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
148
        ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
149
        ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
150
        return( ret );
151
 
152
    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
153
        return( ret );
154
 
155
    ctx->len = mbedtls_mpi_size( &ctx->P );
156
 
157
    return( 0 );
158
}
159
 
160
/*
161
 * Setup and write the ServerKeyExchange parameters
162
 */
163
int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
164
                     unsigned char *output, size_t *olen,
165
                     int (*f_rng)(void *, unsigned char *, size_t),
166
                     void *p_rng )
167
{
168
    int ret, count = 0;
169
    size_t n1, n2, n3;
170
    unsigned char *p;
171
    DHM_VALIDATE_RET( ctx != NULL );
172
    DHM_VALIDATE_RET( output != NULL );
173
    DHM_VALIDATE_RET( olen != NULL );
174
    DHM_VALIDATE_RET( f_rng != NULL );
175
 
176
    if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
177
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
178
 
179
    /*
180
     * Generate X as large as possible ( < P )
181
     */
182
    do
183
    {
184
        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
185
 
186
        while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
187
            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
188
 
189
        if( count++ > 10 )
190
            return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
191
    }
192
    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
193
 
194
    /*
195
     * Calculate GX = G^X mod P
196
     */
197
    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
198
                          &ctx->P , &ctx->RP ) );
199
 
200
    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
201
        return( ret );
202
 
203
    /*
204
     * export P, G, GX
205
     */
206
#define DHM_MPI_EXPORT( X, n )                                          \
207
    do {                                                                \
208
        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ),               \
209
                                                   p + 2,               \
210
                                                   ( n ) ) );           \
211
        *p++ = (unsigned char)( ( n ) >> 8 );                           \
212
        *p++ = (unsigned char)( ( n )      );                           \
213
        p += ( n );                                                     \
214
    } while( 0 )
215
 
216
    n1 = mbedtls_mpi_size( &ctx->P  );
217
    n2 = mbedtls_mpi_size( &ctx->G  );
218
    n3 = mbedtls_mpi_size( &ctx->GX );
219
 
220
    p = output;
221
    DHM_MPI_EXPORT( &ctx->P , n1 );
222
    DHM_MPI_EXPORT( &ctx->G , n2 );
223
    DHM_MPI_EXPORT( &ctx->GX, n3 );
224
 
225
    *olen = p - output;
226
 
227
    ctx->len = n1;
228
 
229
cleanup:
230
 
231
    if( ret != 0 )
232
        return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
233
 
234
    return( 0 );
235
}
236
 
237
/*
238
 * Set prime modulus and generator
239
 */
240
int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
241
                           const mbedtls_mpi *P,
242
                           const mbedtls_mpi *G )
243
{
244
    int ret;
245
    DHM_VALIDATE_RET( ctx != NULL );
246
    DHM_VALIDATE_RET( P != NULL );
247
    DHM_VALIDATE_RET( G != NULL );
248
 
249
    if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
250
        ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
251
    {
252
        return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
253
    }
254
 
255
    ctx->len = mbedtls_mpi_size( &ctx->P );
256
    return( 0 );
257
}
258
 
259
/*
260
 * Import the peer's public value G^Y
261
 */
262
int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
263
                     const unsigned char *input, size_t ilen )
264
{
265
    int ret;
266
    DHM_VALIDATE_RET( ctx != NULL );
267
    DHM_VALIDATE_RET( input != NULL );
268
 
269
    if( ilen < 1 || ilen > ctx->len )
270
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
271
 
272
    if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
273
        return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
274
 
275
    return( 0 );
276
}
277
 
278
/*
279
 * Create own private value X and export G^X
280
 */
281
int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
282
                     unsigned char *output, size_t olen,
283
                     int (*f_rng)(void *, unsigned char *, size_t),
284
                     void *p_rng )
285
{
286
    int ret, count = 0;
287
    DHM_VALIDATE_RET( ctx != NULL );
288
    DHM_VALIDATE_RET( output != NULL );
289
    DHM_VALIDATE_RET( f_rng != NULL );
290
 
291
    if( olen < 1 || olen > ctx->len )
292
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
293
 
294
    if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
295
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
296
 
297
    /*
298
     * generate X and calculate GX = G^X mod P
299
     */
300
    do
301
    {
302
        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
303
 
304
        while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
305
            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
306
 
307
        if( count++ > 10 )
308
            return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
309
    }
310
    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
311
 
312
    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
313
                          &ctx->P , &ctx->RP ) );
314
 
315
    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
316
        return( ret );
317
 
318
    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
319
 
320
cleanup:
321
 
322
    if( ret != 0 )
323
        return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
324
 
325
    return( 0 );
326
}
327
 
328
/*
329
 * Use the blinding method and optimisation suggested in section 10 of:
330
 *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
331
 *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
332
 *  Berlin Heidelberg, 1996. p. 104-113.
333
 */
334
static int dhm_update_blinding( mbedtls_dhm_context *ctx,
335
                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
336
{
337
    int ret, count;
338
 
339
    /*
340
     * Don't use any blinding the first time a particular X is used,
341
     * but remember it to use blinding next time.
342
     */
343
    if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
344
    {
345
        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
346
        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
347
        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
348
 
349
        return( 0 );
350
    }
351
 
352
    /*
353
     * Ok, we need blinding. Can we re-use existing values?
354
     * If yes, just update them by squaring them.
355
     */
356
    if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
357
    {
358
        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
359
        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
360
 
361
        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
362
        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
363
 
364
        return( 0 );
365
    }
366
 
367
    /*
368
     * We need to generate blinding values from scratch
369
     */
370
 
371
    /* Vi = random( 2, P-1 ) */
372
    count = 0;
373
    do
374
    {
375
        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) );
376
 
377
        while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
378
            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
379
 
380
        if( count++ > 10 )
381
            return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
382
    }
383
    while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
384
 
385
    /* Vf = Vi^-X mod P */
386
    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
387
    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
388
 
389
cleanup:
390
    return( ret );
391
}
392
 
393
/*
394
 * Derive and export the shared secret (G^Y)^X mod P
395
 */
396
int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
397
                     unsigned char *output, size_t output_size, size_t *olen,
398
                     int (*f_rng)(void *, unsigned char *, size_t),
399
                     void *p_rng )
400
{
401
    int ret;
402
    mbedtls_mpi GYb;
403
    DHM_VALIDATE_RET( ctx != NULL );
404
    DHM_VALIDATE_RET( output != NULL );
405
    DHM_VALIDATE_RET( olen != NULL );
406
 
407
    if( output_size < ctx->len )
408
        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
409
 
410
    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
411
        return( ret );
412
 
413
    mbedtls_mpi_init( &GYb );
414
 
415
    /* Blind peer's value */
416
    if( f_rng != NULL )
417
    {
418
        MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
419
        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
420
        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
421
    }
422
    else
423
        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
424
 
425
    /* Do modular exponentiation */
426
    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
427
                          &ctx->P, &ctx->RP ) );
428
 
429
    /* Unblind secret value */
430
    if( f_rng != NULL )
431
    {
432
        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
433
        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
434
    }
435
 
436
    *olen = mbedtls_mpi_size( &ctx->K );
437
 
438
    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
439
 
440
cleanup:
441
    mbedtls_mpi_free( &GYb );
442
 
443
    if( ret != 0 )
444
        return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
445
 
446
    return( 0 );
447
}
448
 
449
/*
450
 * Free the components of a DHM key
451
 */
452
void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
453
{
454
    if( ctx == NULL )
455
        return;
456
 
457
    mbedtls_mpi_free( &ctx->pX );
458
    mbedtls_mpi_free( &ctx->Vf );
459
    mbedtls_mpi_free( &ctx->Vi );
460
    mbedtls_mpi_free( &ctx->RP );
461
    mbedtls_mpi_free( &ctx->K  );
462
    mbedtls_mpi_free( &ctx->GY );
463
    mbedtls_mpi_free( &ctx->GX );
464
    mbedtls_mpi_free( &ctx->X  );
465
    mbedtls_mpi_free( &ctx->G  );
466
    mbedtls_mpi_free( &ctx->P  );
467
 
468
    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
469
}
470
 
471
#if defined(MBEDTLS_ASN1_PARSE_C)
472
/*
473
 * Parse DHM parameters
474
 */
475
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
476
                   size_t dhminlen )
477
{
478
    int ret;
479
    size_t len;
480
    unsigned char *p, *end;
481
#if defined(MBEDTLS_PEM_PARSE_C)
482
    mbedtls_pem_context pem;
483
#endif /* MBEDTLS_PEM_PARSE_C */
484
 
485
    DHM_VALIDATE_RET( dhm != NULL );
486
    DHM_VALIDATE_RET( dhmin != NULL );
487
 
488
#if defined(MBEDTLS_PEM_PARSE_C)
489
    mbedtls_pem_init( &pem );
490
 
491
    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
492
    if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
493
        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
494
    else
495
        ret = mbedtls_pem_read_buffer( &pem,
496
                               "-----BEGIN DH PARAMETERS-----",
497
                               "-----END DH PARAMETERS-----",
498
                               dhmin, NULL, 0, &dhminlen );
499
 
500
    if( ret == 0 )
501
    {
502
        /*
503
         * Was PEM encoded
504
         */
505
        dhminlen = pem.buflen;
506
    }
507
    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
508
        goto exit;
509
 
510
    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
511
#else
512
    p = (unsigned char *) dhmin;
513
#endif /* MBEDTLS_PEM_PARSE_C */
514
    end = p + dhminlen;
515
 
516
    /*
517
     *  DHParams ::= SEQUENCE {
518
     *      prime              INTEGER,  -- P
519
     *      generator          INTEGER,  -- g
520
     *      privateValueLength INTEGER OPTIONAL
521
     *  }
522
     */
523
    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
524
            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
525
    {
526
        ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
527
        goto exit;
528
    }
529
 
530
    end = p + len;
531
 
532
    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
533
        ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
534
    {
535
        ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
536
        goto exit;
537
    }
538
 
539
    if( p != end )
540
    {
541
        /* This might be the optional privateValueLength.
542
         * If so, we can cleanly discard it */
543
        mbedtls_mpi rec;
544
        mbedtls_mpi_init( &rec );
545
        ret = mbedtls_asn1_get_mpi( &p, end, &rec );
546
        mbedtls_mpi_free( &rec );
547
        if ( ret != 0 )
548
        {
549
            ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
550
            goto exit;
551
        }
552
        if ( p != end )
553
        {
554
            ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
555
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
556
            goto exit;
557
        }
558
    }
559
 
560
    ret = 0;
561
 
562
    dhm->len = mbedtls_mpi_size( &dhm->P );
563
 
564
exit:
565
#if defined(MBEDTLS_PEM_PARSE_C)
566
    mbedtls_pem_free( &pem );
567
#endif
568
    if( ret != 0 )
569
        mbedtls_dhm_free( dhm );
570
 
571
    return( ret );
572
}
573
 
574
#if defined(MBEDTLS_FS_IO)
575
/*
576
 * Load all data from a file into a given buffer.
577
 *
578
 * The file is expected to contain either PEM or DER encoded data.
579
 * A terminating null byte is always appended. It is included in the announced
580
 * length only if the data looks like it is PEM encoded.
581
 */
582
static int load_file( const char *path, unsigned char **buf, size_t *n )
583
{
584
    FILE *f;
585
    long size;
586
 
587
    if( ( f = fopen( path, "rb" ) ) == NULL )
588
        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
589
 
590
    fseek( f, 0, SEEK_END );
591
    if( ( size = ftell( f ) ) == -1 )
592
    {
593
        fclose( f );
594
        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
595
    }
596
    fseek( f, 0, SEEK_SET );
597
 
598
    *n = (size_t) size;
599
 
600
    if( *n + 1 == 0 ||
601
        ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
602
    {
603
        fclose( f );
604
        return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
605
    }
606
 
607
    if( fread( *buf, 1, *n, f ) != *n )
608
    {
609
        fclose( f );
610
 
611
        mbedtls_platform_zeroize( *buf, *n + 1 );
612
        mbedtls_free( *buf );
613
 
614
        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
615
    }
616
 
617
    fclose( f );
618
 
619
    (*buf)[*n] = '\0';
620
 
621
    if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
622
        ++*n;
623
 
624
    return( 0 );
625
}
626
 
627
/*
628
 * Load and parse DHM parameters
629
 */
630
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
631
{
632
    int ret;
633
    size_t n;
634
    unsigned char *buf;
635
    DHM_VALIDATE_RET( dhm != NULL );
636
    DHM_VALIDATE_RET( path != NULL );
637
 
638
    if( ( ret = load_file( path, &buf, &n ) ) != 0 )
639
        return( ret );
640
 
641
    ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
642
 
643
    mbedtls_platform_zeroize( buf, n );
644
    mbedtls_free( buf );
645
 
646
    return( ret );
647
}
648
#endif /* MBEDTLS_FS_IO */
649
#endif /* MBEDTLS_ASN1_PARSE_C */
650
#endif /* MBEDTLS_DHM_ALT */
651
 
652
#if defined(MBEDTLS_SELF_TEST)
653
 
654
#if defined(MBEDTLS_PEM_PARSE_C)
655
static const char mbedtls_test_dhm_params[] =
656
"-----BEGIN DH PARAMETERS-----\r\n"
657
"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
658
"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
659
"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
660
"-----END DH PARAMETERS-----\r\n";
661
#else /* MBEDTLS_PEM_PARSE_C */
662
static const char mbedtls_test_dhm_params[] = {
663
  0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
664
  0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
665
  0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
666
  0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
667
  0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
668
  0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
669
  0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
670
  0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
671
  0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
672
  0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
673
  0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
674
  0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
675
#endif /* MBEDTLS_PEM_PARSE_C */
676
 
677
static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
678
 
679
/*
680
 * Checkup routine
681
 */
682
int mbedtls_dhm_self_test( int verbose )
683
{
684
    int ret;
685
    mbedtls_dhm_context dhm;
686
 
687
    mbedtls_dhm_init( &dhm );
688
 
689
    if( verbose != 0 )
690
        mbedtls_printf( "  DHM parameter load: " );
691
 
692
    if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
693
                    (const unsigned char *) mbedtls_test_dhm_params,
694
                    mbedtls_test_dhm_params_len ) ) != 0 )
695
    {
696
        if( verbose != 0 )
697
            mbedtls_printf( "failed\n" );
698
 
699
        ret = 1;
700
        goto exit;
701
    }
702
 
703
    if( verbose != 0 )
704
        mbedtls_printf( "passed\n\n" );
705
 
706
exit:
707
    mbedtls_dhm_free( &dhm );
708
 
709
    return( ret );
710
}
711
 
712
#endif /* MBEDTLS_SELF_TEST */
713
 
714
#endif /* MBEDTLS_DHM_C */