diff --git a/legacy/eet/configure.ac b/legacy/eet/configure.ac index bc4a35d0f8..65d6e149c3 100644 --- a/legacy/eet/configure.ac +++ b/legacy/eet/configure.ac @@ -75,6 +75,25 @@ AC_ARG_ENABLE([gnutls], AC_MSG_CHECKING([whether to use Gnutls]) AC_MSG_RESULT([${want_gnutls}]) +# Specific GNUTLS improvement + +new_gnutls_api="no" +AC_ARG_ENABLE(new-gnutls-api, + [AC_HELP_STRING( + [--enable-new-gnutls-api], + [enable use of gnutls_x509_crt_verify_hash. [[default=disable]]] + )], + [new_gnutls_api=$enableval] +) +AC_MSG_CHECKING([whether to use gnutls_x509_crt_verify_hash]) +AC_MSG_RESULT([${new_gnutls_api}]) + +if test "x${new_gnutls_api}" = "xyes" ; then + AC_DEFINE(EET_USE_NEW_GNUTLS_API, 1, [use gnutls_x509_crt_verify_hash]) +else + AC_DEFINE(EET_USE_NEW_GNUTLS_API, 0, [don't use gnutls_x509_crt_verify_hash]) +fi + # Openssl support AC_ARG_ENABLE([openssl], diff --git a/legacy/eet/src/lib/Eet_private.h b/legacy/eet/src/lib/Eet_private.h index c05f203928..46d34367ce 100644 --- a/legacy/eet/src/lib/Eet_private.h +++ b/legacy/eet/src/lib/Eet_private.h @@ -69,6 +69,7 @@ int eet_dictionary_string_get_hash(const Eet_Dictionary *ed, int in int _eet_hash_gen(const char *key, int hash_size); const void* eet_identity_check(const void *data_base, unsigned int data_length, + void **sha1, int *sha1_length, const void *signature_base, unsigned int signature_length, const void **raw_signature_base, unsigned int *raw_signature_length, int *x509_length); diff --git a/legacy/eet/src/lib/eet_cipher.c b/legacy/eet/src/lib/eet_cipher.c index a12056606d..1e1aba2420 100644 --- a/legacy/eet/src/lib/eet_cipher.c +++ b/legacy/eet/src/lib/eet_cipher.c @@ -504,6 +504,7 @@ eet_identity_sign(FILE *fp, Eet_Key *key) const void* eet_identity_check(const void *data_base, unsigned int data_length, + void **sha1, int *sha1_length, const void *signature_base, unsigned int signature_length, const void **raw_signature_base, unsigned int *raw_signature_length, int *x509_length) @@ -534,8 +535,11 @@ eet_identity_check(const void *data_base, unsigned int data_length, # ifdef HAVE_GNUTLS gnutls_x509_crt_t cert; + gcry_md_hd_t md; gnutls_datum_t datum; gnutls_datum_t signature; + unsigned char *hash; + int err; /* Create an understanding certificate structure for gnutls */ datum.data = (void *)cert_der; @@ -547,10 +551,60 @@ eet_identity_check(const void *data_base, unsigned int data_length, signature.size = sign_len; /* Verify the signature */ +# if EET_USE_NEW_GNUTLS_API + /* + I am waiting for my patch being accepted in GnuTLS release. + But we now have a way to prevent double computation of SHA1. + */ + err = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (err < 0) return NULL; + + gcry_md_write(md, data_base, data_length); + + hash = gcry_md_read(md, GCRY_MD_SHA1); + if (hash == NULL) + { + gcry_md_close(md); + return NULL; + } + + datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + datum.data = hash; + + if (!gnutls_x509_crt_verify_hash(cert, 0, &datum, &signature)) + { + gcry_md_close(md); + return NULL; + } + + if (sha1) + { + *sha1 = malloc(datum.size); + if (!*sha1) + { + gcry_md_close(md); + return NULL; + } + + memcpy(*sha1, hash, datum.size); + *sha1_length = datum.size; + } + + gcry_md_close(md); +# else datum.data = (void *)data_base; datum.size = data_length; + if (!gnutls_x509_crt_verify_data(cert, 0, &datum, &signature)) return NULL; + + if (sha1) + { + *sha1 = NULL; + *sha1_length = -1; + } +# endif + # else const unsigned char *tmp; EVP_PKEY *pkey; @@ -580,6 +634,12 @@ eet_identity_check(const void *data_base, unsigned int data_length, X509_free(x509); EVP_PKEY_free(pkey); + if (sha1) + { + *sha1 = NULL; + *sha1_length = -1; + } + if (err != 1) return NULL; # endif diff --git a/legacy/eet/src/lib/eet_lib.c b/legacy/eet/src/lib/eet_lib.c index af5f62dd23..0026172964 100644 --- a/legacy/eet/src/lib/eet_lib.c +++ b/legacy/eet/src/lib/eet_lib.c @@ -1049,6 +1049,7 @@ eet_internal_read2(Eet_File *ef) #ifdef HAVE_SIGNATURE const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset; ef->x509_der = eet_identity_check(ef->data, signature_base_offset, + &ef->sha1, &ef->sha1_length, buffer, ef->data_size - signature_base_offset, &ef->signature, &ef->signature_length, &ef->x509_length); @@ -1567,6 +1568,7 @@ eet_close(Eet_File *ef) eet_dictionary_free(ef->ed); + if (ef->sha1) free(ef->sha1); if (ef->data) munmap((void*)ef->data, ef->data_size); if (ef->fp) fclose(ef->fp); if (ef->readfp) fclose(ef->readfp);