Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1 lines
9.8 KiB

/*****************************************************************/ /** Microsoft Windows 2000 **/ /** Copyright (C) Microsoft Corp., 1991-1998 **/ /*****************************************************************/ /*****************************************************************/ /** Microsoft Windows **/ /** Copyright (C) Microsoft Corp., 1991-1995 **/ /*****************************************************************/ /*****************************************************************/ /** Microsoft Windows for Workgroups **/ /** Copyright (C) Microsoft Corp., 1991-1992 **/ /*****************************************************************/ /********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1991 **/ /********************************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "USRPWST3.h" // --------------------------------------------------------------------------- // ¥ EncryptStdBlock() // --------------------------------------------------------------------------- // Routine Description: // // Takes a block key encrypts the standard text block with it. // The resulting encrypted block is returned. // This is a One-Way-Function - the key cannot be recovered from the // encrypted data block. // // Arguments: // // BlockKey - The key to use to encrypt the standard text block. // // CypherBlock - The encrypted data is returned here // // Return Values: // // TRUE - The encryption was successful. // The result is in CypherBlock // // FALSE - Something failed. The CypherBlock is undefined. bool EncryptStdBlock( IN PBLOCK_KEY BlockKey, OUT PCYPHER_BLOCK CypherBlock ) { unsigned Result; char StdEncrPwd[] = "KGS!@#$%"; Result = DES_ECB_LM((DWORD)ENCR_KEY, (const char *)BlockKey, (unsigned char *)StdEncrPwd, (unsigned char *)CypherBlock ); if (Result == CRYPT_OK) { return(TRUE); } else { return(FALSE); } } // --------------------------------------------------------------------------- // ¥ CalculateLmOwfPassword() // --------------------------------------------------------------------------- // Routine Description: // // Takes the passed LmPassword and performs a one-way-function on it. // The current implementation does this by using the password as a key // to encrypt a known block of text. // // Arguments: // // LmPassword - The password to perform the one-way-function on. // // LmOwfPassword - The hashed password is returned here // // Return Values: // // BOOL - The function was completed successfully. The hashed // password is in LmOwfPassword. // // FALSE - Something failed. The LmOwfPassword is undefined. bool CalculateLmOwfPassword( IN PLM_PASSWORD LmPassword, OUT PLM_OWF_PASSWORD LmOwfPassword ) { bool Status; BLOCK_KEY Key[2]; PCHAR pKey; // Copy the password into our key buffer and zero pad to fill the 2 keys pKey = (PCHAR)(&Key[0]); while (*LmPassword && (pKey < (PCHAR)(&Key[2]))) { *pKey++ = *LmPassword++; } while (pKey < (PCHAR)(&Key[2])) { *pKey++ = 0; } // Use the keys to encrypt the standard text Status = EncryptStdBlock(&Key[0], &(LmOwfPassword->data[0])); if (!Status) { return(Status); } //***************************************************** //BUGBUG: Alignment work-around needed for 68K, may not //work under PowerPC! //***************************************************** PBLOCK_KEY pK = (PBLOCK_KEY)(((PUCHAR)&Key[1])-1); Status = EncryptStdBlock(pK /*&Key[1]*/, &(LmOwfPassword->data[1])); // // clear our copy of the cleartext password // pKey = (PCHAR)(&Key[0]); while (pKey < (PCHAR)(&Key[2])) { *pKey++ = 0; } return(Status); } // --------------------------------------------------------------------------- // ¥ EncryptBlock() // --------------------------------------------------------------------------- // Routine Description: // // Takes a block of data and encrypts it with a key producing // an encrypted block of data. // // Arguments: // // ClearBlock - The block of data that is to be encrypted. // // BlockKey - The key to use to encrypt data // // CypherBlock - Encrypted data is returned here // // Return Values: // // TRUE - The data was encrypted successfully. The encrypted // data block is in CypherBlock // // FALSE - Something failed. The CypherBlock is undefined. bool EncryptBlock( IN PCLEAR_BLOCK ClearBlock, IN PBLOCK_KEY BlockKey, OUT PCYPHER_BLOCK CypherBlock ) { unsigned Result; Result = DES_ECB_LM(ENCR_KEY, (const char *)BlockKey, (unsigned char *)ClearBlock, (unsigned char *)CypherBlock ); if (Result == CRYPT_OK) { return(TRUE); } else { return(FALSE); } } // --------------------------------------------------------------------------- // ¥ EncryptLmOwfPwdWithLmOwfPwd() // --------------------------------------------------------------------------- // Routine Description: // // Encrypts one OwfPassword with another // // Arguments: // // DataLmOwfPassword - OwfPassword to be encrypted // // KeyLmOwfPassword - OwfPassword to be used as a key to the encryption // // EncryptedLmOwfPassword - The encrypted OwfPassword is returned here. // // Return Values: // // TRUE - The function completed successfully. The encrypted // OwfPassword is in EncryptedLmOwfPassword // // FALSE - Something failed. The EncryptedLmOwfPassword is undefined. bool EncryptLmOwfPwdWithLmOwfPwd( IN PLM_OWF_PASSWORD DataLmOwfPassword, IN PLM_OWF_PASSWORD KeyLmOwfPassword, OUT PENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword ) { bool Status; Status = EncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[0]), &(((PBLOCK_KEY)(KeyLmOwfPassword->data))[0]), &(EncryptedLmOwfPassword->data[0])); if (!Status) { return(Status); } // //***************************************** //****WILL PROBABLY BREAK UNDER POWERPC**** //****This is necessary on Mac68K********** //****WILL PROBABLY BREAK UNDER POWERPC**** // PBLOCK_KEY pK = (PBLOCK_KEY)&(KeyLmOwfPassword->data[1]); //pK++; // //Notice the "-1" in the second parameter, this is necessary to position the //ptr at byte 7 in the FIRST parameter of the struct. // Status = EncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[1]), (PBLOCK_KEY)(((PUCHAR)pK)-1), &(EncryptedLmOwfPassword->data[1])); // //***************************************** // return(Status); } // --------------------------------------------------------------------------- // ¥ SampEncryptLmPasswords() // --------------------------------------------------------------------------- //Routine Description: // // Encrypts the cleartext passwords into the form that is sent over // the network. Before computing the OWF passwords, the cleartext forms // are upper cased, then OEMed (the order is significant). The cleartext // password to be sent is OEMed only. // //Arguments: // //Return Value: DWORD SampEncryptLmPasswords( LPSTR OldUpcasePassword, LPSTR NewUpcasePassword, LPSTR NewPassword, PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldLm, PENCRYPTED_NT_OWF_PASSWORD OldLmOwfEncryptedWithNewLm ) { LM_OWF_PASSWORD OldLmOwfPassword; LM_OWF_PASSWORD NewLmOwfPassword; PSAMPR_USER_PASSWORD NewLm = (PSAMPR_USER_PASSWORD) NewEncryptedWithOldLm; struct RC4_KEYSTRUCT Rc4Key; bool Status; memset(&Rc4Key, 0, sizeof(RC4_KEYSTRUCT)); // // Calculate the LM OWF passwords // Status = CalculateLmOwfPassword( OldUpcasePassword, &OldLmOwfPassword ); if (Status) { Status = CalculateLmOwfPassword( NewUpcasePassword, &NewLmOwfPassword ); } // // Calculate the encrypted old passwords // if (Status) { Status = EncryptLmOwfPwdWithLmOwfPwd( &OldLmOwfPassword, &NewLmOwfPassword, OldLmOwfEncryptedWithNewLm ); } // // Calculate the encrypted new passwords // if (Status) { // // Compute the encrypted new password with LM key. // rc4_key( &Rc4Key, (DWORD)LM_OWF_PASSWORD_LENGTH, (PUCHAR)&OldLmOwfPassword ); memcpy( ((PUCHAR) NewLm->Buffer) + (SAM_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) - strlen(NewPassword), NewPassword, strlen(NewPassword) ); //**************************************************** //BUGBUG: We must swap the significant bytes on Mac68K //**************************************************** NewLm->Length = strlen(NewPassword); NewLm->Length = ntoh(NewLm->Length); rc4(&Rc4Key, sizeof(SAMPR_USER_PASSWORD), (PUCHAR) NewLm->Buffer ); } if (Status) { return(ERROR_SUCCESS); } else return(ERROR_INVALID_FUNCTION); }