summaryrefslogtreecommitdiffhomepage
path: root/src/pk/dsa
diff options
context:
space:
mode:
Diffstat (limited to 'src/pk/dsa')
-rw-r--r--src/pk/dsa/dsa_export.c72
-rw-r--r--src/pk/dsa/dsa_free.c34
-rw-r--r--src/pk/dsa/dsa_import.c89
-rw-r--r--src/pk/dsa/dsa_make_key.c146
-rw-r--r--src/pk/dsa/dsa_sign_hash.c159
-rw-r--r--src/pk/dsa/dsa_verify_hash.c128
-rw-r--r--src/pk/dsa/dsa_verify_key.c102
7 files changed, 730 insertions, 0 deletions
diff --git a/src/pk/dsa/dsa_export.c b/src/pk/dsa/dsa_export.c
new file mode 100644
index 0000000..5a093d9
--- /dev/null
+++ b/src/pk/dsa/dsa_export.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_export.c
+ DSA implementation, export key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Export a DSA key to a binary packet
+ @param out [out] Where to store the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of key to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+ unsigned char flags[1];
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type != PK_PUBLIC && type != PK_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ flags[0] = (type != PK_PUBLIC) ? 1 : 0;
+
+ if (type == PK_PRIVATE) {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_export.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/06/03 19:24:31 $ */
diff --git a/src/pk/dsa/dsa_free.c b/src/pk/dsa/dsa_free.c
new file mode 100644
index 0000000..9157acb
--- /dev/null
+++ b/src/pk/dsa/dsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_free.c
+ DSA implementation, free a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Free a DSA key
+ @param key The key to free from memory
+*/
+void dsa_free(dsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_free.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */
diff --git a/src/pk/dsa/dsa_import.c b/src/pk/dsa/dsa_import.c
new file mode 100644
index 0000000..e81bac8
--- /dev/null
+++ b/src/pk/dsa/dsa_import.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_import.c
+ DSA implementation, import a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Import a DSA key
+ @param in The binary packet to import from
+ @param inlen The length of the binary packet
+ @param key [out] Where to store the imported key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ unsigned char flags[1];
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if (flags[0] == 1) {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PRIVATE;
+ } else {
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+ key->type = PK_PUBLIC;
+ }
+ key->qord = mp_unsigned_bin_size(&key->q);
+
+ if (key->qord >= MDSA_MAX_GROUP || key->qord <= 15 ||
+ key->qord >= mp_unsigned_bin_size(&key->p) || (mp_unsigned_bin_size(&key->p) - key->qord) >= MDSA_DELTA) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ return CRYPT_OK;
+error:
+ mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_import.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2005/06/08 23:31:17 $ */
diff --git a/src/pk/dsa/dsa_make_key.c b/src/pk/dsa/dsa_make_key.c
new file mode 100644
index 0000000..02f69e0
--- /dev/null
+++ b/src/pk/dsa/dsa_make_key.c
@@ -0,0 +1,146 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_make_key.c
+ DSA implementation, generate a DSA key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Create a DSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
+{
+ mp_int tmp, tmp2;
+ int err, res;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* check prng */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* check size */
+ if (group_size >= MDSA_MAX_GROUP || group_size <= 15 ||
+ group_size >= modulus_size || (modulus_size - group_size) >= MDSA_DELTA) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate ram */
+ buf = XMALLOC(MDSA_DELTA);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* init mp_ints */
+ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
+ err = mpi_to_ltc_error(err);
+ goto LBL_ERR;
+ }
+
+ /* make our prime q */
+ if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK) { goto LBL_ERR; }
+
+ /* double q */
+ if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY) { goto error; }
+
+ /* now make a random string and multply it against q */
+ if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* force magnitude */
+ buf[0] |= 0xC0;
+
+ /* force even */
+ buf[modulus_size - group_size - 1] &= ~1;
+
+ if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY) { goto error; }
+
+ /* now loop until p is prime */
+ for (;;) {
+ if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { goto LBL_ERR; }
+ if (res == MP_YES) break;
+
+ /* add 2q to p and 2 to tmp2 */
+ if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY) { goto error; }
+ }
+
+ /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
+ mp_set(&key->g, 1);
+
+ do {
+ if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) == MP_EQ);
+
+ /* at this point tmp generates a group of order q mod p */
+ mp_exch(&tmp, &key->g);
+
+ /* so now we have our DH structure, generator g, order q, modulus p
+ Now we need a random exponent [mod q] and it's power g^x mod p
+ */
+ do {
+ if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+ if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&key->x, 1) != MP_GT);
+ if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY) { goto error; }
+
+ key->type = PK_PRIVATE;
+ key->qord = group_size;
+
+ /* shrink the ram required */
+ if ((err = mp_shrink(&key->g)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
+ if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MDSA_DELTA);
+#endif
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+
+ XFREE(buf);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_make_key.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2005/06/11 05:45:35 $ */
diff --git a/src/pk/dsa/dsa_sign_hash.c b/src/pk/dsa/dsa_sign_hash.c
new file mode 100644
index 0000000..48d29a2
--- /dev/null
+++ b/src/pk/dsa/dsa_sign_hash.c
@@ -0,0 +1,159 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_sign_hash.c
+ DSA implementation, sign a hash, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param r The "r" integer of the signature (caller must initialize with mp_init() first)
+ @param s The "s" integer of the signature (caller must initialize with mp_init() first)
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ mp_int *r, mp_int *s,
+ prng_state *prng, int wprng, dsa_key *key)
+{
+ mp_int k, kinv, tmp;
+ unsigned char *buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* check group order size */
+ if (key->qord >= MDSA_MAX_GROUP) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ buf = XMALLOC(MDSA_MAX_GROUP);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Init our temps */
+ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != MP_OKAY) { goto error; }
+
+retry:
+
+ do {
+ /* gen random k */
+ if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
+ err = CRYPT_ERROR_READPRNG;
+ goto LBL_ERR;
+ }
+
+ /* read k */
+ if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; }
+
+ /* k > 1 ? */
+ if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; }
+
+ /* test gcd */
+ if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) != MP_EQ);
+
+ /* now find 1/k mod q */
+ if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; }
+
+ /* now find r = g^k mod p mod q */
+ if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(r, &key->q, r)) != MP_OKAY) { goto error; }
+
+ if (mp_iszero(r) == MP_YES) { goto retry; }
+
+ /* now find s = (in + xr)/k mod q */
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
+ if ((err = mp_mul(&key->x, r, s)) != MP_OKAY) { goto error; }
+ if ((err = mp_add(s, &tmp, s)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(s, &kinv, &key->q, s)) != MP_OKAY) { goto error; }
+
+ if (mp_iszero(s) == MP_YES) { goto retry; }
+
+ err = CRYPT_OK;
+ goto LBL_ERR;
+
+error:
+ err = mpi_to_ltc_error(err);
+LBL_ERR:
+ mp_clear_multi(&k, &kinv, &tmp, NULL);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, MDSA_MAX_GROUP);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param out [out] Where to store the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, dsa_key *key)
+{
+ mp_int r, s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (mp_init_multi(&r, &s, NULL) != MP_OKAY) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = dsa_sign_hash_raw(in, inlen, &r, &s, prng, wprng, key)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2005/05/15 21:48:59 $ */
diff --git a/src/pk/dsa/dsa_verify_hash.c b/src/pk/dsa/dsa_verify_hash.c
new file mode 100644
index 0000000..11e5c33
--- /dev/null
+++ b/src/pk/dsa/dsa_verify_hash.c
@@ -0,0 +1,128 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_hash.c
+ DSA implementation, verify a signature, Tom St Denis
+*/
+
+
+#ifdef MDSA
+
+/**
+ Verify a DSA signature
+ @param r DSA "r" parameter
+ @param s DSA "s" parameter
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash_raw( mp_int *r, mp_int *s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ mp_int w, v, u1, u2;
+ int err;
+
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* init our variables */
+ if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* neither r or s can be null or >q*/
+ if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto done;
+ }
+
+ /* w = 1/s mod q */
+ if ((err = mp_invmod(s, &key->q, &w)) != MP_OKAY) { goto error; }
+
+ /* u1 = m * w mod q */
+ if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY) { goto error; }
+
+ /* u2 = r*w mod q */
+ if ((err = mp_mulmod(r, &w, &key->q, &u2)) != MP_OKAY) { goto error; }
+
+ /* v = g^u1 * y^u2 mod p mod q */
+ if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY) { goto error; }
+ if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY) { goto error; }
+ if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY) { goto error; }
+ if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY) { goto error; }
+
+ /* if r = v then we're set */
+ if (mp_cmp(r, &v) == MP_EQ) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+ goto done;
+
+error : err = mpi_to_ltc_error(err);
+done : mp_clear_multi(&w, &v, &u1, &u2, NULL);
+ return err;
+}
+
+/**
+ Verify a DSA signature
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ int err;
+ mp_int r, s;
+
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* decode the sequence */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* do the op */
+ err = dsa_verify_hash_raw(&r, &s, hash, hashlen, stat, key);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_hash.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2005/05/15 21:48:59 $ */
diff --git a/src/pk/dsa/dsa_verify_key.c b/src/pk/dsa/dsa_verify_key.c
new file mode 100644
index 0000000..b7be103
--- /dev/null
+++ b/src/pk/dsa/dsa_verify_key.c
@@ -0,0 +1,102 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_key.c
+ DSA implementation, verify a key, Tom St Denis
+*/
+
+#ifdef MDSA
+
+/**
+ Verify a DSA key for validity
+ @param key The key to verify
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_verify_key(dsa_key *key, int *stat)
+{
+ mp_int tmp, tmp2;
+ int res, err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to an invalid key */
+ *stat = 0;
+
+ /* first make sure key->q and key->p are prime */
+ if ((err = is_prime(&key->q, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+
+ if ((err = is_prime(&key->p, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ /* now make sure that g is not -1, 0 or 1 and <p */
+ if (mp_cmp_d(&key->g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) {
+ return CRYPT_OK;
+ }
+ if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY) { goto error; }
+ if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* 1 < y < p-1 */
+ if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
+ if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY) { goto error; }
+ if (mp_iszero(&tmp2) != MP_YES) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
+ if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+ err = CRYPT_OK;
+ goto done;
+ }
+
+ /* at this point we are out of tests ;-( */
+ err = CRYPT_OK;
+ *stat = 1;
+ goto done;
+error: err = mpi_to_ltc_error(err);
+done : mp_clear_multi(&tmp, &tmp2, NULL);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/05 14:35:59 $ */