Skip to main content
  • Products
  • Evaluate our Software
  • Downloads
  • Free Utilities
  • Purchase
  • Silicon Vendors
  • Support
  • About Us
  • Blog
  • Forum
  • Search
  • Jobs
  • Newsletter
  • Blog
  • Contact
  • Shop
  • emCrypt
  • ECDSA Benchmark

    ECDSA Benchmark
    Example applications

    Contact us
    Downloads
    Documentation
    SEGGER emCrypt

    Example application Benchmark ECDSA Sign & Verify

    /*********************************************************************
    *               (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 ****************************/
    • User manual
    • List of downloads
    • Update notification
    • Pricing
    • Support
    • Silicon vendor resources

    Headquarters

    SEGGER Microcontroller GmbH

    Ecolab-Allee 5
    40789 Monheim am Rhein, Germany
    info@segger.com
    Tel.: +49-2173-99312-0
    Fax: +49-2173-99312-28

    Locations

    USA: SEGGER Microcontroller Systems LLC

    Boston area
    101 Suffolk Lane
    Gardner, MA 01440, USA
    us-east@segger.com
    Tel.: +1-978-874-0299
    Fax: +1-978-874-0599

    Silicon Valley
    Milpitas, CA 95035, USA
    us-west@segger.com
    Tel.: +1-408-767-4068

    China: SEGGER Microcontroller China Co., Ltd.

    Room 218, Block A, Dahongqiaoguoji
    No. 133 Xiulian Road
    Minhang District, Shanghai 201199, China
    china@segger.com
    Tel.: +86-133-619-907-60

    ISO 9001 certified

    ISO 9001

    30+ years of experience

    First-class embedded software tools since 1992
    • Imprint
    • Disclaimer
    • Code of Conduct
    • Privacy Policy
    © 2025 SEGGER - All rights reserved.