DIRECTORY DESFace USING [ Block, CBCCheckEncrypt, CorrectParity, EncryptBlock, GetRandomIV, GetRandomKey, IV, Key, nullKey ], NamesGV USING [ Authenticity, GVAuthenticate, GVIsAuthenticated ], NamesRPC, Rope USING [ Length ], RPC USING [ AuthenticateFailed, ConversationLevel, EncryptionKey, maxPrincipalLength, Principal ], RPCInternal USING [ Authenticator, AuthenticatorObject, ConversationObject ], RPCSecurity USING [ CopyPrincipal, EntryGenerate ] ; NamesGVAuthImpl: CEDAR PROGRAM IMPORTS DESFace, NamesGV, Rope, RPC, RPCSecurity EXPORTS NamesRPC, RPC SHARES RPCSecurity = { Conversation: TYPE = REF ConversationObject; ConversationObject: PUBLIC TYPE = RPCInternal.ConversationObject; Authenticator: TYPE = RPCInternal.Authenticator; -- The rest is encrypted with CBC-check using a zero IV -- AuthenticatorLayout: TYPE = MACHINE DEPENDENT RECORD[ ky(0): DESFace.Key, kySpare(4): DESFace.Key, -- space for larger keys! -- ck(8): DESFace.Key, ckSpare(12): DESFace.Key, -- space for larger keys! -- time(16): LONG CARDINAL, a(18): StringBody]; StartConversation: PUBLIC PROC[ caller: RPC.Principal, key: RPC.EncryptionKey, callee: RPC.Principal, level: RPC.ConversationLevel] RETURNS[ conversation: Conversation] = TRUSTED { authenticator: Authenticator; convKey: DESFace.Key; iv: DESFace.IV; nBlks: CARDINAL =( SIZE[AuthenticatorLayout] - SIZE[StringBody[0]] + SIZE[StringBody[caller.Length[]]] + SIZE[DESFace.Block]-1 --rounding-- ) / SIZE[DESFace.Block]; IF caller.Length[] > RPC.maxPrincipalLength THEN ERROR RPC.AuthenticateFailed[badCaller]; IF callee.Length[] > RPC.maxPrincipalLength THEN ERROR RPC.AuthenticateFailed[badCallee]; SELECT NamesGV.GVAuthenticate[rName: caller, key: key] FROM unknown => ERROR RPC.AuthenticateFailed[communications]; nonexistent => ERROR RPC.AuthenticateFailed[badCaller]; bogus, perhaps => ERROR RPC.AuthenticateFailed[badKey]; authentic => NULL; ENDCASE => ERROR; SELECT NamesGV.GVIsAuthenticated[callee] FROM unknown => ERROR RPC.AuthenticateFailed[communications]; nonexistent => ERROR RPC.AuthenticateFailed[badCallee]; bogus, perhaps, authentic => NULL; ENDCASE => ERROR; iv _ DESFace.GetRandomIV[]; authenticator _ NEW[RPCInternal.AuthenticatorObject[nBlks]]; BEGIN kb: DESFace.Key _ DESFace.nullKey -- !!! --; authRec: LONG POINTER TO AuthenticatorLayout = LOOPHOLE[@authenticator[0]]; authRec.ky _ DESFace.GetRandomKey[]; authRec.ck _ convKey _ DESFace.GetRandomKey[]; authRec.time _ 0; RPCSecurity.CopyPrincipal[from: caller, to: @(authRec.a)]; DESFace.CorrectParity[@kb]; DESFace.EncryptBlock[key: kb, from: LOOPHOLE[@authRec.ck], to: LOOPHOLE[@authRec.ck] ]; DESFace.CBCCheckEncrypt[key: authRec.ky, nBlks: nBlks-2, from: LOOPHOLE[@authRec.ck], to: LOOPHOLE[@authRec.ck], seed: [0,0,0,0] ]; DESFace.EncryptBlock[key: kb, from: LOOPHOLE[@authRec.ky], to: LOOPHOLE[@authRec.ky] ]; END; RETURN[RPCSecurity.EntryGenerate[level, iv, caller, callee, convKey, authenticator]]; }; }. .NamesGVAuthImpl.Mesa Last modified by Swinehart, June 13, 1984 3:21:12 pm PDT for A talking to B using key CK, contains: {KY}KB, spare, { {CK}KB, spare, time, A }KY . The keys are single cipher blocks. Preliminaries Here's the authenticate portion Here's the linkage to the RPC data structures. �Êo˜Jšœ™Jšœ8™8J˜šÏk ˜ Jšœ�œS�œ˜sJšœ�œ5˜BJ˜ Jšœ�œ ˜Jš�œ�œY˜bJšœ �œ<˜MJšœ �œ!˜2J˜J˜—šœ� ˜Jš�œ�œ ˜0Jš�œ�œ˜,J˜Jšœ�œ�œ˜,Jšœ� œ"˜A—J˜šœ�œ˜0Jšœ*™*Jšœ-™-Jšœ"™"JšÏc:˜:—J˜š œ�œ�œ� œ�œ˜5Jšœ˜Jšœž˜6Jšœ˜Jšœž˜6Jšœ �œ�œ˜Jšœ˜—J˜šÏnœ�œ�œ˜Jš œ�œ�œ�œ�œ˜cJš�œ �œ˜0J˜J˜Jšœ �œ˜™ šœ�œ�œ˜.Jš�œ˜Jš�œ˜#Jš�œž œ�œ˜;—š�œ*�˜0Jš�œ#˜(—š�œ*�˜0Jš�œ#˜(——šœ™š�œ1�˜;Jšœ �œ�œ$˜8Jšœ�œ�œ˜7Jšœ�œ�œ˜7Jšœ �œ˜Jš�œ�œ˜—š�œ#�˜-Jšœ �œ�œ$˜8Jšœ�œ�œ˜7Jšœ�œ˜"Jš�œ�œ˜—J˜Jšœ�œ)˜<š�˜Jšœ"ž œ˜,Jš œ �œ�œ�œ�œ˜KJšœ$˜$Jšœ.˜.Jšœ˜Jšœ:˜:Jšœ˜šœ˜Jšœ�œ˜Jšœ�œ˜—šœ(˜(Jšœ˜Jšœ�œ˜Jšœ�œ˜Jšœ˜—šœ˜Jšœ�œ˜Jšœ�œ˜—Jš�œ˜——šœ.™.Jš�œO˜U—J˜—J˜J˜—…— œ9