From bda121ef22285edfd93f42669dcf09abd6424faa Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 26 Mar 2009 20:36:49 +0200 Subject: Applied patch by Cedric Bail to add functions gnutls_x509_crt_verify_hash() and gnutls_x509_crt_get_sig_algorithm(). --- lib/includes/gnutls/x509.h | 8 +++ lib/x509/verify.c | 136 ++++++++++++++++++++++++++++++++++++--------- lib/x509/x509.c | 64 ++++++++++++++++++++- lib/x509/x509_int.h | 4 ++ 4 files changed, 186 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 00c62a609b..46038474df 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -641,6 +641,14 @@ 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_crt_get_sig_algorithm(gnutls_digest_algorithm_t *hash, + const gnutls_x509_crt_t crt, + const gnutls_datum_t * signature); int gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key, const gnutls_datum_t * hash, diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 4b1252e85d..3a1b1f00c4 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -332,7 +332,7 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, } ret = - _gnutls_x509_verify_signature (&cert_signed_data, &cert_signature, + _gnutls_x509_verify_signature (&cert_signed_data, NULL, &cert_signature, issuer); if (ret < 0) { @@ -603,12 +603,13 @@ decode_ber_digest_info (const gnutls_datum_t * info, */ static int _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, + const gnutls_datum_t * prehash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN; int ret; - opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE]; + opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp; int digest_size; digest_hd_st hd; gnutls_datum_t decrypted; @@ -641,17 +642,32 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, return GNUTLS_E_ASN1_GENERIC_ERROR; } - ret = _gnutls_hash_init (&hd, hash); - if (ret < 0) + if (prehash && prehash->data && prehash->size == digest_size) { - gnutls_assert (); - return ret; + cmp = prehash->data; + } + else + { + if (!text) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = _gnutls_hash_init (&hd, hash); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + _gnutls_hash (&hd, text->data, text->size); + _gnutls_hash_deinit (&hd, md); + + cmp = &md; } - _gnutls_hash (&hd, text->data, text->size); - _gnutls_hash_deinit (&hd, md); - - if (memcmp (md, digest, digest_size) != 0) + if (memcmp (cmp, digest, digest_size) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; @@ -664,6 +680,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, */ static int dsa_verify_sig (const gnutls_datum_t * text, + const gnutls_datum_t * hash, const gnutls_datum_t * signature, bigint_t * params, int params_len) { @@ -672,18 +689,25 @@ dsa_verify_sig (const gnutls_datum_t * text, gnutls_datum_t digest; digest_hd_st hd; - ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1); - if (ret < 0) + if (hash && hash->data && hash->size == 20) { - gnutls_assert (); - return ret; + digest = *hash; + } + else + { + ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + _gnutls_hash (&hd, text->data, text->size); + _gnutls_hash_deinit (&hd, _digest); + + digest.data = _digest; + digest.size = 20; } - - _gnutls_hash (&hd, text->data, text->size); - _gnutls_hash_deinit (&hd, _digest); - - digest.data = _digest; - digest.size = 20; ret = _gnutls_dsa_verify (&digest, signature, params, params_len); @@ -695,6 +719,7 @@ dsa_verify_sig (const gnutls_datum_t * text, */ static int verify_sig (const gnutls_datum_t * tbs, + const gnutls_datum_t * hash, const gnutls_datum_t * signature, gnutls_pk_algorithm_t pk, bigint_t * issuer_params, int issuer_params_size) @@ -705,7 +730,7 @@ verify_sig (const gnutls_datum_t * tbs, case GNUTLS_PK_RSA: if (_pkcs1_rsa_verify_sig - (tbs, signature, issuer_params, issuer_params_size) != 0) + (tbs, hash, signature, issuer_params, issuer_params_size) != 0) { gnutls_assert (); return 0; @@ -716,7 +741,7 @@ verify_sig (const gnutls_datum_t * tbs, case GNUTLS_PK_DSA: if (dsa_verify_sig - (tbs, signature, issuer_params, issuer_params_size) != 0) + (tbs, hash, signature, issuer_params, issuer_params_size) != 0) { gnutls_assert (); return 0; @@ -731,6 +756,66 @@ verify_sig (const gnutls_datum_t * tbs, } } +int +_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t *hash, + const gnutls_datum_t * signature, + const gnutls_x509_crt_t issuer) +{ + bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE]; + opaque digest[MAX_HASH_SIZE]; + gnutls_datum_t decrypted; + int issuer_params_size; + int digest_size; + int ret; + + switch (gnutls_x509_crt_get_pk_algorithm (issuer, NULL)) + { + case GNUTLS_PK_DSA: + if (hash) *hash = GNUTLS_MAC_SHA1; + return 0; + + case GNUTLS_PK_RSA: + issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; + ret = _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = + _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, + issuer_params, issuer_params_size, 1); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + digest_size = sizeof (digest); + if ((ret = + decode_ber_digest_info (&decrypted, hash, digest, &digest_size)) != 0) + { + gnutls_assert (); + _gnutls_free_datum (&decrypted); + return ret; + } + + _gnutls_free_datum (&decrypted); + if (digest_size != _gnutls_hash_get_algo_len (*hash)) + { + gnutls_assert (); + return GNUTLS_E_ASN1_GENERIC_ERROR; + } + + return 0; + + default: + gnutls_assert (); + return GNUTLS_E_INTERNAL_ERROR; + } +} + /* verifies if the certificate is properly signed. * returns 0 on failure and 1 on success. * @@ -739,6 +824,7 @@ verify_sig (const gnutls_datum_t * tbs, */ int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs, + const gnutls_datum_t * hash, const gnutls_datum_t * signature, gnutls_x509_crt_t issuer) { @@ -757,7 +843,7 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * tbs, } ret = - verify_sig (tbs, signature, + verify_sig (tbs, hash, signature, gnutls_x509_crt_get_pk_algorithm (issuer, NULL), issuer_params, issuer_params_size); if (ret < 0) @@ -788,7 +874,7 @@ _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs, { int ret; - ret = verify_sig (tbs, signature, issuer->pk_algorithm, + ret = verify_sig (tbs, NULL, signature, issuer->pk_algorithm, issuer->params, issuer->params_size); if (ret < 0) { @@ -1073,7 +1159,7 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl, } ret = - _gnutls_x509_verify_signature (&crl_signed_data, &crl_signature, issuer); + _gnutls_x509_verify_signature (&crl_signed_data, NULL, &crl_signature, issuer); if (ret < 0) { gnutls_assert (); diff --git a/lib/x509/x509.c b/lib/x509/x509.c index ca8cac5107..1c6206af61 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -2304,6 +2304,32 @@ gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert, return 0; /* not revoked. */ } +/** + * gnutls_x509_crt_get_sig_algorithm - This function will return the hash algorithm used during signature. + * @hash: The result of the call with the hash algorithm used for signature + * @crt: Holds the certificate + * @signature: contains the signature + * + * This function will read the certifcate and the signed data to + * determine the hash algorithm used to generate the signature. + * + * Returns: 0 if the hash algorithm was found. A negative value is + * returned on error. + **/ +int +gnutls_x509_crt_get_sig_algorithm(gnutls_digest_algorithm_t *hash, + const gnutls_x509_crt_t crt, + const gnutls_datum_t * signature) +{ + if (crt == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_verify_algorithm(hash, signature, crt); +} + /** * gnutls_x509_crt_verify_data - This function will verify the given signed data. * @crt: Holds the certificate @@ -2330,7 +2356,43 @@ gnutls_x509_crt_verify_data (gnutls_x509_crt_t crt, unsigned int flags, return GNUTLS_E_INVALID_REQUEST; } - result = _gnutls_x509_verify_signature (data, signature, crt); + result = _gnutls_x509_verify_signature (data, NULL, signature, crt); + if (result < 0) + { + gnutls_assert (); + return 0; + } + + return result; +} + +/** + * gnutls_x509_crt_verify_data - This function will verify the given signed data. + * @crt: Holds the certificate + * @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 certificate. + * + * Returns: In case of a verification failure 0 is returned, and 1 on + * success. + **/ +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 result; + + if (crt == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + result = _gnutls_x509_verify_signature (NULL, hash, signature, crt); if (result < 0) { gnutls_assert (); diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 2186e8c287..5a1497a4cd 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -184,7 +184,11 @@ int _gnutls_parse_general_name (ASN1_TYPE src, const char *src_name, /* verify.c */ int gnutls_x509_crt_is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer); +int _gnutls_x509_verify_algorithm(gnutls_mac_algorithm_t *hash, + const gnutls_datum_t * signature, + const gnutls_x509_crt_t crt); int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs, + const gnutls_datum_t * hash, const gnutls_datum_t * signature, gnutls_x509_crt_t issuer); int _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs, -- cgit v1.2.1