Search code examples
blockchainvalgrind

Elliptic curve key verification failed


I am trying to create an EC_KEY using EC_KEY_new_by_curve_name(NID_secp256k1) but m having this output when ii check the key

Output of runing EC_KEY_check_key(key)

This is the error on the image.

==13629== Memcheck, a memory error detector
==13629== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==13629== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==13629== Command: ./ec_create-test
==13629==
Key verification failed
==13629==
==13629== HEAP SUMMARY:
==13629==     in use at exit: 1,224 bytes in 28 blocks
==13629==   total heap usage: 2,558 allocs, 2,530 frees, 96,068 bytes allocated
==13629==
==13629== LEAK SUMMARY:
==13629==    definitely lost: 80 bytes in 1 blocks
==13629==    indirectly lost: 1,144 bytes in 27 blocks
==13629==      possibly lost: 0 bytes in 0 blocks
==13629==    still reachable: 0 bytes in 0 blocks
==13629==         suppressed: 0 bytes in 0 blocks
==13629== Rerun with --leak-check=full to see details of leaked memory
==13629==
==13629== For counts of detected and suppressed errors, rerun with: -v
==13629== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Solution

  • TLDR: you didn't create (or set) any key

    An EC_KEY object in OpenSSL, like the objects for other publickey schemes with parameters (DSA and DH), can actually be in one of 4 states:

    1. the object exists but is not set at all

    2. the object has the paramweters set, but neither private nor public key

    3. the object has the parameters and public key set, but not private key; this is commonly used by parties other than the key owner

    4. the object has the parameters set and both private and public key; this is commonly used by the key owner

    For EC the parameters are often loosely called a "curve" but technically that is imprecise: they actually include an underlying field (here Fp, the integers modulo a particular 256-bit prime); the coefficients of a short Weierstrass equation defining a curve over that field; and a prechosen 'base' or 'generator' point on that curve. Mathematically these parameters form a finite group, and OpenSSL actually stores them in a related but different object type EC_GROUP.

    EC_KEY_new_by_curve_name produces state 2 -- it has the parameters (specifically EC_GROUP) set, but no key -- so EC_KEY_check_key has no key to check, and fails.

    In general whenever any OpenSSL crypto function returns a failure indication (and often but not always when an SSL/TLS function does) you should look at the error stack. (Note the subsequent item there, PROG9, is mostly obsolete; OpenSSL 1.1.0 up automatically initializes library data, including the error strings, without you coding it explicitly as in older versions.) With this code

    /* SO 66847659 2021-03-29 */
    #include <stdio.h>
    #include <openssl/ec.h>
    #include <openssl/obj_mac.h>
    #include <openssl/err.h>
    
    int main (void){
      EC_KEY * ec = EC_KEY_new_by_curve_name(NID_secp256k1);
      if( EC_KEY_check_key(ec) <= 0 ) ERR_print_errors_fp(stdout);
      return 0;
    }
    

    I get the more specific and helpful error message

    140659993163520:error:100B1043:elliptic curve routines:EC_KEY_check_key:passed a null parameter:crypto/ec/ec_key.c:258:
    

    If you want to generate a new keypair, after creating the EC_KEY object (with parameters) call EC_KEY_generate_key -- or better style since 1.0.0 in 2010 is to use the higher-level generic EVP_PKEY interface instead of the algorithm-specific one. OTOH if you want to use an existing keypair, or publickey, there are numerous options depending on the details of your environment and data that you didn't specify.