Import code from previous AssetBuilder version

This commit is contained in:
Jan
2019-09-24 10:45:09 +02:00
parent 5609557516
commit 0d8432d4f7
919 changed files with 154412 additions and 26 deletions

View File

@ -0,0 +1,139 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_decrypt_key.c
DSA Crypto, Tom St Denis
*/
#ifdef LTC_MDSA
/**
Decrypt an DSA encrypted key
@param in The ciphertext
@param inlen The length of the ciphertext (octets)
@param out [out] The plaintext
@param outlen [in/out] The max size and resulting size of the plaintext
@param key The corresponding private DSA key
@return CRYPT_OK if successful
*/
int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
dsa_key *key)
{
unsigned char *skey, *expt;
void *g_pub;
unsigned long x, y;
unsigned long hashOID[32] = { 0 };
int hash, err;
ltc_asn1_list decode[3];
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* decode to find out hash */
LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
err = der_decode_sequence(in, inlen, decode, 1);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
return err;
}
hash = find_hash_oid(hashOID, decode[0].size);
if (hash_is_valid(hash) != CRYPT_OK) {
return CRYPT_INVALID_PACKET;
}
/* we now have the hash! */
if ((err = mp_init(&g_pub)) != CRYPT_OK) {
return err;
}
/* allocate memory */
expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
skey = XMALLOC(MAXBLOCKSIZE);
if (expt == NULL || skey == NULL) {
if (expt != NULL) {
XFREE(expt);
}
if (skey != NULL) {
XFREE(skey);
}
mp_clear(g_pub);
return CRYPT_MEM;
}
LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL);
LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
/* read the structure in now */
if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
goto LBL_ERR;
}
/* make shared key */
x = mp_unsigned_bin_size(key->p) + 1;
if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y = mp_unsigned_bin_size(key->p) + 1;
y = MIN(y, MAXBLOCKSIZE);
if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) {
goto LBL_ERR;
}
/* ensure the hash of the shared secret is at least as big as the encrypt itself */
if (decode[2].size > y) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
/* avoid buffer overflow */
if (*outlen < decode[2].size) {
*outlen = decode[2].size;
err = CRYPT_BUFFER_OVERFLOW;
goto LBL_ERR;
}
/* Decrypt the key */
for (x = 0; x < decode[2].size; x++) {
out[x] = expt[x] ^ skey[x];
}
*outlen = x;
err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
zeromem(expt, mp_unsigned_bin_size(key->p) + 1);
zeromem(skey, MAXBLOCKSIZE);
#endif
XFREE(expt);
XFREE(skey);
mp_clear(g_pub);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -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.
*/
#include "tomcrypt.h"
/**
@file dsa_encrypt_key.c
DSA Crypto, Tom St Denis
*/
#ifdef LTC_MDSA
/**
Encrypt a symmetric key with DSA
@param in The symmetric key you want to encrypt
@param inlen The length of the key to encrypt (octets)
@param out [out] The destination for the ciphertext
@param outlen [in/out] The max size and resulting size of the ciphertext
@param prng An active PRNG state
@param wprng The index of the PRNG you wish to use
@param hash The index of the hash you want to use
@param key The DSA key you want to encrypt to
@return CRYPT_OK if successful
*/
int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int hash,
dsa_key *key)
{
unsigned char *expt, *skey;
void *g_pub, *g_priv;
unsigned long x, y;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
/* check that wprng/cipher/hash are not invalid */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if (inlen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_HASH;
}
/* make a random key and export the public copy */
if ((err = mp_init_multi(&g_pub, &g_priv, NULL)) != CRYPT_OK) {
return err;
}
expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
skey = XMALLOC(MAXBLOCKSIZE);
if (expt == NULL || skey == NULL) {
if (expt != NULL) {
XFREE(expt);
}
if (skey != NULL) {
XFREE(skey);
}
mp_clear_multi(g_pub, g_priv, NULL);
return CRYPT_MEM;
}
/* make a random g_priv, g_pub = g^x pair
private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2)
*/
if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) {
goto LBL_ERR;
}
/* compute y */
if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) {
goto LBL_ERR;
}
/* make random key */
x = mp_unsigned_bin_size(key->p) + 1;
if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y = MAXBLOCKSIZE;
if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) {
goto LBL_ERR;
}
/* Encrypt key */
for (x = 0; x < inlen; x++) {
skey[x] ^= in[x];
}
err = der_encode_sequence_multi(out, outlen,
LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
LTC_ASN1_INTEGER, 1UL, g_pub,
LTC_ASN1_OCTET_STRING, inlen, skey,
LTC_ASN1_EOL, 0UL, NULL);
LBL_ERR:
#ifdef LTC_CLEAN_STACK
/* clean up */
zeromem(expt, mp_unsigned_bin_size(key->p) + 1);
zeromem(skey, MAXBLOCKSIZE);
#endif
XFREE(skey);
XFREE(expt);
mp_clear_multi(g_pub, g_priv, NULL);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,116 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_export.c
DSA implementation, export key, Tom St Denis
*/
#ifdef LTC_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 long zero=0;
int err, std;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
std = type & PK_STD;
type &= ~PK_STD;
/* 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;
}
if (type == PK_PRIVATE) {
if (std) {
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_INTEGER, 1UL, key->y,
LTC_ASN1_INTEGER, 1UL, key->x,
LTC_ASN1_EOL, 0UL, NULL);
}
else {
unsigned char flags[1];
flags[0] = 1;
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 {
if (std) {
unsigned long tmplen = (unsigned long)(mp_count_bits(key->y) / 8) + 8;
unsigned char* tmp = XMALLOC(tmplen);
ltc_asn1_list int_list[3];
if (tmp == NULL) {
return CRYPT_MEM;
}
err = der_encode_integer(key->y, tmp, &tmplen);
if (err != CRYPT_OK) {
goto error;
}
LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL);
LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
err = der_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
tmplen, LTC_ASN1_SEQUENCE, int_list,
sizeof(int_list) / sizeof(int_list[0]));
error:
XFREE(tmp);
return err;
}
else {
unsigned char flags[1];
flags[0] = 0;
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
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,33 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_free.c
DSA implementation, free a DSA key, Tom St Denis
*/
#ifdef LTC_MDSA
/**
Free a DSA key
@param key The key to free from memory
*/
void dsa_free(dsa_key *key)
{
LTC_ARGCHKVD(key != NULL);
mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, NULL);
key->type = key->qord = 0;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,47 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_make_key.c
DSA implementation, generate a DSA key
*/
#ifdef LTC_MDSA
/**
Create a DSA key
@param prng An active PRNG state
@param wprng The index of the PRNG desired
@param key [in/out] Where to store the created key
@return CRYPT_OK if successful.
*/
int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key)
{
int err;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* 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
*/
/* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; }
if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; }
key->type = PK_PRIVATE;
return CRYPT_OK;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,244 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_generate_pqg.c
DSA implementation - generate DSA parameters p, q & g
*/
#ifdef LTC_MDSA
/**
Create DSA parameters (INTERNAL ONLY, not part of public API)
@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 p [out] bignum where generated 'p' is stored (must be initialized by caller)
@param q [out] bignum where generated 'q' is stored (must be initialized by caller)
@param g [out] bignum where generated 'g' is stored (must be initialized by caller)
@return CRYPT_OK if successful, upon error this function will free all allocated memory
*/
static int _dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g)
{
unsigned long L, N, n, outbytes, seedbytes, counter, j, i;
int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash;
unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE];
void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc;
/* check size */
if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) {
return CRYPT_INVALID_ARG;
}
/* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
*
* L = The desired length of the prime p (in bits e.g. L = 1024)
* N = The desired length of the prime q (in bits e.g. N = 160)
* seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N
* outlen = The bit length of Hash function
*
* 1. Check that the (L, N)
* 2. If (seedlen <N), then return INVALID.
* 3. n = ceil(L / outlen) - 1
* 4. b = L- 1 - (n * outlen)
* 5. domain_parameter_seed = an arbitrary sequence of seedlen bits
* 6. U = Hash (domain_parameter_seed) mod 2^(N-1)
* 7. q = 2^(N-1) + U + 1 - (U mod 2)
* 8. Test whether or not q is prime as specified in Appendix C.3
* 9. If qis not a prime, then go to step 5.
* 10. offset = 1
* 11. For counter = 0 to (4L- 1) do {
* For j=0 to n do {
* Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen
* }
* W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen))
* X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L
* c = X mod 2*q
* p = X - (c - 1) Comment: p ~ 1 (mod 2*q)
* If (p >= 2^(L-1)) {
* Test whether or not p is prime as specified in Appendix C.3.
* If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter
* }
* offset = offset + n + 1 Comment: Increment offset
* }
*/
seedbytes = group_size;
L = (unsigned long)modulus_size * 8;
N = (unsigned long)group_size * 8;
/* XXX-TODO no Lucas test */
#ifdef LTC_MPI_HAS_LUCAS_TEST
/* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
mr_tests_p = (L <= 2048) ? 3 : 2;
if (N <= 160) { mr_tests_q = 19; }
else if (N <= 224) { mr_tests_q = 24; }
else { mr_tests_q = 27; }
#else
/* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
if (L <= 1024) { mr_tests_p = 40; }
else if (L <= 2048) { mr_tests_p = 56; }
else { mr_tests_p = 64; }
if (N <= 160) { mr_tests_q = 40; }
else if (N <= 224) { mr_tests_q = 56; }
else { mr_tests_q = 64; }
#endif
if (N <= 256) {
hash = register_hash(&sha256_desc);
}
else if (N <= 384) {
hash = register_hash(&sha384_desc);
}
else if (N <= 512) {
hash = register_hash(&sha512_desc);
}
else {
return CRYPT_INVALID_ARG; /* group_size too big */
}
if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; }
outbytes = hash_descriptor[hash].hashsize;
n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1;
if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; }
if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; }
err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL);
if (err != CRYPT_OK) { goto cleanup1; }
if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; }
/* t2L1 = 2^(L-1) */
if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; }
/* t2N1 = 2^(N-1) */
if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; }
/* t2seedlen = 2^seedlen */
for(found_p=0; !found_p;) {
/* q */
for(found_q=0; !found_q;) {
if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; }
i = outbytes;
if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; }
if (!mp_isodd(q)) mp_add_d(q, 1, q);
if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; }
if (res == LTC_MP_YES) found_q = 1;
}
/* p */
if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; }
for(counter=0; counter < 4*L && !found_p; counter++) {
for(j=0; j<=n; j++) {
if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; }
/* seedinc = (seedinc+1) % 2^seed_bitlen */
if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; }
zeromem(sbuf, seedbytes);
if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; }
i = outbytes;
err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i);
if (err != CRYPT_OK) { goto cleanup; }
}
if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; }
if (mp_cmp(p, t2L1) != LTC_MP_LT) {
/* p >= 2^(L-1) */
if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; }
if (res == LTC_MP_YES) {
found_p = 1;
}
}
}
}
/* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g
* 1. e = (p - 1)/q
* 2. h = any integer satisfying: 1 < h < (p - 1)
* h could be obtained from a random number generator or from a counter that changes after each use
* 3. g = h^e mod p
* 4. if (g == 1), then go to step 2.
*
*/
if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; }
if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; }
/* e = (p - 1)/q */
i = mp_count_bits(p);
do {
do {
if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; }
} while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT);
if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; }
/* h is randon and 1 < h < (p-1) */
if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; }
} while (mp_cmp_d(g, 1) == LTC_MP_EQ);
err = CRYPT_OK;
cleanup:
mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL);
cleanup1:
XFREE(sbuf);
cleanup2:
XFREE(wbuf);
cleanup3:
return err;
}
/**
Generate DSA parameters p, q & g
@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.
*/
int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
{
int err;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init mp_ints */
if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL)) != CRYPT_OK) {
return err;
}
/* generate params */
err = _dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g);
if (err != CRYPT_OK) {
goto cleanup;
}
key->qord = group_size;
return CRYPT_OK;
cleanup:
dsa_free(key);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,152 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_import.c
DSA implementation, import a DSA key, Tom St Denis
*/
#ifdef LTC_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)
{
int err, stat;
unsigned long zero = 0;
unsigned char* tmpbuf = NULL;
unsigned char flags[1];
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != CRYPT_OK) {
return CRYPT_MEM;
}
/* try to match the old libtomcrypt format */
err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_EOL, 0UL, NULL);
if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) {
/* private key */
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 LBL_ERR;
}
key->type = PK_PRIVATE;
goto LBL_OK;
}
/* public key */
else if (flags[0] == 0) {
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 LBL_ERR;
}
key->type = PK_PUBLIC;
goto LBL_OK;
}
else {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
}
/* get key type */
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_INTEGER, 1UL, key->y,
LTC_ASN1_INTEGER, 1UL, key->x,
LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
key->type = PK_PRIVATE;
} else { /* public */
ltc_asn1_list params[3];
unsigned long tmpbuf_len = inlen;
LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL);
LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL);
tmpbuf = XCALLOC(1, tmpbuf_len);
if (tmpbuf == NULL) {
err = CRYPT_MEM;
goto LBL_ERR;
}
err = der_decode_subject_public_key_info(in, inlen, PKA_DSA,
tmpbuf, &tmpbuf_len,
LTC_ASN1_SEQUENCE, params, 3);
if (err != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;
}
if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;
}
XFREE(tmpbuf);
key->type = PK_PUBLIC;
}
LBL_OK:
key->qord = mp_unsigned_bin_size(key->q);
/* quick p, q, g validation, without primality testing */
if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) {
goto LBL_ERR;
}
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
/* validate x, y */
if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) {
goto LBL_ERR;
}
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
return CRYPT_OK;
LBL_ERR:
dsa_free(key);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,41 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_make_key.c
DSA implementation, generate a DSA key
*/
#ifdef LTC_MDSA
/**
Old-style creation of 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.
*/
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
{
int err;
if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; }
if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
return CRYPT_OK;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

112
thirdparty/libtomcrypt/pk/dsa/dsa_set.c vendored Normal file
View File

@ -0,0 +1,112 @@
/* 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.
*/
#include "tomcrypt.h"
#ifdef LTC_MDSA
/**
Import DSA's p, q & g from raw numbers
@param p DSA's p in binary representation
@param plen The length of p
@param q DSA's q in binary representation
@param qlen The length of q
@param g DSA's g in binary representation
@param glen The length of g
@param key [out] the destination for the imported key
@return CRYPT_OK if successful.
*/
int dsa_set_pqg(const unsigned char *p, unsigned long plen,
const unsigned char *q, unsigned long qlen,
const unsigned char *g, unsigned long glen,
dsa_key *key)
{
int err, stat;
LTC_ARGCHK(p != NULL);
LTC_ARGCHK(q != NULL);
LTC_ARGCHK(g != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
if (err != CRYPT_OK) return err;
if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; }
if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; }
if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; }
key->qord = mp_unsigned_bin_size(key->q);
/* do only a quick validation, without primality testing */
if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; }
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
return CRYPT_OK;
LBL_ERR:
dsa_free(key);
return err;
}
/**
Import DSA public or private key-part from raw numbers
NB: The p, q & g parts must be set beforehand
@param in The key-part to import, either public or private.
@param inlen The key-part's length
@param type Which type of key (PK_PRIVATE or PK_PUBLIC)
@param key [out] the destination for the imported key
@return CRYPT_OK if successful.
*/
int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key)
{
int err, stat = 0;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(key->x != NULL);
LTC_ARGCHK(key->y != NULL);
LTC_ARGCHK(key->p != NULL);
LTC_ARGCHK(key->g != NULL);
LTC_ARGCHK(key->q != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
if (type == PK_PRIVATE) {
key->type = PK_PRIVATE;
if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; }
}
else {
key->type = PK_PUBLIC;
if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
}
if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; }
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
return CRYPT_OK;
LBL_ERR:
dsa_free(key);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,67 @@
/* 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.
*/
#include "tomcrypt.h"
#ifdef LTC_MDSA
/**
Import DSA's p, q & g from dsaparam
dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048
@param dsaparam The DSA param DER encoded data
@param dsaparamlen The length of dhparam data
@param key [out] the destination for the imported key
@return CRYPT_OK if successful.
*/
int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen,
dsa_key *key)
{
int err, stat;
LTC_ARGCHK(dsaparam != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
if (err != CRYPT_OK) return err;
if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto LBL_ERR;
}
key->qord = mp_unsigned_bin_size(key->q);
/* quick p, q, g validation, without primality testing */
if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) {
goto LBL_ERR;
}
if (stat == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
return CRYPT_OK;
LBL_ERR:
dsa_free(key);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,70 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_shared_secret.c
DSA Crypto, Tom St Denis
*/
#ifdef LTC_MDSA
/**
Create a DSA shared secret between two keys
@param private_key The private DSA key (the exponent)
@param base The base of the exponentiation (allows this to be used for both encrypt and decrypt)
@param public_key The public key
@param out [out] Destination of the shared secret
@param outlen [in/out] The max size and resulting size of the shared secret
@return CRYPT_OK if successful
*/
int dsa_shared_secret(void *private_key, void *base,
dsa_key *public_key,
unsigned char *out, unsigned long *outlen)
{
unsigned long x;
void *res;
int err;
LTC_ARGCHK(private_key != NULL);
LTC_ARGCHK(public_key != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* make new point */
if ((err = mp_init(&res)) != CRYPT_OK) {
return err;
}
if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) {
mp_clear(res);
return err;
}
x = (unsigned long)mp_unsigned_bin_size(res);
if (*outlen < x) {
*outlen = x;
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
zeromem(out, x);
if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; }
err = CRYPT_OK;
*outlen = x;
done:
mp_clear(res);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,152 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_sign_hash.c
DSA implementation, sign a hash, Tom St Denis
*/
#ifdef LTC_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,
void *r, void *s,
prng_state *prng, int wprng, dsa_key *key)
{
void *k, *kinv, *tmp;
unsigned char *buf;
int err, qbits;
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 >= LTC_MDSA_MAX_GROUP) {
return CRYPT_INVALID_ARG;
}
buf = XMALLOC(LTC_MDSA_MAX_GROUP);
if (buf == NULL) {
return CRYPT_MEM;
}
/* Init our temps */
if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; }
qbits = mp_count_bits(key->q);
retry:
do {
/* gen random k */
if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; }
/* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */
if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; }
/* test gcd */
if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; }
} while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);
/* now find 1/k mod q */
if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; }
/* now find r = g^k mod p mod q */
if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; }
if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; }
if (mp_iszero(r) == LTC_MP_YES) { goto retry; }
/* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/
inlen = MIN(inlen, (unsigned long)(key->qord));
/* now find s = (in + xr)/k mod q */
if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; }
if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; }
if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; }
if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; }
if (mp_iszero(s) == LTC_MP_YES) { goto retry; }
err = CRYPT_OK;
error:
mp_clear_multi(k, kinv, tmp, NULL);
ERRBUF:
#ifdef LTC_CLEAN_STACK
zeromem(buf, LTC_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)
{
void *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) != CRYPT_OK) {
return CRYPT_MEM;
}
if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) {
goto error;
}
err = der_encode_sequence_multi(out, outlen,
LTC_ASN1_INTEGER, 1UL, r,
LTC_ASN1_INTEGER, 1UL, s,
LTC_ASN1_EOL, 0UL, NULL);
error:
mp_clear_multi(r, s, NULL);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,137 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_verify_hash.c
DSA implementation, verify a signature, Tom St Denis
*/
#ifdef LTC_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 DSA key
@return CRYPT_OK if successful (even if the signature is invalid)
*/
int dsa_verify_hash_raw( void *r, void *s,
const unsigned char *hash, unsigned long hashlen,
int *stat, dsa_key *key)
{
void *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)) != CRYPT_OK) {
return err;
}
/* neither r or s can be null or >q*/
if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */
hashlen = MIN(hashlen, (unsigned long)(key->qord));
/* w = 1/s mod q */
if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; }
/* u1 = m * w mod q */
if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; }
/* u2 = r*w mod q */
if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; }
/* v = g^u1 * y^u2 mod p mod q */
if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; }
if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; }
if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; }
if ((err = mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; }
/* if r = v then we're set */
if (mp_cmp(r, v) == LTC_MP_EQ) {
*stat = 1;
}
err = CRYPT_OK;
error:
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 DSA 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;
void *r, *s;
ltc_asn1_list sig_seq[2];
unsigned long reallen = 0;
LTC_ARGCHK(stat != NULL);
*stat = 0; /* must be set before the first return */
if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
return err;
}
LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
err = der_decode_sequence(sig, siglen, sig_seq, 2);
if (err != CRYPT_OK) {
goto LBL_ERR;
}
err = der_length_sequence(sig_seq, 2, &reallen);
if (err != CRYPT_OK || reallen != siglen) {
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
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */

View File

@ -0,0 +1,199 @@
/* 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.
*/
#include "tomcrypt.h"
/**
@file dsa_verify_key.c
DSA implementation, verify a key, Tom St Denis
*/
#ifdef LTC_MDSA
/**
Validate a DSA key
Yeah, this function should've been called dsa_validate_key()
in the first place and for compat-reasons we keep it
as it was (for now).
@param key The key to validate
@param stat [out] Result of test, 1==valid, 0==invalid
@return CRYPT_OK if successful
*/
int dsa_verify_key(dsa_key *key, int *stat)
{
int err;
err = dsa_int_validate_primes(key, stat);
if (err != CRYPT_OK || *stat == 0) return err;
err = dsa_int_validate_pqg(key, stat);
if (err != CRYPT_OK || *stat == 0) return err;
return dsa_int_validate_xy(key, stat);
}
/**
Non-complex part (no primality testing) of the validation
of DSA params (p, q, g)
@param key The key to validate
@param stat [out] Result of test, 1==valid, 0==invalid
@return CRYPT_OK if successful
*/
int dsa_int_validate_pqg(dsa_key *key, int *stat)
{
void *tmp1, *tmp2;
int err;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(stat != NULL);
*stat = 0;
/* check q-order */
if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
(unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
(mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
return CRYPT_OK;
}
/* FIPS 186-4 chapter 4.1: 1 < g < p */
if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
return CRYPT_OK;
}
if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) { return err; }
/* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; }
if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; }
if (mp_iszero(tmp2) != LTC_MP_YES) {
err = CRYPT_OK;
goto error;
}
/* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
* the multiplicative group of GF(p) - so we make sure that g^q mod p = 1
*/
if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; }
if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) {
err = CRYPT_OK;
goto error;
}
err = CRYPT_OK;
*stat = 1;
error:
mp_clear_multi(tmp2, tmp1, NULL);
return err;
}
/**
Primality testing of DSA params p and q
@param key The key to validate
@param stat [out] Result of test, 1==valid, 0==invalid
@return CRYPT_OK if successful
*/
int dsa_int_validate_primes(dsa_key *key, int *stat)
{
int err, res;
*stat = 0;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(stat != NULL);
/* key->q prime? */
if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
return err;
}
if (res == LTC_MP_NO) {
return CRYPT_OK;
}
/* key->p prime? */
if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
return err;
}
if (res == LTC_MP_NO) {
return CRYPT_OK;
}
*stat = 1;
return CRYPT_OK;
}
/**
Validation of a DSA key (x and y values)
@param key The key to validate
@param stat [out] Result of test, 1==valid, 0==invalid
@return CRYPT_OK if successful
*/
int dsa_int_validate_xy(dsa_key *key, int *stat)
{
void *tmp;
int err;
*stat = 0;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(stat != NULL);
/* 1 < y < p-1 */
if ((err = mp_init(&tmp)) != CRYPT_OK) {
return err;
}
if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) {
goto error;
}
if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) {
err = CRYPT_OK;
goto error;
}
if (key->type == PK_PRIVATE) {
/* FIPS 186-4 chapter 4.1: 0 < x < q */
if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) {
err = CRYPT_OK;
goto error;
}
/* FIPS 186-4 chapter 4.1: y = g^x mod p */
if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) {
goto error;
}
if (mp_cmp(tmp, key->y) != LTC_MP_EQ) {
err = CRYPT_OK;
goto error;
}
}
else {
/* with just a public key we cannot test y = g^x mod p therefore we
* only test that y^q mod p = 1, which makes sure y is in g^x mod p
*/
if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) {
goto error;
}
if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) {
err = CRYPT_OK;
goto error;
}
}
err = CRYPT_OK;
*stat = 1;
error:
mp_clear(tmp);
return err;
}
#endif
/* ref: HEAD -> master, tag: v1.18.2 */
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
/* commit time: 2018-07-01 22:49:01 +0200 */