NamesGVAuthImpl.Mesa
Last modified by Swinehart, June 13, 1984 3:21:12 pm PDT
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;
for A talking to B using key CK, contains:
{KY}KB, spare, { {CK}KB, spare, time, A }KY .
The keys are single cipher blocks.
-- 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;
Preliminaries
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];
Here's the authenticate portion
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;
Here's the linkage to the RPC data structures.
RETURN[RPCSecurity.EntryGenerate[level, iv, caller, callee, convKey, authenticator]];
};
}.