summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2009-03-26 20:36:49 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2009-03-26 20:36:49 +0200
commitbda121ef22285edfd93f42669dcf09abd6424faa (patch)
treea76aef696f349da9dd9497a797de3b62a31cf16c /lib
parent975c2dd7745cb24d970e8101501c6aa7c7e532ee (diff)
downloadgnutls-bda121ef22285edfd93f42669dcf09abd6424faa.tar.gz
Applied patch by Cedric Bail to add functions gnutls_x509_crt_verify_hash() and gnutls_x509_crt_get_sig_algorithm().
Diffstat (limited to 'lib')
-rw-r--r--lib/includes/gnutls/x509.h8
-rw-r--r--lib/x509/verify.c136
-rw-r--r--lib/x509/x509.c64
-rw-r--r--lib/x509/x509_int.h4
4 files changed, 186 insertions, 26 deletions
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
@@ -2305,6 +2305,32 @@ gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
}
/**
+ * 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
* @flags: should be 0 for now
@@ -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,