Add dsa signature alg to fips provider
authorShane Lontis <shane.lontis@oracle.com>
Sun, 12 Jan 2020 01:32:12 +0000 (11:32 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Sun, 12 Jan 2020 01:32:12 +0000 (11:32 +1000)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10615)

22 files changed:
apps/fipsinstall.c
crypto/dsa/build.info
crypto/dsa/dsa_asn1.c
crypto/dsa/dsa_lib.c
crypto/dsa/dsa_local.h
crypto/dsa/dsa_ossl.c
crypto/dsa/dsa_sign.c
crypto/evp/build.info
crypto/evp/p_lib.c
crypto/evp/pmeth_fn.c
crypto/evp/pmeth_gn.c
crypto/evp/pmeth_lib.c
crypto/evp/signature.c [new file with mode: 0644]
doc/man3/EVP_PKEY_CTX_new.pod
include/crypto/dsa.h [new file with mode: 0644]
include/crypto/evp.h
include/openssl/evp.h
providers/fips/fipsprov.c
providers/implementations/keymgmt/dsa_kmgmt.c
providers/implementations/signature/dsa.c
test/evp_pkey_provided_test.c
util/libcrypto.num

index 3b19ef1..739df23 100644 (file)
@@ -170,7 +170,7 @@ static CONF *generate_config_and_load(const char *prov_name,
     if (conf == NULL)
         goto end;
 
-    if (!CONF_modules_load(conf, NULL, 0))
+    if (CONF_modules_load(conf, NULL, 0) <= 0)
         goto end;
     BIO_free(mem_bio);
     return conf;
index 2e75985..309fda3 100644 (file)
@@ -1,5 +1,9 @@
 LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
-        dsa_gen.c dsa_key.c dsa_lib.c dsa_asn1.c dsa_vrf.c dsa_sign.c \
-        dsa_err.c dsa_ossl.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \
+
+$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c
+
+SOURCE[../../libcrypto]=$COMMON\
+        dsa_gen.c dsa_key.c dsa_asn1.c \
+        dsa_err.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \
         dsa_meth.c
+SOURCE[../../providers/libfips.a]=$COMMON
index bf16e28..20bf251 100644 (file)
 #include <openssl/rand.h>
 #include "crypto/asn1_dsa.h"
 
-DSA_SIG *DSA_SIG_new(void)
-{
-    DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
-    if (sig == NULL)
-        DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE);
-    return sig;
-}
-
-void DSA_SIG_free(DSA_SIG *sig)
-{
-    if (sig == NULL)
-        return;
-    BN_clear_free(sig->r);
-    BN_clear_free(sig->s);
-    OPENSSL_free(sig);
-}
-
-DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len)
-{
-    DSA_SIG *sig;
-
-    if (len < 0)
-        return NULL;
-    if (psig != NULL && *psig != NULL) {
-        sig = *psig;
-    } else {
-        sig = DSA_SIG_new();
-        if (sig == NULL)
-            return NULL;
-    }
-    if (sig->r == NULL)
-        sig->r = BN_new();
-    if (sig->s == NULL)
-        sig->s = BN_new();
-    if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
-        if (psig == NULL || *psig == NULL)
-            DSA_SIG_free(sig);
-        return NULL;
-    }
-    if (psig != NULL && *psig == NULL)
-        *psig = sig;
-    return sig;
-}
-
-int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout)
-{
-    BUF_MEM *buf = NULL;
-    size_t encoded_len;
-    WPACKET pkt;
-
-    if (ppout == NULL) {
-        if (!WPACKET_init_null(&pkt, 0))
-            return -1;
-    } else if (*ppout == NULL) {
-        if ((buf = BUF_MEM_new()) == NULL
-                || !WPACKET_init_len(&pkt, buf, 0)) {
-            BUF_MEM_free(buf);
-            return -1;
-        }
-    } else {
-        if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
-            return -1;
-    }
-
-    if (!encode_der_dsa_sig(&pkt, sig->r, sig->s)
-            || !WPACKET_get_total_written(&pkt, &encoded_len)
-            || !WPACKET_finish(&pkt)) {
-        BUF_MEM_free(buf);
-        WPACKET_cleanup(&pkt);
-        return -1;
-    }
-
-    if (ppout != NULL) {
-        if (*ppout == NULL) {
-            *ppout = (unsigned char *)buf->data;
-            buf->data = NULL;
-            BUF_MEM_free(buf);
-        } else {
-            *ppout += encoded_len;
-        }
-    }
-
-    return (int)encoded_len;
-}
-
-void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
-{
-    if (pr != NULL)
-        *pr = sig->r;
-    if (ps != NULL)
-        *ps = sig->s;
-}
-
-int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
-{
-    if (r == NULL || s == NULL)
-        return 0;
-    BN_clear_free(sig->r);
-    BN_clear_free(sig->s);
-    sig->r = r;
-    sig->s = s;
-    return 1;
-}
-
 /* Override the default free and new methods */
 static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                   void *exarg)
@@ -168,50 +64,3 @@ DSA *DSAparams_dup(const DSA *dsa)
 {
     return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), dsa);
 }
-
-int DSA_sign(int type, const unsigned char *dgst, int dlen,
-             unsigned char *sig, unsigned int *siglen, DSA *dsa)
-{
-    DSA_SIG *s;
-
-    s = DSA_do_sign(dgst, dlen, dsa);
-    if (s == NULL) {
-        *siglen = 0;
-        return 0;
-    }
-    *siglen = i2d_DSA_SIG(s, &sig);
-    DSA_SIG_free(s);
-    return 1;
-}
-
-/* data has already been hashed (probably with SHA or SHA-1). */
-/*-
- * returns
- *      1: correct signature
- *      0: incorrect signature
- *     -1: error
- */
-int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
-               const unsigned char *sigbuf, int siglen, DSA *dsa)
-{
-    DSA_SIG *s;
-    const unsigned char *p = sigbuf;
-    unsigned char *der = NULL;
-    int derlen = -1;
-    int ret = -1;
-
-    s = DSA_SIG_new();
-    if (s == NULL)
-        return ret;
-    if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
-        goto err;
-    /* Ensure signature uses DER and doesn't have trailing garbage */
-    derlen = i2d_DSA_SIG(s, &der);
-    if (derlen != siglen || memcmp(sigbuf, der, derlen))
-        goto err;
-    ret = DSA_do_verify(dgst, dgst_len, s, dsa);
- err:
-    OPENSSL_clear_free(der, derlen);
-    DSA_SIG_free(s);
-    return ret;
-}
index 4670c43..2a97c08 100644 (file)
 #include <openssl/asn1.h>
 #include <openssl/engine.h>
 #include <openssl/dh.h>
+#include "crypto/dsa.h"
+
+#ifndef FIPS_MODE
 
 DSA *DSA_new(void)
 {
     return DSA_new_method(NULL);
 }
 
+int DSA_set_ex_data(DSA *d, int idx, void *arg)
+{
+    return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+
+void *DSA_get_ex_data(DSA *d, int idx)
+{
+    return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+
+int DSA_security_bits(const DSA *d)
+{
+    if (d->p && d->q)
+        return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
+    return -1;
+}
+
+#ifndef OPENSSL_NO_DH
+DH *DSA_dup_DH(const DSA *r)
+{
+    /*
+     * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
+     * optional length, g, optional pub_key, optional priv_key, optional q.
+     */
+
+    DH *ret = NULL;
+    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
+
+    if (r == NULL)
+        goto err;
+    ret = DH_new();
+    if (ret == NULL)
+        goto err;
+    if (r->p != NULL || r->g != NULL || r->q != NULL) {
+        if (r->p == NULL || r->g == NULL || r->q == NULL) {
+            /* Shouldn't happen */
+            goto err;
+        }
+        p = BN_dup(r->p);
+        g = BN_dup(r->g);
+        q = BN_dup(r->q);
+        if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g))
+            goto err;
+        p = g = q = NULL;
+    }
+
+    if (r->pub_key != NULL) {
+        pub_key = BN_dup(r->pub_key);
+        if (pub_key == NULL)
+            goto err;
+        if (r->priv_key != NULL) {
+            priv_key = BN_dup(r->priv_key);
+            if (priv_key == NULL)
+                goto err;
+        }
+        if (!DH_set0_key(ret, pub_key, priv_key))
+            goto err;
+    } else if (r->priv_key != NULL) {
+        /* Shouldn't happen */
+        goto err;
+    }
+
+    return ret;
+
+ err:
+    BN_free(p);
+    BN_free(g);
+    BN_free(q);
+    BN_free(pub_key);
+    BN_free(priv_key);
+    DH_free(ret);
+    return NULL;
+}
+#endif
+
+const BIGNUM *DSA_get0_p(const DSA *d)
+{
+    return d->p;
+}
+
+const BIGNUM *DSA_get0_q(const DSA *d)
+{
+    return d->q;
+}
+
+const BIGNUM *DSA_get0_g(const DSA *d)
+{
+    return d->g;
+}
+
+const BIGNUM *DSA_get0_pub_key(const DSA *d)
+{
+    return d->pub_key;
+}
+
+const BIGNUM *DSA_get0_priv_key(const DSA *d)
+{
+    return d->priv_key;
+}
+
+void DSA_clear_flags(DSA *d, int flags)
+{
+    d->flags &= ~flags;
+}
+
+int DSA_test_flags(const DSA *d, int flags)
+{
+    return d->flags & flags;
+}
+
+void DSA_set_flags(DSA *d, int flags)
+{
+    d->flags |= flags;
+}
+
+ENGINE *DSA_get0_engine(DSA *d)
+{
+    return d->engine;
+}
+
+int DSA_bits(const DSA *dsa)
+{
+    return BN_num_bits(dsa->p);
+}
+
 int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
 {
     /*
@@ -40,13 +168,15 @@ int DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
         meth->init(dsa);
     return 1;
 }
+#endif /* FIPS_MODE */
+
 
 const DSA_METHOD *DSA_get_method(DSA *d)
 {
     return d->meth;
 }
 
-DSA *DSA_new_method(ENGINE *engine)
+static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine)
 {
     DSA *ret = OPENSSL_zalloc(sizeof(*ret));
 
@@ -64,7 +194,7 @@ DSA *DSA_new_method(ENGINE *engine)
     }
 
     ret->meth = DSA_get_default_method();
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
     ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */
     if (engine) {
         if (!ENGINE_init(engine)) {
@@ -85,7 +215,7 @@ DSA *DSA_new_method(ENGINE *engine)
 
     ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
 
-    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data))
+    if (!crypto_new_ex_data_ex(libctx, CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data))
         goto err;
 
     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
@@ -100,6 +230,16 @@ DSA *DSA_new_method(ENGINE *engine)
     return NULL;
 }
 
+DSA *DSA_new_method(ENGINE *engine)
+{
+    return dsa_new_method(NULL, engine);
+}
+
+DSA *dsa_new(OPENSSL_CTX *libctx)
+{
+    return dsa_new_method(libctx, NULL);
+}
+
 void DSA_free(DSA *r)
 {
     int i;
@@ -115,7 +255,7 @@ void DSA_free(DSA *r)
 
     if (r->meth != NULL && r->meth->finish != NULL)
         r->meth->finish(r);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
     ENGINE_finish(r->engine);
 #endif
 
@@ -143,103 +283,6 @@ int DSA_up_ref(DSA *r)
     return ((i > 1) ? 1 : 0);
 }
 
-int DSA_size(const DSA *r)
-{
-    int ret, i;
-    ASN1_INTEGER bs;
-    unsigned char buf[4];       /* 4 bytes looks really small. However,
-                                 * i2d_ASN1_INTEGER() will not look beyond
-                                 * the first byte, as long as the second
-                                 * parameter is NULL. */
-
-    i = BN_num_bits(r->q);
-    bs.length = (i + 7) / 8;
-    bs.data = buf;
-    bs.type = V_ASN1_INTEGER;
-    /* If the top bit is set the asn1 encoding is 1 larger. */
-    buf[0] = 0xff;
-
-    i = i2d_ASN1_INTEGER(&bs, NULL);
-    i += i;                     /* r and s */
-    ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
-    return ret;
-}
-
-int DSA_set_ex_data(DSA *d, int idx, void *arg)
-{
-    return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
-}
-
-void *DSA_get_ex_data(DSA *d, int idx)
-{
-    return CRYPTO_get_ex_data(&d->ex_data, idx);
-}
-
-int DSA_security_bits(const DSA *d)
-{
-    if (d->p && d->q)
-        return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
-    return -1;
-}
-
-#ifndef OPENSSL_NO_DH
-DH *DSA_dup_DH(const DSA *r)
-{
-    /*
-     * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
-     * optional length, g, optional pub_key, optional priv_key, optional q.
-     */
-
-    DH *ret = NULL;
-    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
-
-    if (r == NULL)
-        goto err;
-    ret = DH_new();
-    if (ret == NULL)
-        goto err;
-    if (r->p != NULL || r->g != NULL || r->q != NULL) {
-        if (r->p == NULL || r->g == NULL || r->q == NULL) {
-            /* Shouldn't happen */
-            goto err;
-        }
-        p = BN_dup(r->p);
-        g = BN_dup(r->g);
-        q = BN_dup(r->q);
-        if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g))
-            goto err;
-        p = g = q = NULL;
-    }
-
-    if (r->pub_key != NULL) {
-        pub_key = BN_dup(r->pub_key);
-        if (pub_key == NULL)
-            goto err;
-        if (r->priv_key != NULL) {
-            priv_key = BN_dup(r->priv_key);
-            if (priv_key == NULL)
-                goto err;
-        }
-        if (!DH_set0_key(ret, pub_key, priv_key))
-            goto err;
-    } else if (r->priv_key != NULL) {
-        /* Shouldn't happen */
-        goto err;
-    }
-
-    return ret;
-
- err:
-    BN_free(p);
-    BN_free(g);
-    BN_free(q);
-    BN_free(pub_key);
-    BN_free(priv_key);
-    DH_free(ret);
-    return NULL;
-}
-#endif
-
 void DSA_get0_pqg(const DSA *d,
                   const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
 {
@@ -309,52 +352,3 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
     return 1;
 }
 
-const BIGNUM *DSA_get0_p(const DSA *d)
-{
-    return d->p;
-}
-
-const BIGNUM *DSA_get0_q(const DSA *d)
-{
-    return d->q;
-}
-
-const BIGNUM *DSA_get0_g(const DSA *d)
-{
-    return d->g;
-}
-
-const BIGNUM *DSA_get0_pub_key(const DSA *d)
-{
-    return d->pub_key;
-}
-
-const BIGNUM *DSA_get0_priv_key(const DSA *d)
-{
-    return d->priv_key;
-}
-
-void DSA_clear_flags(DSA *d, int flags)
-{
-    d->flags &= ~flags;
-}
-
-int DSA_test_flags(const DSA *d, int flags)
-{
-    return d->flags & flags;
-}
-
-void DSA_set_flags(DSA *d, int flags)
-{
-    d->flags |= flags;
-}
-
-ENGINE *DSA_get0_engine(DSA *d)
-{
-    return d->engine;
-}
-
-int DSA_bits(const DSA *dsa)
-{
-    return BN_num_bits(dsa->p);
-}
index e56ff06..13a3007 100644 (file)
@@ -78,3 +78,6 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
                           size_t seed_len, int idx, unsigned char *seed_out,
                           int *counter_ret, unsigned long *h_ret,
                           BN_GENCB *cb);
+
+DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
+                         int dlen, DSA *dsa);
index 5e34fc5..af0fa6b 100644 (file)
@@ -44,10 +44,12 @@ static DSA_METHOD openssl_dsa_meth = {
 
 static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth;
 
+#ifndef FIPS_MODE
 void DSA_set_default_method(const DSA_METHOD *meth)
 {
     default_DSA_method = meth;
 }
+#endif /* FIPS_MODE */
 
 const DSA_METHOD *DSA_get_default_method(void)
 {
@@ -59,7 +61,8 @@ const DSA_METHOD *DSA_OpenSSL(void)
     return &openssl_dsa_meth;
 }
 
-static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
+                         int dlen, DSA *dsa)
 {
     BIGNUM *kinv = NULL;
     BIGNUM *m, *blind, *blindm, *tmp;
@@ -85,7 +88,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
     if (ret->r == NULL || ret->s == NULL)
         goto err;
 
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(libctx);
     if (ctx == NULL)
         goto err;
     m = BN_CTX_get(ctx);
@@ -121,8 +124,8 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 
     /* Generate a blinding value */
     do {
-        if (!BN_priv_rand(blind, BN_num_bits(dsa->q) - 1,
-                          BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+        if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->q) - 1,
+                             BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx))
             goto err;
     } while (BN_is_zero(blind));
     BN_set_flags(blind, BN_FLG_CONSTTIME);
@@ -164,7 +167,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 
  err:
     if (rv == 0) {
-        DSAerr(DSA_F_DSA_DO_SIGN, reason);
+        DSAerr(0, reason);
         DSA_SIG_free(ret);
         ret = NULL;
     }
@@ -173,6 +176,11 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
     return ret;
 }
 
+static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+    return dsa_do_sign_int(NULL, dgst, dlen, dsa);
+}
+
 static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
                                     BIGNUM **kinvp, BIGNUM **rp)
 {
@@ -210,7 +218,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
         goto err;
 
     if (ctx_in == NULL) {
-        if ((ctx = BN_CTX_new()) == NULL)
+        /* if you don't pass in ctx_in you get a default libctx */
+        if ((ctx = BN_CTX_new_ex(NULL)) == NULL)
             goto err;
     } else
         ctx = ctx_in;
@@ -232,7 +241,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
             if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst,
                                        dlen, ctx))
                 goto err;
-        } else if (!BN_priv_rand_range(k, dsa->q))
+        } else if (!BN_priv_rand_range_ex(k, dsa->q, ctx))
             goto err;
     } while (BN_is_zero(k));
 
@@ -323,7 +332,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
     u1 = BN_new();
     u2 = BN_new();
     t1 = BN_new();
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(NULL); /* verify does not need a libctx */
     if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL)
         goto err;
 
index 99ef004..d09aaea 100644 (file)
@@ -7,9 +7,11 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <openssl/bn.h>
 #include "internal/cryptlib.h"
 #include "dsa_local.h"
-#include <openssl/bn.h>
+#include "crypto/asn1_dsa.h"
+#include "crypto/dsa.h"
 
 DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 {
@@ -22,3 +24,178 @@ int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
     return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
 }
 #endif
+
+DSA_SIG *DSA_SIG_new(void)
+{
+    DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
+    if (sig == NULL)
+        DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE);
+    return sig;
+}
+
+void DSA_SIG_free(DSA_SIG *sig)
+{
+    if (sig == NULL)
+        return;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    OPENSSL_free(sig);
+}
+
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len)
+{
+    DSA_SIG *sig;
+
+    if (len < 0)
+        return NULL;
+    if (psig != NULL && *psig != NULL) {
+        sig = *psig;
+    } else {
+        sig = DSA_SIG_new();
+        if (sig == NULL)
+            return NULL;
+    }
+    if (sig->r == NULL)
+        sig->r = BN_new();
+    if (sig->s == NULL)
+        sig->s = BN_new();
+    if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
+        if (psig == NULL || *psig == NULL)
+            DSA_SIG_free(sig);
+        return NULL;
+    }
+    if (psig != NULL && *psig == NULL)
+        *psig = sig;
+    return sig;
+}
+
+int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout)
+{
+    BUF_MEM *buf = NULL;
+    size_t encoded_len;
+    WPACKET pkt;
+
+    if (ppout == NULL) {
+        if (!WPACKET_init_null(&pkt, 0))
+            return -1;
+    } else if (*ppout == NULL) {
+        if ((buf = BUF_MEM_new()) == NULL
+                || !WPACKET_init_len(&pkt, buf, 0)) {
+            BUF_MEM_free(buf);
+            return -1;
+        }
+    } else {
+        if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
+            return -1;
+    }
+
+    if (!encode_der_dsa_sig(&pkt, sig->r, sig->s)
+            || !WPACKET_get_total_written(&pkt, &encoded_len)
+            || !WPACKET_finish(&pkt)) {
+        BUF_MEM_free(buf);
+        WPACKET_cleanup(&pkt);
+        return -1;
+    }
+
+    if (ppout != NULL) {
+        if (*ppout == NULL) {
+            *ppout = (unsigned char *)buf->data;
+            buf->data = NULL;
+            BUF_MEM_free(buf);
+        } else {
+            *ppout += encoded_len;
+        }
+    }
+
+    return (int)encoded_len;
+}
+
+int DSA_size(const DSA *dsa)
+{
+    int ret;
+    DSA_SIG sig;
+
+    sig.r = sig.s = dsa->q;
+    ret = i2d_DSA_SIG(&sig, NULL);
+
+    if (ret < 0)
+        ret = 0;
+    return ret;
+}
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
+                 int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+    DSA_SIG *s;
+
+    /* legacy case uses the method table */
+    if (libctx == NULL || dsa->meth != DSA_get_default_method())
+        s = DSA_do_sign(dgst, dlen, dsa);
+    else
+        s = dsa_do_sign_int(libctx, dgst, dlen, dsa);
+    if (s == NULL) {
+        *siglen = 0;
+        return 0;
+    }
+    *siglen = i2d_DSA_SIG(s, &sig);
+    DSA_SIG_free(s);
+    return 1;
+}
+
+int DSA_sign(int type, const unsigned char *dgst, int dlen,
+             unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+    return dsa_sign_int(NULL, type, dgst, dlen, sig, siglen, dsa);
+}
+
+/* data has already been hashed (probably with SHA or SHA-1). */
+/*-
+ * returns
+ *      1: correct signature
+ *      0: incorrect signature
+ *     -1: error
+ */
+int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
+               const unsigned char *sigbuf, int siglen, DSA *dsa)
+{
+    DSA_SIG *s;
+    const unsigned char *p = sigbuf;
+    unsigned char *der = NULL;
+    int derlen = -1;
+    int ret = -1;
+
+    s = DSA_SIG_new();
+    if (s == NULL)
+        return ret;
+    if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
+        goto err;
+    /* Ensure signature uses DER and doesn't have trailing garbage */
+    derlen = i2d_DSA_SIG(s, &der);
+    if (derlen != siglen || memcmp(sigbuf, der, derlen))
+        goto err;
+    ret = DSA_do_verify(dgst, dgst_len, s, dsa);
+ err:
+    OPENSSL_clear_free(der, derlen);
+    DSA_SIG_free(s);
+    return ret;
+}
+
index 156b260..71e0eba 100644 (file)
@@ -1,19 +1,18 @@
 LIBS=../../libcrypto
 $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \
         mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \
-        m_sigver.c
+        m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c
+
 SOURCE[../../libcrypto]=$COMMON\
         encode.c evp_key.c evp_cnf.c \
         e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
         e_rc4.c e_aes.c names.c e_seed.c e_aria.c e_sm4.c \
-        e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
-        m_null.c \
-        p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
+        e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c m_null.c \
+        p_open.c p_seal.c p_sign.c p_verify.c p_enc.c p_dec.c \
         bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
         c_allc.c c_alld.c bio_ok.c \
         evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
-        pkey_kdf.c \
-        e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c \
+        pkey_kdf.c e_old.c pmeth_fn.c\
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
         e_chacha20_poly1305.c \
         pkey_mac.c exchange.c \
index 59cadb4..5c11ce1 100644 (file)
@@ -28,7 +28,9 @@
 #include "crypto/evp.h"
 #include "internal/provider.h"
 
-static void EVP_PKEY_free_it(EVP_PKEY *x);
+static void evp_pkey_free_it(EVP_PKEY *key);
+
+#ifndef FIPS_MODE
 
 int EVP_PKEY_bits(const EVP_PKEY *pkey)
 {
@@ -46,16 +48,9 @@ int EVP_PKEY_security_bits(const EVP_PKEY *pkey)
     return pkey->ameth->pkey_security_bits(pkey);
 }
 
-int EVP_PKEY_size(const EVP_PKEY *pkey)
-{
-    if (pkey && pkey->ameth && pkey->ameth->pkey_size)
-        return pkey->ameth->pkey_size(pkey);
-    return 0;
-}
-
 int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
 {
-#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_DSA
     if (pkey->type == EVP_PKEY_DSA) {
         int ret = pkey->save_parameters;
 
@@ -63,8 +58,8 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
             pkey->save_parameters = mode;
         return ret;
     }
-#endif
-#ifndef OPENSSL_NO_EC
+# endif
+# ifndef OPENSSL_NO_EC
     if (pkey->type == EVP_PKEY_EC) {
         int ret = pkey->save_parameters;
 
@@ -72,7 +67,7 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
             pkey->save_parameters = mode;
         return ret;
     }
-#endif
+# endif
     return 0;
 }
 
@@ -141,38 +136,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
     return -2;
 }
 
-EVP_PKEY *EVP_PKEY_new(void)
-{
-    EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
-
-    if (ret == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-    ret->type = EVP_PKEY_NONE;
-    ret->save_type = EVP_PKEY_NONE;
-    ret->references = 1;
-    ret->save_parameters = 1;
-    ret->lock = CRYPTO_THREAD_lock_new();
-    if (ret->lock == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
-        OPENSSL_free(ret);
-        return NULL;
-    }
-    return ret;
-}
-
-int EVP_PKEY_up_ref(EVP_PKEY *pkey)
-{
-    int i;
-
-    if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
-        return 0;
-
-    REF_PRINT_COUNT("EVP_PKEY", pkey);
-    REF_ASSERT_ISNT(i < 2);
-    return ((i > 1) ? 1 : 0);
-}
 
 /*
  * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
@@ -187,29 +150,29 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
 
     if (pkey) {
         if (pkey->pkey.ptr)
-            EVP_PKEY_free_it(pkey);
+            evp_pkey_free_it(pkey);
         /*
          * If key type matches and a method exists then this lookup has
          * succeeded once so just indicate success.
          */
         if ((type == pkey->save_type) && pkey->ameth)
             return 1;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
         /* If we have ENGINEs release them */
         ENGINE_finish(pkey->engine);
         pkey->engine = NULL;
         ENGINE_finish(pkey->pmeth_engine);
         pkey->pmeth_engine = NULL;
-#endif
+# endif
     }
     if (str)
         ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
     else
         ameth = EVP_PKEY_asn1_find(eptr, type);
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     if (pkey == NULL && eptr != NULL)
         ENGINE_finish(e);
-#endif
+# endif
     if (ameth == NULL) {
         EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
         return 0;
@@ -321,10 +284,10 @@ int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
 EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
                                 size_t len, const EVP_CIPHER *cipher)
 {
-#ifndef OPENSSL_NO_CMAC
-# ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_CMAC
+#  ifndef OPENSSL_NO_ENGINE
     const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL;
-# endif
+#  endif
     const char *cipher_name = EVP_CIPHER_name(cipher);
     const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher);
     OPENSSL_CTX *libctx =
@@ -342,11 +305,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
         goto err;
     }
 
-# ifndef OPENSSL_NO_ENGINE
+#  ifndef OPENSSL_NO_ENGINE
     if (engine_id != NULL)
         params[paramsn++] =
             OSSL_PARAM_construct_utf8_string("engine", (char *)engine_id, 0);
-# endif
+#  endif
 
     params[paramsn++] =
         OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
@@ -369,11 +332,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
     EVP_MAC_CTX_free(cmctx);
     EVP_MAC_free(cmac);
     return NULL;
-#else
+# else
     EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
            EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return NULL;
-#endif
+# endif
 }
 
 int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
@@ -405,7 +368,7 @@ int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
     return 1;
 }
 
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
 int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
 {
     if (e != NULL) {
@@ -428,7 +391,7 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
 {
     return pkey->engine;
 }
-#endif
+# endif
 int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
 {
     if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
@@ -454,7 +417,7 @@ const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
     return os->data;
 }
 
-#ifndef OPENSSL_NO_POLY1305
+# ifndef OPENSSL_NO_POLY1305
 const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
 {
     ASN1_OCTET_STRING *os = NULL;
@@ -466,9 +429,9 @@ const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
     *len = os->length;
     return os->data;
 }
-#endif
+# endif
 
-#ifndef OPENSSL_NO_SIPHASH
+# ifndef OPENSSL_NO_SIPHASH
 const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
 {
     ASN1_OCTET_STRING *os = NULL;
@@ -481,9 +444,9 @@ const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
     *len = os->length;
     return os->data;
 }
-#endif
+# endif
 
-#ifndef OPENSSL_NO_RSA
+# ifndef OPENSSL_NO_RSA
 int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
 {
     int ret = EVP_PKEY_assign_RSA(pkey, key);
@@ -508,9 +471,9 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
         RSA_up_ref(ret);
     return ret;
 }
-#endif
+# endif
 
-#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_DSA
 int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
 {
     int ret = EVP_PKEY_assign_DSA(pkey, key);
@@ -535,9 +498,9 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
         DSA_up_ref(ret);
     return ret;
 }
-#endif
+# endif
 
-#ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_EC
 
 int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
 {
@@ -563,9 +526,9 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
         EC_KEY_up_ref(ret);
     return ret;
 }
-#endif
+# endif
 
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
 
 int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
 {
@@ -593,7 +556,7 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
         DH_up_ref(ret);
     return ret;
 }
-#endif
+# endif
 
 int EVP_PKEY_type(int type)
 {
@@ -605,9 +568,9 @@ int EVP_PKEY_type(int type)
         ret = ameth->pkey_id;
     else
         ret = NID_undef;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(e);
-#endif
+# endif
     return ret;
 }
 
@@ -621,41 +584,6 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey)
     return EVP_PKEY_type(pkey->type);
 }
 
-void EVP_PKEY_free(EVP_PKEY *x)
-{
-    int i;
-
-    if (x == NULL)
-        return;
-
-    CRYPTO_DOWN_REF(&x->references, &i, x->lock);
-    REF_PRINT_COUNT("EVP_PKEY", x);
-    if (i > 0)
-        return;
-    REF_ASSERT_ISNT(i < 0);
-    EVP_PKEY_free_it(x);
-    CRYPTO_THREAD_lock_free(x->lock);
-    sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
-    OPENSSL_free(x);
-}
-
-static void EVP_PKEY_free_it(EVP_PKEY *x)
-{
-    /* internal function; x is never NULL */
-
-    evp_keymgmt_clear_pkey_cache(x);
-
-    if (x->ameth && x->ameth->pkey_free) {
-        x->ameth->pkey_free(x);
-        x->pkey.ptr = NULL;
-    }
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_finish(x->engine);
-    x->engine = NULL;
-    ENGINE_finish(x->pmeth_engine);
-    x->pmeth_engine = NULL;
-#endif
-}
 
 static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
 {
@@ -807,3 +735,87 @@ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt)
         return 0;
     return rv;
 }
+
+#endif /* FIPS_MODE */
+
+/*- All methods below can also be used in FIPS_MODE */
+
+EVP_PKEY *EVP_PKEY_new(void)
+{
+    EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+    if (ret == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    ret->type = EVP_PKEY_NONE;
+    ret->save_type = EVP_PKEY_NONE;
+    ret->references = 1;
+    ret->save_parameters = 1;
+    ret->lock = CRYPTO_THREAD_lock_new();
+    if (ret->lock == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+int EVP_PKEY_up_ref(EVP_PKEY *pkey)
+{
+    int i;
+
+    if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
+        return 0;
+
+    REF_PRINT_COUNT("EVP_PKEY", pkey);
+    REF_ASSERT_ISNT(i < 2);
+    return ((i > 1) ? 1 : 0);
+}
+
+static void evp_pkey_free_it(EVP_PKEY *x)
+{
+    /* internal function; x is never NULL */
+
+    evp_keymgmt_clear_pkey_cache(x);
+
+    if (x->ameth && x->ameth->pkey_free) {
+        x->ameth->pkey_free(x);
+        x->pkey.ptr = NULL;
+    }
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+    ENGINE_finish(x->engine);
+    x->engine = NULL;
+    ENGINE_finish(x->pmeth_engine);
+    x->pmeth_engine = NULL;
+#endif
+}
+
+void EVP_PKEY_free(EVP_PKEY *x)
+{
+    int i;
+
+    if (x == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&x->references, &i, x->lock);
+    REF_PRINT_COUNT("EVP_PKEY", x);
+    if (i > 0)
+        return;
+    REF_ASSERT_ISNT(i < 0);
+    evp_pkey_free_it(x);
+    CRYPTO_THREAD_lock_free(x->lock);
+#ifndef FIPS_MODE
+    sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
+#endif
+    OPENSSL_free(x);
+}
+
+/* TODO (3.0) : Needs to call getparams fo non legacy case */
+int EVP_PKEY_size(const EVP_PKEY *pkey)
+{
+    if (pkey && pkey->ameth && pkey->ameth->pkey_size)
+        return pkey->ameth->pkey_size(pkey);
+    return 0;
+}
+
index 3d0ee2e..31422ba 100644 (file)
 #include "internal/provider.h"
 #include "evp_local.h"
 
-static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
-{
-    EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE));
-
-    if (signature == NULL) {
-        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    signature->lock = CRYPTO_THREAD_lock_new();
-    if (signature->lock == NULL) {
-        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
-        OPENSSL_free(signature);
-        return NULL;
-    }
-    signature->prov = prov;
-    ossl_provider_up_ref(prov);
-    signature->refcnt = 1;
-
-    return signature;
-}
-
-static void *evp_signature_from_dispatch(int name_id,
-                                         const OSSL_DISPATCH *fns,
-                                         OSSL_PROVIDER *prov)
-{
-    EVP_SIGNATURE *signature = NULL;
-    int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0;
-    int digsignfncnt = 0, digverifyfncnt = 0;
-    int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0;
-
-    if ((signature = evp_signature_new(prov)) == NULL) {
-        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
-    signature->name_id = name_id;
-
-    for (; fns->function_id != 0; fns++) {
-        switch (fns->function_id) {
-        case OSSL_FUNC_SIGNATURE_NEWCTX:
-            if (signature->newctx != NULL)
-                break;
-            signature->newctx = OSSL_get_OP_signature_newctx(fns);
-            ctxfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SIGN_INIT:
-            if (signature->sign_init != NULL)
-                break;
-            signature->sign_init = OSSL_get_OP_signature_sign_init(fns);
-            signfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SIGN:
-            if (signature->sign != NULL)
-                break;
-            signature->sign = OSSL_get_OP_signature_sign(fns);
-            signfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_VERIFY_INIT:
-            if (signature->verify_init != NULL)
-                break;
-            signature->verify_init = OSSL_get_OP_signature_verify_init(fns);
-            verifyfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_VERIFY:
-            if (signature->verify != NULL)
-                break;
-            signature->verify = OSSL_get_OP_signature_verify(fns);
-            verifyfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT:
-            if (signature->verify_recover_init != NULL)
-                break;
-            signature->verify_recover_init
-                = OSSL_get_OP_signature_verify_recover_init(fns);
-            verifyrecfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER:
-            if (signature->verify_recover != NULL)
-                break;
-            signature->verify_recover
-                = OSSL_get_OP_signature_verify_recover(fns);
-            verifyrecfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:
-            if (signature->digest_sign_init != NULL)
-                break;
-            signature->digest_sign_init
-                = OSSL_get_OP_signature_digest_sign_init(fns);
-            digsignfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE:
-            if (signature->digest_sign_update != NULL)
-                break;
-            signature->digest_sign_update
-                = OSSL_get_OP_signature_digest_sign_update(fns);
-            digsignfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL:
-            if (signature->digest_sign_final != NULL)
-                break;
-            signature->digest_sign_final
-                = OSSL_get_OP_signature_digest_sign_final(fns);
-            digsignfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT:
-            if (signature->digest_verify_init != NULL)
-                break;
-            signature->digest_verify_init
-                = OSSL_get_OP_signature_digest_verify_init(fns);
-            digverifyfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE:
-            if (signature->digest_verify_update != NULL)
-                break;
-            signature->digest_verify_update
-                = OSSL_get_OP_signature_digest_verify_update(fns);
-            digverifyfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL:
-            if (signature->digest_verify_final != NULL)
-                break;
-            signature->digest_verify_final
-                = OSSL_get_OP_signature_digest_verify_final(fns);
-            digverifyfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_FREECTX:
-            if (signature->freectx != NULL)
-                break;
-            signature->freectx = OSSL_get_OP_signature_freectx(fns);
-            ctxfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_DUPCTX:
-            if (signature->dupctx != NULL)
-                break;
-            signature->dupctx = OSSL_get_OP_signature_dupctx(fns);
-            break;
-        case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS:
-            if (signature->get_ctx_params != NULL)
-                break;
-            signature->get_ctx_params
-                = OSSL_get_OP_signature_get_ctx_params(fns);
-            gparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS:
-            if (signature->gettable_ctx_params != NULL)
-                break;
-            signature->gettable_ctx_params
-                = OSSL_get_OP_signature_gettable_ctx_params(fns);
-            gparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS:
-            if (signature->set_ctx_params != NULL)
-                break;
-            signature->set_ctx_params
-                = OSSL_get_OP_signature_set_ctx_params(fns);
-            sparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS:
-            if (signature->settable_ctx_params != NULL)
-                break;
-            signature->settable_ctx_params
-                = OSSL_get_OP_signature_settable_ctx_params(fns);
-            sparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS:
-            if (signature->get_ctx_md_params != NULL)
-                break;
-            signature->get_ctx_md_params
-                = OSSL_get_OP_signature_get_ctx_md_params(fns);
-            gmdparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS:
-            if (signature->gettable_ctx_md_params != NULL)
-                break;
-            signature->gettable_ctx_md_params
-                = OSSL_get_OP_signature_gettable_ctx_md_params(fns);
-            gmdparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS:
-            if (signature->set_ctx_md_params != NULL)
-                break;
-            signature->set_ctx_md_params
-                = OSSL_get_OP_signature_set_ctx_md_params(fns);
-            smdparamfncnt++;
-            break;
-        case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS:
-            if (signature->settable_ctx_md_params != NULL)
-                break;
-            signature->settable_ctx_md_params
-                = OSSL_get_OP_signature_settable_ctx_md_params(fns);
-            smdparamfncnt++;
-            break;
-        }
-    }
-    if (ctxfncnt != 2
-        || (signfncnt == 0
-            && verifyfncnt == 0
-            && verifyrecfncnt == 0
-            && digsignfncnt == 0
-            && digverifyfncnt == 0)
-        || (signfncnt != 0 && signfncnt != 2)
-        || (verifyfncnt != 0 && verifyfncnt != 2)
-        || (verifyrecfncnt != 0 && verifyrecfncnt != 2)
-        || (digsignfncnt != 0 && digsignfncnt != 3)
-        || (digverifyfncnt != 0 && digverifyfncnt != 3)
-        || (gparamfncnt != 0 && gparamfncnt != 2)
-        || (sparamfncnt != 0 && sparamfncnt != 2)
-        || (gmdparamfncnt != 0 && gmdparamfncnt != 2)
-        || (smdparamfncnt != 0 && smdparamfncnt != 2)) {
-        /*
-         * In order to be a consistent set of functions we must have at least
-         * a set of context functions (newctx and freectx) as well as a set of
-         * "signature" functions:
-         *  (sign_init, sign) or
-         *  (verify_init verify) or
-         *  (verify_recover_init, verify_recover) or
-         *  (digest_sign_init, digest_sign_update, digest_sign_final) or
-         *  (digest_verify_init, digest_verify_update, digest_verify_final).
-         *
-         * set_ctx_params and settable_ctx_params are optional, but if one of
-         * them is present then the other one must also be present. The same
-         * applies to get_ctx_params and gettable_ctx_params. The same rules
-         * apply to the "md_params" functions. The dupctx function is optional.
-         */
-        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
-        goto err;
-    }
-
-    return signature;
- err:
-    EVP_SIGNATURE_free(signature);
-    return NULL;
-}
-
-void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
-{
-    if (signature != NULL) {
-        int i;
-
-        CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock);
-        if (i > 0)
-            return;
-        ossl_provider_free(signature->prov);
-        CRYPTO_THREAD_lock_free(signature->lock);
-        OPENSSL_free(signature);
-    }
-}
-
-int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature)
-{
-    int ref = 0;
-
-    CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock);
-    return 1;
-}
-
-OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature)
-{
-    return signature->prov;
-}
-
-EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
-                                   const char *properties)
-{
-    return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties,
-                             evp_signature_from_dispatch,
-                             (int (*)(void *))EVP_SIGNATURE_up_ref,
-                             (void (*)(void *))EVP_SIGNATURE_free);
-}
-
-int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name)
-{
-    return evp_is_a(signature->prov, signature->name_id, name);
-}
-
-int EVP_SIGNATURE_number(const EVP_SIGNATURE *signature)
-{
-    return signature->name_id;
-}
-
-void EVP_SIGNATURE_do_all_provided(OPENSSL_CTX *libctx,
-                                   void (*fn)(EVP_SIGNATURE *signature,
-                                              void *arg),
-                                   void *arg)
-{
-    evp_generic_do_all(libctx, OSSL_OP_SIGNATURE,
-                       (void (*)(void *, void *))fn, arg,
-                       evp_signature_from_dispatch,
-                       (void (*)(void *))EVP_SIGNATURE_free);
-}
-
-
-void EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature,
-                                void (*fn)(const char *name, void *data),
-                                void *data)
-{
-    if (signature->prov != NULL)
-        evp_names_do_all(signature->prov, signature->name_id, fn, data);
-}
-
-static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
-{
-    int ret = 0;
-    void *provkey = NULL;
-    EVP_SIGNATURE *signature = NULL;
-
-    if (ctx == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    evp_pkey_ctx_free_old_ops(ctx);
-    ctx->operation = operation;
-
-    if (ctx->keytype == NULL)
-        goto legacy;
-
-    if (ctx->keymgmt == NULL)
-        ctx->keymgmt =
-            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
-    if (ctx->keymgmt != NULL) {
-        const char *supported_sig = NULL;
-
-        if (ctx->keymgmt->query_operation_name != NULL)
-            supported_sig =
-                ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE);
-
-        /*
-         * If we didn't get a supported sig, assume there is one with the
-         * same name as the key type.
-         */
-        if (supported_sig == NULL)
-            supported_sig = ctx->keytype;
-
-        /*
-         * Because we cleared out old ops, we shouldn't need to worry about
-         * checking if signature is already there.
-         */
-        signature =
-            EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery);
-    }
-
-    if (ctx->keymgmt == NULL
-        || signature == NULL
-        || (EVP_KEYMGMT_provider(ctx->keymgmt)
-            != EVP_SIGNATURE_provider(signature))) {
-        /*
-         * We don't have the full support we need with provided methods,
-         * let's go see if legacy does.  Also, we don't need to free
-         * ctx->keymgmt here, as it's not necessarily tied to this
-         * operation.  It will be freed by EVP_PKEY_CTX_free().
-         */
-        EVP_SIGNATURE_free(signature);
-        goto legacy;
-    }
-
-    ctx->op.sig.signature = signature;
-
-    if (ctx->pkey != NULL) {
-        provkey =
-            evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
-        /* If export failed, legacy may be able to pick it up */
-        if (provkey == NULL)
-            goto legacy;
-    }
-    ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov));
-    if (ctx->op.sig.sigprovctx == NULL) {
-        /* The provider key can stay in the cache */
-        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-        goto err;
-    }
-
-    switch (operation) {
-    case EVP_PKEY_OP_SIGN:
-        if (signature->sign_init == NULL) {
-            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-            ret = -2;
-            goto err;
-        }
-        ret = signature->sign_init(ctx->op.sig.sigprovctx, provkey);
-        break;
-    case EVP_PKEY_OP_VERIFY:
-        if (signature->verify_init == NULL) {
-            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-            ret = -2;
-            goto err;
-        }
-        ret = signature->verify_init(ctx->op.sig.sigprovctx, provkey);
-        break;
-    case EVP_PKEY_OP_VERIFYRECOVER:
-        if (signature->verify_recover_init == NULL) {
-            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-            ret = -2;
-            goto err;
-        }
-        ret = signature->verify_recover_init(ctx->op.sig.sigprovctx, provkey);
-        break;
-    default:
-        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-        goto err;
-    }
-
-    if (ret <= 0) {
-        signature->freectx(ctx->op.sig.sigprovctx);
-        ctx->op.sig.sigprovctx = NULL;
-        goto err;
-    }
-    return 1;
-
- legacy:
-    if (ctx->pmeth == NULL
-            || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL)
-            || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL)
-            || (operation == EVP_PKEY_OP_VERIFYRECOVER
-                && ctx->pmeth->verify_recover == NULL)) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    switch (operation) {
-    case EVP_PKEY_OP_SIGN:
-        if (ctx->pmeth->sign_init == NULL)
-            return 1;
-        ret = ctx->pmeth->sign_init(ctx);
-        break;
-    case EVP_PKEY_OP_VERIFY:
-        if (ctx->pmeth->verify_init == NULL)
-            return 1;
-        ret = ctx->pmeth->verify_init(ctx);
-        break;
-    case EVP_PKEY_OP_VERIFYRECOVER:
-        if (ctx->pmeth->verify_recover_init == NULL)
-            return 1;
-        ret = ctx->pmeth->verify_recover_init(ctx);
-        break;
-    default:
-        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-        goto err;
-    }
-    if (ret <= 0)
-        goto err;
-    return ret;
-
- err:
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return ret;
-}
-
-int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
-{
-    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN);
-}
-
-int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
-                  unsigned char *sig, size_t *siglen,
-                  const unsigned char *tbs, size_t tbslen)
-{
-    int ret;
-
-    if (ctx == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    if (ctx->operation != EVP_PKEY_OP_SIGN) {
-        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
-        return -1;
-    }
-
-    if (ctx->op.sig.sigprovctx == NULL)
-        goto legacy;
-
-    ret = ctx->op.sig.signature->sign(ctx->op.sig.sigprovctx, sig, siglen,
-                                      SIZE_MAX, tbs, tbslen);
-
-    return ret;
- legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
-        return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
-}
-
-int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
-{
-    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY);
-}
-
-int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
-                    const unsigned char *sig, size_t siglen,
-                    const unsigned char *tbs, size_t tbslen)
-{
-    int ret;
-
-    if (ctx == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    if (ctx->operation != EVP_PKEY_OP_VERIFY) {
-        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
-        return -1;
-    }
-
-    if (ctx->op.sig.sigprovctx == NULL)
-        goto legacy;
-
-    ret = ctx->op.sig.signature->verify(ctx->op.sig.sigprovctx, sig, siglen,
-                                        tbs, tbslen);
-
-    return ret;
- legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
-}
-
-int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
-{
-    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER);
-}
-
-int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
-                            unsigned char *rout, size_t *routlen,
-                            const unsigned char *sig, size_t siglen)
-{
-    int ret;
-
-    if (ctx == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
-        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
-        return -1;
-    }
-
-    if (ctx->op.sig.sigprovctx == NULL)
-        goto legacy;
-
-    ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.sigprovctx, rout,
-                                                routlen,
-                                                (rout == NULL ? 0 : *routlen),
-                                                sig, siglen);
-    return ret;
- legacy:
-    if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) {
-        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-    M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
-        return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
-}
-
 static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
 {
     int ret = 0;
index 100931c..14c5fd4 100644 (file)
 #include "crypto/evp.h"
 #include "evp_local.h"
 
-static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
-{
-    if (ctx == NULL || ctx->keytype == NULL)
-        goto not_supported;
-
-    evp_pkey_ctx_free_old_ops(ctx);
-    ctx->operation = operation;
-    if (ctx->keymgmt == NULL)
-        ctx->keymgmt = EVP_KEYMGMT_fetch(NULL, ctx->keytype, ctx->propquery);
-    if (ctx->keymgmt == NULL)
-        goto not_supported;
-
-    return 1;
-
- not_supported:
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-    return -2;
-}
-
-int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx)
-{
-    return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA);
-}
-
-int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
-{
-    return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA);
-}
-
-int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
-{
-    void *provdata = NULL;
-
-    if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        return -2;
-    }
-
-    if (ppkey == NULL)
-        return -1;
-
-    if (*ppkey == NULL)
-        *ppkey = EVP_PKEY_new();
-
-    if (*ppkey == NULL) {
-        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
-        return -1;
-    }
-
-    provdata =
-        evp_keymgmt_fromdata(*ppkey, ctx->keymgmt, params,
-                             ctx->operation == EVP_PKEY_OP_PARAMFROMDATA);
-
-    if (provdata == NULL)
-        return 0;
-    /* provdata is cached in *ppkey, so we need not bother with it further */
-    return 1;
-}
-
-/*
- * TODO(3.0) Re-evaluate the names, it's possible that we find these to be
- * better:
- *
- * EVP_PKEY_param_settable()
- * EVP_PKEY_param_gettable()
- */
-const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
-{
-    /* We call fromdata_init to get ctx->keymgmt populated */
-    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
-        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
-    return NULL;
-}
-
-const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
-{
-    /* We call fromdata_init to get ctx->keymgmt populated */
-    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
-        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
-    return NULL;
-}
-
+#ifndef FIPS_MODE
 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
 {
     int ret;
@@ -321,3 +239,93 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
 
     return pkey->ameth->pkey_param_check(pkey);
 }
+
+#endif /* FIPS_MODE */
+
+/*- All methods below can also be used in FIPS_MODE */
+
+static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
+{
+    if (ctx == NULL || ctx->keytype == NULL)
+        goto not_supported;
+
+    evp_pkey_ctx_free_old_ops(ctx);
+    ctx->operation = operation;
+    if (ctx->keymgmt == NULL)
+        ctx->keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype,
+                                         ctx->propquery);
+    if (ctx->keymgmt == NULL)
+        goto not_supported;
+
+    return 1;
+
+ not_supported:
+    ctx->operation = EVP_PKEY_OP_UNDEFINED;
+    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    return -2;
+}
+
+int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx)
+{
+    return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA);
+}
+
+int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
+{
+    return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA);
+}
+
+int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
+{
+    void *provdata = NULL;
+
+    if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    if (ppkey == NULL)
+        return -1;
+
+    if (*ppkey == NULL)
+        *ppkey = EVP_PKEY_new();
+
+    if (*ppkey == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+
+    provdata =
+        evp_keymgmt_fromdata(*ppkey, ctx->keymgmt, params,
+                             ctx->operation == EVP_PKEY_OP_PARAMFROMDATA);
+
+    if (provdata == NULL)
+        return 0;
+    /* provdata is cached in *ppkey, so we need not bother with it further */
+    return 1;
+}
+
+/*
+ * TODO(3.0) Re-evaluate the names, it's possible that we find these to be
+ * better:
+ *
+ * EVP_PKEY_param_settable()
+ * EVP_PKEY_param_gettable()
+ */
+const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
+{
+    /* We call fromdata_init to get ctx->keymgmt populated */
+    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
+        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
+    return NULL;
+}
+
+const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
+{
+    /* We call fromdata_init to get ctx->keymgmt populated */
+    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
+        return evp_keymgmt_importdomparam_types(ctx->keymgmt);
+    return NULL;
+}
+
+
index 2ecc177..428b97b 100644 (file)
@@ -23,6 +23,8 @@
 #include "internal/provider.h"
 #include "evp_local.h"
 
+#ifndef FIPS_MODE
+
 typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
 typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
 
@@ -30,50 +32,50 @@ static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
 
 /* This array needs to be in order of NIDs */
 static pmeth_fn standard_methods[] = {
-#ifndef OPENSSL_NO_RSA
+# ifndef OPENSSL_NO_RSA
     rsa_pkey_method,
-#endif
-#ifndef OPENSSL_NO_DH
+# endif
+# ifndef OPENSSL_NO_DH
     dh_pkey_method,
-#endif
-#ifndef OPENSSL_NO_DSA
+# endif
+# ifndef OPENSSL_NO_DSA
     dsa_pkey_method,
-#endif
-#ifndef OPENSSL_NO_EC
+# endif
+# ifndef OPENSSL_NO_EC
     ec_pkey_method,
-#endif
+# endif
     hmac_pkey_method,
-#ifndef OPENSSL_NO_CMAC
+# ifndef OPENSSL_NO_CMAC
     cmac_pkey_method,
-#endif
-#ifndef OPENSSL_NO_RSA
+# endif
+# ifndef OPENSSL_NO_RSA
     rsa_pss_pkey_method,
-#endif
-#ifndef OPENSSL_NO_DH
+# endif
+# ifndef OPENSSL_NO_DH
     dhx_pkey_method,
-#endif
-#ifndef OPENSSL_NO_SCRYPT
+# endif
+# ifndef OPENSSL_NO_SCRYPT
     scrypt_pkey_method,
-#endif
+# endif
     tls1_prf_pkey_method,
-#ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_EC
     ecx25519_pkey_method,
     ecx448_pkey_method,
-#endif
+# endif
     hkdf_pkey_method,
-#ifndef OPENSSL_NO_POLY1305
+# ifndef OPENSSL_NO_POLY1305
     poly1305_pkey_method,
-#endif
-#ifndef OPENSSL_NO_SIPHASH
+# endif
+# ifndef OPENSSL_NO_SIPHASH
     siphash_pkey_method,
-#endif
-#ifndef OPENSSL_NO_EC
+# endif
+# ifndef OPENSSL_NO_EC
     ed25519_pkey_method,
     ed448_pkey_method,
-#endif
-#ifndef OPENSSL_NO_SM2
+# endif
+# ifndef OPENSSL_NO_SM2
     sm2_pkey_method,
-#endif
+# endif
 };
 
 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func);
@@ -112,10 +114,27 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
     return (**ret)();
 }
 
+EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
+{
+    EVP_PKEY_METHOD *pmeth;
+
+    pmeth = OPENSSL_zalloc(sizeof(*pmeth));
+    if (pmeth == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    pmeth->pkey_id = id;
+    pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
+    return pmeth;
+}
+#endif /* FIPS_MODE */
+
 static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
                                  EVP_PKEY *pkey, ENGINE *e,
                                  const char *name, const char *propquery,
                                  int id)
+
 {
     EVP_PKEY_CTX *ret;
     const EVP_PKEY_METHOD *pmeth = NULL;
@@ -131,7 +150,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
      * If the key doesn't contain anything legacy, then it must be provided,
      * so we extract the necessary information and use that.
      */
-    if (pkey != NULL && pkey->ameth == NULL) {
+    if (pkey != NULL && pkey->pkey.ptr == NULL) {
         /* If we have an engine, something went wrong somewhere... */
         if (!ossl_assert(e == NULL))
             return NULL;
@@ -143,7 +162,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
          */
         goto common;
     }
-
+#ifndef FIPS_MODE
     /* TODO(3.0) Legacy code should be removed when all is provider based */
     /* BEGIN legacy */
     if (id == -1) {
@@ -179,7 +198,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
      */
     libctx = NULL;
 
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     if (e == NULL && pkey != NULL)
         e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
     /* Try to find an ENGINE which implements this method */
@@ -199,22 +218,22 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
     if (e)
         pmeth = ENGINE_get_pkey_meth(e, id);
     else
-#endif
+# endif
         pmeth = EVP_PKEY_meth_find(id);
 
     if (pmeth == NULL) {
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
         ENGINE_finish(e);
-#endif
+# endif
         EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
         return NULL;
     }
     /* END legacy */
-
+#endif /* FIPS_MODE */
  common:
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
         ENGINE_finish(e);
 #endif
         EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
@@ -241,20 +260,37 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
     return ret;
 }
 
+/*- All methods below can also be used in FIPS_MODE */
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx,
+                                         const char *name,
+                                         const char *propquery)
+{
+    return int_ctx_new(libctx, NULL, NULL, name, propquery, -1);
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx, EVP_PKEY *pkey)
+{
+    return int_ctx_new(libctx, pkey, NULL, NULL, NULL, -1);
+}
+
 void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
 {
-    if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
-        if (ctx->op.kex.exchprovctx != NULL && ctx->op.kex.exchange != NULL)
-            ctx->op.kex.exchange->freectx(ctx->op.kex.exchprovctx);
-        EVP_KEYEXCH_free(ctx->op.kex.exchange);
-        ctx->op.kex.exchprovctx = NULL;
-        ctx->op.kex.exchange = NULL;
-    } else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+    if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
         if (ctx->op.sig.sigprovctx != NULL && ctx->op.sig.signature != NULL)
             ctx->op.sig.signature->freectx(ctx->op.sig.sigprovctx);
         EVP_SIGNATURE_free(ctx->op.sig.signature);
         ctx->op.sig.sigprovctx = NULL;
         ctx->op.sig.signature = NULL;
+    }
+/* TODO(3.0): add dependancies and uncomment this when available for fips mode */
+#ifndef FIPS_MODE
+    else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+        if (ctx->op.kex.exchprovctx != NULL && ctx->op.kex.exchange != NULL)
+            ctx->op.kex.exchange->freectx(ctx->op.kex.exchprovctx);
+        EVP_KEYEXCH_free(ctx->op.kex.exchange);
+        ctx->op.kex.exchprovctx = NULL;
+        ctx->op.kex.exchange = NULL;
     } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
         if (ctx->op.ciph.ciphprovctx != NULL && ctx->op.ciph.cipher != NULL)
             ctx->op.ciph.cipher->freectx(ctx->op.ciph.ciphprovctx);
@@ -262,23 +298,29 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
         ctx->op.ciph.ciphprovctx = NULL;
         ctx->op.ciph.cipher = NULL;
     }
+#endif
 }
 
-EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
+void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
 {
-    EVP_PKEY_METHOD *pmeth;
+    if (ctx == NULL)
+        return;
+    if (ctx->pmeth && ctx->pmeth->cleanup)
+        ctx->pmeth->cleanup(ctx);
 
-    pmeth = OPENSSL_zalloc(sizeof(*pmeth));
-    if (pmeth == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
+    evp_pkey_ctx_free_old_ops(ctx);
+    EVP_KEYMGMT_free(ctx->keymgmt);
 
-    pmeth->pkey_id = id;
-    pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
-    return pmeth;
+    EVP_PKEY_free(ctx->pkey);
+    EVP_PKEY_free(ctx->peerkey);
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+    ENGINE_finish(ctx->engine);
+#endif
+    OPENSSL_free(ctx);
 }
 
+#ifndef FIPS_MODE
+
 void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
                              const EVP_PKEY_METHOD *meth)
 {
@@ -347,12 +389,6 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
     return int_ctx_new(NULL, NULL, e, NULL, NULL, id);
 }
 
-EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx,
-                                        const char *name,
-                                        const char *propquery)
-{
-    return int_ctx_new(libctx, NULL, NULL, name, propquery, -1);
-}
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
 {
@@ -364,13 +400,13 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
                 || (EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)
                     && pctx->op.sig.sigprovctx == NULL)))
         return NULL;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     /* Make sure it's safe to copy a pkey context using an ENGINE */
     if (pctx->engine && !ENGINE_init(pctx->engine)) {
         EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB);
         return 0;
     }
-#endif
+# endif
     rctx = OPENSSL_zalloc(sizeof(*rctx));
     if (rctx == NULL) {
         EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_MALLOC_FAILURE);
@@ -448,9 +484,9 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
     }
 
     rctx->pmeth = pctx->pmeth;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     rctx->engine = pctx->engine;
-#endif
+# endif
 
     if (pctx->peerkey)
         EVP_PKEY_up_ref(pctx->peerkey);
@@ -517,25 +553,32 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx)
         return NULL;
     return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
 }
+#endif
 
-void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
+int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
 {
-    if (ctx == NULL)
-        return;
-    if (ctx->pmeth && ctx->pmeth->cleanup)
-        ctx->pmeth->cleanup(ctx);
-
-    evp_pkey_ctx_free_old_ops(ctx);
-    EVP_KEYMGMT_free(ctx->keymgmt);
-
-    EVP_PKEY_free(ctx->pkey);
-    EVP_PKEY_free(ctx->peerkey);
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_finish(ctx->engine);
-#endif
-    OPENSSL_free(ctx);
+    if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+            && ctx->op.kex.exchprovctx != NULL
+            && ctx->op.kex.exchange != NULL
+            && ctx->op.kex.exchange->set_ctx_params != NULL)
+        return ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.exchprovctx,
+                                                    params);
+    if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+            && ctx->op.sig.sigprovctx != NULL
+            && ctx->op.sig.signature != NULL
+            && ctx->op.sig.signature->set_ctx_params != NULL)
+        return ctx->op.sig.signature->set_ctx_params(ctx->op.sig.sigprovctx,
+                                                     params);
+    if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+            && ctx->op.ciph.ciphprovctx != NULL
+            && ctx->op.ciph.cipher != NULL
+            && ctx->op.ciph.cipher->set_ctx_params != NULL)
+        return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx,
+                                                     params);
+    return 0;
 }
 
+#ifndef FIPS_MODE
 int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
 {
     if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
@@ -568,29 +611,6 @@ const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx)
     return NULL;
 }
 
-int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
-{
-    if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
-            && ctx->op.kex.exchprovctx != NULL
-            && ctx->op.kex.exchange != NULL
-            && ctx->op.kex.exchange->set_ctx_params != NULL)
-        return ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.exchprovctx,
-                                                    params);
-    if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
-            && ctx->op.sig.sigprovctx != NULL
-            && ctx->op.sig.signature != NULL
-            && ctx->op.sig.signature->set_ctx_params != NULL)
-        return ctx->op.sig.signature->set_ctx_params(ctx->op.sig.sigprovctx,
-                                                     params);
-    if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
-            && ctx->op.ciph.ciphprovctx != NULL
-            && ctx->op.ciph.cipher != NULL
-            && ctx->op.ciph.cipher->set_ctx_params != NULL)
-        return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx,
-                                                     params);
-    return 0;
-}
-
 const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx)
 {
     if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
@@ -609,7 +629,7 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx)
     return NULL;
 }
 
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
 int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
 {
     OSSL_PARAM dh_pad_params[2];
@@ -631,7 +651,7 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
 
     return EVP_PKEY_CTX_set_params(ctx, dh_pad_params);
 }
-#endif
+# endif
 
 int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
 {
@@ -711,10 +731,10 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
                                 int cmd, int p1, void *p2)
 {
     switch (cmd) {
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
     case EVP_PKEY_CTRL_DH_PAD:
         return EVP_PKEY_CTX_set_dh_pad(ctx, p1);
-#endif
+# endif
     case EVP_PKEY_CTRL_MD:
         return EVP_PKEY_CTX_set_signature_md(ctx, p2);
     case EVP_PKEY_CTRL_GET_MD:
@@ -737,10 +757,10 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
         return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
-#ifndef OPENSSL_NO_CMS
+# ifndef OPENSSL_NO_CMS
     case EVP_PKEY_CTRL_CMS_DECRYPT:
     case EVP_PKEY_CTRL_CMS_ENCRYPT:
-#endif
+# endif
         if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
             return 1;
         ERR_raise(ERR_LIB_EVP,
@@ -806,14 +826,14 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
 static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
                                     const char *value)
 {
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
     if (strcmp(name, "dh_pad") == 0) {
         int pad;
 
         pad = atoi(value);
         return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
     }
-#endif
+# endif
     if (strcmp(name, "digest") == 0) {
         int ret;
         EVP_MD *md;
@@ -1380,3 +1400,5 @@ void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
     if (pdigest_custom != NULL)
         *pdigest_custom = pmeth->digest_custom;
 }
+
+#endif /* FIPS_MODE */
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
new file mode 100644 (file)
index 0000000..119cd32
--- /dev/null
@@ -0,0 +1,580 @@
+/*
+ * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "crypto/evp.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
+{
+    EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE));
+
+    if (signature == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    signature->lock = CRYPTO_THREAD_lock_new();
+    if (signature->lock == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(signature);
+        return NULL;
+    }
+    signature->prov = prov;
+    ossl_provider_up_ref(prov);
+    signature->refcnt = 1;
+
+    return signature;
+}
+
+static void *evp_signature_from_dispatch(int name_id,
+                                         const OSSL_DISPATCH *fns,
+                                         OSSL_PROVIDER *prov)
+{
+    EVP_SIGNATURE *signature = NULL;
+    int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0;
+    int digsignfncnt = 0, digverifyfncnt = 0;
+    int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0;
+
+    if ((signature = evp_signature_new(prov)) == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    signature->name_id = name_id;
+
+    for (; fns->function_id != 0; fns++) {
+        switch (fns->function_id) {
+        case OSSL_FUNC_SIGNATURE_NEWCTX:
+            if (signature->newctx != NULL)
+                break;
+            signature->newctx = OSSL_get_OP_signature_newctx(fns);
+            ctxfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SIGN_INIT:
+            if (signature->sign_init != NULL)
+                break;
+            signature->sign_init = OSSL_get_OP_signature_sign_init(fns);
+            signfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SIGN:
+            if (signature->sign != NULL)
+                break;
+            signature->sign = OSSL_get_OP_signature_sign(fns);
+            signfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_VERIFY_INIT:
+            if (signature->verify_init != NULL)
+                break;
+            signature->verify_init = OSSL_get_OP_signature_verify_init(fns);
+            verifyfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_VERIFY:
+            if (signature->verify != NULL)
+                break;
+            signature->verify = OSSL_get_OP_signature_verify(fns);
+            verifyfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT:
+            if (signature->verify_recover_init != NULL)
+                break;
+            signature->verify_recover_init
+                = OSSL_get_OP_signature_verify_recover_init(fns);
+            verifyrecfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER:
+            if (signature->verify_recover != NULL)
+                break;
+            signature->verify_recover
+                = OSSL_get_OP_signature_verify_recover(fns);
+            verifyrecfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:
+            if (signature->digest_sign_init != NULL)
+                break;
+            signature->digest_sign_init
+                = OSSL_get_OP_signature_digest_sign_init(fns);
+            digsignfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE:
+            if (signature->digest_sign_update != NULL)
+                break;
+            signature->digest_sign_update
+                = OSSL_get_OP_signature_digest_sign_update(fns);
+            digsignfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL:
+            if (signature->digest_sign_final != NULL)
+                break;
+            signature->digest_sign_final
+                = OSSL_get_OP_signature_digest_sign_final(fns);
+            digsignfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT:
+            if (signature->digest_verify_init != NULL)
+                break;
+            signature->digest_verify_init
+                = OSSL_get_OP_signature_digest_verify_init(fns);
+            digverifyfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE:
+            if (signature->digest_verify_update != NULL)
+                break;
+            signature->digest_verify_update
+                = OSSL_get_OP_signature_digest_verify_update(fns);
+            digverifyfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL:
+            if (signature->digest_verify_final != NULL)
+                break;
+            signature->digest_verify_final
+                = OSSL_get_OP_signature_digest_verify_final(fns);
+            digverifyfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_FREECTX:
+            if (signature->freectx != NULL)
+                break;
+            signature->freectx = OSSL_get_OP_signature_freectx(fns);
+            ctxfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DUPCTX:
+            if (signature->dupctx != NULL)
+                break;
+            signature->dupctx = OSSL_get_OP_signature_dupctx(fns);
+            break;
+        case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS:
+            if (signature->get_ctx_params != NULL)
+                break;
+            signature->get_ctx_params
+                = OSSL_get_OP_signature_get_ctx_params(fns);
+            gparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS:
+            if (signature->gettable_ctx_params != NULL)
+                break;
+            signature->gettable_ctx_params
+                = OSSL_get_OP_signature_gettable_ctx_params(fns);
+            gparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS:
+            if (signature->set_ctx_params != NULL)
+                break;
+            signature->set_ctx_params
+                = OSSL_get_OP_signature_set_ctx_params(fns);
+            sparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS:
+            if (signature->settable_ctx_params != NULL)
+                break;
+            signature->settable_ctx_params
+                = OSSL_get_OP_signature_settable_ctx_params(fns);
+            sparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS:
+            if (signature->get_ctx_md_params != NULL)
+                break;
+            signature->get_ctx_md_params
+                = OSSL_get_OP_signature_get_ctx_md_params(fns);
+            gmdparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS:
+            if (signature->gettable_ctx_md_params != NULL)
+                break;
+            signature->gettable_ctx_md_params
+                = OSSL_get_OP_signature_gettable_ctx_md_params(fns);
+            gmdparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS:
+            if (signature->set_ctx_md_params != NULL)
+                break;
+            signature->set_ctx_md_params
+                = OSSL_get_OP_signature_set_ctx_md_params(fns);
+            smdparamfncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS:
+            if (signature->settable_ctx_md_params != NULL)
+                break;
+            signature->settable_ctx_md_params
+                = OSSL_get_OP_signature_settable_ctx_md_params(fns);
+            smdparamfncnt++;
+            break;
+        }
+    }
+    if (ctxfncnt != 2
+        || (signfncnt == 0
+            && verifyfncnt == 0
+            && verifyrecfncnt == 0
+            && digsignfncnt == 0
+            && digverifyfncnt == 0)
+        || (signfncnt != 0 && signfncnt != 2)
+        || (verifyfncnt != 0 && verifyfncnt != 2)
+        || (verifyrecfncnt != 0 && verifyrecfncnt != 2)
+        || (digsignfncnt != 0 && digsignfncnt != 3)
+        || (digverifyfncnt != 0 && digverifyfncnt != 3)
+        || (gparamfncnt != 0 && gparamfncnt != 2)
+        || (sparamfncnt != 0 && sparamfncnt != 2)
+        || (gmdparamfncnt != 0 && gmdparamfncnt != 2)
+        || (smdparamfncnt != 0 && smdparamfncnt != 2)) {
+        /*
+         * In order to be a consistent set of functions we must have at least
+         * a set of context functions (newctx and freectx) as well as a set of
+         * "signature" functions:
+         *  (sign_init, sign) or
+         *  (verify_init verify) or
+         *  (verify_recover_init, verify_recover) or
+         *  (digest_sign_init, digest_sign_update, digest_sign_final) or
+         *  (digest_verify_init, digest_verify_update, digest_verify_final).
+         *
+         * set_ctx_params and settable_ctx_params are optional, but if one of
+         * them is present then the other one must also be present. The same
+         * applies to get_ctx_params and gettable_ctx_params. The same rules
+         * apply to the "md_params" functions. The dupctx function is optional.
+         */
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+        goto err;
+    }
+
+    return signature;
+ err:
+    EVP_SIGNATURE_free(signature);
+    return NULL;
+}
+
+void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
+{
+    if (signature != NULL) {
+        int i;
+
+        CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock);
+        if (i > 0)
+            return;
+        ossl_provider_free(signature->prov);
+        CRYPTO_THREAD_lock_free(signature->lock);
+        OPENSSL_free(signature);
+    }
+}
+
+int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock);
+    return 1;
+}
+
+OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature)
+{
+    return signature->prov;
+}
+
+EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                                   const char *properties)
+{
+    return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties,
+                             evp_signature_from_dispatch,
+                             (int (*)(void *))EVP_SIGNATURE_up_ref,
+                             (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name)
+{
+    return evp_is_a(signature->prov, signature->name_id, name);
+}
+
+int EVP_SIGNATURE_number(const EVP_SIGNATURE *signature)
+{
+    return signature->name_id;
+}
+
+void EVP_SIGNATURE_do_all_provided(OPENSSL_CTX *libctx,
+                                   void (*fn)(EVP_SIGNATURE *signature,
+                                              void *arg),
+                                   void *arg)
+{
+    evp_generic_do_all(libctx, OSSL_OP_SIGNATURE,
+                       (void (*)(void *, void *))fn, arg,
+                       evp_signature_from_dispatch,
+                       (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+
+void EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature,
+                                void (*fn)(const char *name, void *data),
+                                void *data)
+{
+    if (signature->prov != NULL)
+        evp_names_do_all(signature->prov, signature->name_id, fn, data);
+}
+
+static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
+{
+    int ret = 0;
+    void *provkey = NULL;
+    EVP_SIGNATURE *signature = NULL;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    evp_pkey_ctx_free_old_ops(ctx);
+    ctx->operation = operation;
+
+    if (ctx->keytype == NULL)
+        goto legacy;
+
+    if (ctx->keymgmt == NULL)
+        ctx->keymgmt =
+            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
+    if (ctx->keymgmt != NULL) {
+        const char *supported_sig = NULL;
+
+        if (ctx->keymgmt->query_operation_name != NULL)
+            supported_sig =
+                ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE);
+
+        /*
+         * If we didn't get a supported sig, assume there is one with the
+         * same name as the key type.
+         */
+        if (supported_sig == NULL)
+            supported_sig = ctx->keytype;
+
+        /*
+         * Because we cleared out old ops, we shouldn't need to worry about
+         * checking if signature is already there.
+         */
+        signature =
+            EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery);
+    }
+
+    if (ctx->keymgmt == NULL
+        || signature == NULL
+        || (EVP_KEYMGMT_provider(ctx->keymgmt)
+            != EVP_SIGNATURE_provider(signature))) {
+        /*
+         * We don't have the full support we need with provided methods,
+         * let's go see if legacy does.  Also, we don't need to free
+         * ctx->keymgmt here, as it's not necessarily tied to this
+         * operation.  It will be freed by EVP_PKEY_CTX_free().
+         */
+        EVP_SIGNATURE_free(signature);
+        goto legacy;
+    }
+
+    ctx->op.sig.signature = signature;
+
+    if (ctx->pkey != NULL) {
+        provkey =
+            evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
+        /* If export failed, legacy may be able to pick it up */
+        if (provkey == NULL)
+            goto legacy;
+    }
+    ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov));
+    if (ctx->op.sig.sigprovctx == NULL) {
+        /* The provider key can stay in the cache */
+        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+        goto err;
+    }
+
+    switch (operation) {
+    case EVP_PKEY_OP_SIGN:
+        if (signature->sign_init == NULL) {
+            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            ret = -2;
+            goto err;
+        }
+        ret = signature->sign_init(ctx->op.sig.sigprovctx, provkey);
+        break;
+    case EVP_PKEY_OP_VERIFY:
+        if (signature->verify_init == NULL) {
+            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            ret = -2;
+            goto err;
+        }
+        ret = signature->verify_init(ctx->op.sig.sigprovctx, provkey);
+        break;
+    case EVP_PKEY_OP_VERIFYRECOVER:
+        if (signature->verify_recover_init == NULL) {
+            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            ret = -2;
+            goto err;
+        }
+        ret = signature->verify_recover_init(ctx->op.sig.sigprovctx, provkey);
+        break;
+    default:
+        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+        goto err;
+    }
+
+    if (ret <= 0) {
+        signature->freectx(ctx->op.sig.sigprovctx);
+        ctx->op.sig.sigprovctx = NULL;
+        goto err;
+    }
+    return 1;
+
+ legacy:
+    if (ctx->pmeth == NULL
+            || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL)
+            || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL)
+            || (operation == EVP_PKEY_OP_VERIFYRECOVER
+                && ctx->pmeth->verify_recover == NULL)) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    switch (operation) {
+    case EVP_PKEY_OP_SIGN:
+        if (ctx->pmeth->sign_init == NULL)
+            return 1;
+        ret = ctx->pmeth->sign_init(ctx);
+        break;
+    case EVP_PKEY_OP_VERIFY:
+        if (ctx->pmeth->verify_init == NULL)
+            return 1;
+        ret = ctx->pmeth->verify_init(ctx);
+        break;
+    case EVP_PKEY_OP_VERIFYRECOVER:
+        if (ctx->pmeth->verify_recover_init == NULL)
+            return 1;
+        ret = ctx->pmeth->verify_recover_init(ctx);
+        break;
+    default:
+        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+        goto err;
+    }
+    if (ret <= 0)
+        goto err;
+    return ret;
+
+ err:
+    ctx->operation = EVP_PKEY_OP_UNDEFINED;
+    return ret;
+}
+
+int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
+{
+    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN);
+}
+
+int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
+                  unsigned char *sig, size_t *siglen,
+                  const unsigned char *tbs, size_t tbslen)
+{
+    int ret;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    if (ctx->operation != EVP_PKEY_OP_SIGN) {
+        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
+        return -1;
+    }
+
+    if (ctx->op.sig.sigprovctx == NULL)
+        goto legacy;
+
+    ret = ctx->op.sig.signature->sign(ctx->op.sig.sigprovctx, sig, siglen,
+                                      SIZE_MAX, tbs, tbslen);
+
+    return ret;
+ legacy:
+
+    if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
+        return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
+}
+
+int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
+{
+    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY);
+}
+
+int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
+                    const unsigned char *sig, size_t siglen,
+                    const unsigned char *tbs, size_t tbslen)
+{
+    int ret;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    if (ctx->operation != EVP_PKEY_OP_VERIFY) {
+        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
+        return -1;
+    }
+
+    if (ctx->op.sig.sigprovctx == NULL)
+        goto legacy;
+
+    ret = ctx->op.sig.signature->verify(ctx->op.sig.sigprovctx, sig, siglen,
+                                        tbs, tbslen);
+
+    return ret;
+ legacy:
+    if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
+}
+
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
+{
+    return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER);
+}
+
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
+                            unsigned char *rout, size_t *routlen,
+                            const unsigned char *sig, size_t siglen)
+{
+    int ret;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
+        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
+        return -1;
+    }
+
+    if (ctx->op.sig.sigprovctx == NULL)
+        goto legacy;
+
+    ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.sigprovctx, rout,
+                                                routlen,
+                                                (rout == NULL ? 0 : *routlen),
+                                                sig, siglen);
+    return ret;
+ legacy:
+    if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+    M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
+        return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
+}
index 90486ae..b08f7e4 100644 (file)
@@ -2,8 +2,8 @@
 
 =head1 NAME
 
-EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_provided,
-EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free
+EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_from_name,
+EVP_PKEY_CTX_new_from_pkey, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free
 - public key algorithm context functions
 
 =head1 SYNOPSIS
@@ -12,9 +12,11 @@ EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free
 
  EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
  EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
- EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx,
-                                         const char *name,
-                                         const char *propquery);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx,
+                                          const char *name,
+                                          const char *propquery);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx,
+                                          EVP_PKEY *pkey);
  EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
  void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 
@@ -26,13 +28,19 @@ the I<pkey> key type and ENGINE I<e>.
 The EVP_PKEY_CTX_new_id() function allocates public key algorithm context
 using the key type specified by I<id> and ENGINE I<e>.
 
-The EVP_PKEY_CTX_new_provided() function allocates a public key algorithm
+The EVP_PKEY_CTX_new_from_name() function allocates a public key algorithm
 context using the library context I<libctx> (see L<OPENSSL_CTX(3)>), the
 key type specified by I<name> and the property query I<propquery>.  None
 of the arguments are duplicated, so they  must remain unchanged for the
 lifetime of the returned B<EVP_PKEY_CTX> or of any of its duplicates.
 
-EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_provided() are normally
+The EVP_PKEY_CTX_new_from_pkey() function allocates a public key algorithm
+context using the library context I<libctx> (see L<OPENSSL_CTX(3)>) and the
+algorithm specified by I<pkey> . None of the arguments are duplicated, so they
+must remain unchanged for the lifetime of the returned B<EVP_PKEY_CTX> or of
+any of its duplicates.
+
+EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_from_name() are normally
 used when no B<EVP_PKEY> structure is associated with the operations,
 for example during parameter generation or key generation for some
 algorithms.
@@ -76,7 +84,11 @@ L<EVP_PKEY_new(3)>
 
 =head1 HISTORY
 
-These functions were added in OpenSSL 1.0.0.
+The EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id(), EVP_PKEY_CTX_dup() and
+EVP_PKEY_CTX_free() functions were added in OpenSSL 1.0.0.
+
+The EVP_PKEY_CTX_new_from_name() and EVP_PKEY_CTX_new_from_pkey() functions were
+added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h
new file mode 100644 (file)
index 0000000..efd4acf
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/dsa.h>
+
+DSA *dsa_new(OPENSSL_CTX *libctx);
+int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
+                 int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa);
index 973ef20..91f5350 100644 (file)
@@ -638,3 +638,4 @@ void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags);
 
 const EVP_CIPHER *evp_get_cipherbyname_ex(OPENSSL_CTX *libctx, const char *name);
 const EVP_MD *evp_get_digestbyname_ex(OPENSSL_CTX *libctx, const char *name);
+
index e661053..57a7338 100644 (file)
@@ -1466,9 +1466,11 @@ void EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
-EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx,
-                                        const char *name,
-                                        const char *propquery);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx,
+                                         const char *name,
+                                         const char *propquery);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx,
+                                         EVP_PKEY *pkey);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 
index 7afab78..7889639 100644 (file)
@@ -121,6 +121,49 @@ static OSSL_PARAM core_params[] =
     OSSL_PARAM_END
 };
 
+/*
+ * This routine is currently necessary as bn params are currently processed
+ * using BN_native2bn when raw data is received. This means we need to do
+ * magic to reverse the order of the bytes to match native format.
+ * The array of hexdata is to get around compilers that dont like
+ * strings longer than 509 bytes,
+ */
+static int rawnative_fromhex(const char *hex_data[],
+                             unsigned char **native, size_t *nativelen)
+{
+    int ret = 0;
+    unsigned char *data = NULL;
+    BIGNUM *bn = NULL;
+    int i, slen, datalen, sz;
+    char *str = NULL;
+
+    for (slen = 0, i = 0; hex_data[i] != NULL; ++i)
+        slen += strlen(hex_data[i]);
+    str = OPENSSL_zalloc(slen + 1);
+    if (str == NULL)
+        return 0;
+    for (i = 0; hex_data[i] != NULL; ++i)
+        strcat(str, hex_data[i]);
+
+    if (BN_hex2bn(&bn, str) <= 0)
+        return 0;
+
+    datalen = slen / 2;
+    data = (unsigned char *)str; /* reuse the str buffer */
+
+    sz = BN_bn2nativepad(bn, data, datalen);
+    if (sz <= 0)
+        goto err;
+    ret = 1;
+    *native = data;
+    *nativelen = datalen;
+    data = NULL; /* so it does not get freed */
+err:
+    BN_free(bn);
+    OPENSSL_free(data);
+    return ret;
+}
+
 /* TODO(3.0): To be removed */
 static int dummy_evp_call(void *provctx)
 {
@@ -128,6 +171,58 @@ static int dummy_evp_call(void *provctx)
     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
     EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL);
     EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF2, NULL);
+    EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
+    EVP_PKEY *pkey = NULL;
+    OSSL_PARAM *p;
+    OSSL_PARAM params[16];
+    unsigned char sig[64];
+    size_t siglen, sigdgstlen;
+    unsigned char *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
+    unsigned char *dsa_pub = NULL, *dsa_priv = NULL;
+    size_t dsa_p_len, dsa_q_len, dsa_g_len, dsa_pub_len, dsa_priv_len;
+
+    /* dsa 2048 */
+    static const char *dsa_p_hex[] = {
+        "a29b8872ce8b8423b7d5d21d4b02f57e03e9e6b8a258dc16611ba098ab543415"
+        "e415f156997a3ee236658fa093260de3ad422e05e046f9ec29161a375f0eb4ef"
+        "fcef58285c5d39ed425d7a62ca12896c4a92cb1946f2952a48133f07da364d1b"
+        "df6b0f7139983e693c80059b0eacd1479ba9f2857754ede75f112b07ebbf3534",
+        "8bbf3e01e02f2d473de39453f99dd2367541caca3ba01166343d7b5b58a37bd1"
+        "b7521db2f13b86707132fe09f4cd09dc1618fa3401ebf9cc7b19fa94aa472088"
+        "133d6cb2d35c1179c8c8ff368758d507d9f9a17d46c110fe3144ce9b022b42e4"
+        "19eb4f5388613bfc3e26241a432e8706bc58ef76117278deab6cf692618291b7",
+         NULL
+    };
+    static const char *dsa_q_hex[] = {
+        "a3bfd9ab7884794e383450d5891dc18b65157bdcfcdac51518902867",
+        NULL
+    };
+    static const char *dsa_g_hex[] = {
+        "6819278869c7fd3d2d7b77f77e8150d9ad433bea3ba85efc80415aa3545f78f7"
+        "2296f06cb19ceda06c94b0551cfe6e6f863e31d1de6eed7dab8b0c9df231e084"
+        "34d1184f91d033696bb382f8455e9888f5d31d4784ec40120246f4bea61794bb"
+        "a5866f09746463bdf8e9e108cd9529c3d0f6df80316e2e70aaeb1b26cdb8ad97",
+        "bc3d287e0b8d616c42e65b87db20deb7005bc416747a6470147a68a7820388eb"
+        "f44d52e0628af9cf1b7166d03465f35acc31b6110c43dabc7c5d591e671eaf7c"
+        "252c1c145336a1a4ddf13244d55e835680cab2533b82df2efe55ec18c1e6cd00"
+        "7bb089758bb17c2cbe14441bd093ae66e5976d53733f4fa3269701d31d23d467",
+        NULL
+    };
+    static const char *dsa_pub_hex[] = {
+        "a012b3b170b307227957b7ca2061a816ac7a2b3d9ae995a5119c385b603bf6f6"
+        "c5de4dc5ecb5dfa4a41c68662eb25b638b7e2620ba898d07da6c4991e76cc0ec"
+        "d1ad3421077067e47c18f58a92a72ad43199ecb7bd84e7d3afb9019f0e9dd0fb"
+        "aa487300b13081e33c902876436f7b03c345528481d362815e24fe59dac5ac34",
+        "660d4c8a76cb99a7c7de93eb956cd6bc88e58d901034944a094b01803a43c672"
+        "b9688c0e01d8f4fc91c62a3f88021f7bd6a651b1a88f43aa4ef27653d12bf8b7"
+        "099fdf6b461082f8e939107bfd2f7210087d326c375200f1f51e7e74a3413190"
+        "1bcd0863521ff8d676c48581868736c5e51b16a4e39215ea0b17c4735974c516",
+        NULL
+    };
+    static const char *dsa_priv_hex[] = {
+        "6ccaeef6d73b4e80f11c17b8e9627c036635bac39423505e407e5cb7",
+        NULL
+    };
     char msg[] = "Hello World!";
     const unsigned char exptd[] = {
         0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
@@ -186,7 +281,54 @@ static int dummy_evp_call(void *provctx)
     if (!EC_KEY_generate_key(key))
         goto err;
 #endif
+    if (!rawnative_fromhex(dsa_p_hex, &dsa_p, &dsa_p_len)
+            || !rawnative_fromhex(dsa_q_hex, &dsa_q, &dsa_q_len)
+            || !rawnative_fromhex(dsa_g_hex, &dsa_g, &dsa_g_len)
+            || !rawnative_fromhex(dsa_pub_hex, &dsa_pub, &dsa_pub_len)
+            || !rawnative_fromhex(dsa_priv_hex, &dsa_priv, &dsa_priv_len))
+        goto err;
+
+    p = params;
+    *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, dsa_p, dsa_p_len);
+    *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, dsa_q, dsa_q_len);
+    *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, dsa_g, dsa_g_len);
+    *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PUB_KEY,
+                                   dsa_pub, dsa_pub_len);
+    *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PRIV_KEY,
+                                   dsa_priv, dsa_priv_len);
+    *p = OSSL_PARAM_construct_end();
+
+    kctx = EVP_PKEY_CTX_new_from_name(libctx, SN_dsa, "");
+    if (kctx == NULL)
+        goto err;
+    if (EVP_PKEY_key_fromdata_init(kctx) <= 0
+            || EVP_PKEY_fromdata(kctx, &pkey, params) <= 0)
+        goto err;
+
+    sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey);
+    if (sctx == NULL)
+        goto err;;
 
+    if (EVP_PKEY_sign_init(sctx) <= 0)
+        goto err;
+
+    /* set signature parameters */
+    sigdgstlen = SHA256_DIGEST_LENGTH;
+    p = params;
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
+                                            SN_sha256,
+                                            strlen(SN_sha256) + 1);
+
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
+                                       &sigdgstlen);
+    *p = OSSL_PARAM_construct_end();
+    if (EVP_PKEY_CTX_set_params(sctx, params) <= 0)
+        goto err;
+
+    if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0
+            || EVP_PKEY_verify_init(sctx) <= 0
+            || EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0)
+        goto err;
     ret = 1;
  err:
     BN_CTX_end(bnctx);
@@ -199,6 +341,14 @@ static int dummy_evp_call(void *provctx)
 #ifndef OPENSSL_NO_EC
     EC_KEY_free(key);
 #endif
+    OPENSSL_free(dsa_p);
+    OPENSSL_free(dsa_q);
+    OPENSSL_free(dsa_g);
+    OPENSSL_free(dsa_pub);
+    OPENSSL_free(dsa_priv);
+    EVP_PKEY_free(pkey);
+    EVP_PKEY_CTX_free(kctx);
+    EVP_PKEY_CTX_free(sctx);
     return ret;
 }
 
@@ -435,6 +585,19 @@ static const OSSL_ALGORITHM fips_kdfs[] = {
     { NULL, NULL, NULL }
 };
 
+static const OSSL_ALGORITHM fips_signature[] = {
+#ifndef OPENSSL_NO_DSA
+    { "DSA:dsaEncryption", "fips=yes", dsa_signature_functions },
+#endif
+    { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM fips_keymgmt[] = {
+#ifndef OPENSSL_NO_DSA
+    { "DSA", "fips=yes", dsa_keymgmt_functions },
+#endif
+    { NULL, NULL, NULL }
+};
 
 static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
                                          int operation_id,
@@ -451,6 +614,10 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
         return fips_macs;
     case OSSL_OP_KDF:
         return fips_kdfs;
+    case OSSL_OP_KEYMGMT:
+        return fips_keymgmt;
+    case OSSL_OP_SIGNATURE:
+        return fips_signature;
     }
     return NULL;
 }
@@ -574,19 +741,18 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
         return 0;
     }
 
-    *out = fips_dispatch_table;
-    *provctx = ctx;
-
     /*
      * TODO(3.0): Remove me. This is just a dummy call to demonstrate making
      * EVP calls from within the FIPS module.
      */
-    if (!dummy_evp_call(*provctx)) {
-        OPENSSL_CTX_free(*provctx);
-        *provctx = NULL;
+    if (!dummy_evp_call(ctx)) {
+        OPENSSL_CTX_free(ctx);
         return 0;
     }
 
+    *out = fips_dispatch_table;
+    *provctx = ctx;
+
     return 1;
 }
 
index ca4354a..c3ab48b 100644 (file)
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
 #include <openssl/bn.h>
-#include <openssl/dsa.h>
 #include <openssl/params.h>
 #include "internal/param_build.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "crypto/dsa.h"
 
 static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams;
 static OSSL_OP_keymgmt_exportdomparams_fn dsa_exportdomparams;
@@ -134,8 +135,9 @@ static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
 static void *dsa_importdomparams(void *provctx, const OSSL_PARAM params[])
 {
     DSA *dsa;
+    OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
 
-    if ((dsa = DSA_new()) == NULL
+    if ((dsa = dsa_new(libctx)) == NULL
         || !params_to_domparams(dsa, params)) {
         DSA_free(dsa);
         dsa = NULL;
@@ -164,8 +166,9 @@ static int dsa_exportdomparams(void *domparams,
 static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
 {
     DSA *dsa;
+    OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
 
-    if ((dsa = DSA_new()) == NULL
+    if ((dsa = dsa_new(libctx)) == NULL
         || !params_to_key(dsa, params)) {
         DSA_free(dsa);
         dsa = NULL;
index 1eef3c9..c656a45 100644 (file)
@@ -15,6 +15,7 @@
 #include <openssl/evp.h>
 #include "prov/implementations.h"
 #include "prov/provider_ctx.h"
+#include "crypto/dsa.h"
 
 static OSSL_OP_signature_newctx_fn dsa_newctx;
 static OSSL_OP_signature_sign_init_fn dsa_signature_init;
@@ -95,8 +96,8 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
     if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize)
         return 0;
 
-    ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa);
-
+    ret = dsa_sign_int(pdsactx->libctx, 0, tbs, tbslen, sig, &sltmp,
+                       pdsactx->dsa);
     if (ret <= 0)
         return 0;
 
index c38f79c..029a8e4 100644 (file)
@@ -122,7 +122,7 @@ static int test_fromdata_rsa(void)
         OSSL_PARAM_END
     };
 
-    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_provided(NULL, "RSA", NULL)))
+    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
         goto err;
 
     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
@@ -172,7 +172,7 @@ static int test_fromdata_dh(void)
         OSSL_PARAM_END
     };
 
-    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_provided(NULL, "DH", NULL)))
+    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
         goto err;
 
     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
index 1fbd264..e272989 100644 (file)
@@ -4819,7 +4819,6 @@ EVP_DigestSignUpdate                    ? 3_0_0   EXIST::FUNCTION:
 EVP_DigestVerifyInit_ex                 ?      3_0_0   EXIST::FUNCTION:
 EVP_DigestVerifyUpdate                  ?      3_0_0   EXIST::FUNCTION:
 BN_check_prime                          ?      3_0_0   EXIST::FUNCTION:
-EVP_PKEY_CTX_new_provided               ?      3_0_0   EXIST::FUNCTION:
 EVP_KEYMGMT_is_a                        ?      3_0_0   EXIST::FUNCTION:
 EVP_KEYMGMT_do_all_provided             ?      3_0_0   EXIST::FUNCTION:
 EVP_KEYEXCH_is_a                        ?      3_0_0   EXIST::FUNCTION:
@@ -4912,3 +4911,5 @@ RSA_get0_pss_params                     ? 3_0_0   EXIST::FUNCTION:RSA
 X509_cmp_timeframe                      ?      3_0_0   EXIST::FUNCTION:
 OSSL_CMP_MSG_get0_header                ?      3_0_0   EXIST::FUNCTION:CMP
 BIO_f_prefix                            ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_new_from_name              ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_new_from_pkey              ?      3_0_0   EXIST::FUNCTION: