1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <limits.h>
14 
15 /* mbedtls lib */
16 #include "mbedtls/ecdsa.h"
17 #include "mbedtls/ecp.h"
18 #include "mbedtls/timing.h"
19 #include "mbedtls/bignum.h"
20 #include "mbedtls/ctr_drbg.h"
21 #include "mbedtls_cc_ecdsa_edwards.h"
22 
23 /* local */
24 #include "run_integration_pal_log.h"
25 #include "run_integration_test.h"
26 #include "run_integration_helper.h"
27 
28 #if defined MBEDTLS_ECDSA_C
29 /************************************************************
30  *
31  * defines
32  *
33  ************************************************************/
34 #define DIGEST_SIZE         64
35 #define ECP_GROUP_ID        MBEDTLS_ECP_DP_SECP256R1
36 #define ECP_GROUP_ID_STR    "DP_SECP256R1"
37 #define MD_TYPE_ID          MBEDTLS_MD_SHA256
38 #define MD_TYPE_ID_STR      "SHA256"
39 
40 #define RUNIT_ECDSA_TEST_R521 0
41 /************************************************************
42  *
43  * static function prototypes
44  *
45  ************************************************************/
46 static RunItError_t runIt_ecdsaPrimRandomTest(void);
47 static RunItError_t runIt_ecdsaPrimVectorsTest(void);
48 static RunItError_t runIt_ecdsaDetVectorsTest(void);
49 static RunItError_t runIt_ecdsaWriteReadRandomTest(void);
50 static RunItError_t runIt_ecdsaPrimRandomEdwTest(void);
51 
52 /************************************************************
53  *
54  * variables
55  *
56  ************************************************************/
57 
58 /************************************************************
59  *
60  * static functions
61  *
62  ************************************************************/
runIt_ecdsaPrimRandomTest(void)63 static RunItError_t runIt_ecdsaPrimRandomTest(void)
64 {
65     RunItError_t rc = RUNIT_ERROR__OK;
66 
67 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
68     mbedtls_ecp_group_id id = RUNIT_ECDSA_TEST_R521 ? MBEDTLS_ECP_DP_SECP521R1 : MBEDTLS_ECP_DP_SECP256R1;
69     mbedtls_ctr_drbg_context *pCtrDrbg = (mbedtls_ctr_drbg_context *)gpRndState;
70     mbedtls_ecp_group *pGrp = NULL;
71     mbedtls_ecp_point *pQ = NULL;
72     mbedtls_mpi d, r, s;
73     unsigned char *pBuf = NULL;
74 
75     RunItPtr grpPtr;
76     RunItPtr qPtr;
77     RunItPtr bufPtr;
78 
79     const char* TEST_NAME = "ECDSA Primary Random";
80     RUNIT_SUB_TEST_START(TEST_NAME);
81 
82     ALLOC(bufPtr, pBuf, DIGEST_SIZE);
83     ALLOC_STRUCT(mbedtls_ecp_group, grpPtr, pGrp);
84     ALLOC_STRUCT(mbedtls_ecp_point, qPtr, pQ);
85 
86     mbedtls_ecp_group_init(pGrp);
87     mbedtls_ecp_point_init(pQ);
88     mbedtls_mpi_init(&d);
89     mbedtls_mpi_init(&r);
90     mbedtls_mpi_init(&s);
91     memset(pBuf, 0, DIGEST_SIZE);
92 
93     RUNIT_ASSERT(mbedtls_ctr_drbg_random(pCtrDrbg, pBuf, DIGEST_SIZE) == 0);
94     RUNIT_ASSERT(mbedtls_ecp_group_load(pGrp, id) == 0);
95     RUNIT_ASSERT(mbedtls_ecp_gen_keypair(pGrp, &d, pQ, mbedtls_ctr_drbg_random, pCtrDrbg) == 0);
96     RUNIT_ASSERT_API(mbedtls_ecdsa_sign(pGrp, &r, &s, &d, pBuf, DIGEST_SIZE, mbedtls_ctr_drbg_random, pCtrDrbg) == 0);
97     RUNIT_ASSERT_API(mbedtls_ecdsa_verify(pGrp, pBuf, DIGEST_SIZE, pQ, &r, &s) == 0);
98 
99 bail:
100     mbedtls_ecp_group_free(pGrp);
101     mbedtls_ecp_point_free(pQ);
102 
103     mbedtls_mpi_free(&d);
104     mbedtls_mpi_free(&r);
105     mbedtls_mpi_free(&s);
106 
107     FREE_IF_NOT_NULL(grpPtr);
108     FREE_IF_NOT_NULL(qPtr);
109     FREE_IF_NOT_NULL(bufPtr);
110 
111     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "ID[%s]", mbedtls_ecp_curve_info_from_grp_id(id)->name);
112 #endif /* defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) */
113     return rc;
114 }
115 
runIt_ecdsaPrimRandomEdwTest(void)116 static RunItError_t runIt_ecdsaPrimRandomEdwTest(void)
117 {
118     RunItError_t rc = RUNIT_ERROR__OK;
119 
120     size_t data_len = 200;
121 
122     mbedtls_ctr_drbg_context *pCtrDrbg = (mbedtls_ctr_drbg_context *)gpRndState;
123     mbedtls_ecdsa_context *pCtx = NULL;
124 
125     unsigned char *pDataIn = NULL;
126 
127     RunItPtr ctxPtr;
128     RunItPtr dataPtr;
129 
130     mbedtls_mpi r, s;
131     const char* TEST_NAME = "ECDSA Random Edwards";
132     RUNIT_SUB_TEST_START(TEST_NAME);
133 
134     mbedtls_mpi_init( &r );
135     mbedtls_mpi_init( &s );
136 
137 
138     ALLOC_STRUCT(mbedtls_ecdsa_context, ctxPtr, pCtx);
139     ALLOC(dataPtr, pDataIn, data_len);
140 
141     RUNIT_API(mbedtls_ecdsa_init(pCtx));
142 
143     /* prepare material for signature */
144     RUNIT_ASSERT_WITH_RESULT(mbedtls_ctr_drbg_random(pCtrDrbg, pDataIn, data_len), 0);
145 
146     /* generate signing key */
147     RUNIT_ASSERT_WITH_RESULT( mbedtls_ecdsa_genkey_edwards(pCtx, MBEDTLS_ECP_DP_CURVE25519, mbedtls_ctr_drbg_random, pCtrDrbg), 0);
148     RUNIT_ASSERT_WITH_RESULT( mbedtls_ecdsa_sign_edwards( &pCtx->grp, &r, &s, &pCtx->d, pDataIn, data_len), 0 );
149     RUNIT_ASSERT_WITH_RESULT( mbedtls_ecdsa_verify_edwards(&pCtx->grp, pDataIn, data_len, &pCtx->Q, &r, &s), 0 );
150 
151 bail:
152     RUNIT_API(mbedtls_ecdsa_free(pCtx));
153 
154     FREE_IF_NOT_NULL(ctxPtr);
155     FREE_IF_NOT_NULL(dataPtr);
156 
157     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "ID[DP_CURVE25519] MD[%s]", MD_TYPE_ID_STR);
158     return rc;
159 }
160 
runIt_ecdsaPrimVectorsTest(void)161 static RunItError_t runIt_ecdsaPrimVectorsTest(void)
162 {
163     RunItError_t rc = RUNIT_ERROR__OK;
164 
165 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
166     static const char *d_str = "DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F";
167     static const char *xQ_str = "2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970";
168     static const char *yQ_str = "6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D";
169     static const char *k_str = "9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE";
170     static const char *hash_str = "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD";
171     static const char *r_str = "CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C";
172     static const char *s_str = "86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315";
173 
174     mbedtls_ecp_group *pGrp = NULL;
175     mbedtls_ecp_point *pQ = NULL;
176     mbedtls_mpi d;
177     mbedtls_mpi r;
178     mbedtls_mpi s;
179     mbedtls_mpi rCheck;
180     mbedtls_mpi sCheck;
181     unsigned char *pHash = NULL;
182     unsigned char *pRndBuf = NULL;
183 
184     RunItPtr grpPtr;
185     RunItPtr qPtr;
186     RunItPtr hashPtr;
187     RunItPtr rndBufPtr;
188 
189     size_t hlen;
190     rnd_buf_info rnd_info;
191 
192     const char* TEST_NAME = "ECDSA Primary Vector";
193     RUNIT_SUB_TEST_START(TEST_NAME);
194 
195     ALLOC_STRUCT(mbedtls_ecp_group, grpPtr, pGrp);
196     ALLOC_STRUCT(mbedtls_ecp_point, qPtr, pQ);
197     ALLOC(hashPtr, pHash, 66);
198     ALLOC(rndBufPtr, pRndBuf, 66);
199 
200     mbedtls_ecp_group_init(pGrp);
201     mbedtls_ecp_point_init(pQ);
202     mbedtls_mpi_init(&d);
203     mbedtls_mpi_init(&r);
204     mbedtls_mpi_init(&s);
205     mbedtls_mpi_init(&rCheck);
206     mbedtls_mpi_init(&sCheck);
207     memset(pHash, 0, 66);
208     memset(pRndBuf, 0, 66);
209 
210     RUNIT_ASSERT(mbedtls_ecp_group_load(pGrp, ECP_GROUP_ID) == 0);
211     RUNIT_ASSERT(mbedtls_ecp_point_read_string(pQ, 16, xQ_str, yQ_str) == 0);
212 
213     RUNIT_ASSERT(mbedtls_mpi_read_string(&d, 16, d_str) == 0);
214     RUNIT_ASSERT(mbedtls_mpi_read_string(&rCheck, 16, r_str) == 0);
215     RUNIT_ASSERT(mbedtls_mpi_read_string(&sCheck, 16, s_str) == 0);
216 
217     hlen = runIt_unhexify(pHash, hash_str);
218 
219     rnd_info.buf = pRndBuf;
220     rnd_info.length = runIt_unhexify(pRndBuf, k_str);
221 
222     /* Fix pRndBuf by shifting it left if necessary */
223     if (pGrp->nbits % 8 != 0)
224     {
225         unsigned char shift = 8 - (pGrp->nbits % 8);
226         size_t i;
227 
228         for (i = 0; i < rnd_info.length - 1; i++)
229             pRndBuf[i] = pRndBuf[i] << shift | pRndBuf[i + 1] >> (8 - shift);
230 
231         pRndBuf[rnd_info.length - 1] <<= shift;
232     }
233 
234     RUNIT_ASSERT_API(mbedtls_ecdsa_sign(pGrp, &r, &s, &d, pHash, hlen, runIt_rndBufferRand, &rnd_info) == 0);
235     RUNIT_ASSERT(mbedtls_mpi_cmp_mpi(&r, &rCheck) == 0);
236     RUNIT_ASSERT(mbedtls_mpi_cmp_mpi(&s, &sCheck) == 0);
237     RUNIT_ASSERT_API(mbedtls_ecdsa_verify(pGrp, pHash, hlen, pQ, &rCheck, &sCheck) == 0);
238 
239 bail:
240     mbedtls_ecp_group_free(pGrp);
241     mbedtls_ecp_point_free(pQ);
242 
243     mbedtls_mpi_free(&d);
244     mbedtls_mpi_free(&r);
245     mbedtls_mpi_free(&s);
246     mbedtls_mpi_free(&rCheck);
247     mbedtls_mpi_free(&sCheck);
248 
249     FREE_IF_NOT_NULL(grpPtr);
250     FREE_IF_NOT_NULL(qPtr);
251     FREE_IF_NOT_NULL(hashPtr);
252     FREE_IF_NOT_NULL(rndBufPtr);
253 
254     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "ID[%s]", ECP_GROUP_ID_STR);
255 #endif /* defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) */
256     return rc;
257 }
258 
runIt_ecdsaDetVectorsTest(void)259 static RunItError_t runIt_ecdsaDetVectorsTest(void)
260 {
261     RunItError_t rc = RUNIT_ERROR__OK;
262 
263 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && defined(MBEDTLS_SHA256_C)
264 
265 #if RUNIT_ECDSA_TEST_R521
266     mbedtls_ecp_group_id id = MBEDTLS_ECP_DP_SECP521R1;
267     static const char *d_str = "0100085F47B8E1B8B11B7EB33028C0B2888E304BFC98501955B45BBA1478DC184EEEDF09B86A5F7C21994406072787205E69A63709FE35AA93BA333514B24F961722";
268     static const mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA512;
269     static const char *msg = "Example of ECDSA with P-521";
270     static const char *r_str = "26B55806BC7F28FF38323A46DB837CCA018FE58B766577498AAC828A76E272D61657E3C386F2FA940CDEC5961F9A81800F1385D2AF365C88B4E341824C5203D0CD";
271     static const char *s_str = "01399C2DBA893C4296C9EB06C29E2B87114EE1A8AF7EFF2312737C147AAC69BF77EB4BE520406EADAB45AE2621970B175B0213526B939FCE6B780523C20693B33601";
272 #else
273     mbedtls_ecp_group_id id = ECP_GROUP_ID;
274     static const char *d_str = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721";
275     static const mbedtls_md_type_t md_alg = MD_TYPE_ID;
276     static const char *msg = "sample";
277     static const char *r_str = "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716";
278     static const char *s_str = "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8";
279 #endif
280 
281     size_t hlen;
282     const mbedtls_md_info_t *md_info;
283 
284     unsigned char *pHash = NULL;
285     mbedtls_ecp_group *pGrp = NULL;
286     mbedtls_mpi *pD = NULL;
287     mbedtls_mpi *pR = NULL;
288     mbedtls_mpi *pS = NULL;
289     mbedtls_mpi *pRCheck = NULL;
290     mbedtls_mpi *pSCheck = NULL;
291 
292     RunItPtr hashPtr;
293     RunItPtr grpPtr;
294     RunItPtr dPtr;
295     RunItPtr rPtr;
296     RunItPtr sPtr;
297     RunItPtr rCheckPtr;
298     RunItPtr sCheckPtr;
299 
300     const char* TEST_NAME = "ECDSA Det Primary Vector";
301     RUNIT_SUB_TEST_START(TEST_NAME);
302 
303     md_info = mbedtls_md_info_from_type(md_alg);
304     RUNIT_ASSERT(md_info != NULL);
305 
306     ALLOC(hashPtr, pHash, MBEDTLS_MD_MAX_SIZE);
307     ALLOC_STRUCT(mbedtls_ecp_group, grpPtr, pGrp);
308     ALLOC_STRUCT(mbedtls_mpi, dPtr, pD);
309     ALLOC_STRUCT(mbedtls_mpi, rPtr, pR);
310     ALLOC_STRUCT(mbedtls_mpi, sPtr, pS);
311     ALLOC_STRUCT(mbedtls_mpi, rCheckPtr, pRCheck);
312     ALLOC_STRUCT(mbedtls_mpi, sCheckPtr, pSCheck);
313 
314     memset(pHash, 0, MBEDTLS_MD_MAX_SIZE);
315     mbedtls_ecp_group_init(pGrp);
316     mbedtls_mpi_init(pD);
317     mbedtls_mpi_init(pR);
318     mbedtls_mpi_init(pS);
319     mbedtls_mpi_init(pRCheck);
320     mbedtls_mpi_init(pSCheck);
321 
322     RUNIT_ASSERT(mbedtls_ecp_group_load(pGrp, id) == 0);
323 
324     RUNIT_ASSERT(mbedtls_mpi_read_string(pD, 16, d_str) == 0);
325     RUNIT_ASSERT(mbedtls_mpi_read_string(pRCheck, 16, r_str) == 0);
326     RUNIT_ASSERT(mbedtls_mpi_read_string(pSCheck, 16, s_str) == 0);
327 
328     hlen = mbedtls_md_get_size(md_info);
329 
330     RUNIT_ASSERT_API(mbedtls_md(md_info, (const unsigned char *) msg, strlen(msg), pHash) == 0);
331     RUNIT_ASSERT_API(mbedtls_ecdsa_sign_det(pGrp, pR, pS, pD, pHash, hlen, md_alg) == 0);
332 
333 #if 0
334     {
335         char buff[300] = {0};
336         uint32_t len = 0;
337         RUNIT_ASSERT_WITH_RESULT(mbedtls_mpi_write_string(pR, 16, buff, 299, &len), 0);
338         RUNIT_PRINT_DBG("pR[%s]\n", buff);
339         RUNIT_ASSERT_WITH_RESULT(mbedtls_mpi_write_string(pRCheck, 16, buff, 299, &len), 0);
340         RUNIT_PRINT_DBG("pRCheck[%s]\n", buff);
341 
342         RUNIT_ASSERT_WITH_RESULT(mbedtls_mpi_write_string(pS, 16, buff, 299, &len), 0);
343         RUNIT_PRINT_DBG("pS[%s]\n", buff);
344         RUNIT_ASSERT_WITH_RESULT(mbedtls_mpi_write_string(pSCheck, 16, buff, 299, &len), 0);
345         RUNIT_PRINT_DBG("pSCheck[%s]\n", buff);
346     }
347 #endif /* 0 */
348 
349     RUNIT_ASSERT(mbedtls_mpi_cmp_mpi(pR, pRCheck) == 0);
350     RUNIT_ASSERT(mbedtls_mpi_cmp_mpi(pS, pSCheck) == 0);
351 
352 bail:
353     mbedtls_ecp_group_free(pGrp);
354 
355     mbedtls_mpi_free(pD);
356     mbedtls_mpi_free(pR);
357     mbedtls_mpi_free(pS);
358     mbedtls_mpi_free(pRCheck);
359     mbedtls_mpi_free(pSCheck);
360 
361     FREE_IF_NOT_NULL(hashPtr);
362     FREE_IF_NOT_NULL(grpPtr);
363     FREE_IF_NOT_NULL(dPtr);
364     FREE_IF_NOT_NULL(rPtr);
365     FREE_IF_NOT_NULL(sPtr);
366     FREE_IF_NOT_NULL(rCheckPtr);
367     FREE_IF_NOT_NULL(sCheckPtr);
368 
369     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "ID[%s] MD[%s]", (mbedtls_ecp_curve_info_from_grp_id(id)->name), mbedtls_md_get_name(md_info));
370 #endif /* defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && defined(MBEDTLS_SHA256_C) */
371     return rc;
372 }
373 
runIt_ecdsaWriteReadRandomTest(void)374 static RunItError_t runIt_ecdsaWriteReadRandomTest(void)
375 {
376     RunItError_t rc = RUNIT_ERROR__OK;
377 
378 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && defined(MBEDTLS_SHA256_C)
379     unsigned char hash[32];
380     size_t sig_len;
381 
382     mbedtls_ctr_drbg_context *pCtrDrbg = (mbedtls_ctr_drbg_context *)gpRndState;
383     mbedtls_ecdsa_context *pCtx = NULL;
384     unsigned char *pSig = NULL;
385 
386     RunItPtr ctxPtr;
387     RunItPtr sigPtr;
388 
389     const char* TEST_NAME = "ECDSA Write Read Random";
390     RUNIT_SUB_TEST_START(TEST_NAME);
391 
392     ALLOC_STRUCT(mbedtls_ecdsa_context, ctxPtr, pCtx);
393     ALLOC(sigPtr, pSig, 200);
394 
395     RUNIT_API(mbedtls_ecdsa_init(pCtx));
396     memset(hash, 0, sizeof(hash));
397     memset(pSig, 0, 200);
398 
399     /* prepare material for signature */
400     RUNIT_ASSERT_API(mbedtls_ctr_drbg_random(pCtrDrbg, hash, sizeof(hash)) == 0);
401 
402     /* generate signing key */
403     RUNIT_ASSERT_API(mbedtls_ecdsa_genkey(pCtx, ECP_GROUP_ID, mbedtls_ctr_drbg_random, pCtrDrbg) == 0);
404     RUNIT_ASSERT_API(mbedtls_ecdsa_write_signature(pCtx, MD_TYPE_ID, hash, sizeof(hash), pSig, &sig_len, mbedtls_ctr_drbg_random, pCtrDrbg) == 0);
405     RUNIT_ASSERT_API(mbedtls_ecdsa_read_signature(pCtx, hash, sizeof(hash), pSig, sig_len) == 0);
406 
407 bail:
408     RUNIT_API(mbedtls_ecdsa_free(pCtx));
409 
410     FREE_IF_NOT_NULL(ctxPtr);
411     FREE_IF_NOT_NULL(sigPtr);
412 
413     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "ID[%s] MD[%s]", ECP_GROUP_ID_STR, MD_TYPE_ID_STR);
414 #endif /* defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && defined(MBEDTLS_SHA256_C) */
415     return rc;
416 }
417 
418 /************************************************************
419  *
420  * public functions
421  *
422  ************************************************************/
runIt_ecdsaTest(void)423 RunItError_t runIt_ecdsaTest(void)
424 {
425     RunItError_t rc = RUNIT_ERROR__OK;
426 
427     const char* TEST_NAME = "ECDSA";
428     RUNIT_TEST_START(TEST_NAME);
429 
430     RUNIT_ASSERT(runIt_ecdsaPrimRandomTest() == RUNIT_ERROR__OK);
431     RUNIT_ASSERT(runIt_ecdsaPrimVectorsTest() == RUNIT_ERROR__OK);
432     RUNIT_ASSERT(runIt_ecdsaDetVectorsTest() == RUNIT_ERROR__OK);
433     RUNIT_ASSERT(runIt_ecdsaWriteReadRandomTest() == RUNIT_ERROR__OK);
434     RUNIT_ASSERT(runIt_ecdsaPrimRandomEdwTest() == RUNIT_ERROR__OK);
435 
436 bail:
437     RUNIT_TEST_RESULT(TEST_NAME);
438     return rc;
439 }
440 #endif /* MBEDTLS_ECDSA_C */
441