Skip to content

Commit

Permalink
ECC: Add FHMQV support
Browse files Browse the repository at this point in the history
  • Loading branch information
kkrentz committed Nov 26, 2024
1 parent 8a8e3f0 commit 7076055
Show file tree
Hide file tree
Showing 8 changed files with 440 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@
url = https://github.com/kkrentz/libcoap.git
[submodule "os/net/security/micro-ecc"]
path = os/net/security/micro-ecc
url = https://github.com/kmackay/micro-ecc
url = https://github.com/kkrentz/micro-ecc.git
113 changes: 112 additions & 1 deletion arch/cpu/cc2538/dev/cc2538-ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* @{
*
* \file
* Implementation of PKA-accelerated ECDH and ECDSA.
* Implementation of PKA-accelerated ECDH, ECDSA, and FHMQV.
*/

#include "lib/ecc.h"
Expand Down Expand Up @@ -1092,6 +1092,116 @@ static PT_THREAD(generate_shared_secret(const uint8_t *public_key,
PT_END(&main_protothread);
}
/*---------------------------------------------------------------------------*/
static PT_THREAD(generate_fhmqv_secret(const uint8_t *static_private_key,
const uint8_t *ephemeral_private_key,
const uint8_t *static_public_key,
const uint8_t *ephemeral_public_key,
const uint8_t *d,
const uint8_t *e,
uint8_t *shared_secret,
int *const result))
{
static const uintptr_t static_private_key_offset =
variables_offset;
static const uintptr_t ephemeral_private_key_offset =
PKA_NEXT_OFFSET(static_private_key_offset, MAX_ELEMENT_WORDS);
static const uintptr_t static_public_key_offset =
PKA_NEXT_OFFSET(ephemeral_private_key_offset, MAX_ELEMENT_WORDS);
static const uintptr_t ephemeral_public_key_offset =
PKA_NEXT_OFFSET(static_public_key_offset, MAX_POINT_WORDS);
static const uintptr_t d_offset =
PKA_NEXT_OFFSET(ephemeral_public_key_offset, MAX_POINT_WORDS);
static const uintptr_t e_offset =
PKA_NEXT_OFFSET(d_offset, MAX_ELEMENT_WORDS);
static const uintptr_t s_offset =
PKA_NEXT_OFFSET(e_offset, MAX_ELEMENT_WORDS);
static const uintptr_t sigma_offset =
PKA_NEXT_OFFSET(s_offset, MAX_ELEMENT_WORDS);
/* PKA_NEXT_OFFSET(sigma_offset, MAX_POINT_WORDS); */

PT_BEGIN(&main_protothread);

/* copy inputs to PKA RAM */
element_to_pka_ram(static_private_key, static_private_key_offset);
element_to_pka_ram(ephemeral_private_key, ephemeral_private_key_offset);
point_to_pka_ram(static_public_key, static_public_key_offset);
point_to_pka_ram(ephemeral_public_key, ephemeral_public_key_offset);
element_to_pka_ram(d, d_offset);
element_to_pka_ram(e, e_offset);

/* s := d * static private key */
PT_SPAWN(&main_protothread,
&helper_protothread,
add_or_multiply_modulo(PKA_FUNCTION_MULTIPLY,
d_offset,
static_private_key_offset,
curve_n_offset,
s_offset,
result));
if(*result != PKA_STATUS_SUCCESS) {
LOG_ERR("Line: %u Error: %u\n", __LINE__, *result);
PT_EXIT(&main_protothread);
}

/* s := ephemeral private key + d * static private key */
PT_SPAWN(&main_protothread,
&helper_protothread,
add_or_multiply_modulo(PKA_FUNCTION_ADD,
s_offset,
ephemeral_private_key_offset,
curve_n_offset,
s_offset,
result));
if(*result != PKA_STATUS_SUCCESS) {
LOG_ERR("Line: %u Error: %u\n", __LINE__, *result);
PT_EXIT(&main_protothread);
}

/* sigma := e x static public key */
PT_SPAWN(&main_protothread,
&helper_protothread,
add_or_multiply_point(PKA_FUNCTION_ECCMUL,
e_offset,
static_public_key_offset,
sigma_offset,
result));
if(*result != PKA_STATUS_SUCCESS) {
LOG_ERR("Line: %u Error: %u\n", __LINE__, *result);
PT_EXIT(&main_protothread);
}

/* sigma := ephemeral public key + e x static public key */
PT_SPAWN(&main_protothread,
&helper_protothread,
add_or_multiply_point(PKA_FUNCTION_ECCADD,
sigma_offset,
ephemeral_public_key_offset,
sigma_offset,
result));
if(*result != PKA_STATUS_SUCCESS) {
LOG_ERR("Line: %u Error: %u\n", __LINE__, *result);
PT_EXIT(&main_protothread);
}

/* sigma := s x (ephemeral public key + e x static public key) */
PT_SPAWN(&main_protothread,
&helper_protothread,
add_or_multiply_point(PKA_FUNCTION_ECCMUL,
s_offset,
sigma_offset,
sigma_offset,
result));
if(*result != PKA_STATUS_SUCCESS) {
LOG_ERR("Line: %u Error: %u\n", __LINE__, *result);
PT_EXIT(&main_protothread);
}

element_from_pka_ram(shared_secret, sigma_offset);
*result = PKA_STATUS_SUCCESS;

PT_END(&main_protothread);
}
/*---------------------------------------------------------------------------*/
static void
disable(void)
{
Expand All @@ -1111,6 +1221,7 @@ const struct ecc_driver cc2538_ecc_driver = {
verify,
generate_key_pair,
generate_shared_secret,
generate_fhmqv_secret,
disable
};
/*---------------------------------------------------------------------------*/
Expand Down
2 changes: 1 addition & 1 deletion examples/libs/ecc/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CONTIKI_PROJECT = compress ecdh ecdsa
CONTIKI_PROJECT = compress ecdh ecdsa fhmqv
all: $(CONTIKI_PROJECT)

CONTIKI = ../../..
Expand Down
166 changes: 166 additions & 0 deletions examples/libs/ecc/fhmqv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (c) 2022, Uppsala universitet.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/

/**
* \file
* Demonstrates the usage of FHMQV.
* \author
* Konrad Krentz <[email protected]>
*/

#include "contiki.h"
#include "lib/ecc.h"
#include "lib/sha-256.h"
#include <string.h>

#include "sys/log.h"
#define LOG_MODULE "FHMQV"
#define LOG_LEVEL LOG_LEVEL_DBG

#define ECC_CURVE (&ecc_curve_p_256)
#define ECC_CURVE_SIZE (ECC_CURVE_P_256_SIZE)

PROCESS(fhmqv_process, "FHMQV");
AUTOSTART_PROCESSES(&fhmqv_process);

/*---------------------------------------------------------------------------*/
PROCESS_THREAD(fhmqv_process, ev, data)
{
int result;
static uint8_t static_public_key_a[ECC_CURVE_SIZE * 2];
static uint8_t static_private_key_a[ECC_CURVE_SIZE];
static uint8_t ephemeral_public_key_a[ECC_CURVE_SIZE * 2];
static uint8_t ephemeral_private_key_a[ECC_CURVE_SIZE];
static uint8_t static_public_key_b[ECC_CURVE_SIZE * 2];
static uint8_t static_private_key_b[ECC_CURVE_SIZE];
static uint8_t ephemeral_public_key_b[ECC_CURVE_SIZE * 2];
static uint8_t ephemeral_private_key_b[ECC_CURVE_SIZE];
static uint8_t d[SHA_256_DIGEST_LENGTH];
static uint8_t e[SHA_256_DIGEST_LENGTH];
static uint8_t k_a[ECC_CURVE_SIZE];
static uint8_t k_b[ECC_CURVE_SIZE];

PROCESS_BEGIN();

/* enable ECC driver */
PROCESS_WAIT_UNTIL(process_mutex_try_lock(ECC.get_mutex()));
if(ECC.enable(ECC_CURVE)) {
LOG_ERR("enable failed\n");
PROCESS_EXIT();
}

LOG_INFO("generating key pairs\n");
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(static_public_key_a,
static_private_key_a,
&result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(ephemeral_public_key_a,
ephemeral_private_key_a,
&result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(static_public_key_b,
static_private_key_b,
&result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(ephemeral_public_key_b,
ephemeral_private_key_b,
&result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}

LOG_INFO("running FHMQV\n");

/* d || e */
SHA_256.init();
SHA_256.update(ephemeral_public_key_a, sizeof(ephemeral_public_key_a));
SHA_256.update(ephemeral_public_key_b, sizeof(ephemeral_public_key_b));
SHA_256.update(static_public_key_a, sizeof(static_public_key_a));
SHA_256.update(static_public_key_b, sizeof(static_public_key_b));
SHA_256.finalize(d);
memcpy(e + SHA_256_DIGEST_LENGTH / 2, d, SHA_256_DIGEST_LENGTH / 2);
memset(e, 0, SHA_256_DIGEST_LENGTH / 2);
memset(d, 0, SHA_256_DIGEST_LENGTH / 2);

PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_fhmqv_secret(static_private_key_b,
ephemeral_private_key_b,
static_public_key_a,
ephemeral_public_key_a,
e,
d,
k_b,
&result));
if(result) {
LOG_ERR("ECC.generate_fhmqv_secret failed\n");
PROCESS_EXIT();
}

PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_fhmqv_secret(static_private_key_a,
ephemeral_private_key_a,
static_public_key_b,
ephemeral_public_key_b,
d,
e,
k_a,
&result));
if(result) {
LOG_ERR("ECC.generate_fhmqv_secret failed\n");
PROCESS_EXIT();
}

ECC.disable();

if(memcmp(k_a, k_b, ECC_CURVE_SIZE)) {
LOG_ERR("unequal\n");
} else {
LOG_INFO("OK\n");
}

PROCESS_END();
}
/*---------------------------------------------------------------------------*/
24 changes: 24 additions & 0 deletions os/lib/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,30 @@ struct ecc_driver {
uint8_t *shared_secret,
int *result));

/**
* \brief Generates a shared secret as per FHMQV.
*
* NOTE: A shortcut taken in fastd is to set
* d||e = Hash(ours and peer's ephemeral and static public keys).
*
* \param static_private_key Our static |CURVE|-byte private key.
* \param ephemeral_private_key Our ephemeral |CURVE|-byte private key.
* \param static_public_key Peer's static 2|CURVE|-byte public key.
* \param ephemeral_public_key Peer's ephemeral 2|CURVE|-byte public key.
* \param d The |CURVE|-byte FHMQV parameter d.
* \param e The |CURVE|-byte FHMQV parameter e.
* \param shared_secret The resultant |CURVE|-byte shared secret.
* \param result 0 on success or a driver-specific error code.
*/
PT_THREAD((* generate_fhmqv_secret)(const uint8_t *static_private_key,
const uint8_t *ephemeral_private_key,
const uint8_t *static_public_key,
const uint8_t *ephemeral_public_key,
const uint8_t *d,
const uint8_t *e,
uint8_t *shared_secret,
int *result));

/**
* \brief Shuts down the ECC driver and unlocks the mutex.
*/
Expand Down
2 changes: 1 addition & 1 deletion os/net/security/micro-ecc
Submodule micro-ecc updated 4 files
+11 −1 platform-specific.inc
+1 −5 types.h
+82 −41 uECC.c
+36 −0 uECC.h
24 changes: 24 additions & 0 deletions os/services/ecc/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,29 @@ static PT_THREAD(generate_shared_secret(const uint8_t *public_key,
PT_END(&protothread);
}
/*---------------------------------------------------------------------------*/
static PT_THREAD(generate_fhmqv_secret(const uint8_t *static_private_key,
const uint8_t *ephemeral_private_key,
const uint8_t *static_public_key,
const uint8_t *ephemeral_public_key,
const uint8_t *d,
const uint8_t *e,
uint8_t *shared_secret,
int *const result))
{
PT_BEGIN(&protothread);

*result = !uECC_shared_fhmqv_secret(static_private_key,
ephemeral_private_key,
static_public_key,
ephemeral_public_key,
d,
e,
shared_secret,
uecc_curve);

PT_END(&protothread);
}
/*---------------------------------------------------------------------------*/
static void
disable(void)
{
Expand All @@ -197,6 +220,7 @@ const struct ecc_driver ecc_driver = {
verify,
generate_key_pair,
generate_shared_secret,
generate_fhmqv_secret,
disable
};
/*---------------------------------------------------------------------------*/
Expand Down
Loading

0 comments on commit 7076055

Please sign in to comment.