Ejemplo n.º 1
0
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context)
{
	wStream* s;
	AV_PAIR* restrictions = &context->av_pairs->Restrictions;

	BYTE machineID[32] =
		"\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43"
		"\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20";

	restrictions->value = malloc(48);
	restrictions->length = 48;

	s = PStreamAllocAttach(restrictions->value, restrictions->length);

	Stream_Write_UINT32(s, 48); /* Size */
	Stream_Zero(s, 4); /* Z4 (set to zero) */

	/* IntegrityLevel (bit 31 set to 1) */
	Stream_Write_UINT8(s, 1);
	Stream_Zero(s, 3);

	Stream_Write_UINT32(s, 0x00002000); /* SubjectIntegrityLevel */
	Stream_Write(s, machineID, 32); /* MachineID */

	PStreamFreeDetach(s);
}
Ejemplo n.º 2
0
static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
{
	SERIAL_TTY* tty;

	tty = serial->tty;

	if (tty == NULL)
	{
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		DEBUG_WARN("tty not valid.");
	}
	else
	{
		DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);

		TerminateThread(serial->mthread, 0);
		WaitForSingleObject(serial->mthread, INFINITE);
		CloseHandle(serial->mthread);
		serial->mthread = NULL;

		serial_tty_free(tty);
		serial->tty = NULL;
	}

	Stream_Zero(irp->output, 5); /* Padding(5) */

	irp->Complete(irp);
}
Ejemplo n.º 3
0
int cliprdr_temp_directory(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory)
{
	int length;
	wStream* s;
	WCHAR* wszTempDir = NULL;
	cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;

	s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2);

	length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, 0);

	if (length < 0)
		return -1;

	if (length > 520)
		length = 520;

	Stream_Write(s, tempDirectory->szTempDir, length * 2);
	Stream_Zero(s, (520 - length) * 2);

	free(wszTempDir);

	WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
			tempDirectory->szTempDir);

	cliprdr_packet_send(cliprdr, s);

	return 1;
}
Ejemplo n.º 4
0
static UINT video_control_send_client_notification(VideoClientContext *context, TSMM_CLIENT_NOTIFICATION *notif)
{
	BYTE buf[100];
	wStream *s;
	VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)context->handle;
	IWTSVirtualChannel* channel;
	UINT ret;
	UINT32 cbSize;

	s = Stream_New(buf, 30);
	if (!s)
		return CHANNEL_RC_NO_MEMORY;

	cbSize = 16;
	Stream_Seek_UINT32(s); /* cbSize */
	Stream_Write_UINT32(s, TSMM_PACKET_TYPE_CLIENT_NOTIFICATION); /* PacketType */
	Stream_Write_UINT8(s, notif->PresentationId);
	Stream_Write_UINT8(s, notif->NotificationType);
	Stream_Zero(s, 2);
	if (notif->NotificationType == TSMM_CLIENT_NOTIFICATION_TYPE_FRAMERATE_OVERRIDE)
	{
		Stream_Write_UINT32(s, 16); /* cbData */

		/* TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE */
		Stream_Write_UINT32(s, notif->FramerateOverride.Flags);
		Stream_Write_UINT32(s, notif->FramerateOverride.DesiredFrameRate);
		Stream_Zero(s, 4 * 2);

		cbSize += 4 * 4;
	}
	else
	{
		Stream_Write_UINT32(s, 0); /* cbData */
	}

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);
	Stream_Write_UINT32(s, cbSize);
	Stream_Free(s, FALSE);

	channel = video->control_callback->channel_callback->channel;
	ret = channel->Write(channel, cbSize, buf, NULL);

	return ret;
}
Ejemplo n.º 5
0
static void update_send_synchronize(rdpContext* context)
{
	wStream* s;
	rdpRdp* rdp = context->rdp;

	s = fastpath_update_pdu_init(rdp->fastpath);
	Stream_Zero(s, 2); /* pad2Octets (2 bytes) */
	fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s);
	Stream_Release(s);
}
Ejemplo n.º 6
0
static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{
	if (close(parallel->file) < 0)
		DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id);
	else
		DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id);

	Stream_Zero(irp->output, 5); /* Padding(5) */

	irp->Complete(irp);
}
Ejemplo n.º 7
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{
	if (close(parallel->file) < 0)
	{
	}
	else
	{
	}

	Stream_Zero(irp->output, 5); /* Padding(5) */
	return irp->Complete(irp);
}
Ejemplo n.º 8
0
void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* input_stream,
        int file_id, int completion_id) {

    wStream* output_stream = guac_rdpdr_new_io_completion(device,
            completion_id, STATUS_NOT_SUPPORTED, 5);

    guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
            "%s: [file_id=%i] Lock not supported",
            __func__, file_id);

    Stream_Zero(output_stream, 5); /* Padding */

    svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);

}
Ejemplo n.º 9
0
static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
{
	Stream_Seek(irp->input, 32); /* Padding (32 bytes) */

	if (!CloseHandle(serial->hComm))
	{
		WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%d) closed.",
		           serial->device.name, irp->device->id);
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		goto error_handle;
	}

	WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) closed.",
	           serial->device.name, irp->device->id, irp->FileId);
	serial->hComm = NULL;
	irp->IoStatus = STATUS_SUCCESS;
error_handle:
	Stream_Zero(irp->output, 5); /* Padding (5 bytes) */
}
Ejemplo n.º 10
0
static UINT32 smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, GetAttrib_Call* call)
{
	LONG status;
	DWORD cbAttrLen;
	GetAttrib_Return ret;
	IRP* irp = operation->irp;

	ret.pbAttr = NULL;

	if (call->fpbAttrIsNULL)
		call->cbAttrLen = 0;

	if (call->cbAttrLen)
		ret.pbAttr = (BYTE*) malloc(call->cbAttrLen);

	cbAttrLen = call->cbAttrLen;

	status = ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId, ret.pbAttr, &cbAttrLen);

	ret.cbAttrLen = cbAttrLen;

	smartcard_trace_get_attrib_return(smartcard, &ret, call->dwAttrId);

	if (ret.ReturnCode)
	{
		WLog_Print(smartcard->log, WLOG_WARN,
				"SCardGetAttrib: %s (0x%08X) cbAttrLen: %d\n",
				SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);

		Stream_Zero(irp->output, 256);
		return ret.ReturnCode;
	}

	status = smartcard_pack_get_attrib_return(smartcard, irp->output, &ret);

	if (status != SCARD_S_SUCCESS)
		return status;

	free(ret.pbAttr);

	return ret.ReturnCode;
}
Ejemplo n.º 11
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
{
	void* key;
	DRIVE_FILE* file;
	file = drive_get_file_by_id(drive, irp->FileId);
	key = (void*)(size_t) irp->FileId;

	if (!file)
	{
		irp->IoStatus = STATUS_UNSUCCESSFUL;
	}
	else
	{
		ListDictionary_Remove(drive->files, key);
		drive_file_free(file);
	}

	Stream_Zero(irp->output, 5); /* Padding(5) */
	return irp->Complete(irp);
}
Ejemplo n.º 12
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
{
	rdpPrintJob* printjob = NULL;

	if (printer_dev->printer)
		printjob = printer_dev->printer->FindPrintJob(printer_dev->printer,
		           irp->FileId);

	if (!printjob)
	{
		irp->IoStatus = STATUS_UNSUCCESSFUL;
	}
	else
	{
		printjob->Close(printjob);
	}

	Stream_Zero(irp->output, 4); /* Padding(4) */
	return irp->Complete(irp);
}
Ejemplo n.º 13
0
void license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob, UINT32 ModulusLength)
{
	UINT32 length;

	length = ModulusLength + 8;

	if (blob->length > ModulusLength)
	{
		fprintf(stderr, "license_write_encrypted_premaster_secret_blob: invalid blob\n");
		return;
	}

	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
	Stream_Write_UINT16(s, length); /* wBlobLen (2 bytes) */

	if (blob->length > 0)
		Stream_Write(s, blob->data, blob->length); /* blobData */

	Stream_Zero(s, length - blob->length);
}
Ejemplo n.º 14
0
void license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob, UINT32 ModulusLength)
{
	UINT32 length;
	length = ModulusLength + 8;

	if (blob->length > ModulusLength)
	{
		WLog_ERR(TAG, "license_write_encrypted_premaster_secret_blob: invalid blob");
		return;
	}

	Stream_EnsureRemainingCapacity(s, length + 4);
	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
	Stream_Write_UINT16(s, length); /* wBlobLen (2 bytes) */

	if (blob->length > 0)
		Stream_Write(s, blob->data, blob->length); /* blobData */

	Stream_Zero(s, length - blob->length);
}
Ejemplo n.º 15
0
static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
{
	SERIAL_TTY* tty;

	tty = serial->tty;

	if (tty == NULL)
	{
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		DEBUG_WARN("tty not valid.");
	}
	else
	{
		DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);

		serial_tty_free(tty);
		serial->tty = NULL;
	}

	Stream_Zero(irp->output, 5); /* Padding(5) */

	irp->Complete(irp);
}
Ejemplo n.º 16
0
static UINT serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
{
	if (Stream_GetRemainingLength(irp->input) < 32)
		return ERROR_INVALID_DATA;

	Stream_Seek(irp->input, 32); /* Padding (32 bytes) */

	if (!CloseHandle(serial->hComm))
	{
		WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%"PRIu32") closed.",
		           serial->device.name, irp->device->id);
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		goto error_handle;
	}

	WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %"PRIu32", FileId: %"PRIu32") closed.",
	           serial->device.name, irp->device->id, irp->FileId);
	serial->hComm = NULL;
	irp->IoStatus = STATUS_SUCCESS;
error_handle:
	Stream_Zero(irp->output, 5); /* Padding (5 bytes) */
	return CHANNEL_RC_OK;
}
Ejemplo n.º 17
0
static BOOL TestStream_Zero(void)
{
	UINT32 x;
	BOOL rc = FALSE;
	const BYTE data[] = "someteststreamdata";
	wStream* s = Stream_New(NULL, sizeof(data));
	if (!s)
		goto out;

	Stream_Write(s, data, sizeof(data));
	if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0)
		goto out;
	Stream_SetPosition(s, 0);
	if (s->pointer != s->buffer)
		goto out;
	Stream_Zero(s, 5);
	if (s->pointer != s->buffer + 5)
		goto out;
	if (memcmp(Stream_Pointer(s), data+5, sizeof(data)-5) != 0)
		goto out;
	Stream_SetPosition(s, 0);
	if (s->pointer != s->buffer)
		goto out;
	for (x=0; x<5; x++)
	{
		UINT8 val;
		Stream_Read_UINT8(s, val);
		if (val != 0)
			goto out;
	}

	rc = TRUE;
out:
	Stream_Free(s, TRUE);
	return rc;
}
Ejemplo n.º 18
0
static UINT video_control_send_presentation_response(VideoClientContext *context, TSMM_PRESENTATION_RESPONSE *resp)
{
	BYTE buf[12];
	wStream *s;
	VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)context->handle;
	IWTSVirtualChannel* channel;
	UINT ret;

	s = Stream_New(buf, 12);
	if (!s)
		return CHANNEL_RC_NO_MEMORY;

	Stream_Write_UINT32(s, 12); /* cbSize */
	Stream_Write_UINT32(s, TSMM_PACKET_TYPE_PRESENTATION_RESPONSE); /* PacketType */
	Stream_Write_UINT8(s, resp->PresentationId);
	Stream_Zero(s, 3);
	Stream_SealLength(s);

	channel = video->control_callback->channel_callback->channel;
	ret = channel->Write(channel, 12, buf, NULL);
	Stream_Free(s, FALSE);

	return ret;
}
Ejemplo n.º 19
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT cliprdr_server_format_list(CliprdrServerContext* context, CLIPRDR_FORMAT_LIST* formatList)
{
	wStream* s;
	UINT32 index;
	int length = 0;
	int cchWideChar;
	LPWSTR lpWideCharStr;
	int formatNameSize;
	int formatNameLength;
	char* szFormatName;
	WCHAR* wszFormatName;
	BOOL asciiNames = FALSE;
	CLIPRDR_FORMAT* format;
	CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle;

	if (!cliprdr->useLongFormatNames)
	{
		length = formatList->numFormats * 36;

		s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length);
		if (!s)
		{
			WLog_ERR(TAG, "cliprdr_server_packet_new failed!");
			return ERROR_INTERNAL_ERROR;
		}

		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);

			Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */

			formatNameSize = 0;
			formatNameLength = 0;

			szFormatName = format->formatName;

			if (asciiNames)
			{
				if (szFormatName)
					formatNameLength = strlen(szFormatName);

				if (formatNameLength > 31)
					formatNameLength = 31;

				Stream_Write(s, szFormatName, formatNameLength);
				Stream_Zero(s, 32 - formatNameLength);
			}
			else
			{
				wszFormatName = NULL;

				if (szFormatName)
					formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);

				if (formatNameSize > 15)
					formatNameSize = 15;

				if (wszFormatName)
					Stream_Write(s, wszFormatName, formatNameSize * 2);

				Stream_Zero(s, 32 - (formatNameSize * 2));

				free(wszFormatName);
			}
		}
	}
	else
	{
		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
			length += 4;
			formatNameSize = 2;

			if (format->formatName)
				formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2;

			length += formatNameSize;
		}

		s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length);

		if (!s)
		{
			WLog_ERR(TAG, "cliprdr_server_packet_new failed!");
			return ERROR_INTERNAL_ERROR;
		}

		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
			Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */

			if (format->formatName)
			{
				lpWideCharStr = (LPWSTR) Stream_Pointer(s);
				cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
				formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
					format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
				Stream_Seek(s, formatNameSize);
			}
			else
			{
				Stream_Write_UINT16(s, 0);
			}
		}
	}

	WLog_DBG(TAG, "ServerFormatList: numFormats: %d",
			formatList->numFormats);

	return cliprdr_server_packet_send(cliprdr, s);
}
Ejemplo n.º 20
0
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
{
	int size;
	BYTE* src;
	int frames;
	int fill_size;
	BOOL status;
	AUDIO_FORMAT* format;
	int tbytes_per_frame;
	wStream* s = context->priv->rdpsnd_pdu;

	format = &context->client_formats[context->selected_client_format];
	tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;

	if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
			(format->nChannels == context->src_format.nChannels))
	{
		src = context->priv->out_buffer;
		frames = context->priv->out_pending_frames;
	}
	else
	{
		context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer,
				context->priv->src_bytes_per_sample, context->src_format.nChannels,
				context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
				format->nChannels, format->nSamplesPerSec);
		frames = context->priv->dsp_context->resampled_frames;
		src = context->priv->dsp_context->resampled_buffer;
	}
	size = frames * tbytes_per_frame;

	if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
	{
		context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
			src, size, format->nChannels, format->nBlockAlign);
		src = context->priv->dsp_context->adpcm_buffer;
		size = context->priv->dsp_context->adpcm_size;
	}
	else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
	{
		context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
			src, size, format->nChannels, format->nBlockAlign);
		src = context->priv->dsp_context->adpcm_buffer;
		size = context->priv->dsp_context->adpcm_size;
	}

	context->block_no = (context->block_no + 1) % 256;

	/* Fill to nBlockAlign for the last audio packet */

	fill_size = 0;

	if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
		(context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0))
	{
		fill_size = format->nBlockAlign - (size % format->nBlockAlign);
	}

	/* WaveInfo PDU */
	Stream_SetPosition(s, 0);
	Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
	Stream_Write_UINT8(s, 0); /* bPad */
	Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */

	Stream_Write_UINT16(s, 0); /* wTimeStamp */
	Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
	Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
	Stream_Seek(s, 3); /* bPad */
	Stream_Write(s, src, 4);

	status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
	if (!status)
		goto out;
	Stream_SetPosition(s, 0);

	/* Wave PDU */
	Stream_EnsureRemainingCapacity(s, size + fill_size);
	Stream_Write_UINT32(s, 0); /* bPad */
	Stream_Write(s, src + 4, size - 4);

	if (fill_size > 0)
		Stream_Zero(s, fill_size);

	status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);

out:
	Stream_SetPosition(s, 0);
	context->priv->out_pending_frames = 0;
	return status;
}
Ejemplo n.º 21
0
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
	const char* path, wStream* output)
{
	int length;
	BOOL ret;
	WCHAR* ent_path;
	struct STAT st;
	struct dirent* ent;

	DEBUG_SVC("path %s FsInformationClass %d InitialQuery %d", path, FsInformationClass, InitialQuery);

	if (!file->dir)
	{
		Stream_Write_UINT32(output, 0); /* Length */
		Stream_Write_UINT8(output, 0); /* Padding */
		return FALSE;
	}

	if (InitialQuery != 0)
	{
		rewinddir(file->dir);
		free(file->pattern);

		if (path[0])
			file->pattern = _strdup(strrchr(path, '\\') + 1);
		else
			file->pattern = NULL;
	}

	if (file->pattern)
	{
		do
		{
			ent = readdir(file->dir);

			if (ent == NULL)
				continue;

			if (FilePatternMatchA(ent->d_name, file->pattern))
				break;

		}
		while (ent);
	}
	else
	{
		ent = readdir(file->dir);
	}

	if (ent == NULL)
	{
		DEBUG_SVC("  pattern %s not found.", file->pattern);
		Stream_Write_UINT32(output, 0); /* Length */
		Stream_Write_UINT8(output, 0); /* Padding */
		return FALSE;
	}

	memset(&st, 0, sizeof(struct STAT));
	ent_path = (WCHAR*) malloc(strlen(file->fullpath) + strlen(ent->d_name) + 2);
	sprintf((char*) ent_path, "%s/%s", file->fullpath, ent->d_name);

	if (STAT((char*) ent_path, &st) != 0)
	{
		DEBUG_WARN("stat %s failed. errno = %d", (char*) ent_path, errno);
	}

	DEBUG_SVC("  pattern %s matched %s", file->pattern, ent_path);
	free(ent_path);
	ent_path = NULL;

	length = ConvertToUnicode(CP_UTF8, 0, ent->d_name, -1, &ent_path, 0) * 2;

	ret = TRUE;

	switch (FsInformationClass)
	{
		case FileDirectoryInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232097.aspx */
			Stream_Write_UINT32(output, 64 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 64 + length);
			Stream_Write_UINT32(output, 0); /* NextEntryOffset */
			Stream_Write_UINT32(output, 0); /* FileIndex */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
			Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
			Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
			Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
			Stream_Write_UINT32(output, length); /* FileNameLength */
			Stream_Write(output, ent_path, length);
			break;

		case FileFullDirectoryInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232068.aspx */
			Stream_Write_UINT32(output, 68 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 68 + length);
			Stream_Write_UINT32(output, 0); /* NextEntryOffset */
			Stream_Write_UINT32(output, 0); /* FileIndex */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
			Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
			Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
			Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
			Stream_Write_UINT32(output, length); /* FileNameLength */
			Stream_Write_UINT32(output, 0); /* EaSize */
			Stream_Write(output, ent_path, length);
			break;

		case FileBothDirectoryInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232095.aspx */
			Stream_Write_UINT32(output, 93 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 93 + length);
			Stream_Write_UINT32(output, 0); /* NextEntryOffset */
			Stream_Write_UINT32(output, 0); /* FileIndex */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
			Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
			Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
			Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
			Stream_Write_UINT32(output, length); /* FileNameLength */
			Stream_Write_UINT32(output, 0); /* EaSize */
			Stream_Write_UINT8(output, 0); /* ShortNameLength */
			/* Reserved(1), MUST NOT be added! */
			Stream_Zero(output, 24); /* ShortName */
			Stream_Write(output, ent_path, length);
			break;

		case FileNamesInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232077.aspx */
			Stream_Write_UINT32(output, 12 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 12 + length);
			Stream_Write_UINT32(output, 0); /* NextEntryOffset */
			Stream_Write_UINT32(output, 0); /* FileIndex */
			Stream_Write_UINT32(output, length); /* FileNameLength */
			Stream_Write(output, ent_path, length);
			break;

		default:
			Stream_Write_UINT32(output, 0); /* Length */
			Stream_Write_UINT8(output, 0); /* Padding */
			DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
			ret = FALSE;
			break;
	}

	free(ent_path);

	return ret;
}
Ejemplo n.º 22
0
void gcc_write_client_core_data(wStream* s, rdpMcs* mcs)
{
	UINT32 version;
	WCHAR* clientName = NULL;
	int clientNameLength;
	BYTE connectionType;
	UINT16 highColorDepth;
	UINT16 supportedColorDepths;
	UINT16 earlyCapabilityFlags;
	WCHAR* clientDigProductId = NULL;
	int clientDigProductIdLength;
	rdpSettings* settings = mcs->settings;

	gcc_write_user_data_header(s, CS_CORE, 216);

	version = settings->RdpVersion >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4;

	clientNameLength = ConvertToUnicode(CP_UTF8, 0, settings->ClientHostname, -1, &clientName, 0);
	clientDigProductIdLength = ConvertToUnicode(CP_UTF8, 0, settings->ClientProductId, -1, &clientDigProductId, 0);

	Stream_Write_UINT32(s, version); /* Version */
	Stream_Write_UINT16(s, settings->DesktopWidth); /* DesktopWidth */
	Stream_Write_UINT16(s, settings->DesktopHeight); /* DesktopHeight */
	Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP); /* ColorDepth, ignored because of postBeta2ColorDepth */
	Stream_Write_UINT16(s, RNS_UD_SAS_DEL);	/* SASSequence (Secure Access Sequence) */
	Stream_Write_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
	Stream_Write_UINT32(s, settings->ClientBuild); /* ClientBuild */

	/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */

	if (clientNameLength >= 16)
	{
		clientNameLength = 16;
		clientName[clientNameLength - 1] = 0;
	}

	Stream_Write(s, clientName, (clientNameLength * 2));
	Stream_Zero(s, 32 - (clientNameLength * 2));
	free(clientName);

	Stream_Write_UINT32(s, settings->KeyboardType); /* KeyboardType */
	Stream_Write_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
	Stream_Write_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */

	Stream_Zero(s, 64); /* imeFileName */

	Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
	Stream_Write_UINT16(s, 1); /* clientProductID */
	Stream_Write_UINT32(s, 0); /* serialNumber (should be initialized to 0) */

	highColorDepth = MIN(settings->ColorDepth, 24);

	supportedColorDepths =
			RNS_UD_24BPP_SUPPORT |
			RNS_UD_16BPP_SUPPORT |
			RNS_UD_15BPP_SUPPORT;

	earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;

	if (settings->NetworkAutoDetect)
		settings->ConnectionType = CONNECTION_TYPE_AUTODETECT;

	if (settings->RemoteFxCodec && !settings->NetworkAutoDetect)
		settings->ConnectionType = CONNECTION_TYPE_LAN;

	connectionType = settings->ConnectionType;

	if (connectionType)
		earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;

	if (settings->ColorDepth == 32)
	{
		supportedColorDepths |= RNS_UD_32BPP_SUPPORT;
		earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
	}

	if (settings->NetworkAutoDetect)
		earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT;

	if (settings->SupportHeartbeatPdu)
		earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;

	if (settings->SupportGraphicsPipeline)
		earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;

	if (settings->SupportDynamicTimeZone)
		earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE;

	Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */
	Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */

	Stream_Write_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */

	/* clientDigProductId (64 bytes, null-terminated unicode, truncated to 31 characters) */
	if (clientDigProductIdLength >= 32)
	{
		clientDigProductIdLength = 32;
		clientDigProductId[clientDigProductIdLength - 1] = 0;
	}
	Stream_Write(s, clientDigProductId, (clientDigProductIdLength * 2) );
	Stream_Zero(s, 64 - (clientDigProductIdLength * 2) );
	free(clientDigProductId);

	Stream_Write_UINT8(s, connectionType); /* connectionType */
	Stream_Write_UINT8(s, 0); /* pad1octet */

	Stream_Write_UINT32(s, settings->SelectedProtocol); /* serverSelectedProtocol */
}
Ejemplo n.º 23
0
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
	CryptoMd5 md5;
	BYTE* sigData;
	int expLen, keyLen, sigDataLen;
	BYTE encryptedSignature[TSSK_KEY_LENGTH];
	BYTE signature[sizeof(initial_signature)];
	UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
	rdpSettings* settings = mcs->settings;

	/**
	 * Re: settings->EncryptionLevel:
	 * This is configured/set by the server implementation and serves the same
	 * purpose as the "Encryption Level" setting in the RDP-Tcp configuration
	 * dialog of Microsoft's Remote Desktop Session Host Configuration.
	 * Re: settings->EncryptionMethods:
	 * at this point this setting contains the client's supported encryption
	 * methods we've received in gcc_read_client_security_data()
	 */

	if (!settings->UseRdpSecurityLayer)
	{
		/* TLS/NLA is used: disable rdp style encryption */
		settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
	}

	/* verify server encryption level value */
	switch (settings->EncryptionLevel)
	{
		case ENCRYPTION_LEVEL_NONE:
			WLog_INFO(TAG, "Active rdp encryption level: NONE");
			break;
		case ENCRYPTION_LEVEL_FIPS:
			WLog_INFO(TAG, "Active rdp encryption level: FIPS Compliant");
			break;
		case ENCRYPTION_LEVEL_HIGH:
			WLog_INFO(TAG, "Active rdp encryption level: HIGH");
			break;
		case ENCRYPTION_LEVEL_LOW:
			WLog_INFO(TAG, "Active rdp encryption level: LOW");
			break;
		case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
			WLog_INFO(TAG, "Active rdp encryption level: CLIENT-COMPATIBLE");
			break;
		default:
			WLog_ERR(TAG, "Invalid server encryption level 0x%08X", settings->EncryptionLevel);
			WLog_ERR(TAG, "Switching to encryption level CLIENT-COMPATIBLE");
			settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
	}

	/* choose rdp encryption method based on server level and client methods */
	switch (settings->EncryptionLevel)
	{
		case ENCRYPTION_LEVEL_NONE:
			/* The only valid method is NONE in this case */
			settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
			break;
		case ENCRYPTION_LEVEL_FIPS:
			/* The only valid method is FIPS in this case */
			if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS))
			{
				WLog_WARN(TAG, "client does not support FIPS as required by server configuration");
			}
			settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
			break;
		case ENCRYPTION_LEVEL_HIGH:
			/* Maximum key strength supported by the server must be used (128 bit)*/
			if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT))
			{
				WLog_WARN(TAG, "client does not support 128 bit encryption method as required by server configuration");
			}
			settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			break;
		case ENCRYPTION_LEVEL_LOW:
		case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
			/* Maximum key strength supported by the client must be used */
			if (settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_56BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_56BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS)
				settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
			else
			{
				WLog_WARN(TAG, "client has not announced any supported encryption methods");
				settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			}
			break;
		default:
			WLog_ERR(TAG, "internal error: unknown encryption level");
	}

	/* log selected encryption method */
	switch (settings->EncryptionMethods)
	{
		case ENCRYPTION_METHOD_NONE:
			WLog_INFO(TAG, "Selected rdp encryption method: NONE");
			break;
		case ENCRYPTION_METHOD_40BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 40BIT");
			break;
		case ENCRYPTION_METHOD_56BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 56BIT");
			break;
		case ENCRYPTION_METHOD_128BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 128BIT");
			break;
		case ENCRYPTION_METHOD_FIPS:
			WLog_INFO(TAG, "Selected rdp encryption method: FIPS");
			break;
		default:
			WLog_ERR(TAG, "internal error: unknown encryption method");
	}

	headerLen = 12;
	keyLen = 0;
	wPublicKeyBlobLen = 0;
	serverRandomLen = 0;
	serverCertLen = 0;

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE)
	{
		serverRandomLen = 32;

		keyLen = settings->RdpServerRsaKey->ModulusLength;
		expLen = sizeof(settings->RdpServerRsaKey->exponent);
		wPublicKeyBlobLen = 4; /* magic (RSA1) */
		wPublicKeyBlobLen += 4; /* keylen */
		wPublicKeyBlobLen += 4; /* bitlen */
		wPublicKeyBlobLen += 4; /* datalen */
		wPublicKeyBlobLen += expLen;
		wPublicKeyBlobLen += keyLen;
		wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */

		serverCertLen = 4; /* dwVersion */
		serverCertLen += 4; /* dwSigAlgId */
		serverCertLen += 4; /* dwKeyAlgId */
		serverCertLen += 2; /* wPublicKeyBlobType */
		serverCertLen += 2; /* wPublicKeyBlobLen */
		serverCertLen += wPublicKeyBlobLen;
		serverCertLen += 2; /* wSignatureBlobType */
		serverCertLen += 2; /* wSignatureBlobLen */
		serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
		serverCertLen += 8; /* 8 bytes of zero padding */

		headerLen += sizeof(serverRandomLen);
		headerLen += sizeof(serverCertLen);
		headerLen += serverRandomLen;
		headerLen += serverCertLen;
	}

	gcc_write_user_data_header(s, SC_SECURITY, headerLen);

	Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
	Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */

	if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
	{
		return;
	}

	Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */
	Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */

	settings->ServerRandomLength = serverRandomLen;
	settings->ServerRandom = (BYTE*) malloc(serverRandomLen);
	crypto_nonce(settings->ServerRandom, serverRandomLen);
	Stream_Write(s, settings->ServerRandom, serverRandomLen);

	sigData = Stream_Pointer(s);

	Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
	Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
	Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
	Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */

	Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
	Stream_Write(s, "RSA1", 4); /* magic */
	Stream_Write_UINT32(s, keyLen + 8); /* keylen */
	Stream_Write_UINT32(s, keyLen * 8); /* bitlen */
	Stream_Write_UINT32(s, keyLen - 1); /* datalen */

	Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen);
	Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen);
	Stream_Zero(s, 8);

	sigDataLen = Stream_Pointer(s) - sigData;

	Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
	Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */

	memcpy(signature, initial_signature, sizeof(initial_signature));

	md5 = crypto_md5_init();
	if (!md5)
	{
		WLog_ERR(TAG,  "unable to allocate a md5");
		return;
	}

	crypto_md5_update(md5, sigData, sigDataLen);
	crypto_md5_final(md5, signature);

	crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
		tssk_modulus, tssk_privateExponent, encryptedSignature);

	Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
	Stream_Zero(s, 8);
}
Ejemplo n.º 24
0
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
	CryptoMd5 md5;
	BYTE* sigData;
	int expLen, keyLen, sigDataLen;
	BYTE encryptedSignature[TSSK_KEY_LENGTH];
	BYTE signature[sizeof(initial_signature)];
	UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
	rdpSettings* settings = mcs->settings;

	if (!settings->DisableEncryption)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
		settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT;
	}

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE)
		settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;

	headerLen = 12;
	keyLen = 0;
	wPublicKeyBlobLen = 0;
	serverRandomLen = 0;
	serverCertLen = 0;

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE ||
	    settings->EncryptionLevel != ENCRYPTION_LEVEL_NONE)
	{
		serverRandomLen = 32;

		keyLen = settings->RdpServerRsaKey->ModulusLength;
		expLen = sizeof(settings->RdpServerRsaKey->exponent);
		wPublicKeyBlobLen = 4; /* magic (RSA1) */
		wPublicKeyBlobLen += 4; /* keylen */
		wPublicKeyBlobLen += 4; /* bitlen */
		wPublicKeyBlobLen += 4; /* datalen */
		wPublicKeyBlobLen += expLen;
		wPublicKeyBlobLen += keyLen;
		wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */

		serverCertLen = 4; /* dwVersion */
		serverCertLen += 4; /* dwSigAlgId */
		serverCertLen += 4; /* dwKeyAlgId */
		serverCertLen += 2; /* wPublicKeyBlobType */
		serverCertLen += 2; /* wPublicKeyBlobLen */
		serverCertLen += wPublicKeyBlobLen;
		serverCertLen += 2; /* wSignatureBlobType */
		serverCertLen += 2; /* wSignatureBlobLen */
		serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
		serverCertLen += 8; /* 8 bytes of zero padding */

		headerLen += sizeof(serverRandomLen);
		headerLen += sizeof(serverCertLen);
		headerLen += serverRandomLen;
		headerLen += serverCertLen;
	}

	gcc_write_user_data_header(s, SC_SECURITY, headerLen);

	Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
	Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */

	if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE &&
	    settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
	{
		return;
	}

	Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */
	Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */

	settings->ServerRandomLength = serverRandomLen;
	settings->ServerRandom = (BYTE*) malloc(serverRandomLen);
	crypto_nonce(settings->ServerRandom, serverRandomLen);
	Stream_Write(s, settings->ServerRandom, serverRandomLen);

	sigData = Stream_Pointer(s);

	Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
	Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
	Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
	Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */

	Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
	Stream_Write(s, "RSA1", 4); /* magic */
	Stream_Write_UINT32(s, keyLen + 8); /* keylen */
	Stream_Write_UINT32(s, keyLen * 8); /* bitlen */
	Stream_Write_UINT32(s, keyLen - 1); /* datalen */

	Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen);
	Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen);
	Stream_Zero(s, 8);

	sigDataLen = Stream_Pointer(s) - sigData;

	Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
	Stream_Write_UINT16(s, keyLen + 8); /* wSignatureBlobLen */

	memcpy(signature, initial_signature, sizeof(initial_signature));

	md5 = crypto_md5_init();
	crypto_md5_update(md5, sigData, sigDataLen);
	crypto_md5_final(md5, signature);

	crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
		tssk_modulus, tssk_privateExponent, encryptedSignature);

	Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
	Stream_Zero(s, 8);
}