Contiki-NG
Loading...
Searching...
No Matches
ecdh.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024, RISE Research Institutes of Sweden AB
3 * Copyright (c) 2020, Industrial Systems Institute (ISI), Patras, Greece
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
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holder nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32/**
33 * \file
34 * Synchronous wrapper around lib/ecc.h for the EDHOC implementation.
35 *
36 * The Contiki-NG ECC driver exposes long-running operations as
37 * protothreads so that other protothreads may make progress
38 * while the cryptographic operation is in flight. The current
39 * EDHOC protocol implementation is synchronous, so we busy-wait
40 * the underlying protothread to completion. This still
41 * deduplicates the per-backend wrappers EDHOC used to ship.
42 *
43 * \author
44 * Lidia Pocero <pocero@isi.gr>, Peter A Jonsson, Rikard Höglund,
45 * Marco Tiloca, Nicolas Tsiftes
46 */
47
48#include "contiki.h"
49#include "dev/watchdog.h"
50#include "ecdh.h"
51#include "edhoc-config.h"
52#include "lib/ecc.h"
53#include "lib/ecc-curve.h"
54#include "sys/process-mutex.h"
55#include "sys/pt.h"
56#include <string.h>
57
58#include "sys/log.h"
59#define LOG_MODULE "ECDH"
60#define LOG_LEVEL LOG_LEVEL_EDHOC
61
62/*---------------------------------------------------------------------------*/
63static const ecc_curve_t *
64get_curve(uint8_t curve_id)
65{
66 switch(curve_id) {
67 case EDHOC_CURVE_P256:
68 return &ecc_curve_p_256;
69 default:
70 LOG_ERR("Unsupported ECDH curve id %u\n", curve_id);
71 return NULL;
72 }
73}
74/*---------------------------------------------------------------------------*/
75static bool
76acquire_ecc(const ecc_curve_t *curve)
77{
79 while(!process_mutex_try_lock(mutex)) {
81 }
82 if(ecc_enable(curve) != 0) {
83 /* ecc_enable() releases the mutex on failure. */
84 LOG_ERR("ecc_enable() failed\n");
85 return false;
86 }
87 return true;
88}
89/*---------------------------------------------------------------------------*/
90bool
91ecdh_generate_keypair(uint8_t curve_id,
92 uint8_t *pub_x, uint8_t *pub_y, uint8_t *priv)
93{
94 const ecc_curve_t *curve = get_curve(curve_id);
95 if(!curve) {
96 return false;
97 }
98 if(!acquire_ecc(curve)) {
99 return false;
100 }
101
102 uint8_t public_key[2 * ECC_KEY_LEN];
103 int result = -1;
104
106 while(PT_SCHEDULE(ecc_generate_key_pair(public_key, priv, &result))) {
108 }
109
110 ecc_disable();
111
112 if(result != 0) {
113 LOG_ERR("ecc_generate_key_pair() failed (%d)\n", result);
114 return false;
115 }
116
117 memcpy(pub_x, public_key, ECC_KEY_LEN);
118 memcpy(pub_y, public_key + ECC_KEY_LEN, ECC_KEY_LEN);
119 return true;
120}
121/*---------------------------------------------------------------------------*/
122bool
123ecdh_generate_ikm(uint8_t curve_id,
124 const uint8_t *peer_x,
125 const uint8_t *private_key, uint8_t *ikm)
126{
127 const ecc_curve_t *curve = get_curve(curve_id);
128 if(!curve) {
129 return false;
130 }
131 if(!acquire_ecc(curve)) {
132 return false;
133 }
134
135 /*
136 * EDHOC encodes peer ephemeral keys as the x-coordinate only. Recover
137 * the full point by decompressing the (0x03 || x) compressed encoding.
138 * The 0x03 sign-byte (odd y) matches the convention used by the
139 * reference implementations and the EDHOC test vectors.
140 */
141 uint8_t compressed[1 + ECC_KEY_LEN];
142 uint8_t public_key[2 * ECC_KEY_LEN];
143 compressed[0] = 0x03;
144 memcpy(compressed + 1, peer_x, ECC_KEY_LEN);
145
146 int result = -1;
148 while(PT_SCHEDULE(ecc_decompress_public_key(compressed, public_key,
149 &result))) {
151 }
152 if(result != 0) {
153 LOG_ERR("ecc_decompress_public_key() failed (%d)\n", result);
154 ecc_disable();
155 return false;
156 }
157
159 while(PT_SCHEDULE(ecc_generate_shared_secret(public_key, private_key,
160 ikm, &result))) {
162 }
163
164 ecc_disable();
165
166 if(result != 0) {
167 LOG_ERR("ecc_generate_shared_secret() failed (%d)\n", result);
168 return false;
169 }
170 return true;
171}
172/*---------------------------------------------------------------------------*/
173bool
174ecc_sign_hash(uint8_t curve_id,
175 const uint8_t *hash,
176 const uint8_t *private_key,
177 uint8_t *signature)
178{
179 const ecc_curve_t *curve = get_curve(curve_id);
180 if(!curve) {
181 return false;
182 }
183 if(!acquire_ecc(curve)) {
184 return false;
185 }
186
187 int result = -1;
189 while(PT_SCHEDULE(ecc_sign(hash, private_key, signature, &result))) {
191 }
192
193 ecc_disable();
194
195 if(result != 0) {
196 LOG_ERR("ecc_sign() failed (%d)\n", result);
197 return false;
198 }
199 return true;
200}
201/*---------------------------------------------------------------------------*/
202bool
203ecc_verify_hash(uint8_t curve_id,
204 const uint8_t *hash,
205 const uint8_t *public_key,
206 const uint8_t *signature)
207{
208 const ecc_curve_t *curve = get_curve(curve_id);
209 if(!curve) {
210 return false;
211 }
212 if(!acquire_ecc(curve)) {
213 return false;
214 }
215
216 int result = -1;
218 while(PT_SCHEDULE(ecc_verify(signature, hash, public_key, &result))) {
220 }
221
222 ecc_disable();
223
224 if(result != 0) {
225 LOG_ERR("ecc_verify() failed (%d)\n", result);
226 return false;
227 }
228 return true;
229}
230/*---------------------------------------------------------------------------*/
NIST curves for various key sizes.
Header file of ECC.
bool ecc_sign_hash(uint8_t curve_id, const uint8_t *hash, const uint8_t *private_key, uint8_t *signature)
Generates an ECDSA signature for a message hash.
Definition ecdh.c:174
bool ecdh_generate_ikm(uint8_t curve_id, const uint8_t *peer_x, const uint8_t *private_key, uint8_t *ikm)
Computes an ECDH shared secret.
Definition ecdh.c:123
bool ecc_verify_hash(uint8_t curve_id, const uint8_t *hash, const uint8_t *public_key, const uint8_t *signature)
Verifies an ECDSA signature of a message hash.
Definition ecdh.c:203
bool ecdh_generate_keypair(uint8_t curve_id, uint8_t *pub_x, uint8_t *pub_y, uint8_t *priv)
Generates a fresh ECDH key pair.
Definition ecdh.c:91
ECDH interface for the EDHOC implementation.
EDHOC configuration file.
char ecc_verify(const uint8_t *signature, const uint8_t *message_hash, const uint8_t *public_key, int *const result)
Definition cc2538-ecc.c:858
char ecc_decompress_public_key(const uint8_t *compressed_public_key, uint8_t *uncompressed_public_key, int *const result)
Definition cc2538-ecc.c:570
char ecc_generate_key_pair(uint8_t *public_key, uint8_t *private_key, int *const result)
char ecc_sign(const uint8_t *message_hash, const uint8_t *private_key, uint8_t *signature, int *const result)
Definition cc2538-ecc.c:696
char ecc_generate_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uint8_t *shared_secret, int *const result)
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition watchdog.c:85
void ecc_disable(void)
Shuts down the ECC driver and unlocks the mutex.
Definition ecc.c:184
process_mutex_t * ecc_get_mutex(void)
Provides a mutex to be locked before proceeding with ecc_enable().
Definition ecc.c:66
struct pt * ecc_get_protothread(void)
Provides the protothread that runs long-running ECC operations.
Definition ecc.c:87
bool process_mutex_try_lock(process_mutex_t *mutex)
Tries to acquire a process mutex.
#define PT_INIT(pt)
Initialize a protothread.
Definition pt.h:245
#define PT_SCHEDULE(f)
Schedule a protothread.
Definition pt.h:436
Header file for the logging system.
Header file for Process mutexes.
Protothreads implementation.
Parameters of an ECC curve in little-endian word order.
Definition ecc-curve.h:53
Structure of a process mutex.