Add control to retrieve signature MD.
[openssl.git] / crypto / ec / ec_pmeth.c
index caaeebdb6d0fed0bcee7841585b562a23a0dd8e0..4110d5e4f0c867ed8887fbd29bb7bda891fc8145 100644 (file)
@@ -1,4 +1,4 @@
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
 /* ====================================================================
@@ -120,7 +120,7 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
                                        const unsigned char *tbs, size_t tbslen)
        {
        int ret, type;
-       size_t sltmp;
+       unsigned int sltmp;
        EC_PKEY_CTX *dctx = ctx->data;
        EC_KEY *ec = ctx->pkey->pkey.ec;
 
@@ -143,9 +143,9 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
 
        ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
 
-       if (ret < 0)
+       if (ret <= 0)
                return ret;
-       *siglen = sltmp;
+       *siglen = (size_t)sltmp;
        return 1;
        }
 
@@ -188,7 +188,7 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
 
        pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
 
-       /* NB: unlike PKS#3 DH, if *outlen is less than maximum size this is
+       /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is
         * not an error, the result is truncated.
         */
 
@@ -219,8 +219,22 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                dctx->gen_group = group;
                return 1;
 
+               case EVP_PKEY_CTRL_EC_PARAM_ENC:
+               if (!dctx->gen_group)
+                       {
+                       ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
+                       return 0;
+                       }
+               EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
+               return 1;
+
                case EVP_PKEY_CTRL_MD:
-               if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1)
+               if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha512)
                        {
                        ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
                        return 0;
@@ -228,8 +242,15 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                dctx->md = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_GET_MD:
+               *(const EVP_MD **)p2 = dctx->md;
+               return 1;
+
                case EVP_PKEY_CTRL_PEER_KEY:
                /* Default behaviour is OK */
+               case EVP_PKEY_CTRL_DIGESTINIT:
+               case EVP_PKEY_CTRL_PKCS7_SIGN:
+               case EVP_PKEY_CTRL_CMS_SIGN:
                return 1;
 
                default:
@@ -244,7 +265,9 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
        if (!strcmp(type, "ec_paramgen_curve"))
                {
                int nid;
-               nid = OBJ_sn2nid(value);
+               nid = EC_curve_nist2nid(value);
+               if (nid == NID_undef)
+                       nid = OBJ_sn2nid(value);
                if (nid == NID_undef)
                        nid = OBJ_ln2nid(value);
                if (nid == NID_undef)
@@ -254,6 +277,18 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
                        }
                return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
                }
+       else if (!strcmp(type, "ec_param_enc"))
+               {
+               int param_enc;
+               if (!strcmp(value, "explicit"))
+                       param_enc = 0;
+               else if (!strcmp(value, "named_curve"))
+                       param_enc = OPENSSL_EC_NAMED_CURVE;
+               else
+                       return -2;
+               return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
+               }
+                       
        return -2;
        }
 
@@ -281,7 +316,8 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
        {
        EC_KEY *ec = NULL;
-       if (ctx->pkey == NULL)
+       EC_PKEY_CTX *dctx = ctx->data;
+       if (ctx->pkey == NULL && dctx->gen_group == NULL)
                {
                ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
                return 0;
@@ -290,9 +326,17 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
        if (!ec)
                return 0;
        EVP_PKEY_assign_EC_KEY(pkey, ec);
-       /* Note: if error return, pkey is freed by parent routine */
-       if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
-               return 0;
+       if (ctx->pkey)
+               {
+               /* Note: if error return, pkey is freed by parent routine */
+               if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+                       return 0;
+               }
+       else
+               {
+               if (!EC_KEY_set_group(ec, dctx->gen_group))
+                       return 0;
+               }
        return EC_KEY_generate_key(pkey->pkey.ec);
        }