Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

394 lines
8.9 KiB

//+-----------------------------------------------------------------------
//
// File: crypt.c
//
// Contents: cryptography routines for building EncryptedData structs
//
//
// History: 17-Dec-91, RichardW Created
// 25-Feb-92, RichardW Revised for CryptoSystems
//
//------------------------------------------------------------------------
#ifndef WIN32_CHICAGO
#include "krbprgma.h"
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <kerbcomm.h>
#include <kerberr.h>
#include <kerbcon.h>
#else // WIN32_CHICAGO
#include <kerb.hxx>
#include <kerbp.h>
#endif // WIN32_CHICAGO
#define CONFOUNDER_SIZE 8
#define CHECKSUM_SIZE sizeof(CheckSum)
//+-------------------------------------------------------------------------
//
// Function: KerbEncryptData
//
// Synopsis: shim for KerbEncryptDataEx
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
KERBERR NTAPI
KerbEncryptData(
OUT PKERB_ENCRYPTED_DATA EncryptedData,
IN ULONG DataSize,
IN PUCHAR Data,
IN ULONG Algorithm,
IN PKERB_ENCRYPTION_KEY Key
)
{
return KerbEncryptDataEx(
EncryptedData,
DataSize,
Data,
KERB_NO_KEY_VERSION,
0, // no usage flags
Key
);
}
//+---------------------------------------------------------------------------
//
// Function: KerbEncryptDataEx
//
// Synopsis: Turns cleartext into cipher text
//
// Effects: In place encryption of data
//
// Arguments: Data - Contains data to be encrypted
// DataSize - Contains length of data in bytes
// KeyVersion - KERB_NO_KEY_VERSION for no key version or kvno for KERB_ENCRYPTED_DATA
// Algorithm - Algorithm to be used for encryption/checksum
// UsageFlags - Flags indicating usage (client/serve, encryption/authentication)
// Key - Key to use for encryption
//
//
//
// Notes:
//
//----------------------------------------------------------------------------
KERBERR NTAPI
KerbEncryptDataEx(
OUT PKERB_ENCRYPTED_DATA EncryptedData,
IN ULONG DataSize,
IN PUCHAR Data,
IN ULONG KeyVersion,
IN ULONG UsageFlags,
IN PKERB_ENCRYPTION_KEY Key
)
{
PCRYPTO_SYSTEM pcsCrypt = NULL;
PCRYPT_STATE_BUFFER psbCryptBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS;
Status = CDLocateCSystem(Key->keytype, &pcsCrypt);
if (!NT_SUCCESS(Status))
{
return(KDC_ERR_ETYPE_NOTSUPP);
}
//
// Initialize header
//
EncryptedData->encryption_type = Key->keytype;
Status = pcsCrypt->Initialize(
(PUCHAR) Key->keyvalue.value,
Key->keyvalue.length,
UsageFlags,
&psbCryptBuffer
);
if (!NT_SUCCESS(Status))
{
return(KRB_ERR_GENERIC);
}
Status = pcsCrypt->Encrypt(
psbCryptBuffer,
Data,
DataSize,
EncryptedData->cipher_text.value,
&EncryptedData->cipher_text.length
);
(void) pcsCrypt->Discard(&psbCryptBuffer);
if (!NT_SUCCESS(Status))
{
return(KRB_ERR_GENERIC);
}
if (KeyVersion != KERB_NO_KEY_VERSION)
{
EncryptedData->version = KeyVersion;
EncryptedData->bit_mask |= version_present;
}
return(KDC_ERR_NONE);
}
//+-------------------------------------------------------------------------
//
// Function: KerbDecryptData
//
// Synopsis: Shim for KerbDecryptDataEx with no usage flags
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
KERBERR NTAPI
KerbDecryptData(
IN PKERB_ENCRYPTED_DATA EncryptedData,
IN PKERB_ENCRYPTION_KEY pkKey,
OUT PULONG DataSize,
OUT PUCHAR Data
)
{
return(KerbDecryptDataEx(
EncryptedData,
pkKey,
0, // no usage flags
DataSize,
Data
) );
}
//+---------------------------------------------------------------------------
//
// Function: KerbDecryptDataEx
//
// Synopsis: Decrypts an EncryptedData structure
//
// Effects:
//
// Arguments: [pedData] -- EncryptedData
// [pkKey] -- Key to use
//
// History: 4-16-93 RichardW Created Comment
//
//----------------------------------------------------------------------------
KERBERR NTAPI
KerbDecryptDataEx(
IN PKERB_ENCRYPTED_DATA EncryptedData,
IN PKERB_ENCRYPTION_KEY pkKey,
IN ULONG UsageFlags,
OUT PULONG DataSize,
OUT PUCHAR Data
)
{
PCRYPTO_SYSTEM pcsCrypt = NULL;
PCRYPT_STATE_BUFFER psbCryptBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS;
Status = CDLocateCSystem(
EncryptedData->encryption_type,
&pcsCrypt
);
if (!NT_SUCCESS(Status))
{
return(KDC_ERR_ETYPE_NOTSUPP);
}
if (EncryptedData->cipher_text.length & (pcsCrypt->BlockSize - 1))
{
return(KRB_ERR_GENERIC);
}
Status = pcsCrypt->Initialize(
(PUCHAR) pkKey->keyvalue.value,
pkKey->keyvalue.length,
UsageFlags,
&psbCryptBuffer
);
if (!NT_SUCCESS(Status))
{
return(KRB_ERR_GENERIC);
}
Status = pcsCrypt->Decrypt(
psbCryptBuffer,
EncryptedData->cipher_text.value,
EncryptedData->cipher_text.length,
Data,
DataSize
);
(VOID) pcsCrypt->Discard(&psbCryptBuffer);
if (!NT_SUCCESS(Status))
{
return(KRB_AP_ERR_MODIFIED);
}
else
{
return(KDC_ERR_NONE);
}
}
//+-------------------------------------------------------------------------
//
// Function: KerbGetEncryptionOverhead
//
// Synopsis: Gets the extra space required for encryption to store the ckecksum
//
// Effects:
//
// Arguments: Algorithm - the algorithm to use
// Overhead - receives the overhead in bytes
//
// Requires:
//
// Returns: STATUS_SUCCESS or KRB_E_ETYPE_NOSUPP
//
// Notes:
//
//
//--------------------------------------------------------------------------
KERBERR
KerbGetEncryptionOverhead(
IN ULONG Algorithm,
OUT PULONG Overhead,
OUT OPTIONAL PULONG BlockSize
)
{
PCRYPTO_SYSTEM pcsCrypt;
NTSTATUS Status = STATUS_SUCCESS;
Status = CDLocateCSystem(Algorithm, &pcsCrypt);
if (!NT_SUCCESS(Status))
{
return(KDC_ERR_ETYPE_NOTSUPP);
}
*Overhead = pcsCrypt->HeaderSize;
if (ARGUMENT_PRESENT(BlockSize))
{
*BlockSize = pcsCrypt->BlockSize;
}
return(KDC_ERR_NONE);
}
//+-------------------------------------------------------------------------
//
// Function: KerbAllocateEncryptionBuffer
//
// Synopsis: Allocates the space required for encryption with a given
// key
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
KERBERR
KerbAllocateEncryptionBuffer(
IN ULONG EncryptionType,
IN ULONG BufferSize,
OUT PUINT EncryptionBufferSize,
OUT PBYTE * EncryptionBuffer
)
{
KERBERR KerbErr = KDC_ERR_NONE;
ULONG EncryptionOverhead = 0;
ULONG BlockSize = 0;
KerbErr = KerbGetEncryptionOverhead(
EncryptionType,
&EncryptionOverhead,
&BlockSize
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
*EncryptionBufferSize = (UINT) ROUND_UP_COUNT(EncryptionOverhead + BufferSize, BlockSize);
*EncryptionBuffer = (PBYTE) MIDL_user_allocate(*EncryptionBufferSize);
if (*EncryptionBuffer == NULL)
{
KerbErr = KRB_ERR_GENERIC;
}
Cleanup:
return(KerbErr);
}
KERBERR
KerbAllocateEncryptionBufferWrapper(
IN ULONG EncryptionType,
IN ULONG BufferSize,
OUT unsigned long * EncryptionBufferSize,
OUT PBYTE * EncryptionBuffer
)
{
KERBERR KerbErr = KDC_ERR_NONE;
unsigned int tempInt = 0;
KerbErr = KerbAllocateEncryptionBuffer(
EncryptionType,
BufferSize,
&tempInt,
EncryptionBuffer
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
*EncryptionBufferSize = tempInt;
Cleanup:
return (KerbErr);
}