Contiki 3.x
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 c2538-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 
44 #include "dev/ecc-algorithm.h"
45 #include "dev/ecc-driver.h"
46 #include "dev/pka.h"
47 
48 #define CHECK_RESULT(...) \
49  state->result = __VA_ARGS__; \
50  if(state->result) { \
51  printf("Line: %u Error: %u\n", __LINE__, (unsigned int)state->result); \
52  PT_EXIT(&state->pt); \
53  }
54 
55 PT_THREAD(ecc_compare(ecc_compare_state_t *state)) {
56  PT_BEGIN(&state->pt);
57 
58  CHECK_RESULT(bignum_cmp_start(state->a, state->b, state->size, state->process));
59  PT_WAIT_UNTIL(&state->pt, pka_check_status());
60  state->result = bignum_cmp_get_result();
61 
62  PT_END(&state->pt);
63 }
64 
65 PT_THREAD(ecc_multiply(ecc_multiply_state_t *state)) {
66  PT_BEGIN(&state->pt);
67 
68  CHECK_RESULT(ecc_mul_start(state->secret, &state->point_in, state->curve_info, &state->rv, state->process));
69  PT_WAIT_UNTIL(&state->pt, pka_check_status());
70  CHECK_RESULT(ecc_mul_get_result(&state->point_out, state->rv));
71 
72  PT_END(&state->pt);
73 }
74 
75 PT_THREAD(ecc_dsa_sign(ecc_dsa_sign_state_t *state)) {
76  /* Executed Every Time */
77  uint8_t size = state->curve_info->size;
78  const uint32_t *ord = state->curve_info->n;
79 
80  ec_point_t point;
81  memcpy(point.x, state->curve_info->x, sizeof(point.x));
82  memcpy(point.y, state->curve_info->y, sizeof(point.y));
83 
84  PT_BEGIN(&state->pt);
85 
86  /* Invert k_e mod n */
87  CHECK_RESULT(bignum_inv_mod_start(state->k_e, size, ord, size, &state->rv, state->process));
88  PT_WAIT_UNTIL(&state->pt, pka_check_status());
89  CHECK_RESULT(bignum_inv_mod_get_result(state->k_e_inv, size, state->rv));
90 
91  /* Calculate Point R = K_e * GeneratorPoint */
92  CHECK_RESULT(ecc_mul_start(state->k_e, &point, state->curve_info, &state->rv, state->process));
93  PT_WAIT_UNTIL(&state->pt, pka_check_status());
94  CHECK_RESULT(ecc_mul_get_result(&state->point_r, state->rv));
95 
96  /* Calculate signature using big math functions
97  * d*r (r is the x coordinate of PointR) */
98  CHECK_RESULT(bignum_mul_start(state->secret, size, state->point_r.x, size, &state->rv, state->process));
99  PT_WAIT_UNTIL(&state->pt, pka_check_status());
100  state->len = 24;
101  CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
102 
103  /* d*r mod n */
104  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
105  PT_WAIT_UNTIL(&state->pt, pka_check_status());
106  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
107 
108  /* hash + d*r */
109  CHECK_RESULT(bignum_add_start(state->hash, size, state->signature_s, size, &state->rv, state->process));
110  PT_WAIT_UNTIL(&state->pt, pka_check_status());
111  state->len = 24;
112  CHECK_RESULT(bignum_add_get_result(state->signature_s, &state->len, state->rv));
113 
114  /* hash + d*r mod n */
115  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
116  PT_WAIT_UNTIL(&state->pt, pka_check_status());
117  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
118 
119  /* k_e_inv * (hash + d*r) */
120  CHECK_RESULT(bignum_mul_start(state->k_e_inv, size, state->signature_s, size, &state->rv, state->process));
121  PT_WAIT_UNTIL(&state->pt, pka_check_status());
122  state->len = 24;
123  CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
124 
125  /* k_e_inv * (hash + d*r) mod n */
126  CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
127  PT_WAIT_UNTIL(&state->pt, pka_check_status());
128  CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
129 
130  PT_END(&state->pt);
131 }
132 
133 PT_THREAD(ecc_dsa_verify(ecc_dsa_verify_state_t *state)) {
134  /* Executed Every Time */
135  uint8_t size = state->curve_info->size;
136  const uint32_t *ord = state->curve_info->n;
137 
138  ec_point_t point;
139  memcpy(point.x, state->curve_info->x, sizeof(point.x));
140  memcpy(point.y, state->curve_info->y, sizeof(point.y));
141 
142  PT_BEGIN(&state->pt);
143 
144  /* Invert s mod n */
145  CHECK_RESULT(bignum_inv_mod_start(state->signature_s, size, ord, size, &state->rv, state->process));
146  PT_WAIT_UNTIL(&state->pt, pka_check_status());
147  CHECK_RESULT(bignum_inv_mod_get_result(state->s_inv, size, state->rv));
148 
149  /* Calculate u1 = s_inv * hash */
150  CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->hash, size, &state->rv, state->process));
151  PT_WAIT_UNTIL(&state->pt, pka_check_status());
152  state->len = 24;
153  CHECK_RESULT(bignum_mul_get_result(state->u1, &state->len, state->rv));
154 
155  /* Calculate u1 = s_inv * hash mod n */
156  CHECK_RESULT(bignum_mod_start(state->u1, state->len, ord, size, &state->rv, state->process));
157  PT_WAIT_UNTIL(&state->pt, pka_check_status());
158  CHECK_RESULT(bignum_mod_get_result(state->u1, size, state->rv));
159 
160  /* Calculate u2 = s_inv * r */
161  CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->signature_r, size, &state->rv, state->process));
162  PT_WAIT_UNTIL(&state->pt, pka_check_status());
163  state->len = 24;
164  CHECK_RESULT(bignum_mul_get_result(state->u2, &state->len, state->rv));
165 
166  /* Calculate u2 = s_inv * r mod n */
167  CHECK_RESULT(bignum_mod_start(state->u2, state->len, ord, size, &state->rv, state->process));
168  PT_WAIT_UNTIL(&state->pt, pka_check_status());
169  CHECK_RESULT(bignum_mod_get_result(state->u2, size, state->rv));
170 
171  /* Calculate p1 = u1 * A */
172  CHECK_RESULT(ecc_mul_start(state->u1, &point, state->curve_info, &state->rv, state->process));
173  PT_WAIT_UNTIL(&state->pt, pka_check_status());
174  CHECK_RESULT(ecc_mul_get_result(&state->p1, state->rv));
175 
176  /* Calculate p2 = u1 * B */
177  CHECK_RESULT(ecc_mul_start(state->u2, &state->public, state->curve_info, &state->rv, state->process));
178  PT_WAIT_UNTIL(&state->pt, pka_check_status());
179  CHECK_RESULT(ecc_mul_get_result(&state->p2, state->rv));
180 
181  /* Calculate P = p1 + p2 */
182  CHECK_RESULT(ecc_add_start(&state->p1, &state->p2, state->curve_info, &state->rv, state->process));
183  PT_WAIT_UNTIL(&state->pt, pka_check_status());
184  CHECK_RESULT(ecc_add_get_result(&state->p1, state->rv));
185 
186  /* Verify Result */
187  CHECK_RESULT(bignum_cmp_start(state->signature_r, state->p1.x, size, state->process));
188  PT_WAIT_UNTIL(&state->pt, pka_check_status());
189  state->result = bignum_cmp_get_result();
190  if((state->result == PKA_STATUS_A_GR_B) || (state->result == PKA_STATUS_A_LT_B)) {
191  state->result = PKA_STATUS_SIGNATURE_INVALID;
192  }
193 
194  PT_END(&state->pt);
195 }
196 
197 /**
198  * @}
199  * @}
200  */
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
#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
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.
#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 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 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
PT_THREAD(ecc_compare(ecc_compare_state_t *state))
Do a compare of two big numbers.
Definition: ecc-algorithm.c:55
Header file for the cc2538 ECC driver.
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
Definition: pt.h:147
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.
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.
Header file for the cc2538 ECC Algorithms.
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
int32_t ecc_compare(const uint32_t *a, const uint32_t *b)
Compares the value of a with the value of b.
Definition: ecc.c:112
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition: pt.h:114
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.
Header file for the Contiki process interface.
uint8_t pka_check_status(void)
Checks the status of the PKA engine operation.
Definition: pka.c:119
#define PT_END(pt)
Declare the end of a protothread.
Definition: pt.h:126
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_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.
#define PKA_STATUS_SIGNATURE_INVALID
Signature is invalid.
Definition: pka.h:1313
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.
uint8_t bignum_cmp_get_result(void)
Gets the result of the comparison operation of two big numbers.
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_cmp_start(const uint32_t *number1, const uint32_t *number2, const uint8_t size, struct process *process)
Starts the comparison of two big numbers.
Header file for the cc2538 PKA engine driver.