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
  • ECDH Key Agreement

    ECDH Key Agreement
    Performance benchmarks

    Contact us
    Downloads
    Documentation
    SEGGER emCrypt

    This benchmarks one end of an ECDH key agreement on a Kinetis K66 device with Cortex-M4 core running at 168 MHz from flash memory. All times are in milliseconds.

    Curve SEGGER Embedded Studio [1]
    Version 3.22 [ms]
    IAR Embedded Workbench [2]
    Version 8.11.1 [ms]
    Execution time
    Shorter is better
    secp192r1168.82192.04x1.14
    secp224r1190.39225.8x1.19
    secp256r1285.08337.88x1.19
    secp384r1477.45537.31x1.13
    secp521r1934.951104.28x1.18
    brainpoolP160r1198.93256.31x1.29
    brainpoolP160t1179.1231.65x1.29
    brainpoolP192r1262.99352.02x1.34
    brainpoolP192t1255.86320.01x1.25
    brainpoolP224r1347.8447.97x1.29
    brainpoolP224t1326.51406.66x1.25
    brainpoolP256r1492.47616.41x1.25
    brainpoolP256t1437.95549.88x1.26
    brainpoolP320r1721.92915.46x1.27
    brainpoolP320t1664.48847.24x1.28
    brainpoolP384r11172.361422.41x1.21
    brainpoolP384t11116.231310.96x1.17
    brainpoolP512r12154.362860.05x1.33
    brainpoolP512t12035.862573.09x1.26

    [1] Optimized for speed using -O3
    [2] Optimized for speed using -Ohs

    Benchmarks

    Compiler: clang 4.0.0

    (c) 2014-2017 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
    ECDH Key Agreement Benchmark compiled Jul  3 2017 14:04:05
    
    Compiler: clang 4.0.0 (tags/RELEASE_400/final)
    System:   Processor speed          = 168.000 MHz
    Config:   Static heap size         = 3256 bytes
    Config:   CRYPTO_MPI_BITS_PER_LIMB = 32
    
    This benchmarks both ends of an ECDH key agreement, but.
    timing is reported as the time for one end's calculation.
    
    +------------------+--------------+--------------+
    | Curve            | ms/Agreement |       Memory |
    +------------------+--------------+--------------+
    | secp192r1        |       168.82 |          704 |
    | secp224r1        |       190.39 |          792 |
    | secp256r1        |       285.08 |          880 |
    | secp384r1        |       477.45 |         1232 |
    | secp521r1        |       934.95 |         1628 |
    | brainpoolP160r1  |       198.93 |          616 |
    | brainpoolP160t1  |       179.10 |          616 |
    | brainpoolP192r1  |       262.99 |          704 |
    | brainpoolP192t1  |       255.86 |          704 |
    | brainpoolP224r1  |       347.80 |          792 |
    | brainpoolP224t1  |       326.51 |          792 |
    | brainpoolP256r1  |       492.47 |          880 |
    | brainpoolP256t1  |       437.95 |          880 |
    | brainpoolP320r1  |       721.92 |         1056 |
    | brainpoolP320t1  |       664.48 |         1056 |
    | brainpoolP384r1  |      1172.36 |         1232 |
    | brainpoolP384t1  |      1116.23 |         1232 |
    | brainpoolP512r1  |      2154.36 |         1584 |
    | brainpoolP512t1  |      2035.86 |         1584 |
    +------------------+--------------+--------------+

    Compiler: IAR icc 8.11.1

    (c) 2014-2017 SEGGER Microcontroller GmbH & Co. KG    www.segger.com
    ECDH Key Agreement Benchmark compiled Jul  3 2017 14:04:36
    
    Compiler: IAR icc 8.11.1
    System:   Processor speed          = 168.000 MHz
    Config:   Static heap size         = 3256 bytes
    Config:   CRYPTO_MPI_BITS_PER_LIMB = 32
    
    This benchmarks both ends of an ECDH key agreement, but.
    timing is reported as the time for one end's calculation.
    
    +------------------+--------------+--------------+
    | Curve            | ms/Agreement |       Memory |
    +------------------+--------------+--------------+
    | secp192r1        |       192.04 |          704 |
    | secp224r1        |       225.80 |          792 |
    | secp256r1        |       337.88 |          880 |
    | secp384r1        |       537.31 |         1232 |
    | secp521r1        |      1104.28 |         1628 |
    | brainpoolP160r1  |       256.31 |          616 |
    | brainpoolP160t1  |       231.65 |          616 |
    | brainpoolP192r1  |       352.02 |          704 |
    | brainpoolP192t1  |       320.01 |          704 |
    | brainpoolP224r1  |       447.97 |          792 |
    | brainpoolP224t1  |       406.66 |          792 |
    | brainpoolP256r1  |       616.41 |          880 |
    | brainpoolP256t1  |       549.88 |          880 |
    | brainpoolP320r1  |       915.46 |         1056 |
    | brainpoolP320t1  |       847.24 |         1056 |
    | brainpoolP384r1  |      1422.41 |         1232 |
    | brainpoolP384t1  |      1310.96 |         1232 |
    | brainpoolP512r1  |      2860.05 |         1584 |
    | brainpoolP512t1  |      2573.09 |         1584 |
    +------------------+--------------+--------------+

    Program listing

    /*********************************************************************
    *               (c) SEGGER Microcontroller GmbH & Co. KG             *
    *                        The Embedded Experts                        *
    *                           www.segger.com                           *
    **********************************************************************
    
    -------------------------- END-OF-HEADER -----------------------------
    
    File        : CRYPTO_Bench_ECDH.c
    Purpose     : Benchmark ECDH key agreement performance.
    
    */
    
    /*********************************************************************
    *
    *       #include section
    *
    **********************************************************************
    */
    
    #include "CRYPTO_Int.h"
    #include "SEGGER_MEM.h"
    #include "SEGGER_SYS.h"
    
    /*********************************************************************
    *
    *       Defines, configurable
    *
    **********************************************************************
    */
    
    #define MAX_CHUNKS             22
    
    /*********************************************************************
    *
    *       Local data 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
    *
    **********************************************************************
    */
    
    /*********************************************************************
    *
    *       _LFSR_Get()
    *
    *  Function description
    *    Get pseudo-random data.
    *
    *  Parameters
    *    pData   - Pointer to object the receives the random data.
    *    DataLen - Octet length of the random data.
    *
    *  Additional information
    *    This LFSR PRNG does not need to be cryptographically strong as
    *    its purpose is only to deliver repeatable pseudo-random data
    *    that does not depend upon a nondeterministic source (such as
    *    a hardware RNG or the availability of hardware ciphering and
    *    hashing in the DRBG code).  Therefore, this RNG is suitable
    *    for deterministic benchmarking across compilers and systems.
    */
    static void _LFSR_Get(U8 *pData, unsigned Len) {
      static U32 State32 = 0xFEDCBA8uL;
      static U32 State31 = 0x1234567uL;
      //
      while (Len > 0) {
        if (State32 & 1) {
          State32 >>= 1;
          State32 ^= 0xB4BCD35CuL;
        } else {
          State32 >>= 1;
        }
        if (State32 & 1) {
          State31 >>= 1;
          State31 ^= 0x7A5BC2E3uL;
        } else {
          State31 >>= 1;
        }
        if (Len >= 2) {
          CRYPTO_WRU16LE(pData, (U16)(State31 ^ State32));
          pData += 2;
          Len   -= 2;
        } else {
          *pData = (U8)(State31 ^ State32);
          Len -= 1;
        }
      }
    }
    
    /*********************************************************************
    *
    *       _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;
    }
    
    /*********************************************************************
    *
    *       _BenchmarkECDHKeyAgreement()
    *
    *  Function description
    *    Benchmark ECDH key agreement, both sides.
    *
    *  Parameters
    *    pCurve - Pointer to elliptic curve.
    */
    static void _BenchmarkECDHKeyAgreement(const CRYPTO_EC_CURVE *pCurve) {
      CRYPTO_ECDH_KA_CONTEXT Us;
      CRYPTO_ECDH_KA_CONTEXT Them;
      U64                    OneSecond;
      U64                    T0;
      U64                    Elapsed;
      int                    Loops;
      int                    Status;
      unsigned               PeakBytes;
      unsigned               UnitSize;
      float                  Time;
      //
      // Make PC-lint quiet, it's dataflow analysis provides false positives.
      //
      Loops     = 0;
      Elapsed   = 0;
      PeakBytes = 0;
      UnitSize  = CRYPTO_MPI_BYTES_REQUIRED(2*CRYPTO_MPI_BitCount(&pCurve->P)+63) + 2*CRYPTO_MPI_BYTES_PER_LIMB;
      //
      SEGGER_SYS_IO_Printf("| %-16s |", pCurve->aCurveName);
      //
      OneSecond = SEGGER_SYS_OS_ConvertMicrosToTicks(1000000);
      T0 = SEGGER_SYS_OS_GetTimer();
      do {
        //
        _Heap.Stats.NumInUseMax = _Heap.Stats.NumInUse;
        //
        CRYPTO_ECDH_KA_Init(&Us,   &_MemContext);
        CRYPTO_ECDH_KA_Init(&Them, &_MemContext);
        //
        CRYPTO_CHECK(CRYPTO_ECDH_KA_Start(&Us,   pCurve, &_MemContext));
        CRYPTO_CHECK(CRYPTO_ECDH_KA_Start(&Them, pCurve, &_MemContext));
        //
        CRYPTO_CHECK(CRYPTO_ECDH_KA_Agree(&Us,   &Them.Public.Y, &_MemContext));
        CRYPTO_CHECK(CRYPTO_ECDH_KA_Agree(&Them, &Us.Public.Y,   &_MemContext));
        //
        CRYPTO_ECDH_KA_Kill(&Us);
        CRYPTO_ECDH_KA_Kill(&Them);
        //
        PeakBytes = _Heap.Stats.NumInUseMax * UnitSize;
        //
        Elapsed = SEGGER_SYS_OS_GetTimer() - T0;
        ++Loops;
      } while (Status >= 0 && Elapsed < OneSecond);
      //
    cleanup:
      CRYPTO_ECDH_KA_Kill(&Us);
      CRYPTO_ECDH_KA_Kill(&Them);
      //
      if (Status < 0 || Loops == 0) {
        SEGGER_SYS_IO_Printf("%13s |%13s | ", "-Fail-", "-Fail-");
      } else {
        Loops     *= 2;    // Two agreements per loop
        PeakBytes /= 2;    // Two agreements per loop
        Time = 1000.0f * _ConvertTicksToSeconds(Elapsed) / Loops;
        SEGGER_SYS_IO_Printf("%13.2f |%13d |", Time, PeakBytes);
      }
      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) {
      static const CRYPTO_RNG_API LFSR = { NULL, _LFSR_Get, NULL, NULL };
      //
      CRYPTO_Init();
      SEGGER_SYS_Init();
      SEGGER_MEM_SELFTEST_HEAP_Init(&_MemContext, &_Heap, _aUnits, MAX_CHUNKS, sizeof(MPI_UNIT));
      CRYPTO_RNG_Install(&LFSR);
      //
      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("ECDH Key Agreement 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("\n");
      //
      SEGGER_SYS_IO_Printf("This benchmarks both ends of an ECDH key agreement, but.\n");
      SEGGER_SYS_IO_Printf("timing is reported as the time for one end's calculation.\n");
      SEGGER_SYS_IO_Printf("\n");
      SEGGER_SYS_IO_Printf("+------------------+--------------+--------------+\n");
      SEGGER_SYS_IO_Printf("| Curve            | ms/Agreement |       Memory |\n");
      SEGGER_SYS_IO_Printf("+------------------+--------------+--------------+\n");
      //
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_P192);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_P224);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_P256);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_P384);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_P521);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP160r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP160t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP192r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP192t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP224r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP224t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP256r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP256t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP320r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP320t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP384r1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP384t1);
      _BenchmarkECDHKeyAgreement(&CRYPTO_EC_CURVE_brainpoolP512r1);
      _BenchmarkECDHKeyAgreement(&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.