Contiki-NG
Loading...
Searching...
No Matches
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
56PT_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
66PT_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
76PT_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
134PT_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 */
Header file for the cc2538 ECC Algorithms.
Header file for the cc2538 ECC driver.
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_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_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.
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_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.
uint8_t bignum_cmp_get_result(void)
Gets the result of the comparison operation of two big numbers.
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_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.
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 ecc_mul_get_result(ec_point_t *ec_point, uint32_t result_vector)
Gets the result of ECC Multiplication.
Definition ecc-driver.c:163
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 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 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 pka_check_status(void)
Checks the status of the PKA engine operation.
Definition pka.c:114
#define PKA_STATUS_SIGNATURE_INVALID
Signature is invalid.
Definition pka.h:830
#define PKA_STATUS_A_LT_B
Big number compare return status if the first big num is less than the second.
Definition pka.h:825
#define PKA_STATUS_A_GR_B
Big number compare return status if the first big num is greater than the second.
Definition pka.h:822
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition pt.h:280
#define PT_THREAD(name_args)
Declaration of a protothread.
Definition pt.h:265
#define PT_END(pt)
Declare the end of a protothread.
Definition pt.h:292
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
Definition pt.h:313
Header file for the cc2538 PKA engine driver.
Header file for the Contiki process interface.