]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls: New interface to get key id for certificate requests.
authorSimon Josefsson <simon@josefsson.org>
Thu, 11 Dec 2008 07:33:04 +0000 (08:33 +0100)
committerSimon Josefsson <simon@josefsson.org>
Thu, 11 Dec 2008 07:33:04 +0000 (08:33 +0100)
Patch from David Marín Carreño <davefx@gmail.com> in
<http://thread.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/3321>.

AUTHORS
NEWS
lib/includes/gnutls/x509.h
lib/x509/crq.c

diff --git a/AUTHORS b/AUTHORS
index 456f4c6c60755fea03ac36828672eff4c906b25b..539ef072bf8795af38de2daa77594be8dac018be 100644 (file)
--- 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 0e14919c244ea7d61d9ea28bd32d673de3a62bde..0c317d8ab3c65224325d5f79d17d86bd2ea9220f 100644 (file)
--- 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.
index 63da3201cb9a5dc6dcdc5776be832e64de49c741..00c62a609b54f35e73f87166ec7696040b5b34f3 100644 (file)
@@ -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);
index a6cfa3e57a5433457675bd9224ad82ade6cdbc68..b5cb7911ad71a366a6523597d224cf55620c4f73 100644 (file)
@@ -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 */