413 lines
9.3 KiB
C
413 lines
9.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
cr.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Local Security Authority - Cipher Routines common to Client and Server
|
||
|
|
||
|
These routines interface the LSA client or server sides with the Cipher
|
||
|
Routines. They perform RPC-style memory allocation.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Scott Birrell (ScottBi) December 13, 1991
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <lsacomp.h>
|
||
|
|
||
|
VOID
|
||
|
LsapCrFreeMemoryValue(
|
||
|
IN PVOID MemoryValue
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function frees the memory allocated for an Cipher Value.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// The memory is currently a counted string contained in a UNICODE
|
||
|
// STRING structure in which the buffer follows the structure. A
|
||
|
// single MIDL_user_free will therefore do the trick.
|
||
|
//
|
||
|
|
||
|
MIDL_user_free(MemoryValue);
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
LsapCrEncryptValue(
|
||
|
IN OPTIONAL PLSAP_CR_CLEAR_VALUE ClearValue,
|
||
|
IN PLSAP_CR_CIPHER_KEY CipherKey,
|
||
|
OUT PLSAP_CR_CIPHER_VALUE *CipherValue
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function two-way encrypts a Value with the given Cipher Key
|
||
|
and allocates memory for the output. The memory must be freed after
|
||
|
use by calling LsapCrFreeMemoryValue().
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ClearValue - Pointer to structure referencing value to be encrypted.
|
||
|
A NULL pointer may be specified.
|
||
|
|
||
|
CipherKey - Pointer to structure referencing the Cipher Key
|
||
|
|
||
|
CipherValue - Receives a pointer to a structure referencing the
|
||
|
encrypted value or NULL.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
LSAP_CR_CIPHER_VALUE TempCipherValue;
|
||
|
PLSAP_CR_CIPHER_VALUE OutputCipherValue = NULL;
|
||
|
ULONG CipherValueBufferLength;
|
||
|
LSAP_CR_CLEAR_VALUE LocalFake = { 0 };
|
||
|
|
||
|
//
|
||
|
// If NULL is specified for input, return NULL for output.
|
||
|
//
|
||
|
|
||
|
if (!ARGUMENT_PRESENT(ClearValue)) {
|
||
|
|
||
|
*CipherValue = NULL;
|
||
|
ClearValue = &LocalFake ;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Obtain the length of the encrypted value buffer that will be
|
||
|
// required by calling the encryption routine in 'query' mode
|
||
|
// by passing a pointer to a return Cipher Value structure containing
|
||
|
// a MaximumLength of 0.
|
||
|
//
|
||
|
|
||
|
TempCipherValue.MaximumLength = 0;
|
||
|
TempCipherValue.Length = 0;
|
||
|
TempCipherValue.Buffer = NULL;
|
||
|
|
||
|
Status = LsapCrRtlEncryptData(
|
||
|
ClearValue,
|
||
|
CipherKey,
|
||
|
&TempCipherValue
|
||
|
);
|
||
|
|
||
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
||
|
|
||
|
goto EncryptValueError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate memory for the output structure followed by buffer.
|
||
|
//
|
||
|
|
||
|
CipherValueBufferLength = TempCipherValue.Length;
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
|
||
|
OutputCipherValue = MIDL_user_allocate(
|
||
|
sizeof (LSAP_CR_CIPHER_VALUE) +
|
||
|
CipherValueBufferLength
|
||
|
);
|
||
|
|
||
|
if (OutputCipherValue == NULL) {
|
||
|
|
||
|
goto EncryptValueError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize Cipher Value structure. The Buffer pointer is set to
|
||
|
// to point to the byte following the structure header.
|
||
|
//
|
||
|
|
||
|
OutputCipherValue->Buffer = (PCHAR)(OutputCipherValue + 1);
|
||
|
OutputCipherValue->MaximumLength = CipherValueBufferLength;
|
||
|
OutputCipherValue->Length = CipherValueBufferLength;
|
||
|
|
||
|
//
|
||
|
// Now call the two-way encryption routine.
|
||
|
//
|
||
|
|
||
|
Status = LsapCrRtlEncryptData(
|
||
|
ClearValue,
|
||
|
CipherKey,
|
||
|
OutputCipherValue
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS(Status)) {
|
||
|
|
||
|
*CipherValue = OutputCipherValue;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
EncryptValueError:
|
||
|
|
||
|
//
|
||
|
// If necessary, free the memory allocated for the output encrypted value.
|
||
|
//
|
||
|
|
||
|
if (OutputCipherValue != NULL) {
|
||
|
|
||
|
MIDL_user_free(OutputCipherValue);
|
||
|
}
|
||
|
|
||
|
*CipherValue = NULL;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
LsapCrDecryptValue(
|
||
|
IN OPTIONAL PLSAP_CR_CIPHER_VALUE CipherValue,
|
||
|
IN PLSAP_CR_CIPHER_KEY CipherKey,
|
||
|
OUT PLSAP_CR_CLEAR_VALUE *ClearValue
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function decrypts a Value that has been two-way Cipher with the
|
||
|
given Cipher Key and allocates memory for the output. The memory
|
||
|
must be freed after use by calling LsapCrFreeMemoryValue();
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CipherValue - Pointer to structure referencing encrypted Value.
|
||
|
|
||
|
CipherKey - Pointer to structure referencing the Cipher Key
|
||
|
|
||
|
ClearValue - Receives a pointer to a structure referencing the
|
||
|
Decrypted Value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
LSAP_CR_CLEAR_VALUE TempClearValue;
|
||
|
PLSAP_CR_CLEAR_VALUE OutputClearValue = NULL;
|
||
|
ULONG ClearValueBufferLength;
|
||
|
|
||
|
//
|
||
|
// If NULL is specified for input, return NULL for output.
|
||
|
//
|
||
|
|
||
|
if (!ARGUMENT_PRESENT(CipherValue)) {
|
||
|
|
||
|
*ClearValue = NULL;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if ( CipherValue->MaximumLength < CipherValue->Length ||
|
||
|
( CipherValue->Length != 0 && CipherValue->Buffer == NULL ) ) {
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Obtain the length of the decrypted (clear) value buffer that will be
|
||
|
// required by calling the decryption routine in 'query' mode
|
||
|
// by passing a pointer to a return Clear Value structure containing
|
||
|
// a MaximumLength of 0.
|
||
|
//
|
||
|
|
||
|
TempClearValue.MaximumLength = 0;
|
||
|
TempClearValue.Length = 0;
|
||
|
TempClearValue.Buffer = NULL;
|
||
|
|
||
|
Status = LsapCrRtlDecryptData(
|
||
|
CipherValue,
|
||
|
CipherKey,
|
||
|
&TempClearValue
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Since we supplied a buffer length of 0, we would normally expect
|
||
|
// to receive STATUS_BUFFER_TOO_SMALL back plus the buffer size required.
|
||
|
// There is one exceptional case and that is where the original
|
||
|
// unencrypted data had length 0. In this case, we expect
|
||
|
// STATUS_SUCCESS and a length required equal to 0 returned.
|
||
|
//
|
||
|
|
||
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
||
|
|
||
|
if (!(Status == STATUS_SUCCESS && TempClearValue.Length == 0)) {
|
||
|
goto DecryptValueError;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate memory for the output structure followed by buffer.
|
||
|
//
|
||
|
|
||
|
ClearValueBufferLength = TempClearValue.Length;
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
|
||
|
OutputClearValue = MIDL_user_allocate(
|
||
|
sizeof (LSAP_CR_CLEAR_VALUE) +
|
||
|
ClearValueBufferLength
|
||
|
);
|
||
|
|
||
|
if (OutputClearValue == NULL) {
|
||
|
|
||
|
goto DecryptValueError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize Clear Value structure. The Buffer pointer is set to
|
||
|
// to point to the byte following the structure header.
|
||
|
//
|
||
|
|
||
|
OutputClearValue->Buffer = (PCHAR)(OutputClearValue + 1);
|
||
|
OutputClearValue->MaximumLength = ClearValueBufferLength;
|
||
|
OutputClearValue->Length = ClearValueBufferLength;
|
||
|
|
||
|
//
|
||
|
// Now call the two-way decryption routine.
|
||
|
//
|
||
|
|
||
|
Status = LsapCrRtlDecryptData(
|
||
|
CipherValue,
|
||
|
CipherKey,
|
||
|
OutputClearValue
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS(Status)) {
|
||
|
|
||
|
*ClearValue = OutputClearValue;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
DecryptValueError:
|
||
|
|
||
|
//
|
||
|
// If necessary, free the memory allocated for the output decrypted value.
|
||
|
//
|
||
|
|
||
|
if (OutputClearValue != NULL) {
|
||
|
|
||
|
MIDL_user_free(OutputClearValue);
|
||
|
}
|
||
|
|
||
|
*ClearValue = NULL;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LsapCrUnicodeToClearValue(
|
||
|
IN OPTIONAL PUNICODE_STRING UnicodeString,
|
||
|
OUT PLSAP_CR_CLEAR_VALUE ClearValue
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function converts a Unicode structure to a Clear Value structure.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
UnicodeString - Optional pointer to Unicode string. If NULL, the
|
||
|
output Clear Value structure is initialized to have zero
|
||
|
length and Maximum length, and with a NULL buffer pointer.
|
||
|
|
||
|
ClearValue - Pointer to Clear Value structure.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
UNICODE_STRING IntermediateUnicodeString;
|
||
|
|
||
|
if (ARGUMENT_PRESENT(UnicodeString)) {
|
||
|
|
||
|
IntermediateUnicodeString = *UnicodeString;
|
||
|
|
||
|
ClearValue->Length = (ULONG) IntermediateUnicodeString.Length;
|
||
|
ClearValue->MaximumLength = (ULONG) IntermediateUnicodeString.MaximumLength;
|
||
|
ClearValue->Buffer = (PUCHAR) IntermediateUnicodeString.Buffer;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ClearValue->Length = ClearValue->MaximumLength = 0;
|
||
|
ClearValue->Buffer = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LsapCrClearValueToUnicode(
|
||
|
IN OPTIONAL PLSAP_CR_CLEAR_VALUE ClearValue,
|
||
|
OUT PUNICODE_STRING UnicodeString
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function converts a Clear Value to a Unicode String. The Clear
|
||
|
Value structure must have valid syntax - no checking will be done.
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ClearValue - Optional pointer to Clear Value to be converted. If
|
||
|
NULL is specified, the output Unicode String structure will
|
||
|
be initialized to point to the NULL string.
|
||
|
|
||
|
UnicodeString - Pointer to target Unicode String structure.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
LSAP_CR_CLEAR_VALUE IntermediateClearValue;
|
||
|
|
||
|
if (ARGUMENT_PRESENT(ClearValue)) {
|
||
|
|
||
|
IntermediateClearValue = *ClearValue;
|
||
|
|
||
|
UnicodeString->Length = (USHORT) IntermediateClearValue.Length;
|
||
|
UnicodeString->MaximumLength = (USHORT) IntermediateClearValue.MaximumLength;
|
||
|
UnicodeString->Buffer = (PWSTR) IntermediateClearValue.Buffer;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UnicodeString->Length = UnicodeString->MaximumLength = 0;
|
||
|
UnicodeString->Buffer = NULL;
|
||
|
}
|