Matt / List, Thanks for the example. It sure helped a lot. But I am still stuck at the EC key generation.
I've created keys for NIST Prime curves (224-571bit), Binary and Kolbits curves (233-571 bit). I then convert the keys to PEM using the same method which I used successfully for RSA and DSA which only calls PEM_write_bio_PrivateKey() and PEM_write_bio_PUBKEY(). The type is never specified in my functions. What is interesting now is that if I test the EC PEM files, using the openssl command line tool, all the keys generated for the NIST Prime curves is successfully parsed while the others fails with the following error: $openssl ec -in ec-b233.pem -text -noout read EC key unable to load Key 139742524995232:error:100DC08E:elliptic curve routines:ECKEY_TYPE2PARAM:decode error:ec_ameth.c:178: 139742524995232:error:100D5010:elliptic curve routines:ECKEY_PRIV_DECODE:EC lib:ec_ameth.c:305: 139742524995232:error:0606F091:digital envelope routines:EVP_PKCS82PKEY:private key decode error:evp_pkey.c:95: 139742524995232:error:0907B00D:PEM routines:PEM_READ_BIO_PRIVATEKEY:ASN1 lib:pem_pkey.c:132: I've noticed that writing the PEM files using the above mentioned mechanism does not add the letters "EC" to the PEM header and footer of the private key (e.g. -----BEGIN EC PRIVATE KEY------ misses the "EC"). The spec seems to say it must have these two characters. If I add the "EC" manually, I get the following parsing error: $ openssl ec -in ec-b233.pem -text -noout read EC key unable to load Key 140357067445920:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1319: 140357067445920:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:831: 140357067445920:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:751:Field=privateKey, Type=EC_PRIVATEKEY 140357067445920:error:10092010:elliptic curve routines:d2i_ECPrivateKey:EC lib:ec_asn1.c:1130: 140357067445920:error:100DE08E:elliptic curve routines:OLD_EC_PRIV_DECODE:decode error:ec_ameth.c:565: 140357067445920:error:100DC08E:elliptic curve routines:ECKEY_TYPE2PARAM:decode error:ec_ameth.c:178: 140357067445920:error:100D5010:elliptic curve routines:ECKEY_PRIV_DECODE:EC lib:ec_ameth.c:305: 140357067445920:error:0606F091:digital envelope routines:EVP_PKCS82PKEY:private key decode error:evp_pkey.c:95: 140357067445920:error:0907B00D:PEM routines:PEM_READ_BIO_PRIVATEKEY:ASN1 lib:pem_pkey.c:132: Any suggestions on why my binary curve keys are not validated? Also can someone shed some light on the naming of the curves: Take for example "NID_secp224r1". From the bits I can see that it is a NIST prime curve which is also indicated by the 'p' (right?), which then makes me wonder why all the binary curves has a 't' (e.g. NID_sect233r1). Next, to distinguish between the NIST binary curves and the Kolbitz curves the only indication is that the Kolbitz curve names ends with a 'k1' - is this correct? And if so what is the 'r' for then in the NIST prime and NIST binary numbers? And finally, why is there not a NID_sect256r1, but rather a NID_X9_62_prime256v1? Thanks again for a great mailing list Leon Brits From: owner-openssl-...@openssl.org [mailto:owner-openssl-...@openssl.org] On Behalf Of Matt Caswell Sent: 15 March 2013 02:05 AM To: openssl-dev@openssl.org Subject: Re: EVP and Elliptic curve On Thu, Mar 14, 2013, Leon Brits wrote: > Hi List, > > I just want to verify: Elliptic curve functions are not encapsulated by the > EVP functions - correct? If so, what is the > EVP_PKEY_CTX_set_ec_paramgen_curve_nid function then used for? If NOT so, > then please help with an example since I could only find the normal > EC_{KEY,GROUP}* type of example code? > > I am required to perform ECDSA and was hoping I could use EVP which is now > working for DSA and RSA (sans the padding problem). > As Steve has said, yes you can use ECDSA using EVP. The EVP_PKEY_CTX_set_ec_paramgen_curve_nid is used during parameter generation. Here is some sample code that uses it. Once you have an EVP_PKEY set up with a type of EVP_PKEY_EC, then the code to do signatures should be pretty much identical for DSA and ECDSA. This code generates a new key but you can equally set it directly using EVP_PKEY_set1_EC_KEY. See the man page for further details: http://www.openssl.org/docs/crypto/EVP_PKEY_set1_RSA.html EVP_PKEY *generate_key(int type) { EVP_PKEY_CTX *pctx = NULL, *kctx = NULL; EVP_PKEY *params = NULL, *key = NULL; /* Check whether we need to generate parameters first */ if(type == EVP_PKEY_EC || type == EVP_PKEY_DSA || type == EVP_PKEY_DH) { /* Create the context for generating the parameters */ if(!(pctx = EVP_PKEY_CTX_new_id(type, NULL))) goto err; if(!EVP_PKEY_paramgen_init(pctx)) goto err; /* Set the paramgen parameters according to the type */ switch(type) { case EVP_PKEY_EC: if(!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) goto err; break; case EVP_PKEY_DSA: if(!EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, 2048)) goto err; break; case EVP_PKEY_DH: if(!EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, 2048)) goto err; } /* Generate parameters */ if (!EVP_PKEY_paramgen(pctx, ¶ms)) goto err; /* Create context for the key generation */ if(!(kctx = EVP_PKEY_CTX_new(params, NULL))) goto err; } else { /* Create context for the key generation */ if(!(kctx = EVP_PKEY_CTX_new_id(type, NULL))) goto err; } /* Set the keygen parameters according to the type */ if(type == EVP_PKEY_RSA) { if(!EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, 2048)) goto err; } /* Generate the key */ if(!EVP_PKEY_keygen_init(kctx)) goto err; if(type == EVP_PKEY_CMAC) { if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_CIPHER, 0, (void *)EVP_aes_256_ecb()) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_SET_MAC_KEY, /*key length*/32, "01234567890123456789012345678901") <= 0) goto err; } if (!EVP_PKEY_keygen(kctx, &key)) goto err; goto end; err: ERR_print_errors_fp(stderr); end: if(pctx) EVP_PKEY_CTX_free(pctx); if(params) EVP_PKEY_free(params); if(kctx) EVP_PKEY_CTX_free(kctx); return key; } Regards Matt