From: Nikos Mavrogiannopoulos Date: Sat, 11 Dec 2010 17:22:13 +0000 (+0100) Subject: Separated the sign_data functions to a hashing phase, a preparing phase, and the... X-Git-Tag: gnutls_2_11_7~136 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40a545318bced43171e062949b01988b6cda8e18;p=thirdparty%2Fgnutls.git Separated the sign_data functions to a hashing phase, a preparing phase, and the actual signing. --- diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c index 99f47e8f5f..a10d1a5947 100644 --- a/lib/gnutls_privkey.c +++ b/lib/gnutls_privkey.c @@ -249,10 +249,17 @@ gnutls_privkey_sign_data (gnutls_privkey_t signer, int ret; gnutls_datum_t digest; + ret = pk_hash_data(signer->pk_algorithm, hash, NULL, data, signature); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + switch (signer->pk_algorithm) { case GNUTLS_PK_RSA: - ret = pk_pkcs1_rsa_hash (hash, data, &digest); + ret = pk_prepare_pkcs1_rsa_hash (hash, &digest); if (ret < 0) { gnutls_assert (); @@ -260,20 +267,14 @@ gnutls_privkey_sign_data (gnutls_privkey_t signer, } break; case GNUTLS_PK_DSA: - ret = pk_dsa_hash (hash, data, &digest); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - break; default: gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; } - ret = gnutls_privkey_sign_hash (signer, &digest, signature); + ret = _gnutls_privkey_sign_hash (signer, &digest, signature); _gnutls_free_datum (&digest); if (ret < 0) @@ -283,10 +284,14 @@ gnutls_privkey_sign_data (gnutls_privkey_t signer, } return 0; + +cleanup: + _gnutls_free_datum (&digest); + return ret; } -/** - * gnutls_privkey_sign_hash: +/*- + * _gnutls_privkey_sign_hash: * @key: Holds the key * @data: holds the data to be signed * @signature: will contain the signature allocate with gnutls_malloc() @@ -296,9 +301,9 @@ gnutls_privkey_sign_data (gnutls_privkey_t signer, * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. - **/ + -*/ int -gnutls_privkey_sign_hash (gnutls_privkey_t key, +_gnutls_privkey_sign_hash (gnutls_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index 5d5cf48250..efc5e6de2e 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -140,10 +140,17 @@ gnutls_pkcs11_privkey_sign_data (gnutls_pkcs11_privkey_t signer, int ret; gnutls_datum_t digest; + ret = pk_hash_data(signer->pk_algorithm, hash, NULL, data, signature); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + switch (signer->pk_algorithm) { case GNUTLS_PK_RSA: - ret = pk_pkcs1_rsa_hash (hash, data, &digest); + ret = pk_prepare_pkcs1_rsa_hash (hash, &digest); if (ret < 0) { gnutls_assert (); @@ -151,17 +158,11 @@ gnutls_pkcs11_privkey_sign_data (gnutls_pkcs11_privkey_t signer, } break; case GNUTLS_PK_DSA: - ret = pk_dsa_hash (hash, data, &digest); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - break; default: gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; } ret = gnutls_pkcs11_privkey_sign_hash (signer, &digest, signature); @@ -175,6 +176,9 @@ gnutls_pkcs11_privkey_sign_data (gnutls_pkcs11_privkey_t signer, return 0; +cleanup: + _gnutls_free_datum (&digest); + return ret; } #define FIND_OBJECT(pks, obj, key) \ diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index baa39db8f7..e023d7b33e 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1687,10 +1687,17 @@ gnutls_x509_privkey_sign_data2 (gnutls_x509_privkey_t signer, int ret; gnutls_datum_t digest; + ret = pk_hash_data(signer->pk_algorithm, hash, signer->params, data, signature); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + switch (signer->pk_algorithm) { case GNUTLS_PK_RSA: - ret = pk_pkcs1_rsa_hash (hash, data, &digest); + ret = pk_prepare_pkcs1_rsa_hash (hash, &digest); if (ret < 0) { gnutls_assert (); @@ -1698,23 +1705,15 @@ gnutls_x509_privkey_sign_data2 (gnutls_x509_privkey_t signer, } break; case GNUTLS_PK_DSA: - /* override hash for DSA */ - ret = - pk_dsa_hash (_gnutls_dsa_q_to_hash (signer->params[1]), data, - &digest); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - break; default: gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; } - ret = gnutls_x509_privkey_sign_hash (signer, &digest, signature); + ret = _gnutls_soft_sign (signer->pk_algorithm, signer->params, + signer->params_size, &digest, signature); _gnutls_free_datum (&digest); if (ret < 0) @@ -1725,6 +1724,9 @@ gnutls_x509_privkey_sign_data2 (gnutls_x509_privkey_t signer, return 0; +cleanup: + _gnutls_free_datum (&digest); + return ret; } /** diff --git a/lib/x509/sign.c b/lib/x509/sign.c index 1151300c6c..3da98ed778 100644 --- a/lib/x509/sign.c +++ b/lib/x509/sign.c @@ -55,6 +55,8 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash, ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; int result; const char *algo; + opaque* tmp_output; + int tmp_output_size; algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash); if (algo == NULL) @@ -102,10 +104,10 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash, return _gnutls_asn2err (result); } - output->size = 0; - asn1_der_coding (dinfo, "", NULL, &output->size, NULL); + tmp_output_size = 0; + asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL); - output->data = gnutls_malloc (output->size); + tmp_output = gnutls_malloc (tmp_output_size); if (output->data == NULL) { gnutls_assert (); @@ -113,7 +115,7 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash, return GNUTLS_E_MEMORY_ERROR; } - result = asn1_der_coding (dinfo, "", output->data, &output->size, NULL); + result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); @@ -122,87 +124,83 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash, } asn1_delete_structure (&dinfo); + + output->size = tmp_output_size; + output->data = tmp_output; return 0; } -/* if hash==MD5 then we do RSA-MD5 - * if hash==SHA then we do RSA-SHA - * params[0] is modulus - * params[1] is public key - */ -int -pk_pkcs1_rsa_hash (gnutls_digest_algorithm_t hash, - const gnutls_datum_t * text, gnutls_datum_t * output) +int pk_hash_data(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash, + bigint_t * params, + const gnutls_datum_t * data, gnutls_datum_t * digest) { int ret; - opaque _digest[MAX_HASH_SIZE]; - digest_hd_st hd; - gnutls_datum_t digest; - ret = _gnutls_hash_init (&hd, HASH2MAC (hash)); - if (ret < 0) + switch (pk) { - gnutls_assert (); - return ret; + case GNUTLS_PK_RSA: + if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA224 && + hash != GNUTLS_DIG_SHA256) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + break; + case GNUTLS_PK_DSA: + if (params && hash != _gnutls_dsa_q_to_hash (params[1])) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + break; } - _gnutls_hash (&hd, text->data, text->size); - _gnutls_hash_deinit (&hd, _digest); - - digest.data = _digest; - digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash)); - - /* Encode the digest as a DigestInfo - */ - if ((ret = encode_ber_digest_info (hash, &digest, output)) != 0) + digest->size = _gnutls_hash_get_algo_len (hash); + digest->data = gnutls_malloc (digest->size); + if (digest->data == NULL) { gnutls_assert (); - return ret; + return GNUTLS_E_MEMORY_ERROR; + } + + ret = _gnutls_hash_fast(hash, data->data, data->size, digest->data); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; } return 0; + +cleanup: + gnutls_free(digest->data); + return ret; } +/* if hash==MD5 then we do RSA-MD5 + * if hash==SHA then we do RSA-SHA + * params[0] is modulus + * params[1] is public key + */ int -pk_dsa_hash (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text, - gnutls_datum_t * digest) +pk_prepare_pkcs1_rsa_hash (gnutls_digest_algorithm_t hash, + gnutls_datum_t * digest) { int ret; - digest_hd_st hd; - - if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA224 && - hash != GNUTLS_DIG_SHA256) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - digest->size = _gnutls_hash_get_algo_len (hash); - digest->data = gnutls_malloc (digest->size); - if (digest->data == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } + gnutls_datum old_digest = { digest->data, digest->size }; - ret = _gnutls_hash_init (&hd, hash); - if (ret < 0) + /* Encode the digest as a DigestInfo + */ + if ((ret = encode_ber_digest_info (hash, digest, digest)) != 0) { gnutls_assert (); - goto fail; + return ret; } - _gnutls_hash (&hd, text->data, text->size); - - _gnutls_hash_deinit (&hd, digest->data); + _gnutls_free_datum(&old_digest); return 0; - -fail: - gnutls_free (digest->data); - - return ret; } /* This is the same as the _gnutls_x509_sign, but this one will decode diff --git a/lib/x509/sign.h b/lib/x509/sign.h index 190e4c363b..5992bbd3bf 100644 --- a/lib/x509/sign.h +++ b/lib/x509/sign.h @@ -1,9 +1,9 @@ #ifndef GNUTLS_SIGN_H #define GNUTLS_SIGN_H -int pk_pkcs1_rsa_hash (gnutls_digest_algorithm_t hash, - const gnutls_datum_t * text, gnutls_datum_t * output); -int pk_dsa_hash (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text, - gnutls_datum_t * output); +int pk_prepare_pkcs1_rsa_hash (gnutls_digest_algorithm_t hash, + gnutls_datum_t * output); +int pk_hash_data(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash, + bigint_t * params, const gnutls_datum_t * data, gnutls_datum_t * digest); #endif