From: Nikos Mavrogiannopoulos Date: Sat, 11 Dec 2010 17:58:27 +0000 (+0100) Subject: Introduced gnutls_*_privkey_sign_hash2() that is a high level function to produce... X-Git-Tag: gnutls_2_11_7~135 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b4566f433f23d82ed36461cf7eb45cde839d8296;p=thirdparty%2Fgnutls.git Introduced gnutls_*_privkey_sign_hash2() that is a high level function to produce signatures. --- diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c index a10d1a5947..4ba21d4e8d 100644 --- a/lib/gnutls_privkey.c +++ b/lib/gnutls_privkey.c @@ -290,6 +290,76 @@ cleanup: return ret; } +/** + * gnutls_privkey_sign_hash2: + * @signer: Holds the signer's key + * @hash_algo: The hash algorithm used + * @flags: zero for now + * @hash_data: holds the data to be signed + * @signature: will contain newly allocated signature + * + * This function will sign the given hashed data using a signature algorithm + * supported by the private key. Signature algorithms are always used + * together with a hash functions. Different hash functions may be + * used for the RSA algorithm, but only SHA-XXX for the DSA keys. + * + * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine + * the hash algorithm. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_privkey_sign_hash2 (gnutls_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature) +{ + int ret; + gnutls_datum_t digest; + + digest.data = gnutls_malloc(hash_data->size); + if (digest.data == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + digest.size = hash_data->size; + memcpy(digest.data, hash_data->data, digest.size); + + switch (signer->pk_algorithm) + { + case GNUTLS_PK_RSA: + ret = pk_prepare_pkcs1_rsa_hash (hash_algo, &digest); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + break; + case GNUTLS_PK_DSA: + break; + default: + gnutls_assert (); + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; + } + + ret = _gnutls_privkey_sign_hash (signer, &digest, signature); + if (ret < 0) + { + gnutls_assert (); + goto cleanup; + } + + ret = 0; + +cleanup: + _gnutls_free_datum(&digest); + return ret; +} + /*- * _gnutls_privkey_sign_hash: * @key: Holds the key @@ -311,14 +381,15 @@ _gnutls_privkey_sign_hash (gnutls_privkey_t key, { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: - return gnutls_openpgp_privkey_sign_hash (key->key.openpgp, + return _gnutls_openpgp_privkey_sign_hash (key->key.openpgp, hash, signature); #endif case GNUTLS_PRIVKEY_PKCS11: return gnutls_pkcs11_privkey_sign_hash (key->key.pkcs11, hash, signature); case GNUTLS_PRIVKEY_X509: - return gnutls_x509_privkey_sign_hash (key->key.x509, hash, signature); + return _gnutls_soft_sign (key->key.x509->pk_algorithm, key->key.x509->params, + key->key.x509->params_size, hash, signature); default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index f80d136359..2e68632b23 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -104,9 +104,13 @@ int gnutls_privkey_sign_data (gnutls_privkey_t signer, unsigned int flags, const gnutls_datum_t * data, gnutls_datum_t * signature); -int gnutls_privkey_sign_hash (gnutls_privkey_t key, - const gnutls_datum_t * hash, - gnutls_datum_t * signature); + +int +gnutls_privkey_sign_hash2 (gnutls_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature); int gnutls_privkey_decrypt_data (gnutls_privkey_t signer, unsigned int flags, diff --git a/lib/includes/gnutls/compat.h b/lib/includes/gnutls/compat.h index a31f067485..aaee9d8f4e 100644 --- a/lib/includes/gnutls/compat.h +++ b/lib/includes/gnutls/compat.h @@ -223,9 +223,10 @@ gnutls_sign_callback_get (gnutls_session_t session, void **userdata); gnutls_datum_t * signature) _GNUTLS_GCC_ATTR_DEPRECATED; - int gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, - const gnutls_datum_t * hash, - gnutls_datum_t * signature) - _GNUTLS_GCC_ATTR_DEPRECATED; + int gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, + unsigned int flags, + const gnutls_datum_t * hash, + const gnutls_datum_t * signature) + _GNUTLS_GCC_ATTR_DEPRECATED; #endif /* _GNUTLS_COMPAT_H */ diff --git a/lib/includes/gnutls/openpgp.h b/lib/includes/gnutls/openpgp.h index 4babbcc652..d6961458c1 100644 --- a/lib/includes/gnutls/openpgp.h +++ b/lib/includes/gnutls/openpgp.h @@ -169,6 +169,18 @@ extern "C" const char *password, unsigned int flags); + int gnutls_openpgp_privkey_sign_hash2 (gnutls_openpgp_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature); + + int gnutls_openpgp_privkey_sign_data2 (gnutls_openpgp_privkey_t signer, + gnutls_digest_algorithm_t hash, + unsigned int flags, + const gnutls_datum_t * data, + gnutls_datum_t * signature); + int gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 80bb435999..21923a3ba4 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -729,10 +729,12 @@ extern "C" unsigned int flags, const gnutls_datum_t * data, const gnutls_datum_t * signature); - int gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, - unsigned int flags, - const gnutls_datum_t * hash, - const gnutls_datum_t * signature); + + int gnutls_x509_privkey_sign_hash2 (gnutls_x509_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature); int gnutls_x509_crt_get_verify_algorithm (gnutls_x509_crt_t crt, const gnutls_datum_t * signature, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index f719563fe9..971931f3f1 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -694,6 +694,10 @@ GNUTLS_2_12 gnutls_pkcs11_token_init; gnutls_pkcs11_token_set_pin; gnutls_pkcs11_token_get_mechanism; + gnutls_privkey_sign_hash2; + gnutls_openpgp_privkey_sign_data2; + gnutls_openpgp_privkey_sign_hash2; + gnutls_x509_privkey_sign_hash2; } GNUTLS_2_10; GNUTLS_PRIVATE { diff --git a/lib/openpgp/gnutls_openpgp.c b/lib/openpgp/gnutls_openpgp.c index 2223c98068..1cd0528e52 100644 --- a/lib/openpgp/gnutls_openpgp.c +++ b/lib/openpgp/gnutls_openpgp.c @@ -840,8 +840,8 @@ _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) } -/** - * gnutls_openpgp_privkey_sign_hash: +/*- + * _gnutls_openpgp_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature @@ -852,9 +852,9 @@ _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. - **/ + -*/ int -gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, +_gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { @@ -913,6 +913,126 @@ gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, return 0; } +/** + * gnutls_openpgp_privkey_sign_hash2: + * @signer: Holds the signer's key + * @hash_algo: The hash algorithm used + * @hash_data: holds the data to be signed + * @signature: will contain newly allocated signature + * @flags: zero for now + * + * This function will sign the given hash using the private key. You + * should use gnutls_openpgp_privkey_set_preferred_key_id() before + * calling this function to set the subkey to use. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_openpgp_privkey_sign_hash2 (gnutls_openpgp_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature) +{ + int ret; + gnutls_datum_t digest; + + digest.data = gnutls_malloc(hash_data->size); + if (digest.data == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + digest.size = hash_data->size; + memcpy(digest.data, hash_data->data, digest.size); + + switch (gnutls_openpgp_privkey_get_pk_algorithm (signer, NULL)) + { + case GNUTLS_PK_RSA: + ret = pk_prepare_pkcs1_rsa_hash (hash_algo, &digest); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + break; + case GNUTLS_PK_DSA: + break; + default: + gnutls_assert (); + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; + } + return 0; + + ret = _gnutls_openpgp_privkey_sign_hash (signer, &digest, signature); + if (ret < 0) + { + gnutls_assert (); + goto cleanup; + } + + ret = 0; + +cleanup: + _gnutls_free_datum(&digest); + return ret; +} + +/** + * gnutls_openpgp_privkey_sign_data2: + * @signer: Holds the key + * @digest: should be MD5 or SHA1 + * @flags: should be 0 for now + * @data: holds the data to be signed + * @signature: will contain the signature allocate with gnutls_malloc() + * + * This function will sign the given data using a signature algorithm + * supported by the private key. Signature algorithms are always used + * together with a hash functions. Different hash functions may be + * used for the RSA algorithm, but only SHA-XXX for the DSA keys. + * + * The RSA algorithm is used in PKCS #1 v1.5 mode. + * + * If the buffer provided is not long enough to hold the output, then + * *@signature_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will + * be returned. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_openpgp_privkey_sign_data2 (gnutls_openpgp_privkey_t signer, + gnutls_digest_algorithm_t hash, + unsigned int flags, + const gnutls_datum_t * data, + gnutls_datum_t * signature) +{ + int ret; + gnutls_datum_t digest; + + ret = pk_hash_data(gnutls_openpgp_privkey_get_pk_algorithm(signer,NULL), hash, NULL, data, &digest); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + + ret = gnutls_openpgp_privkey_sign_hash2(signer, hash, flags, &digest, signature); + if (ret < 0) + { + gnutls_assert (); + goto cleanup; + } + + ret = 0; + +cleanup: + _gnutls_free_datum (&digest); + return ret; +} + /** * gnutls_openpgp_privkey_decrypt_data: * @key: Holds the key diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index e023d7b33e..456427e193 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1665,7 +1665,9 @@ cleanup: * This function will sign the given data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be - * used for the RSA algorithm, but only SHA-1 for the DSA keys. + * used for the RSA algorithm, but only SHA-XXX for the DSA keys. + * + * The RSA algorithm is used in PKCS #1 v1.5 mode. * * If the buffer provided is not long enough to hold the output, then * *@signature_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will @@ -1687,49 +1689,28 @@ 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); + ret = pk_hash_data(signer->pk_algorithm, hash, signer->params, data, &digest); if (ret < 0) { gnutls_assert(); return ret; } - switch (signer->pk_algorithm) - { - case GNUTLS_PK_RSA: - ret = pk_prepare_pkcs1_rsa_hash (hash, &digest); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - break; - case GNUTLS_PK_DSA: - break; - default: - gnutls_assert (); - ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; - goto cleanup; - } - - ret = _gnutls_soft_sign (signer->pk_algorithm, signer->params, - signer->params_size, &digest, signature); - _gnutls_free_datum (&digest); - + ret = gnutls_x509_privkey_sign_hash2(signer, hash, flags, &digest, signature); if (ret < 0) { gnutls_assert (); - return ret; + goto cleanup; } - return 0; + ret = 0; cleanup: _gnutls_free_datum (&digest); return ret; } -/** +/*- * gnutls_x509_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed @@ -1742,7 +1723,7 @@ cleanup: * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. - **/ + -*/ int gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key, const gnutls_datum_t * hash, @@ -1767,6 +1748,78 @@ gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key, return 0; } +/** + * gnutls_x509_privkey_sign_hash2: + * @signer: Holds the signer's key + * @hash_algo: The hash algorithm used + * @hash_data: holds the data to be signed + * @signature: will contain newly allocated signature + * @flags: zero for now + * + * This function will sign the given hashed data using a signature algorithm + * supported by the private key. Signature algorithms are always used + * together with a hash functions. Different hash functions may be + * used for the RSA algorithm, but only SHA-XXX for the DSA keys. + * + * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine + * the hash algorithm. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_x509_privkey_sign_hash2 (gnutls_x509_privkey_t signer, + gnutls_digest_algorithm_t hash_algo, + unsigned int flags, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature) +{ + int ret; + gnutls_datum_t digest; + + digest.data = gnutls_malloc(hash_data->size); + if (digest.data == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + digest.size = hash_data->size; + memcpy(digest.data, hash_data->data, digest.size); + + switch (signer->pk_algorithm) + { + case GNUTLS_PK_RSA: + ret = pk_prepare_pkcs1_rsa_hash (hash_algo, &digest); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + break; + case GNUTLS_PK_DSA: + break; + default: + gnutls_assert (); + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + goto cleanup; + } + + ret = _gnutls_soft_sign (signer->pk_algorithm, signer->params, + signer->params_size, &digest, signature); + + if (ret < 0) + { + gnutls_assert (); + goto cleanup; + } + + ret = 0; + +cleanup: + _gnutls_free_datum(&digest); + return ret; +} + #ifdef ENABLE_PKI /** * gnutls_x509_privkey_sign_data: