blob: a635ebeef194c98c73c7a35ad8b0e9b86bd60fc8 [file] [log] [blame]
David Brownfecda2d2017-09-07 10:20:34 -06001/* test_ecc_utils.c - TinyCrypt common functions for ECC tests */
2
3/*
4 * Copyright (C) 2015 by Intel Corporation, All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * - Neither the name of Intel Corporation nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * test_ecc_utils.c -- Implementation of some common functions for ECC tests.
33 *
34 */
35#include <tinycrypt/ecc.h>
36#include <tinycrypt/ecc_dh.h>
37#include <test_ecc_utils.h>
38#include <tinycrypt/constants.h>
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45extern int randfd;
46
47void getRandomBytes(void *p_dest, unsigned p_size) {
48 if(read(randfd, p_dest, p_size) != (int)p_size) {
49 printf("Failed to get random bytes.\n");
50 }
51}
52
53int hex2int (char hex) {
54 uint8_t dec;
55
56 if ('0' <= hex && hex <= '9') dec = hex - '0';
57 else if ('a' <= hex && hex <= 'f') dec = hex - 'a' + 10;
58 else if ('A' <= hex && hex <= 'F') dec = hex - 'A' + 10;
59 else return -1;
60
61 return dec;
62}
63
64/*
65 * Convert hex string to byte string
66 * Return number of bytes written to buf, or 0 on error
67 */
68int hex2bin(
69 uint8_t *buf,
70 const size_t buflen,
71 const char *hex,
72 const size_t hexlen) {
73
74 int dec;
75
76 if (buflen < hexlen/2 + hexlen%2)
77 return false;
78
79 // if hexlen is uneven, insert leading zero nibble
80 if (hexlen%2) {
81 dec = hex2int(hex[0]);
82 if (dec == -1)
83 return false;
84 buf[0] = dec;
85 buf++;
86 hex++;
87 }
88
89 // regular hex conversion
90 for (size_t i = 0; i<hexlen/2; i++) {
91 dec = hex2int(hex[2*i]);
92 if (dec == -1)
93 return false;
94 buf[i] = dec << 4;
95
96 dec = hex2int(hex[2*i+1]);
97 if (dec == -1)
98 return false;
99 buf[i] += dec;
100 }
101 return hexlen/2 + hexlen%2;
102}
103
104/*
105 * Convert hex string to zero-padded nanoECC scalar
106 */
107void string2scalar(uint32_t * scalar, uint32_t num_word32, char *str) {
108
109 uint32_t num_bytes = 4*num_word32;
110 uint8_t tmp[num_bytes];
111 size_t hexlen = strlen(str);
112
113 int padding;
114
115 if (0 > (padding = 2*num_bytes - strlen(str))) {
116 printf(
117 "Error: 2*num_bytes(%u) < strlen(hex) (%zu)\n",
118 2*num_bytes,
119 strlen(str));
120 exit(-1);
121 }
122
123 memset(tmp, 0, padding/2);
124
125 if (false == hex2bin(tmp+padding/2, num_bytes, str, hexlen))
126 exit(-1);
127 ecc_bytes2native(scalar, tmp);
128
129}
130
131void vli_print(uint32_t *p_vli, unsigned int p_size) {
132 while(p_size) {
133 printf("%08X ", (unsigned)p_vli[p_size - 1]);
134 --p_size;
135 }
136}
137
138void print_ecc_scalar(
139 const char *label,
140 const uint32_t * p_vli,
141 uint32_t num_word32) {
142 uint32_t i;
143
144 if (label)
145 printf("%s = { ", label);
146
147 for(i=0; i<num_word32-1; ++i)
148 printf("0x%08lX, ", (unsigned long)p_vli[i]);
149 printf("0x%08lX", (unsigned long)p_vli[i]);
150
151 if (label)
152 printf(" };\n");
153}
154
155void check_code(const int num,
156 const char *name,
157 const int expected,
158 const int computed,
159 const int verbose) {
160
161 if (expected != computed) {
162 printf("\n Vector #%02d check %s - FAILURE:\n", num, name);
163 printf("\n Expected: %d, computed: %d\n\n", expected, computed);
164 exit(-1);
165 }
166
167 if (verbose)
168 printf(" Vector #%02d check %s - success (%d=%d)\n",
169 num,
170 name,
171 expected,
172 computed);
173
174}
175
176void check_ecc_result(const int num, const char *name,
177 const uint32_t *expected,
178 const uint32_t *computed,
179 const uint32_t num_word32,
180 const bool verbose) {
181
182 uint32_t num_bytes = 4*num_word32;
183 if (memcmp(computed, expected, num_bytes)) {
184 printf("\n Vector #%02d check %s - FAILURE:\n\n", num, name);
185 print_ecc_scalar("Expected", expected, num_word32);
186 print_ecc_scalar("Computed", computed, num_word32);
187 printf("\n");
188 exit(-1);
189 }
190 if (verbose)
191 printf(" Vector #%02d check %s - success\n", num, name);
192}
193
194/* Test ecc_make_keys, and also as keygen part of other tests */
195EccPoint keygen_vectors(char **d_vec,
196 char **qx_vec,
197 char **qy_vec,
198 int tests,
199 bool verbose) {
200
201 EccPoint pub;
202 uint32_t seed[NUM_ECC_DIGITS * 2];
203 uint32_t prv[NUM_ECC_DIGITS];
204
205 /* expected outputs (converted input vectors) */
206 EccPoint exp_pub;
207 uint32_t exp_prv[NUM_ECC_DIGITS];
208
209 for (int i=0; i<tests; i++) {
210
211 string2scalar(exp_prv, NUM_ECC_DIGITS, d_vec[i]);
212 string2scalar(exp_pub.x, NUM_ECC_DIGITS, qx_vec[i]);
213 string2scalar(exp_pub.y, NUM_ECC_DIGITS, qy_vec[i]);
214
215 /*
216 * Feed prvkey vector as padded random seed into ecc_make_key.
217 * Internal mod-reduction will be zero-op and generate correct prv/pub
218 */
219 memset(seed, 0, NUM_ECC_BYTES * 2);
220 string2scalar(seed, NUM_ECC_DIGITS, d_vec[i]);
221 ecc_make_key(&pub, prv, seed);
222
223 // validate correctness of vector conversion and make_key()
224 check_ecc_result(i, "prv ", exp_prv, prv, NUM_ECC_DIGITS, verbose);
225 check_ecc_result(i, "pub.x", exp_pub.x, pub.x, NUM_ECC_DIGITS, verbose);
226 check_ecc_result(i, "pub.y", exp_pub.y, pub.y, NUM_ECC_DIGITS, verbose);
227
228 }
229 return pub;
230}