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