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 Oct 21, 2024
1 parent 4e8c769 commit 8c91d93
Show file tree
Hide file tree
Showing 8 changed files with 403 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
114 changes: 113 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 @@ -1042,6 +1042,117 @@ static PT_THREAD(generate_shared_secret(
PT_END(protothreads);
}
/*---------------------------------------------------------------------------*/
static PT_THREAD(generate_fhmqv_secret(
uint8_t *shared_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,
int *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(protothreads);

/* 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(protothreads,
protothreads + 1,
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(protothreads);
}

/* s := ephemeral private key + d * static private key */
PT_SPAWN(protothreads,
protothreads + 1,
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(protothreads);
}

/* sigma := e x static public key */
PT_SPAWN(protothreads,
protothreads + 1,
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(protothreads);
}

/* sigma := ephemeral public key + e x static public key */
PT_SPAWN(protothreads,
protothreads + 1,
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(protothreads);
}

/* sigma := s x (ephemeral public key + e x static public key) */
PT_SPAWN(protothreads,
protothreads + 1,
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(protothreads);
}

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

PT_END(protothreads);
}
/*---------------------------------------------------------------------------*/
static void
disable(void)
{
Expand All @@ -1064,6 +1175,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
154 changes: 154 additions & 0 deletions examples/libs/ecc/fhmqv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* 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 spkA[ECC_CURVE_SIZE * 2];
static uint8_t sskA[ECC_CURVE_SIZE];
static uint8_t epkA[ECC_CURVE_SIZE * 2];
static uint8_t eskA[ECC_CURVE_SIZE];
static uint8_t spkB[ECC_CURVE_SIZE * 2];
static uint8_t sskB[ECC_CURVE_SIZE];
static uint8_t epkB[ECC_CURVE_SIZE * 2];
static uint8_t eskB[ECC_CURVE_SIZE];
static uint8_t d[SHA_256_DIGEST_LENGTH];
static uint8_t e[SHA_256_DIGEST_LENGTH];
static uint8_t kA[ECC_CURVE_SIZE];
static uint8_t kB[ECC_CURVE_SIZE];

PROCESS_BEGIN();

/* enable ECC driver */
ECC_WAIT_UNTIL_ENABLED(process_pt, ECC_CURVE, PROCESS_EXIT());

LOG_INFO("generating key pairs\n");
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(sskA, spkA, &result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(eskA, epkA, &result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(sskB, spkB, &result));
if(result) {
LOG_ERR("generate_key_pair failed\n");
PROCESS_EXIT();
}
PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_key_pair(eskB, epkB, &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(epkA, sizeof(epkA));
SHA_256.update(epkB, sizeof(epkB));
SHA_256.update(spkA, sizeof(spkA));
SHA_256.update(spkB, sizeof(spkB));
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(kB,
sskB,
eskB,
spkA,
epkA,
e,
d,
&result));
if(result) {
LOG_ERR("ECC.generate_fhmqv_secret failed\n");
PROCESS_EXIT();
}

PROCESS_PT_SPAWN(ECC.get_protothread(),
ECC.generate_fhmqv_secret(kA,
sskA,
eskA,
spkB,
epkB,
d,
e,
&result));
if(result) {
LOG_ERR("ECC.generate_fhmqv_secret failed\n");
PROCESS_EXIT();
}

ECC.disable();

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

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

/**
* \brief Generates a shared secret as per FHMQV.
* \param shared_secret The resultant n-byte shared secret.
* \param static_private_key Our long-term n-byte private key.
* \param ephemeral_private_key Our ephemeral n-byte private key.
* \param static_public_key Their long-term 2n-byte public key.
* \param ephemeral_public_key Their ephemeral 2n-byte public key.
* \param d The n-byte FHMQV parameter d.
* \param e The n-byte FHMQV parameter e.
* \param result 0 on success.
*/
PT_THREAD((* generate_fhmqv_secret)(uint8_t *shared_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,
int *result));

/**
* \brief Shuts down the ECC driver.
*/
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
+70 −41 uECC.c
+35 −0 uECC.h
25 changes: 25 additions & 0 deletions os/services/ecc/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,30 @@ static PT_THREAD(generate_shared_secret(
PT_END(&protothread);
}
/*---------------------------------------------------------------------------*/
static PT_THREAD(generate_fhmqv_secret(
uint8_t *shared_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,
int *result))
{
PT_BEGIN(&protothread);

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

PT_END(&protothread);
}
/*---------------------------------------------------------------------------*/
static void
disable(void)
{
Expand All @@ -201,6 +225,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 8c91d93

Please sign in to comment.