X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=blobdiff_plain;f=lib%2Fsilccrypt%2Fdsa.c;fp=lib%2Fsilccrypt%2Fdsa.c;h=7b6064156be14f53e3a0bb6fd4e57212c9ed2ee6;hp=e201a1c1fddc489b0d3f03427728ae3594033907;hb=bd548b5771a325d3dc051887d3fd0225550d4418;hpb=957577debbf00959048d7a5adebdff8d5019f1d5 diff --git a/lib/silccrypt/dsa.c b/lib/silccrypt/dsa.c index e201a1c1..7b606415 100644 --- a/lib/silccrypt/dsa.c +++ b/lib/silccrypt/dsa.c @@ -59,19 +59,28 @@ */ -/* Generates DSA key pair. For now this uses group size of 160 bits. */ +/* Generates DSA key pair. The q length and hash comes as argument. */ -SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key) +static SilcBool +silc_dsa_generate_key_int(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcUInt32 q_len, const char *hash, + SilcUInt32 keylen, SilcRng rng, + void **ret_public_key, void **ret_private_key) { DsaPublicKey *pubkey; DsaPrivateKey *privkey; SilcMPInt tmp, tmp2; unsigned char rnd[4096]; - int i, len = (keylen + 7) / 8, q_len = 160 / 8; + int i, len = (keylen + 7) / 8; + + q_len /= 8; if (keylen < 768 || keylen > 16384) return FALSE; + if (!silc_hash_is_supported(hash)) + return FALSE; + pubkey = silc_calloc(1, sizeof(*pubkey)); if (!pubkey) return FALSE; @@ -82,6 +91,9 @@ SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key) return FALSE; } + silc_hash_alloc(hash, &pubkey->hash); + silc_hash_alloc(hash, &privkey->hash); + silc_mp_init(&tmp); silc_mp_init(&tmp2); silc_mp_init(&privkey->p); @@ -101,8 +113,7 @@ SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key) silc_mp_add(&tmp, &privkey->q, &privkey->q); do { - /* Create p. Take random data, this returns non-zero bytes. Make the - number even. */ + /* Create p. Take random data, this returns non-zero bytes. */ silc_rng_get_rn_data(rng, len - q_len, rnd, sizeof(rnd)); rnd[(len - q_len) - 1] &= ~1; silc_mp_bin2mp(rnd, len - q_len, &tmp2); @@ -156,6 +167,37 @@ SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key) return TRUE; } +/* Generates DSA key pair. Complies with FIPS186-2. Uses 160 bit q. */ + +SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_fips186_2_generate_key) +{ + return silc_dsa_generate_key_int(pkcs, 160, "sha1", keylen, rng, + ret_public_key, ret_private_key); +} + +/* Generates DSA key pair. Complies with FIPS186-3. Same as the FIPS186-2 + but determines the length of q automatically. */ + +SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key) +{ + SilcUInt32 q_len; + const char *hash; + + if (keylen <= 1024) { + q_len = 160; + hash = "sha1"; + } else if (keylen <= 2048) { + q_len = 224; + hash = "sha224"; + } else { + q_len = 256; + hash = "sha256"; + } + + return silc_dsa_generate_key_int(pkcs, q_len, hash, keylen, rng, + ret_public_key, ret_private_key); +} + /* Import DSA public key */ SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_dsa_import_public_key) @@ -303,6 +345,7 @@ SILC_PKCS_ALG_PUBLIC_KEY_FREE(silc_dsa_public_key_free) silc_mp_uninit(&key->q); silc_mp_uninit(&key->g); silc_mp_uninit(&key->y); + silc_hash_free(key->hash); silc_free(key); } @@ -414,6 +457,7 @@ SILC_PKCS_ALG_PRIVATE_KEY_FREE(silc_dsa_private_key_free) silc_mp_uninit(&key->g); silc_mp_uninit(&key->y); silc_mp_uninit(&key->x); + silc_hash_free(key->hash); silc_free(key); } @@ -461,9 +505,13 @@ SILC_PKCS_ALG_SIGN(silc_dsa_sign) /* Compute hash if requested */ if (compute_hash) { + if (!hash) + hash = key->hash; silc_hash_make(hash, src, src_len, hashr); src = hashr; src_len = silc_hash_len(hash); + if (src_len > key->group_order) + src_len = key->group_order; } stack = silc_stack_alloc(2048, silc_crypto_stack()); @@ -583,10 +631,14 @@ SILC_PKCS_ALG_VERIFY(silc_dsa_verify) } /* Hash data if requested */ - if (hash) { + if (compute_hash) { + if (!hash) + hash = key->hash; silc_hash_make(hash, data, data_len, hashr); data = hashr; data_len = silc_hash_len(hash); + if (data_len > key->group_order) + data_len = key->group_order; } silc_mp_sinit(stack, &v); @@ -620,7 +672,7 @@ SILC_PKCS_ALG_VERIFY(silc_dsa_verify) /* Deliver result */ verify_cb(ret, context); - if (hash) + if (compute_hash) memset(hashr, 0, sizeof(hashr)); silc_mp_uninit(&v); silc_mp_uninit(&w);