Blob PrivateKey::decrypt(const Blob& cipher) const { if (!key) throw CryptoException("Can't decrypt data without private key !"); unsigned key_len = 0; int err = gnutls_privkey_get_pk_algorithm(key, &key_len); if (err < 0) throw CryptoException("Can't read public key length !"); if (err != GNUTLS_PK_RSA) throw CryptoException("Must be an RSA key"); unsigned cypher_block_sz = key_len / 8; if (cipher.size() % cypher_block_sz) throw CryptoException("Unexpected cipher length"); Blob ret; for (auto cb = cipher.cbegin(), ce = cipher.cend(); cb < ce; cb += cypher_block_sz) { const gnutls_datum_t dat {(uint8_t*)(&(*cb)), cypher_block_sz}; gnutls_datum_t out; int err = gnutls_privkey_decrypt_data(key, 0, &dat, &out); if (err != GNUTLS_E_SUCCESS) throw DhtException(std::string("Can't decrypt data: ") + gnutls_strerror(err)); ret.insert(ret.end(), out.data, out.data+out.size); gnutls_free(out.data); } return ret; }
void sec_mod_server(struct cfg_st* config, const char* socket_file) { struct sockaddr_un sa; socklen_t sa_len; int cfd, ret, e; unsigned i, buffer_size, type; gnutls_privkey_t *key; uint8_t *buffer; unsigned key_size = config->key_size; struct pin_st pins; gnutls_datum_t data, out; uint16_t length; struct iovec iov[2]; int sd; #if defined(SO_PEERCRED) && defined(HAVE_STRUCT_UCRED) struct ucred cr; socklen_t cr_len; #endif ocsignal(SIGHUP, SIG_IGN); ocsignal(SIGINT, SIG_DFL); ocsignal(SIGTERM, SIG_DFL); #ifdef HAVE_PKCS11 ret = gnutls_pkcs11_reinit(); if (ret < 0) { syslog(LOG_WARNING, "error in PKCS #11 reinitialization: %s", gnutls_strerror(ret)); } #endif buffer_size = 8*1024; buffer = malloc(buffer_size); if (buffer == NULL) { syslog(LOG_ERR, "error in memory allocation"); exit(1); } memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file); remove(socket_file); sd = socket(AF_UNIX, SOCK_STREAM, 0); if (sd == -1) { e = errno; syslog(LOG_ERR, "could not create socket '%s': %s", socket_file, strerror(e)); exit(1); } umask(066); ret = bind(sd, (struct sockaddr *)&sa, SUN_LEN(&sa)); if (ret == -1) { e = errno; syslog(LOG_ERR, "could not bind socket '%s': %s", socket_file, strerror(e)); exit(1); } ret = chown(socket_file, config->uid, config->gid); if (ret == -1) { e = errno; syslog(LOG_ERR, "could not chown socket '%s': %s", socket_file, strerror(e)); } ret = listen(sd, 1024); if (ret == -1) { e = errno; syslog(LOG_ERR, "could not listen to socket '%s': %s", socket_file, strerror(e)); exit(1); } ret = load_pins(config, &pins); if (ret < 0) { syslog(LOG_ERR, "error loading PIN files"); exit(1); } key = malloc(sizeof(*key)*config->key_size); if (key == NULL) { syslog(LOG_ERR, "error in memory allocation"); exit(1); } /* read private keys */ for (i=0;i<key_size;i++) { ret = gnutls_privkey_init(&key[i]); GNUTLS_FATAL_ERR(ret); /* load the private key */ if (gnutls_url_is_supported(config->key[i]) != 0) { gnutls_privkey_set_pin_function (key[i], pin_callback, &pins); ret = gnutls_privkey_import_url(key[i], config->key[i], 0); GNUTLS_FATAL_ERR(ret); } else { ret = gnutls_load_file(config->key[i], &data); if (ret < 0) { syslog(LOG_ERR, "error loading file '%s'", config->key[i]); GNUTLS_FATAL_ERR(ret); } ret = gnutls_privkey_import_x509_raw(key[i], &data, GNUTLS_X509_FMT_PEM, NULL, 0); GNUTLS_FATAL_ERR(ret); gnutls_free(data.data); } } syslog(LOG_INFO, "sec-mod initialized (socket: %s)", socket_file); for (;;) { sa_len = sizeof(sa); cfd = accept(sd, (struct sockaddr *)&sa, &sa_len); if (cfd == -1) { e = errno; syslog(LOG_ERR, "sec-mod error accepting connection: %s", strerror(e)); continue; } #if defined(SO_PEERCRED) && defined(HAVE_STRUCT_UCRED) cr_len = sizeof(cr); ret = getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len); if (ret == -1) { e = errno; syslog(LOG_ERR, "sec-mod error obtaining peer credentials: %s", strerror(e)); goto cont; } syslog(LOG_DEBUG, "sec-mod received request from pid %u and uid %u", (unsigned)cr.pid, (unsigned)cr.uid); if (cr.uid != config->uid || cr.gid != config->gid) { syslog(LOG_ERR, "sec-mod received unauthorized request from pid %u and uid %u", (unsigned)cr.pid, (unsigned)cr.uid); goto cont; } #endif /* read request */ ret = recv(cfd, buffer, buffer_size, 0); if (ret == 0) goto cont; else if (ret <= 2) { e = errno; syslog(LOG_ERR, "error receiving sec-mod data: %s", strerror(e)); goto cont; } /* calculate */ i = buffer[0]; type = buffer[1]; if (i >= key_size) { syslog(LOG_ERR, "sec-mod received out-of-bounds key index"); goto cont; } data.data = &buffer[2]; data.size = ret - 2; if (type == 'S') { #if GNUTLS_VERSION_NUMBER >= 0x030200 ret = gnutls_privkey_sign_hash(key[i], 0, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &data, &out); #else ret = gnutls_privkey_sign_raw_data(key[i], 0, &data, &out); #endif } else if (type == 'D') { ret = gnutls_privkey_decrypt_data(key[i], 0, &data, &out); } else { syslog(LOG_ERR, "unknown type 0x%.2x", type); goto cont; } if (ret < 0) { syslog(LOG_ERR, "sec-mod error in crypto operation: %s", gnutls_strerror(ret)); goto cont; } /* write reply */ length = out.size; iov[0].iov_base = &length; iov[0].iov_len = 2; iov[1].iov_base = out.data; iov[1].iov_len = out.size; ret = writev(cfd, iov, 2); if (ret == -1) { e = errno; syslog(LOG_ERR, "sec-mod error in writev: %s", strerror(e)); } gnutls_free(out.data); cont: close(cfd); } }
static int proc_rsa_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { gnutls_datum_t plaintext; gnutls_datum_t ciphertext; int ret, dsize; int use_rnd_key = 0; ssize_t data_size = _data_size; gnutls_datum_t rndkey = {NULL, 0}; if (get_num_version(session) == GNUTLS_SSL3) { /* SSL 3.0 */ ciphertext.data = data; ciphertext.size = data_size; } else { /* TLS 1.0 */ DECR_LEN(data_size, 2); ciphertext.data = &data[2]; dsize = _gnutls_read_uint16(data); if (dsize != data_size) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } ciphertext.size = dsize; } rndkey.size = GNUTLS_MASTER_SIZE; rndkey.data = gnutls_malloc(rndkey.size); if (rndkey.data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } /* we do not need strong random numbers here. */ ret = _gnutls_rnd(GNUTLS_RND_NONCE, rndkey.data, rndkey.size); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_privkey_decrypt_data(session->internals.selected_key, 0, &ciphertext, &plaintext); if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) { /* In case decryption fails then don't inform * the peer. Just use a random key. (in order to avoid * attack against pkcs-1 formating). */ _gnutls_debug_log("auth_rsa: Possible PKCS #1 format attack\n"); use_rnd_key = 1; } else { /* If the secret was properly formatted, then * check the version number. */ if (_gnutls_get_adv_version_major(session) != plaintext.data[0] || (session->internals.priorities.allow_wrong_pms == 0 && _gnutls_get_adv_version_minor(session) != plaintext.data[1])) { /* No error is returned here, if the version number check * fails. We proceed normally. * That is to defend against the attack described in the paper * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, * Ondej Pokorny and Tomas Rosa. */ _gnutls_debug_log("auth_rsa: Possible PKCS #1 version check format attack\n"); } } if (use_rnd_key != 0) { session->key.key.data = rndkey.data; session->key.key.size = rndkey.size; rndkey.data = NULL; } else { session->key.key.data = plaintext.data; session->key.key.size = plaintext.size; } /* This is here to avoid the version check attack * discussed above. */ session->key.key.data[0] = _gnutls_get_adv_version_major(session); session->key.key.data[1] = _gnutls_get_adv_version_minor(session); ret = 0; cleanup: gnutls_free(rndkey.data); return ret; }
int tls_process_record_handshake(struct SSLConnection *conn, const opaque *fragment) { struct Handshake *handshake; struct ClientHello *clienthello; struct ServerHello *serverhello; struct ClientKeyExchange *clientkeyex; const opaque *body; // Get Handshake data handshake = (struct Handshake *) fragment; if (UINT24_INT(handshake->length) > 0) { // Hanshake body pointer body = fragment + sizeof(struct Handshake); switch (handshake->type) { case hello_request: break; case client_hello: // Store client random clienthello = (struct ClientHello *) body; memcpy(&conn->client_random, &clienthello->random, sizeof(struct Random)); // Check we have a TLS handshake if (!(clienthello->client_version.major == 0x03 && clienthello->client_version.minor == 0x01)) { tls_connection_destroy(conn); return 1; } break; case server_hello: // Store server random serverhello = (struct ServerHello *) body; memcpy(&conn->server_random, &serverhello->random, sizeof(struct Random)); // Get the selected cipher memcpy(&conn->cipher_suite, body + sizeof(struct ServerHello) + serverhello->session_id_length, sizeof(uint16_t)); // Check if we have a handled cipher if (tls_connection_load_cipher(conn) != 0) { tls_connection_destroy(conn); return 1; } break; case certificate: case certificate_request: case server_hello_done: case certificate_verify: break; case client_key_exchange: // Decrypt PreMasterKey clientkeyex = (struct ClientKeyExchange *) body; gnutls_datum_t exkeys, pms; exkeys.size = UINT16_INT(clientkeyex->length); exkeys.data = (unsigned char *)&clientkeyex->exchange_keys; gnutls_privkey_decrypt_data(conn->server_private_key, 0, &exkeys, &pms); memcpy(&conn->pre_master_secret, pms.data, pms.size); // Get MasterSecret unsigned char *seed = sng_malloc(sizeof(struct Random) * 2); memcpy(seed, &conn->client_random, sizeof(struct Random)); memcpy(seed + sizeof(struct Random), &conn->server_random, sizeof(struct Random)); PRF((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret), (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret), (unsigned char *) "master secret", seed, sizeof(struct Random) * 2); memcpy(seed, &conn->server_random, sizeof(struct Random)); memcpy(seed + sizeof(struct Random), &conn->client_random, sizeof(struct Random)); // Generate MACs, Write Keys and IVs PRF((unsigned char *) &conn->key_material, sizeof(struct tls_data), (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret), (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2); // Done with the seed sng_free(seed); // Create Client decoder gcry_cipher_open(&conn->client_cipher_ctx, conn->ciph, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(conn->client_cipher_ctx, conn->key_material.client_write_key, gcry_cipher_get_algo_keylen(conn->ciph)); gcry_cipher_setiv(conn->client_cipher_ctx, conn->key_material.client_write_IV, gcry_cipher_get_algo_blklen(conn->ciph)); // Create Server decoder gcry_cipher_open(&conn->server_cipher_ctx, conn->ciph, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(conn->server_cipher_ctx, conn->key_material.server_write_key, gcry_cipher_get_algo_keylen(conn->ciph)); gcry_cipher_setiv(conn->server_cipher_ctx, conn->key_material.server_write_IV, gcry_cipher_get_algo_blklen(conn->ciph)); break; case finished: break; default: if (conn->encrypted) { // Encrypted Hanshake Message unsigned char *decoded = sng_malloc(48); uint32_t decodedlen; tls_process_record_data(conn, fragment, 48, &decoded, &decodedlen); sng_free(decoded); } break; } } return 0; }
/* Process the client key exchange message */ static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { gnutls_datum_t username; psk_auth_info_t info; gnutls_datum_t plaintext; gnutls_datum_t ciphertext; gnutls_datum_t pwd_psk = { NULL, 0 }; int ret, dsize; int randomize_key = 0; ssize_t data_size = _data_size; gnutls_psk_server_credentials_t cred; gnutls_datum_t premaster_secret = { NULL, 0 }; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); if (ret < 0) { gnutls_assert(); return ret; } /*** 1. Extract user psk_identity ***/ DECR_LEN(data_size, 2); username.size = _gnutls_read_uint16(&data[0]); DECR_LEN(data_size, username.size); username.data = &data[2]; /* copy the username to the auth info structures */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if (username.size > MAX_USERNAME_SIZE) { gnutls_assert(); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy(info->username, username.data, username.size); info->username[username.size] = 0; /* Adjust data so it points to EncryptedPreMasterSecret */ data += username.size + 2; /*** 2. Decrypt and extract EncryptedPreMasterSecret ***/ DECR_LEN(data_size, 2); ciphertext.data = &data[2]; dsize = _gnutls_read_uint16(data); if (dsize != data_size) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } ciphertext.size = dsize; ret = gnutls_privkey_decrypt_data(session->internals.selected_key, 0, &ciphertext, &plaintext); if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) { /* In case decryption fails then don't inform * the peer. Just use a random key. (in order to avoid * attack against pkcs-1 formatting). */ gnutls_assert(); _gnutls_debug_log ("auth_rsa_psk: Possible PKCS #1 format attack\n"); if (ret >= 0) { gnutls_free(plaintext.data); } randomize_key = 1; } else { /* If the secret was properly formatted, then * check the version number. */ if (_gnutls_get_adv_version_major(session) != plaintext.data[0] || (session->internals.allow_wrong_pms == 0 && _gnutls_get_adv_version_minor(session) != plaintext.data[1])) { /* No error is returned here, if the version number check * fails. We proceed normally. * That is to defend against the attack described in the paper * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, * Ondej Pokorny and Tomas Rosa. */ gnutls_assert(); _gnutls_debug_log ("auth_rsa: Possible PKCS #1 version check format attack\n"); } } if (randomize_key != 0) { premaster_secret.size = GNUTLS_MASTER_SIZE; premaster_secret.data = gnutls_malloc(premaster_secret.size); if (premaster_secret.data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } /* we do not need strong random numbers here. */ ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data, premaster_secret.size); if (ret < 0) { gnutls_assert(); goto cleanup; } } else { premaster_secret.data = plaintext.data; premaster_secret.size = plaintext.size; } /* This is here to avoid the version check attack * discussed above. */ premaster_secret.data[0] = _gnutls_get_adv_version_major(session); premaster_secret.data[1] = _gnutls_get_adv_version_minor(session); /* find the key of this username */ ret = _gnutls_psk_pwd_find_entry(session, info->username, &pwd_psk); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = set_rsa_psk_session_key(session, &pwd_psk, &premaster_secret); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: _gnutls_free_key_datum(&pwd_psk); _gnutls_free_temp_key_datum(&premaster_secret); return ret; }
static int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st * sec, cmd_request_t cmd, uint8_t * buffer, size_t buffer_size) { unsigned i; gnutls_datum_t data, out; int ret; SecOpMsg *op; PROTOBUF_ALLOCATOR(pa, pool); seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size, cmd_request_to_str(cmd)); data.data = buffer; data.size = buffer_size; switch (cmd) { case CMD_SEC_SIGN: case CMD_SEC_DECRYPT: op = sec_op_msg__unpack(&pa, data.size, data.data); if (op == NULL) { seclog(sec, LOG_INFO, "error unpacking sec op\n"); return -1; } i = op->key_idx; if (op->has_key_idx == 0 || i >= sec->key_size) { seclog(sec, LOG_INFO, "received out-of-bounds key index (%d)", i); return -1; } data.data = op->data.data; data.size = op->data.len; if (cmd == CMD_SEC_DECRYPT) { ret = gnutls_privkey_decrypt_data(sec->key[i], 0, &data, &out); } else { #if GNUTLS_VERSION_NUMBER >= 0x030200 ret = gnutls_privkey_sign_hash(sec->key[i], 0, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &data, &out); #else ret = gnutls_privkey_sign_raw_data(sec->key[i], 0, &data, &out); #endif } sec_op_msg__free_unpacked(op, &pa); if (ret < 0) { seclog(sec, LOG_INFO, "error in crypto operation: %s", gnutls_strerror(ret)); return -1; } ret = handle_op(pool, cfd, sec, cmd, out.data, out.size); gnutls_free(out.data); return ret; case CMD_SEC_CLI_STATS:{ CliStatsMsg *tmsg; tmsg = cli_stats_msg__unpack(&pa, data.size, data.data); if (tmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return -1; } ret = handle_sec_auth_stats_cmd(sec, tmsg, pid); cli_stats_msg__free_unpacked(tmsg, &pa); return ret; } break; case CMD_SEC_AUTH_INIT:{ SecAuthInitMsg *auth_init; auth_init = sec_auth_init_msg__unpack(&pa, data.size, data.data); if (auth_init == NULL) { seclog(sec, LOG_INFO, "error unpacking auth init\n"); return -1; } ret = handle_sec_auth_init(cfd, sec, auth_init, pid); sec_auth_init_msg__free_unpacked(auth_init, &pa); return ret; } case CMD_SEC_AUTH_CONT:{ SecAuthContMsg *auth_cont; auth_cont = sec_auth_cont_msg__unpack(&pa, data.size, data.data); if (auth_cont == NULL) { seclog(sec, LOG_INFO, "error unpacking auth cont\n"); return -1; } ret = handle_sec_auth_cont(cfd, sec, auth_cont); sec_auth_cont_msg__free_unpacked(auth_cont, &pa); return ret; } case RESUME_STORE_REQ:{ SessionResumeStoreReqMsg *smsg; smsg = session_resume_store_req_msg__unpack(&pa, buffer_size, buffer); if (smsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_store_req(sec, smsg); /* zeroize the data */ safe_memset(buffer, 0, buffer_size); safe_memset(smsg->session_data.data, 0, smsg->session_data.len); session_resume_store_req_msg__free_unpacked(smsg, &pa); if (ret < 0) { seclog(sec, LOG_DEBUG, "could not store resumption data"); } } break; case RESUME_DELETE_REQ:{ SessionResumeFetchMsg *fmsg; fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size, buffer); if (fmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_delete_req(sec, fmsg); session_resume_fetch_msg__free_unpacked(fmsg, &pa); if (ret < 0) { seclog(sec, LOG_DEBUG, "could not delete resumption data."); } } break; case RESUME_FETCH_REQ:{ SessionResumeReplyMsg msg = SESSION_RESUME_REPLY_MSG__INIT; SessionResumeFetchMsg *fmsg; /* FIXME: rate limit that */ fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size, buffer); if (fmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_fetch_req(sec, fmsg, &msg); session_resume_fetch_msg__free_unpacked(fmsg, &pa); if (ret < 0) { msg.reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED; seclog(sec, LOG_DEBUG, "could not fetch resumption data."); } else { msg.reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__OK; } ret = send_msg(pool, cfd, RESUME_FETCH_REP, &msg, (pack_size_func) session_resume_reply_msg__get_packed_size, (pack_func) session_resume_reply_msg__pack); if (ret < 0) { seclog(sec, LOG_ERR, "could not send reply cmd %d.", (unsigned)cmd); return ERR_BAD_COMMAND; } } break; default: seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd); return -1; } return 0; }
void doit(void) { gnutls_x509_privkey_t key; gnutls_x509_crt_t crt; gnutls_pubkey_t pubkey; gnutls_privkey_t privkey; gnutls_datum_t out, out2; int ret; size_t i; global_init(); 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_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_pubkey_encrypt_data(pubkey, 0, &hash_data, &out); if (ret < 0) fail("gnutls_pubkey_encrypt_data\n"); ret = gnutls_privkey_decrypt_data(privkey, 0, &out, &out2); if (ret < 0) fail("gnutls_privkey_decrypt_data\n"); if (out2.size != hash_data.size) fail("Decrypted data don't match original (1)\n"); if (memcmp(out2.data, hash_data.data, hash_data.size) != 0) fail("Decrypted data don't match original (2)\n"); gnutls_free(out.data); gnutls_free(out2.data); ret = gnutls_pubkey_encrypt_data(pubkey, 0, &raw_data, &out); if (ret < 0) fail("gnutls_pubkey_encrypt_data\n"); ret = gnutls_privkey_decrypt_data(privkey, 0, &out, &out2); if (ret < 0) fail("gnutls_privkey_decrypt_data\n"); if (out2.size != raw_data.size) fail("Decrypted data don't match original (3)\n"); if (memcmp(out2.data, raw_data.data, raw_data.size) != 0) fail("Decrypted data don't match original (4)\n"); if (debug) success("ok\n"); gnutls_free(out.data); gnutls_free(out2.data); gnutls_x509_privkey_deinit(key); gnutls_x509_crt_deinit(crt); gnutls_privkey_deinit(privkey); gnutls_pubkey_deinit(pubkey); } gnutls_global_deinit(); }