From bd548b5771a325d3dc051887d3fd0225550d4418 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 5 Mar 2008 20:58:27 +0200 Subject: [PATCH] Added support for default hash functions in all PKCS algorithm schemes. Each PKCS algorithm scheme now allocates default hash function. The hash function is used in signature computation and verification if user does not give it as argument to silc_pkcs_sign or silc_pkcs_verify. --- lib/silccrypt/dsa.c | 66 ++++++++++++++++++++++++++++++++++---- lib/silccrypt/dsa.h | 5 ++- lib/silccrypt/rsa.c | 5 ++- lib/silccrypt/rsa.h | 4 ++- lib/silccrypt/silcpkcs1.c | 62 ++++++++++++++++++++--------------- lib/silccrypt/silcpkcs1.h | 8 ++--- lib/silccrypt/silcpkcs_i.h | 4 ++- lib/silccrypt/silcrng.h | 42 ++++++++++++------------ 8 files changed, 134 insertions(+), 62 deletions(-) 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); diff --git a/lib/silccrypt/dsa.h b/lib/silccrypt/dsa.h index 280d8248..18fb03e5 100644 --- a/lib/silccrypt/dsa.h +++ b/lib/silccrypt/dsa.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2007 Pekka Riikonen + Copyright (C) 2007 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ /* DSA Public key */ typedef struct { + SilcHash hash; /* Default hash function */ SilcMPInt g; /* generator */ SilcMPInt p; /* prime */ SilcMPInt q; /* prime */ @@ -32,6 +33,7 @@ typedef struct { /* DSA Private key */ typedef struct { + SilcHash hash; /* Default hash function */ SilcMPInt g; /* generator */ SilcMPInt p; /* prime */ SilcMPInt q; /* prime */ @@ -41,6 +43,7 @@ typedef struct { SilcUInt16 group_order; /* group order (size) */ } DsaPrivateKey; +SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_fips186_2_generate_key); SILC_PKCS_ALG_GENERATE_KEY(silc_dsa_generate_key); SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_dsa_import_public_key); SILC_PKCS_ALG_EXPORT_PUBLIC_KEY(silc_dsa_export_public_key); diff --git a/lib/silccrypt/rsa.c b/lib/silccrypt/rsa.c index 2b5151a8..cc5e0988 100644 --- a/lib/silccrypt/rsa.c +++ b/lib/silccrypt/rsa.c @@ -46,7 +46,6 @@ everything else too about cryptography. */ -/* $Id$ */ /* ChangeLog @@ -98,6 +97,10 @@ SilcBool silc_rsa_generate_keys(SilcUInt32 bits, SilcMPInt *p, SilcMPInt *q, if (!privkey) return FALSE; + /* Default hash shall be sha1 */ + silc_hash_alloc("sha1", &pubkey->hash); + silc_hash_alloc("sha1", &privkey->hash); + /* Initialize variables */ silc_mp_init(&privkey->n); silc_mp_init(&privkey->e); diff --git a/lib/silccrypt/rsa.h b/lib/silccrypt/rsa.h index 6a9506a4..1302f3b4 100644 --- a/lib/silccrypt/rsa.h +++ b/lib/silccrypt/rsa.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ /* RSA Public Key */ typedef struct { + SilcHash hash; /* Default hash */ SilcMPInt n; /* modulus */ SilcMPInt e; /* public exponent */ int bits; /* bits in key */ @@ -29,6 +30,7 @@ typedef struct { /* RSA Private Key */ typedef struct { + SilcHash hash; /* Default hash */ SilcMPInt n; /* modulus */ SilcMPInt e; /* public exponent */ SilcMPInt d; /* private exponent */ diff --git a/lib/silccrypt/silcpkcs1.c b/lib/silccrypt/silcpkcs1.c index 3d619612..347addec 100644 --- a/lib/silccrypt/silcpkcs1.c +++ b/lib/silccrypt/silcpkcs1.c @@ -338,6 +338,7 @@ SILC_PKCS_ALG_PUBLIC_KEY_FREE(silc_pkcs1_public_key_free) silc_mp_uninit(&key->n); silc_mp_uninit(&key->e); + silc_hash_free(key->hash); silc_free(key); } @@ -457,6 +458,7 @@ SILC_PKCS_ALG_PRIVATE_KEY_FREE(silc_pkcs1_private_key_free) silc_mp_uninit(&key->qP); silc_mp_uninit(&key->p); silc_mp_uninit(&key->q); + silc_hash_free(key->hash); silc_free(key); } @@ -598,6 +600,8 @@ SILC_PKCS_ALG_SIGN(silc_pkcs1_sign) /* Compute hash */ if (compute_hash) { + if (!hash) + hash = key->hash; silc_hash_make(hash, src, src_len, hashr); src = hashr; src_len = silc_hash_len(hash); @@ -702,33 +706,35 @@ SILC_PKCS_ALG_VERIFY(silc_pkcs1_verify) silc_buffer_set(&di, unpadded, len); /* If hash isn't given, allocate the one given in digest info */ - if (!hash) { - has_null = FALSE; + if (compute_hash) { + if (!hash) { + has_null = FALSE; - /* Decode digest info */ - if (!silc_asn1_decode(asn1, &di, - SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL), - SILC_ASN1_SEQUENCE, + /* Decode digest info */ + if (!silc_asn1_decode(asn1, &di, + SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL), SILC_ASN1_SEQUENCE, - SILC_ASN1_OID(&oid), - SILC_ASN1_NULL_T(SILC_ASN1_OPTIONAL, - SILC_ASN1_TAG_NULL, &has_null), - SILC_ASN1_END, - SILC_ASN1_END, SILC_ASN1_END)) - goto err; - - if (!silc_hash_alloc_by_oid(oid, &ihash)) { - SILC_LOG_DEBUG(("Unknown OID %s", oid)); - goto err; + SILC_ASN1_SEQUENCE, + SILC_ASN1_OID(&oid), + SILC_ASN1_NULL_T(SILC_ASN1_OPTIONAL, + SILC_ASN1_TAG_NULL, &has_null), + SILC_ASN1_END, + SILC_ASN1_END, SILC_ASN1_END)) + goto err; + + if (!silc_hash_alloc_by_oid(oid, &ihash)) { + SILC_LOG_DEBUG(("Unknown OID %s", oid)); + goto err; + } + hash = ihash; } - hash = ihash; - } - /* Hash the data */ - silc_hash_make(hash, data, data_len, hashr); - data = hashr; - data_len = silc_hash_len(hash); - oid = (char *)silc_hash_get_oid(hash); + /* Hash the data */ + silc_hash_make(hash, data, data_len, hashr); + data = hashr; + data_len = silc_hash_len(hash); + oid = (char *)silc_hash_get_oid(hash); + } /* Encode digest info for comparison */ memset(&ldi, 0, sizeof(ldi)); @@ -762,7 +768,7 @@ SILC_PKCS_ALG_VERIFY(silc_pkcs1_verify) silc_free(verify); silc_mp_uninit(&mp_tmp2); silc_mp_uninit(&mp_dst); - if (hash) + if (compute_hash) memset(hashr, 0, sizeof(hashr)); if (ihash) silc_hash_free(ihash); @@ -805,6 +811,8 @@ SILC_PKCS_ALG_SIGN(silc_pkcs1_sign_no_oid) /* 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); @@ -885,7 +893,9 @@ SILC_PKCS_ALG_VERIFY(silc_pkcs1_verify_no_oid) } /* 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); @@ -900,7 +910,7 @@ SILC_PKCS_ALG_VERIFY(silc_pkcs1_verify_no_oid) memset(verify, 0, verify_len); memset(unpadded, 0, sizeof(unpadded)); - if (hash) + if (compute_hash) memset(hashr, 0, sizeof(hashr)); silc_free(verify); silc_mp_uninit(&mp_tmp2); diff --git a/lib/silccrypt/silcpkcs1.h b/lib/silccrypt/silcpkcs1.h index 2218106e..bd366633 100644 --- a/lib/silccrypt/silcpkcs1.h +++ b/lib/silccrypt/silcpkcs1.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2003 - 2005 Pekka Riikonen + Copyright (C) 2003 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ #ifndef SILCPKCS1_H #define SILCPKCS1_H -/****d* silccrypt/SilcPKCS1API/SilcPkcs1BlockType +/****d* silccrypt/SilcPkcs1BlockType * * NAME * @@ -52,7 +52,7 @@ typedef enum { } SilcPkcs1BlockType; /***/ -/****f* silccrypt/SilcPKCS1API/silc_pkcs1_encode +/****f* silccrypt/silc_pkcs1_encode * * SYNOPSIS * @@ -84,7 +84,7 @@ SilcBool silc_pkcs1_encode(SilcPkcs1BlockType bt, SilcUInt32 dest_data_size, SilcRng rng); -/****f* silccrypt/SilcPKCS1API/silc_pkcs1_decode +/****f* silccrypt/silc_pkcs1_decode * * SYNOPSIS * diff --git a/lib/silccrypt/silcpkcs_i.h b/lib/silccrypt/silcpkcs_i.h index b730307a..7d666112 100644 --- a/lib/silccrypt/silcpkcs_i.h +++ b/lib/silccrypt/silcpkcs_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -111,6 +111,7 @@ SilcUInt32 signature_len, \ unsigned char *data, \ SilcUInt32 data_len, \ + SilcBool compute_hash, \ SilcHash hash, \ SilcRng rng, \ SilcPKCSVerifyCb verify_cb, \ @@ -288,6 +289,7 @@ struct SilcPKCSAlgorithmStruct { SilcUInt32 signature_len, \ unsigned char *data, \ SilcUInt32 data_len, \ + SilcBool compute_hash, \ SilcHash hash, \ SilcRng rng, \ SilcPKCSVerifyCb verify_cb, \ diff --git a/lib/silccrypt/silcrng.h b/lib/silccrypt/silcrng.h index bf32fd8f..4348fb2a 100644 --- a/lib/silccrypt/silcrng.h +++ b/lib/silccrypt/silcrng.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ #ifndef SILCRNG_H #define SILCRNG_H -/****s* silccrypt/SilcRNGAPI/SilcRng +/****s* silccrypt/SilcRng * * NAME * @@ -54,7 +54,7 @@ typedef struct SilcRngStruct *SilcRng; /* Prototypes */ -/****f* silccrypt/SilcRNGAPI/silc_rng_alloc +/****f* silccrypt/silc_rng_alloc * * SYNOPSIS * @@ -70,7 +70,7 @@ typedef struct SilcRngStruct *SilcRng; ***/ SilcRng silc_rng_alloc(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_free +/****f* silccrypt/silc_rng_free * * SYNOPSIS * @@ -84,7 +84,7 @@ SilcRng silc_rng_alloc(void); ***/ void silc_rng_free(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_init +/****f* silccrypt/silc_rng_init * * SYNOPSIS * @@ -105,7 +105,7 @@ void silc_rng_free(SilcRng rng); ***/ void silc_rng_init(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_byte +/****f* silccrypt/silc_rng_get_byte * * SYNOPSIS * @@ -118,7 +118,7 @@ void silc_rng_init(SilcRng rng); ***/ SilcUInt8 silc_rng_get_byte(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_byte_fast +/****f* silccrypt/silc_rng_get_byte_fast * * SYNOPSIS * @@ -139,7 +139,7 @@ SilcUInt8 silc_rng_get_byte(SilcRng rng); ***/ SilcUInt8 silc_rng_get_byte_fast(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_rn16 +/****f* silccrypt/silc_rng_get_rn16 * * SYNOPSIS * @@ -152,7 +152,7 @@ SilcUInt8 silc_rng_get_byte_fast(SilcRng rng); ***/ SilcUInt16 silc_rng_get_rn16(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_rn32 +/****f* silccrypt/silc_rng_get_rn32 * * SYNOPSIS * @@ -165,7 +165,7 @@ SilcUInt16 silc_rng_get_rn16(SilcRng rng); ***/ SilcUInt32 silc_rng_get_rn32(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_rn_string +/****f* silccrypt/silc_rng_get_rn_string * * SYNOPSIS * @@ -180,7 +180,7 @@ SilcUInt32 silc_rng_get_rn32(SilcRng rng); ***/ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len); -/****f* silccrypt/SilcRNGAPI/silc_rng_get_rn_data +/****f* silccrypt/silc_rng_get_rn_data * * SYNOPSIS * @@ -197,7 +197,7 @@ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len); SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, unsigned char *buf, SilcUInt32 buf_size); -/****f* silccrypt/SilcRNGAPI/silc_rng_add_noise +/****f* silccrypt/silc_rng_add_noise * * SYNOPSIS * @@ -212,7 +212,7 @@ SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, ***/ void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_init +/****f* silccrypt/silc_rng_global_init * * SYNOPSIS * @@ -238,7 +238,7 @@ void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len); ***/ SilcBool silc_rng_global_init(SilcRng rng); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_uninit +/****f* silccrypt/silc_rng_global_uninit * * SYNOPSIS * @@ -252,7 +252,7 @@ SilcBool silc_rng_global_init(SilcRng rng); ***/ SilcBool silc_rng_global_uninit(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_byte +/****f* silccrypt/silc_rng_global_get_byte * * SYNOPSIS * @@ -265,7 +265,7 @@ SilcBool silc_rng_global_uninit(void); ***/ SilcUInt8 silc_rng_global_get_byte(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_byte_fast +/****f* silccrypt/silc_rng_global_get_byte_fast * * SYNOPSIS * @@ -286,7 +286,7 @@ SilcUInt8 silc_rng_global_get_byte(void); ***/ SilcUInt8 silc_rng_global_get_byte_fast(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_rn16 +/****f* silccrypt/silc_rng_global_get_rn16 * * SYNOPSIS * @@ -299,7 +299,7 @@ SilcUInt8 silc_rng_global_get_byte_fast(void); ***/ SilcUInt16 silc_rng_global_get_rn16(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_rn32 +/****f* silccrypt/silc_rng_global_get_rn32 * * SYNOPSIS * @@ -312,7 +312,7 @@ SilcUInt16 silc_rng_global_get_rn16(void); ***/ SilcUInt32 silc_rng_global_get_rn32(void); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_rn_string +/****f* silccrypt/silc_rng_global_get_rn_string * * SYNOPSIS * @@ -327,7 +327,7 @@ SilcUInt32 silc_rng_global_get_rn32(void); ***/ unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_get_rn_data +/****f* silccrypt/silc_rng_global_get_rn_data * * SYNOPSIS * @@ -345,7 +345,7 @@ unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len); SilcBool silc_rng_global_get_rn_data(SilcRng rng, SilcUInt32 len, unsigned char *buf, SilcUInt32 buf_size); -/****f* silccrypt/SilcRNGAPI/silc_rng_global_add_noise +/****f* silccrypt/silc_rng_global_add_noise * * SYNOPSIS * -- 2.24.0