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