diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-04-06 10:54:17 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-04-06 10:54:17 +0000 |
commit | 9c5dff71d17ae3dc85d8fc9e9e1a7b165e9a5db3 (patch) | |
tree | 5392895395e9bd1212126851b431ad361d5738b6 | |
parent | 47bfe61d3f583c238ce4b3211afc032f5203591b (diff) | |
download | gnutls-9c5dff71d17ae3dc85d8fc9e9e1a7b165e9a5db3.tar.gz |
(gnutls_x509_crt_get_key_id): Don't fail on non-RSA/DSA public keys.
-rw-r--r-- | lib/x509/x509.c | 147 |
1 files changed, 98 insertions, 49 deletions
diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 9b8f244cb4..956dbfb8e3 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -1954,61 +1954,18 @@ gnutls_x509_crt_export (gnutls_x509_crt_t cert, } -/** - * gnutls_x509_crt_get_key_id - Return unique ID of public key's parameters - * @crt: Holds the certificate - * @flags: should be 0 for now - * @output_data: will contain the key ID - * @output_data_size: holds the size of output_data (and will be - * replaced by the actual size of parameters) - * - * This function will return a unique ID the depends on the public key - * parameters. This ID can be used in checking whether a certificate - * corresponds to the given private key. - * - * If the buffer provided is not long enough to hold the output, then - * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will - * be returned. The output will normally be a SHA-1 hash output, - * which is 20 bytes. - * - * Return value: In case of failure a negative value will be - * returned, and 0 on success. - * - **/ -int -gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, unsigned int flags, - unsigned char *output_data, - size_t * output_data_size) +static int +rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk, + unsigned char *output_data, + size_t * output_data_size) { mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; int params_size = MAX_PUBLIC_PARAMS_SIZE; - int i, pk, result = 0; + int i, result = 0; gnutls_datum_t der = { NULL, 0 }; GNUTLS_HASH_HANDLE hd; - if (crt == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - if (*output_data_size < 20) - { - gnutls_assert (); - *output_data_size = 20; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL); - - if (pk < 0) - { - gnutls_assert (); - return pk; - } - result = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); - if (result < 0) { gnutls_assert (); @@ -2051,7 +2008,7 @@ gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, unsigned int flags, result = 0; -cleanup: + cleanup: _gnutls_free_datum (&der); @@ -2064,6 +2021,98 @@ cleanup: return result; } +/** + * gnutls_x509_crt_get_key_id - Return unique ID of public key's parameters + * @crt: Holds the certificate + * @flags: should be 0 for now + * @output_data: will contain the key ID + * @output_data_size: holds the size of output_data (and will be + * replaced by the actual size of parameters) + * + * This function will return a unique ID the depends on the public + * key parameters. This ID can be used in checking whether a + * certificate corresponds to the given private key. + * + * If the buffer provided is not long enough to hold the output, then + * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will + * be returned. The output will normally be a SHA-1 hash output, + * which is 20 bytes. + * + * Return value: In case of failure a negative value will be + * returned, and 0 on success. + * + **/ +int +gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, unsigned int flags, + unsigned char *output_data, + size_t * output_data_size) +{ + int pk, result = 0; + gnutls_datum_t pubkey; + + if (crt == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + if (*output_data_size < 20) + { + gnutls_assert (); + *output_data_size = 20; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL); + if (pk < 0) + { + gnutls_assert (); + return pk; + } + + if (pk == GNUTLS_PK_RSA || pk == GNUTLS_PK_DSA) + { + /* This is for compatibility with what GnuTLS has printed for + RSA/DSA before the code below was added. The code below is + applicable to all types, and it would probably be a better + idea to use it for RSA/DSA too, but doing so would break + backwards compatibility. */ + return rsadsa_get_key_id (crt, pk, output_data, output_data_size); + } + + pubkey.size = 0; + result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo", + NULL, &pubkey.size, NULL); + if (result != ASN1_MEM_ERROR) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + pubkey.data = gnutls_alloca (pubkey.size); + if (pubkey.data == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo", + pubkey.data, &pubkey.size, NULL); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + gnutls_afree (pubkey.data); + return _gnutls_asn2err (result); + } + + result = gnutls_fingerprint (GNUTLS_DIG_SHA1, &pubkey, + output_data, output_data_size); + + gnutls_afree (pubkey.data); + + return result; +} + #ifdef ENABLE_PKI |