From: Nikos Mavrogiannopoulos Date: Sun, 22 May 2011 13:59:58 +0000 (+0200) Subject: print information on ECC certificates. X-Git-Tag: gnutls_2_99_2~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80febddf239ff7209a4eaf184023f336fcdc5fde;p=thirdparty%2Fgnutls.git print information on ECC certificates. --- diff --git a/lib/algorithms/secparams.c b/lib/algorithms/secparams.c index 35969b3feb..09dd2401f4 100644 --- a/lib/algorithms/secparams.c +++ b/lib/algorithms/secparams.c @@ -83,14 +83,25 @@ gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo, ); return ret; } - - GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param) + else if (algo == GNUTLS_PK_ECC) + { + GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param) + { + ret = p->ecc_bits; break; + } + ); + return ret; + } + else + { + GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param) { ret = p->pk_bits; break; } - ); + ); - return ret; + return ret; + } } /* Returns the corresponding size for subgroup bits (q), @@ -149,13 +160,24 @@ gnutls_sec_param_get_name (gnutls_sec_param_t param) gnutls_sec_param_t gnutls_pk_bits_to_sec_param (gnutls_pk_algorithm_t algo, unsigned int bits) { - gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_WEAK; + gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_UNKNOWN; - GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits > bits) + if (algo == GNUTLS_PK_ECC) + { + GNUTLS_SEC_PARAM_LOOP (if (p->ecc_bits > bits) + { + break; + } + ret = p->sec_param;); + } + else + { + GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits > bits) { break; } ret = p->sec_param;); + } return ret; } diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index c6ad39abc8..c75f7f80a9 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -672,6 +672,59 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key, return 0; } +/** + * gnutls_pubkey_get_pk_ecc_raw: + * @key: Holds the public key + * @curve: will hold the curve + * @x: will hold x + * @y: will hold y + * + * This function will export the ECC public key's parameters found in + * the given certificate. The new parameters will be allocated using + * gnutls_malloc() and will be stored in the appropriate datum. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. + **/ +int +gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t *curve, + gnutls_datum_t * x, gnutls_datum_t * y) +{ + int ret; + + if (key == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + if (key->pk_algorithm != GNUTLS_PK_ECC) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + *curve = key->params.flags; + + /* X */ + ret = _gnutls_mpi_dprint (key->params.params[5], x); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + /* Y */ + ret = _gnutls_mpi_dprint (key->params.params[6], y); + if (ret < 0) + { + gnutls_assert (); + _gnutls_free_datum (x); + return ret; + } + + return 0; +} + /** * gnutls_pubkey_import: * @key: The structure to store the parsed public key. diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 3c6274fc21..ba097b0b69 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -40,6 +40,8 @@ int gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key, int gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g, gnutls_datum_t * y); +int gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t *curve, + gnutls_datum_t * x, gnutls_datum_t * y); int gnutls_pubkey_export (gnutls_pubkey_t key, gnutls_x509_crt_fmt_t format, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 1fe7dcfd9c..a26bb5b73f 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -715,6 +715,7 @@ GNUTLS_3_0_0 { gnutls_global_set_audit_log_function; gnutls_ecc_curve_get_name; gnutls_ecc_curve_get_size; + gnutls_pubkey_get_pk_ecc_raw; } GNUTLS_2_12; GNUTLS_PRIVATE { diff --git a/lib/x509/common.c b/lib/x509/common.c index 9bbfd387bc..3395834091 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -1259,7 +1259,6 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, unsigned int *bits) { int result; - opaque *str = NULL; int algo; char oid[64]; int len; @@ -1292,52 +1291,13 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, /* Now read the parameters' bits */ - _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey"); - - len = 0; - result = asn1_read_value (src, name, NULL, &len); - if (result != ASN1_MEM_ERROR) - { - gnutls_assert (); - return _gnutls_asn2err (result); - } - - if (len % 8 != 0) - { - gnutls_assert (); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - len /= 8; - - str = gnutls_malloc (len); - if (str == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey"); - - result = asn1_read_value (src, name, str, &len); - - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - gnutls_free (str); - return _gnutls_asn2err (result); - } - - len /= 8; - - result = _gnutls_x509_read_pubkey (algo, str, len, ¶ms); + result = _gnutls_get_asn_mpis(src, src_name, ¶ms); if (result < 0) return gnutls_assert_val(result); - + bits[0] = pubkey_to_bits(algo, ¶ms); gnutls_pk_params_release(¶ms); - gnutls_free (str); return algo; } diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c index e2b56b538b..d0bbce1b45 100644 --- a/lib/x509/key_decode.c +++ b/lib/x509/key_decode.c @@ -104,23 +104,43 @@ _gnutls_x509_read_rsa_pubkey (opaque * der, int dersize, gnutls_pk_params_st * p int _gnutls_x509_read_ecc_pubkey (opaque * der, int dersize, gnutls_pk_params_st * params) { - uint8_t* octet; +#if 0 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); + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + gnutls_datum_t octet; + + if ((ret = asn1_create_element + (_gnutls_get_gnutls_asn (), "GNUTLS.ECPoint", &spk)) + != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (ret); + } + + ret = asn1_der_decoding (&spk, der, dersize, NULL); + if (ret != ASN1_SUCCESS) + { + gnutls_assert (); + asn1_delete_structure (&spk); + return _gnutls_asn2err (ret); + } + + + if ((ret = _gnutls_x509_read_value (spk, "", &octet, 0)) < 0) + { + gnutls_assert (); + asn1_delete_structure (&spk); + return GNUTLS_E_ASN1_GENERIC_ERROR; + } - ret = _gnutls_ecc_ansi_x963_import (octet, octet_size, ¶ms->params[5], + ret = _gnutls_ecc_ansi_x963_import (octet.data, octet.size, ¶ms->params[5], ¶ms->params[6]); - gnutls_free(octet); + _gnutls_free_datum(&octet); return ret; +#endif + return _gnutls_ecc_ansi_x963_import (der, dersize, ¶ms->params[5], + ¶ms->params[6]); } @@ -237,7 +257,7 @@ _gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * p ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto cleanup; } - + ret = _gnutls_ecc_curve_fill_params(params->flags, params); if (ret < 0) { @@ -258,17 +278,27 @@ cleanup: int _gnutls_x509_read_pubkey (gnutls_pk_algorithm_t algo, opaque * der, int dersize, gnutls_pk_params_st * params) { +int ret; + switch(algo) { case GNUTLS_PK_RSA: - return _gnutls_x509_read_rsa_pubkey(der, dersize, params); + ret = _gnutls_x509_read_rsa_pubkey(der, dersize, params); + if (ret >= 0) params->params_nr = RSA_PUBLIC_PARAMS; + break; case GNUTLS_PK_DSA: - return _gnutls_x509_read_dsa_pubkey(der, dersize, params); + ret = _gnutls_x509_read_dsa_pubkey(der, dersize, params); + if (ret >= 0) params->params_nr = DSA_PUBLIC_PARAMS; + break; case GNUTLS_PK_ECC: - return _gnutls_x509_read_ecc_pubkey(der, dersize, params); + ret = _gnutls_x509_read_ecc_pubkey(der, dersize, params); + if (ret >= 0) params->params_nr = ECC_PUBLIC_PARAMS; + break; default: - return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); + ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); + break; } + return ret; } int _gnutls_x509_read_pubkey_params (gnutls_pk_algorithm_t algo, opaque * der, int dersize, diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index b57e7988a8..37a8386946 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -123,24 +123,27 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, _asnstr_append_name (name, sizeof (name), root, ".algorithm.parameters"); - result = _gnutls_x509_read_value (asn, name, &tmp, 0); /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ - if (result < 0 && pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */ + if (pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */ { - gnutls_assert (); - goto error; - } - - if ((result = - _gnutls_x509_read_pubkey_params (pk_algorithm, tmp.data, tmp.size, params)) < 0) - { - gnutls_assert (); - goto error; + result = _gnutls_x509_read_value (asn, name, &tmp, 0); + if (result < 0) + { + gnutls_assert (); + goto error; + } + + if ((result = + _gnutls_x509_read_pubkey_params (pk_algorithm, tmp.data, tmp.size, params)) < 0) + { + gnutls_assert (); + goto error; + } } result = 0; diff --git a/lib/x509/output.c b/lib/x509/output.c index a49ae9543f..3977596bc4 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -1147,7 +1147,7 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned) /* SubjectPublicKeyInfo. */ { - int err; + int err, pk; unsigned int bits; err = gnutls_x509_crt_get_pk_algorithm (cert, &bits); @@ -1155,23 +1155,39 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned) addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err)); else { + gnutls_pubkey_t pubkey; const char *name = gnutls_pk_algorithm_get_name (err); if (name == NULL) name = _("unknown"); + + pk = err; addf (str, _("\tSubject Public Key Algorithm: %s\n"), name); addf (str, _("\tCertificate Security Level: %s\n"), gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param (err, bits))); - #ifdef ENABLE_PKI - switch (err) + err = gnutls_pubkey_init(&pubkey); + if (err < 0) + { + addf (str, "error: gnutls_pubkey_init: %s\n", gnutls_strerror (err)); + return; + } + + err = gnutls_pubkey_import_x509(pubkey, cert, 0); + if (err < 0) + { + addf (str, "error: gnutls_pubkey_import_x509: %s\n", gnutls_strerror (err)); + return; + } + + switch (pk) { case GNUTLS_PK_RSA: { gnutls_datum_t m, e; - err = gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e); + err = gnutls_pubkey_get_pk_rsa_raw (pubkey, &m, &e); if (err < 0) addf (str, "error: get_pk_rsa_raw: %s\n", gnutls_strerror (err)); @@ -1189,11 +1205,34 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned) } break; + case GNUTLS_PK_ECC: + { + gnutls_datum_t x, y; + gnutls_ecc_curve_t curve; + + err = gnutls_pubkey_get_pk_ecc_raw (pubkey, &curve, &x, &y); + if (err < 0) + addf (str, "error: get_pk_ecc_raw: %s\n", + gnutls_strerror (err)); + else + { + addf (str, _("\t\tCurve:\t%s\n"), gnutls_ecc_curve_get_name(curve)); + addf (str, _("\t\tX:\n")); + hexdump (str, x.data, x.size, "\t\t\t"); + adds (str, _("\t\tY:\n")); + hexdump (str, y.data, y.size, "\t\t\t"); + + gnutls_free (x.data); + gnutls_free (y.data); + + } + } + break; case GNUTLS_PK_DSA: { gnutls_datum_t p, q, g, y; - err = gnutls_x509_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y); + err = gnutls_pubkey_get_pk_dsa_raw (pubkey, &p, &q, &g, &y); if (err < 0) addf (str, "error: get_pk_dsa_raw: %s\n", gnutls_strerror (err)); @@ -1220,6 +1259,8 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned) default: break; } + + gnutls_pubkey_deinit(pubkey); #endif } }