summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2008-12-11 08:33:04 +0100
committerSimon Josefsson <simon@josefsson.org>2008-12-11 08:33:04 +0100
commite311252bf0dd32fb2ca52e327763ae856e54e3f7 (patch)
tree5f98439ab77ad684171cca7460c3add494938a44
parent894e7471ab51c30f67f379f9b80530b9a9d22b11 (diff)
downloadgnutls-e311252bf0dd32fb2ca52e327763ae856e54e3f7.tar.gz
gnutls: New interface to get key id for certificate requests.
Patch from David Marín Carreño <davefx@gmail.com> in <http://thread.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/3321>.
-rw-r--r--AUTHORS3
-rw-r--r--NEWS9
-rw-r--r--lib/includes/gnutls/x509.h3
-rw-r--r--lib/x509/crq.c159
4 files changed, 174 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index 456f4c6c60..539ef072bf 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -48,6 +48,9 @@ Certificate name import/export, build fixes, test vectors.
Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>
OpenPGP discussion and improvements.
+David Marín Carreño <davefx@gmail.com>
+Added gnutls_x509_crq_get_key_id.
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
URL: http://josefsson.org/key.txt (always latest version)
Comment: This 0xB565716F key is used to sign releases of GnuTLS.
diff --git a/NEWS b/NEWS
index 0e14919c24..0c317d8ab3 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,15 @@ Copyright (C) 2004, 2005, 2006, 2007, 2008 Simon Josefsson
Copyright (C) 2000, 2001, 2002, 2003, 2004 Nikos Mavrogiannopoulos
See the end for copying conditions.
+* Version 2.7.4 (unreleased)
+
+** gnutls: New interface to get key id for certificate requests.
+Patch from David Marín Carreño <davefx@gmail.com> in
+<http://thread.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/3321>.
+
+** API and ABI modifications:
+gnutls_x509_crq_get_key_id: ADDED.
+
* Version 2.7.3 (released 2008-12-10)
** gnutls: Fix chain verification for chains that ends with RSA-MD2 CAs.
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 63da3201cb..00c62a609b 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -738,6 +738,9 @@ extern "C"
int gnutls_x509_crq_get_pk_algorithm (gnutls_x509_crq_t crq,
unsigned int *bits);
+ int gnutls_x509_crq_get_key_id (gnutls_x509_crq_t crq, unsigned int flags,
+ unsigned char *output_data,
+ size_t * output_data_size);
int gnutls_x509_crq_get_key_rsa_raw (gnutls_x509_crq_t crq,
gnutls_datum_t * m,
gnutls_datum_t * e);
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index a6cfa3e57a..b5cb7911ad 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -2234,4 +2234,163 @@ gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t cert,
return 0;
}
+static int
+rsadsa_crq_get_key_id (gnutls_x509_crq_t crq, int pk,
+ unsigned char *output_data, size_t * output_data_size)
+{
+ bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
+ int params_size = MAX_PUBLIC_PARAMS_SIZE;
+ int i, result = 0;
+ gnutls_datum_t der = { NULL, 0 };
+ digest_hd_st hd;
+
+ result = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ if (pk == GNUTLS_PK_RSA)
+ {
+ result = _gnutls_x509_write_rsa_params (params, params_size, &der);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+ }
+ else if (pk == GNUTLS_PK_DSA)
+ {
+ result = _gnutls_x509_write_dsa_public_key (params, params_size, &der);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+ }
+ else
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+
+ _gnutls_hash (&hd, der.data, der.size);
+
+ _gnutls_hash_deinit (&hd, output_data);
+ *output_data_size = 20;
+
+ result = 0;
+
+cleanup:
+
+ _gnutls_free_datum (&der);
+
+ /* release all allocated MPIs
+ */
+ for (i = 0; i < params_size; i++)
+ {
+ _gnutls_mpi_release (&params[i]);
+ }
+ return result;
+}
+
+/**
+ * gnutls_x509_crq_get_key_id - Return unique ID of public key's parameters
+ * @crq: Holds the certificate signing request
+ * @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.
+ *
+ * Since: 2.8.0
+ **/
+int
+gnutls_x509_crq_get_key_id (gnutls_x509_crq_t crq, unsigned int flags,
+ unsigned char *output_data,
+ size_t * output_data_size)
+{
+ int pk, result = 0;
+ gnutls_datum_t pubkey;
+
+ if (crq == 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_crq_get_pk_algorithm (crq, 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_crq_get_key_id (crq, pk, output_data, output_data_size);
+ }
+
+ pubkey.size = 0;
+ result = asn1_der_coding (crq->crq, "certificationRequestInfo.subjectPKInfo",
+ NULL, &pubkey.size, NULL);
+ if (result != ASN1_MEM_ERROR)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ pubkey.data = gnutls_malloc (pubkey.size);
+ if (pubkey.data == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ result = asn1_der_coding (crq->crq, "certificationRequestInfo.subjectPKInfo",
+ pubkey.data, &pubkey.size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ gnutls_free (pubkey.data);
+ return _gnutls_asn2err (result);
+ }
+
+ result = gnutls_fingerprint (GNUTLS_DIG_SHA1, &pubkey,
+ output_data, output_data_size);
+
+ gnutls_free (pubkey.data);
+
+ return result;
+}
+
+
#endif /* ENABLE_PKI */