uschar * tls_cert_signature_algorithm(void * cert, uschar * mod) { gnutls_sign_algorithm_t algo = gnutls_x509_crt_get_signature_algorithm((gnutls_x509_crt_t)cert); return algo < 0 ? NULL : string_copy(gnutls_sign_get_name(algo)); }
void __certificate_properties_fill_cert_signature(GtkTreeStore *store, GtkTreeIter *parent, gnutls_x509_crt_t *certificate) { int result; GtkTreeIter j; GtkTreeIter k; const gchar *name = NULL; result = gnutls_x509_crt_get_signature_algorithm(*certificate); name = gnutls_sign_algorithm_get_name(result); gtk_tree_store_append(store, &j, parent); gtk_tree_store_set(store, &j, CERTIFICATE_PROPERTIES_COL_NAME, _("Signature"), -1); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Algorithm"), CERTIFICATE_PROPERTIES_COL_VALUE, name, -1); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Parameters"), CERTIFICATE_PROPERTIES_COL_VALUE, _("(unknown)"), -1); }
/* * Verifies the given certificate again a certificate list of * trusted CAs. * * Returns only 0 or 1. If 1 it means that the certificate * was successfuly verified. * * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. * * Output will hold some extra information about the verification * procedure. Issuer will hold the actual issuer from the trusted list. */ static int _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, const gnutls_x509_crt_t * trusted_cas, int tcas_size, unsigned int flags, unsigned int *output, gnutls_x509_crt_t * _issuer, time_t now, gnutls_verify_output_function func) { gnutls_datum_t cert_signed_data = { NULL, 0 }; gnutls_datum_t cert_signature = { NULL, 0 }; gnutls_x509_crt_t issuer = NULL; int issuer_version, result, hash_algo; unsigned int out = 0; if (output) *output = 0; if (tcas_size >= 1) issuer = find_issuer (cert, trusted_cas, tcas_size); else { gnutls_assert (); out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; if (output) *output |= out; result = 0; goto cleanup; } /* issuer is not in trusted certificate * authorities. */ if (issuer == NULL) { out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; if (output) *output |= out; gnutls_assert (); result = 0; goto cleanup; } if (_issuer != NULL) *_issuer = issuer; issuer_version = gnutls_x509_crt_get_version (issuer); if (issuer_version < 0) { gnutls_assert (); return issuer_version; } if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) || issuer_version != 1)) { if (check_if_ca (cert, issuer, flags) == 0) { gnutls_assert (); out = GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; if (output) *output |= out; result = 0; goto cleanup; } } result = _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", &cert_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signature_algorithm(cert->cert, "signatureAlgorithm.algorithm"); if (result < 0) { gnutls_assert (); goto cleanup; } hash_algo = gnutls_sign_get_hash_algorithm(result); result = _gnutls_x509_verify_data (hash_algo, &cert_signed_data, &cert_signature, issuer); if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) { gnutls_assert (); out |= GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNATURE_FAILURE; /* error. ignore it */ if (output) *output |= out; result = 0; } else if (result < 0) { gnutls_assert(); goto cleanup; } /* If the certificate is not self signed check if the algorithms * used are secure. If the certificate is self signed it doesn't * really matter. */ if (is_issuer (cert, cert) == 0) { int sigalg; sigalg = gnutls_x509_crt_get_signature_algorithm (cert); if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || ((sigalg == GNUTLS_SIGN_RSA_MD5) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) { out = GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; if (output) *output |= out; result = 0; } } /* Check activation/expiration times */ if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) { /* check the time of the issuer first */ if (!(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS)) { out |= check_time (issuer, now); if (out != 0) { result = 0; if (output) *output |= out; } } out |= check_time (cert, now); if (out != 0) { result = 0; if (output) *output |= out; } } cleanup: if (result >= 0 && func) func(cert, issuer, NULL, out); _gnutls_free_datum (&cert_signed_data); _gnutls_free_datum (&cert_signature); return result; }
bool CTlsSocket::ExtractCert(const void* in, CCertificate& out) { const gnutls_datum_t* datum = reinterpret_cast<const gnutls_datum_t*>(in); gnutls_x509_crt_t cert; if (gnutls_x509_crt_init(&cert)) { m_pOwner->LogMessage(::Error, _("Could not initialize structure for peer certificates, gnutls_x509_crt_init failed")); return false; } if (gnutls_x509_crt_import(cert, datum, GNUTLS_X509_FMT_DER)) { m_pOwner->LogMessage(::Error, _("Could not import peer certificates, gnutls_x509_crt_import failed")); gnutls_x509_crt_deinit(cert); return false; } wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert); wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert); // Get the serial number of the certificate unsigned char buffer[40]; size_t size = sizeof(buffer); int res = gnutls_x509_crt_get_serial(cert, buffer, &size); if( res != 0 ) { size = 0; } wxString serial = bin2hex(buffer, size); unsigned int pkBits; int pkAlgo = gnutls_x509_crt_get_pk_algorithm(cert, &pkBits); wxString pkAlgoName; if (pkAlgo >= 0) { const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)pkAlgo); if (pAlgo) pkAlgoName = wxString(pAlgo, wxConvUTF8); } int signAlgo = gnutls_x509_crt_get_signature_algorithm(cert); wxString signAlgoName; if (signAlgo >= 0) { const char* pAlgo = gnutls_sign_algorithm_get_name((gnutls_sign_algorithm_t)signAlgo); if (pAlgo) signAlgoName = wxString(pAlgo, wxConvUTF8); } wxString subject, issuer; size = 0; res = gnutls_x509_crt_get_dn(cert, 0, &size); if (size) { char* dn = new char[size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size))) { dn[size] = 0; subject = wxString(dn, wxConvUTF8); } else LogError(res, _T("gnutls_x509_crt_get_dn")); delete [] dn; } else LogError(res, _T("gnutls_x509_crt_get_dn")); if (subject == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate subject, gnutls_x509_get_dn failed")); gnutls_x509_crt_deinit(cert); return false; } size = 0; res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size); if (size) { char* dn = new char[++size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size))) { dn[size] = 0; issuer = wxString(dn, wxConvUTF8); } else LogError(res, _T("gnutls_x509_crt_get_issuer_dn")); delete [] dn; } else LogError(res, _T("gnutls_x509_crt_get_issuer_dn")); if (issuer == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate issuer, gnutls_x509_get_issuer_dn failed")); gnutls_x509_crt_deinit(cert); return false; } wxString fingerprint_md5; wxString fingerprint_sha1; unsigned char digest[100]; size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size)) { digest[size] = 0; fingerprint_md5 = bin2hex(digest, size); } size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size)) { digest[size] = 0; fingerprint_sha1 = bin2hex(digest, size); } gnutls_x509_crt_deinit(cert); out = CCertificate( datum->data, datum->size, activationTime, expirationTime, serial, pkAlgoName, pkBits, signAlgoName, fingerprint_md5, fingerprint_sha1, subject, issuer); return true; }
static int cert_callback (gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) { char issuer_dn[256]; int i, ret; size_t len; if (verbose) { /* Print the server's trusted CAs */ if (nreqs > 0) printf ("- Server's trusted authorities:\n"); else printf ("- Server did not send us any trusted authorities names.\n"); /* print the names (if any) */ for (i = 0; i < nreqs; i++) { len = sizeof (issuer_dn); ret = gnutls_x509_rdn_get (&req_ca_rdn[i], issuer_dn, &len); if (ret >= 0) { printf (" [%d]: ", i); printf ("%s\n", issuer_dn); } } } /* Select a certificate and return it. * The certificate must be of any of the "sign algorithms" * supported by the server. */ st->type = gnutls_certificate_type_get (session); st->ncerts = 0; if (st->type == GNUTLS_CRT_X509) { gnutls_sign_algorithm_t cert_algo, req_algo; int i, match = 0; if (x509_crt[0] != NULL) { ret = gnutls_x509_crt_get_signature_algorithm (x509_crt[0]); if (ret < 0) { /* error reading signature algorithm */ return -1; } cert_algo = ret; i = 0; do { ret = gnutls_sign_algorithm_get_requested (session, i, &req_algo); if (ret >= 0 && cert_algo == req_algo) { match = 1; break; } /* server has not requested anything specific */ if (i == 0 && ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { match = 1; break; } i++; } while (ret >= 0); if (match == 0) { printf ("- Could not find a suitable certificate to send to server\n"); return -1; } } if (x509_crt != NULL && x509_key != NULL) { st->ncerts = x509_crt_size; st->cert.x509 = x509_crt; st->key.x509 = x509_key; st->deinit_all = 0; return 0; } } else if (st->type == GNUTLS_CRT_OPENPGP) { if (pgp_key != NULL && pgp_crt != NULL) { st->ncerts = 1; st->cert.pgp = pgp_crt; st->key.pgp = pgp_key; st->deinit_all = 0; return 0; } } printf ("- Successfully sent %d certificate(s) to server.\n", st->ncerts); return 0; }
const void * eet_identity_check(const void *data_base, unsigned int data_length, void **sha1, int *sha1_length, const void *signature_base, unsigned int signature_length, const void **raw_signature_base, unsigned int *raw_signature_length, int *x509_length) { #ifdef HAVE_SIGNATURE const int *header = signature_base; const unsigned char *sign; const unsigned char *cert_der; int sign_len; int cert_len; int magic; /* At least the header size */ if (signature_length < sizeof(int) * 3) return NULL; if (!emile_cipher_init()) return NULL; /* Get the header */ memcpy(&magic, header, sizeof(int)); memcpy(&sign_len, header+1, sizeof(int)); memcpy(&cert_len, header+2, sizeof(int)); magic = ntohl(magic); sign_len = ntohl(sign_len); cert_len = ntohl(cert_len); /* Verify the header */ if (magic != EET_MAGIC_SIGN) return NULL; if (sign_len + cert_len + sizeof(int) * 3 > signature_length) return NULL; /* Update the signature and certificate pointer */ sign = (unsigned char *)signature_base + sizeof(int) * 3; cert_der = sign + sign_len; # ifdef HAVE_GNUTLS gnutls_x509_crt_t cert; gnutls_datum_t datum; gnutls_datum_t signature; gnutls_pubkey_t pubkey; unsigned char *hash; gcry_md_hd_t md; int err; /* Create an understanding certificate structure for gnutls */ datum.data = (void *)cert_der; datum.size = cert_len; gnutls_x509_crt_init(&cert); gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER); signature.data = (void *)sign; signature.size = sign_len; /* Verify the signature */ /* I am waiting for my patch being accepted in GnuTLS release. But we now have a way to prevent double computation of SHA1. */ err = gcry_md_open (&md, GCRY_MD_SHA1, 0); if (err < 0) return NULL; gcry_md_write(md, data_base, data_length); hash = gcry_md_read(md, GCRY_MD_SHA1); if (!hash) goto on_error; datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1); datum.data = hash; if (gnutls_pubkey_init(&pubkey) < 0) goto on_error; if (gnutls_pubkey_import_x509(pubkey, cert, 0) < 0) goto on_error; if (gnutls_pubkey_verify_hash2(pubkey, gnutls_x509_crt_get_signature_algorithm(cert), 0, &datum, &signature) < 0) goto on_error; if (sha1) { *sha1 = malloc(datum.size); if (!*sha1) goto on_error; memcpy(*sha1, hash, datum.size); *sha1_length = datum.size; } gcry_md_close(md); gnutls_x509_crt_deinit(cert); # else /* ifdef HAVE_GNUTLS */ const unsigned char *tmp; EVP_PKEY *pkey; X509 *x509; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) EVP_MD_CTX *md_ctx; #else EVP_MD_CTX md_ctx; #endif int err; /* Strange but d2i_X509 seems to put 0 all over the place. */ tmp = alloca(cert_len); memcpy((char *)tmp, cert_der, cert_len); x509 = d2i_X509(NULL, &tmp, cert_len); if (!x509) return NULL; /* Get public key - eay */ pkey = X509_get_pubkey(x509); if (!pkey) { X509_free(x509); return NULL; } /* Verify the signature */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) md_ctx = EVP_MD_CTX_new(); EVP_VerifyInit(md_ctx, EVP_sha1()); EVP_VerifyUpdate(md_ctx, data_base, data_length); err = EVP_VerifyFinal(md_ctx, sign, sign_len, pkey); EVP_MD_CTX_free(md_ctx); #else EVP_VerifyInit(&md_ctx, EVP_sha1()); EVP_VerifyUpdate(&md_ctx, data_base, data_length); err = EVP_VerifyFinal(&md_ctx, sign, sign_len, pkey); EVP_MD_CTX_cleanup(&md_ctx); #endif X509_free(x509); EVP_PKEY_free(pkey); if (sha1) { *sha1 = NULL; *sha1_length = -1; } if (err != 1) return NULL; # endif /* ifdef HAVE_GNUTLS */ if (x509_length) *x509_length = cert_len; if (raw_signature_base) *raw_signature_base = sign; if (raw_signature_length) *raw_signature_length = sign_len; return cert_der; # ifdef HAVE_GNUTLS on_error: gcry_md_close(md); return NULL; # endif #else /* ifdef HAVE_SIGNATURE */ data_base = NULL; data_length = 0; sha1 = NULL; sha1_length = NULL; signature_base = NULL; signature_length = 0; raw_signature_base = NULL; raw_signature_length = NULL; x509_length = NULL; return NULL; #endif /* ifdef HAVE_SIGNATURE */ }
/* * Verifies the given certificate again a certificate list of * trusted CAs. * * Returns only 0 or 1. If 1 it means that the certificate * was successfuly verified. * * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. * * Output will hold some extra information about the verification * procedure. Issuer will hold the actual issuer from the trusted list. */ static int _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, const gnutls_x509_crt_t * trusted_cas, int tcas_size, unsigned int flags, unsigned int *output, gnutls_x509_crt_t * _issuer) { gnutls_datum_t cert_signed_data = { NULL, 0 }; gnutls_datum_t cert_signature = { NULL, 0 }; gnutls_x509_crt_t issuer = NULL; int issuer_version, result; if (output) *output = 0; if (tcas_size >= 1) issuer = find_issuer (cert, trusted_cas, tcas_size); else { gnutls_assert (); if (output) *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; return 0; } /* issuer is not in trusted certificate * authorities. */ if (issuer == NULL) { if (output) *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; gnutls_assert (); return 0; } if (_issuer != NULL) *_issuer = issuer; issuer_version = gnutls_x509_crt_get_version (issuer); if (issuer_version < 0) { gnutls_assert (); return issuer_version; } if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) || issuer_version != 1)) { if (check_if_ca (cert, issuer, flags) == 0) { gnutls_assert (); if (output) *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; return 0; } } result = _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", &cert_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_verify_signature (&cert_signed_data, NULL, &cert_signature, issuer); if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) { gnutls_assert (); /* error. ignore it */ if (output) *output |= GNUTLS_CERT_INVALID; result = 0; } else if (result < 0) { gnutls_assert(); goto cleanup; } /* If the certificate is not self signed check if the algorithms * used are secure. If the certificate is self signed it doesn't * really matter. */ if (is_issuer (cert, cert) == 0) { int sigalg; sigalg = gnutls_x509_crt_get_signature_algorithm (cert); if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || ((sigalg == GNUTLS_SIGN_RSA_MD5) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) { if (output) *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; result = 0; } } cleanup: _gnutls_free_datum (&cert_signed_data); _gnutls_free_datum (&cert_signature); return result; }
void doit(void) { gnutls_x509_privkey_t key; gnutls_x509_crt_t crt; gnutls_pubkey_t pubkey; gnutls_privkey_t privkey; gnutls_sign_algorithm_t sign_algo; gnutls_datum_t signature; gnutls_datum_t signature2; int ret; size_t i; global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); for (i = 0; i < sizeof(key_dat) / sizeof(key_dat[0]); i++) { if (debug) success("loop %d\n", (int) i); ret = gnutls_x509_privkey_init(&key); if (ret < 0) fail("gnutls_x509_privkey_init\n"); ret = gnutls_x509_privkey_import(key, &key_dat[i], GNUTLS_X509_FMT_PEM); if (ret < 0) fail("gnutls_x509_privkey_import\n"); ret = gnutls_pubkey_init(&pubkey); if (ret < 0) fail("gnutls_privkey_init\n"); ret = gnutls_privkey_init(&privkey); if (ret < 0) fail("gnutls_pubkey_init\n"); ret = gnutls_privkey_import_x509(privkey, key, 0); if (ret < 0) fail("gnutls_privkey_import_x509\n"); ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, 0, &hash_data, &signature2); if (ret < 0) fail("gnutls_privkey_sign_hash\n"); ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &raw_data, &signature); if (ret < 0) fail("gnutls_x509_privkey_sign_hash\n"); ret = gnutls_x509_crt_init(&crt); if (ret < 0) fail("gnutls_x509_crt_init\n"); ret = gnutls_x509_crt_import(crt, &cert_dat[i], GNUTLS_X509_FMT_PEM); if (ret < 0) fail("gnutls_x509_crt_import\n"); ret = gnutls_pubkey_import_x509(pubkey, crt, 0); if (ret < 0) fail("gnutls_x509_pubkey_import\n"); ret = gnutls_x509_crt_get_signature_algorithm(crt); if (ret != GNUTLS_SIGN_RSA_SHA1) fail("gnutls_crt_get_signature_algorithm\n"); ret = gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &hash_data, &signature); if (ret < 0) fail("gnutls_x509_pubkey_verify_hash2\n"); ret = gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &hash_data, &signature2); if (ret < 0) fail("gnutls_x509_pubkey_verify_hash-1 (hashed data)\n"); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &invalid_hash_data, &signature2); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) fail("gnutls_x509_pubkey_verify_hash-2 (hashed data)\n"); sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm (pubkey, NULL), GNUTLS_DIG_SHA1); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &hash_data, &signature2); if (ret < 0) fail("gnutls_x509_pubkey_verify_hash2-1 (hashed data)\n"); /* should fail */ ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0, &invalid_hash_data, &signature2); if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) fail("gnutls_x509_pubkey_verify_hash2-2 (hashed data)\n"); /* test the raw interface */ gnutls_free(signature.data); signature.data = NULL; if (gnutls_pubkey_get_pk_algorithm(pubkey, NULL) == GNUTLS_PK_RSA) { ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &hash_data, &signature); if (ret < 0) fail("gnutls_privkey_sign_hash: %s\n", gnutls_strerror(ret)); sign_algo = gnutls_pk_to_sign (gnutls_pubkey_get_pk_algorithm(pubkey, NULL), GNUTLS_DIG_SHA1); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, &hash_data, &signature); if (ret < 0) fail("gnutls_pubkey_verify_hash-3 (raw hashed data)\n"); gnutls_free(signature.data); /* test the legacy API */ ret = gnutls_privkey_sign_raw_data(privkey, 0, &hash_data, &signature); if (ret < 0) fail("gnutls_privkey_sign_raw_data: %s\n", gnutls_strerror(ret)); ret = gnutls_pubkey_verify_hash2(pubkey, sign_algo, GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, &hash_data, &signature); if (ret < 0) fail("gnutls_pubkey_verify_hash-4 (legacy raw hashed data)\n"); } gnutls_free(signature.data); gnutls_free(signature2.data); gnutls_x509_privkey_deinit(key); gnutls_x509_crt_deinit(crt); gnutls_privkey_deinit(privkey); gnutls_pubkey_deinit(pubkey); } gnutls_global_deinit(); }