;Alto->8086 small-c compiler rev 2.0 C←CODE SEGMENT $INCLUDE(8086LIB.D) $INCLUDE(RPCSecurity.DEC) ASSUME CS:C←CODE, DS:C←DATA ; #include <Env.h> ; extern int PktExchange(); ; extern SetupResponse(); ; extern struct ExportInstance *exportTable; ; extern union Machine myHost; ; extern int *mySoc; ; extern SendPup(); ; extern struct PBI *GetPBI(); ; extern int MultEq(); ; extern int DoubleEq(); ; extern ReleasePBI(); ; extern CryptData(); ; extern DecryptBlock(); ; extern CBCCheckDecrypt(); ; extern int DoubleComp(); ; extern int DoubleInc(); ; extern Move2(); ; extern int StringSize(); ; extern int StringSizeN(); ; extern struct ShortSTRING *ShallString(); ; extern int AuthenticateFailed; ; extern ReadCalendar(); ; extern Timer(); ; extern int *GetFixed(); ; extern MoveBlock(); ; struct ConversationID *lastConversation; ; struct PktConversationID *firstConversation; ; static struct Conversation *conversations[0]; ; int UnknownConversation; /* SIGNAL */ ; static struct EncryptionKey *ka; ; static struct EncryptionKey *kb; ; static struct EncryptionKey privateKey; /* null, for now */ ; struct Block { ; byte blockElt[8]; ; }; ; struct RFARequest { ; struct PktConversationID callerConv; ; struct PktID callerPktID; /* still encrypted , */ ; word nonceID[2]; /* nominated by requester*/ ; }; ; struct RFAResponse { ; struct IV iv; ; struct ConnectionID connection; ; struct CallCount callCt; ; word nonceID[2]; ; word level; ; struct Authenticator authenticator; ; }; ; struct EncryptionKey nullKeyB; /* = table { 0; 0; 0; 0; } */ ; struct EncryptionKey nullSeedB; /* = table { 0; 0; 0; 0; } */ ; struct Conversation ; *GenerateConversation() { ←GenerateConversation: PUSH BP MOV BP,SP ; return (EntryGenerate(slNone, nullKey, 0, 0, nullKey, 0)); XOR BX,BX PUSH BX LEA BX,←nullKeyB PUSH BX XOR BX,BX PUSH BX XOR BX,BX PUSH BX XOR BX,BX LEA CX,←nullKeyB CALL ←EntryGenerate ADD SP,8 MOV SP,BP POP BP RET; ; }; ; static struct Conversation ; *EntryGenerate(level, iv, originator, responder, convKey, auth) ←EntryGenerate: ; int /* SecurityLevel */ level; ; struct IV *iv; ; struct ShortSTRING *originator; ; struct ShortSTRING *responder; ; struct EncryptionKey *convKey; ; struct Authenticator *auth; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; DoubleInc(&lastConversation->count, 1); MOV BX,←lastConversation INC BX INC BX PUSH BX MOV BX,1 POP CX CALL ←DoubleInc ; lastConversation->count.fields &= notCalleeMask; MOV BX,←lastConversation AND WORD PTR [BX+4],0FF7FX ; return (AddConversation(lastConversation, level, iv, originator, responder, convKey, auth)); MOV BX,←lastConversation PUSH BX ; BX ← ←level MOV BX,[BP+10] PUSH BX ; BX ← ←iv MOV BX,[BP+8] PUSH BX ; BX ← ←originator MOV BX,[BP+6] PUSH BX ; BX ← ←responder MOV BX,[BP+4] PUSH BX ; BX ← ←auth MOV BX,[BP-4] ; CX ← ←convKey MOV CX,[BP-2] CALL ←AddConversation ADD SP,0AX MOV SP,BP POP BP RET; ; }; ; struct Conversation ; *StartConversation(caller, key, callee, level) ←StartConversation: ; struct ShortSTRING *caller; ; struct EncryptionKey *key; ; struct ShortSTRING *callee; ; int /* SecurityLevel */ level; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { /* RETURNS {conversation: Conversation;}; */ ; struct Authenticator *authenticator; ; struct IV iv; ; struct EncryptionKey convKey; ; if (level == slNone) SIGNAL(ERROR); /* may relax this constraint later, to allow multi clear convs. */ ADD SP,0FFEEX ; BX ← ←level MOV BX,[BP-4] OR BX,BX JNZ X1 MOV BX,2 CALL ←SIGNAL X1: ; authenticator = Authenticate(caller, key, callee, &convKey, &iv); ; BX ← ←caller MOV BX,[BP+6] PUSH BX ; BX ← ←key MOV BX,[BP+4] PUSH BX ; BX ← ←callee MOV BX,[BP-2] PUSH BX ;&←iv LEA BX,[BP-14] ;&←convKey LEA CX,[BP-22] CALL ←Authenticate ADD SP,6 ; ←authenticator ← BX MOV [BP-6],BX ; return (EntryGenerate(level, &iv, caller, callee, &convKey, authenticator)); ; BX ← ←level MOV BX,[BP-4] PUSH BX ;&←iv LEA BX,[BP-14] PUSH BX ; BX ← ←caller MOV BX,[BP+6] PUSH BX ; BX ← ←callee MOV BX,[BP-2] PUSH BX ; BX ← ←authenticator MOV BX,[BP-6] ;&←convKey LEA CX,[BP-22] CALL ←EntryGenerate ADD SP,8 MOV SP,BP POP BP RET; ; }; ; struct Authenticator ; *Authenticate(caller, key, callee, /* more results */ convKey, iv) ←Authenticate: ; struct ShortSTRING *caller; ; struct EncryptionKey *key; ; struct ShortSTRING *callee; ; struct EncryptionKey *convKey; ; struct IV *iv; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; int nBlks, authLength; ; int nonceId[2]; ; int args[5]; ; struct Authenticator *authenticator; ; struct Authentication *authentication; ; struct EncryptionKey kx; ; struct ShortSTRING *b; ; int nonceOK; ADD SP,0FFDEX ; ReadCalendar(nonceId); ;&←nonceId LEA BX,[BP-12] CALL ←ReadCalendar ; authentication = AgentAuthenticate(nonceId, caller, callee, &authenticator); ;&←nonceId LEA BX,[BP-12] PUSH BX ; BX ← ←caller MOV BX,[BP+8] PUSH BX ;&←authenticator LEA BX,[BP-24] ; CX ← ←callee MOV CX,[BP+4] CALL ←AgentAuthenticate ADD SP,4 ; ←authentication ← BX MOV [BP-26],BX ; if (authentication==0) SIGNAL(AuthenticateFailed, badCommunications); /* MORE analysis! */ ; BX ← ←authentication MOV BX,[BP-26] OR BX,BX JNZ X2 MOV BX,1 MOV CX,←AuthenticateFailed CALL ←SIGNAL X2: ; nBlks = DESBlocks(authentication->length); ; DI ← ←authentication MOV DI,[BP-26] MOV BX,[DI] CALL ←DESBlocks ; ←nBlks ← BX MOV [BP-6],BX ; DecryptBlock(ka, &authentication->kx, &kx); MOV BX,←ka PUSH BX ; BX ← ←authentication MOV BX,[BP-26] INC BX INC BX PUSH BX ;&←kx LEA BX,[BP-34] POP CX CALL ←DecryptBlock POP DX ; CBCCheckDecrypt(&kx, nBlks-2, &authentication->ck, &authentication->ck, nullSeed); ;&←kx LEA BX,[BP-34] PUSH BX ; BX ← ←nBlks MOV BX,[BP-6] DEC BX DEC BX PUSH BX ; BX ← ←authentication MOV BX,[BP-26] ADD BX,012X PUSH BX ; BX ← ←authentication MOV BX,[BP-26] ADD BX,012X PUSH BX LEA BX,←nullSeedB POP CX CALL ←CBCCheckDecrypt ADD SP,6 ; nonceOK = (nonceId[0] == swab(authentication->nonceId[0]) && ; nonceId[1] == swab(authentication->nonceId[1])); ; BX ← ←authentication MOV BX,[BP-26] ADD BX,022X MOV CX,[BX] MOV BX,CX CALL ←swab ; CX ← ←nonceId MOV CX,[BP-12] CMP CX,BX JNZ X3 ; BX ← ←authentication MOV BX,[BP-26] ADD BX,022X MOV CX,[BX+2] MOV BX,CX CALL ←swab ; CX ← ←nonceId+2 MOV CX,[BP-10] CMP CX,BX X3: JNZ X4 MOV BX,1 JR X5 X4: XOR BX,BX X5: ; ←nonceOK ← BX POP DX PUSH BX ; b = ShallString(0, &authentication->b.length, 2); XOR BX,BX PUSH BX ; BX ← ←authentication MOV BX,[BP-26] ADD BX,026X PUSH BX MOV BX,2 POP CX CALL ←ShallString POP DX ; ←b ← BX MOV [BP-36],BX ; if ((!nonceOK) || !EquivalentStrings(callee, b)) SIGNAL(AuthenticateFailed, badKey); ; BX ← ←nonceOK POP BX PUSH BX OR BX,BX JZ X8 ; BX ← ←b MOV BX,[BP-36] ; CX ← ←callee MOV CX,[BP+4] CALL ←EquivalentStrings OR BX,BX X8: X7: JNZ X6 MOV BX,3 MOV CX,←AuthenticateFailed CALL ←SIGNAL X6: ; DecryptBlock(ka, &authentication->ck, convKey); MOV BX,←ka PUSH BX ; BX ← ←authentication MOV BX,[BP-26] ADD BX,012X PUSH BX ; BX ← ←convKey MOV BX,[BP-2] POP CX CALL ←DecryptBlock POP DX ; nBlks = DESBlocks(authenticator->length); ; DI ← ←authenticator MOV DI,[BP-24] MOV BX,[DI] CALL ←DESBlocks ; ←nBlks ← BX MOV [BP-6],BX ; CBCCheckDecrypt(&kx, nBlks, &authenticator->ky, &authenticator->ky, nullSeed); ;&←kx LEA BX,[BP-34] PUSH BX ; BX ← ←nBlks MOV BX,[BP-6] PUSH BX ; BX ← ←authenticator MOV BX,[BP-24] INC BX INC BX PUSH BX ; BX ← ←authenticator MOV BX,[BP-24] INC BX INC BX PUSH BX LEA BX,←nullSeedB POP CX CALL ←CBCCheckDecrypt ADD SP,6 ; GetRandomIV(iv); ; BX ← ←iv MOV BX,[BP-4] CALL ←GetRandomIV ; return (authenticator); ; BX ← ←authenticator MOV BX,[BP-24] MOV SP,BP POP BP RET; ; }; ; static struct Conversation ; *AddConversation(id, level, iv, originator, responder, convKey, auth) ←AddConversation: ; struct ConversationID *id; ; int /* SecurityLevel */ level; ; struct IV *iv; ; struct ShortSTRING *originator; ; struct ShortSTRING *responder; ; struct EncryptionKey *convKey; ; struct Authenticator *auth; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct Conversation *conversation, *dataPtr; ADD SP,0FFFCX ; dataPtr = (struct Conversation *) &conversations[swab(id->count.LS) & 127]; ; BX ← ←id MOV BX,[BP+12] MOV CX,[BX+2] MOV BX,CX CALL ←swab AND BX,07FX MOV CX,←conversations SAL BX ADD BX,CX ; ←dataPtr ← BX POP DX PUSH BX ; while (conversation=dataPtr->next) { X9: ; DI ← ←dataPtr POP DI PUSH DI MOV BX,[DI] ; ←conversation ← BX MOV [BP-6],BX OR BX,BX JZ X10 ; if (MultEq(&conversation->id, id, lenConversationID)) return conversation; ; BX ← ←conversation MOV BX,[BP-6] INC BX INC BX PUSH BX MOV BX,3 ; CX ← ←id MOV CX,[BP+12] CALL ←MultEq POP DX OR BX,BX JZ X11 ; BX ← ←conversation MOV BX,[BP-6] MOV SP,BP POP BP RET; X11: ; dataPtr = conversation; ; BX ← ←conversation MOV BX,[BP-6] ; ←dataPtr ← BX POP DX PUSH BX ; }; JR X9 X10: ; conversation = (struct Conversation *) GetFixed(lenConversationObject); MOV BX,010X CALL ←GetFixed ; ←conversation ← BX MOV [BP-6],BX ; MoveBlock(&conversation->id, id, lenConversationID); ; BX ← ←conversation MOV BX,[BP-6] INC BX INC BX PUSH BX MOV BX,3 ; CX ← ←id MOV CX,[BP+12] CALL ←MoveBlock POP DX ; conversation->level = level; ; BX ← ←conversation MOV BX,[BP-6] ; CX ← ←level MOV CX,[BP+10] MOV [BX+8],CX ; MoveBlock(&conversation->key, convKey, lenEncryptionKey); ; BX ← ←conversation MOV BX,[BP-6] ADD BX,0AX PUSH BX MOV BX,4 ; CX ← ←convKey MOV CX,[BP-2] CALL ←MoveBlock POP DX ; MoveBlock(&conversation->iv, iv, lenIV); ; BX ← ←conversation MOV BX,[BP-6] ADD BX,012X PUSH BX MOV BX,4 ; CX ← ←iv MOV CX,[BP+8] CALL ←MoveBlock POP DX ; conversation->originator = ShallString(0, originator, 0); ; BX ← ←conversation MOV BX,[BP-6] PUSH BX XOR BX,BX PUSH BX XOR BX,BX ; CX ← ←originator MOV CX,[BP+6] CALL ←ShallString POP DX MOV CX,BX POP BX MOV [BX+26],CX ; conversation->responder = ShallString(0, responder, 0); ; BX ← ←conversation MOV BX,[BP-6] PUSH BX XOR BX,BX PUSH BX XOR BX,BX ; CX ← ←responder MOV CX,[BP+4] CALL ←ShallString POP DX MOV CX,BX POP BX MOV [BX+28],CX ; conversation->authenticator = auth; /* Assume I can keep it. */ ; BX ← ←conversation MOV BX,[BP-6] ; CX ← ←auth MOV CX,[BP-4] MOV [BX+30],CX ; dataPtr->next = conversation; ; BX ← ←dataPtr POP BX PUSH BX ; CX ← ←conversation MOV CX,[BP-6] MOV [BX],CX ; Block(); CALL ←Block ; return (conversation); ; BX ← ←conversation MOV BX,[BP-6] MOV SP,BP POP BP RET; ; }; ; EndConversation(conversation) ←EndConversation: ; struct Conversation *conversation; PUSH BP MOV BP,SP PUSH BX ; { ; struct Conversation *dataPtr; ; struct Conversation *this; ADD SP,0FFFCX ; dataPtr = (struct Conversation *) &conversations[swab(conversation->id.count.LS) & 127]; ; BX ← ←conversation MOV BX,[BP-2] MOV CX,[BX+4] MOV BX,CX CALL ←swab AND BX,07FX MOV CX,←conversations SAL BX ADD BX,CX ; ←dataPtr ← BX MOV [BP-4],BX ; this = dataPtr->next; ; DI ← ←dataPtr MOV DI,[BP-4] MOV BX,[DI] ; ←this ← BX POP DX PUSH BX ; if (conversation->id.originator.w == myHost.w) ; BX ← ←conversation MOV BX,[BP-2] MOV CX,[BX+2] MOV BX,WORD PTR ←myHost CMP CX,BX JNZ X12 ; while (this) { X13: ; BX ← ←this POP BX PUSH BX OR BX,BX JZ X14 ; if (this == conversation) { ; BX ← ←conversation MOV BX,[BP-2] ; CX ← ←this POP CX PUSH CX CMP CX,BX JNZ X15 ; dataPtr->next = this->next; ; DI ← ←this POP DI PUSH DI MOV BX,[DI] MOV CX,BX ; BX ← ←dataPtr MOV BX,[BP-4] MOV [BX],CX ; Block(); CALL ←Block ; return; MOV SP,BP POP BP RET; ; }; X15: ; dataPtr = this; this=this->next; ; BX ← ←this POP BX PUSH BX ; ←dataPtr ← BX MOV [BP-4],BX ; DI ← ←this POP DI PUSH DI MOV BX,[DI] ; ←this ← BX POP DX PUSH BX ; }; JR X13 X14: X12: ; SIGNAL(UnknownConversation); MOV BX,←UnknownConversation CALL ←SIGNAL ; }; MOV SP,BP POP BP RET; ; InvalidateConversations() ←InvalidateConversations: PUSH BP MOV BP,SP ; { ; int i; ; struct Conversation *conv; ; for (i=0; i<128; ++i) { ADD SP,0FFFCX MOV WORD PTR [BP-2],0 X18: ; BX ← ←i MOV BX,[BP-2] CMP BX,080X JGE X17 JR X16 X19: INC WORD PTR [BP-2] JR X18 X16: ; conv = conversations[i]; ; BX ← ←i MOV BX,[BP-2] MOV CX,←conversations SAL BX ADD BX,CX MOV CX,[BX] ; ←conv ← CX POP DX PUSH CX ; while (conv) { X20: ; BX ← ←conv POP BX PUSH BX OR BX,BX JZ X21 ; if (conv->id.originator.w == myHost.w) conv->id.originator.w = 0; ; BX ← ←conv POP BX PUSH BX MOV CX,[BX+2] MOV BX,WORD PTR ←myHost CMP CX,BX JNZ X22 ; BX ← ←conv POP BX PUSH BX MOV WORD PTR [BX+2],0 X22: ; conv = conv->next; ; DI ← ←conv POP DI PUSH DI MOV BX,[DI] ; ←conv ← BX POP DX PUSH BX ; }; JR X20 X21: ; }; JR X19 X17: ; }; MOV SP,BP POP BP RET; ; AttachConversation(handle, conversation) ←AttachConversation: ; struct ImportInstance *handle; ; struct Conversation *conversation; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; handle->currentConversation = conversation; ; BX ← ←handle MOV BX,[BP-2] ; CX ← ←conversation POP CX PUSH CX MOV [BX+2],CX ; }; MOV SP,BP POP BP RET; ; struct ConversationID ; *GetConversationID(conversation) ←GetConversationID: ; struct Conversation *conversation; PUSH BP MOV BP,SP PUSH BX ; { ; return((conversation)? &conversation->id: 0); ; BX ← ←conversation POP BX PUSH BX OR BX,BX JZ X23 ; BX ← ←conversation POP BX PUSH BX INC BX INC BX JR X24 X23: XOR BX,BX X24: MOV SP,BP POP BP RET; ; }; ; struct ShortSTRING ; *GetCaller(conversation) ←GetCaller: ; struct Conversation *conversation; PUSH BP MOV BP,SP PUSH BX ; { ; return((conversation)? conversation->originator: 0); ; BX ← ←conversation POP BX PUSH BX OR BX,BX JZ X25 ; BX ← ←conversation POP BX PUSH BX MOV CX,[BX+26] JR X26 X25: XOR CX,CX X26: MOV BX,CX MOV SP,BP POP BP RET; ; }; ; int /* SecurityLevel */ ; *GetLevel(conversation) ←GetLevel: ; struct Conversation *conversation; PUSH BP MOV BP,SP PUSH BX ; { ; return((conversation)? conversation->level: slNone); ; BX ← ←conversation POP BX PUSH BX OR BX,BX JZ X27 ; BX ← ←conversation POP BX PUSH BX MOV CX,[BX+8] JR X28 X27: XOR CX,CX X28: MOV BX,CX MOV SP,BP POP BP RET; ; }; ; int /* DataLength */ ; EncryptPkt(pkt, ln) ←EncryptPkt: ; struct PBI *pkt; ; int ln; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct Header *header; ; struct Conversation *conv; ; int words, nBlks, *checkPtr; ; struct Block blocks[]; ADD SP,0FFF4X ; header = pkt->pup; ; BX ← ←pkt MOV BX,[BP-2] MOV CX,[BX+6] ; ←header ← CX MOV [BP-6],CX ; conv = pkt->convHandle; ; BX ← ←pkt MOV BX,[BP-2] MOV CX,[BX+4] ; ←conv ← CX MOV [BP-8],CX ; if ((conv != 0) && (conv->level != slNone) && (conv->level != slAuthOnly)) { ; BX ← ←conv MOV BX,[BP-8] OR BX,BX JZ X30 ; BX ← ←conv MOV BX,[BP-8] MOV CX,[BX+8] OR CX,CX JZ X31 ; BX ← ←conv MOV BX,[BP-8] MOV CX,[BX+8] MOV BX,CX CMP BX,0100X X31: X30: JZ X29 ; words = ln /* stub data words */ + encryptedHeaderLength + 2 /* SIZE[Check] */; ; BX ← ←ln MOV BX,[BP-4] ADD BX,0AX ; ←words ← BX MOV [BP-10],BX ; nBlks = (words + encryptionBlockSize - 1)/encryptionBlockSize; ; BX ← ←words MOV BX,[BP-10] ADD BX,3 SAR BX SAR BX ; ←nBlks ← BX MOV [BP-12],BX ; blocks = (struct Block *) &header->pktID; ; BX ← ←header MOV BX,[BP-6] ADD BX,018X ; ←blocks ← BX POP DX PUSH BX ; checkPtr = ((int *) (&blocks[nBlks])) - lenCheck; ; BX ← ←nBlks MOV BX,[BP-12] ; CX ← ←blocks POP CX PUSH CX SAL BX SAL BX SAL BX ADD BX,CX ADD BX,0FFFCX ; ←checkPtr ← BX MOV [BP-14],BX ; checkPtr[0] = swab(nBlks*encryptionBlockSize-words); /* Roundoff adj? */ ; BX ← ←nBlks MOV BX,[BP-12] SAL BX SAL BX ; CX ← ←words MOV CX,[BP-10] SUB BX,CX CALL ←swab MOV CX,BX ; BX ← ←checkPtr MOV BX,[BP-14] MOV [BX],CX ; checkPtr[1] = 0; ; BX ← ←checkPtr MOV BX,[BP-14] MOV WORD PTR [BX+2],0 ; CryptData(&conv->key, nBlks, blocks, 0, dirEncrypt, conv->level, &conv->iv); ; BX ← ←conv MOV BX,[BP-8] ADD BX,0AX PUSH BX ; BX ← ←nBlks MOV BX,[BP-12] PUSH BX ; BX ← ←blocks MOV BX,[BP-16] PUSH BX XOR BX,BX PUSH BX MOV BX,1 PUSH BX ; BX ← ←conv MOV BX,[BP-8] MOV CX,[BX+8] ; BX ← ←conv MOV BX,[BP-8] ADD BX,012X CALL ←CryptData JR $+5 X29: JMP X32 ADD SP,0AX ; return (((nBlks*encryptionBlockSize) - encryptedHeaderLength) + pktLengthOverhead); ; BX ← ←nBlks MOV BX,[BP-12] SAL BX SAL BX ADD BX,0FFF8X ADD BX,015X MOV SP,BP POP BP RET; ; }; X32: ; return (ln+pktLengthOverhead); ; BX ← ←ln MOV BX,[BP-4] ADD BX,015X MOV SP,BP POP BP RET; ; }; ; int /* BOOL */ ; DecryptPkt(header, convHandle, /* results */ lvL) ←DecryptPkt: ; struct Header *header; ; struct Conversation *convHandle; ; int *lvL; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; int /*BOOL*/ ok, pktLen; ; int nBlks, *checkPtr, cp; ; struct Block blocks[]; ADD SP,0FFF4X ; ok=true; MOV WORD PTR [BP-6],0FFFFX ; pktLen = (swab(header->length)>>1) - pktLengthOverhead; ; DI ← ←header MOV DI,[BP+4] MOV BX,[DI] CALL ←swab SHR BX ADD BX,0FFEBX ; ←pktLen ← BX MOV [BP-8],BX ; if (convHandle != 0 && convHandle->level != slNone && convHandle->level != slAuthOnly) { ; BX ← ←convHandle MOV BX,[BP-2] OR BX,BX JZ X34 ; BX ← ←convHandle MOV BX,[BP-2] MOV CX,[BX+8] OR CX,CX JZ X35 ; BX ← ←convHandle MOV BX,[BP-2] MOV CX,[BX+8] MOV BX,CX CMP BX,0100X X35: X34: JZ X33 ; nBlks = (pktLen + encryptedHeaderLength)/encryptionBlockSize; ; BX ← ←pktLen MOV BX,[BP-8] ADD BX,8 SAR BX SAR BX ; ←nBlks ← BX MOV [BP-10],BX ; blocks = (struct Block *) &header->pktID; ; BX ← ←header MOV BX,[BP+4] ADD BX,018X ; ←blocks ← BX POP DX PUSH BX ; checkPtr = ((int *) (&blocks[nBlks])) - lenCheck; ; BX ← ←nBlks MOV BX,[BP-10] ; CX ← ←blocks POP CX PUSH CX SAL BX SAL BX SAL BX ADD BX,CX ADD BX,0FFFCX ; ←checkPtr ← BX MOV [BP-12],BX ; CryptData(&convHandle->key, nBlks, blocks, 0, dirDecrypt, ; convHandle->level, &convHandle->iv); ; BX ← ←convHandle MOV BX,[BP-2] ADD BX,0AX PUSH BX ; BX ← ←nBlks MOV BX,[BP-10] PUSH BX ; BX ← ←blocks MOV BX,[BP-16] PUSH BX XOR BX,BX PUSH BX XOR BX,BX PUSH BX ; BX ← ←convHandle MOV BX,[BP-2] MOV CX,[BX+8] ; BX ← ←convHandle MOV BX,[BP-2] ADD BX,012X CALL ←CryptData ADD SP,0AX ; cp = swab(checkPtr[0]); ; DI ← ←checkPtr MOV DI,[BP-12] MOV BX,[DI] CALL ←swab ; ←cp ← BX MOV [BP-14],BX ; if (0 > cp || cp >= encryptionBlockSize) ok = false; ; BX ← ←cp MOV BX,[BP-14] XOR CX,CX CMP CX,BX JG X38 ; BX ← ←cp MOV BX,[BP-14] CMP BX,4 JL X37 X38: MOV AL,1 JR X39 X37: XOR AL,AL X39: OR AL,AL JR $+5 X33: JMP X40 JZ X36 MOV WORD PTR [BP-6],0 ; else *lvL = (((nBlks*encryptionBlockSize) - cp) - lenCheck) - encryptedHeaderLength; JR X41 X36: ; BX ← ←nBlks MOV BX,[BP-10] SAL BX SAL BX ; CX ← ←cp MOV CX,[BP-14] SUB BX,CX DEC BX DEC BX ADD BX,0FFF8X MOV CX,BX ; BX ← ←lvL MOV BX,[BP-4] MOV [BX],CX X41: ; }; ; else *lvL = pktLen; JR X42 X40: ; BX ← ←lvL MOV BX,[BP-4] ; CX ← ←pktLen MOV CX,[BP-8] MOV [BX],CX X42: ; return (ok); ; BX ← ←ok MOV BX,[BP-6] MOV SP,BP POP BP RET; ; }; ; static int Rlse(sig,code,sel) ←Rlse: ; int sig, code; ; struct Seal1 *sel; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; ReleasePBI(sel->data[0]); ; BX ← ←sel POP BX PUSH BX ADD BX,4 MOV CX,[BX] MOV BX,CX CALL ←ReleasePBI ; return (sig); ; BX ← ←sig MOV BX,[BP+4] MOV SP,BP POP BP RET; ; }; ; int /* ok: BOOLEAN */ ; GetConnectionState(decrypted, callPkt, /* more results */ id, callCt, lvConv, lvNewLength) ←GetConnectionState: ; int /*BOOL*/ decrypted; ; struct PBI *callPkt; ; struct ConversationID *id; ; struct CallCount *callCt; ; struct Conversation *lvConv[]; ; int *lvNewLength; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct PBI *rfaPkt; ; struct Seal1 sel; ; word myNonceID[2]; ; struct Header *callHeader; ; struct Header *rfaHeader; ; struct RFARequest *request; ; struct RFAResponse *response; ; int responseLength; ; struct ConversationID convID; ; int ok; ; struct EncryptionKey *ky, *ck; ADD SP,0FFDEX ; callHeader = callPkt->pup; ; BX ← ←callPkt MOV BX,[BP+8] MOV CX,[BX+6] ; ←callHeader ← CX MOV [BP-18],CX ; rfaPkt = GetPBI(mySoc); MOV BX,←mySoc CALL ←GetPBI ; ←rfaPkt ← BX MOV [BP-6],BX ; sel.data[0] = (int) rfaPkt; ; BX ← ←rfaPkt MOV BX,[BP-6] ; ←sel+4 ← BX MOV [BP-8],BX ; ENABLE(UNWIND, &Rlse, &sel); MOV BX,1 PUSH BX ;&←sel LEA BX,[BP-12] MOV CX,OFFSET ←Rlse CALL ←ENABLE POP DX ; Timer(myNonceID); ;&←myNonceID LEA BX,[BP-16] CALL ←Timer ; rfaHeader = rfaPkt->pup; ; BX ← ←rfaPkt MOV BX,[BP-6] MOV CX,[BX+6] ; ←rfaHeader ← CX MOV [BP-20],CX ; request = (struct RFARequest *) &rfaHeader->callData; ; BX ← ←rfaHeader MOV BX,[BP-20] ADD BX,028X ; ←request ← BX MOV [BP-22],BX ; response = (struct RFAResponse *) request; ; BX ← ←request MOV BX,[BP-22] ; ←response ← BX MOV [BP-24],BX ; MoveBlock(&request->callerConv, ; &callHeader->conv, lenPktConversationID+lenPktID); /* PktID still encrypted */ ; BX ← ←request MOV BX,[BP-22] PUSH BX ; BX ← ←callHeader MOV BX,[BP-18] ADD BX,014X PUSH BX MOV BX,6 POP CX CALL ←MoveBlock POP DX ; Move2(&request->nonceID[0], myNonceID); ; BX ← ←request MOV BX,[BP-22] ADD BX,0CX PUSH BX ;&←myNonceID LEA BX,[BP-16] POP CX CALL ←Move2 ; rfaPkt->convHandle = unencrypted; ; BX ← ←rfaPkt MOV BX,[BP-6] MOV WORD PTR [BX+4],0 ; MoveBlock(rfaHeader, callHeader, lenHeader); ; BX ← ←rfaHeader MOV BX,[BP-20] PUSH BX MOV BX,014X ; CX ← ←callHeader MOV CX,[BP-18] CALL ←MoveBlock POP DX ; SetupResponse(rfaHeader); ; BX ← ←rfaHeader MOV BX,[BP-20] CALL ←SetupResponse ; Move2(&rfaHeader->conv, firstConversation); ; BX ← ←rfaHeader MOV BX,[BP-20] ADD BX,014X PUSH BX MOV BX,←firstConversation POP CX CALL ←Move2 ; rfaHeader->pktID.activity = 0; ; BX ← ←rfaHeader MOV BX,[BP-20] MOV WORD PTR [BX+24],0 ; rfaHeader->pktID.pktSeq = 0; ; BX ← ←rfaHeader MOV BX,[BP-20] MOV WORD PTR [BX+30],0 ; responseLength = PktExchange(rfaPkt, lenRFARequest, rfaDataLength, authReq); ; BX ← ←rfaPkt MOV BX,[BP-6] PUSH BX MOV BX,8 PUSH BX MOV BX,4 MOV CX,060X CALL ←PktExchange ADD SP,4 ; ←responseLength ← BX MOV [BP-26],BX ; if (responseLength < lenRFAResponse-lenAuthenticator) return (false); ; BX ← ←responseLength MOV BX,[BP-26] CMP BX,0DX JGE X43 XOR BX,BX MOV SP,BP POP BP RET; X43: ; ok = true; MOV WORD PTR [BP-34],0FFFFX ; if (response->level == slNone) { ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+24] OR CX,CX JNZ X44 ; *lvNewLength = (swab(callHeader->length)>>1) - pktLengthOverhead; *lvConv = 0; }; ; DI ← ←callHeader MOV DI,[BP-18] MOV BX,[DI] CALL ←swab SHR BX ADD BX,0FFEBX MOV CX,BX ; BX ← ←lvNewLength MOV BX,[BP-4] MOV [BX],CX ; BX ← ←lvConv MOV BX,[BP-2] MOV WORD PTR [BX],0 ; else { /* response = {IV, conn, call, nonce}CK,,{KY}KB,{{CK}KB, time, A}KY */ JR X45 X44: ; ky = &response->authenticator.ky; ; BX ← ←response MOV BX,[BP-24] ADD BX,01CX ; ←ky ← BX MOV [BP-36],BX ; ck = &response->authenticator.ck; ; BX ← ←response MOV BX,[BP-24] ADD BX,02CX ; ←ck ← BX POP DX PUSH BX ; DecryptBlock(kb, ky, 0); MOV BX,←kb PUSH BX XOR BX,BX ; CX ← ←ky MOV CX,[BP-36] CALL ←DecryptBlock POP DX ; CBCCheckDecrypt(ky, ; (swab(response->authenticator.length)/encryptionBlockSize)-2, ck, 0, nullSeed); ; BX ← ←ky MOV BX,[BP-36] PUSH BX ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+26] MOV BX,CX CALL ←swab SAR BX SAR BX DEC BX DEC BX PUSH BX ; BX ← ←ck MOV BX,[BP-38] PUSH BX LEA BX,←nullSeedB XOR CX,CX CALL ←CBCCheckDecrypt ADD SP,6 ; DecryptBlock(kb, ck, 0); MOV BX,←kb PUSH BX XOR BX,BX ; CX ← ←ck MOV CX,[BP-38] CALL ←DecryptBlock POP DX ; CBCCheckDecrypt(ck, responseCKBlocks, response, 0, nullSeed); ; BX ← ←ck POP BX PUSH BX PUSH BX MOV BX,3 PUSH BX ; BX ← ←response MOV BX,[BP-24] PUSH BX LEA BX,←nullSeedB XOR CX,CX CALL ←CBCCheckDecrypt ADD SP,6 ; Move2(&convID.count, &response->connection.conv); ; BX ← ←response MOV BX,[BP-24] ADD BX,8 ;&←convID LEA CX,[BP-30] CALL ←Move2 ; convID.count.fields &= notCalleeMask; JR $+5 X45: JMP X46 AND WORD PTR [BP-28],0FF7FX ; convID.originator = ; ((response->connection.conv.fields&originatorField) != callerField)? myHost.w ; :response->connection.caller.w; ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+10] MOV BX,CX AND BX,080X PUSH BX POP BX OR BX,BX JZ X47 MOV BX,WORD PTR ←myHost JR X48 X47: ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+12] MOV BX,CX X48: ; ←convID ← BX MOV [BP-32],BX ; response->authenticator.a.length = swab(response->authenticator.a.length); ; BX ← ←response MOV BX,[BP-24] PUSH BX ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+64] MOV BX,CX CALL ←swab MOV CX,BX POP BX MOV [BX+64],CX ; *lvConv = AddConversation( /* Construct a ConversationID from a PktConversationID */ ; &convID, response->level, &response->iv, &response->authenticator.a, 0, ; &response->authenticator.ck, 0); ;&←convID LEA BX,[BP-32] PUSH BX ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+24] PUSH CX ; BX ← ←response MOV BX,[BP-24] PUSH BX ; BX ← ←response MOV BX,[BP-24] ADD BX,040X PUSH BX XOR BX,BX PUSH BX ; BX ← ←response MOV BX,[BP-24] ADD BX,02CX PUSH BX XOR BX,BX POP CX CALL ←AddConversation ADD SP,0AX MOV CX,BX ; BX ← ←lvConv MOV BX,[BP-2] MOV [BX],CX ; callPkt->convHandle = *lvConv; ; BX ← ←callPkt MOV BX,[BP+8] ; DI ← ←lvConv MOV DI,[BP-2] MOV CX,[DI] MOV [BX+4],CX ; if (decrypted==false && DecryptPkt(callHeader, *lvConv, lvNewLength)==false) ok=false; ; BX ← ←decrypted MOV BX,[BP+10] OR BX,BX JNZ X50 ; BX ← ←callHeader MOV BX,[BP-18] PUSH BX ; DI ← ←lvConv MOV DI,[BP-2] MOV BX,[DI] PUSH BX ; BX ← ←lvNewLength MOV BX,[BP-4] POP CX CALL ←DecryptPkt POP DX OR BX,BX X50: JNZ X49 MOV WORD PTR [BP-34],0 X49: ; } X46: ; if (ok) if (DoubleComp(&response->nonceID[0], myNonceID) != 1) ok=false; ; BX ← ←ok MOV BX,[BP-34] OR BX,BX JZ X51 ; BX ← ←response MOV BX,[BP-24] ADD BX,014X PUSH BX ;&←myNonceID LEA BX,[BP-16] POP CX CALL ←DoubleComp CMP BX,1 JZ X52 MOV WORD PTR [BP-34],0 ; else if (DoubleEq(&response->connection.conv, &callHeader->conv)==false) ok=false; JR X53 X52: ; BX ← ←response MOV BX,[BP-24] ADD BX,8 ; CX ← ←callHeader MOV CX,[BP-18] ADD CX,014X XCHG BX,CX CALL ←DoubleEq OR BX,BX JNZ X54 MOV WORD PTR [BP-34],0 ; else if (response->connection.caller != callHeader->srceHost) ok=false; JR X55 X54: ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+12] ; BX ← ←callHeader MOV BX,[BP-18] MOV AX,[BX+14] CMP CX,AX JZ X56 MOV WORD PTR [BP-34],0 ; else if (response->connection.activity != callHeader->pktID.activity) ok=false; JR X57 X56: ; BX ← ←response MOV BX,[BP-24] MOV CX,[BX+14] ; BX ← ←callHeader MOV BX,[BP-18] MOV AX,[BX+24] CMP CX,AX JZ X58 MOV WORD PTR [BP-34],0 ; else if (DoubleEq(&response->callCt, &callHeader->pktID.callCt) == false) ok=false; JR X59 X58: ; BX ← ←response MOV BX,[BP-24] ADD BX,010X ; CX ← ←callHeader MOV CX,[BP-18] ADD CX,01AX XCHG BX,CX CALL ←DoubleEq JR $+5 X51: JMP X61 OR BX,BX JNZ X60 MOV WORD PTR [BP-34],0 X60: X59: X57: X55: X53: X61: ; if (ok) { MoveBlock(id, &response->connection, lenConnectionID); ; BX ← ←ok MOV BX,[BP-34] OR BX,BX JZ X62 ; BX ← ←id MOV BX,[BP+6] PUSH BX ; BX ← ←response MOV BX,[BP-24] ADD BX,8 PUSH BX MOV BX,4 POP CX CALL ←MoveBlock POP DX ; Move2(callCt, &response->callCt); }; ; BX ← ←response MOV BX,[BP-24] ADD BX,010X ; CX ← ←callCt MOV CX,[BP+4] CALL ←Move2 X62: ; Block(); CALL ←Block ; return (Rlse(ok, 0, &sel)); ; BX ← ←ok MOV BX,[BP-34] PUSH BX ;&←sel LEA BX,[BP-12] XOR CX,CX CALL ←Rlse POP DX MOV SP,BP POP BP RET; ; }; ; int /*BOOLEAN*/ ; ReplyToRFA(recvdPkt, callHeader/*encrypted*/, callPktID /* clear */, convHandle) ←ReplyToRFA: ; struct PBI *recvdPkt; ; struct Header *callHeader; ; struct PktID *callPktID; ; struct Conversation *convHandle; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct Header *recvdHeader; ; struct RFARequest request; ; struct RFAResponse *response; ; int used; ; int authLen; ; struct Authenticator *auth; ; int *resp; ADD SP,0FFE4X ; recvdHeader = recvdPkt->pup; ; BX ← ←recvdPkt MOV BX,[BP+6] MOV CX,[BX+6] ; ←recvdHeader ← CX MOV [BP-6],CX ; response = (struct RFAResponse *) &recvdHeader->callData; ; BX ← ←recvdHeader MOV BX,[BP-6] ADD BX,028X ; ←response ← BX MOV [BP-24],BX ; MoveBlock(&request, response, lenRFARequest); ;&←request LEA BX,[BP-22] PUSH BX MOV BX,8 ; CX ← ←response MOV CX,[BP-24] CALL ←MoveBlock POP DX ; used = lenRFAResponse-lenAuthenticator; MOV WORD PTR [BP-26],0DX ; if (MultEq(&request.callerConv, ; &callHeader->conv, lenPktConversationID+lenPktID) == 0) { ;&←request LEA BX,[BP-22] PUSH BX ; BX ← ←callHeader MOV BX,[BP+4] ADD BX,014X PUSH BX MOV BX,6 POP CX CALL ←MultEq POP DX OR BX,BX JNZ X63 ; ReleasePBI(recvdPkt); ; BX ← ←recvdPkt MOV BX,[BP+6] CALL ←ReleasePBI ; return (false); XOR BX,BX MOV SP,BP POP BP RET; ; }; X63: ; Move2(&response->connection.conv, &callHeader->conv); ; BX ← ←response MOV BX,[BP-24] ADD BX,8 ; CX ← ←callHeader MOV CX,[BP+4] ADD CX,014X XCHG BX,CX CALL ←Move2 ; response->connection.caller = callHeader->srceHost; ; BX ← ←response MOV BX,[BP-24] ; CX ← ←callHeader MOV CX,[BP+4] MOV DI,CX MOV CX,[DI+14] MOV [BX+12],CX ; response->connection.activity = callPktID->activity; ; BX ← ←response MOV BX,[BP-24] ; DI ← ←callPktID MOV DI,[BP-2] MOV CX,[DI] MOV [BX+14],CX ; Move2(&response->callCt, &callPktID->callCt); ; BX ← ←response MOV BX,[BP-24] ADD BX,010X ; CX ← ←callPktID MOV CX,[BP-2] INC CX INC CX XCHG BX,CX CALL ←Move2 ; Move2(&response->nonceID[0], &request.nonceID[0]); ; BX ← ←response MOV BX,[BP-24] ADD BX,014X PUSH BX ;&←request LEA BX,[BP-10] POP CX CALL ←Move2 ; DoubleInc(&response->nonceID[0], 1); ; BX ← ←response MOV BX,[BP-24] ADD BX,014X PUSH BX MOV BX,1 POP CX CALL ←DoubleInc ; if (DoubleEq(&callHeader->conv, firstConversation)) { ; BX ← ←callHeader MOV BX,[BP+4] ADD BX,014X PUSH BX MOV BX,←firstConversation POP CX CALL ←DoubleEq OR BX,BX JZ X64 ; response->level = slNone; ; BX ← ←response MOV BX,[BP-24] MOV WORD PTR [BX+24],0 ; ++used; INC WORD PTR [BP-26] ; }; ; else { JR X65 X64: ; if ((callHeader->conv.fields&originatorField) == calleeField) SIGNAL(ERROR); /* TEMP */ ; BX ← ←callHeader MOV BX,[BP+4] MOV CX,[BX+22] MOV BX,CX AND BX,080X CMP BX,080X JNZ X66 MOV BX,2 CALL ←SIGNAL X66: ; response->level = convHandle->level; ; BX ← ←response MOV BX,[BP-24] ; CX ← ←convHandle MOV CX,[BP-4] MOV DI,CX MOV CX,[DI+8] MOV [BX+24],CX ; MoveBlock(&response->iv, &convHandle->iv, lenIV); ; BX ← ←response MOV BX,[BP-24] PUSH BX ; BX ← ←convHandle MOV BX,[BP-4] ADD BX,012X PUSH BX MOV BX,4 POP CX CALL ←MoveBlock POP DX ; CryptData(&convHandle->key, responseCKBlocks, ; response, 0, dirEncrypt, slCBCCheck, nullSeed); ; BX ← ←convHandle MOV BX,[BP-4] ADD BX,0AX PUSH BX MOV BX,3 PUSH BX ; BX ← ←response MOV BX,[BP-24] PUSH BX XOR BX,BX PUSH BX MOV BX,1 PUSH BX LEA BX,←nullSeedB MOV CX,0400X CALL ←CryptData ADD SP,0AX ; auth = convHandle->authenticator; ; BX ← ←convHandle MOV BX,[BP-4] MOV CX,[BX+30] ; ←auth ← CX MOV [BP-30],CX ; authLen = auth->length+1; ; DI ← ←auth MOV DI,[BP-30] MOV BX,[DI] INC BX ; ←authLen ← BX MOV [BP-28],BX ; MoveBlock(&response->authenticator, auth, authLen); ; BX ← ←response MOV BX,[BP-24] ADD BX,01AX PUSH BX ; BX ← ←authLen JR $+5 X65: JMP X67 MOV BX,[BP-28] ; CX ← ←auth MOV CX,[BP-30] CALL ←MoveBlock POP DX ; response->authenticator.length = swab(auth->length); ; BX ← ←response MOV BX,[BP-24] PUSH BX ; DI ← ←auth MOV DI,[BP-30] MOV BX,[DI] CALL ←swab MOV CX,BX POP BX MOV [BX+26],CX ; used += authLen; ; BX ← ←authLen MOV BX,[BP-28] ADD [BP-26],BX ; resp = (int *) response; ; BX ← ←response MOV BX,[BP-24] ; ←resp ← BX POP DX PUSH BX ; ShallString(&resp[used], convHandle->originator, 1); ; BX ← ←used MOV BX,[BP-26] ; CX ← ←resp POP CX PUSH CX SAL BX ADD BX,CX PUSH BX ; BX ← ←convHandle MOV BX,[BP-4] MOV CX,[BX+26] MOV BX,1 CALL ←ShallString POP DX ; used += StringSize(convHandle->originator); ; BX ← ←convHandle MOV BX,[BP-4] MOV CX,[BX+26] MOV BX,CX CALL ←StringSize ADD [BP-26],BX ; }; X67: ; SetupResponse(recvdHeader); ; BX ← ←recvdHeader MOV BX,[BP-6] CALL ←SetupResponse ; recvdHeader->length = swab((pktLengthOverhead + used) << 1); ; BX ← ←used MOV BX,[BP-26] ADD BX,015X SAL BX CALL ←swab MOV CX,BX ; BX ← ←recvdHeader MOV BX,[BP-6] MOV [BX],CX ; recvdHeader->type.fields = typeData; ; BX ← ←recvdHeader MOV BX,[BP-6] MOV BYTE PTR [BX+3],061X ; recvdHeader->pktID.pktSeq += swapped1; ; BX ← ←recvdHeader MOV BX,[BP-6] ADD WORD PTR [BX+30],0100X ; recvdHeader->srceHost.w = myHost.w; ; BX ← ←recvdHeader MOV BX,[BP-6] MOV CX,WORD PTR ←myHost MOV [BX+14],CX ; recvdHeader->srceSoc.LS = rpcSocket; ; BX ← ←recvdHeader MOV BX,[BP-6] MOV BYTE PTR [BX+19],01EX ; recvdHeader->srcePSB = nullPSB; ; BX ← ←recvdHeader MOV BX,[BP-6] MOV WORD PTR [BX+6],0 ; SendPup(recvdPkt); ; BX ← ←recvdPkt MOV BX,[BP+6] CALL ←SendPup ; Block(); CALL ←Block ; return (true); MOV BX,0FFFFX MOV SP,BP POP BP RET; ; }; ; SecurityInitialize() { ←SecurityInitialize: PUSH BP MOV BP,SP ; firstConversation = ; (struct PktConversationID *) GetFixed(lenPktConversationID); MOV BX,2 CALL ←GetFixed MOV ←firstConversation,BX ; ReadCalendar(firstConversation); MOV BX,←firstConversation CALL ←ReadCalendar ; firstConversation->fields &= notCalleeMask; /* time unpredictable in 32 bits */ MOV BX,←firstConversation AND WORD PTR [BX+2],0FF7FX ; lastConversation = ; (struct ConversationID *) GetFixed(lenConversationID); MOV BX,3 CALL ←GetFixed MOV ←lastConversation,BX ; lastConversation->originator.w = myHost.w; MOV BX,←lastConversation MOV CX,WORD PTR ←myHost MOV [BX],CX ; Move2(&lastConversation->count, firstConversation); MOV BX,←lastConversation INC BX INC BX PUSH BX MOV BX,←firstConversation POP CX CALL ←Move2 ; conversations = (struct Conversation **) GetFixed(128); MOV BX,080X CALL ←GetFixed MOV ←conversations,BX ; UnknownConversation = CODE(); CALL ←CODE MOV ←UnknownConversation,BX ; AddConversation(lastConversation, slNone, nullSeed, 0, 0, nullKey, 0); MOV BX,←lastConversation PUSH BX XOR BX,BX PUSH BX LEA BX,←nullSeedB PUSH BX XOR BX,BX PUSH BX XOR BX,BX PUSH BX XOR BX,BX LEA CX,←nullKeyB CALL ←AddConversation ADD SP,0AX ; kb = ka = &privateKey; LEA BX,←privateKey MOV ←ka,BX MOV ←kb,BX ; CorrectParity(ka); MOV BX,←ka CALL ←CorrectParity ; }; MOV SP,BP POP BP RET; ; SecurityRestart() ←SecurityRestart: PUSH BP MOV BP,SP ; { ; InvalidateConversations(); CALL ←InvalidateConversations ; }; MOV SP,BP POP BP RET; ; Externals Declared Here PUBLIC ←lastConversation PUBLIC ←firstConversation PUBLIC ←UnknownConversation PUBLIC ←nullKeyB PUBLIC ←nullSeedB PUBLIC ←GenerateConversation PUBLIC ←StartConversation PUBLIC ←Authenticate PUBLIC ←EndConversation PUBLIC ←InvalidateConversations PUBLIC ←AttachConversation PUBLIC ←GetConversationID PUBLIC ←GetCaller PUBLIC ←GetLevel PUBLIC ←EncryptPkt PUBLIC ←DecryptPkt PUBLIC ←GetConnectionState PUBLIC ←ReplyToRFA PUBLIC ←SecurityInitialize PUBLIC ←SecurityRestart C←CODE ENDS ; Number of Bytes of Code = 0ACDX, (2765)