예제 #1
0
// 解読
SE_BUF *SeIkeDecrypt(void *data, UINT size, SE_IKE_CRYPTO_PARAM *cparam)
{
	void *tmp;
	SE_BUF *b;
	// 引数チェック
	if (data == NULL || cparam == NULL)
	{
		return NULL;
	}

	if ((size % SE_DES_BLOCK_SIZE) != 0)
	{
		// ブロックサイズの整数倍でない
		return NULL;
	}

	tmp = SeMalloc(size);
	SeDes3Decrypt(tmp, data, size, cparam->DesKey, cparam->Iv);

	if (size >= SE_DES_BLOCK_SIZE)
	{
		SeCopy(cparam->NextIv, ((UCHAR *)data) + (size - SE_DES_BLOCK_SIZE), SE_DES_BLOCK_SIZE);
	}
	else
	{
		SeZero(cparam->NextIv, SE_DES_BLOCK_SIZE);
	}

	b = SeMemToBuf(tmp, size);
	SeFree(tmp);

	return b;
}
예제 #2
0
static void
GetPhysicalNicInfo (void *handle, struct nicinfo *info)
{
	info->mtu = 1500;
	info->media_speed = 1000000000;
	SeCopy (info->mac_address, pro100_get_ctx()->mac_address, 6);
}
예제 #3
0
// 暗号化 (パディングも実行する)
SE_BUF *SeIkeEncryptWithPadding(void *data, UINT size, SE_IKE_CRYPTO_PARAM *cparam)
{
	UINT total_size;
	UINT i;
	UCHAR n = 0;
	UCHAR *tmp;
	SE_BUF *ret;
	// 引数チェック
	if (data == NULL || cparam == NULL)
	{
		return NULL;
	}

	total_size = ((size / SE_DES_BLOCK_SIZE) + ((size % SE_DES_BLOCK_SIZE) == 0 ? 0 : 1))
		* SE_DES_BLOCK_SIZE;
	if (total_size == 0)
	{
		total_size = SE_DES_BLOCK_SIZE;
	}

	tmp = SeMalloc(total_size);
	SeCopy(tmp, data, size);

	for (i = size;i < total_size;i++)
	{
		tmp[i] = ++n;
	}

	ret = SeIkeEncrypt(tmp, total_size, cparam);

	SeFree(tmp);

	return ret;
}
예제 #4
0
static void
GetVirtualNicInfo (SE_HANDLE nic_handle, SE_NICINFO *info)
{
	info->MediaType = SE_MEDIA_TYPE_ETHERNET;
	info->Mtu = 1500;
	info->MediaSpeed = 1000000000;
	SeCopy(info->MacAddress, pro100_get_ctx()->mac_address, 6);
}
예제 #5
0
// ETH の情報を取得
void SeEthGetInfo(SE_ETH *e, SE_NICINFO *info)
{
	// 引数チェック
	if (e == NULL || info == NULL)
	{
		return;
	}

	SeCopy(info, &e->Info, sizeof(SE_ETH));
}
예제 #6
0
// 物理的にパケットを送信する
void pro100_send_packet_to_line(PRO100_CTX *ctx, void *buf, UINT size)
{
	volatile PRO100_OP_BLOCK *b;
	PRO100_OP_TRANSMIT *t;
	phys_t ptr;
	// 引数チェック
	if (ctx == NULL || buf == NULL || size == 0)
	{
		return;
	}

	// メモリ確保
	b = pro100_alloc_page(&ptr);

	t = (PRO100_OP_TRANSMIT *)b;

	t->op_block.op = PRO100_CU_OP_TRANSMIT;
	t->op_block.transmit_flexible_mode = 0;
	t->op_block.transmit_raw_packet = 0;
	t->op_block.transmit_cid = 31;
	t->op_block.i = false;
	t->op_block.s = false;
	t->op_block.el = true;
	t->op_block.link_address = 0;
	t->tbd_array_address = 0xffffffff;
	t->data_bytes = size;
	t->threshold = 1;

	SeCopy(((UCHAR *)b) + sizeof(PRO100_OP_TRANSMIT) +
		(ctx->use_standard_txcb ? 0 : sizeof(PRO100_TBD) * 2), buf, size);

	if (false)
	{
		char tmp[8000];
		SeBinToStrEx(tmp, sizeof(tmp), (void *)b, size + sizeof(PRO100_OP_TRANSMIT));

		printf("%s\n\n", tmp);
	}

	pro100_init_cu_base_addr(ctx);
	pro100_wait_cu_ru_accepable(ctx);
	pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ptr, 4);
	pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, 
		PRO100_MAKE_CU_RU_COMMAND(PRO100_CU_CMD_START, PRO100_RU_CMD_NOOP), 1);
	pro100_flush(ctx);

	//printf("1\n");
	while (b->c == false);
	//printf("2\n");

	pro100_free_page((void *)b, ptr);
}
예제 #7
0
// 割り込みを発生させる
void pro100_generate_int(PRO100_CTX *ctx)
{
	PRO100_INT_BIT ib;
	// 引数チェック
	if (ctx == NULL)
	{
		return;
	}

	SeCopy(&ib, &ctx->int_mask_guest_set, sizeof(UINT));
	if (ib.mask_all != 0)
	{
		return;
	}

	ib.si = 1;

	//printf("*");
	pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_1, *((UINT *)(void *)&ib), 1);
}
예제 #8
0
// MAC アドレスをリストへ追加
void SeEthAddSenderMacList(SE_ETH *e, UCHAR *mac_address)
{
	// 引数チェック
	if (e == NULL || mac_address == NULL)
	{
		return;
	}

	SeLock(e->SenderMacListLock);
	{
		UINT i;
		bool exists = false;

		for (i = 0;i < SE_LIST_NUM(e->SenderMacList);i++)
		{
			SE_ETH_SENDER_MAC *m = SE_LIST_DATA(e->SenderMacList, i);

			if (SeCmp(m->MacAddress, mac_address, SE_ETHERNET_MAC_ADDR_SIZE) == 0)
			{
				m->Expires = SeTick64() + (UINT64)SE_ETH_SENDER_MAC_EXPIRES;

				exists = true;
			}
		}

		if (exists == false)
		{
			SE_ETH_SENDER_MAC *m = SeZeroMalloc(sizeof(SE_ETH_SENDER_MAC));

			m->Expires = SeTick64() + (UINT64)SE_ETH_SENDER_MAC_EXPIRES;

			SeCopy(m->MacAddress, mac_address, SE_ETHERNET_MAC_ADDR_SIZE);

			SeAdd(e->SenderMacList, m);
		}

		SeEthDeleteOldSenderMacList(e);
	}
	SeUnlock(e->SenderMacListLock);
}
예제 #9
0
// ランダムな MAC アドレスの生成
void SeEthGenRandMacAddress(UCHAR *mac_address, void *key, UINT key_size)
{
	UCHAR hash[SE_SHA1_HASH_SIZE];
	// 引数チェック
	if (mac_address == NULL)
	{
		return;
	}

	if (key == NULL || key_size == 0)
	{
		SeRand(hash, sizeof(hash));
	}
	else
	{
		SeSha1(hash, key, key_size);
	}

	SeCopy(mac_address, hash, SE_ETHERNET_MAC_ADDR_SIZE);

	mac_address[0] = 0x00;
	mac_address[1] = 0xAC;
}
예제 #10
0
// ゲスト OS が開始したオペレーションを処理する
void pro100_proc_guest_op(PRO100_CTX *ctx)
{
	phys_t ptr;
	// 引数チェック
	if (ctx == NULL)
	{
		return;
	}
	if (ctx->guest_cu_started == false || ctx->guest_cu_current_pointer == 0)
	{
		return;
	}

	ptr = ctx->guest_cu_current_pointer;

	// 終端まで読み取る
	while (true)
	{
		PRO100_OP_BLOCK_MAX b;

		if (ctx->guest_cu_suspended)
		{
			// サスペンド中の場合、前回の最後のオペレーションの S ビットがクリア
			// されたかどうか検査する
			pro100_mem_read(&b, ptr, sizeof(b));
			if (b.op_block.s)
			{
				// サスペンド継続中
				break;
			}

			ptr = ctx->guest_cu_next_pointer;

			ctx->guest_cu_suspended = false;
		}

		pro100_mem_read(&b, ptr, sizeof(b));

		if (b.op_block.op == PRO100_CU_OP_TRANSMIT)
		{
			// 送信処理
			PRO100_OP_TRANSMIT *t = (PRO100_OP_TRANSMIT *)&b;

			if (false)
			{
				printf("flexible_mode=%u, raw_packet=%u, cid=%u, array=0x%x, thres=%u, tcount=%u, size=%u\n",
					t->op_block.transmit_flexible_mode,
					t->op_block.transmit_raw_packet,
					t->op_block.transmit_cid,
					t->tbd_array_address,
					t->threshold,
					t->tbd_count,
					t->data_bytes);
			}

			//printf("SEND\n");

			if (false)
			{
				char tmp[4096];

				SeBinToStrEx(tmp, sizeof(tmp), &b, 24);
				printf("%s\n", tmp);
			}

			if (true)
			{
				UCHAR buf[PRO100_MAX_PACKET_SIZE];
				UINT packet_size = pro100_read_send_packet(ctx, ptr, buf);

#ifdef	PRO100_PASS_MODE
				pro100_write_recv_packet(ctx, buf, packet_size);
#else	// PRO100_PASS_MODE
				if (ctx->CallbackRecvVirtNic != NULL)
				{
					void *packet_data[1];
					UINT packet_sizes[1];

					packet_data[0] = buf;
					packet_sizes[0] = packet_size;
					ctx->CallbackRecvVirtNic(ctx, 1, packet_data, packet_sizes, ctx->CallbackRecvVirtNicParam);
				}
#endif	// PRO100_PASS_MODE
			}

			b.op_block.ok = b.op_block.c = true;
			b.op_block.transmit_overrun = false;

			pro100_mem_write(ptr, &b, sizeof(PRO100_OP_BLOCK) + sizeof(PRO100_OP_TRANSMIT));

			if (b.op_block.i)
			{
				pro100_generate_int(ctx);
			}
		}
		else
		{
			// 送信以外の処理
			UINT size = pro100_get_op_size(b.op_block.op, &b);

			//printf("0x%x: OP: %u  Size=%u\n", (UINT)ptr, b.op_block.op, size);

			switch (b.op_block.op)
			{
			case PRO100_CU_OP_IA_SETUP:
				// IA Setup
				SeCopy(ctx->mac_address, ((UCHAR *)&b) + sizeof(PRO100_OP_BLOCK), 6);
				pro100_init_vpn_client(ctx);
				break;

			case PRO100_CU_OP_CONFIG:
				// Configure
				ctx->use_standard_txcb = ((((UCHAR *)&b)[sizeof(PRO100_OP_BLOCK) + 6] & 0x10) ? true : false);
				break;
			}

			pro100_exec_cu_op(ctx, &b, size);

			pro100_mem_write(ptr, &b, size);
		}

		if (b.op_block.el)
		{
			// 終了フラグ
			ctx->guest_cu_started = false;
			ctx->guest_cu_current_pointer = 0;
			ctx->guest_cu_suspended = false;
			//printf("EL\n");
			pro100_generate_int(ctx);
			break;
		}
		if (b.op_block.s)
		{
			// サスペンドフラグ
			ctx->guest_cu_suspended = true;
			ctx->guest_cu_next_pointer = b.op_block.link_address;
			//printf("SUSPEND\n");
			pro100_generate_int(ctx);
			break;
		}

		ptr = b.op_block.link_address;
	}

	if (ctx->guest_cu_started)
	{
		ctx->guest_cu_current_pointer = ptr;
	}
}
예제 #11
0
// 送信しようとしているパケットを読み取る
UINT pro100_read_send_packet(PRO100_CTX *ctx, phys_t addr, void *buf)
{
	PRO100_OP_BLOCK_MAX b;
	PRO100_OP_TRANSMIT *t;
	UINT ret = 0;
	// 引数チェック
	if (ctx == NULL || addr == 0 || buf == NULL)
	{
		return 0;
	}

	// メモリから読み取る
	pro100_mem_read(&b, addr, sizeof(b));

	t = (PRO100_OP_TRANSMIT *)&b;

	if (t->op_block.transmit_flexible_mode == 0)
	{
		// Simplified モード
		ret = t->data_bytes;
		if (ret > PRO100_MAX_PACKET_SIZE)
		{
			// パケットサイズが大きすぎる
			return 0;
		}

		// パケットデータのコピー
		SeCopy(buf, ((UCHAR *)&b) + sizeof(PRO100_OP_TRANSMIT), ret);

		return ret;
	}
	else
	{
		UINT num_tbd = t->tbd_count;
		PRO100_TBD *tbd_array = SeZeroMalloc(num_tbd * sizeof(PRO100_TBD));
		UINT total_packet_size;
		UINT i;

		if (ctx->use_standard_txcb)
		{
			// Standard Flexible モード
			pro100_mem_read(tbd_array, (phys_t)t->tbd_array_address, num_tbd * sizeof(PRO100_TBD));
		}
		else
		{
			// Extended Flexible モード: 最初の 2 個を末尾から読む
			UINT num_tbd_ex = num_tbd;
			if (num_tbd_ex >= 2)
			{
				num_tbd_ex = 2;
			}
			SeCopy(tbd_array, ((UCHAR *)&b) + sizeof(PRO100_OP_TRANSMIT), num_tbd_ex * sizeof(PRO100_TBD));

			// 残りがある場合は TBD アレイアドレスから読み込む
			if ((num_tbd - num_tbd_ex) >= 1)
			{
				pro100_mem_read(((UCHAR *)tbd_array) + num_tbd_ex * sizeof(PRO100_TBD),
					(phys_t)t->tbd_array_address,
					(num_tbd - num_tbd_ex) * sizeof(PRO100_TBD));
			}
		}

		// TBD アレイアドレスを用いてパケットを読み込む
		total_packet_size = 0;

		for (i = 0;i < num_tbd;i++)
		{
			PRO100_TBD *tbd = &tbd_array[i];

			total_packet_size += tbd->size;
		}

		if (total_packet_size > PRO100_MAX_PACKET_SIZE)
		{
			// パケットサイズが大きすぎる
			ret = 0;
		}
		else
		{
			// パケットデータを読み込む
			UCHAR *current_ptr = buf;
			for (i = 0;i < num_tbd;i++)
			{
				PRO100_TBD *tbd = &tbd_array[i];

				pro100_mem_read(current_ptr, (phys_t)tbd->data_address, tbd->size);

				current_ptr += tbd->size;
			}

			ret = total_packet_size;
		}

		SeFree(tbd_array);

		return ret;
	}
}
예제 #12
0
// CU にオペレーションを実行させる
void pro100_exec_cu_op(PRO100_CTX *ctx, PRO100_OP_BLOCK_MAX *op, UINT size)
{
	volatile PRO100_OP_BLOCK *b;
	PRO100_OP_BLOCK *b2;
	phys_t ptr;
	bool src_el, src_s, src_i;
	UINT src_link_addr;
	bool timeouted;
	UINT64 start_tick;
	// 引数チェック
	if (ctx == NULL || op == NULL)
	{
		return;
	}

	// メモリ確保
	b = pro100_alloc_page(&ptr);

	// 一時領域にコピー
	SeCopy((void *)b, op, size);

	// バックアップ
	src_el = b->el;
	src_s = b->s;
	src_i = b->i;
	src_link_addr = b->link_address;

	// フラグセット
	b->el = true;
	b->s = false;
	//b->ok = b->c = false;
	b->link_address = ptr;
	//b->i = false;

	pro100_init_cu_base_addr(ctx);

	pro100_wait_cu_ru_accepable(ctx);

	if (false)
	{
		char tmp[4096];

		SeBinToStrEx(tmp, sizeof(tmp), (void *)b, size);
		printf("%s\n", tmp);
	}

	pro100_write(ctx, PRO100_CSR_OFFSET_SCB_GENERAL_POINTER, (UINT)ptr, 4);
	pro100_write(ctx, PRO100_CSR_OFFSET_SCB_COMMAND_WORD_0, 
		PRO100_MAKE_CU_RU_COMMAND(PRO100_CU_CMD_START, PRO100_RU_CMD_NOOP), 1);
	pro100_flush(ctx);

	// NIC がコマンドを完了するまで待機
	//printf("[");
	start_tick = SeTick64();
	timeouted = true;
	while ((start_tick + 1000ULL) >= SeTick64())
	{
		if (b->c)
		{
			timeouted = false;
			break;
		}
	}
	//printf("%u] ", b->c);
	//b->c = true;

	if (false)
	{
		UINT t = pro100_read(ctx, PRO100_CSR_OFFSET_SCB_STATUS_WORD_0, 1);
		PRO100_SCB_STATUS_WORD_BIT *b = (PRO100_SCB_STATUS_WORD_BIT *)(void *)&t;

		printf("STATUS  CU=%u, RU=%u\n", b->cu_status, b->ru_status);
	}

	// 結果を書き戻す
	SeCopy(op, (void *)b, size);
	b2 = (PRO100_OP_BLOCK *)op;

	// バックアップを復元
	b2->el = src_el;
	b2->s = src_s;
	b2->i = src_i;
	b2->link_address = src_link_addr;

	// メモリ解放
	pro100_free_page((void *)b, ptr);

	if (timeouted && src_i)
	{
		//pro100_generate_int(ctx);
	}
}
예제 #13
0
// パケットを受信したことにしてゲスト OS に渡す
void pro100_write_recv_packet(PRO100_CTX *ctx, void *buf, UINT size)
{
	PRO100_RFD rfd;
	phys_t ptr;
	// 引数チェック
	if (ctx == NULL || buf == NULL || size == 0)
	{
		return;
	}

	if (ctx->guest_rfd_current == 0)
	{
		// ゲスト OS が RFD のアドレスを指定していない
		return;
	}
/*
	if (ctx->guest_ru_suspended)
	{
		// ゲスト OS によって RU がサスペンドされている
		return;
	}*/

	// 現在の RFD バッファの内容をチェックする
	ptr = ctx->guest_rfd_current;
	pro100_mem_read(&rfd, ptr, sizeof(PRO100_RFD));

	if (rfd.eof)
	{
		// EOF ビットが有効になっているためこの RFD にはデータを受信できない
		return;
	}

	// RFD にデータを書き込む
	rfd.status = 0;
	rfd.sf = rfd.h = 0;

	SeCopy(rfd.data, buf, size);

	rfd.recved_bytes = size;
	rfd.f = 1;
	rfd.ok	= 1;
	rfd.c = 1;
	rfd.eof = 1;

	// ビットチェック
	if (rfd.el)
	{
		// これが最後の RFD である
		ctx->guest_rfd_current = ctx->guest_rfd_first = 0;
	}
	else
	{
		// 次の RFD のリンクアドレスを取得する
		ctx->guest_rfd_current = rfd.link_address;
		if (ctx->guest_rfd_current == 0xffffffff)
		{
			ctx->guest_rfd_current = 0;
		}

		if (rfd.s)
		{
			ctx->guest_ru_suspended = true;
		}
	}

	pro100_mem_write(ptr, &rfd, sizeof(PRO100_RFD));

	// 割り込み発生
	pro100_generate_int(ctx);
}
예제 #14
0
파일: crypt.c 프로젝트: imgits/rkanalyzer
// 提供システムコール: RSA 署名操作
bool
crypt_sys_rsa_sign (void *key_data, UINT key_size, void *data, UINT data_size,
		    void *sign, UINT *sign_buf_size)
{
	SE_BUF *ret_buf;
	SE_KEY *key;
	SE_BUF *key_file_buf;
	SE_BUF *tmp_buf;

	// 引数チェック
	if (key_data == NULL || data == NULL || data_size == 0 || sign == NULL || sign_buf_size == NULL)
	{
		return false;
	}

	// 秘密鍵データのコピー
	key_file_buf = SeNewBuf();
	SeWriteBuf(key_file_buf, key_data, key_size);

	tmp_buf = SeMemToBuf(key_file_buf->Buf, key_file_buf->Size);
	SeFreeBuf(key_file_buf);

	key = SeBufToKey(tmp_buf, true, true, NULL);

	if (key == NULL)
	{
		key = SeBufToKey(tmp_buf, true, false, NULL);
	}

	if (key == NULL)
	{
		chelp_printf("crypt.c: Loading Key Failed.\n");
		SeFreeBuf(tmp_buf);
		*sign_buf_size = 0;
		return false;
	}

	SeFreeBuf(tmp_buf);

	ret_buf = SeRsaSignWithPadding(data, data_size, key);
	if (ret_buf == NULL)
	{
		chelp_printf("crypt.c: SeRsaSignWithPadding() Failed.\n");
		SeFreeKey(key);
		*sign_buf_size = 0;
		return false;
	}

	if (*sign_buf_size < ret_buf->Size)
	{
		chelp_printf("crypt.c: Not Enough Buffer Space.\n");
		*sign_buf_size = ret_buf->Size;
		SeFreeBuf(ret_buf);
		SeFreeKey(key);
		*sign_buf_size = ret_buf->Size;
		return false;
	}

	*sign_buf_size = ret_buf->Size;

	SeCopy(sign, ret_buf->Buf, ret_buf->Size);
	SeFreeBuf(ret_buf);
	SeFreeKey(key);

	return true;
}