DIRECTORY
Agent
USING [ Authentication, AuthenticationRecord,
Authenticator, AuthenticatorLayout, Frob, FrobRecord, Principal ],
AgentRpcControl USING [ ExportInterface, InterfaceName ],
DESFace
USING [ Block, Blocks, CBCCheckEncrypt, CorrectParity,
EncryptBlock, GetRandomKey, Key, nullKey ],
IO,
Log USING [ Report, Problem ],
Names USING [ CurrentPasskey, GetDefaultInstance, GetDefaultDetails, GetGVDetails, GVDetails, Results ],
PupDefs USING [ GetPupAddress, PupAddress ],
PupTypes USING [ PupHostID, PupNetID ],
Rope USING [ Length, Flatten, ROPE ],
RPC USING [ EncryptionKey, matchAllVersions, ShortROPE, VersionRange ],
RPCPkt USING [ Machine ],
RPCSecurity USING [ CopyPrincipal ],
UserProfile USING [ Token ]
;
Authenticate:
PUBLIC
PROC [ nonceId:
LONG
INTEGER, a, b: Agent.Principal ]
RETURNS [ an: Agent.Frob,
ar: Agent.Frob ] = TRUSTED {
ka, kb: DESFace.Key ← DESFace.nullKey -- !!! --;
kx, ky, ck: DESFace.Key;
aLen: NAT=a.Length[];
bLen: NAT=b.Length[];
authenticator: Agent.Authenticator;
authentication: Agent.Authentication;
nBlks: NAT ← DESBlocks[SIZE[Agent.AuthenticatorLayout[aLen]]];
IF a=
NIL
OR b=
NIL
OR aLen=0
OR bLen=0
THEN
{
Log.Problem["Authenticate: Null arguments", $System]; RETURN[NIL, NIL]; };
ar ← NEW[Agent.FrobRecord[nBlks*blockSize]];
authenticator ← LOOPHOLE[@ar[0]];
a ← a.Flatten[];
b ← b.Flatten[];
DESFace.CorrectParity[@ka];
DESFace.CorrectParity[@kb];
kx ← DESFace.GetRandomKey[];
ky ← DESFace.GetRandomKey[];
ck ← DESFace.GetRandomKey[];
-- Build and encrypt Authenticator --
DESFace.EncryptBlock[key: kb, from: Blk[LONG[@ky]], to: Blk[@authenticator.ky ]];
DESFace.EncryptBlock[key: kb, from: Blk[LONG[@ck]], to: Blk[@authenticator.ck ]];
authenticator.time ← 0;
RPCSecurity.CopyPrincipal[from: a, to: @(authenticator.a)];
DESFace.CBCCheckEncrypt[key: ky, nBlks: nBlks-2, from: Blks[@authenticator.ck],
to: Blks[@authenticator.ck], seed: [0,0,0,0] ];
Encrypt the whole thing for a's benefit
DESFace.CBCCheckEncrypt[key: kx, nBlks: nBlks, from: Blks[@authenticator.ky],
to: Blks[@authenticator.ky], seed: [0,0,0,0] ];
Build and encrypt Authentication
nBlks ← DESBlocks[SIZE[Agent.AuthenticationRecord[bLen]]];
an ← NEW[Agent.FrobRecord[nBlks*blockSize]];
authentication ← LOOPHOLE[@an[0]];
authentication.nonceId ← nonceId;
DESFace.EncryptBlock[key: ka, from: Blk[LONG[@kx]],to: Blk[@authentication.kx] ];
DESFace.EncryptBlock[key: ka, from: Blk[LONG[@ck]], to: Blk[@authentication.ck ]];
RPCSecurity.CopyPrincipal[from: b, to: @authentication.b];
DESFace.CBCCheckEncrypt[key: kx, nBlks: nBlks-2, from: Blks[@authentication.ck],
to: Blks[@authentication.ck], seed: [0,0,0,0] ];
Log.Report[IO.PutFR["Authenticate[%s, to; %s]", rope[a], rope[b]], $System];
DESBlocks:
PROC[len:
NAT]
RETURNS [nBlks:
NAT] = {
RETURN [
(len + blockSize - 1) / blockSize ]; };
Blk:
PROC[p:
LONG
POINTER]
RETURNS [
LONG
POINTER
TO DESFace.Block] =
TRUSTED INLINE { RETURN [LOOPHOLE[p]]; };
Blks:
PROC[p:
LONG
POINTER]
RETURNS [DESFace.Blocks] =
TRUSTED INLINE { RETURN [LOOPHOLE[p]]; };
Vitae:
PUBLIC
PROC[
clientMachine: RPCPkt.Machine,
range: RPC.VersionRange←RPC.matchAllVersions,
interfaceType: RPC.ShortROPE ]
RETURNS [
serverMachine: RPCPkt.Machine←[[0],[0]],
clientRname: Agent.Principal,
clientInstance: RPC.ShortROPE←NIL,
serverInstance: RPC.ShortROPE←NIL
] = TRUSTED {
Implements everything but range check
machineInstance: RPC.ShortROPE;
serverMachineRope: RPC.ShortROPE;
pa: PupDefs.PupAddress;
clientDetails: Names.GVDetails;
results: Names.Results;
machineInstance ← Names.GetDefaultInstance[clientMachine, FALSE];
clientInstance ← Names.GetDefaultInstance[netAddress: clientMachine!ANY=>CONTINUE];
IF clientInstance=NIL THEN clientInstance ← machineInstance;
[results, clientDetails] ← Names.GetDefaultDetails[netAddress: clientMachine];
IF results#ok OR ~clientDetails.valid OR ~clientDetails.larkSpec THEN RETURN;
clientRname ← clientDetails.connect;
serverInstance ← clientDetails.instance;
IF serverInstance = NIL THEN RETURN;
[results, clientDetails] ← Names.GetGVDetails[ serverInstance ];
IF results#ok OR ~clientDetails.valid THEN RETURN;
serverMachineRope ← clientDetails.connect;
pa ← PupDefs.GetPupAddress[[0,0], serverMachineRope];
serverMachine ← [net: pa.net, host: pa.host];
Log.Report[
IO.PutFR["Vitae[lark: %b, type: %s] -> [ rName: %s, client: %s, server: %s]",
card[clientMachine.host], rope[interfaceType], rope[clientRname], rope[clientInstance],
rope[serverInstance]], $System];
};
}.