📄 emSecure-RSA User Guide & Reference Manual
📄 emSSH User Guide & Reference Manual
📄 emSSL User Guide & Reference Manual
📄 emUSB-Device User Guide & Reference Manual
📄 emUSB-Host User Guide & Reference Manual
📄 emWeb User Guide & Reference Manual
📄 emWin User Guide & Reference Manual
📄 IoT Toolkit User Guide & Reference Manual
📄 SEGGER Assembler User Guide & Reference Manual
📄 SEGGER Floating-point Library User Guide & Reference Manual
📄 SEGGER Linker User Guide & Reference Manual
📄 SEGGER Runtime Library User Guide & Reference Manual
📄 AppWizard User Guide & Reference Manual
📄 embOS & embOS-MPU User Guide & Reference Manual
📄 emCompress-Embed User Guide & Reference Manual
📄 emCompress-Flex User Guide & Reference Manual
📄 emCompress-ToGo User Guide & Reference Manual
📄 emCrypt User Guide & Reference Manual
📄 emDropbox User Guide & Reference Manual
📄 emFile User Guide & Reference Manual
📄 emNet User Guide & Reference Manual
📄 emSecure-ECDSA User Guide & Reference Manual

emSecure-ECDSA User Guide & Reference Manual

Digital signature suite.

Introduction to emSecure-ECDSA

This section presents an overview of emSecure-ECDSA, its structure, and its capabilities.

What is emSecure-ECDSA?

emSecure-ECDSA is a SEGGER software package that allows creation and verification of digital signatures. One important feature is that emSecure-ECDSA can make it impossible to create a clone of an embedded device by simply copying hardware and firmware.

And it can do much more, such as securing firmware updates distributed to embedded devices and authenticating licenses, serial numbers, and sensitive data.

emSecure-ECDSA offers 100% protection against hacking. It is not just nice to have, but in fact a must-have, not only for critical devices such as election machines, financial applications, or sensors.

Compromised devices are dangerous in several ways, not just from a commercial point of view. They hamper manufacturers’ reputation and might entail severe legal disputes. Not addressing the issue of hacking and cloning is irresponsible.

Based on asymmetric encryption algorithms with two keys, emSecure-ECDSA signatures cannot be forged by reverse engineering of the firmware. A secure, private key is used to generate the digital signature, whereas a second, public key is used to authenticate data by its signature. There is neither a way to get the private key from the public key, nor is it possible to generate a valid signature without the private key.

The emSecure-ECDSA source code has been created from scratch for embedded systems, to achieve highest portability with a small memory footprint and high performance. However, usage is not restricted to embedded systems.

With its easy usage, it takes less than one day to add and integrate emSecure-ECDSA into an existing product. emSecure-ECDSA is a very complete package, including ready-to-run tools and functionality for generation of keys and signatures.

Why should I use emSecure-ECDSA?

emSecure-ECDSA offers a fast and easy way to prevent hacking and cloning of products. Not addressing the issue of hacking and cloning would be irresponsible.

Security consideration

If you want to check the integrity of your data, for instance the firmware running on your product, you would normally include a checksum or hash value into it, generated by a CRC or SHA function. Hashes are excellent at ensuring a critical data transmission, such as a firmware download, has worked flawlessly and to verify that an image, stored in memory, has not changed. However they do not add much security, as an attacker can easily compute the hash value of modified data or images.

Digital signatures can do more. In addition to the integrity check, which is provided by hash functions, a digital signature assures the authenticity of the provider of the signed data, as only he can create a valid signature. emSecure-ECDSA creates digital signatures using the modern Elliptic Curve Digital Signature Algorithm.

emSecure-ECDSA can be used for two security approaches:

Features

emSecure-ECDSA is written in standard ANSI C and can run on virtually any CPU. Here’s a list summarising the main features of emSecure-ECDSA:

We recommend keeping emSecure-ECDSA separate from your application files. It is good practice to keep all the source files (including the header files) together in the subdirectories of your project’s root directory as they are shipped. This practice has the advantage of being very easy to update to newer versions of emSecure-ECDSA by simply replacing the directories. Your application files can be stored anywhere.

Note

When updating to a newer emSecure-ECDSA version: as files may have been added, moved or deleted, the project directories may need to be updated accordingly.

Package content

emSecure-ECDSA is provided in source code and contains everything needed. The following table shows the content of the emSecure-ECDSA Package:

Files Description
Application emSSL sample applications for bare metal and embOS.
Config Configuration header files.
Doc emSecure-ECDSA documentation.
CRYPTO Shared cryptographic library source code.
SECURE emSecure-ECDSA implementation code.
SEGGER SEGGER software component source code used in emSecure-ECDSA.
Sample/Config Example emSecure-ECDSA configuration.
Sample/Keys Example emSecure-ECDSA key pairs.
Windows Supporting applications in binary and source form.

Include directories

You should make sure that the include path contains the following directories (the order of inclusion is of no importance):

Note

Always make sure that you have only one version of each file!

It is frequently a major problem when updating to a new version of emSecure-ECDSA if you have old files included and therefore mix different versions. If you keep emSecure-ECDSA in the directories as suggested (and only in these), this type of problem cannot occur. When updating to a newer version, you should be able to keep your configuration files and leave them unchanged. For safety reasons, we recommend backing up (or at least renaming) the SECURE directories before to updating.

Working with emSecure-ECDSA

This chapter gives some recommendations on how to use emSecure-ECDSA in your applications. It explains the steps of “emSecuring” a product.

Introduction

emSecure-ECDSA is created to be simple but powerful, and easy to integrate. It can be used in new products and even extend existing ones as emSecure-ECDSA is a software solution and no additional hardware is required. The code is completely written in ANSI C and can be used platform- and controller-independent.

emSecure-ECDSA has been created from scratch to achieve highest portability and performance with a very small memory footprint. It enables you to profit from the security of digital signatures in embedded applications, even on small single-chip microcontrollers without the need of additional hardware such as external security devices or external memory.

emSecure-ECDSA is a complete package. It includes ready-to-run tools to generate keys and signatures, to sign and verify data and to convert the keys and signatures into compilable formats.

The required key pairs can be generated with the included tool. The generated keys can be exported into different formats to be stored on the application code or loaded from a key file. This allows portability and exchangeability between different platforms.

Signing data, for instance firmware images, can be done with the included tool. It is also possible to integrate the signing process directly into a production application running on any PC or even on a microcontroller.

Once a signature is generated, the signed data can be verified by its signature in an embedded application or on an external application communicating with the device. Verifying data takes less than 190 ms on a Cortex-M4, running at 200 MHz, which is not significantly more time for a bootloader to start a firmware.

emSecure-ECDSA includes all required source code to integrate signature generation directly into your production process and data verification into your application or firmware.

emSecure-ECDSA incorporates proven security algorithms as proposed by NIST. The algorithms are proven to be cryptographically strong and can provide a maximum of security to your applications.

emSecure-ECDSA is licensed in the same way as other SEGGER middleware products and not covered by an open-source or required-attribution license. It can be integrated in any commercial or proprietary product without the obligation to disclose the combined source. It can be used royalty-free in your product.

Anti-hacking

Authentication of firmware

To make sure only authorized firmware images are run on a product the firmware image will be signed with emSecure-ECDSA. To do this an emSecure-ECDSA key pair is generated one time.

The private key will be included in the production process of the firmware. Once a firmware is created and ready to be shipped or included into a product it will be signed with this private key. The signature will be transferred and stored in the product alongside the firmware.

Signing firmware

The public key will be included in the bootloader of the product, which manages firmware updates and starts the firmware.

On a firmware update and when starting the product, the bootloader will verify the firmware by its signature. If they match, the firmware is started, otherwise the application will stay in the bootloader or even erase the firmware.

Verifying firmware

Anti-cloning

Authentication of hardware

To make sure a product cannot be re-produced by non-authorized manufacturers, by simply copying the hardware, emSecure-ECDSA will be used to sign each genuine product unit.

First an emSecure-ECDSA key pair is generated one time. This is likely done at the production site.

Signing firmware for a specific device

The private key will be included in the production process of the product. At the end of the production process, after the unit is assembled and tested, some hardware-specific, fixed, and unique data, like the unique id of the microcontroller is read from the unit. This data is signed by emSecure-ECDSA with the private key and the signature is written back to the unit into an OTP area or a specified location on memory.

The public key will be included in the firmware which will run on the product. When the firmware is running it will read the unique data from the unit and verify it with the signature. When the signature does not match, for example, when it was simply copied to a counterfeit unit with other unique data, the firmware will refuse to run.

Verifying firmware for a specific device

Additional measures to keep the system secure

When it comes to the degree of security emSecure-ECDSA offers, there is an easy answer: It is unbreakable because no one can generate a valid signature without knowledge of the private key.

Putting enough effort into getting the bootloader or firmware image, disassembling and analyzing it and modifying the application to bypass the security measures, hackers might be able to clone a product or use alternative firmware images. However this will only work until a firmware update is done.

There are additional ways to increase overall system security:

Signature strength

The strength of an ECDSA signature directly depends upon the elliptic curve chosen for the digital signature: more bits in the curve’s prime make the signature stronger, but also longer.

Included applications

This chapter describes the applications which are part of the emSecure-ECDSA package. The executables can be found at \Windows\SECURE\. The source code of the basic utilities is included. For the source code of the key generator, please contact SEGGER: mailto:info@segger.com.

emSecure-ECDSA Key Generator

emSecure-ECDSA KeyGen generates an ECDSA public and a private key. The generation parameters can be set via command line options. The keys are saved in a common key file format and can be published and exchanged.

Usage

emKeyGenECDSA.exe [<Options>]

Command line options

emSecure-ECDSA KeyGen accepts the following command line options.

Option Description
-h Print usage information and available command line options.
-q Operate silently and do not print log output.
-v Increase verbosity of log output.
-k string Set the key file prefix to string. Default is “emSecure”.
-pn Selects the NIST prime curve P-arg which has arg bits in its base prime. The five prime curves supported by emSecure-ECDSA are P-192, P-224, P-256, P-384, and P-521.

Utilities

emSecure-ECDSA includes all basic applications required for securing a product. The applications’ source-code is included and provides an easy to use starting point for modifications and integration into other applications.

emSecure-ECDSA Sign

emSignECDSA digitally signs the file content, usually the data to be secured, with a given (private) key file and creates a signature file.

Usage

emSignECDSA.exe [<Options>] <InputFile>

Command line options

Option Description
-h Print usage information and available command line options.
-q Operate silently and do not print log output.
-v Increase verbosity of log output.
-k string Set the key file prefix to string. Default is “emSecure”.
-d Use RFC 6979 deterministic ECDSA. Default.
-nd Use random “secure k” signing.

emSecure-ECDSA Verify

emVerifyECDSA accepts a signature file and verifies if the corresponding data file matches the signature.

Usage

emVerifyECDSA.exe [<Options>] <InputFile>

Command line options

Option Description
-h Print usage information and available command line options.
-q Operate silently and do not print log output.
-v Increase verbosity of log output.
-k string Set the key file prefix to string. Default is “emSecure”.

emSecure-ECDSA Print Key

emPrintKeyECDSA exports key and signature files into a format suitable for compilation by a standard C compiler. The output can be linked into your application, so there is no need to load them from a file at runtime. This is especially useful for embedded applications.

Usage

emPrintKeyECDSA.exe [<Options>] <Input-File>

Command line options

emSecure-ECDSA PrintKey accepts the following command line options.

Option Description
-v Increase verbosity of log output.
-x Define objects with external linkage.
-p string Prefix object names with string. Default is “_”.

emSecure-ECDSA walkthrough

This section will walk you through generating keys, installing those in an application, and then signing some data and verifying that the signature operation succeeded.

Generating the keys

Before signing anything, you must generate a set of keys that can sign data and verify the generated signatures. The tool emKeyGenECDSA will construct the keys for you: they are generated using secure random numbers such that they are strong.

To use emKeyGenECDSA you must choose the elliptic curve that the signature scheme will use. Curves that have longer base primes offer stronger signatures but also require more storage and computation in order to both sign and verify.

The curves you can select from are:

In this example we will choose the curve P-256 as it offers excellent security whilst having modest performance and memory requirements.

Generating the keys is a matter of running emKeyGenECDSA specifying P-256 and the curve:

C:> emKeyGenECDSA -p256

(c) 2014-2015 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA KeyGen V2.38 compiled May 17 2018 10:43:55

Writing public key file emSecure.pub.
Writing private key file emSecure.prv.

C:> _

The two files that are written contain the public key and the private key, together making a matched key pair. The private key is required when signing some data and must be kept private and secure. The public key is required when verifying some signed data and can be distributed without concern for privacy.

Testing the keys

You can test out the keys by signing and verifying a small text file:

C:> dir >test.txt
C:> emSignECDSA test.txt

(c) 2014-2015 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA Sign V2.38 compiled May 17 2018 10:43:55

Loading private key from emSecure.prv
Probing file to determine type of key: ECDSA key detected
Elliptic curve is P-256
Loading content from test.txt
Loaded content is 790 bytes
Writing ECDSA signature file test.txt.sig

C:> _

Once signed, you can verify the signature:

C:> emVerifyECDSA test.txt

(c) 2014-2015 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA Verify V2.38 compiled May 17 2018 10:43:55

Loading public key from emSecure.pub
Probing file to determine type of key: ECDSA key detected
Elliptic curve is P-256
Loading ECDSA signature from test.txt.sig
Loading content from test.txt
Loaded content is 790 bytes
Signature OK.

C:> _

If you tamper with the signature or alter the original file, even by one bit, the alteration is detected and the signature is not verified:

C:> edit test.txt
C:> emVerifyECDSA test.txt

(c) 2014-2015 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA Verify V2.38 compiled May 17 2018 10:43:55

Loading public key from emSecure.pub
Probing file to determine type of key: ECDSA key detected
Elliptic curve is P-256
Loading ECDSA signature from test.txt.sig
Loading content from test.txt
Loaded content is 790 bytes
Signature NOT VERIFIED!

C:> _

Signing and verifying in your application

Now that you have a pair of keys, it’s time to integrate them into your program. You can do that by using emPrintKeyECDSA which converts the textual form of the key into something that a C program can use.

First we convert the private and public keys into C declarations:

C:> emPrintKeyECDSA -p _SECURE_ECDSA_PrivateKey_P256 emSecure.prv \
      >SECURE_ECDSA_PrivateKey_P256.h
C>> emPrintKeyECDSA -p _SECURE_ECDSA_PrivateKey_P256 emSecure.pub \
      >SECURE_ECDSA_PublicKey_P256.h
C:> _

The generated output contains declarations in a format suitable for direct inclusion into C program. The -p option sets the prefix for the names of the generated C identifiers.

Now we have the keys, we can write a program that uses the private key to sign an message and a public key to verify it:

/*********************************************************************
*                   (c) SEGGER Microcontroller GmbH                  *
*                        The Embedded Experts                        *
*                           www.segger.com                           *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File        : CRYPTO_ECDSA_Example1.c
Purpose     : Sign and verify a message.

Additional information:
  Preparations:
    None.

  Expected behavior:
    Signs and verifies an encrypted message using the Elliptic Curve
    Digital Signature Algorithm (ECSDA).
    For more detailed information see the emSecure ECSDA manual.

  Sample output:
    Signed message...SUCCESS!
    Verified message is correctly signed...SUCCESS!

*/

/*********************************************************************
*
*       #include section
*
**********************************************************************
*/

#include "SECURE_ECDSA.h"
#include "SECURE_ECDSA_PrivateKey_P256.h"
#include "SECURE_ECDSA_PublicKey_P256.h"
#include <stdio.h>

/*********************************************************************
*
*       Static const data
*
**********************************************************************
*/

static const U8 _aMessage[]       = { "This is a message, sign me." };

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

static U8 _aSignature[64];

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

static int _Sign(void) {
  return SECURE_ECDSA_Sign(&_SECURE_ECDSA_PrivateKey_P256,
                           &_aMessage[0],   sizeof(_aMessage),
                           &_aSignature[0], sizeof(_aSignature));
}

static int _Verify(void) {
  return SECURE_ECDSA_Verify(&_SECURE_ECDSA_PublicKey_P256,
                             &_aMessage[0],   sizeof(_aMessage),
                             &_aSignature[0], sizeof(_aSignature));
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

int main(void) {
  if (_Sign() > 0) {
    printf("Signed message...SUCCESS!\n");
    if (_Verify() > 0) {
      printf("Verified message is correctly signed...SUCCESS!\n");
    } else {
      printf("Correctly signed message did not verify...ERROR!\n");
    }
  } else {
    printf("Failed to sign message...ERROR!\n");
  }
  return 0;
}

/*************************** End of file ****************************/

The private key is defined as a constant SECURE_ECDSA_PrivateKey_P256 in SECURE_ECDSA_PrivateKey_P256.h The public key is defined as a constant SECURE_ECDSA_PublicKey_P256 in SECURE_ECDSA_PublicKey_P256.h

If you compile and run this application, you will see this output:

C:> SECURE_ECDSA_Example1
Signed message...SUCCESS!
Verified message is correctly signed...SUCCESS!

C:> _

If you tamper with the signature or the message, the signature is detected as invalid. For instance, altering the program like this…

if (_Sign() > 0) {
  printf("Signed message...SUCCESS!\n");
  _aMessage[0]++;
  if (_Verify() > 0) {

…causes verification to fail:

C:> SECURE_ECDSA_Example1
Signed message...SUCCESS!
Correctly signed message did not verify...ERROR!

C:> _

Incremental sign and verify

The previous example shows how to sign and verify a complete message. However, it may well be that the message to sign or verify is not able to entirely fit into the microcontroller’s memory. If this is the case, emSecure-ECDSA offers the ability to compute the message signature and verify that signature incrementally.

Incrementally signing and verifying a message is very straightforward:

The following example shows show this is achieved:

/*********************************************************************
*                   (c) SEGGER Microcontroller GmbH                  *
*                        The Embedded Experts                        *
*                           www.segger.com                           *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File        : CRYPTO_RSA_Example2.c
Purpose     : Incrementally sign and verify a message.

Additional information:
  Preparations:
    None.

  Expected behavior:
    Incrementally signs and verifies an encrypted message split over
    several parts using the Elliptic Curve Digital Signature
    Algorithm (ECSDA).
    For more detailed information see the emSecure ECSDA manual.

  Sample output:
    Signed message...SUCCESS!
    Verified message is correctly signed...SUCCESS!

*/

/*********************************************************************
*
*       #include section
*
**********************************************************************
*/

#include "SECURE_ECDSA.h"
#include "SECURE_ECDSA_PrivateKey_P256.h"
#include "SECURE_ECDSA_PublicKey_P256.h"
#include <stdio.h>

/*********************************************************************
*
*       Static const data
*
**********************************************************************
*/

static const U8 _aMessagePart1[]       = { "This is a message, " };
static const U8 _aMessagePart2[]       = { "sign me." };

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

static U8 _aSignature[64];

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

static int _Sign(void) {
  SECURE_ECDSA_HASH_CONTEXT Context;
  //
  // Sign message incrementally.
  //
  SECURE_ECDSA_HASH_Init(&Context);
  SECURE_ECDSA_HASH_Add (&Context, &_aMessagePart1[0], sizeof(_aMessagePart1));
  SECURE_ECDSA_HASH_Add (&Context, &_aMessagePart2[0], sizeof(_aMessagePart2));
  //
  return SECURE_ECDSA_HASH_Sign(&Context,
                                &_SECURE_ECDSA_PrivateKey_P256,
                                &_aSignature[0], sizeof(_aSignature));
}

static int _Verify(void) {
  SECURE_ECDSA_HASH_CONTEXT Context;
  //
  // Verify message incrementally.
  //
  SECURE_ECDSA_HASH_Init(&Context);
  SECURE_ECDSA_HASH_Add (&Context, &_aMessagePart1[0], sizeof(_aMessagePart1));
  SECURE_ECDSA_HASH_Add (&Context, &_aMessagePart2[0], sizeof(_aMessagePart2));
  //
  return SECURE_ECDSA_HASH_Verify(&Context,
                                  &_SECURE_ECDSA_PublicKey_P256,
                                  &_aSignature[0], sizeof(_aSignature));
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

int main(void) {
  if (_Sign() > 0) {
    printf("Signed message...SUCCESS!\n");
    if (_Verify() > 0) {
      printf("Verified message is correctly signed...SUCCESS!\n");
    } else {
      printf("Correctly signed message did not verify...ERROR!\n");
    }
  } else {
    printf("Failed to sign message...ERROR!\n");
  }
  return 0;
}

/*************************** End of file ****************************/

API reference

This section describes the public API for emSecure-ECDSA. Any functions or data structures that are not described here but are exposed through inclusion of the SECURE_ECDSA.h header file must be considered private and subject to change.

Preprocessor symbols

Version number

Description

Symbol expands to a number that identifies the specific emSecure-ECDSA release.

Definition

#define SECURE_ECDSA_VERSION    24200

Symbols

Definition Description
SECURE_ECDSA_VERSION Format is “Mmmrr” so, for example, 23800 corresponds to version 2.38.

Elliptic curves

Declaration

extern const SECURE_ECDSA_CURVE SECURE_ECDSA_CURVE_P192;
extern const SECURE_ECDSA_CURVE SECURE_ECDSA_CURVE_P224;
extern const SECURE_ECDSA_CURVE SECURE_ECDSA_CURVE_P256;
extern const SECURE_ECDSA_CURVE SECURE_ECDSA_CURVE_P384;
extern const SECURE_ECDSA_CURVE SECURE_ECDSA_CURVE_P521;

Description

emSecure-ECDSA supports the following NIST prime elliptic curves:

C name NIST prime curve
SECURE_ECDSA_CURVE_P192 P-192
SECURE_ECDSA_CURVE_P224 P-224
SECURE_ECDSA_CURVE_P256 P-256
SECURE_ECDSA_CURVE_P384 P-384
SECURE_ECDSA_CURVE_P521 P-521

See also

SECURE_ECDSA_InitPublicKey, SECURE_ECDSA_InitPrivateKey

API functions

Function Description
Initialization
SECURE_ECDSA_Init() Initialize emSecure-ECDSA.
Complete message signature functions
SECURE_ECDSA_Sign() Sign message.
SECURE_ECDSA_Verify() Verify message.
Precomputed digest message signature functions
SECURE_ECDSA_SignDigest() Sign message digest.
SECURE_ECDSA_VerifyDigest() Verify message digest.
Incremental message signature functions
SECURE_ECDSA_HASH_Init() Initialize, incremental sign or verify.
SECURE_ECDSA_HASH_Add() Add message data to hash.
SECURE_ECDSA_HASH_Sign() Sign a message hash with a private key.
SECURE_ECDSA_HASH_Verify() Verify message, incremental.
Initialization functions
SECURE_ECDSA_InitPrivateKey() Initialize private key.
SECURE_ECDSA_InitPublicKey() Initialize public key.
Version information
SECURE_ECDSA_GetCopyrightText() Get copyright as printable string.
SECURE_ECDSA_GetVersionText() Get version as printable string.

SECURE_ECDSA_Init()

Description

Initialize emSecure-ECDSA.

Prototype

void SECURE_ECDSA_Init(void);

Additional information

If not already installed as part of CRYPTO initialization, install the software-implemented SHA-256 hash function.

SECURE_ECDSA_Sign()

Description

Sign message.

Prototype

int SECURE_ECDSA_Sign(const SECURE_ECDSA_PRIVATE_KEY * pPrivate,
                      const U8                       * pMessage,
                            int                        MessageLen,
                            U8                       * pSignature,
                            int                        SignatureLen);

Parameters

Parameter Description
pPrivate Pointer to the private key to sign the message with.
pMessage Pointer to message to sign.
MessageLen Octet length of the message to sign.
pSignature Pointer to buffer that received the generated signature.
SignatureLen Octet length of the signature buffer.

Return value

≤ 0 Signature failure (signature buffer too small).
> 0 Success, number of bytes written to the the signature buffer that constitute the signature.

Additional information

The signature buffer must be at least twice the number of bytes required for curve’s underlying prime field. For instance, the P-256 prime is 256 bits (32 bytes) hence the signature will require 64 bytes. The P-521 prime requires 66 bytes and the signature 132 bytes.

SECURE_ECDSA_Verify()

Description

Verify message.

Prototype

int SECURE_ECDSA_Verify(const SECURE_ECDSA_PUBLIC_KEY * pPublic,
                        const U8                      * pMessage,
                              int                       MessageLen,
                        const U8                      * pSignature,
                              int                       SignatureLen);

Parameters

Parameter Description
pPublic Pointer to public key used to verify the message.
pMessage Pointer to message to verify.
MessageLen Octet length of the message.
pSignature Pointer to signature to verify.
SignatureLen Octet length of the signature.

Return value

< 0 Processing error verifying signature, signature is not verified.
= 0 Processing successful, signature is not verified.
> 0 Processing successful, signature is verified.

Additional information

The signature buffer must be exactly twice the number of bytes required for the curve’s underlying prime field. For instance, the P-256 prime is 256 bits (32 bytes) hence the signature will require 64 bytes. The P-521 prime requires 66 bytes and the signature 132 bytes.

SECURE_ECDSA_SignDigest()

Description

Sign message digest.

Prototype

int SECURE_ECDSA_SignDigest(const SECURE_ECDSA_PRIVATE_KEY * pPrivate,
                            const U8                       * pDigest,
                                  U8                       * pSignature,
                                  int                        SignatureLen);

Parameters

Parameter Description
pPrivate Pointer to the private key to sign the digest with.
pDigest Pointer to octet string that is the digest of the message.
pSignature Pointer to buffer that receives the generated signature.
SignatureLen Octet length of the signature buffer.

Return value

≤ 0 Signature failure (signature buffer too small).
> 0 Success, number of bytes written to the the signature buffer that constitute the signature.

Additional information

The signature buffer must be at least twice the number of bytes required for curve’s underlying prime field. For instance, the P-256 prime is 256 bits (32 bytes) hence the signature will require 64 bytes. The P-521 prime requires 66 bytes and the signature 132 bytes.

SECURE_ECDSA_VerifyDigest()

Description

Verify message digest.

Prototype

int SECURE_ECDSA_VerifyDigest(const SECURE_ECDSA_PUBLIC_KEY * pPublic,
                              const U8                      * pDigest,
                              const U8                      * pSignature,
                                    int                       SignatureLen);

Parameters

Parameter Description
pPublic Pointer to public key used to verify the message.
pDigest Pointer to digest of the original message to be verified.
pSignature Pointer to signature to verify.
SignatureLen Octet length of the signature.

Return value

< 0 Processing error verifying signature, signature is not verified.
= 0 Processing successful, signature is not verified.
> 0 Processing successful, signature is verified.

Additional information

The signature buffer must be exactly twice the number of bytes required for the curve’s underlying prime field. For instance, the P-256 prime is 256 bits (32 bytes) hence the signature will require 64 bytes. The P-521 prime requires 66 bytes and the signature 132 bytes.

SECURE_ECDSA_InitPrivateKey()

Description

Initialize private key.

Prototype

void SECURE_ECDSA_InitPrivateKey(      SECURE_ECDSA_PRIVATE_KEY   * pPrivate,
                                 const SECURE_ECDSA_KEY_PARAMETER * pParamX,
                                 const SECURE_ECDSA_CURVE         * pCurve);

Parameters

Parameter Description
pPrivate Pointer to private key to be initialized.
pParamX Public key parameter X.
pCurve Elliptic curve that points are embedded on.

SECURE_ECDSA_InitPublicKey()

Description

Initialize public key.

Prototype

void SECURE_ECDSA_InitPublicKey(      SECURE_ECDSA_PUBLIC_KEY    * pPublic,
                                const SECURE_ECDSA_KEY_PARAMETER * pParamYX,
                                const SECURE_ECDSA_KEY_PARAMETER * pParamYY,
                                const SECURE_ECDSA_CURVE         * pCurve);

Parameters

Parameter Description
pPublic Pointer to public key to be initialized.
pParamYX Public key parameter Y (x coordinate).
pParamYY Public key parameter Y (y coordinate).
pCurve Elliptic curve that points are embedded on.

SECURE_ECDSA_HASH_Init()

Description

Initialize, incremental sign or verify.

Prototype

void SECURE_ECDSA_HASH_Init(SECURE_ECDSA_HASH_CONTEXT * pHash);

Parameters

Parameter Description
pHash Pointer to hash context.

SECURE_ECDSA_HASH_Add()

Description

Add message data to hash.

Prototype

void SECURE_ECDSA_HASH_Add(      SECURE_ECDSA_HASH_CONTEXT * pHash,
                           const void                      * pData,
                                 unsigned                    DataLen);

Parameters

Parameter Description
pHash Pointer to hash context.
pData Pointer to message fragment to add to hash.
DataLen Octet length of the message fragment.

SECURE_ECDSA_HASH_Sign()

Description

Sign a message hash with a private key.

Prototype

int SECURE_ECDSA_HASH_Sign(      SECURE_ECDSA_HASH_CONTEXT * pHash,
                           const SECURE_ECDSA_PRIVATE_KEY  * pPrivate,
                                 U8                        * pSignature,
                                 int                         SignatureLen);

Parameters

Parameter Description
pHash Pointer to hash context.
pPrivate Pointer to the private key to sign the message with.
pSignature Pointer to object that receives the generated signature.
SignatureLen Octet length of the signature buffer.

Return value

≤ 0 Signature failure (signature buffer too small).
> 0 Success, number of bytes written to the the signature buffer that constitute the signature.

Additional information

The signature buffer must be at least twice the number of bytes required for curve’s underlying prime field. For instance, the P-256 prime is 256 bits (32 bytes) hence the signature will require 64 bytes. The P-521 prime requires 66 bytes and the signature 132 bytes.

SECURE_ECDSA_HASH_Verify()

Description

Verify message, incremental.

Prototype

int SECURE_ECDSA_HASH_Verify(      SECURE_ECDSA_HASH_CONTEXT * pHash,
                             const SECURE_ECDSA_PUBLIC_KEY   * pPublic,
                             const U8                        * pSignature,
                                   int                         SignatureLen);

Parameters

Parameter Description
pHash Pointer to hash context.
pPublic Pointer to public key used to verify the message.
pSignature Pointer to signature to verify.
SignatureLen Octet length of the signature.

Return value

< 0 Processing error verifying signature, signature is not verified.
= 0 Processing successful, signature is not verified.
> 0 Processing successful, signature is verified.

SECURE_ECDSA_GetCopyrightText()

Description

Get copyright as printable string.

Prototype

char *SECURE_ECDSA_GetCopyrightText(void);

Return value

Zero-terminated copyright string.

SECURE_ECDSA_GetVersionText()

Description

Get version as printable string.

Prototype

char *SECURE_ECDSA_GetVersionText(void);

Return value

Zero-terminated version string.

Configuring emSecure-ECDSA

emSecure-ECDSA can be configured via preprocessor flags at compile-time. All compile-time configuration flags are preconfigured with valid values, which match the requirements of most applications.

In order to configure the shared memory component and to select the way that SHA-256 is compiled to balance code size and execution performance you can change the compile-time flags in the main configuration files CRYPTO_Conf.h and SEGGER_MEM_Conf.h.

The cryptography modules (prefixed CRYPTO_), and SEGGER modules (prefixed SEGGER_) are shared with other SEGGER products, for instance emSSL, and should be configured to match all modules which are used in the same application.

Algorithm parameters

Key length

Default

#define SECURE_ECDSA_MAX_KEY_LENGTH     256

This preprocessor symbol, if overridden, must be set in the configuration file SECURE_ECDSA_Conf.h.

Description

Configure the maximum length of keys. This define is used to reserve enough memory when signing or verifying a message.

The key length is in bits. If you are using P-256, for instance, set this to 256. If you intend to sign and verify signatures using P-521, set this to 521.

The default is 256 which supports any curve up to P-256.

Crytographic components

The following definitions must be set to configure the underlying cryptographic algorithm library, emCrypt.

The relevant sections of the emCrypt documentation are included here.

Multiprecision integers

Default

#define CRYPTO_MPI_BITS_PER_LIMB     32

Override

To define a non-default value, define this symbol in CRYPTO_Conf.h.

Description

This preprocessor symbol configures the number of bits per limb for multiprecision integer algorithms. The default of 32 matches 32-bit targets well, such as ARM and PIC32. In general, it is best to set the number of bits per limb to the number of bits in the standard int or unsigned type used by the target compiler.

Supported configurations are:

Twin multiply

Default

#define CRYPTO_CONFIG_ECDSA_TWIN_MULTIPLY     1

This preprocessor symbol, if overridden, must be set in the configuration file CRYPTO_Conf.h.

Description

Configure whether ECDSA signature verification uses twin point multiplication or discrete point multiplication. ECDSA signature verification speed approximately doubles when using twin point multiplication at the expense of additional memory.

SHA-256 hash algorithm

The following definitions can be set for the hash components in order to balance code size and performance.

Default

#define CRYPTO_CONFIG_SHA256_OPTIMIZE     0

Override

To define a non-default value, define this symbol in CRYPTO_Conf.h.

Description

Set this preprocessor symbol to zero to optimize the SHA-256 hash functions for size rather than for speed. When optimized for speed, the SHA-256 function is open coded and faster, but is significantly larger.

Profile

The following table shows required context size, lookup table (LUT) size, and code size in kilobytes for each configuration value. All values are approximate and for a Cortex-M3 processor.

Setting Context size LUT LUT size Code size Total size
0 0.17 KB Flash 0.3 KB 0.5 KB 0.8 KB
1 0.17 KB - - 7.7 KB 7.7 KB

Performance and resource use

This chapter describes the memory requirements and performance of emSecure-ECDSA.

Performance

ECDSA sign and verify performance can be benchmarked with the application SECURE_ECDSA_Bench_Performance.c.

Twin multiply enabled

The following is the output for the Cortex-M4 on a SEGGER emPower board when configured for twin mulitply:

(c) 2014-2018 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA Performance Benchmark compiled May 18 2018 18:44:15

Compiler: clang 4.0.0 (tags/RELEASE_400/final)
System:   Processor speed                   = 168.000 MHz
Config:   CRYPTO_VERSION                    = 20000 [2.00]
Config:   SECURE_ECDSA_VERSION              = 22000 [2.30]
Config:   CRYPTO_MPI_BITS_PER_LIMB          = 32
Config:   CRYPTO_CONFIG_ECDSA_TWIN_MULTIPLY = 1
Config:   CRYPTO_CONFIG_SHA1_OPTIMIZE       = 1
Config:   SECURE_ECDSA_MAX_KEY_LENGTH       = 521 bits

Sign/Verify Performance
=======================

+-----------+----------+----------+----------+
|     Curve |  Message |     Sign |   Verify |
|           |   /bytes |      /ms |      /ms |
+-----------+----------+----------+----------+
| secp192r1 |        0 |   156.86 |    73.93 |
| secp192r1 |     1024 |   161.29 |    72.36 |
| secp192r1 |   102400 |   200.60 |   116.78 |
+-----------+----------+----------+----------+
| secp224r1 |        0 |   200.20 |    93.73 |
| secp224r1 |     1024 |   193.83 |    91.91 |
| secp224r1 |   102400 |   238.60 |   135.00 |
+-----------+----------+----------+----------+
| secp256r1 |        0 |   298.00 |   142.25 |
| secp256r1 |     1024 |   308.25 |   140.12 |
| secp256r1 |   102400 |   348.33 |   181.67 |
+-----------+----------+----------+----------+
| secp384r1 |        0 |   504.50 |   234.40 |
| secp384r1 |     1024 |   515.50 |   235.40 |
| secp384r1 |   102400 |   539.00 |   279.00 |
+-----------+----------+----------+----------+
| secp521r1 |        0 |   899.50 |   421.33 |
| secp521r1 |     1024 |   906.00 |   419.67 |
| secp521r1 |   102400 |   940.50 |   464.67 |
+-----------+----------+----------+----------+

Benchmark complete

Twin multiply disabled

The following is the output for the Cortex-M4 on a SEGGER emPower board when configured with twin mulitply disabled:

(c) 2014-2018 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
emSecure-ECDSA Performance Benchmark compiled May 18 2018 18:48:33

Compiler: clang 4.0.0 (tags/RELEASE_400/final)
System:   Processor speed                   = 168.000 MHz
Config:   CRYPTO_VERSION                    = 20000 [2.00]
Config:   SECURE_ECDSA_VERSION              = 22000 [2.30]
Config:   CRYPTO_MPI_BITS_PER_LIMB          = 32
Config:   CRYPTO_CONFIG_ECDSA_TWIN_MULTIPLY = 0
Config:   CRYPTO_CONFIG_SHA1_OPTIMIZE       = 1
Config:   SECURE_ECDSA_MAX_KEY_LENGTH       = 521 bits

Sign/Verify Performance
=======================

+-----------+----------+----------+----------+
|     Curve |  Message |     Sign |   Verify |
|           |   /bytes |      /ms |      /ms |
+-----------+----------+----------+----------+
| secp192r1 |        0 |   158.14 |   153.71 |
| secp192r1 |     1024 |   162.57 |   149.43 |
| secp192r1 |   102400 |   201.60 |   194.83 |
+-----------+----------+----------+----------+
| secp224r1 |        0 |   200.40 |   183.83 |
| secp224r1 |     1024 |   194.17 |   189.67 |
| secp224r1 |   102400 |   238.60 |   231.00 |
+-----------+----------+----------+----------+
| secp256r1 |        0 |   291.25 |   284.50 |
| secp256r1 |     1024 |   301.50 |   296.50 |
| secp256r1 |   102400 |   341.67 |   323.50 |
+-----------+----------+----------+----------+
| secp384r1 |        0 |   495.00 |   480.00 |
| secp384r1 |     1024 |   505.50 |   490.33 |
| secp384r1 |   102400 |   529.50 |   528.00 |
+-----------+----------+----------+----------+
| secp521r1 |        0 |   888.00 |   892.00 |
| secp521r1 |     1024 |   894.00 |   873.50 |
| secp521r1 |   102400 |   928.50 |   931.50 |
+-----------+----------+----------+----------+

Benchmark complete

SECURE_ECDSA_Bench_Performance.c listing

/*********************************************************************
*                   (c) SEGGER Microcontroller GmbH                  *
*                        The Embedded Experts                        *
*                           www.segger.com                           *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File        : SECURE_ECDSA_Bench_Performance.c
Purpose     : Benchmark emSecure-ECDSA performance.

*/

/*********************************************************************
*
*       #include section
*
**********************************************************************
*/

#include "SECURE_ECDSA.h"
#include "SECURE_ECDSA_PrivateKey_P192.h"
#include "SECURE_ECDSA_PrivateKey_P224.h"
#include "SECURE_ECDSA_PrivateKey_P256.h"
#include "SECURE_ECDSA_PrivateKey_P384.h"
#include "SECURE_ECDSA_PrivateKey_P521.h"
#include "SECURE_ECDSA_PublicKey_P192.h"
#include "SECURE_ECDSA_PublicKey_P224.h"
#include "SECURE_ECDSA_PublicKey_P256.h"
#include "SECURE_ECDSA_PublicKey_P384.h"
#include "SECURE_ECDSA_PublicKey_P521.h"
#include "SEGGER_SYS.h"

/*********************************************************************
*
*       Local data types
*
**********************************************************************
*/

typedef struct {
  const CRYPTO_ECDSA_PRIVATE_KEY * pPrivateKey;
  const CRYPTO_ECDSA_PUBLIC_KEY  * pPublicKey;
  const U8                       * pMesssage;
  unsigned                         MessageLen;
} BENCH_PARA;

/*********************************************************************
*
*       Static const data
*
**********************************************************************
*/

static const U8 _aMessage_100k[100*1024] = {
  0x00,
};

static const BENCH_PARA _aBenchKeys[] = {
  { &_SECURE_ECDSA_PrivateKey_P192, &_SECURE_ECDSA_PublicKey_P192, _aMessage_100k,        0u },
  { &_SECURE_ECDSA_PrivateKey_P192, &_SECURE_ECDSA_PublicKey_P192, _aMessage_100k,     1024u },
  { &_SECURE_ECDSA_PrivateKey_P192, &_SECURE_ECDSA_PublicKey_P192, _aMessage_100k, 100*1024u },
  { NULL,                           NULL,                          NULL,                  0u },
  { &_SECURE_ECDSA_PrivateKey_P224, &_SECURE_ECDSA_PublicKey_P224, _aMessage_100k,        0u },
  { &_SECURE_ECDSA_PrivateKey_P224, &_SECURE_ECDSA_PublicKey_P224, _aMessage_100k,     1024u },
  { &_SECURE_ECDSA_PrivateKey_P224, &_SECURE_ECDSA_PublicKey_P224, _aMessage_100k, 100*1024u },
  { NULL,                           NULL,                          NULL,                  0u },
  { &_SECURE_ECDSA_PrivateKey_P256, &_SECURE_ECDSA_PublicKey_P256, _aMessage_100k,        0u },
  { &_SECURE_ECDSA_PrivateKey_P256, &_SECURE_ECDSA_PublicKey_P256, _aMessage_100k,     1024u },
  { &_SECURE_ECDSA_PrivateKey_P256, &_SECURE_ECDSA_PublicKey_P256, _aMessage_100k, 100*1024u },
  { NULL,                           NULL,                          NULL,                  0u },
  { &_SECURE_ECDSA_PrivateKey_P384, &_SECURE_ECDSA_PublicKey_P384, _aMessage_100k,        0u },
  { &_SECURE_ECDSA_PrivateKey_P384, &_SECURE_ECDSA_PublicKey_P384, _aMessage_100k,     1024u },
  { &_SECURE_ECDSA_PrivateKey_P384, &_SECURE_ECDSA_PublicKey_P384, _aMessage_100k, 100*1024u },
  { NULL,                           NULL,                          NULL,                  0u },
  { &_SECURE_ECDSA_PrivateKey_P521, &_SECURE_ECDSA_PublicKey_P521, _aMessage_100k,        0u },
  { &_SECURE_ECDSA_PrivateKey_P521, &_SECURE_ECDSA_PublicKey_P521, _aMessage_100k,     1024u },
  { &_SECURE_ECDSA_PrivateKey_P521, &_SECURE_ECDSA_PublicKey_P521, _aMessage_100k, 100*1024u },
};

/*********************************************************************
*
*       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;
}

/*********************************************************************
*
*       _BenchmarkSignVerify()
*
*  Function description
*    Count the number of signs and verifies completed in one second.
*
*  Parameters
*    pPara - Pointer to benchmark parameters.
*/
static void _BenchmarkSignVerify(const BENCH_PARA *pPara) {
  U8    aSignature[270];
  U64   OneSecond;
  U64   T0;
  U64   Elapsed;
  int   SignatureLen;
  int   Loops;
  int   Status;
  float Time;
  //
  SEGGER_SYS_IO_Printf("| %9s | %8u | ", pPara->pPublicKey->pCurve->aCurveName, pPara->MessageLen);
  //
  Loops = 0;
  OneSecond = SEGGER_SYS_OS_ConvertMicrosToTicks(1000000);
  T0 = SEGGER_SYS_OS_GetTimer();
  do {
    SignatureLen = SECURE_ECDSA_Sign(pPara->pPrivateKey,
                                     pPara->pMesssage, pPara->MessageLen,
                                     aSignature,       sizeof(aSignature));
    Elapsed = SEGGER_SYS_OS_GetTimer() - T0;
    ++Loops;
  } while (SignatureLen >= 0 && Elapsed < OneSecond);
  //
  Time = 1000.0f * _ConvertTicksToSeconds(Elapsed) / Loops;
  if (SignatureLen < 0) {
    SEGGER_SYS_IO_Printf("%8s | ", "-Fail-");
  } else {
    SEGGER_SYS_IO_Printf("%8.2f | ", Time);
  }
  //
  if (SignatureLen < 0) {
    SEGGER_SYS_IO_Printf("%8s |\n", "-Skip-");
  } else {
    Loops = 0;
    OneSecond = SEGGER_SYS_OS_ConvertMicrosToTicks(1000000);
    T0 = SEGGER_SYS_OS_GetTimer();
    do {
      Status = SECURE_ECDSA_Verify(pPara->pPublicKey,
                                   pPara->pMesssage, pPara->MessageLen,
                                   aSignature,       SignatureLen);
      Elapsed = SEGGER_SYS_OS_GetTimer() - T0;
      ++Loops;
    } while (Status >= 0 && Elapsed < OneSecond);
    //
    Time = 1000.0f * _ConvertTicksToSeconds(Elapsed) / Loops;
    if (Status <= 0) {
      SEGGER_SYS_IO_Printf("%8s |\n", "-Fail-");
    } else {
      SEGGER_SYS_IO_Printf("%8.2f |\n", Time);
    }
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       MainTask()
*
*  Function description
*    Main entry point for application to run all the tests.
*/
void MainTask(void);
void MainTask(void) {
  unsigned i;
  //
  SECURE_ECDSA_Init();
  SEGGER_SYS_Init();
  //
  SEGGER_SYS_IO_Printf("\n");
  SEGGER_SYS_IO_Printf("%s    www.segger.com\n", SECURE_ECDSA_GetCopyrightText());
  SEGGER_SYS_IO_Printf("emSecure-ECDSA Performance 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",
                                    (float)SEGGER_SYS_GetProcessorSpeed() / 1000000.0f);
  }
  SEGGER_SYS_IO_Printf("Config:   CRYPTO_VERSION                    = %u [%s]\n",
                                  CRYPTO_VERSION, CRYPTO_GetVersionText());
  SEGGER_SYS_IO_Printf("Config:   SECURE_ECDSA_VERSION              = %u [%s]\n",
                                  SECURE_ECDSA_VERSION, SECURE_ECDSA_GetVersionText());
  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("Config:   CRYPTO_CONFIG_SHA256_OPTIMIZE     = %u\n",
                                  CRYPTO_CONFIG_SHA256_OPTIMIZE);
  SEGGER_SYS_IO_Printf("Config:   SECURE_ECDSA_MAX_KEY_LENGTH       = %u bits\n",
                                  SECURE_ECDSA_MAX_KEY_LENGTH);
  SEGGER_SYS_IO_Printf("\n");
  //
  SEGGER_SYS_IO_Printf("Sign/Verify Performance\n");
  SEGGER_SYS_IO_Printf("=======================\n\n");
  //
  SEGGER_SYS_IO_Printf("+-----------+----------+----------+----------+\n");
  SEGGER_SYS_IO_Printf("|     Curve |  Message |     Sign |   Verify |\n");
  SEGGER_SYS_IO_Printf("|           |   /bytes |      /ms |      /ms |\n");
  SEGGER_SYS_IO_Printf("+-----------+----------+----------+----------+\n");
  for (i = 0; i < SEGGER_COUNTOF(_aBenchKeys); ++i) {
    if (_aBenchKeys[i].pPublicKey == NULL) {
      SEGGER_SYS_IO_Printf("+-----------+----------+----------+----------+\n");
    } else {
      _BenchmarkSignVerify(&_aBenchKeys[i]);
    }
  }
  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 ****************************/

Memory footprint

The following table lists the memory requirements of emSecure-ECDSA configured for operation using the P-256 curve. There are two components to the ROM use, one for the emSecure-ECDSA code and one for the emCrypt component that can be shared with other security products such as emSecure-RSA, emSSL, and emSSH.

Twin multiply disabled

Process ROM (SECURE) ROM (CRYPTO) Total ROM Static RAM
Sign only 0.26 KB 10.68 KB 10.94 KB 0.01 KB
Verify only 0.36 KB 9.34 KB 9.70 KB 0.01 KB
Sign and verify 0.70 KB 11.04 KB 11.74 KB 0.01 KB

Twin multiply enabled

Process ROM (SECURE) ROM (CRYPTO) Total ROM Static RAM
Sign only 0.26 KB 10.68 KB 10.94 KB 0.01 KB
Verify only 0.36 KB 10.00 KB 10.36 KB 0.01 KB
Sign and verify 0.70 KB 11.68 KB 12.38 KB 0.01 KB

Frequently asked questions

Appendix

Example key pair

The example key pair was generated with emKeyGenECDSA and used in the example walkthrough.

SECURE_ECDSA_PrivateKey_P256.h listing

static const CRYPTO_MPI_LIMB _SECURE_ECDSA_PrivateKey_P256_X_aLimbs[] = {
  CRYPTO_MPI_LIMB_DATA4(0x91, 0xC9, 0x0B, 0x85),
  CRYPTO_MPI_LIMB_DATA4(0x0F, 0x58, 0xD4, 0x46),
  CRYPTO_MPI_LIMB_DATA4(0x15, 0xA1, 0x3B, 0x4C),
  CRYPTO_MPI_LIMB_DATA4(0x17, 0x00, 0xEC, 0xE9),
  CRYPTO_MPI_LIMB_DATA4(0xC8, 0xB1, 0x62, 0x5A),
  CRYPTO_MPI_LIMB_DATA4(0x9F, 0x8D, 0x88, 0x8A),
  CRYPTO_MPI_LIMB_DATA4(0x52, 0x1F, 0x6C, 0xB5),
  CRYPTO_MPI_LIMB_DATA4(0x1E, 0x8D, 0x1B, 0xE0)
};

static const CRYPTO_ECDSA_PRIVATE_KEY _SECURE_ECDSA_PrivateKey_P256 = {
  { CRYPTO_MPI_INIT_RO(_SECURE_ECDSA_PrivateKey_P256_X_aLimbs) },
  &CRYPTO_EC_CURVE_secp256r1
};

SECURE_ECDSA_PublicKey_P256.h listing

static const CRYPTO_MPI_LIMB _SECURE_ECDSA_PublicKey_P256_YX_aLimbs[] = {
  CRYPTO_MPI_LIMB_DATA4(0x28, 0x59, 0x5E, 0x86),
  CRYPTO_MPI_LIMB_DATA4(0xAD, 0xED, 0x67, 0xC9),
  CRYPTO_MPI_LIMB_DATA4(0x82, 0x0A, 0x6B, 0x47),
  CRYPTO_MPI_LIMB_DATA4(0xA9, 0x44, 0x41, 0xC1),
  CRYPTO_MPI_LIMB_DATA4(0xD6, 0x46, 0xEE, 0x03),
  CRYPTO_MPI_LIMB_DATA4(0xB4, 0x69, 0x77, 0xDD),
  CRYPTO_MPI_LIMB_DATA4(0xF4, 0x82, 0x22, 0xB5),
  CRYPTO_MPI_LIMB_DATA4(0xA7, 0xE3, 0x75, 0xB9)
};

static const CRYPTO_MPI_LIMB _SECURE_ECDSA_PublicKey_P256_YY_aLimbs[] = {
  CRYPTO_MPI_LIMB_DATA4(0x28, 0xC5, 0xF6, 0xF9),
  CRYPTO_MPI_LIMB_DATA4(0x1D, 0x5F, 0xAB, 0x1C),
  CRYPTO_MPI_LIMB_DATA4(0x3C, 0x93, 0x5E, 0x34),
  CRYPTO_MPI_LIMB_DATA4(0x29, 0xB1, 0xB5, 0x94),
  CRYPTO_MPI_LIMB_DATA4(0xE1, 0xB7, 0x45, 0x2F),
  CRYPTO_MPI_LIMB_DATA4(0x2B, 0x4E, 0xD9, 0xAD),
  CRYPTO_MPI_LIMB_DATA4(0x38, 0xA1, 0xAE, 0x27),
  CRYPTO_MPI_LIMB_DATA4(0x57, 0x97, 0x7E, 0x5C)
};

static const CRYPTO_ECDSA_PUBLIC_KEY _SECURE_ECDSA_PublicKey_P256 = { {
  { CRYPTO_MPI_INIT_RO(_SECURE_ECDSA_PublicKey_P256_YX_aLimbs) },
  { CRYPTO_MPI_INIT_RO(_SECURE_ECDSA_PublicKey_P256_YY_aLimbs) },
  { CRYPTO_MPI_INIT_RO_ZERO },
  { CRYPTO_MPI_INIT_RO_ZERO },
  },
  &CRYPTO_EC_CURVE_secp256r1
};