From 531bac41a0ee19158f0722937d0c9efafbc3bb14 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 7 Oct 2012 10:33:55 +0200 Subject: [PATCH] Added functions to export structures in an allocated buffer. --- NEWS | 15 ++++++ doc/cha-cert-auth2.texi | 4 +- doc/cha-tokens.texi | 2 +- doc/invoke-gnutls-cli.texi | 19 ++++++- lib/gnutls_dh_primes.c | 116 ++++++++++++++++++++------------------- lib/gnutls_pubkey.c | 67 +++++++++++++++++++++++ lib/includes/gnutls/abstract.h | 4 ++ lib/includes/gnutls/gnutls.h.in | 3 ++ lib/includes/gnutls/openpgp.h | 8 +++ lib/includes/gnutls/pkcs11.h | 3 +- lib/includes/gnutls/pkcs12.h | 3 ++ lib/includes/gnutls/x509.h | 23 ++++++++ lib/libgnutls.map | 13 +++++ lib/openpgp/openpgp_int.h | 6 ++- lib/openpgp/pgp.c | 55 +++++++++++++++++-- lib/openpgp/privkey.c | 25 +++++++++ lib/pkcs11.c | 32 +++++++++++ lib/x509/common.c | 117 ++++++++++++++++++---------------------- lib/x509/common.h | 14 +++-- lib/x509/crl.c | 59 +++++++++++--------- lib/x509/crq.c | 32 +++++++++++ lib/x509/dn.c | 32 +++++++++++ lib/x509/pkcs12.c | 31 +++++++++++ lib/x509/pkcs7.c | 26 +++++++++ lib/x509/privkey.c | 59 +++++++++++++++++--- lib/x509/privkey_pkcs8.c | 89 ++++++++++++++++++++++++++++++ lib/x509/x509.c | 30 +++++++++++ libdane/dane.c | 18 +------ 28 files changed, 719 insertions(+), 186 deletions(-) diff --git a/NEWS b/NEWS index caafbbd6c..a7f8d3f8a 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ certificate status extension in verification. ** libgnutls: Fixed the receipt of session tickets during session resumption. Reported by danblack at http://savannah.gnu.org/support/?108146 +** libgnutls: Added functions to export structures in an allocated buffer. + ** libgnutls: Added gnutls_ocsp_resp_check_crt() to check whether the OCSP response corresponds to the given certificate. @@ -25,6 +27,19 @@ gnutls_certificate_set_ocsp_status_request_file: Added gnutls_ocsp_status_request_enable_client: Added gnutls_ocsp_status_request_get: Added gnutls_ocsp_resp_check_crt: Added +gnutls_dh_params_export2_pkcs3: Added +gnutls_pubkey_export2: Added +gnutls_x509_crt_export2: Added +gnutls_x509_dn_export2: Added +gnutls_x509_crl_export2: Added +gnutls_pkcs7_export2: Added +gnutls_x509_privkey_export2: Added +gnutls_x509_privkey_export2_pkcs8: Added +gnutls_x509_crq_export2: Added +gnutls_openpgp_crt_export2: Added +gnutls_openpgp_privkey_export2: Added +gnutls_pkcs11_obj_export2: Added +gnutls_pkcs12_export2: Added dane_query_init: Added dane_query_deinit: Added dane_query_resolve_tlsa: Added diff --git a/doc/cha-cert-auth2.texi b/doc/cha-cert-auth2.texi index e375050a3..6ce6d7a3b 100644 --- a/doc/cha-cert-auth2.texi +++ b/doc/cha-cert-auth2.texi @@ -99,7 +99,7 @@ Optional CRL structure extensions. The basic CRL structure functions follow. -@showfuncC{gnutls_x509_crl_init,gnutls_x509_crl_import,gnutls_x509_crl_export} +@showfuncD{gnutls_x509_crl_init,gnutls_x509_crl_import,gnutls_x509_crl_export,gnutls_x509_crl_export} @subheading Reading a CRL @@ -322,7 +322,7 @@ enumeration. Note however, that GnuTLS only supports the PKCS #5 PBES2 encryption scheme. Keys encrypted with the obsolete PBES1 scheme cannot be decrypted. -@showfuncB{gnutls_x509_privkey_import_pkcs8,gnutls_x509_privkey_export_pkcs8} +@showfuncC{gnutls_x509_privkey_import_pkcs8,gnutls_x509_privkey_export_pkcs8,gnutls_x509_privkey_export2_pkcs8} @showenumdesc{gnutls_pkcs_encrypt_flags_t,Encryption flags} diff --git a/doc/cha-tokens.texi b/doc/cha-tokens.texi index 936cf6dd3..b290ff52c 100644 --- a/doc/cha-tokens.texi +++ b/doc/cha-tokens.texi @@ -71,7 +71,7 @@ sequence. @showfuncC{gnutls_pubkey_import_url,gnutls_pubkey_import_privkey,gnutls_pubkey_import} -@showfuncdesc{gnutls_pubkey_export} +@showfuncB{gnutls_pubkey_export,gnutls_pubkey_export2} An important function is @funcref{gnutls_pubkey_import_url} which will import public keys from URLs that identify objects stored in tokens (see @ref{Smart cards and HSMs} and @ref{Trusted Platform Module}). diff --git a/doc/invoke-gnutls-cli.texi b/doc/invoke-gnutls-cli.texi index 91f597097..ade332a00 100644 --- a/doc/invoke-gnutls-cli.texi +++ b/doc/invoke-gnutls-cli.texi @@ -7,7 +7,7 @@ # # DO NOT EDIT THIS FILE (invoke-gnutls-cli.texi) # -# It has been AutoGen-ed October 6, 2012 at 03:27:13 AM by AutoGen 5.16 +# It has been AutoGen-ed October 7, 2012 at 10:36:28 AM by AutoGen 5.16 # From the definitions ../src/cli-args.def # and the template file agtexi-cmd.tpl @end ignore @@ -47,6 +47,9 @@ USAGE: gnutls-cli [ - [] | --[@{=| @}] ]... [hostname] - disabled as --no-tofu --dane Enable DANE certificate verification (DNSSEC) - disabled as --no-dane + --ca-verification Disable CA certificate verification + - disabled as --no-ca-verification + - enabled by default --ocsp Enable OCSP certificate verification - disabled as --no-ocsp -r, --resume Establish a session and resume @@ -133,6 +136,20 @@ This is the ``enable dane certificate verification (dnssec)'' option. This option will, in addition to certificate authentication using the trusted CAs, verify the server certificates using on the DANE information available via DNSSEC. +@anchor{gnutls-cli ca-verification} +@subheading ca-verification option +@cindex gnutls-cli-ca-verification + +This is the ``disable ca certificate verification'' option. + +@noindent +This option has some usage constraints. It: +@itemize @bullet +@item +is enabled by default. +@end itemize + +This option will disable CA certificate verification. It is to be used with the --dane or --tofu options. @anchor{gnutls-cli ocsp} @subheading ocsp option @cindex gnutls-cli-ocsp diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c index caa9fe893..4eb16388e 100644 --- a/lib/gnutls_dh_primes.c +++ b/lib/gnutls_dh_primes.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "x509/x509_int.h" #include "debug.h" @@ -341,8 +342,56 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params, unsigned char *params_data, size_t * params_data_size) { +gnutls_datum_t out; +int ret; + + ret = gnutls_dh_params_export2_pkcs3( params, format, &out); + if (ret < 0) + return gnutls_assert_val(ret); + + if (*params_data_size < (unsigned) out.size+1) + { + gnutls_assert (); + gnutls_free (out.data); + *params_data_size = out.size + 1; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + *params_data_size = out.size; + if (params_data) + { + memcpy( params_data, out.data, out.size); + params_data[out.size] = 0; + } + + gnutls_free(out.data); + + return 0; +} + +/** + * gnutls_dh_params_export2_pkcs3: + * @params: Holds the DH parameters + * @format: the format of output params. One of PEM or DER. + * @out: will contain a PKCS3 DHParams structure PEM or DER encoded + * + * This function will export the given dh parameters to a PKCS3 + * DHParams structure. This is the format generated by "openssl dhparam" tool. + * The data in @out will be allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN DH PARAMETERS". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + **/ +int +gnutls_dh_params_export2_pkcs3 (gnutls_dh_params_t params, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out) +{ ASN1_TYPE c2; - int result, _params_data_size; + int result; size_t g_size, p_size; uint8_t *p_data, *g_data; uint8_t *all_data; @@ -395,6 +444,7 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params, if (result < 0) { gnutls_assert (); + gnutls_free (all_data); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } @@ -415,78 +465,34 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params, if (format == GNUTLS_X509_FMT_DER) { - if (params_data == NULL) - *params_data_size = 0; + result = _gnutls_x509_der_encode(c2, "", out, 0); - _params_data_size = *params_data_size; - result = - asn1_der_coding (c2, "", params_data, &_params_data_size, NULL); - *params_data_size = _params_data_size; asn1_delete_structure (&c2); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - if (result == ASN1_MEM_ERROR) - return GNUTLS_E_SHORT_MEMORY_BUFFER; - - return _gnutls_asn2err (result); - } + if (result < 0) + return gnutls_assert_val (result); } else { /* PEM */ - uint8_t *tmp; - gnutls_datum_t out; - int len; + gnutls_datum_t t; - len = 0; - asn1_der_coding (c2, "", NULL, &len, NULL); - - tmp = gnutls_malloc (len); - if (tmp == NULL) - { - gnutls_assert (); - asn1_delete_structure (&c2); - return GNUTLS_E_MEMORY_ERROR; - } - - if ((result = - asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS) - { - gnutls_assert (); - gnutls_free (tmp); - asn1_delete_structure (&c2); - return _gnutls_asn2err (result); - } + result = _gnutls_x509_der_encode(c2, "", &t, 0); asn1_delete_structure (&c2); - result = _gnutls_fbase64_encode ("DH PARAMETERS", tmp, len, &out); + if (result < 0) + return gnutls_assert_val (result); + + result = _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size, out); - gnutls_free (tmp); + gnutls_free (t.data); if (result < 0) { gnutls_assert (); return result; } - - if ((unsigned) out.size > *params_data_size) - { - gnutls_assert (); - gnutls_free (out.data); - *params_data_size = out.size + 1; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - *params_data_size = out.size; - - if (params_data) - memcpy (params_data, out.data, out.size); - - gnutls_free (out.data); - } return 0; diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index c14556282..21bea55ed 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -540,7 +540,74 @@ cleanup: asn1_delete_structure (&spk); return result; +} + +/** + * gnutls_pubkey_export2: + * @key: Holds the certificate + * @format: the format of output params. One of PEM or DER. + * @out: will contain a certificate PEM or DER encoded + * + * This function will export the public key to DER or PEM format. + * The contents of the exported data is the SubjectPublicKeyInfo + * X.509 structure. + * + * The output buffer will be allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN CERTIFICATE". + * + * Returns: In case of failure a negative error code will be + * returned, and 0 on success. + * + * Since: 3.1.3 + **/ +int +gnutls_pubkey_export2 (gnutls_pubkey_t key, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out) +{ + int result; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + + if (key == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + if ((result = asn1_create_element + (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk)) + != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + result = + _gnutls_x509_encode_and_copy_PKI_params (spk, "", + key->pk_algorithm, + &key->params); + if (result < 0) + { + gnutls_assert (); + goto cleanup; + } + + result = _gnutls_x509_export_int_named2 (spk, "", + format, PK_PEM_HEADER, out); + if (result < 0) + { + gnutls_assert (); + goto cleanup; + } + + result = 0; + +cleanup: + asn1_delete_structure (&spk); + + return result; } /** diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 245af8795..b96d6305e 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -108,6 +108,10 @@ int gnutls_pubkey_export (gnutls_pubkey_t key, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); +int gnutls_pubkey_export2 (gnutls_pubkey_t key, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out); + int gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int flags, unsigned char *output_data, size_t * output_data_size); diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index e7de530f2..51e594e65 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1291,6 +1291,9 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); gnutls_x509_crt_fmt_t format, unsigned char *params_data, size_t * params_data_size); + int gnutls_dh_params_export2_pkcs3 (gnutls_dh_params_t params, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t *out); int gnutls_dh_params_export_raw (gnutls_dh_params_t params, gnutls_datum_t * prime, gnutls_datum_t * generator, diff --git a/lib/includes/gnutls/openpgp.h b/lib/includes/gnutls/openpgp.h index 1d4e0cd59..bed810168 100644 --- a/lib/includes/gnutls/openpgp.h +++ b/lib/includes/gnutls/openpgp.h @@ -68,6 +68,9 @@ extern "C" gnutls_openpgp_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_openpgp_crt_export2 (gnutls_openpgp_crt_t key, + gnutls_openpgp_crt_fmt_t format, + gnutls_datum_t * out); int gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert, gnutls_certificate_print_formats_t format, @@ -241,6 +244,11 @@ extern "C" unsigned int flags, void *output_data, size_t * output_data_size); + int gnutls_openpgp_privkey_export2 (gnutls_openpgp_privkey_t key, + gnutls_openpgp_crt_fmt_t format, + const char *password, + unsigned int flags, + gnutls_datum_t * out); int gnutls_openpgp_privkey_set_preferred_key_id (gnutls_openpgp_privkey_t key, diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 84af6f2ba..0e486cea0 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -120,7 +120,8 @@ void gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj); int gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj, void *output_data, size_t * output_data_size); - +int gnutls_pkcs11_obj_export2 (gnutls_pkcs11_obj_t obj, + gnutls_datum_t *out); int gnutls_pkcs11_copy_x509_crt (const char *token_url, gnutls_x509_crt_t crt, const char *label, unsigned int flags diff --git a/lib/includes/gnutls/pkcs12.h b/lib/includes/gnutls/pkcs12.h index 09b75e935..02f6351c1 100644 --- a/lib/includes/gnutls/pkcs12.h +++ b/lib/includes/gnutls/pkcs12.h @@ -46,6 +46,9 @@ extern "C" int gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_pkcs12_export2 (gnutls_pkcs12_t pkcs12, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t *out); int gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12, int indx, gnutls_pkcs12_bag_t bag); diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 94e01a472..7845f22ed 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -123,6 +123,9 @@ extern "C" int gnutls_x509_crt_export (gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_x509_crt_export2 (gnutls_x509_crt_t cert, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t* out); int gnutls_x509_crt_get_private_key_usage_period (gnutls_x509_crt_t cert, time_t* activation, time_t* expiration, unsigned int *critical); @@ -463,6 +466,9 @@ extern "C" int gnutls_x509_dn_export (gnutls_x509_dn_t dn, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_x509_dn_export2 (gnutls_x509_dn_t dn, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out); void gnutls_x509_dn_deinit (gnutls_x509_dn_t dn); @@ -478,6 +484,9 @@ extern "C" int gnutls_x509_crl_export (gnutls_x509_crl_t crl, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_x509_crl_export2 (gnutls_x509_crl_t crl, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t *out); int gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl, @@ -580,6 +589,9 @@ extern "C" int gnutls_pkcs7_export (gnutls_pkcs7_t pkcs7, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_pkcs7_export2 (gnutls_pkcs7_t pkcs7, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t *out); int gnutls_pkcs7_get_crt_count (gnutls_pkcs7_t pkcs7); int gnutls_pkcs7_get_crt_raw (gnutls_pkcs7_t pkcs7, int indx, @@ -803,12 +815,20 @@ extern "C" gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_x509_privkey_export2 (gnutls_x509_privkey_t key, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out); int gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, gnutls_x509_crt_fmt_t format, const char *password, unsigned int flags, void *output_data, size_t * output_data_size); + int gnutls_x509_privkey_export2_pkcs8 (gnutls_x509_privkey_t key, + gnutls_x509_crt_fmt_t format, + const char *password, + unsigned int flags, + gnutls_datum_t * out); int gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t key, gnutls_datum_t * m, gnutls_datum_t * e, @@ -887,6 +907,9 @@ extern "C" int gnutls_x509_crq_export (gnutls_x509_crq_t crq, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); + int gnutls_x509_crq_export2 (gnutls_x509_crq_t crq, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out); int gnutls_x509_crt_set_crq (gnutls_x509_crt_t crt, gnutls_x509_crq_t crq); int gnutls_x509_crt_set_crq_extensions (gnutls_x509_crt_t crt, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 9cfe3d317..578e159f1 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -841,6 +841,19 @@ GNUTLS_3_1_0 { gnutls_certificate_set_ocsp_status_request_file; gnutls_ocsp_status_request_enable_client; gnutls_ocsp_status_request_get; + gnutls_dh_params_export2_pkcs3; + gnutls_pubkey_export2; + gnutls_x509_crt_export2; + gnutls_x509_dn_export2; + gnutls_x509_crl_export2; + gnutls_pkcs7_export2; + gnutls_x509_privkey_export2; + gnutls_x509_privkey_export2_pkcs8; + gnutls_x509_crq_export2; + gnutls_openpgp_crt_export2; + gnutls_openpgp_privkey_export2; + gnutls_pkcs11_obj_export2; + gnutls_pkcs12_export2; } GNUTLS_3_0_0; GNUTLS_PRIVATE { diff --git a/lib/openpgp/openpgp_int.h b/lib/openpgp/openpgp_int.h index 9f6b3a521..a144793cf 100644 --- a/lib/openpgp/openpgp_int.h +++ b/lib/openpgp/openpgp_int.h @@ -63,7 +63,11 @@ int _gnutls_map_cdk_rc (int rc); int _gnutls_openpgp_export (cdk_kbnode_t node, gnutls_openpgp_crt_fmt_t format, void *output_data, size_t * output_data_size, - int private); + int priv); + +int _gnutls_openpgp_export2 (cdk_kbnode_t node, + gnutls_openpgp_crt_fmt_t format, + gnutls_datum_t* out, int priv); cdk_packet_t _gnutls_get_valid_subkey (cdk_kbnode_t knode, int key_type); diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c index dc6cadcad..78ef7882b 100644 --- a/lib/openpgp/pgp.c +++ b/lib/openpgp/pgp.c @@ -119,13 +119,39 @@ gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, return 0; } +int _gnutls_openpgp_export2 (cdk_kbnode_t node, + gnutls_openpgp_crt_fmt_t format, + gnutls_datum_t* out, int priv) +{ +int ret; +size_t size = 0; + + ret = _gnutls_openpgp_export(node, format, NULL, &size, priv); + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + { + out->data = gnutls_malloc(size); + + ret = _gnutls_openpgp_export(node, format, out->data, &size, priv); + if (ret < 0) + { + gnutls_free(out->data); + return gnutls_assert_val(ret); + } + out->size = size; + } + else if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + /* internal version of export */ int _gnutls_openpgp_export (cdk_kbnode_t node, gnutls_openpgp_crt_fmt_t format, void *output_data, - size_t * output_data_size, int private) + size_t * output_data_size, int priv) { size_t input_data_size = *output_data_size; size_t calc_size; @@ -141,7 +167,7 @@ _gnutls_openpgp_export (cdk_kbnode_t node, /* If the caller uses output_data == NULL then return what he expects. */ - if (!output_data) + if (!output_data && format != GNUTLS_OPENPGP_FMT_BASE64) { gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; @@ -156,7 +182,7 @@ _gnutls_openpgp_export (cdk_kbnode_t node, buffer is large enough. */ rc = cdk_armor_encode_buffer (in, *output_data_size, NULL, 0, &calc_size, - private ? CDK_ARMOR_SECKEY : + priv ? CDK_ARMOR_SECKEY : CDK_ARMOR_PUBKEY); if (rc || calc_size > input_data_size) { @@ -168,7 +194,7 @@ _gnutls_openpgp_export (cdk_kbnode_t node, rc = cdk_armor_encode_buffer (in, *output_data_size, output_data, input_data_size, &calc_size, - private ? CDK_ARMOR_SECKEY : + priv ? CDK_ARMOR_SECKEY : CDK_ARMOR_PUBKEY); gnutls_free (in); *output_data_size = calc_size; @@ -189,7 +215,7 @@ _gnutls_openpgp_export (cdk_kbnode_t node, * gnutls_openpgp_crt_export: * @key: Holds the key. * @format: One of gnutls_openpgp_crt_fmt_t elements. - * @output_data: will contain the key base64 encoded or raw + * @output_data: will contain the raw or base64 encoded key * @output_data_size: holds the size of output_data (and will * be replaced by the actual size of parameters) * @@ -209,6 +235,25 @@ gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key, } /** + * gnutls_openpgp_crt_export2: + * @key: Holds the key. + * @format: One of gnutls_openpgp_crt_fmt_t elements. + * @out: will contain the raw or base64 encoded key + * + * This function will convert the given key to RAW or Base64 format. + * The output buffer is allocated using gnutls_malloc(). + * + * Returns: %GNUTLS_E_SUCCESS on success, or an error code. + **/ +int +gnutls_openpgp_crt_export2 (gnutls_openpgp_crt_t key, + gnutls_openpgp_crt_fmt_t format, + gnutls_datum_t *out) +{ + return _gnutls_openpgp_export2 (key->knode, format, out, 0); +} + +/** * gnutls_openpgp_crt_get_fingerprint: * @key: the raw data that contains the OpenPGP public key. * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c index bd04b2196..461aa9d0e 100644 --- a/lib/openpgp/privkey.c +++ b/lib/openpgp/privkey.c @@ -230,6 +230,31 @@ gnutls_openpgp_privkey_export (gnutls_openpgp_privkey_t key, output_data_size, 1); } +/** + * gnutls_openpgp_privkey_export2: + * @key: Holds the key. + * @format: One of gnutls_openpgp_crt_fmt_t elements. + * @password: the password that will be used to encrypt the key. (unused for now) + * @flags: (0) for future compatibility + * @out: will contain the raw or based64 encoded key + * + * This function will convert the given key to RAW or Base64 format. + * The output buffer is allocated using gnutls_malloc(). + * + * Returns: %GNUTLS_E_SUCCESS on success, or an error code. + * + * Since: 3.1 + **/ +int +gnutls_openpgp_privkey_export2 (gnutls_openpgp_privkey_t key, + gnutls_openpgp_crt_fmt_t format, + const char *password, unsigned int flags, + gnutls_datum_t *out) +{ + /* FIXME for now we do not export encrypted keys */ + return _gnutls_openpgp_export2 (key->knode, format, out, 1); +} + /** * gnutls_openpgp_privkey_get_pk_algorithm: diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 48dcd035e..0357c7ad5 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -832,6 +832,38 @@ gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj, return 0; } +/** + * gnutls_pkcs11_obj_export2: + * @obj: Holds the object + * @out: will contain a certificate PEM or DER encoded + * + * This function will export the PKCS11 object data. It is normal for + * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST + * will be returned. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN CERTIFICATE". + * + * Returns: In case of failure a negative error code will be + * returned, and %GNUTLS_E_SUCCESS (0) on success. + * + * Since: 3.1 + **/ +int +gnutls_pkcs11_obj_export2 (gnutls_pkcs11_obj_t obj, + gnutls_datum_t *out) +{ + if (obj == NULL || obj->raw.data == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_set_datum(out, obj->raw.data, obj->raw.size); +} + int pkcs11_find_object (struct pkcs11_session_info* sinfo, struct pin_info_st * pin_info, diff --git a/lib/x509/common.c b/lib/x509/common.c index fd4b815f3..d577f8ae4 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -776,91 +776,78 @@ _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const char *name, unsigned char *output_data, size_t * output_data_size) { - int result, len; + int ret; + gnutls_datum_t out; + size_t size; - if (format == GNUTLS_X509_FMT_DER) + ret = _gnutls_x509_export_int_named2 (asn1_data, name, + format, pem_header, &out); + if (ret < 0) + return gnutls_assert_val(ret); + + if (format == GNUTLS_X509_FMT_PEM) + size = out.size+1; + else + size = out.size; + + if (*output_data_size < size) { + *output_data_size = size; + ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + goto cleanup; + } - if (output_data == NULL) - *output_data_size = 0; + *output_data_size = (size_t)out.size; + if (output_data) + { + memcpy (output_data, out.data, (size_t)out.size); + if (format == GNUTLS_X509_FMT_PEM) + output_data[out.size] = 0; + } - len = *output_data_size; + ret = 0; - if ((result = - asn1_der_coding (asn1_data, name, output_data, &len, - NULL)) != ASN1_SUCCESS) - { - *output_data_size = (size_t)len; - if (result == ASN1_MEM_ERROR) - { - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - gnutls_assert (); - return _gnutls_asn2err (result); - } +cleanup: + gnutls_free (out.data); - *output_data_size = (size_t)len; + return ret; +} +/* A generic export function. Will export the given ASN.1 encoded data + * to PEM or DER raw data. + */ +int +_gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, const char *name, + gnutls_x509_crt_fmt_t format, + const char *pem_header, + gnutls_datum_t *out) +{ + int ret; + + if (format == GNUTLS_X509_FMT_DER) + { + ret = _gnutls_x509_der_encode(asn1_data, name, out, 0); + if (ret < 0) + return gnutls_assert_val(ret); } else { /* PEM */ - gnutls_datum_t out; gnutls_datum_t tmp; - result = _gnutls_x509_der_encode (asn1_data, name, &tmp, 0); - if (result < 0) - { - gnutls_assert (); - return result; - } - - result = _gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, &out); + ret = _gnutls_x509_der_encode (asn1_data, name, &tmp, 0); + if (ret < 0) + return gnutls_assert_val(ret); + ret = _gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, out); _gnutls_free_datum (&tmp); - if (result < 0) - { - gnutls_assert (); - return result; - } - - if ((size_t) out.size > *output_data_size) - { - gnutls_assert (); - gnutls_free (out.data); - *output_data_size = (size_t)out.size+1; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - *output_data_size = (size_t)out.size; - - if (output_data) - { - memcpy (output_data, out.data, (size_t)out.size); - - /* do not include the null character into output size. - */ - *output_data_size = (size_t)result - 1; - } - gnutls_free (out.data); - + if (ret < 0) + return gnutls_assert_val(ret); } return 0; } -int -_gnutls_x509_export_int (ASN1_TYPE asn1_data, - gnutls_x509_crt_fmt_t format, - const char *pem_header, - unsigned char *output_data, - size_t * output_data_size) -{ - return _gnutls_x509_export_int_named (asn1_data, "", - format, pem_header, output_data, - output_data_size); -} - /* Decodes an octet string. Leave string_type null for a normal * octet string. Otherwise put something like BMPString, PrintableString * etc. diff --git a/lib/x509/common.h b/lib/x509/common.h index e48e0f88e..1ee919435 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -95,11 +95,8 @@ int _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const char *src_name, int _gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, gnutls_datum_t * res, int str); -int _gnutls_x509_export_int (ASN1_TYPE asn1_data, - gnutls_x509_crt_fmt_t format, - const char *pem_header, - unsigned char *output_data, - size_t * output_data_size); +#define _gnutls_x509_export_int(asn1, format, header, out, out_size) \ + _gnutls_x509_export_int_named(asn1, "", format, header, out, out_size) int _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const char *name, gnutls_x509_crt_fmt_t format, @@ -107,6 +104,13 @@ int _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const char *name, unsigned char *output_data, size_t * output_data_size); +#define _gnutls_x509_export_int2(asn1, format, header, out) \ + _gnutls_x509_export_int_named2(asn1, "", format, header, out) +int _gnutls_x509_export_int_named2 (ASN1_TYPE asn1_data, const char *name, + gnutls_x509_crt_fmt_t format, + const char *pem_header, + gnutls_datum_t * out); + int _gnutls_x509_read_value (ASN1_TYPE c, const char *root, gnutls_datum_t * ret, int str); int _gnutls_x509_write_value (ASN1_TYPE c, const char *root, diff --git a/lib/x509/crl.c b/lib/x509/crl.c index b0e1fd82e..2565e9c3a 100644 --- a/lib/x509/crl.c +++ b/lib/x509/crl.c @@ -637,6 +637,37 @@ gnutls_x509_crl_export (gnutls_x509_crl_t crl, output_data, output_data_size); } +/** + * gnutls_x509_crl_export2: + * @crl: Holds the revocation list + * @format: the format of output params. One of PEM or DER. + * @out: will contain a private key PEM or DER encoded + * + * This function will export the revocation list to DER or PEM format. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN X509 CRL". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. and a negative error code on failure. + * + * Since 3.1 + **/ +int +gnutls_x509_crl_export2 (gnutls_x509_crl_t crl, + gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +{ + if (crl == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int2 (crl->crl, format, PEM_CRL, out); +} + /*- * _gnutls_x509_crl_cpy - This function copies a gnutls_x509_crl_t structure * @dest: The structure where to copy @@ -651,37 +682,15 @@ int _gnutls_x509_crl_cpy (gnutls_x509_crl_t dest, gnutls_x509_crl_t src) { int ret; - size_t der_size; - uint8_t *der; gnutls_datum_t tmp; - ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, NULL, &der_size); - if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) - { - gnutls_assert (); - return ret; - } - - der = gnutls_malloc (der_size); - if (der == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, der, &der_size); + ret = gnutls_x509_crl_export2 (src, GNUTLS_X509_FMT_DER, &tmp); if (ret < 0) - { - gnutls_assert (); - gnutls_free (der); - return ret; - } + return gnutls_assert_val(ret); - tmp.data = der; - tmp.size = der_size; ret = gnutls_x509_crl_import (dest, &tmp, GNUTLS_X509_FMT_DER); - gnutls_free (der); + gnutls_free (tmp.data); if (ret < 0) { diff --git a/lib/x509/crq.c b/lib/x509/crq.c index c4dec27ae..5651cb0e4 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -1156,6 +1156,38 @@ gnutls_x509_crq_export (gnutls_x509_crq_t crq, } /** + * gnutls_x509_crq_export2: + * @crq: should contain a #gnutls_x509_crq_t structure + * @format: the format of output params. One of PEM or DER. + * @out: will contain a certificate request PEM or DER encoded + * + * This function will export the certificate request to a PEM or DER + * encoded PKCS10 structure. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header of "BEGIN + * NEW CERTIFICATE REQUEST". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since 3.1 + **/ +int +gnutls_x509_crq_export2 (gnutls_x509_crq_t crq, + gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +{ + if (crq == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int2 (crq->crq, format, PEM_CRQ, out); +} + +/** * gnutls_x509_crq_get_pk_algorithm: * @crq: should contain a #gnutls_x509_crq_t structure * @bits: if bits is non-%NULL it will hold the size of the parameters' in bits diff --git a/lib/x509/dn.c b/lib/x509/dn.c index 5152691d3..9c6096193 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -1241,3 +1241,35 @@ gnutls_x509_dn_export (gnutls_x509_dn_t dn, format, "NAME", output_data, output_data_size); } + +/** + * gnutls_x509_dn_export2: + * @dn: Holds the uint8_t DN object + * @format: the format of output params. One of PEM or DER. + * @out: will contain a DN PEM or DER encoded + * + * This function will export the DN to DER or PEM format. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN NAME". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +int +gnutls_x509_dn_export2 (gnutls_x509_dn_t dn, + gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +{ + ASN1_TYPE asn1 = dn; + + if (asn1 == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int_named2 (asn1, "rdnSequence", + format, "NAME", out); +} diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index d06fea4a8..380f3fc9b 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -276,6 +276,37 @@ gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12, output_data, output_data_size); } +/** + * gnutls_pkcs12_export2: + * @pkcs12: Holds the pkcs12 structure + * @format: the format of output params. One of PEM or DER. + * @out: will contain a structure PEM or DER encoded + * + * This function will export the pkcs12 structure to DER or PEM format. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN PKCS12". + * + * Returns: In case of failure a negative error code will be + * returned, and 0 on success. + * + * Since: 3.1 + **/ +int +gnutls_pkcs12_export2 (gnutls_pkcs12_t pkcs12, + gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +{ + if (pkcs12 == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int2 (pkcs12->pkcs12, format, PEM_PKCS12, out); +} + static int oid2bag (const char *oid) { diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c index 16e4d3b28..5149f5c3f 100644 --- a/lib/x509/pkcs7.c +++ b/lib/x509/pkcs7.c @@ -432,6 +432,32 @@ gnutls_pkcs7_export (gnutls_pkcs7_t pkcs7, output_data, output_data_size); } +/** + * gnutls_pkcs7_export2: + * @pkcs7: Holds the pkcs7 structure + * @format: the format of output params. One of PEM or DER. + * @out: will contain a structure PEM or DER encoded + * + * This function will export the pkcs7 structure to DER or PEM format. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN PKCS7". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +int +gnutls_pkcs7_export2 (gnutls_pkcs7_t pkcs7, + gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +{ + if (pkcs7 == NULL) + return GNUTLS_E_INVALID_REQUEST; + + return _gnutls_x509_export_int2 (pkcs7->pkcs7, format, PEM_PKCS7, out); +} + /* Creates an empty signed data structure in the pkcs7 * structure and returns a handle to the signed data. */ diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index b9039722a..875d1f47e 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1016,6 +1016,18 @@ int ret; return key->pk_algorithm; } +static const char* set_msg(gnutls_x509_privkey_t key) +{ + if (key->pk_algorithm == GNUTLS_PK_RSA) + return PEM_KEY_RSA; + else if (key->pk_algorithm == GNUTLS_PK_DSA) + return PEM_KEY_DSA; + else if (key->pk_algorithm == GNUTLS_PK_EC) + return PEM_KEY_ECC; + else + return "UNKNOWN"; +} + /** * gnutls_x509_privkey_export: * @key: Holds the key @@ -1051,20 +1063,51 @@ gnutls_x509_privkey_export (gnutls_x509_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } - if (key->pk_algorithm == GNUTLS_PK_RSA) - msg = PEM_KEY_RSA; - else if (key->pk_algorithm == GNUTLS_PK_DSA) - msg = PEM_KEY_DSA; - else if (key->pk_algorithm == GNUTLS_PK_EC) - msg = PEM_KEY_ECC; - else - msg = "UNKNOWN"; + msg = set_msg(key); return _gnutls_x509_export_int (key->key, format, msg, output_data, output_data_size); } /** + * gnutls_x509_privkey_export2: + * @key: Holds the key + * @format: the format of output params. One of PEM or DER. + * @out: will contain a private key PEM or DER encoded + * + * This function will export the private key to a PKCS1 structure for + * RSA keys, or an integer sequence for DSA keys. The DSA keys are in + * the same format with the parameters used by openssl. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN RSA PRIVATE KEY". + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since 3.1 + **/ +int +gnutls_x509_privkey_export2 (gnutls_x509_privkey_t key, + gnutls_x509_crt_fmt_t format, + gnutls_datum_t * out) +{ + const char *msg; + + if (key == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + msg = set_msg(key); + + return _gnutls_x509_export_int2 (key->key, format, msg, out); +} + +/** * gnutls_x509_privkey_sec_param: * @key: a key structure * diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 2ccb5f95d..42d3c5112 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -660,6 +660,95 @@ gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, return ret; } +/** + * gnutls_x509_privkey_export2_pkcs8: + * @key: Holds the key + * @format: the format of output params. One of PEM or DER. + * @password: the password that will be used to encrypt the key. + * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t + * @out: will contain a private key PEM or DER encoded + * + * This function will export the private key to a PKCS8 structure. + * Both RSA and DSA keys can be exported. For DSA keys we use + * PKCS #11 definitions. If the flags do not specify the encryption + * cipher, then the default 3DES (PBES2) will be used. + * + * The @password can be either ASCII or UTF-8 in the default PBES2 + * encryption schemas, or ASCII for the PKCS12 schemas. + * + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if + * encryption is not used. + * + * Returns: In case of failure a negative error code will be + * returned, and 0 on success. + * + * Since 3.1 + **/ +int +gnutls_x509_privkey_export2_pkcs8 (gnutls_x509_privkey_t key, + gnutls_x509_crt_fmt_t format, + const char *password, + unsigned int flags, + gnutls_datum_t *out) +{ + ASN1_TYPE pkcs8_asn, pkey_info; + int ret; + gnutls_datum_t tmp; + schema_id schema; + + if (key == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Get the private key info + * tmp holds the DER encoding. + */ + ret = encode_to_private_key_info (key, &tmp, &pkey_info); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + schema = _gnutls_pkcs_flags_to_schema (flags); + + if (((flags & GNUTLS_PKCS_PLAIN) || password == NULL) && !(flags & GNUTLS_PKCS_NULL_PASSWORD)) + { + _gnutls_free_datum (&tmp); + + ret = + _gnutls_x509_export_int2 (pkey_info, format, + PEM_UNENCRYPTED_PKCS8, out); + + asn1_delete_structure (&pkey_info); + } + else + { + asn1_delete_structure (&pkey_info); /* we don't need it */ + + ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn); + _gnutls_free_datum (&tmp); + + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = + _gnutls_x509_export_int2 (pkcs8_asn, format, PEM_PKCS8, out); + + asn1_delete_structure (&pkcs8_asn); + } + + return ret; +} + /* Read the parameters cipher, IV, salt etc using the given * schema ID. diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 0e1430d18..308047fb0 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -2340,6 +2340,36 @@ gnutls_x509_crt_export (gnutls_x509_crt_t cert, output_data, output_data_size); } +/** + * gnutls_x509_crt_export2: + * @cert: Holds the certificate + * @format: the format of output params. One of PEM or DER. + * @out: will contain a certificate PEM or DER encoded + * + * This function will export the certificate to DER or PEM format. + * The output buffer is allocated using gnutls_malloc(). + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN CERTIFICATE". + * + * Returns: In case of failure a negative error code will be + * returned, and 0 on success. + * + * Since: 3.1 + **/ +int +gnutls_x509_crt_export2 (gnutls_x509_crt_t cert, + gnutls_x509_crt_fmt_t format, gnutls_datum_t * out) +{ + if (cert == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int2 (cert->cert, format, "CERTIFICATE", out); +} + int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params, unsigned char *output_data, diff --git a/libdane/dane.c b/libdane/dane.c index 6f9a2db4c..ebf362c49 100644 --- a/libdane/dane.c +++ b/libdane/dane.c @@ -306,7 +306,6 @@ static int crt_to_pubkey(const gnutls_datum_t *raw_crt, gnutls_datum_t * out) gnutls_pubkey_t pub = NULL; gnutls_x509_crt_t crt = NULL; int ret; -size_t size; out->data = NULL; @@ -332,27 +331,12 @@ size_t size; goto cleanup; } - size = 0; - ret = gnutls_pubkey_export(pub, GNUTLS_X509_FMT_DER, NULL, &size); - if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { - ret = DANE_E_PUBKEY_ERROR; - goto cleanup; - } - - out->data = malloc(size); - if (out->data == NULL) { - ret = DANE_E_MEMORY_ERROR; - goto cleanup; - } - - ret = gnutls_pubkey_export(pub, GNUTLS_X509_FMT_DER, out->data, &size); + ret = gnutls_pubkey_export2(pub, GNUTLS_X509_FMT_DER, out); if (ret < 0) { ret = DANE_E_PUBKEY_ERROR; goto cleanup; } - out->size = size; - ret = 0; goto clean_certs; -- 2.11.4.GIT