/*********************************************************************
* (c) SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
* www.segger.com *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : CRYPTO_Bench_ECDSA.c
Purpose : Benchmark ECDSA sign and verify.
*/
/*********************************************************************
*
* #include section
*
**********************************************************************
*/
#include "CRYPTO_Int.h"
#include "SEGGER_MEM.h"
#include "SEGGER_SYS.h"
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
#define MAX_CHUNKS 30 // For twin multiplication
/*********************************************************************
*
* Local types
*
**********************************************************************
*/
// Maximum prime size is 521 bits, but require additional 63 bits
// for underlying fast prime field reduction.
typedef CRYPTO_MPI_LIMB MPI_UNIT[CRYPTO_MPI_LIMBS_REQUIRED(2*521+63)+2];
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
static MPI_UNIT _aUnits[MAX_CHUNKS];
static SEGGER_MEM_CONTEXT _MemContext;
static SEGGER_MEM_SELFTEST_HEAP _Heap;
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _ConvertTicksToSeconds()
*
* Function description
* Convert ticks to seconds.
*
* Parameters
* Ticks - Number of ticks reported by SEGGER_SYS_OS_GetTimer().
*
* Return value
* Number of seconds corresponding to tick.
*/
static float _ConvertTicksToSeconds(U64 Ticks) {
return SEGGER_SYS_OS_ConvertTicksToMicros(Ticks) / 1000000.0f;
}
/*********************************************************************
*
* _BenchmarkECDSASign()
*
* Function description
* Benchmark ECDSA sign.
*
* Parameters
* pCurve - Pointer to elliptic curve.
*/
static void _BenchmarkECDSASign(const CRYPTO_EC_CURVE *pCurve) {
CRYPTO_ECDSA_PRIVATE_KEY Private;
CRYPTO_ECDSA_PUBLIC_KEY Public;
CRYPTO_ECDSA_SIGNATURE Signature;
U8 aDigest[32] = { " SEGGER SEGGER SEGGER SEGGER " };
U64 OneSecond;
U64 T0;
U64 Elapsed;
int Loops;
int Status;
unsigned PeakBytes;
float Time;
//
// Make PC-lint quiet, it's dataflow analysis provides false positives.
//
Loops = 0;
Elapsed = 0;
PeakBytes = 0;
//
CRYPTO_ECDSA_InitPrivateKey(&Private, &_MemContext);
CRYPTO_ECDSA_InitPublicKey (&Public, &_MemContext);
CRYPTO_ECDSA_InitSignature (&Signature, &_MemContext);
//
CRYPTO_ECDSA_GenKeys (pCurve, &Private, &Public, &_MemContext);
//
OneSecond = SEGGER_SYS_OS_ConvertMicrosToTicks(1000000);
T0 = SEGGER_SYS_OS_GetTimer();
do {
//
_Heap.Stats.NumInUseMax = _Heap.Stats.NumInUse;
//
CRYPTO_CHECK(CRYPTO_ECDSA_SignDigest(pCurve, &Private, &aDigest[0], sizeof(aDigest), &Signature, &_MemContext));
if (Status == 0) {
SEGGER_SYS_IO_Printf("ERROR - Did not sign digest\n");
SEGGER_SYS_OS_Halt(100);
}
//
PeakBytes = SEGGER_MAX(PeakBytes, _Heap.Stats.NumInUseMax * CRYPTO_MPI_LimbAllocUnit * CRYPTO_MPI_BYTES_PER_LIMB);
//
CRYPTO_ECDSA_KillSignature(&Signature);
//
Elapsed = SEGGER_SYS_OS_GetTimer() - T0;
++Loops;
} while (Status >= 0 && Elapsed < OneSecond);
//
cleanup:
CRYPTO_ECDSA_KillPrivateKey(&Private);
CRYPTO_ECDSA_KillPublicKey (&Public);
CRYPTO_ECDSA_KillSignature (&Signature);
//
if (Status < 0 || Loops == 0) {
SEGGER_SYS_IO_Printf("%10s |", "-Fail-");
} else {
Loops *= 2; // Two agreements per loop
Time = 1000.0f * _ConvertTicksToSeconds(Elapsed) / Loops;
SEGGER_SYS_IO_Printf("%10.2f |", Time);
SEGGER_SYS_IO_Printf("%10d |", PeakBytes);
}
}
/*********************************************************************
*
* _BenchmarkECDSAVerify()
*
* Function description
* Benchmark ECDSA verify.
*
* Parameters
* pCurve - Pointer to elliptic curve.
*/
static void _BenchmarkECDSAVerify(const CRYPTO_EC_CURVE *pCurve) {
CRYPTO_ECDSA_PRIVATE_KEY Private;
CRYPTO_ECDSA_PUBLIC_KEY Public;
CRYPTO_ECDSA_SIGNATURE Signature;
U8 aDigest[32] = { " SEGGER SEGGER SEGGER SEGGER " };
U64 OneSecond;
U64 T0;
U64 Elapsed;
int Loops;
int Status;
unsigned PeakBytes;
float Time;
//
// Make PC-lint quiet, it's dataflow analysis provides false positives.
//
Loops = 0;
Elapsed = 0;
PeakBytes = 0;
//
CRYPTO_ECDSA_InitPrivateKey(&Private, &_MemContext);
CRYPTO_ECDSA_InitPublicKey (&Public, &_MemContext);
CRYPTO_ECDSA_InitSignature (&Signature, &_MemContext);
//
CRYPTO_ECDSA_GenKeys (pCurve, &Private, &Public, &_MemContext);
//
CRYPTO_CHECK(CRYPTO_ECDSA_SignDigest(pCurve, &Private, &aDigest[0], sizeof(aDigest), &Signature, &_MemContext));
if (Status == 0) {
SEGGER_SYS_IO_Printf("ERROR - Did not sign digest\n");
SEGGER_SYS_OS_Halt(100);
}
//
OneSecond = SEGGER_SYS_OS_ConvertMicrosToTicks(1000000);
T0 = SEGGER_SYS_OS_GetTimer();
do {
//
_Heap.Stats.NumInUseMax = _Heap.Stats.NumInUse;
//
CRYPTO_CHECK(CRYPTO_ECDSA_VerifyDigest(pCurve, &Public, &aDigest[0], sizeof(aDigest), &Signature, &_MemContext));
if (Status == 0) {
SEGGER_SYS_IO_Printf("ERROR - Did not verify digest\n");
SEGGER_SYS_OS_Halt(100);
}
//
PeakBytes = SEGGER_MAX(PeakBytes, _Heap.Stats.NumInUseMax * CRYPTO_MPI_LimbAllocUnit * CRYPTO_MPI_BYTES_PER_LIMB);
//
Elapsed = SEGGER_SYS_OS_GetTimer() - T0;
++Loops;
} while (Status >= 0 && Elapsed < OneSecond);
//
cleanup:
CRYPTO_ECDSA_KillPrivateKey(&Private);
CRYPTO_ECDSA_KillPublicKey (&Public);
CRYPTO_ECDSA_KillSignature (&Signature);
//
if (Status < 0 || Loops == 0) {
SEGGER_SYS_IO_Printf("%10s |", "-Fail-");
} else {
Loops *= 2; // Two agreements per loop
Time = 1000.0f * _ConvertTicksToSeconds(Elapsed) / Loops;
SEGGER_SYS_IO_Printf("%10.2f |", Time);
SEGGER_SYS_IO_Printf("%10d |", PeakBytes);
}
}
/*********************************************************************
*
* _BenchmarkECDSA()
*
* Function description
* Benchmark ECDSA sign and verify.
*
* Parameters
* pCurve - Pointer to elliptic curve.
*/
static void _BenchmarkECDSA(const CRYPTO_EC_CURVE *pCurve) {
CRYPTO_MPI_SetChunkSize(CRYPTO_MPI_BYTES_REQUIRED(2*CRYPTO_MPI_BitCount(&pCurve->P)+63) + 2*CRYPTO_MPI_BYTES_PER_LIMB);
SEGGER_SYS_IO_Printf("| %-16s |", pCurve->aCurveName);
_BenchmarkECDSASign (pCurve);
_BenchmarkECDSAVerify(pCurve);
SEGGER_SYS_IO_Printf("\n");
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* MainTask()
*
* Function description
* Main entry point for application to run all the tests.
*/
void MainTask(void);
void MainTask(void) {
CRYPTO_Init();
CRYPTO_MPI_SetChunkSize(sizeof(MPI_UNIT));
SEGGER_SYS_Init();
SEGGER_MEM_SELFTEST_HEAP_Init(&_MemContext, &_Heap, _aUnits, MAX_CHUNKS, sizeof(MPI_UNIT));
//
SEGGER_SYS_IO_Printf("\n");
SEGGER_SYS_IO_Printf("(c) 2014-2017 SEGGER Microcontroller GmbH & Co. KG www.segger.com\n");
SEGGER_SYS_IO_Printf("ECDSA Sign and Verify Benchmark compiled " __DATE__ " " __TIME__ "\n\n");
//
SEGGER_SYS_IO_Printf("Compiler: %s\n", SEGGER_SYS_GetCompiler());
if (SEGGER_SYS_GetProcessorSpeed() > 0) {
SEGGER_SYS_IO_Printf("System: Processor speed = %.3f MHz\n", (double)SEGGER_SYS_GetProcessorSpeed() / 1000000.0f);
}
SEGGER_SYS_IO_Printf("Config: Static heap size = %u bytes\n", sizeof(_aUnits));
SEGGER_SYS_IO_Printf("Config: CRYPTO_MPI_BITS_PER_LIMB = %u\n", CRYPTO_MPI_BITS_PER_LIMB);
SEGGER_SYS_IO_Printf("Config: CRYPTO_CONFIG_ECDSA_TWIN_MULTIPLY = %u\n", CRYPTO_CONFIG_ECDSA_TWIN_MULTIPLY);
SEGGER_SYS_IO_Printf("\n");
//
SEGGER_SYS_IO_Printf("+------------------+-----------+-----------+-----------+-----------+\n");
SEGGER_SYS_IO_Printf("| | Sign | Sign | Verify | Verify |\n");
SEGGER_SYS_IO_Printf("| Curve | ms | bytes | ms | bytes |\n");
SEGGER_SYS_IO_Printf("+------------------+-----------+-----------+-----------+-----------+\n");
//
_BenchmarkECDSA(&CRYPTO_EC_CURVE_P192);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_P224);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_P256);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_P384);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_P521);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP160r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP160t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP192r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP192t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP224r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP224t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP256r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP256t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP320r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP320t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP384r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP384t1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP512r1);
_BenchmarkECDSA(&CRYPTO_EC_CURVE_brainpoolP512t1);
//
SEGGER_SYS_IO_Printf("+------------------+-----------+-----------+-----------+-----------+\n");
SEGGER_SYS_IO_Printf("\n");
//
SEGGER_SYS_IO_Printf("Benchmark complete\n");
SEGGER_SYS_OS_PauseBeforeHalt();
SEGGER_SYS_OS_Halt(0);
}
/*************************** End of file ****************************/