diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-01-12 11:32:12 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-01-12 11:32:12 +1000 |
commit | e683582bf37de45a9512aea7ff33b9a3ebdf07f4 (patch) | |
tree | 3a8c7e4f3ae908816ef57c15e56b619daa1430ac /crypto/dsa | |
parent | e0e68f9e34585084038fba768fb2eecb5dd1ddf3 (diff) |
Add dsa signature alg to fips provider
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10615)
Diffstat (limited to 'crypto/dsa')
-rw-r--r-- | crypto/dsa/build.info | 10 | ||||
-rw-r--r-- | crypto/dsa/dsa_asn1.c | 151 | ||||
-rw-r--r-- | crypto/dsa/dsa_lib.c | 294 | ||||
-rw-r--r-- | crypto/dsa/dsa_local.h | 3 | ||||
-rw-r--r-- | crypto/dsa/dsa_ossl.c | 25 | ||||
-rw-r--r-- | crypto/dsa/dsa_sign.c | 179 |
6 files changed, 349 insertions, 313 deletions
diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info index 2e759853a2..309fda323e 100644 --- a/crypto/dsa/build.info +++ b/crypto/dsa/build.info @@ -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 diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c index bf16e282d5..20bf2518c8 100644 --- a/crypto/dsa/dsa_asn1.c +++ b/crypto/dsa/dsa_asn1.c @@ -15,110 +15,6 @@ #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; -} diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 4670c433c5..2a97c0852c 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -15,12 +15,140 @@ #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); -} diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h index e56ff06977..13a3007ff0 100644 --- a/crypto/dsa/dsa_local.h +++ b/crypto/dsa/dsa_local.h @@ -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); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 5e34fc5586..af0fa6b566 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -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; diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 99ef0043eb..d09aaea6db 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -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; +} + |