summaryrefslogtreecommitdiffstats
path: root/src/crypto/dsa
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-01-22 14:27:53 -0800
committerAdam Langley <agl@google.com>2015-01-30 16:52:14 -0800
commitd9e397b599b13d642138480a28c14db7a136bf05 (patch)
tree34bab61dc4ce323b123ad4614dbc07e86ea2f9ef /src/crypto/dsa
downloadexternal_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.zip
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.gz
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.bz2
Initial commit of BoringSSL for Android.
Diffstat (limited to 'src/crypto/dsa')
-rw-r--r--src/crypto/dsa/CMakeLists.txt20
-rw-r--r--src/crypto/dsa/dsa.c354
-rw-r--r--src/crypto/dsa/dsa_asn1.c150
-rw-r--r--src/crypto/dsa/dsa_error.c30
-rw-r--r--src/crypto/dsa/dsa_impl.c762
-rw-r--r--src/crypto/dsa/dsa_test.c338
-rw-r--r--src/crypto/dsa/internal.h78
7 files changed, 1732 insertions, 0 deletions
diff --git a/src/crypto/dsa/CMakeLists.txt b/src/crypto/dsa/CMakeLists.txt
new file mode 100644
index 0000000..fbc053e
--- /dev/null
+++ b/src/crypto/dsa/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(. .. ../../include)
+
+add_library(
+ dsa
+
+ OBJECT
+
+ dsa.c
+ dsa_impl.c
+ dsa_asn1.c
+ dsa_error.c
+)
+
+add_executable(
+ dsa_test
+
+ dsa_test.c
+)
+
+target_link_libraries(dsa_test crypto)
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
new file mode 100644
index 0000000..8816b63
--- /dev/null
+++ b/src/crypto/dsa/dsa.c
@@ -0,0 +1,354 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ *
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/dh.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ex_data.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+extern const DSA_METHOD DSA_default_method;
+
+DSA *DSA_new(void) { return DSA_new_method(NULL); }
+
+DSA *DSA_new_method(const ENGINE *engine) {
+ DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA));
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(DSA, DSA_new_method, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(dsa, 0, sizeof(DSA));
+
+ if (engine) {
+ dsa->meth = ENGINE_get_DSA_method(engine);
+ }
+
+ if (dsa->meth == NULL) {
+ dsa->meth = (DSA_METHOD*) &DSA_default_method;
+ }
+ METHOD_ref(dsa->meth);
+
+ dsa->write_params = 1;
+ dsa->references = 1;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data)) {
+ METHOD_unref(dsa->meth);
+ OPENSSL_free(dsa);
+ return NULL;
+ }
+
+ if (dsa->meth->init && !dsa->meth->init(dsa)) {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
+ METHOD_unref(dsa->meth);
+ OPENSSL_free(dsa);
+ return NULL;
+ }
+
+ return dsa;
+}
+
+void DSA_free(DSA *dsa) {
+ if (dsa == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&dsa->references, -1, CRYPTO_LOCK_DSA) > 0) {
+ return;
+ }
+
+ if (dsa->meth->finish) {
+ dsa->meth->finish(dsa);
+ }
+ METHOD_unref(dsa->meth);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
+
+ if (dsa->p != NULL)
+ BN_clear_free(dsa->p);
+ if (dsa->q != NULL)
+ BN_clear_free(dsa->q);
+ if (dsa->g != NULL)
+ BN_clear_free(dsa->g);
+ if (dsa->pub_key != NULL)
+ BN_clear_free(dsa->pub_key);
+ if (dsa->priv_key != NULL)
+ BN_clear_free(dsa->priv_key);
+ if (dsa->kinv != NULL)
+ BN_clear_free(dsa->kinv);
+ if (dsa->r != NULL)
+ BN_clear_free(dsa->r);
+ OPENSSL_free(dsa);
+}
+
+int DSA_up_ref(DSA *dsa) {
+ CRYPTO_add(&dsa->references, 1, CRYPTO_LOCK_DSA);
+ return 1;
+}
+
+int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
+ size_t seed_len, int *out_counter,
+ unsigned long *out_h, BN_GENCB *cb) {
+ if (dsa->meth->generate_parameters) {
+ return dsa->meth->generate_parameters(dsa, bits, seed_in, seed_len,
+ out_counter, out_h, cb);
+ }
+ return DSA_default_method.generate_parameters(dsa, bits, seed_in, seed_len,
+ out_counter, out_h, cb);
+}
+
+int DSA_generate_key(DSA *dsa) {
+ if (dsa->meth->keygen) {
+ return dsa->meth->keygen(dsa);
+ }
+ return DSA_default_method.keygen(dsa);
+}
+
+DSA_SIG *DSA_SIG_new(void) {
+ DSA_SIG *sig;
+ sig = OPENSSL_malloc(sizeof(DSA_SIG));
+ if (!sig) {
+ return NULL;
+ }
+ sig->r = NULL;
+ sig->s = NULL;
+ return sig;
+}
+
+void DSA_SIG_free(DSA_SIG *sig) {
+ if (!sig) {
+ return;
+ }
+
+ if (sig->r) {
+ BN_free(sig->r);
+ }
+ if (sig->s) {
+ BN_free(sig->s);
+ }
+ OPENSSL_free(sig);
+}
+
+DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
+ if (dsa->meth->sign) {
+ return dsa->meth->sign(digest, digest_len, dsa);
+ }
+ return DSA_default_method.sign(digest, digest_len, dsa);
+}
+
+int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig,
+ const DSA *dsa) {
+ int valid;
+ if (!DSA_do_check_signature(&valid, digest, digest_len, sig, dsa)) {
+ return -1;
+ }
+ return valid;
+}
+
+int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
+ if (dsa->meth->verify) {
+ return dsa->meth->verify(out_valid, digest, digest_len, sig, dsa);
+ }
+
+ return DSA_default_method.verify(out_valid, digest, digest_len, sig, dsa);
+}
+
+int DSA_sign(int type, const uint8_t *digest, size_t digest_len,
+ uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) {
+ DSA_SIG *s;
+
+ s = DSA_do_sign(digest, digest_len, dsa);
+ if (s == NULL) {
+ *out_siglen = 0;
+ return 0;
+ }
+
+ *out_siglen = i2d_DSA_SIG(s, &out_sig);
+ DSA_SIG_free(s);
+ return 1;
+}
+
+int DSA_verify(int type, const uint8_t *digest, size_t digest_len,
+ const uint8_t *sig, size_t sig_len, const DSA *dsa) {
+ int valid;
+ if (!DSA_check_signature(&valid, digest, digest_len, sig, sig_len, dsa)) {
+ return -1;
+ }
+ return valid;
+}
+
+int DSA_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, const uint8_t *sig, size_t sig_len,
+ const DSA *dsa) {
+ DSA_SIG *s = NULL;
+ int ret = 0;
+ uint8_t *der = NULL;
+
+ s = DSA_SIG_new();
+ if (s == NULL) {
+ goto err;
+ }
+
+ const uint8_t *sigp = sig;
+ if (d2i_DSA_SIG(&s, &sigp, sig_len) == NULL || sigp != sig + sig_len) {
+ goto err;
+ }
+
+ /* Ensure that the signature uses DER and doesn't have trailing garbage. */
+ int der_len = i2d_DSA_SIG(s, &der);
+ if (der_len < 0 || (size_t)der_len != sig_len || memcmp(sig, der, sig_len)) {
+ goto err;
+ }
+
+ ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa);
+
+err:
+ if (der != NULL) {
+ OPENSSL_free(der);
+ }
+ if (s) {
+ DSA_SIG_free(s);
+ }
+ return ret;
+}
+
+int DSA_size(const DSA *dsa) {
+ 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(dsa->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_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
+ BIGNUM **out_r) {
+ if (dsa->meth->sign_setup) {
+ return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
+ }
+
+ return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
+}
+
+int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp, new_func,
+ dup_func, free_func);
+}
+
+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(const DSA *d, int idx) {
+ return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+
+DH *DSA_dup_DH(const DSA *r) {
+ DH *ret = NULL;
+
+ if (r == NULL) {
+ goto err;
+ }
+ ret = DH_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ if (r->q != NULL) {
+ ret->priv_length = BN_num_bits(r->q);
+ if ((ret->q = BN_dup(r->q)) == NULL) {
+ goto err;
+ }
+ }
+ if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) ||
+ (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) ||
+ (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) ||
+ (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ if (ret != NULL) {
+ DH_free(ret);
+ }
+ return NULL;
+}
diff --git a/src/crypto/dsa/dsa_asn1.c b/src/crypto/dsa/dsa_asn1.c
new file mode 100644
index 0000000..933fba7
--- /dev/null
+++ b/src/crypto/dsa/dsa_asn1.c
@@ -0,0 +1,150 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000. */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+static int dsa_sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg) {
+ if (operation != ASN1_OP_NEW_PRE) {
+ return 1;
+ }
+
+ DSA_SIG *sig;
+ sig = OPENSSL_malloc(sizeof(DSA_SIG));
+ if (!sig) {
+ OPENSSL_PUT_ERROR(DSA, dsa_sig_cb, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memset(sig, 0, sizeof(DSA_SIG));
+ *pval = (ASN1_VALUE *)sig;
+ return 2;
+}
+
+ASN1_SEQUENCE_cb(DSA_SIG, dsa_sig_cb) = {
+ ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
+ ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG);
+
+
+static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg) {
+ switch (operation) {
+ case ASN1_OP_NEW_PRE:
+ *pval = (ASN1_VALUE *)DSA_new();
+ if (*pval) {
+ return 2;
+ }
+ return 0;
+
+ case ASN1_OP_FREE_PRE:
+ DSA_free((DSA *)*pval);
+ *pval = NULL;
+ return 2;
+
+ default:
+ return 1;
+ }
+}
+
+ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
+ ASN1_SIMPLE(DSA, version, LONG),
+ ASN1_SIMPLE(DSA, p, BIGNUM),
+ ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM),
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_SIMPLE(DSA, priv_key, BIGNUM)} ASN1_SEQUENCE_END_cb(DSA,
+ DSAPrivateKey);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey);
+
+ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
+ ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM), } ASN1_SEQUENCE_END_cb(DSA, DSAparams);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams);
+
+
+/* DSA public key is a bit trickier... its effectively a CHOICE type decided by
+ * a field called write_params which can either write out just the public key
+ * as an INTEGER or the parameters and public key in a SEQUENCE. */
+
+ASN1_SEQUENCE(dsa_pub_internal) = {
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_SIMPLE(DSA, p, BIGNUM),
+ ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM)
+} ASN1_SEQUENCE_END_name(DSA, dsa_pub_internal);
+
+ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = {
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_EX_COMBINE(0, 0, dsa_pub_internal)
+} ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey);
+
+DSA *DSAparams_dup(const DSA *dsa) {
+ return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), (DSA*) dsa);
+}
diff --git a/src/crypto/dsa/dsa_error.c b/src/crypto/dsa/dsa_error.c
new file mode 100644
index 0000000..5a83908
--- /dev/null
+++ b/src/crypto/dsa/dsa_error.c
@@ -0,0 +1,30 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/err.h>
+
+#include <openssl/dsa.h>
+
+const ERR_STRING_DATA DSA_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_new_method, 0), "DSA_new_method"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_dsa_sig_cb, 0), "dsa_sig_cb"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_sign, 0), "sign"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_sign_setup, 0), "sign_setup"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_verify, 0), "verify"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "BAD_Q_VALUE"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},
+ {0, NULL},
+};
diff --git a/src/crypto/dsa/dsa_impl.c b/src/crypto/dsa/dsa_impl.c
new file mode 100644
index 0000000..6719758
--- /dev/null
+++ b/src/crypto/dsa/dsa_impl.c
@@ -0,0 +1,762 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ *
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+#define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+
+/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
+ * Rabin-Miller */
+#define DSS_prime_checks 50
+
+static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp, const uint8_t *digest, size_t digest_len) {
+ BN_CTX *ctx;
+ BIGNUM k, kq, *K, *kinv = NULL, *r = NULL;
+ int ret = 0;
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ OPENSSL_PUT_ERROR(DSA, sign_setup, DSA_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ BN_init(&k);
+ BN_init(&kq);
+
+ ctx = ctx_in;
+ if (ctx == NULL) {
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ }
+
+ r = BN_new();
+ if (r == NULL) {
+ goto err;
+ }
+
+ /* Get random k */
+ do {
+ /* If possible, we'll include the private key and message digest in the k
+ * generation. The |digest| argument is only empty if |DSA_sign_setup| is
+ * being used. */
+ int ok;
+
+ if (digest_len > 0) {
+ ok = BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, digest, digest_len,
+ ctx);
+ } else {
+ ok = BN_rand_range(&k, dsa->q);
+ }
+ if (!ok) {
+ goto err;
+ }
+ } while (BN_is_zero(&k));
+
+ BN_set_flags(&k, BN_FLG_CONSTTIME);
+
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ CRYPTO_LOCK_DSA, dsa->p, ctx)) {
+ goto err;
+ }
+
+ /* Compute r = (g^k mod p) mod q */
+ if (!BN_copy(&kq, &k))
+ goto err;
+
+ /* We do not want timing information to leak the length of k,
+ * so we compute g^k using an equivalent exponent of fixed length.
+ *
+ * (This is a kludge that we need because the BN_mod_exp_mont()
+ * does not let us specify the desired timing behaviour.) */
+
+ if (!BN_add(&kq, &kq, dsa->q))
+ goto err;
+ if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) {
+ if (!BN_add(&kq, &kq, dsa->q))
+ goto err;
+ }
+
+ K = &kq;
+
+ if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) {
+ goto err;
+ }
+ if (!BN_mod(r, r, dsa->q, ctx)) {
+ goto err;
+ }
+
+ /* Compute part of 's = inv(k) (m + xr) mod q' */
+ kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx);
+ if (kinv == NULL) {
+ goto err;
+ }
+
+ if (*kinvp != NULL) {
+ BN_clear_free(*kinvp);
+ }
+ *kinvp = kinv;
+ kinv = NULL;
+ if (*rp != NULL) {
+ BN_clear_free(*rp);
+ }
+ *rp = r;
+ ret = 1;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(DSA, sign_setup, ERR_R_BN_LIB);
+ if (r != NULL) {
+ BN_clear_free(r);
+ }
+ }
+
+ if (ctx_in == NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_clear_free(&k);
+ BN_clear_free(&kq);
+ return ret;
+}
+
+static DSA_SIG *sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
+ BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
+ BIGNUM m;
+ BIGNUM xr;
+ BN_CTX *ctx = NULL;
+ int reason = ERR_R_BN_LIB;
+ DSA_SIG *ret = NULL;
+ int noredo = 0;
+
+ BN_init(&m);
+ BN_init(&xr);
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ reason = DSA_R_MISSING_PARAMETERS;
+ goto err;
+ }
+
+ s = BN_new();
+ if (s == NULL) {
+ goto err;
+ }
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+redo:
+ if (dsa->kinv == NULL || dsa->r == NULL) {
+ if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) {
+ goto err;
+ }
+ } else {
+ kinv = dsa->kinv;
+ dsa->kinv = NULL;
+ r = dsa->r;
+ dsa->r = NULL;
+ noredo = 1;
+ }
+
+ if (digest_len > BN_num_bytes(dsa->q)) {
+ /* if the digest length is greater than the size of q use the
+ * BN_num_bits(dsa->q) leftmost bits of the digest, see
+ * fips 186-3, 4.2 */
+ digest_len = BN_num_bytes(dsa->q);
+ }
+
+ if (BN_bin2bn(digest, digest_len, &m) == NULL) {
+ goto err;
+ }
+
+ /* Compute s = inv(k) (m + xr) mod q */
+ if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) {
+ goto err; /* s = xr */
+ }
+ if (!BN_add(s, &xr, &m)) {
+ goto err; /* s = m + xr */
+ }
+ if (BN_cmp(s, dsa->q) > 0) {
+ if (!BN_sub(s, s, dsa->q)) {
+ goto err;
+ }
+ }
+ if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) {
+ goto err;
+ }
+
+ ret = DSA_SIG_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ /* Redo if r or s is zero as required by FIPS 186-3: this is
+ * very unlikely. */
+ if (BN_is_zero(r) || BN_is_zero(s)) {
+ if (noredo) {
+ reason = DSA_R_NEED_NEW_SETUP_VALUES;
+ goto err;
+ }
+ goto redo;
+ }
+ ret->r = r;
+ ret->s = s;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(DSA, sign, reason);
+ BN_free(r);
+ BN_free(s);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_clear_free(&m);
+ BN_clear_free(&xr);
+ if (kinv != NULL) {
+ /* dsa->kinv is NULL now if we used it */
+ BN_clear_free(kinv);
+ }
+
+ return ret;
+}
+
+static int verify(int *out_valid, const uint8_t *dgst, size_t digest_len,
+ DSA_SIG *sig, const DSA *dsa) {
+ BN_CTX *ctx;
+ BIGNUM u1, u2, t1;
+ BN_MONT_CTX *mont = NULL;
+ int ret = 0;
+ unsigned i;
+
+ *out_valid = 0;
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ i = BN_num_bits(dsa->q);
+ /* fips 186-3 allows only different sizes for q */
+ if (i != 160 && i != 224 && i != 256) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_BAD_Q_VALUE);
+ return 0;
+ }
+
+ if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ BN_init(&u1);
+ BN_init(&u2);
+ BN_init(&t1);
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
+ BN_ucmp(sig->r, dsa->q) >= 0) {
+ ret = 1;
+ goto err;
+ }
+ if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
+ BN_ucmp(sig->s, dsa->q) >= 0) {
+ ret = 1;
+ goto err;
+ }
+
+ /* Calculate W = inv(S) mod Q
+ * save W in u2 */
+ if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) {
+ goto err;
+ }
+
+ /* save M in u1 */
+ if (digest_len > (i >> 3)) {
+ /* if the digest length is greater than the size of q use the
+ * BN_num_bits(dsa->q) leftmost bits of the digest, see
+ * fips 186-3, 4.2 */
+ digest_len = (i >> 3);
+ }
+
+ if (BN_bin2bn(dgst, digest_len, &u1) == NULL) {
+ goto err;
+ }
+
+ /* u1 = M * w mod q */
+ if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) {
+ goto err;
+ }
+
+ /* u2 = r * w mod q */
+ if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) {
+ goto err;
+ }
+
+ mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ CRYPTO_LOCK_DSA, dsa->p, ctx);
+ if (!mont) {
+ goto err;
+ }
+
+ if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, mont)) {
+ goto err;
+ }
+
+ /* BN_copy(&u1,&t1); */
+ /* let u1 = u1 mod q */
+ if (!BN_mod(&u1, &t1, dsa->q, ctx)) {
+ goto err;
+ }
+
+ /* V is now in u1. If the signature is correct, it will be
+ * equal to R. */
+ *out_valid = BN_ucmp(&u1, sig->r) == 0;
+ ret = 1;
+
+err:
+ if (ret != 1) {
+ OPENSSL_PUT_ERROR(DSA, verify, ERR_R_BN_LIB);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_free(&u1);
+ BN_free(&u2);
+ BN_free(&t1);
+
+ return ret;
+}
+
+static int keygen(DSA *dsa) {
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+ BIGNUM prk;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ priv_key = dsa->priv_key;
+ if (priv_key == NULL) {
+ priv_key = BN_new();
+ if (priv_key == NULL) {
+ goto err;
+ }
+ }
+
+ do {
+ if (!BN_rand_range(priv_key, dsa->q)) {
+ goto err;
+ }
+ } while (BN_is_zero(priv_key));
+
+ pub_key = dsa->pub_key;
+ if (pub_key == NULL) {
+ pub_key = BN_new();
+ if (pub_key == NULL) {
+ goto err;
+ }
+ }
+
+ BN_init(&prk);
+ BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME);
+
+ if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) {
+ goto err;
+ }
+
+ dsa->priv_key = priv_key;
+ dsa->pub_key = pub_key;
+ ok = 1;
+
+err:
+ if (pub_key != NULL && dsa->pub_key == NULL) {
+ BN_free(pub_key);
+ }
+ if (priv_key != NULL && dsa->priv_key == NULL) {
+ BN_free(priv_key);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+
+ return ok;
+}
+
+static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
+ size_t seed_len, int *counter_ret, unsigned long *h_ret,
+ BN_GENCB *cb) {
+ int ok = 0;
+ unsigned char seed[SHA256_DIGEST_LENGTH];
+ unsigned char md[SHA256_DIGEST_LENGTH];
+ unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
+ BIGNUM *r0, *W, *X, *c, *test;
+ BIGNUM *g = NULL, *q = NULL, *p = NULL;
+ BN_MONT_CTX *mont = NULL;
+ int k, n = 0, m = 0;
+ unsigned i;
+ int counter = 0;
+ int r = 0;
+ BN_CTX *ctx = NULL;
+ unsigned int h = 2;
+ unsigned qbits, qsize;
+ const EVP_MD *evpmd;
+
+ if (bits >= 2048) {
+ qbits = 256;
+ evpmd = EVP_sha256();
+ } else {
+ qbits = 160;
+ evpmd = EVP_sha1();
+ }
+ qsize = qbits / 8;
+
+ if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
+ qsize != SHA256_DIGEST_LENGTH) {
+ /* invalid q size */
+ return 0;
+ }
+
+ if (bits < 512) {
+ bits = 512;
+ }
+
+ bits = (bits + 63) / 64 * 64;
+
+ /* NB: seed_len == 0 is special case: copy generated seed to
+ * seed_in if it is not NULL. */
+ if (seed_len && (seed_len < (size_t)qsize)) {
+ seed_in = NULL; /* seed buffer too small -- ignore */
+ }
+ if (seed_len > (size_t)qsize) {
+ seed_len = qsize; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
+ * but our internal buffers are restricted to 160 bits*/
+ }
+ if (seed_in != NULL) {
+ memcpy(seed, seed_in, seed_len);
+ }
+
+ ctx = BN_CTX_new();
+ mont = BN_MONT_CTX_new();
+ if (ctx == NULL || mont == NULL) {
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+ r0 = BN_CTX_get(ctx);
+ g = BN_CTX_get(ctx);
+ W = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ c = BN_CTX_get(ctx);
+ p = BN_CTX_get(ctx);
+ test = BN_CTX_get(ctx);
+
+ if (!BN_lshift(test, BN_value_one(), bits - 1)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* Find q. */
+ for (;;) {
+ int seed_is_random;
+
+ /* step 1 */
+ if (!BN_GENCB_call(cb, 0, m++)) {
+ goto err;
+ }
+
+ if (!seed_len) {
+ if (!RAND_bytes(seed, qsize)) {
+ goto err;
+ }
+ seed_is_random = 1;
+ } else {
+ seed_is_random = 0;
+ seed_len = 0; /* use random seed if 'seed_in' turns out to be bad*/
+ }
+ memcpy(buf, seed, qsize);
+ memcpy(buf2, seed, qsize);
+ /* precompute "SEED + 1" for step 7: */
+ for (i = qsize - 1; i < qsize; i--) {
+ buf[i]++;
+ if (buf[i] != 0) {
+ break;
+ }
+ }
+
+ /* step 2 */
+ if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) ||
+ !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) {
+ goto err;
+ }
+ for (i = 0; i < qsize; i++) {
+ md[i] ^= buf2[i];
+ }
+
+ /* step 3 */
+ md[0] |= 0x80;
+ md[qsize - 1] |= 0x01;
+ if (!BN_bin2bn(md, qsize, q)) {
+ goto err;
+ }
+
+ /* step 4 */
+ r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, seed_is_random, cb);
+ if (r > 0) {
+ break;
+ }
+ if (r != 0) {
+ goto err;
+ }
+
+ /* do a callback call */
+ /* step 5 */
+ }
+
+ if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) {
+ goto err;
+ }
+
+ /* step 6 */
+ counter = 0;
+ /* "offset = 2" */
+
+ n = (bits - 1) / 160;
+
+ for (;;) {
+ if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) {
+ goto err;
+ }
+
+ /* step 7 */
+ BN_zero(W);
+ /* now 'buf' contains "SEED + offset - 1" */
+ for (k = 0; k <= n; k++) {
+ /* obtain "SEED + offset + k" by incrementing: */
+ for (i = qsize - 1; i < qsize; i--) {
+ buf[i]++;
+ if (buf[i] != 0) {
+ break;
+ }
+ }
+
+ if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) {
+ goto err;
+ }
+
+ /* step 8 */
+ if (!BN_bin2bn(md, qsize, r0) ||
+ !BN_lshift(r0, r0, (qsize << 3) * k) ||
+ !BN_add(W, W, r0)) {
+ goto err;
+ }
+ }
+
+ /* more of step 8 */
+ if (!BN_mask_bits(W, bits - 1) ||
+ !BN_copy(X, W) ||
+ !BN_add(X, X, test)) {
+ goto err;
+ }
+
+ /* step 9 */
+ if (!BN_lshift1(r0, q) ||
+ !BN_mod(c, X, r0, ctx) ||
+ !BN_sub(r0, c, BN_value_one()) ||
+ !BN_sub(p, X, r0)) {
+ goto err;
+ }
+
+ /* step 10 */
+ if (BN_cmp(p, test) >= 0) {
+ /* step 11 */
+ r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
+ if (r > 0) {
+ goto end; /* found it */
+ }
+ if (r != 0) {
+ goto err;
+ }
+ }
+
+ /* step 13 */
+ counter++;
+ /* "offset = offset + n + 1" */
+
+ /* step 14 */
+ if (counter >= 4096) {
+ break;
+ }
+ }
+ }
+end:
+ if (!BN_GENCB_call(cb, 2, 1)) {
+ goto err;
+ }
+
+ /* We now need to generate g */
+ /* Set r0=(p-1)/q */
+ if (!BN_sub(test, p, BN_value_one()) ||
+ !BN_div(r0, NULL, test, q, ctx)) {
+ goto err;
+ }
+
+ if (!BN_set_word(test, h) ||
+ !BN_MONT_CTX_set(mont, p, ctx)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* g=test^r0%p */
+ if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) {
+ goto err;
+ }
+ if (!BN_is_one(g)) {
+ break;
+ }
+ if (!BN_add(test, test, BN_value_one())) {
+ goto err;
+ }
+ h++;
+ }
+
+ if (!BN_GENCB_call(cb, 3, 1)) {
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ if (ok) {
+ if (ret->p) {
+ BN_free(ret->p);
+ }
+ if (ret->q) {
+ BN_free(ret->q);
+ }
+ if (ret->g) {
+ BN_free(ret->g);
+ }
+ ret->p = BN_dup(p);
+ ret->q = BN_dup(q);
+ ret->g = BN_dup(g);
+ if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
+ ok = 0;
+ goto err;
+ }
+ if (counter_ret != NULL) {
+ *counter_ret = counter;
+ }
+ if (h_ret != NULL) {
+ *h_ret = h;
+ }
+ }
+
+ if (ctx) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ if (mont != NULL) {
+ BN_MONT_CTX_free(mont);
+ }
+
+ return ok;
+}
+
+static int finish(DSA *dsa) {
+ BN_MONT_CTX_free(dsa->method_mont_p);
+ dsa->method_mont_p = NULL;
+ return 1;
+}
+
+const struct dsa_method DSA_default_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */,
+ },
+ NULL /* app_data */,
+
+ NULL /* init */,
+ finish /* finish */,
+
+ sign,
+ sign_setup,
+ verify,
+
+ paramgen,
+ keygen,
+};
diff --git a/src/crypto/dsa/dsa_test.c b/src/crypto/dsa/dsa_test.c
new file mode 100644
index 0000000..1273638
--- /dev/null
+++ b/src/crypto/dsa/dsa_test.c
@@ -0,0 +1,338 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ *
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+static int dsa_cb(int p, int n, BN_GENCB *arg);
+
+/* The following values are taken from the updated Appendix 5 to FIPS PUB 186
+ * and also appear in Appendix 5 to FIPS PUB 186-1. */
+
+static const uint8_t seed[20] = {
+ 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
+ 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
+};
+
+static const uint8_t fips_p[] = {
+ 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75,
+ 0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d,
+ 0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0,
+ 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac,
+ 0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
+ 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91,
+};
+
+static const uint8_t fips_q[] = {
+ 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
+ 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
+};
+
+static const uint8_t fips_g[] = {
+ 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63,
+ 0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c,
+ 0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71,
+ 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95,
+ 0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
+ 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02,
+};
+
+static const uint8_t fips_x[] = {
+ 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
+ 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
+};
+
+static const uint8_t fips_y[] = {
+ 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
+ 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
+ 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
+ 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
+ 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
+ 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
+};
+
+static const uint8_t fips_digest[] = {
+ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
+ 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
+};
+
+/* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */
+static const uint8_t fips_sig[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8,
+};
+
+/* fips_sig_negative is fips_sig with r encoded as a negative number. */
+static const uint8_t fips_sig_negative[] = {
+ 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
+ 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
+ 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
+ 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
+ 0xd8, 0xc8,
+};
+
+/* fip_sig_extra is fips_sig with trailing data. */
+static const uint8_t fips_sig_extra[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8, 0x00,
+};
+
+/* fips_sig_lengths is fips_sig with a non-minimally encoded length. */
+static const uint8_t fips_sig_bad_length[] = {
+ 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
+ 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
+ 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
+ 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
+ 0xb6, 0xdc, 0xd8, 0xc8, 0x00,
+};
+
+/* fips_sig_bad_r is fips_sig with a bad r value. */
+static const uint8_t fips_sig_bad_r[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8,
+};
+
+static BIO *bio_err = NULL;
+static BIO *bio_out = NULL;
+
+static DSA *get_fips_dsa(void) {
+ DSA *dsa = DSA_new();
+ if (!dsa) {
+ return NULL;
+ }
+ dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL);
+ dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL);
+ dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL);
+ dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL);
+ dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL);
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL ||
+ dsa->pub_key == NULL || dsa->priv_key == NULL) {
+ DSA_free(dsa);
+ return NULL;
+ }
+ return dsa;
+}
+
+static int test_generate(void) {
+ BN_GENCB cb;
+ DSA *dsa = NULL;
+ int counter, ok = 0, i, j;
+ uint8_t buf[256];
+ unsigned long h;
+ uint8_t sig[256];
+ unsigned int siglen;
+
+ BIO_printf(bio_out, "test generation of DSA parameters\n");
+
+ BN_GENCB_set(&cb, dsa_cb, bio_out);
+ dsa = DSA_new();
+ if (dsa == NULL ||
+ !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
+ goto end;
+ }
+
+ BIO_printf(bio_out, "seed\n");
+ for (i = 0; i < 20; i += 4) {
+ BIO_printf(bio_out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
+ seed[i + 3]);
+ }
+ BIO_printf(bio_out, "\ncounter=%d h=%ld\n", counter, h);
+
+ if (counter != 105) {
+ BIO_printf(bio_err, "counter should be 105\n");
+ goto end;
+ }
+ if (h != 2) {
+ BIO_printf(bio_err, "h should be 2\n");
+ goto end;
+ }
+
+ i = BN_bn2bin(dsa->q, buf);
+ j = sizeof(fips_q);
+ if (i != j || memcmp(buf, fips_q, i) != 0) {
+ BIO_printf(bio_err, "q value is wrong\n");
+ goto end;
+ }
+
+ i = BN_bn2bin(dsa->p, buf);
+ j = sizeof(fips_p);
+ if (i != j || memcmp(buf, fips_p, i) != 0) {
+ BIO_printf(bio_err, "p value is wrong\n");
+ goto end;
+ }
+
+ i = BN_bn2bin(dsa->g, buf);
+ j = sizeof(fips_g);
+ if (i != j || memcmp(buf, fips_g, i) != 0) {
+ BIO_printf(bio_err, "g value is wrong\n");
+ goto end;
+ }
+
+ DSA_generate_key(dsa);
+ DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa);
+ if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
+ ok = 1;
+ } else {
+ BIO_printf(bio_err, "verification failure\n");
+ }
+
+end:
+ if (dsa != NULL) {
+ DSA_free(dsa);
+ }
+
+ return ok;
+}
+
+static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
+ int ok = 0;
+ DSA *dsa = get_fips_dsa();
+ if (dsa == NULL) {
+ goto end;
+ }
+
+ int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
+ if (ret != expect) {
+ BIO_printf(bio_err, "DSA_verify returned %d, want %d\n", ret, expect);
+ goto end;
+ }
+ ok = 1;
+ /* Clear any errorrs from a test with expected failure. */
+ ERR_clear_error();
+
+end:
+ if (dsa != NULL) {
+ DSA_free(dsa);
+ }
+
+ return ok;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+ if (!test_generate() ||
+ !test_verify(fips_sig, sizeof(fips_sig), 1) ||
+ !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
+ !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
+ !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
+ !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
+ BIO_print_errors(bio_err);
+ BIO_free(bio_err);
+ BIO_free(bio_out);
+ return 1;
+ }
+
+ BIO_free(bio_err);
+ BIO_free(bio_out);
+ printf("PASS\n");
+ return 0;
+}
+
+static int dsa_cb(int p, int n, BN_GENCB *arg) {
+ char c = '*';
+ static int ok = 0, num = 0;
+
+ switch (p) {
+ case 0:
+ c = '.';
+ num++;
+ break;
+ case 1:
+ c = '+';
+ break;
+ case 2:
+ c = '*';
+ ok++;
+ break;
+ case 3:
+ c = '\n';
+ }
+
+ BIO_write(arg->arg, &c, 1);
+ (void)BIO_flush(arg->arg);
+
+ if (!ok && p == 0 && num > 1) {
+ BIO_printf((BIO *)arg, "error in dsatest\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/dsa/internal.h b/src/crypto/dsa/internal.h
new file mode 100644
index 0000000..ef99158
--- /dev/null
+++ b/src/crypto/dsa/internal.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ *
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+
+#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
+#define OPENSSL_HEADER_DSA_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/bn.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DSA_INTERNAL_H */