diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | doc/cha-cert-auth2.texi | 2 | ||||
-rw-r--r-- | lib/abstract_int.h | 10 | ||||
-rw-r--r-- | lib/algorithms.h | 2 | ||||
-rw-r--r-- | lib/algorithms/sign.c | 16 | ||||
-rw-r--r-- | lib/ext/signature.c | 2 | ||||
-rw-r--r-- | lib/gnutls_pubkey.c | 60 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 21 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 8 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 3 | ||||
-rw-r--r-- | lib/libgnutls.map | 2 | ||||
-rw-r--r-- | lib/x509/verify.c | 33 | ||||
-rw-r--r-- | lib/x509/x509.c | 33 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 4 | ||||
-rw-r--r-- | tests/x509sign-verify.c | 29 |
15 files changed, 158 insertions, 76 deletions
@@ -2,6 +2,15 @@ GnuTLS NEWS -- History of user-visible changes. -*- outline -*- Copyright (C) 2000-2012 Free Software Foundation, Inc. See the end for copying conditions. +* Version 3.0.20 (unreleased) + +** libgnutls: Added gnutls_pubkey_verify_hash2() + +** API and ABI modifications: +gnutls_pk_to_sign: Added +gnutls_pubkey_verify_hash2: Added + + * Version 3.0.19 (released 2012-04-22) ** libgnutls: When decoding a PKCS #11 URL the pin-source field diff --git a/doc/cha-cert-auth2.texi b/doc/cha-cert-auth2.texi index 6838bf5b94..df0c79990a 100644 --- a/doc/cha-cert-auth2.texi +++ b/doc/cha-cert-auth2.texi @@ -615,7 +615,7 @@ The abstract key types can be used to access signing and signature verification operations with the underlying keys. @showfuncdesc{gnutls_pubkey_verify_data2} -@showfuncdesc{gnutls_pubkey_verify_hash} +@showfuncdesc{gnutls_pubkey_verify_hash2} @showfuncdesc{gnutls_pubkey_encrypt_data} @showfuncdesc{gnutls_privkey_sign_data} diff --git a/lib/abstract_int.h b/lib/abstract_int.h index ca2be2b853..429d27e50f 100644 --- a/lib/abstract_int.h +++ b/lib/abstract_int.h @@ -36,10 +36,12 @@ int _gnutls_pubkey_get_mpis (gnutls_pubkey_t key, gnutls_pk_params_st * params); -int pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk, - const gnutls_datum_t * hash, - const gnutls_datum_t * signature, - gnutls_pk_params_st * issuer_params); +int +pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk, + gnutls_digest_algorithm_t hash_algo, + const gnutls_datum_t * hash, + const gnutls_datum_t * signature, + gnutls_pk_params_st * issuer_params); int pubkey_verify_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t algo, diff --git a/lib/algorithms.h b/lib/algorithms.h index e2600c605a..9fe0272541 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -106,8 +106,6 @@ enum encipher_type _gnutls_kx_encipher_type (gnutls_kx_algorithm_t algorithm); /* Functions for sign algorithms. */ gnutls_sign_algorithm_t _gnutls_x509_oid2sign_algorithm (const char *oid); -gnutls_sign_algorithm_t _gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, - gnutls_digest_algorithm_t mac); gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk (gnutls_sign_algorithm_t sign); const char *_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t, gnutls_digest_algorithm_t mac); diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c index ab81b830d3..d0cbfacb22 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -178,12 +178,22 @@ _gnutls_x509_oid2sign_algorithm (const char *oid) return ret; } +/** + * gnutls_pk_to_sign: + * @pk: is a public key algorithm + * @hash: a hash algorithm + * + * This function maps public key and hash algorithms combinations + * to signature algorithms. + * + * Returns: return a #gnutls_sign_algorithm_t value, or %GNUTLS_SIGN_UNKNOWN on error. + **/ gnutls_sign_algorithm_t -_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t mac) +gnutls_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash) { gnutls_sign_algorithm_t ret = 0; - GNUTLS_SIGN_LOOP (if (pk == p->pk && mac == p->mac) + GNUTLS_SIGN_LOOP (if (pk == p->pk && hash == p->mac) { ret = p->id; break;} ); @@ -200,7 +210,7 @@ _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk, gnutls_sign_algorithm_t sign; const char *ret = NULL; - sign = _gnutls_x509_pk_to_sign (pk, mac); + sign = gnutls_pk_to_sign (pk, mac); if (sign == GNUTLS_SIGN_UNKNOWN) return NULL; diff --git a/lib/ext/signature.c b/lib/ext/signature.c index 4fe9795d8e..1da555e992 100644 --- a/lib/ext/signature.c +++ b/lib/ext/signature.c @@ -264,7 +264,7 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert) || priv->sign_algorithms_size == 0) /* none set, allow SHA-1 only */ { - return _gnutls_x509_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1); + return gnutls_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1); } for (i = 0; i < priv->sign_algorithms_size; i++) diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index 6496537ca7..39246f7748 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -1373,7 +1373,6 @@ gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey, return ret; } - /** * gnutls_pubkey_verify_hash: * @key: Holds the public key @@ -1382,7 +1381,8 @@ gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey, * @signature: contains the signature * * This function will verify the given signed digest, using the - * parameters from the public key. + * parameters from the public key. Use gnutls_pubkey_verify_hash2() + * instead of this function. * * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED * is returned, and zero or positive code on success. @@ -1394,6 +1394,41 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature) { +gnutls_digest_algorithm_t algo; +int ret; + + ret = gnutls_pubkey_get_verify_algorithm (key, signature, &algo); + if (ret < 0) + return gnutls_assert_val(ret); + + return gnutls_pubkey_verify_hash2(key, gnutls_pk_to_sign(key->pk_algorithm, algo), + flags, hash, signature); +} + + +/** + * gnutls_pubkey_verify_hash: + * @key: Holds the public key + * @algo: The signature algorithm used + * @flags: should be 0 for now + * @hash: holds the hash digest to be verified + * @signature: contains the signature + * + * This function will verify the given signed digest, using the + * parameters from the public key. + * + * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED + * is returned, and zero or positive code on success. + * + * Since: 3.0 + **/ +int +gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key, + gnutls_sign_algorithm_t algo, + unsigned int flags, + const gnutls_datum_t * hash, + const gnutls_datum_t * signature) +{ if (key == NULL) { gnutls_assert (); @@ -1404,8 +1439,8 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags, return _gnutls_rsa_verify (hash, signature, &key->params, 1); else { - return pubkey_verify_hashed_data (key->pk_algorithm, hash, signature, - &key->params); + return pubkey_verify_hashed_data (key->pk_algorithm, _gnutls_sign_get_hash_algorithm(algo), + hash, signature, &key->params); } } @@ -1535,7 +1570,8 @@ _gnutls_pubkey_get_mpis (gnutls_pubkey_t key, * params[1] is public key */ static int -_pkcs1_rsa_verify_sig (const gnutls_datum_t * text, +_pkcs1_rsa_verify_sig (gnutls_digest_algorithm_t hash_algo, + const gnutls_datum_t * text, const gnutls_datum_t * prehash, const gnutls_datum_t * signature, gnutls_pk_params_st * params) @@ -1569,6 +1605,9 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, _gnutls_free_datum (&decrypted); + if (hash_algo != GNUTLS_DIG_UNKNOWN && hash_algo != hash) + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + if (digest_size != _gnutls_hash_get_algo_len (hash)) { gnutls_assert (); @@ -1672,9 +1711,10 @@ dsa_verify_data (gnutls_pk_algorithm_t pk, */ int pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk, - const gnutls_datum_t * hash, - const gnutls_datum_t * signature, - gnutls_pk_params_st * issuer_params) + gnutls_digest_algorithm_t hash_algo, + const gnutls_datum_t * hash, + const gnutls_datum_t * signature, + gnutls_pk_params_st * issuer_params) { switch (pk) @@ -1682,7 +1722,7 @@ pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk, case GNUTLS_PK_RSA: if (_pkcs1_rsa_verify_sig - (NULL, hash, signature, issuer_params) != 0) + (hash_algo, NULL, hash, signature, issuer_params) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; @@ -1724,7 +1764,7 @@ pubkey_verify_data (gnutls_pk_algorithm_t pk, case GNUTLS_PK_RSA: if (_pkcs1_rsa_verify_sig - (data, NULL, signature, issuer_params) != 0) + (algo, data, NULL, signature, issuer_params) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 051fe854f6..b30dcc3308 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -272,6 +272,7 @@ static int verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert, const gnutls_datum_t * hash_concat, gnutls_datum_t * signature, size_t sha1pos, + gnutls_sign_algorithm_t sign_algo, gnutls_pk_algorithm_t pk_algo) { int ret; @@ -326,8 +327,8 @@ verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert, return GNUTLS_E_INTERNAL_ERROR; } - ret = gnutls_pubkey_verify_hash(cert->pubkey, flags, &vdata, - signature); + ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags, + &vdata, signature); if (ret < 0) return gnutls_assert_val(ret); @@ -344,7 +345,7 @@ int _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert, const gnutls_datum_t * params, gnutls_datum_t * signature, - gnutls_sign_algorithm_t algo) + gnutls_sign_algorithm_t sign_algo) { gnutls_datum_t dconcat; int ret; @@ -357,17 +358,17 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert, if (_gnutls_version_has_selectable_sighash (ver)) { _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n", - session, gnutls_sign_algorithm_get_name (algo)); + session, gnutls_sign_algorithm_get_name (sign_algo)); - ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, algo); + ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, sign_algo); if (ret < 0) return gnutls_assert_val(ret); - ret = _gnutls_session_sign_algo_enabled (session, algo); + ret = _gnutls_session_sign_algo_enabled (session, sign_algo); if (ret < 0) return gnutls_assert_val(ret); - hash_algo = _gnutls_sign_get_hash_algorithm (algo); + hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo); } else { @@ -420,7 +421,8 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert, ret = verify_tls_hash (ver, cert, &dconcat, signature, dconcat.size - _gnutls_hash_get_algo_len (hash_algo), - _gnutls_sign_get_pk_algorithm (algo)); + sign_algo, + _gnutls_sign_get_pk_algorithm (sign_algo)); if (ret < 0) { gnutls_assert (); @@ -465,7 +467,7 @@ _gnutls_handshake_verify_crt_vrfy12 (gnutls_session_t session, dconcat.size = _gnutls_hash_get_algo_len (hash_algo); ret = - verify_tls_hash (ver, cert, &dconcat, signature, 0, pk); + verify_tls_hash (ver, cert, &dconcat, signature, 0, sign_algo, pk); if (ret < 0) { gnutls_assert (); @@ -560,6 +562,7 @@ _gnutls_handshake_verify_crt_vrfy (gnutls_session_t session, ret = verify_tls_hash (ver, cert, &dconcat, signature, 16, + GNUTLS_SIGN_UNKNOWN, gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL)); if (ret < 0) { diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index b89da86c30..50c1ecac35 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -140,6 +140,14 @@ int gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature); + +int +gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key, + gnutls_sign_algorithm_t algo, + unsigned int flags, + const gnutls_datum_t * hash, + const gnutls_datum_t * signature); + int gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key, const gnutls_datum_t * signature, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 035f63857a..5eff94ab66 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -791,6 +791,9 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); type); const char *gnutls_pk_get_name (gnutls_pk_algorithm_t algorithm); const char *gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm); + gnutls_sign_algorithm_t gnutls_pk_to_sign (gnutls_pk_algorithm_t pk, + gnutls_digest_algorithm_t d); + #define gnutls_sign_algorithm_get_name gnutls_sign_get_name gnutls_mac_algorithm_t gnutls_mac_get_id (const char *name); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 31938482ed..33df09be8d 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -786,6 +786,8 @@ GNUTLS_3_0_0 { gnutls_x509_crt_set_private_key_usage_period; gnutls_x509_crq_set_private_key_usage_period; gnutls_session_get_random; + gnutls_pubkey_verify_hash2; + gnutls_pk_to_sign; } GNUTLS_2_12; GNUTLS_PRIVATE { diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 4a133d451e..23bdcf72c5 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -788,39 +788,6 @@ _gnutls_x509_verify_data (gnutls_digest_algorithm_t algo, return ret; } -int -_gnutls_x509_verify_hashed_data (const gnutls_datum_t * hash, - const gnutls_datum_t * signature, - gnutls_x509_crt_t issuer) -{ - gnutls_pk_params_st issuer_params; - int ret; - - /* Read the MPI parameters from the issuer's certificate. - */ - ret = - _gnutls_x509_crt_get_mpis (issuer, &issuer_params); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = - pubkey_verify_hashed_data (gnutls_x509_crt_get_pk_algorithm (issuer, NULL), - hash, signature, &issuer_params); - if (ret < 0) - { - gnutls_assert (); - } - - /* release all allocated MPIs - */ - gnutls_pk_params_release(&issuer_params); - - return ret; -} - /** * gnutls_x509_crt_list_verify: * @cert_list: is the certificate list to be verified diff --git a/lib/x509/x509.c b/lib/x509/x509.c index d0de3cb97f..643f316f99 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -2693,7 +2693,7 @@ gnutls_x509_crt_verify_data (gnutls_x509_crt_t crt, unsigned int flags, * This function will verify the given signed digest, using the * parameters from the certificate. * - * Deprecated. Please use gnutls_pubkey_verify_data(). + * Deprecated. Please use gnutls_pubkey_verify_data2() or gnutls_pubkey_verify_hash2(). * * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED * is returned, and zero or positive code on success. @@ -2703,7 +2703,9 @@ gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature) { - int result; + gnutls_pk_params_st params; + gnutls_digest_algorithm_t algo; + int ret; if (crt == NULL) { @@ -2711,14 +2713,33 @@ gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, unsigned int flags, return GNUTLS_E_INVALID_REQUEST; } - result = _gnutls_x509_verify_hashed_data (hash, signature, crt); - if (result < 0) + ret = gnutls_x509_crt_get_verify_algorithm (crt, signature, &algo); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Read the MPI parameters from the issuer's certificate. + */ + ret = + _gnutls_x509_crt_get_mpis (crt, ¶ms); + if (ret < 0) { gnutls_assert (); - return result; + return ret; } - return result; + ret = + pubkey_verify_hashed_data (gnutls_x509_crt_get_pk_algorithm (crt, NULL), algo, + hash, signature, ¶ms); + if (ret < 0) + { + gnutls_assert (); + } + + /* release all allocated MPIs + */ + gnutls_pk_params_release(¶ms); + + return ret; } /** diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 19c2c1238b..3cc18e4bb0 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -151,10 +151,6 @@ int _gnutls_x509_verify_data (gnutls_digest_algorithm_t algo, const gnutls_datum_t * signature, gnutls_x509_crt_t issuer); -int _gnutls_x509_verify_hashed_data (const gnutls_datum_t * hash, - const gnutls_datum_t * signature, - gnutls_x509_crt_t issuer); - /* privkey.h */ ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key, diff --git a/tests/x509sign-verify.c b/tests/x509sign-verify.c index 9ac6b5d466..7e0727cf1f 100644 --- a/tests/x509sign-verify.c +++ b/tests/x509sign-verify.c @@ -40,6 +40,12 @@ #include "utils.h" +static void +tls_log_func (int level, const char *str) +{ + fprintf (stderr, "<%d> %s", level, str); +} + /* sha1 hash of "hello" string */ const gnutls_datum_t hash_data = { (void *) @@ -147,6 +153,7 @@ doit (void) gnutls_pubkey_t pubkey; gnutls_privkey_t privkey; gnutls_digest_algorithm_t hash_algo; + gnutls_sign_algorithm_t sign_algo; gnutls_datum_t signature; gnutls_datum_t signature2; int ret; @@ -154,6 +161,10 @@ doit (void) gnutls_global_init (); + gnutls_global_set_log_function (tls_log_func); + if (debug) + gnutls_global_set_log_level (6); + for (i = 0; i < sizeof (key_dat) / sizeof (key_dat[0]); i++) { if (debug) @@ -210,7 +221,7 @@ doit (void) ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature); if (ret < 0) - fail ("gnutls_x509_privkey_verify_hash\n"); + fail ("gnutls_x509_pubkey_verify_hash\n"); ret = gnutls_pubkey_get_verify_algorithm (pubkey, &signature2, &hash_algo); @@ -219,12 +230,24 @@ doit (void) ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature2); if (ret < 0) - fail ("gnutls_x509_privkey_verify_hash (hashed data)\n"); + fail ("gnutls_x509_pubkey_verify_hash-1 (hashed data)\n"); /* should fail */ ret = gnutls_pubkey_verify_hash (pubkey, 0, &invalid_hash_data, &signature2); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) - fail ("gnutls_x509_privkey_verify_hash (hashed data)\n"); + fail ("gnutls_x509_pubkey_verify_hash-2 (hashed data)\n"); + + sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm(pubkey, NULL), + GNUTLS_DIG_SHA1); + + ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &hash_data, &signature2); + if (ret < 0) + fail ("gnutls_x509_pubkey_verify_hash2-1 (hashed data)\n"); + + /* should fail */ + ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &invalid_hash_data, &signature2); + if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) + fail ("gnutls_x509_pubkey_verify_hash2-2 (hashed data)\n"); gnutls_free(signature.data); |