summaryrefslogtreecommitdiff
path: root/lib/x509/key_decode.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-22 11:55:33 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-22 13:37:59 +0200
commitf099342688710138ba8cd94e47846bda5c331faf (patch)
tree5782228c5fa01060673e3273c583e22b70b25202 /lib/x509/key_decode.c
parent8dcf7e8299fed143c2e61500da55b5e5910eb54c (diff)
downloadgnutls-f099342688710138ba8cd94e47846bda5c331faf.tar.gz
gnutls_pk_params_st is used internally to transfer public key parameters. This replaces the raw bigint_t arrays.
Diffstat (limited to 'lib/x509/key_decode.c')
-rw-r--r--lib/x509/key_decode.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c
new file mode 100644
index 0000000000..e2b56b538b
--- /dev/null
+++ b/lib/x509/key_decode.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_global.h>
+#include <libtasn1.h>
+#include <gnutls_datum.h>
+#include "common.h"
+#include "x509_int.h"
+#include <gnutls_num.h>
+#include <gnutls_ecc.h>
+
+static int _gnutls_x509_read_rsa_pubkey (opaque * der, int dersize,
+ gnutls_pk_params_st* params);
+static int _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize,
+ gnutls_pk_params_st * params);
+static int _gnutls_x509_read_ecc_pubkey (opaque * der, int dersize,
+ gnutls_pk_params_st * params);
+
+static int
+_gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * params);
+
+static int
+_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * params);
+
+/*
+ * some x509 certificate parsing functions that relate to MPI parameter
+ * extraction. This reads the BIT STRING subjectPublicKey.
+ * Returns 2 parameters (m,e). It does not set params_nr.
+ */
+int
+_gnutls_x509_read_rsa_pubkey (opaque * der, int dersize, gnutls_pk_params_st * params)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ if ((result = asn1_create_element
+ (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
+ != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ result = asn1_der_decoding (&spk, der, dersize, NULL);
+
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ return _gnutls_asn2err (result);
+ }
+
+
+ if ((result = _gnutls_x509_read_int (spk, "modulus", &params->params[0])) < 0)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ if ((result = _gnutls_x509_read_int (spk, "publicExponent",
+ &params->params[1])) < 0)
+ {
+ gnutls_assert ();
+ _gnutls_mpi_release (&params->params[0]);
+ asn1_delete_structure (&spk);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ asn1_delete_structure (&spk);
+
+ return 0;
+
+}
+
+/*
+ * some x509 certificate parsing functions that relate to MPI parameter
+ * extraction. This reads the BIT STRING subjectPublicKey.
+ * Returns 2 parameters (m,e). It does not set params_nr.
+ */
+int
+_gnutls_x509_read_ecc_pubkey (opaque * der, int dersize, gnutls_pk_params_st * params)
+{
+ uint8_t* octet;
+ int ret;
+ size_t octet_size = dersize;
+
+ octet = gnutls_malloc(octet_size);
+ if (octet == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ ret = _gnutls_x509_decode_octet_string (NULL, der, dersize, octet, &octet_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_ecc_ansi_x963_import (octet, octet_size, &params->params[5],
+ &params->params[6]);
+ gnutls_free(octet);
+
+ return ret;
+}
+
+
+/* reads p,q and g
+ * from the certificate (subjectPublicKey BIT STRING).
+ * params[0-2]. It does NOT set params_nr.
+ */
+static int
+_gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * params)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ if ((result = asn1_create_element
+ (_gnutls_get_pkix (), "PKIX1.Dss-Parms", &spk)) != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ result = asn1_der_decoding (&spk, der, dersize, NULL);
+
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ return _gnutls_asn2err (result);
+ }
+
+ /* FIXME: If the parameters are not included in the certificate
+ * then the issuer's parameters should be used. This is not
+ * done yet.
+ */
+
+ /* Read p */
+
+ if ((result = _gnutls_x509_read_int (spk, "p", &params->params[0])) < 0)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ /* Read q */
+
+ if ((result = _gnutls_x509_read_int (spk, "q", &params->params[1])) < 0)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ _gnutls_mpi_release (&params->params[0]);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ /* Read g */
+
+ if ((result = _gnutls_x509_read_int (spk, "g", &params->params[2])) < 0)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&spk);
+ _gnutls_mpi_release (&params->params[0]);
+ _gnutls_mpi_release (&params->params[1]);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ asn1_delete_structure (&spk);
+
+ return 0;
+
+}
+
+/* reads the curve from the certificate.
+ * params[0-4]. It does NOT set params_nr.
+ */
+static int
+_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * params)
+{
+ int ret;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+ char oid[MAX_OID_SIZE];
+ unsigned int oid_size;
+
+ if ((ret = asn1_create_element
+ (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk)) != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (ret);
+ }
+
+ ret = asn1_der_decoding (&spk, der, dersize, NULL);
+
+ if (ret != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (ret);
+ goto cleanup;
+ }
+
+ /* Read curve */
+ /* read the curve */
+ oid_size = sizeof(oid);
+ ret = asn1_read_value(spk, "namedCurve", oid, &oid_size);
+ if (ret != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ ret = _gnutls_asn2err (ret);
+ goto cleanup;
+ }
+
+ params->flags = _gnutls_oid_to_ecc_curve(oid);
+ if (params->flags == GNUTLS_ECC_CURVE_INVALID)
+ {
+ _gnutls_debug_log("Curve %s is not supported\n", oid);
+ gnutls_assert();
+ ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
+ goto cleanup;
+ }
+
+ ret = _gnutls_ecc_curve_fill_params(params->flags, params);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+
+ asn1_delete_structure (&spk);
+
+ return ret;
+
+}
+
+int _gnutls_x509_read_pubkey (gnutls_pk_algorithm_t algo, opaque * der, int dersize,
+ gnutls_pk_params_st * params)
+{
+ switch(algo)
+ {
+ case GNUTLS_PK_RSA:
+ return _gnutls_x509_read_rsa_pubkey(der, dersize, params);
+ case GNUTLS_PK_DSA:
+ return _gnutls_x509_read_dsa_pubkey(der, dersize, params);
+ case GNUTLS_PK_ECC:
+ return _gnutls_x509_read_ecc_pubkey(der, dersize, params);
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+ }
+}
+
+int _gnutls_x509_read_pubkey_params (gnutls_pk_algorithm_t algo, opaque * der, int dersize,
+ gnutls_pk_params_st * params)
+{
+ switch(algo)
+ {
+ case GNUTLS_PK_RSA:
+ return 0;
+ case GNUTLS_PK_DSA:
+ return _gnutls_x509_read_dsa_params(der, dersize, params);
+ case GNUTLS_PK_ECC:
+ return _gnutls_x509_read_ecc_params(der, dersize, params);
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+ }
+}
+
+/* reads DSA's Y
+ * from the certificate
+ * only sets params[3]
+ */
+int
+_gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, gnutls_pk_params_st * params)
+{
+ /* do not set a number */
+ params->params_nr = 0;
+ return _gnutls_x509_read_der_int (der, dersize, &params->params[3]);
+}
+