Example #1
0
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;
}
Example #2
0
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);
	}
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
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;
}
Example #6
0
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;
}
Example #7
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();
}