NWTP Note 0501 "About the encryption mechanism" This note discribes the password encryption mechanisms as used by Novell Netware 3.x/4.x. Passwords are encrypted by workstations and servers. The password verification process is also based on encryption. This note describes the entire process of password verification and password change. It has 3 appendices: 1. A description of the ASM calls involved with encrypted passwords; 2. Sourcecode of the encryption routines and tables in Turbo Pascal; 3. Sourcecode of the encryption routines and tables in C. Initial state ============= Our transaction model starts with a description of the initial state of the server. The following tables are stored at the server: -The EncryptionKeyTable, containing an 8 byte EncryptionKey for every workstation connection. This table can be queried by workstations using the GetEncryptionKey (INT 21h, AX=F217h, subf. 17h). Table entry [c] is renewed whenever connection c used a call using encrypted passwords. -The PasswordTable containing an 16 Byte encrypted password (socalled "Shuffled" Password) for every connection. A short description of the various encryption mechanisms involved: -Shuffling. ('S' for short) The encryption of the password (string of char) into 16 bytes (the shuffled password), using a number of static tables and the objectID of the object the password is associated with. In Mathematical terms: ShuffledPassWord=S(PasswordString) or Spw=S(pw) -Encryption ('E' for short) The main encryption process, encrypting the shuffled password (S(pw) for short) into 8 bytes, using the same static tables as the Shuffling functions and a dynamic encryption key requested from the server. In mathematical terms: EncryptedPassWord=E(EncryptionKey,ShuffledPassword) or Epw=E(Ekey,Spw) -EncryptDifference ('D' for short) Encrypts the 'difference' between the Shuffled old password and the Shuffled new password, using a static table. The encrypted difference is passed to the server. The computed 'difference' consist of 16 bytes of data and 1 checksum byte. In mathematical terms: PasswordDiff=D(ShuffledOldPW,ShuffledNewPW) or pwDiff=D(SOpw,SNpw) -DecryptDifference ('Dinv' for short) Server decryption process. Decrypts a 'password-difference' encrypted block as suplied by a workstation to a shuffled version of the new password. The shuffled old password, as stored in the servers' EncryptionKeyTable is used in the decryption process. In mathematical terms: ShuffledNewPW=Dinv(ShuffledOldPW,PasswordDiff) or SNpw=Dinv(SOpw,pwDiff) Notes:-ShuffledOldPassword is taken by the server from its' EncryptionKeyTable, i.e. ShuffledOldPassword=EncryptionKeyTable[c] where c is the connection number of the object the password is associated with. -SNpw=Dinv(SOpw,D(SNpw,Opw)), hence the name "D inverse". -GenerateNewKey ('GNK' for short) The server process creating a new encryption key for a certain connection after the previous one has been used by that connection. In mathematical terms: EncryptionKeyTable[c]:=GenerateNewKey(EncryptionTable[c]) Password Verification ===================== Password verification procedure when the encrypted password calls (VerifyEncrBinderyObjectPassword and LoginEncrToFileServer) are used: Workstation Server =========== ====== GetEncryptionKey ----------------> Return EncryptionKeyTable[c] EncrKey <--------------------- Epw:=E(EncrKey,S(pw)) Verify/Login(Epw) ---------------> Epw'=E(EncryptionKeyTable[c], PasswordTable[c]) Epw'=Epw ? completion code <-------------------- EncryptionKeyTable[c]= GNK(EncryptionKeyTable[c]) Note: c = Workstation connection number pw = Password (string, max. 128 characters) Epw= Encrypted Password (8 bytes) Password verification procedure when the calls using unencrypted passwords (VerifyBinderyObjectPassword and LoginToFileserver) are used in combination with a 3.x server: Workstation Server =========== ====== Verify/Login(pw) ----------------> S(pw)=PasswordTable[c] ? completion code <-------------------- EncryptionKeyTable[c]= GNK(EncryptionKeyTable[c]) Note: c = Workstation connection number pw = Password (string, max. 128 characters) Changing Passwords ================== The process of changeing a password using encrypted passwords: Workstation Server =========== ====== GetEncryptionKey ----------------> Return EncryptionKeyTable[c] EncrKey <--------------------- SOpw=S(oldPW) SNpw=S(newPW) EOpw=E(encrKey,SOpw) PWdif=D(SNpw,SOpw) ChangeEncrBinderyObjPW (EOpw,PWdiff) --------------> Epw'=E(EncryptionKeyTable[c], PasswordTable[c]) Epw'=Epw ? completion code <-------------------- SNpw'=Dinv(PasswordTable[c], PWdiff) PasswordTable[c]=SNpw' EncryptionKeyTable[c]= GNK(EncryptionKeyTable[c]) Note: c = Workstation connection number OldPW = Old password (string, max. 128 characters) NewPW = New password (string, max. 128 characters) SNpw = Shuffled new password (12 bytes) SOpw = Shuffled old password (12 bytes) EOpw = Encrypted old Password (8 bytes) THe process of chageing a password when using unencrypted passwords: Workstation Server =========== ====== ChangeBinderyObjPW (OldPW,NewPW) --------------> S(OldPW)=PasswordTable[c] ? completion code <-------------------- PasswordTable[c]=S(NewPW) EncryptionKeyTable[c]= GNK(EncryptionKeyTable[c]) Note: c = Workstation connection number OldPW = Old password (string, max. 128 characters) NewPW = New password (string, max. 128 characters) Sources: NVPW.C by Itsme [Itsme@Hacktic.nl] LOGON.PAS by Barry Nance/Terje Mathesen, Byte, March 1993.