curve25519: strip-down, build and test

Keep only the most compact version of the curve25519 code
and remove the remaining unused code for easier compilation.
Do the minimal changes to make it compile in the EC code base,
there should be no real functional changes.

Re-use the wording from BoringSSL include/openssl/curve25519.h for the
header.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

BRANCH=none
BUG=chrome-os-partner:62991
TEST=run x25519 on host (ie 'make run-x25519')
and the STM32L4 target:
make BOARD=eve_fp PROJECT=x25519 TEST_BUILD=y
./util/flash_ec --board=eve_fp --image=build/eve_fp/x25519.bin
execute 'runtest' in the console.

Change-Id: I13dbe453eff39b461effb1b3ffa549afc1749fef
Reviewed-on: https://chromium-review.googlesource.com/444187
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Adam Langley <agl@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
(cherry picked from commit 0d858f1544)
Reviewed-on: https://chromium-review.googlesource.com/734796
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
This commit is contained in:
Vincent Palatin 2017-02-16 14:15:30 +01:00 committed by ChromeOS Commit Bot
parent f5f6e52282
commit b628bbd3ca
9 changed files with 246 additions and 4177 deletions

View File

@ -44,4 +44,11 @@ typedef uint8_t uint_least8_t;
#define INT32_MAX (2147483647U)
#endif
#ifndef UINT64_C
#define UINT64_C(c) c ## ULL
#endif
#ifndef INT64_C
#define INT64_C(c) c ## LL
#endif
#endif /* __CROS_EC_STDINT_H__ */

View File

@ -45,6 +45,7 @@ common-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic_output.o
common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o
common-$(CONFIG_COMMON_TIMER)+=timer.o
common-$(CONFIG_CRC8)+= crc8.o
common-$(CONFIG_CURVE25519)+=curve25519.o
common-$(CONFIG_DEVICE_STATE)+=device_state.o
common-$(CONFIG_DPTF)+=dptf.o
common-$(CONFIG_EXTENSION_COMMAND)+=extension.o

File diff suppressed because it is too large Load Diff

View File

@ -653,6 +653,10 @@
/* Support curve25519 public key cryptography */
#undef CONFIG_CURVE25519
/*****************************************************************************/
/* Support curve25519 public key cryptography */
#undef CONFIG_CURVE25519
/*****************************************************************************/
/* PMIC config */

62
include/curve25519.h Normal file
View File

@ -0,0 +1,62 @@
/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __CROS_EC_CURVE25519_H
#define __CROS_EC_CURVE25519_H
#include <stdint.h>
/* Curve25519.
*
* Curve25519 is an elliptic curve. See https://tools.ietf.org/html/rfc7748.
*/
/* X25519.
*
* X25519 is the Diffie-Hellman primitive built from curve25519. It is
* sometimes referred to as curve25519, but X25519 is a more precise
* name.
* See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748.
*/
#define X25519_PRIVATE_KEY_LEN 32
#define X25519_PUBLIC_VALUE_LEN 32
/**
* Generate a public/private key pair.
* @param out_public_value generated public key.
* @param out_private_value generated private key.
*/
void X25519_keypair(uint8_t out_public_value[32], uint8_t out_private_key[32]);
/**
* Diffie-Hellman function.
* @param out_shared_key
* @param private_key
* @param out_public_value
* @return one on success and zero on error.
*
* X25519() writes a shared key to @out_shared_key that is calculated from the
* given private key and the peer's public value.
*
* Don't use the shared key directly, rather use a KDF and also include the two
* public values as inputs.
*/
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peers_public_value[32]);
/**
* Compute the matching public key.
* @param out_public_value computed public key.
* @param private_key private key to use.
*
* X25519_public_from_private() calculates a Diffie-Hellman public value from
* the given private key and writes it to @out_public_value.
*/
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]);
#endif /* __CROS_EC_CURVE25519_H */

View File

@ -72,6 +72,7 @@ test-list-host += timer_dos
test-list-host += usb_pd
test-list-host += usb_pd_giveback
test-list-host += utils
test-list-host += x25519
endif
base32-y=base32.o
@ -120,3 +121,4 @@ timer_dos-y=timer_dos.o
usb_pd-y=usb_pd.o
usb_pd_giveback-y=usb_pd.o
utils-y=utils.o
x25519-y=x25519.o

View File

@ -241,6 +241,10 @@ enum nvmem_vars {
#define CONFIG_FLASH_NVMEM_VARS_USER_SIZE 600
#endif /* TEST_NVMEM_VARS */
#ifdef TEST_X25519
#define CONFIG_CURVE25519
#endif /* TEST_X25519 */
#ifndef __ASSEMBLER__
/* Callback function from charge_manager to send host event */
static inline void pd_send_host_event(int mask) { }

View File

@ -12,115 +12,156 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/curve25519.h>
#include "console.h"
#include "common.h"
#include "curve25519.h"
#include "test_util.h"
#include "timer.h"
#include "util.h"
#include "watchdog.h"
static bool TestX25519() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
static const uint8_t kScalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4,
};
static const uint8_t kPoint1[32] = {
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
};
static int test_x25519(void)
{
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
static const uint8_t scalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d,
0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd,
0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18,
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4,
};
static const uint8_t point1[32] = {
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b,
0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
};
static const uint8_t expected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90,
0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f,
0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7,
0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
};
static const uint8_t scalar2[32] = {
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c,
0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5,
0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4,
0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d,
};
static const uint8_t point2[32] = {
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3,
0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c,
0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e,
0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};
static const uint8_t expected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d,
0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8,
0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52,
0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
uint8_t out[32];
uint8_t out[32];
X25519(out, kScalar1, kPoint1);
X25519(out, scalar1, point1);
static const uint8_t kExpected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
};
if (memcmp(kExpected1, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test one failed.\n");
return false;
}
if (memcmp(expected1, out, sizeof(out)) != 0) {
ccprintf("X25519 test one failed.\n");
return 0;
}
static const uint8_t kScalar2[32] = {
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea,
0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d,
};
static const uint8_t kPoint2[32] = {
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95,
0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0,
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};
X25519(out, kScalar2, kPoint2);
X25519(out, scalar2, point2);
static const uint8_t kExpected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
if (memcmp(kExpected2, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test two failed.\n");
return false;
}
if (memcmp(expected2, out, sizeof(out)) != 0) {
ccprintf("X25519 test two failed.\n");
return 0;
}
return true;
return 1;
}
static bool TestX25519SmallOrder() {
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
};
static int test_x25519_small_order(void)
{
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
};
uint8_t out[32], private_key[32];
uint8_t out[32], private_key[32];
memset(private_key, 0x11, sizeof(private_key));
memset(private_key, 0x11, sizeof(private_key));
if (X25519(out, private_key, kSmallOrderPoint)) {
fprintf(stderr, "X25519 returned success with a small-order input.\n");
return false;
}
if (X25519(out, private_key, kSmallOrderPoint)) {
ccprintf("X25519 returned success with a small-order input.\n");
return 0;
}
return true;
return 1;
}
static bool TestX25519Iterated() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
static int test_x25519_iterated(void)
{
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
static const uint8_t expected[32] = {
0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
};
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
unsigned i;
unsigned i;
for (i = 0; i < 1000; i++) {
X25519(out, scalar, point);
memcpy(point, scalar, sizeof(point));
memcpy(scalar, out, sizeof(scalar));
}
for (i = 0; i < 1000; i++) {
watchdog_reload();
X25519(out, scalar, point);
memcpy(point, scalar, sizeof(point));
memcpy(scalar, out, sizeof(scalar));
}
static const uint8_t kExpected[32] = {
0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef,
0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60,
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
};
if (memcmp(expected, scalar, sizeof(expected)) != 0) {
ccprintf("Iterated X25519 test failed\n");
return 0;
}
if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
fprintf(stderr, "Iterated X25519 test failed\n");
return false;
}
return true;
return 1;
}
int main(int argc, char **argv) {
if (!TestX25519() ||
!TestX25519Iterated() ||
!TestX25519SmallOrder()) {
return 1;
}
static void test_x25519_speed(void)
{
static const uint8_t scalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d,
0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd,
0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18,
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4,
};
static const uint8_t point1[32] = {
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b,
0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
};
uint8_t out[32];
timestamp_t t0, t1;
printf("PASS\n");
return 0;
X25519(out, scalar1, point1);
t0 = get_time();
X25519(out, scalar1, point1);
t1 = get_time();
ccprintf("X25519 duration %ld us\n", t1.val - t0.val);
}
void run_test(void)
{
watchdog_reload();
if (!test_x25519() || !test_x25519_iterated() ||
!test_x25519_small_order()) {
test_fail();
return;
}
watchdog_reload();
/* do not check speed, just as a benchmark */
test_x25519_speed();
test_pass();
}

17
test/x25519.tasklist Normal file
View File

@ -0,0 +1,17 @@
/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK_TEST(n, r, d, s) where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
#define CONFIG_TEST_TASK_LIST