re-factor dsa_make_key() etc.
This commit is contained in:
parent
24946d08b7
commit
cfff656e25
@ -646,7 +646,7 @@ static void time_prng(void)
|
|||||||
/* time various DSA operations */
|
/* time various DSA operations */
|
||||||
static void time_dsa(void)
|
static void time_dsa(void)
|
||||||
{
|
{
|
||||||
dsa_key key;
|
dsa_key key = LTC_DSA_KEY_INITIALIZER;
|
||||||
ulong64 t1, t2;
|
ulong64 t1, t2;
|
||||||
unsigned long x, y;
|
unsigned long x, y;
|
||||||
int err;
|
int err;
|
||||||
@ -665,7 +665,11 @@ static const struct {
|
|||||||
for (y = 0; y < 4; y++) {
|
for (y = 0; y < 4; y++) {
|
||||||
t_start();
|
t_start();
|
||||||
t1 = t_read();
|
t1 = t_read();
|
||||||
if ((err = dsa_make_key(&yarrow_prng, find_prng("yarrow"), groups[x].group, groups[x].modulus, &key)) != CRYPT_OK) {
|
if ((err = dsa_generate_pqg(&yarrow_prng, find_prng("yarrow"), groups[x].group, groups[x].modulus, &key)) != CRYPT_OK) {
|
||||||
|
fprintf(stderr, "\n\ndsa_generate_pqg says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if ((err = dsa_make_key_ex(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
|
||||||
fprintf(stderr, "\n\ndsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
|
fprintf(stderr, "\n\ndsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -442,9 +442,20 @@ typedef struct {
|
|||||||
void *y;
|
void *y;
|
||||||
} dsa_key;
|
} dsa_key;
|
||||||
|
|
||||||
|
#define LTC_DSA_KEY_INITIALIZER { PK_PUBLIC, 0, NULL, NULL, NULL, NULL, NULL }
|
||||||
|
|
||||||
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
|
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
|
||||||
|
|
||||||
int dsa_make_key_ex(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key, char* p_hex, char* q_hex, char* g_hex);
|
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 dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
|
||||||
|
|
||||||
|
int dsa_set_key(const unsigned char *pub, unsigned long publen,
|
||||||
|
const unsigned char *priv, unsigned long privlen,
|
||||||
|
dsa_key *key);
|
||||||
|
int dsa_make_key_ex(prng_state *prng, int wprng, dsa_key *key);
|
||||||
|
|
||||||
void dsa_free(dsa_key *key);
|
void dsa_free(dsa_key *key);
|
||||||
|
|
||||||
@ -473,7 +484,6 @@ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
|
|||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
dsa_key *key);
|
dsa_key *key);
|
||||||
|
|
||||||
int dsa_import_radix(int radix, char *p, char *q, char *g, char *x, char *y, dsa_key *key);
|
|
||||||
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
|
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
|
||||||
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
|
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
|
||||||
int dsa_verify_key(dsa_key *key, int *stat);
|
int dsa_verify_key(dsa_key *key, int *stat);
|
||||||
|
248
src/pk/dsa/dsa_generate_pqg.c
Normal file
248
src/pk/dsa/dsa_generate_pqg.c
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/* 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 = modulus_size * 8;
|
||||||
|
N = 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(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(key->qord == 0);
|
||||||
|
LTC_ARGCHK(ltc_mp.name != NULL);
|
||||||
|
|
||||||
|
/* init mp_ints */
|
||||||
|
if ((err = mp_init_multi(&key->g, &key->q, &key->p, &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: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -1,69 +0,0 @@
|
|||||||
/* 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"
|
|
||||||
|
|
||||||
/**
|
|
||||||
Import DSA public or private key from raw numbers
|
|
||||||
@param radix the radix the numbers are represented in (2-64, 16 = hexadecimal)
|
|
||||||
@param p DSA's p in radix representation
|
|
||||||
@param q DSA's q in radix representation
|
|
||||||
@param g DSA's g in radix representation
|
|
||||||
@param x DSA's x in radix representation (only private key, NULL for public key)
|
|
||||||
@param y DSA's y in radix representation
|
|
||||||
@param key [out] the destination for the imported key
|
|
||||||
@return CRYPT_OK if successful, upon error allocated memory is freed
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef LTC_MDSA
|
|
||||||
|
|
||||||
int dsa_import_radix(int radix, char *p, char *q, char *g, char *x, char *y, dsa_key *key)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
LTC_ARGCHK(p != NULL);
|
|
||||||
LTC_ARGCHK(q != NULL);
|
|
||||||
LTC_ARGCHK(g != NULL);
|
|
||||||
LTC_ARGCHK(y != 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_radix(key->p , p , radix)) != CRYPT_OK) { goto LBL_ERR; }
|
|
||||||
if ((err = mp_read_radix(key->q , q , radix)) != CRYPT_OK) { goto LBL_ERR; }
|
|
||||||
if ((err = mp_read_radix(key->g , g , radix)) != CRYPT_OK) { goto LBL_ERR; }
|
|
||||||
if ((err = mp_read_radix(key->y , y , radix)) != CRYPT_OK) { goto LBL_ERR; }
|
|
||||||
if (x && strlen(x) > 0) {
|
|
||||||
key->type = PK_PRIVATE;
|
|
||||||
if ((err = mp_read_radix(key->x , x , radix)) != CRYPT_OK) { goto LBL_ERR; }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
key->type = PK_PUBLIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
key->qord = mp_unsigned_bin_size(key->q);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
goto LBL_ERR;
|
|
||||||
}
|
|
||||||
return CRYPT_OK;
|
|
||||||
|
|
||||||
LBL_ERR:
|
|
||||||
mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ref: $Format:%D$ */
|
|
||||||
/* git commit: $Format:%H$ */
|
|
||||||
/* commit time: $Format:%ai$ */
|
|
@ -10,265 +10,61 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
@file dsa_make_key.c
|
@file dsa_make_key.c
|
||||||
DSA implementation, generate a DSA key, Tom St Denis
|
DSA implementation, generate a DSA key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef LTC_MDSA
|
#ifdef LTC_MDSA
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create DSA parameters (INTERNAL ONLY, not part of public API)
|
Create a DSA key
|
||||||
@param prng An active PRNG state
|
@param prng An active PRNG state
|
||||||
@param wprng The index of the PRNG desired
|
@param wprng The index of the PRNG desired
|
||||||
@param group_size Size of the multiplicative group (octets)
|
@param key [in/out] Where to store the created key
|
||||||
@param modulus_size Size of the modulus (octets)
|
@return CRYPT_OK if successful.
|
||||||
@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)
|
int dsa_make_key_ex(prng_state *prng, int wprng, dsa_key *key)
|
||||||
{
|
|
||||||
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 = modulus_size * 8;
|
|
||||||
N = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Create a DSA key (with given params)
|
|
||||||
@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
|
|
||||||
@param p_hex Hexadecimal string 'p'
|
|
||||||
@param q_hex Hexadecimal string 'q'
|
|
||||||
@param g_hex Hexadecimal string 'g'
|
|
||||||
@return CRYPT_OK if successful, upon error this function will free all allocated memory
|
|
||||||
*/
|
|
||||||
int dsa_make_key_ex(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key, char* p_hex, char* q_hex, char* g_hex)
|
|
||||||
{
|
{
|
||||||
int err, qbits;
|
int err, qbits;
|
||||||
|
|
||||||
LTC_ARGCHK(key != NULL);
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(key->x != NULL);
|
||||||
/* init mp_ints */
|
LTC_ARGCHK(key->y != NULL);
|
||||||
if ((err = mp_init_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
|
LTC_ARGCHK(key->p != NULL);
|
||||||
return err;
|
LTC_ARGCHK(key->g != NULL);
|
||||||
}
|
LTC_ARGCHK(key->q != NULL);
|
||||||
|
LTC_ARGCHK(ltc_mp.name != NULL);
|
||||||
if (p_hex == NULL || q_hex == NULL || g_hex == NULL) {
|
|
||||||
/* generate params */
|
|
||||||
err = _dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g);
|
|
||||||
if (err != CRYPT_OK) { goto cleanup; }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* read params */
|
|
||||||
if ((err = mp_read_radix(key->p, p_hex, 16)) != CRYPT_OK) { goto cleanup; }
|
|
||||||
if ((err = mp_read_radix(key->q, q_hex, 16)) != CRYPT_OK) { goto cleanup; }
|
|
||||||
if ((err = mp_read_radix(key->g, g_hex, 16)) != CRYPT_OK) { goto cleanup; }
|
|
||||||
/* XXX-TODO maybe do some validity check for p, q, g */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* so now we have our DH structure, generator g, order q, modulus p
|
/* 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
|
Now we need a random exponent [mod q] and it's power g^x mod p
|
||||||
*/
|
*/
|
||||||
qbits = mp_count_bits(key->q);
|
qbits = mp_count_bits(key->q);
|
||||||
do {
|
do {
|
||||||
if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK) { goto cleanup; }
|
if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK) { return err; }
|
||||||
/* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
|
/* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
|
||||||
} while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT);
|
} while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT);
|
||||||
if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto cleanup; }
|
if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; }
|
||||||
key->type = PK_PRIVATE;
|
key->type = PK_PRIVATE;
|
||||||
key->qord = group_size;
|
|
||||||
|
|
||||||
return CRYPT_OK;
|
return CRYPT_OK;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a DSA key
|
Old-style creation of a DSA key
|
||||||
@param prng An active PRNG state
|
@param prng An active PRNG state
|
||||||
@param wprng The index of the PRNG desired
|
@param wprng The index of the PRNG desired
|
||||||
@param group_size Size of the multiplicative group (octets)
|
@param group_size Size of the multiplicative group (octets)
|
||||||
@param modulus_size Size of the modulus (octets)
|
@param modulus_size Size of the modulus (octets)
|
||||||
@param key [out] Where to store the created key
|
@param key [out] Where to store the created key
|
||||||
@return CRYPT_OK if successful, upon error this function will free all allocated memory
|
@return CRYPT_OK if successful.
|
||||||
*/
|
*/
|
||||||
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
|
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
|
||||||
{
|
{
|
||||||
return dsa_make_key_ex(prng, wprng, group_size, modulus_size, key, NULL, NULL, NULL);
|
int err;
|
||||||
|
|
||||||
|
if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; }
|
||||||
|
if ((err = dsa_make_key_ex(prng, wprng, key)) != CRYPT_OK) { return err; }
|
||||||
|
|
||||||
|
return CRYPT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
105
src/pk/dsa/dsa_set.c
Executable file
105
src/pk/dsa/dsa_set.c
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
/* 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 public or private key from raw numbers
|
||||||
|
@param p DSA's p in binary representation
|
||||||
|
@param q DSA's q in binary representation
|
||||||
|
@param g DSA's g in binary representation
|
||||||
|
@param key [out] the destination for the imported key
|
||||||
|
@return CRYPT_OK if successful, upon error allocated memory is freed
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
LTC_ARGCHK(p != NULL);
|
||||||
|
LTC_ARGCHK(q != NULL);
|
||||||
|
LTC_ARGCHK(g != NULL);
|
||||||
|
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(key->qord == 0);
|
||||||
|
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);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
goto LBL_ERR;
|
||||||
|
}
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
LBL_ERR:
|
||||||
|
dsa_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Import DSA public or private key from raw numbers
|
||||||
|
@param x DSA's x in binary representation (only private key, NULL for public key)
|
||||||
|
@param y DSA's y in binary representation
|
||||||
|
@param key [out] the destination for the imported key
|
||||||
|
@return CRYPT_OK if successful, upon error allocated memory is freed
|
||||||
|
*/
|
||||||
|
int dsa_set_key(const unsigned char *pub, unsigned long publen,
|
||||||
|
const unsigned char *priv, unsigned long privlen,
|
||||||
|
dsa_key *key)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
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 ((err = mp_read_unsigned_bin(key->y , (unsigned char *)pub , publen)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
|
if (priv != NULL) {
|
||||||
|
key->type = PK_PRIVATE;
|
||||||
|
if ((err = mp_read_unsigned_bin(key->x , (unsigned char *)priv , privlen)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
key->type = PK_PUBLIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
LBL_ERR:
|
||||||
|
dsa_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -59,13 +59,6 @@ static char *hex_q = "AA5BD7F4E5062413E58835CA00C7A635716194C5";
|
|||||||
static char *hex_x = "9936E5E4E9FB28BE91F5065FE8C935B3F5D81FC5";
|
static char *hex_x = "9936E5E4E9FB28BE91F5065FE8C935B3F5D81FC5";
|
||||||
static char *hex_y = "5316B0FBBF598A5E5595C14FAC43B80853E6CF0D9223FAB184595239BFCBF22D383ADD935205497E2B12C46173E36F54BD96E5A7AAA95A58A4B767D2C0BDC81EB13A124F98C005EF395D6ABAB70B3BD8B795DD796EA2D28473470388B464D9B9B84FF1C934BBF97366F57C2E11FEC331E60838596781EB6D4127D70D74AFA035";
|
static char *hex_y = "5316B0FBBF598A5E5595C14FAC43B80853E6CF0D9223FAB184595239BFCBF22D383ADD935205497E2B12C46173E36F54BD96E5A7AAA95A58A4B767D2C0BDC81EB13A124F98C005EF395D6ABAB70B3BD8B795DD796EA2D28473470388B464D9B9B84FF1C934BBF97366F57C2E11FEC331E60838596781EB6D4127D70D74AFA035";
|
||||||
|
|
||||||
/* private key - raw decimal numbers */
|
|
||||||
static char *dec_g = "41834149751984197912953436480983170533071735026506895442815002322147255782590882063707309354781506433716654796985480894012184326029507913813728323760888731712844346877576824916725534905000120412305763983626878322597033839508975868744887842375259196379140567488975525420966465471602331600963525846901216912348";
|
|
||||||
static char *dec_p = "138366127874251453574215823372867983172559870428080754538874699342292548213873551009389476481395012375639515165022292709776266658812209612126692196557051247870332681145778007636026326219557730049370214260237710845864302921876857532769906463917243319959886290876544710558897185626634470575981605420411381006287";
|
|
||||||
static char *dec_q = "972576611327916959546542817054443329226761409733";
|
|
||||||
static char *dec_x = "874699854785640347852049895863914110365034094533";
|
|
||||||
static char *dec_y = "58346825863862115220306694056113472976936045407556113559931032566376300411053620606958863235131122432665794570437845128216268156672161823000705623178942581094085367656740608001229642983928728905397237964247962716781137229394844332774819193277135681825866994604976120931444766148118918668354923664000689348661";
|
|
||||||
|
|
||||||
/* The public part of test_dsa.key in SubjectPublicKeyInfo format */
|
/* The public part of test_dsa.key in SubjectPublicKeyInfo format */
|
||||||
static const unsigned char openssl_pub_dsa[] = {
|
static const unsigned char openssl_pub_dsa[] = {
|
||||||
0x30, 0x82, 0x01, 0xb6, 0x30, 0x82, 0x01, 0x2b, 0x06, 0x07, 0x2a, 0x86,
|
0x30, 0x82, 0x01, 0xb6, 0x30, 0x82, 0x01, 0x2b, 0x06, 0x07, 0x2a, 0x86,
|
||||||
@ -107,11 +100,13 @@ static const unsigned char openssl_pub_dsa[] = {
|
|||||||
0xeb, 0x6d, 0x41, 0x27, 0xd7, 0x0d, 0x74, 0xaf, 0xa0, 0x35
|
0xeb, 0x6d, 0x41, 0x27, 0xd7, 0x0d, 0x74, 0xaf, 0xa0, 0x35
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dsa_compat_test(void)
|
static int _dsa_compat_test(void)
|
||||||
{
|
{
|
||||||
dsa_key key;
|
dsa_key key = LTC_DSA_KEY_INITIALIZER;
|
||||||
unsigned char tmp[1024], buf[1024];
|
unsigned char tmp[1024], buf[1024];
|
||||||
unsigned long x, len;
|
unsigned long x, len;
|
||||||
|
unsigned char key_parts[5][256];
|
||||||
|
unsigned long key_lens[5];
|
||||||
|
|
||||||
DO(dsa_import(openssl_priv_dsa, sizeof(openssl_priv_dsa), &key));
|
DO(dsa_import(openssl_priv_dsa, sizeof(openssl_priv_dsa), &key));
|
||||||
|
|
||||||
@ -135,7 +130,22 @@ static int dsa_compat_test(void)
|
|||||||
dsa_free(&key);
|
dsa_free(&key);
|
||||||
|
|
||||||
/* try import private key from raw hexadecimal numbers */
|
/* try import private key from raw hexadecimal numbers */
|
||||||
DO(dsa_import_radix(16, hex_p, hex_q, hex_g, hex_x, hex_y, &key));
|
for (x = 0; x < 5; ++x) {
|
||||||
|
key_lens[x] = sizeof(key_parts[x]);
|
||||||
|
}
|
||||||
|
DO(radix_to_bin(hex_p, 16, key_parts[0], &key_lens[0]));
|
||||||
|
DO(radix_to_bin(hex_q, 16, key_parts[1], &key_lens[1]));
|
||||||
|
DO(radix_to_bin(hex_g, 16, key_parts[2], &key_lens[2]));
|
||||||
|
DO(radix_to_bin(hex_y, 16, key_parts[3], &key_lens[3]));
|
||||||
|
DO(radix_to_bin(hex_x, 16, key_parts[4], &key_lens[4]));
|
||||||
|
|
||||||
|
DO(dsa_set_pqg(key_parts[0], key_lens[0],
|
||||||
|
key_parts[1], key_lens[1],
|
||||||
|
key_parts[2], key_lens[2],
|
||||||
|
&key));
|
||||||
|
DO(dsa_set_key(key_parts[3], key_lens[3],
|
||||||
|
key_parts[4], key_lens[4],
|
||||||
|
&key));
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
DO(dsa_export(buf, &len, PK_PRIVATE | PK_STD, &key));
|
DO(dsa_export(buf, &len, PK_PRIVATE | PK_STD, &key));
|
||||||
if (len != sizeof(openssl_priv_dsa) || memcmp(buf, openssl_priv_dsa, len)) {
|
if (len != sizeof(openssl_priv_dsa) || memcmp(buf, openssl_priv_dsa, len)) {
|
||||||
@ -144,18 +154,14 @@ static int dsa_compat_test(void)
|
|||||||
}
|
}
|
||||||
dsa_free(&key);
|
dsa_free(&key);
|
||||||
|
|
||||||
/* try import private key from raw decimal numbers */
|
|
||||||
DO(dsa_import_radix(10, dec_p, dec_q, dec_g, dec_x, dec_y, &key));
|
|
||||||
len = sizeof(buf);
|
|
||||||
DO(dsa_export(buf, &len, PK_PRIVATE | PK_STD, &key));
|
|
||||||
if (len != sizeof(openssl_priv_dsa) || memcmp(buf, openssl_priv_dsa, len)) {
|
|
||||||
fprintf(stderr, "DSA private export failed to match dsa_import_radix(10, ..)\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dsa_free(&key);
|
|
||||||
|
|
||||||
/* try import public key from raw hexadecimal numbers */
|
/* try import public key from raw hexadecimal numbers */
|
||||||
DO(dsa_import_radix(16, hex_p, hex_q, hex_g, NULL, hex_y, &key));
|
DO(dsa_set_pqg(key_parts[0], key_lens[0],
|
||||||
|
key_parts[1], key_lens[1],
|
||||||
|
key_parts[2], key_lens[2],
|
||||||
|
&key));
|
||||||
|
DO(dsa_set_key(key_parts[3], key_lens[3],
|
||||||
|
NULL, 0,
|
||||||
|
&key));
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
DO(dsa_export(buf, &len, PK_PUBLIC | PK_STD, &key));
|
DO(dsa_export(buf, &len, PK_PUBLIC | PK_STD, &key));
|
||||||
if (len != sizeof(openssl_pub_dsa) || memcmp(buf, openssl_pub_dsa, len)) {
|
if (len != sizeof(openssl_pub_dsa) || memcmp(buf, openssl_pub_dsa, len)) {
|
||||||
@ -164,16 +170,6 @@ static int dsa_compat_test(void)
|
|||||||
}
|
}
|
||||||
dsa_free(&key);
|
dsa_free(&key);
|
||||||
|
|
||||||
/* try import public key from raw decimal numbers */
|
|
||||||
DO(dsa_import_radix(10, dec_p, dec_q, dec_g, NULL, dec_y, &key));
|
|
||||||
len = sizeof(buf);
|
|
||||||
DO(dsa_export(buf, &len, PK_PUBLIC | PK_STD, &key));
|
|
||||||
if (len != sizeof(openssl_pub_dsa) || memcmp(buf, openssl_pub_dsa, len)) {
|
|
||||||
fprintf(stderr, "DSA public export failed to match dsa_import_radix(10, ..)\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dsa_free(&key);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,12 +178,14 @@ int dsa_test(void)
|
|||||||
unsigned char msg[16], out[1024], out2[1024], ch;
|
unsigned char msg[16], out[1024], out2[1024], ch;
|
||||||
unsigned long x, y;
|
unsigned long x, y;
|
||||||
int stat1, stat2;
|
int stat1, stat2;
|
||||||
dsa_key key, key2;
|
dsa_key key = LTC_DSA_KEY_INITIALIZER;
|
||||||
|
dsa_key key2 = LTC_DSA_KEY_INITIALIZER;
|
||||||
|
|
||||||
dsa_compat_test();
|
_dsa_compat_test();
|
||||||
|
|
||||||
/* make a random key */
|
/* make a random key */
|
||||||
DO(dsa_make_key(&yarrow_prng, find_prng("yarrow"), 20, 128, &key));
|
DO(dsa_generate_pqg(&yarrow_prng, find_prng("yarrow"), 20, 128, &key));
|
||||||
|
DO(dsa_make_key_ex(&yarrow_prng, find_prng("yarrow"), &key));
|
||||||
|
|
||||||
/* verify it */
|
/* verify it */
|
||||||
DO(dsa_verify_key(&key, &stat1));
|
DO(dsa_verify_key(&key, &stat1));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user