//+----------------------------------------------------------------------- // // 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 #include #include #include #include #include #else // WIN32_CHICAGO #include #include #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); }