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, &params)) 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

Reply via email to