static void dane_info(const char *host, const char *proto, unsigned int port, unsigned int ca, unsigned int domain, common_info_st * cinfo) { gnutls_pubkey_t pubkey; gnutls_x509_crt_t crt; unsigned char digest[64]; gnutls_datum_t t; int ret; unsigned int usage, selector, type; size_t size; if (proto == NULL) proto = "tcp"; if (port == 0) port = 443; crt = load_cert(0, cinfo); if (crt != NULL && HAVE_OPT(X509)) { selector = 0; /* X.509 */ size = buffer_size; ret = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, buffer, &size); if (ret < 0) { fprintf(stderr, "export error: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); } else { /* use public key only */ selector = 1; ret = gnutls_pubkey_init(&pubkey); if (ret < 0) { fprintf(stderr, "pubkey_init: %s\n", gnutls_strerror(ret)); exit(1); } if (crt != NULL) { ret = gnutls_pubkey_import_x509(pubkey, crt, 0); if (ret < 0) { fprintf(stderr, "pubkey_import_x509: %s\n", gnutls_strerror(ret)); exit(1); } size = buffer_size; ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, buffer, &size); if (ret < 0) { fprintf(stderr, "pubkey_export: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); } else { pubkey = load_pubkey(1, cinfo); size = buffer_size; ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, buffer, &size); if (ret < 0) { fprintf(stderr, "export error: %s\n", gnutls_strerror(ret)); exit(1); } } gnutls_pubkey_deinit(pubkey); } if (default_dig != GNUTLS_DIG_SHA256 && default_dig != GNUTLS_DIG_SHA512) { if (default_dig != GNUTLS_DIG_UNKNOWN) fprintf(stderr, "Unsupported digest. Assuming SHA256.\n"); default_dig = GNUTLS_DIG_SHA256; } ret = gnutls_hash_fast(default_dig, buffer, size, digest); if (ret < 0) { fprintf(stderr, "hash error: %s\n", gnutls_strerror(ret)); exit(1); } if (default_dig == GNUTLS_DIG_SHA256) type = 1; else type = 2; /* DANE certificate classification crap */ if (domain == 0) { if (ca) usage = 0; else usage = 1; } else { if (ca) usage = 2; else usage = 3; } t.data = digest; t.size = gnutls_hash_get_len(default_dig); size = buffer_size; ret = gnutls_hex_encode(&t, (void *) buffer, &size); if (ret < 0) { fprintf(stderr, "hex encode error: %s\n", gnutls_strerror(ret)); exit(1); } fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, selector, type, buffer); }
int /* O - 1 on success, 0 on failure */ cupsMakeServerCredentials( const char *path, /* I - Path to keychain/directory */ const char *common_name, /* I - Common name */ int num_alt_names, /* I - Number of subject alternate names */ const char **alt_names, /* I - Subject Alternate Names */ time_t expiration_date) /* I - Expiration date */ { gnutls_x509_crt_t crt; /* Self-signed certificate */ gnutls_x509_privkey_t key; /* Encryption private key */ char temp[1024], /* Temporary directory name */ crtfile[1024], /* Certificate filename */ keyfile[1024]; /* Private key filename */ cups_lang_t *language; /* Default language info */ cups_file_t *fp; /* Key/cert file */ unsigned char buffer[8192]; /* Buffer for x509 data */ size_t bytes; /* Number of bytes of data */ unsigned char serial[4]; /* Serial number buffer */ time_t curtime; /* Current time */ int result; /* Result of GNU TLS calls */ DEBUG_printf(("cupsMakeServerCredentials(path=\"%s\", common_name=\"%s\", num_alt_names=%d, alt_names=%p, expiration_date=%d)", path, common_name, num_alt_names, alt_names, (int)expiration_date)); /* * Filenames... */ if (!path) path = http_gnutls_default_path(temp, sizeof(temp)); if (!path || !common_name) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (0); } http_gnutls_make_path(crtfile, sizeof(crtfile), path, common_name, "crt"); http_gnutls_make_path(keyfile, sizeof(keyfile), path, common_name, "key"); /* * Create the encryption key... */ DEBUG_puts("1cupsMakeServerCredentials: Creating key pair."); gnutls_x509_privkey_init(&key); gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); DEBUG_puts("1cupsMakeServerCredentials: Key pair created."); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { DEBUG_printf(("1cupsMakeServerCredentials: Unable to export private key: %s", gnutls_strerror(result))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(result), 0); gnutls_x509_privkey_deinit(key); return (0); } else if ((fp = cupsFileOpen(keyfile, "w")) != NULL) { DEBUG_printf(("1cupsMakeServerCredentials: Writing private key to \"%s\".", keyfile)); cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file \"%s\": %s", keyfile, strerror(errno))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); gnutls_x509_privkey_deinit(key); return (0); } /* * Create the self-signed certificate... */ DEBUG_puts("1cupsMakeServerCredentials: Generating self-signed X.509 certificate."); language = cupsLangDefault(); curtime = time(NULL); serial[0] = curtime >> 24; serial[1] = curtime >> 16; serial[2] = curtime >> 8; serial[3] = curtime; gnutls_x509_crt_init(&crt); if (strlen(language->language) == 5) gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, language->language + 3, 2); else gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, "US", 2); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, common_name, strlen(common_name)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, common_name, strlen(common_name)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, "Unknown", 7); /* gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, ServerAdmin, strlen(ServerAdmin));*/ gnutls_x509_crt_set_key(crt, key); gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); gnutls_x509_crt_set_activation_time(crt, curtime); gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); gnutls_x509_crt_set_ca_status(crt, 0); if (num_alt_names > 0) gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, alt_names[0]); gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); gnutls_x509_crt_set_version(crt, 3); bytes = sizeof(buffer); if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); gnutls_x509_crt_sign(crt, crt, key); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { DEBUG_printf(("1cupsMakeServerCredentials: Unable to export public key and X.509 certificate: %s", gnutls_strerror(result))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(result), 0); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (0); } else if ((fp = cupsFileOpen(crtfile, "w")) != NULL) { DEBUG_printf(("1cupsMakeServerCredentials: Writing public key and X.509 certificate to \"%s\".", crtfile)); cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { DEBUG_printf(("1cupsMakeServerCredentials: Unable to create public key and X.509 certificate file \"%s\": %s", crtfile, strerror(errno))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (0); } /* * Cleanup... */ gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); DEBUG_puts("1cupsMakeServerCredentials: Successfully created credentials."); return (1); }
ssize_t mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER) { #ifdef USE_SSL struct mailstream_ssl_data *data = NULL; ssize_t len = 0; #ifndef USE_GNUTLS SSL *ssl_conn = NULL; X509 *cert = NULL; #else gnutls_session session = NULL; const gnutls_datum *raw_cert_list; unsigned int raw_cert_list_length; gnutls_x509_crt cert = NULL; char output[10*1024]; size_t cert_size; #endif if (cert_DER == NULL || stream == NULL || stream->low == NULL) return -1; data = stream->low->data; if (data == NULL) return -1; #ifndef USE_GNUTLS ssl_conn = data->ssl_conn; if (ssl_conn == NULL) return -1; cert = SSL_get_peer_certificate(ssl_conn); if (cert == NULL) return -1; *cert_DER = NULL; len = (ssize_t) i2d_X509(cert, cert_DER); X509_free(cert); return len; #else session = data->session; raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length); if (raw_cert_list && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509 && gnutls_x509_crt_init(&cert) >= 0 && gnutls_x509_crt_import(cert, &raw_cert_list[0], GNUTLS_X509_FMT_DER) >= 0) { cert_size = sizeof(output); if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, output, &cert_size) < 0) return -1; *cert_DER = malloc (cert_size + 1); if (*cert_DER == NULL) return -1; memcpy (*cert_DER, output, cert_size); len = (ssize_t)cert_size; gnutls_x509_crt_deinit(cert); return len; } #endif #endif return -1; }
/* lists certificates from a token */ void pkcs11_list (FILE * outfile, const char *url, int type, unsigned int login, unsigned int detailed, common_info_st * info) { gnutls_pkcs11_obj_t *crt_list; gnutls_x509_crt_t xcrt; unsigned int crt_list_size = 0; int ret; char *output; int i, attrs; unsigned int obj_flags = 0; if (login) obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common (); if (url == NULL) url = "pkcs11:"; if (type == PKCS11_TYPE_TRUSTED) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED; } else if (type == PKCS11_TYPE_PK) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY; } else if (type == PKCS11_TYPE_CRT_ALL) { attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL; } else if (type == PKCS11_TYPE_PRIVKEY) { attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY; } else { attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL; } /* give some initial value to avoid asking for the pkcs11 pin twice. */ crt_list_size = 128; crt_list = malloc (sizeof (*crt_list) * crt_list_size); if (crt_list == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } ret = gnutls_pkcs11_obj_list_import_url (crt_list, &crt_list_size, url, attrs, obj_flags); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf (stderr, "Error in crt_list_import (1): %s\n", gnutls_strerror (ret)); exit (1); } if (crt_list_size == 0) { fprintf (stderr, "No matching objects found\n"); exit (0); } if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { crt_list = realloc (crt_list, sizeof (*crt_list) * crt_list_size); if (crt_list == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } ret = gnutls_pkcs11_obj_list_import_url (crt_list, &crt_list_size, url, attrs, obj_flags); if (ret < 0) { fprintf (stderr, "Error in crt_list_import: %s\n", gnutls_strerror (ret)); exit (1); } } for (i = 0; i < crt_list_size; i++) { char buf[128]; size_t size; ret = gnutls_pkcs11_obj_export_url (crt_list[i], detailed, &output); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "Object %d:\n\tURL: %s\n", i, output); fprintf (outfile, "\tType: %s\n", gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_get_type (crt_list[i]))); size = sizeof (buf); ret = gnutls_pkcs11_obj_get_info (crt_list[i], GNUTLS_PKCS11_OBJ_LABEL, buf, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "\tLabel: %s\n", buf); size = sizeof (buf); ret = gnutls_pkcs11_obj_get_info (crt_list[i], GNUTLS_PKCS11_OBJ_ID_HEX, buf, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fprintf (outfile, "\tID: %s\n\n", buf); if (attrs == GNUTLS_PKCS11_OBJ_ATTR_ALL || attrs == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) continue; ret = gnutls_x509_crt_init (&xcrt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_x509_crt_import_pkcs11 (xcrt, crt_list[i]); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } #if 0 size = buffer_size; ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); fputs ("\n\n", outfile); #endif gnutls_x509_crt_deinit (xcrt); } return; }
void pkcs11_export (FILE * outfile, const char *url, unsigned int login, common_info_st * info) { gnutls_pkcs11_obj_t crt; gnutls_x509_crt_t xcrt; gnutls_pubkey_t pubkey; int ret; size_t size; unsigned int obj_flags = 0; if (login) obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common (); if (url == NULL) url = "pkcs11:"; ret = gnutls_pkcs11_obj_init (&crt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pkcs11_obj_import_url (crt, url, obj_flags); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } switch (gnutls_pkcs11_obj_get_type (crt)) { case GNUTLS_PKCS11_OBJ_X509_CRT: ret = gnutls_x509_crt_init (&xcrt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_x509_crt_import_pkcs11 (xcrt, crt); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } size = buffer_size; ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); gnutls_x509_crt_deinit (xcrt); break; case GNUTLS_PKCS11_OBJ_PUBKEY: ret = gnutls_pubkey_init (&pubkey); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } ret = gnutls_pubkey_import_pkcs11 (pubkey, crt, 0); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } size = buffer_size; ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (buffer, 1, size, outfile); gnutls_pubkey_deinit (pubkey); break; default: { gnutls_datum_t data, enc; size = buffer_size; ret = gnutls_pkcs11_obj_export (crt, buffer, &size); if (ret < 0) { break; } data.data = buffer; data.size = size; ret = gnutls_pem_base64_encode_alloc ("DATA", &data, &enc); if (ret < 0) { fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror (ret)); exit (1); } fwrite (enc.data, 1, enc.size, outfile); gnutls_free (enc.data); break; } } fputs ("\n\n", outfile); gnutls_pkcs11_obj_deinit (crt); return; }
void empathy_tls_certificate_store_ca (EmpathyTLSCertificate *self) { GArray *last_cert; gnutls_x509_crt_t cert; gnutls_datum_t datum = { NULL, 0 }; gsize exported_len; guchar *exported_cert = NULL; gint res, offset; gchar *user_certs_dir = NULL, *filename = NULL, *path = NULL; gchar *hostname = NULL; GError *error = NULL; EmpathyTLSCertificatePriv *priv = GET_PRIV (self); last_cert = g_ptr_array_index (priv->cert_data, priv->cert_data->len - 1); datum.data = (guchar *) last_cert->data; datum.size = last_cert->len; gnutls_x509_crt_init (&cert); gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER); /* make sure it's self-signed, otherwise it's not a CA */ if (gnutls_x509_crt_check_issuer (cert, cert) <= 0) { DEBUG ("Can't import the CA, as it's not self-signed"); gnutls_x509_crt_deinit (cert); return; } if (gnutls_x509_crt_get_ca_status (cert, NULL) <= 0) { DEBUG ("Can't import the CA, it's not a valid CA certificate"); gnutls_x509_crt_deinit (cert); goto out; } exported_len = get_exported_size (cert); exported_cert = g_malloc (sizeof (guchar) * exported_len); res = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, exported_cert, &exported_len); if (res < 0) { DEBUG ("Failed to export the CA certificate; GnuTLS returned %d," "and should be %lu bytes long", res, (gulong) exported_len); gnutls_x509_crt_deinit (cert); goto out; } hostname = empathy_get_x509_certificate_hostname (cert); if (hostname == NULL) hostname = g_strdup ("ca"); gnutls_x509_crt_deinit (cert); /* write the file */ user_certs_dir = g_build_filename (g_get_user_config_dir (), "telepathy", "certs", NULL); res = g_mkdir_with_parents (user_certs_dir, S_IRWXU | S_IRWXG); if (res < 0) { DEBUG ("Failed to create the user certificate directory: %s", g_strerror (errno)); goto out; } offset = 0; do { g_free (path); if (offset == 0) filename = g_strdup_printf ("cert-%s", hostname); else filename = g_strdup_printf ("cert-%s-%d", hostname, offset); path = g_build_filename (user_certs_dir, filename, NULL); offset++; g_free (filename); } while (g_file_test (path, G_FILE_TEST_EXISTS)); DEBUG ("Will save to %s", path); g_file_set_contents (path, (const gchar *) exported_cert, exported_len, &error); if (error != NULL) { DEBUG ("Can't save the CA certificate to %s: %s", path, error->message); g_error_free (error); } out: g_free (path); g_free (exported_cert); g_free (user_certs_dir); g_free (hostname); }
static void print_x509_info (gnutls_session_t session, const char *hostname, int insecure) { gnutls_x509_crt_t crt; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0, j; int hostname_ok = 0; int ret; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list_size == 0) { fprintf (stderr, "No certificates found!\n"); return; } printf (" - Got a certificate list of %d certificates.\n", cert_list_size); for (j = 0; j < cert_list_size; j++) { gnutls_datum_t cinfo; gnutls_x509_crt_init (&crt); ret = gnutls_x509_crt_import (crt, &cert_list[j], GNUTLS_X509_FMT_DER); if (ret < 0) { fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret)); return; } printf (" - Certificate[%d] info:\n - ", j); if (verbose) ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo); else ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo); if (ret == 0) { printf ("%s\n", cinfo.data); gnutls_free (cinfo.data); } if (print_cert) { size_t size; size = sizeof (buffer); ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM, buffer, &size); if (ret < 0) { fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret)); return; } fputs ("\n", stdout); fputs (buffer, stdout); fputs ("\n", stdout); } if (j == 0 && hostname != NULL) { /* Check the hostname of the first certificate if it matches * the name of the host we connected to. */ if (gnutls_x509_crt_check_hostname (crt, hostname) == 0) hostname_ok = 1; else hostname_ok = 2; } gnutls_x509_crt_deinit (crt); } if (hostname_ok == 1) { printf ("- The hostname in the certificate does NOT match '%s'\n", hostname); if (!insecure) exit (1); } else if (hostname_ok == 2) { printf ("- The hostname in the certificate matches '%s'.\n", hostname); } }
shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertificates() { if (getTracer()) { getTracer()->traceSend("Getting peer certificates"); } unsigned int certCount = 0; const gnutls_datum_t* rawData = gnutls_certificate_get_peers( *m_session->m_gnutlsSession, &certCount ); if (rawData == NULL) { return null; } // Try X.509 gnutls_x509_crt_t* x509Certs = new gnutls_x509_crt_t[certCount]; for (unsigned int i = 0; i < certCount; ++i) { gnutls_x509_crt_init(x509Certs + i); int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, GNUTLS_X509_FMT_DER); if (res < 0) { for (unsigned int j = 0 ; j <= i ; ++j) { gnutls_x509_crt_deinit(x509Certs[j]); } // XXX more fine-grained error reporting? delete [] x509Certs; return null; } } std::vector <shared_ptr <security::cert::certificate> > certs; bool error = false; for (unsigned int i = 0 ; i < certCount ; ++i) { size_t dataSize = 0; gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, NULL, &dataSize); std::vector <byte_t> data(dataSize); gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, &data[0], &dataSize); shared_ptr <security::cert::X509Certificate> cert = security::cert::X509Certificate::import(&data[0], dataSize); if (cert != NULL) { certs.push_back(cert); } else { error = true; } gnutls_x509_crt_deinit(x509Certs[i]); } delete [] x509Certs; if (error) { return null; } return make_shared <security::cert::certificateChain>(certs); }