// File: DiplIngFrankGerlach[P]MST/UnitTest.cpp
// Function: encryptedCommunicationExampleComplex()
void encryptedCommunicationExampleComplex()
{
   uint8_t sharedKey[16] = {11,55,11,33,67,89,91,11,55,11,33,67,89,91,0,0};

   MST_Endpoint endpointA(sharedKey);
   MST_Endpoint endpointB(sharedKey);

   uint8_t mcA[16];
   endpointA.generateMaskCounterExchange(mcA);

   uint8_t mcB[16];
   endpointB.generateMaskCounterExchange(mcB);

   //exchange of masking counters
   endpointA.decryptMaskCounterExchange(mcB);
   endpointB.decryptMaskCounterExchange(mcA);
 
   
   //now we can securely encrypt with all assurances of the protocol

   for(uint32_t i=0; i < 10000; i++)
   {
	   string plaintext = "Schiller, Goethe, Von der Vogelweide";

           uint8_t n= rand() & 0xF;
           for(uint8_t j=0; j < n; j++)
           {
              plaintext += " three more words";
           }
	   uint8_t* secureMessage;
	   uint32_t lengthSM;
	   assert( endpointA.encryptToSecureMessage((uint8_t*)plaintext.c_str(),
		                                    plaintext.length()+1,
		                                    &secureMessage,
		                                    &lengthSM) );
	   
	   uint8_t* plaintextDec;
	   uint32_t lengthPT;
	   assert( endpointB.decryptSecureMessage(secureMessage,lengthSM,&plaintextDec,&lengthPT) );

	   assert( plaintext.compare( (const char*)plaintextDec) == 0 );


           if( (rand() & 0xF) < 5 )
           {
		   string plaintext2 = "Buy 100 shares of Apple and 200 shares of Deutsche Bank";

		   n= rand() & 0xF;
		   for(uint8_t j=0; j < n; j++)
		   {
		      plaintext2 += " three more words";
		   }
		   assert( endpointB.encryptToSecureMessage((uint8_t*)plaintext2.c_str(),
				                            plaintext2.length()+1,
				                            &secureMessage,
				                            &lengthSM) );
	   
		   assert( endpointA.decryptSecureMessage(secureMessage,lengthSM,&plaintextDec,&lengthPT) );

		   assert( plaintext2.compare((const char*)plaintextDec) == 0 );
           }
   }
   
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3a0, %rsp            # imm = 0x3A0
movaps 0x2c0e(%rip), %xmm0     # 0x8f00
movaps %xmm0, -0x10(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x10(%rbp), %rsi
movq %rsi, -0x350(%rbp)
callq 0x7250
movq -0x350(%rbp), %rsi
leaq -0x2a0(%rbp), %rdi
callq 0x7250
jmp 0x6322
leaq -0x158(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x72f0
jmp 0x6337
leaq -0x2a0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
callq 0x72f0
jmp 0x634c
leaq -0x158(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
callq 0x7350
jmp 0x6361
leaq -0x2a0(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x7350
jmp 0x6376
movl $0x0, -0x2d4(%rbp)
cmpl $0x2710, -0x2d4(%rbp)   # imm = 0x2710
jae 0x67c9
leaq -0x2f9(%rbp), %rdi
movq %rdi, -0x358(%rbp)
callq 0x22b0
movq -0x358(%rbp), %rdx
leaq 0x25f6(%rip), %rsi      # 0x89a7
leaq -0x2f8(%rbp), %rdi
callq 0x76b0
jmp 0x63bf
leaq -0x2f9(%rbp), %rdi
callq 0x21c0
callq 0x2050
andl $0xf, %eax
movb %al, -0x2fa(%rbp)
movb $0x0, -0x2fb(%rbp)
movzbl -0x2fb(%rbp), %eax
movzbl -0x2fa(%rbp), %ecx
cmpl %ecx, %eax
jge 0x6485
leaq 0x2695(%rip), %rsi      # 0x8a92
leaq -0x2f8(%rbp), %rdi
callq 0x2170
jmp 0x640b
jmp 0x640d
movb -0x2fb(%rbp), %al
addb $0x1, %al
movb %al, -0x2fb(%rbp)
jmp 0x63e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
jmp 0x67f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
jmp 0x67ea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
leaq -0x2f9(%rbp), %rdi
callq 0x21c0
jmp 0x67ea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
jmp 0x67bb
leaq -0x2f8(%rbp), %rdi
movq %rdi, -0x370(%rbp)
callq 0x2090
movq -0x370(%rbp), %rdi
movq %rax, -0x368(%rbp)
callq 0x2270
movq -0x368(%rbp), %rsi
movl %eax, %edx
incl %edx
leaq -0x158(%rbp), %rdi
leaq -0x308(%rbp), %rcx
leaq -0x30c(%rbp), %r8
callq 0x73a0
movb %al, -0x359(%rbp)
jmp 0x64d8
movb -0x359(%rbp), %al
testb $0x1, %al
jne 0x64e4
jmp 0x64e6
jmp 0x6505
leaq 0x25b7(%rip), %rdi      # 0x8aa4
leaq 0x23f7(%rip), %rsi      # 0x88eb
movl $0x76, %edx
leaq 0x2613(%rip), %rcx      # 0x8b13
callq 0x20e0
movq -0x308(%rbp), %rsi
movl -0x30c(%rbp), %edx
leaq -0x2a0(%rbp), %rdi
leaq -0x318(%rbp), %rcx
leaq -0x31c(%rbp), %r8
callq 0x74c0
movb %al, -0x371(%rbp)
jmp 0x6534
movb -0x371(%rbp), %al
testb $0x1, %al
jne 0x6540
jmp 0x6542
jmp 0x6561
leaq 0x24fa(%rip), %rdi      # 0x8a43
leaq 0x239b(%rip), %rsi      # 0x88eb
movl $0x7a, %edx
leaq 0x25b7(%rip), %rcx      # 0x8b13
callq 0x20e0
movq -0x318(%rbp), %rsi
leaq -0x2f8(%rbp), %rdi
callq 0x2070
cmpl $0x0, %eax
jne 0x657b
jmp 0x659a
leaq 0x25bd(%rip), %rdi      # 0x8b3f
leaq 0x2362(%rip), %rsi      # 0x88eb
movl $0x7c, %edx
leaq 0x257e(%rip), %rcx      # 0x8b13
callq 0x20e0
callq 0x2050
andl $0xf, %eax
cmpl $0x5, %eax
jge 0x679b
leaq -0x341(%rbp), %rdi
movq %rdi, -0x380(%rbp)
callq 0x22b0
movq -0x380(%rbp), %rdx
leaq 0x25a6(%rip), %rsi      # 0x8b72
leaq -0x340(%rbp), %rdi
callq 0x76b0
jmp 0x65da
leaq -0x341(%rbp), %rdi
callq 0x21c0
callq 0x2050
andl $0xf, %eax
movb %al, -0x2fa(%rbp)
movb $0x0, -0x342(%rbp)
movzbl -0x342(%rbp), %eax
movzbl -0x2fa(%rbp), %ecx
cmpl %ecx, %eax
jge 0x667a
leaq 0x247e(%rip), %rsi      # 0x8a92
leaq -0x340(%rbp), %rdi
callq 0x2170
jmp 0x6622
jmp 0x6624
movb -0x342(%rbp), %al
addb $0x1, %al
movb %al, -0x342(%rbp)
jmp 0x65fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
leaq -0x341(%rbp), %rdi
callq 0x21c0
jmp 0x67bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2a8(%rbp)
movl %eax, -0x2ac(%rbp)
leaq -0x340(%rbp), %rdi
callq 0x20d0
jmp 0x67bb
leaq -0x340(%rbp), %rdi
movq %rdi, -0x398(%rbp)
callq 0x2090
movq -0x398(%rbp), %rdi
movq %rax, -0x390(%rbp)
callq 0x2270
movq -0x390(%rbp), %rsi
movl %eax, %edx
incl %edx
leaq -0x2a0(%rbp), %rdi
leaq -0x308(%rbp), %rcx
leaq -0x30c(%rbp), %r8
callq 0x73a0
movb %al, -0x381(%rbp)
jmp 0x66cd
movb -0x381(%rbp), %al
testb $0x1, %al
jne 0x66d9
jmp 0x66db
jmp 0x66fa
leaq 0x24c8(%rip), %rdi      # 0x8baa
leaq 0x2202(%rip), %rsi      # 0x88eb
movl $0x8b, %edx
leaq 0x241e(%rip), %rcx      # 0x8b13
callq 0x20e0
movq -0x308(%rbp), %rsi
movl -0x30c(%rbp), %edx
leaq -0x158(%rbp), %rdi
leaq -0x318(%rbp), %rcx
leaq -0x31c(%rbp), %r8
callq 0x74c0
movb %al, -0x399(%rbp)
jmp 0x6729
movb -0x399(%rbp), %al
testb $0x1, %al
jne 0x6735
jmp 0x6737
jmp 0x6756
leaq 0x24dd(%rip), %rdi      # 0x8c1b
leaq 0x21a6(%rip), %rsi      # 0x88eb
movl $0x8d, %edx
leaq 0x23c2(%rip), %rcx      # 0x8b13
callq 0x20e0
movq -0x318(%rbp), %rsi
leaq -0x340(%rbp), %rdi
callq 0x2070
cmpl $0x0, %eax
jne 0x6770
jmp 0x678f
leaq 0x24f3(%rip), %rdi      # 0x8c6a
leaq 0x216d(%rip), %rsi      # 0x88eb
movl $0x8f, %edx
leaq 0x2389(%rip), %rcx      # 0x8b13
callq 0x20e0
leaq -0x340(%rbp), %rdi
callq 0x20d0
leaq -0x2f8(%rbp), %rdi
callq 0x20d0
movl -0x2d4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2d4(%rbp)
jmp 0x6380
leaq -0x2f8(%rbp), %rdi
callq 0x20d0
jmp 0x67ea
leaq -0x2a0(%rbp), %rdi
callq 0x7610
leaq -0x158(%rbp), %rdi
callq 0x7610
addq $0x3a0, %rsp            # imm = 0x3A0
popq %rbp
retq
leaq -0x2a0(%rbp), %rdi
callq 0x7610
leaq -0x158(%rbp), %rdi
callq 0x7610
movq -0x2a8(%rbp), %rdi
callq 0x22a0
nop