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
16 KiB

// encrypt.c // contains all encryption code necessary for MSUAM encryption #include <string.h> #include "encrypt.h" #include "UAMDebug.h" /*-------------------------------------------------------------------*\ DES defines. \*-------------------------------------------------------------------*/ unsigned char *IP; unsigned char *FP; unsigned char *PC1_C; unsigned char *PC1_D; unsigned char *PC2_C; unsigned char *PC2_D; unsigned char *SHIFTS; unsigned char *E; unsigned char S[8][64]; unsigned char *P; /*-------------------------------------------------------------------*\ DES structure. \*-------------------------------------------------------------------*/ typedef struct _desdata { char header[4]; unsigned char IP[64]; unsigned char FP[64]; unsigned char PC1_C[28]; unsigned char PC1_D[28]; unsigned char SHIFTS[16]; unsigned char PC2_C[24]; unsigned char PC2_D[24]; unsigned char E[48]; unsigned char S[8][64]; unsigned char P[32]; } desdata, *PDesData, **HDesData; static Handle ghMSUAMDesData = NULL; // static global handle (e.g. this file global only) // --------------------------------------------------------------------------- // ¥ SetupUAMEncrypt() // --------------------------------------------------------------------------- // Setup the table. // // Returns TRUE if the data resource was successfully read into memory, FALSE // otherwise. Boolean SetupUAMEncrypt( void ) { PDesData pdd; ghMSUAMDesData = GetResource('data', 2); if (ghMSUAMDesData == NULL) { DbgPrint_((DBGBUFF, "Couldn't get 'data' resource")); return(false); } HLock(ghMSUAMDesData); HNoPurge(ghMSUAMDesData); pdd = *(HDesData)ghMSUAMDesData; IP = pdd->IP; FP = pdd->FP; PC1_C = pdd->PC1_C; PC1_D = pdd->PC1_D; SHIFTS = pdd->SHIFTS; PC2_C = pdd->PC2_C; PC2_D = pdd->PC2_D; E = pdd->E; BlockMove(pdd->S, S, 8*64); P = pdd->P; return(true); } // --------------------------------------------------------------------------- // ¥ CleanupUAMEncrypt() // --------------------------------------------------------------------------- void CleanupUAMEncrypt( void ) { if (ghMSUAMDesData) { HUnlock(ghMSUAMDesData); HPurge(ghMSUAMDesData); ReleaseResource(ghMSUAMDesData); } } // --------------------------------------------------------------------------- // ¥ UprCString() // --------------------------------------------------------------------------- void UprCString(char* psz) { c2pstr(psz); UpperString(*(Str255 *)psz, true); // really a pstr right now p2cstr((StringPtr)psz); } // --------------------------------------------------------------------------- // ¥ OneWayFunction() // --------------------------------------------------------------------------- // Inputs - P14 // Outputs - P22 // // Let P14 be the plain text password obtained at logon time, *passed in as a // zero-terminated string and null padded herein to max length*. // // P14 is used to encrypt the standard text, S8, and get P21. // Encryption of standard text is accomplished with an option (ENCR_STD) // to CryptIOCTL_2. // // P21[0..7] = E(P14[0..6], S8) // P21[8..15] = E(P14[7..13], S8) // P21[16..20] = 0 unsigned char *OneWayFunction(unsigned char *pucPwd, unsigned char *pucDest, short scb) { SInt16 len = strlen((char *)pucPwd); Assert_(pucPwd != NULL); Assert_(pucDest != NULL); if (len > scb) { Assert_(0); return (pucDest); } memset((char *)pucPwd+len, '\0', scb-len); CryptIOCTL2(ENCR_STD, pucPwd, nil, pucDest); CryptIOCTL2(ENCR_STD, pucPwd+7, nil, pucDest+8); memset((char *)pucDest + 16, '\0', 5); return(pucDest); } // --------------------------------------------------------------------------- // ¥ Encrypt() // --------------------------------------------------------------------------- // Inputs - P21 (from OneWayChallenge()) // Outputs - P24 // // P21 is used to encrypt the challenge, C8 sent by the server, to // get P24, which is the response sent back to the server. // // P24[0..7] = E(P21[0..6], C8) // P24[8..15] = E(P21[7..13], C8) // P24[16..23] = E(P21[14..20], C8) unsigned char *Encrypt(unsigned char *key, unsigned char *source, unsigned char *dest) { Assert_(key != NULL); Assert_(source != NULL); Assert_(dest != NULL); CryptIOCTL2(ENCR_KEY, source, key, dest); CryptIOCTL2(ENCR_KEY, source+7, key, dest+8); CryptIOCTL2(ENCR_KEY, source+14, key, dest+16); return(dest); } /************* Macintosh RDEV-environment version hacked by Wayne F. Tackabury, Pacer Software. Adapted from OS/2 version by Narendra Gidwani. Primary modifications: -- StdEncrPwd turned into #define -- Allocation of a large table for underlying DES code to store its encryption tables. Primary motivation: in this environment, we have no global data context to work with. Copyright (c) 1992 Microsoft Corp. ************/ /* Standard text for the ENCR_STD operation */ // --------------------------------------------------------------------------- // ¥ CryptIOCTL2() // --------------------------------------------------------------------------- unsigned pascal CryptIOCTL2( unsigned Option, unsigned char* Key, unsigned char* Src, unsigned char* Dst ) { unsigned char Buffer[8]; unsigned char CBuffer[8]; KeyTbl* allocatedKeyTable; if (Dst == NULL) { Assert_(0); return 1; } Dst[0] = 0; Dst[7] = 0; if (!Src && Option != ENCR_STD) { Assert_(0); return(1); } // //Allocate the key table which the underlying routines will need to generate //their de/en-cryption tables // if ((allocatedKeyTable = (KeyTbl *) NewPtrClear(sizeof(KeyTbl))) == nil) return(1); if (Option == ENCR_STD) memcpy(Buffer, StdEncrPwd, 8); else memcpy(Buffer, Src, 8); InitKey(Key, allocatedKeyTable); switch (Option) { case ENCR_KEY: case ENCR_STD: des( Buffer, CBuffer, allocatedKeyTable, ENCRYPT ); break; case DECR_KEY: des( Buffer, CBuffer, allocatedKeyTable, DECRYPT ); break; default: Assert_(0); DisposePtr((Ptr) allocatedKeyTable); return(1); } // //We have results. Copy them across, deallocate our key table heap, and return. // memcpy(Dst, CBuffer, 8); DisposePtr((Ptr) allocatedKeyTable); return(0); } /* ** This file contains all the routines necessary for implementation of ** Federal Information Processing Data Encryption Standard (DES). ** Sytek Inc., Linden S. Feldman ** ** This file contains the following high level DES routines: ** ** setkey(key); set an 8 byte key for subsequent encrypt/decrypt. ** encrypt(buf); encrypt an 8 byte binary buffer. ** decrypt(buf); decrypt an 8 byte binary buffer. ** ede( buf, l, r ); encrypt buf with key encrypting key parts l and r. ** ded( buf, l, r ); decrypt buf with key encrypting key parts l and r. ** ** ** Also in this file are the following low level DES routines: ** ** key_table(key) called by setkey() to init key table. ** des(buf,crypt_mode) called by encrypt() and decrypt(). ** des_cipher(buf,crypt_mode) called by des(). */ /** Macintosh rdev/Chooser environment version hacked by Wayne Tackabury, Pacer Software, Inc. Sunday, August 9, 1992. Copyright (c) 1992 Pacer Software, Inc.,La Jolla, CA 92037 Copyright (c) 1992 Microsoft Corp. PRIMARY MODIFICATIONS: In this environment, we have no global data context, and certainly no capa- bility for autoinitialization of same. What we must do instead is to either externally reference constant tablular/heap information which can be stored in the outermost assembly-code storage of this containing module, or dynamically allocate what we actually need to modify. I cheated even further, stuffing some tables into automatic storage of routines herein, since in this envrionment, we are considerably more blessed with stack space than we are with static heap. -> the following arrays previously declared globally are now in the routines indicated C[], D[] key_table() L[], tempL[], f[] des_cipher(); -> The key selector table, previously just known as KS[][], is now defined in typedef KeyTbl. A pointer to an allocated KeyTbl is now an input parameter to InitKey(), Key_table(), des(), and des_cipher. -> Also, SetKey() was deleted since it didn't seem to get called and I would like to save some code resource space here where I can. -> Also, function desf(), which was just dealing with far/near insecurities for data addressing was removed since we don't worry about that in this environment. -> last, various PC/Microsoft C-centric typedefs (e.g., "_cdecl") were axed. **/ // --------------------------------------------------------------------------- // ¥ key_table() // --------------------------------------------------------------------------- // Set up the key table (schedule) from the key. void key_table(unsigned char *key, KeyTbl *generatedKeyTable) { register int i, j; unsigned short k, t; /* ** The C and D arrays used to calculate the key schedule. */ unsigned char C[28]; unsigned char D[28]; /* ** First, generate C and D by permuting ** the key. The low order bit of each ** 8-bit unsigned char is not used, so C and D are only 28 ** bits apiece. */ for (i=0; i<28; i++) { C[i] = key[PC1_C[i]]; D[i] = key[PC1_D[i]]; } /* ** To generate Ki, rotate C and D according ** to schedule and pick up a permutation ** using PC2. */ for (i=0; i<16; i++) { /* ** rotate. */ for (k=0; k<SHIFTS[i]; k++) { t = C[0]; for (j=0; j<28-1; j++) C[j] = C[j+1]; C[27] = (unsigned char) t; t = D[0]; for (j=0; j<28-1; j++) D[j] = D[j+1]; D[27] = (unsigned char) t; } /* ** get Ki. Note C and D are concatenated. */ for (j=0; j<24; j++) { generatedKeyTable->KS[i][j] = C[PC2_C[j]]; generatedKeyTable->KS[i][j+24] = D[PC2_D[j]]; } } } // --------------------------------------------------------------------------- // ¥ des_cipher() // --------------------------------------------------------------------------- // The payoff: encrypt or decrypt a block depending on crypt_mode = 0 or 1 // respectively. void des_cipher(unsigned char *block, KeyTbl *keySchedule, int crypt_mode) { register int i, j; int ii, v, t, k, tblIndex; /* ** The current block, divided into 2 halves. */ unsigned char L[64]; // unsigned char R[32]; /* ** R[32] not used. ** Normally L[64] would be set to L[32] and R[32] is not accessed directly ** but indirectly through extended access of L[32+j] where j is 0 - 32. ** Due to INTEL byte swapping some C compilers align arrays on even ** boundaries, some worse yet on paragraph boundaries, so L[32] was ** modified to be L[64] in order to correctly handle the extended accessing. */ unsigned char tempL[32]; unsigned char f[32]; /* ** The combination of the key and the input, before selection. */ unsigned char preS[48]; /* ** First, permute the bits in the input */ for (j=0; j<64; j++) { tblIndex = (int)IP[j]; L[j] = block[tblIndex]; } /* ** Perform an encryption operation 16 times. */ for (ii=0; ii<16; ii++) { /* ** Set direction */ if (crypt_mode) i = 15-ii; else i = ii; /* ** Save the R array, ** which will be the new L. */ for (j=0; j<32; j++) tempL[j] = L[j+32]; /* ** Expand R to 48 bits using the E selector; ** exclusive-or with the current key bits. */ for (j=0; j<48; j++) preS[j] = L[E[j]+32] ^ keySchedule->KS[i][j]; /* ** The pre-select bits are now considered ** in 8 groups of 6 bits each. ** The 8 selection functions map these ** 6-bit quantities into 4-bit quantities ** and the results permuted to make an f(R, K). ** The indexing into the selection functions ** is peculiar; it could be simplified by ** rewriting the tables. */ for (j=0; j<8; j++) { t = 6*j; v = j; k = S[v][(preS[t+0]<<5)+ (preS[t+1]<<3)+ (preS[t+2]<<2)+ (preS[t+3]<<1)+ (preS[t+4]<<0)+ (preS[t+5]<<4)]; t = 4*j; f[t+0] = (unsigned char) ((k>>3)&01); f[t+1] = (unsigned char) ((k>>2)&01); f[t+2] = (unsigned char) ((k>>1)&01); f[t+3] = (unsigned char) ((k>>0)&01); } /* end of for loop doing the 8 groups of pre-select bits */ /* ** The new R is L ^ f(R, K). ** The f here has to be permuted first, though. */ for (j=0; j<32; j++) L[j+32] = L[j] ^ f[P[j]]; /* ** Finally, the new L (the original R) ** is copied back. */ for (j=0; j<32; j++) L[j] = tempL[j]; } /* end of encrypted operation (16 times) */ /* ** The output L and R are reversed. */ for (j=0; j<32; j++) { t = L[j]; L[j] = L[j+32]; L[j+32] = (unsigned char) t; } /* ** The final output ** gets the inverse permutation of the very original. */ for (j=0; j<64; j++) block[j] = L[FP[j]]; } // --------------------------------------------------------------------------- // ¥ des() // --------------------------------------------------------------------------- void des(unsigned char *inbuf, unsigned char *outbuf, KeyTbl *keySchedule, int crypt_mode) { register int i, j; unsigned char block[64]; for(i=0; i<64; i++) block[i] = 0; /* ** expand the bytes into a bit table. */ for(i=0; i<8; i++) for(j=0; j<8; j++) block[8*i+j]=(unsigned char)((inbuf[i] >> (7-j)) & 01); des_cipher( block, keySchedule, crypt_mode ); for(i=0; i<8; i++) { /* compress */ outbuf[i] = 0; for(j=0; j<8; j++) { outbuf[i] <<= 1; outbuf[i] |= block[8*i+j]; } } } // --------------------------------------------------------------------------- // ¥ InitKey() // --------------------------------------------------------------------------- void InitKey(unsigned char *Key, KeyTbl *generatedKeyTable) { register int i, j, k; unsigned char block[64]; k = 0; memset((char *)block, 0, 64); for (i = 0; i < 8 ; i++ ) { for (j = 0 ; j < 7 ; j++ ) { block[8*i + j] = GETBIT(Key, k); k++; } } key_table(block, generatedKeyTable); }