Contiki-NG
ecc-algorithm.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
3  * All rights reserved.
4  *
5  * Author: Andreas Dröscher <contiki@anticat.ch>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. 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  * 3. Neither the name of the Institute nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 /**
32  * \addtogroup cc2538-ecc-algo
33  * @{
34  *
35  * \file
36  * Implementation of the cc2538 ECC Algorithms
37  */
38 #include "contiki.h"
39 #include "sys/process.h"
40 
41 #include <limits.h>
42 #include <stdio.h>
43 #include <string.h>
44 
45 #include "dev/ecc-algorithm.h"
46 #include "dev/ecc-driver.h"
47 #include "dev/pka.h"
48 
49 #define CHECK_RESULT(...) \
50  state->result = __VA_ARGS__; \
51  if(state->result) { \
52  printf("Line: %u Error: %u\n", __LINE__, (unsigned int)state->result); \
53  PT_EXIT(&state->pt); \
54  }
55 
56 PT_THREAD(ecc_compare(ecc_compare_state_t *state)) {
57  PT_BEGIN(&state->pt);
58 
59  CHECK_RESULT(bignum_cmp_start(state->a, state->b, state->size, state->process));
60  PT_WAIT_UNTIL(&state->pt, pka_check_status());
61  state->result = bignum_cmp_get_result();
62 
63  PT_END(&state->pt);
64 }
65 
66 PT_THREAD(ecc_multiply(ecc_multiply_state_t *state)) {
67  PT_BEGIN(&state->pt);
68 
69  CHECK_RESULT(ecc_mul_start(state->secret, &state->point_in, state->curve_info, &state->rv, state->process));
70  PT_WAIT_UNTIL(&state->pt, pka_check_status());
71  CHECK_RESULT(ecc_mul_get_result(&state->point_out, state->rv));
72 
73  PT_END(&state->pt);
74 }
75 
76 PT_THREAD(ecc_dsa_sign(ecc_dsa_sign_state_t *state)) {
77  /* Executed Every Time */
78  uint8_t size = state->curve_info->size;
79  const uint32_t *ord = state->curve_info->n;
80 
81  ec_point_t point;
82  memcpy(point.x, state->curve_info->x, sizeof(point.x));
83  memcpy(point.y, state->curve_info->y, sizeof(point.y));
84 
85  PT_BEGIN(&state->pt);
86 
87  /* Invert k_e mod n */
88  CHECK_RESULT(bignum_inv_mod_start(state->k_e, size, ord, size, &state->rv, state->process));
89  PT_WAIT_UNTIL(&state->pt, pka_check_status());
90  CHECK_RESULT(bignum_inv_mod_get_result(state->k_e_inv, size, state->rv));
91 
92  /* Calculate Point R = K_e * GeneratorPoint */
93  CHECK_RESULT(ecc_mul_start(state->k_e, &point, state->curve_info, &state->rv, state->process));
94  PT_WAIT_UNTIL(&state->pt, pka_check_status());
95  CHECK_RESULT(ecc_mul_get_result(&state->point_r, state->rv));
96 
97  /* Calculate signature using big math functions
98  * d*r (r is the x coordinate of PointR) */
99  CHECK_RESULT(bignum_mul_start(state->secret, size, state->point_r.x, size, &state->rv, state->process));
100  PT_WAIT_UNTIL(&state->pt, pka_check_status());
101  state->len = 24;
102  CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
103 
104  /* d*r mod n */
105  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
106  PT_WAIT_UNTIL(&state->pt, pka_check_status());
107  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
108 
109  /* hash + d*r */
110  CHECK_RESULT(bignum_add_start(state->hash, size, state->signature_s, size, &state->rv, state->process));
111  PT_WAIT_UNTIL(&state->pt, pka_check_status());
112  state->len = 24;
113  CHECK_RESULT(bignum_add_get_result(state->signature_s, &state->len, state->rv));
114 
115  /* hash + d*r mod n */
116  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
117  PT_WAIT_UNTIL(&state->pt, pka_check_status());
118  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
119 
120  /* k_e_inv * (hash + d*r) */
121  CHECK_RESULT(bignum_mul_start(state->k_e_inv, size, state->signature_s, size, &state->rv, state->process));
122  PT_WAIT_UNTIL(&state->pt, pka_check_status());
123  state->len = 24;
124  CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
125 
126  /* k_e_inv * (hash + d*r) mod n */
127  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
128  PT_WAIT_UNTIL(&state->pt, pka_check_status());
129  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
130 
131  PT_END(&state->pt);
132 }
133 
134 PT_THREAD(ecc_dsa_verify(ecc_dsa_verify_state_t *state)) {
135  /* Executed Every Time */
136  uint8_t size = state->curve_info->size;
137  const uint32_t *ord = state->curve_info->n;
138 
139  ec_point_t point;
140  memcpy(point.x, state->curve_info->x, sizeof(point.x));
141  memcpy(point.y, state->curve_info->y, sizeof(point.y));
142 
143  PT_BEGIN(&state->pt);
144 
145  /* Invert s mod n */
146  CHECK_RESULT(bignum_inv_mod_start(state->signature_s, size, ord, size, &state->rv, state->process));
147  PT_WAIT_UNTIL(&state->pt, pka_check_status());
148  CHECK_RESULT(bignum_inv_mod_get_result(state->s_inv, size, state->rv));
149 
150  /* Calculate u1 = s_inv * hash */
151  CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->hash, size, &state->rv, state->process));
152  PT_WAIT_UNTIL(&state->pt, pka_check_status());
153  state->len = 24;
154  CHECK_RESULT(bignum_mul_get_result(state->u1, &state->len, state->rv));
155 
156  /* Calculate u1 = s_inv * hash mod n */
157  CHECK_RESULT(bignum_mod_start(state->u1, state->len, ord, size, &state->rv, state->process));
158  PT_WAIT_UNTIL(&state->pt, pka_check_status());
159  CHECK_RESULT(bignum_mod_get_result(state->u1, size, state->rv));
160 
161  /* Calculate u2 = s_inv * r */
162  CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->signature_r, size, &state->rv, state->process));
163  PT_WAIT_UNTIL(&state->pt, pka_check_status());
164  state->len = 24;
165  CHECK_RESULT(bignum_mul_get_result(state->u2, &state->len, state->rv));
166 
167  /* Calculate u2 = s_inv * r mod n */
168  CHECK_RESULT(bignum_mod_start(state->u2, state->len, ord, size, &state->rv, state->process));
169  PT_WAIT_UNTIL(&state->pt, pka_check_status());
170  CHECK_RESULT(bignum_mod_get_result(state->u2, size, state->rv));
171 
172  /* Calculate p1 = u1 * A */
173  CHECK_RESULT(ecc_mul_start(state->u1, &point, state->curve_info, &state->rv, state->process));
174  PT_WAIT_UNTIL(&state->pt, pka_check_status());
175  CHECK_RESULT(ecc_mul_get_result(&state->p1, state->rv));
176 
177  /* Calculate p2 = u1 * B */
178  CHECK_RESULT(ecc_mul_start(state->u2, &state->public, state->curve_info, &state->rv, state->process));
179  PT_WAIT_UNTIL(&state->pt, pka_check_status());
180  CHECK_RESULT(ecc_mul_get_result(&state->p2, state->rv));
181 
182  /* Calculate P = p1 + p2 */
183  CHECK_RESULT(ecc_add_start(&state->p1, &state->p2, state->curve_info, &state->rv, state->process));
184  PT_WAIT_UNTIL(&state->pt, pka_check_status());
185  CHECK_RESULT(ecc_add_get_result(&state->p1, state->rv));
186 
187  /* Verify Result */
188  CHECK_RESULT(bignum_cmp_start(state->signature_r, state->p1.x, size, state->process));
189  PT_WAIT_UNTIL(&state->pt, pka_check_status());
190  state->result = bignum_cmp_get_result();
191  if((state->result == PKA_STATUS_A_GR_B) || (state->result == PKA_STATUS_A_LT_B)) {
192  state->result = PKA_STATUS_SIGNATURE_INVALID;
193  }
194 
195  PT_END(&state->pt);
196 }
197 
198 /**
199  * @}
200  * @}
201  */
uint8_t bignum_cmp_get_result(void)
Gets the result of the comparison operation of two big numbers.
uint8_t ecc_mul_get_result(ec_point_t *ec_point, uint32_t result_vector)
Gets the result of ECC Multiplication.
Definition: ecc-driver.c:163
Header file for the cc2538 ECC Algorithms.
uint8_t pka_check_status(void)
Checks the status of the PKA engine operation.
Definition: pka.c:114
#define PKA_STATUS_A_LT_B
Big number compare return status if the first big num is less than the second.
Definition: pka.h:1306
uint8_t bignum_mod_get_result(uint32_t *buffer, const uint8_t buffer_size, const uint32_t result_vector)
Gets the result of the big number modulus operation.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition: pt.h:114
uint8_t bignum_inv_mod_get_result(uint32_t *buffer, const uint8_t buffer_size, const uint32_t result_vector)
Gets the result of the big number inverse modulo operation.
uint8_t bignum_mod_start(const uint32_t *number, const uint8_t number_size, const uint32_t *modulus, const uint8_t modulus_size, uint32_t *result_vector, struct process *process)
Starts the big number modulus operation.
Definition: bignum-driver.c:64
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
Definition: pt.h:147
#define PKA_STATUS_A_GR_B
Big number compare return status if the first big num is greater than the second. ...
Definition: pka.h:1301
PT_THREAD(ecc_compare(ecc_compare_state_t *state))
Do a compare of two big numbers.
Definition: ecc-algorithm.c:56
uint8_t ecc_add_get_result(ec_point_t *ec_point, uint32_t result_vector)
Gets the result of the ECC Addition.
Definition: ecc-driver.c:503
uint8_t bignum_mul_start(const uint32_t *multiplicand, const uint8_t multiplicand_size, const uint32_t *multiplier, const uint8_t multiplier_size, uint32_t *result_vector, struct process *process)
Starts the big number multiplication.
uint8_t ecc_mul_start(uint32_t *scalar, ec_point_t *ec_point, ecc_curve_info_t *curve, uint32_t *result_vector, struct process *process)
Starts ECC Multiplication.
Definition: ecc-driver.c:50
uint8_t bignum_add_start(const uint32_t *number1, const uint8_t number1_size, const uint32_t *number2, const uint8_t number2_size, uint32_t *result_vector, struct process *process)
Starts the addition of two big number.
Header file for the cc2538 PKA engine driver.
#define PT_END(pt)
Declare the end of a protothread.
Definition: pt.h:126
Header file for the cc2538 ECC driver.
Header file for the Contiki process interface.
uint8_t ecc_add_start(ec_point_t *ec_point1, ec_point_t *ec_point2, ecc_curve_info_t *curve, uint32_t *result_vector, struct process *process)
Starts the ECC Addition.
Definition: ecc-driver.c:391
uint8_t bignum_add_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the result of the addition operation on two big number.
uint8_t bignum_cmp_start(const uint32_t *number1, const uint32_t *number2, const uint8_t size, struct process *process)
Starts the comparison of two big numbers.
uint8_t bignum_inv_mod_start(const uint32_t *number, const uint8_t number_size, const uint32_t *modulus, const uint8_t modulus_size, uint32_t *result_vector, struct process *process)
Starts the big number inverse modulo operation.
uint8_t bignum_mul_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the results of the big number multiplication.
#define PKA_STATUS_SIGNATURE_INVALID
Signature is invalid.
Definition: pka.h:1313