/******************************************************************************
* Copyright (c) 2000-2019 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
//
//  File:               TCCSecurity_Example.ttcn
//  Description:        TCC Useful testcases: Security testcases.
//  Rev:                R32A
//  Prodnr:             CNL 113 472
//  Updated:            2013-02-08
//  Contact:            http://ttcn.ericsson.se
///////////////////////////////////////////////

module TCCSecurity_Example 
{

import from TCCSecurity_Functions all;

type component Security_CT {
  var DigestData dg;

  var AKAInput aka_input;
  var SIMOutput sim_output;
};
type component  IKEv2_CT {
  var DigestData dg;

  var AKAInput aka_input;
  var SIMOutput sim_output;
};

//////////////////////////////////////////////////////////////
// Security functions
//////////////////////////////////////////////////////////////

type record DigestData {
  charstring nonce,
  charstring cnonce,
  charstring user, 
  charstring realm,
  charstring passwd,
  charstring alg,
  charstring nonceCount,
  charstring method,
  charstring qop,
  charstring URI,
  charstring HEntity
}

type record AKAInput {
  octetstring OP,
  octetstring k,
  octetstring rand,
  octetstring sqn, 
  octetstring amf
}

type record SIMOutput {
  octetstring sres,
  octetstring kc
}

const octetstring c_OP := '00'O;

// test f_calculateDigestResponse function
testcase f_test_digestresponse() runs on Security_CT
{
  log(" ----------- f_calculateDigestResponse ----------- ");

  dg := {
    nonce := "dcd98b7102dd2f0e8b11d0f600bfb0c093",
    cnonce := "0a4f113b",
    user := "Mufasa",
    realm := "testrealm@host.com",
    passwd := "password",
    alg := "MD5",
    nonceCount := "00000001",
    method := "GET",
    qop := "auth",
    URI := "/dir/index.html",
    HEntity := "d41d8cd98f00b204e9800998ecf8427e" // MD5 hash of entity body
  }

  log("Data to compute digest from: ", dg);
  log("Digest response: ", 
    f_calculateDigestResponse(
        dg.nonce,
        dg.cnonce,
        dg.user,
        dg.realm,
        dg.passwd,
        dg.alg,
        dg.nonceCount,
        dg.method,
        dg.qop,
        dg.URI,
        dg.HEntity));

  // no check
  setverdict(pass);
}

testcase f_test_MD5() runs on Security_CT
{ 
  var charstring v_hash := f_calculateMD5("")
  log("MD5 Hash of empty string: ", v_hash)
  log("Expected: ", "d41d8cd98f00b204e9800998ecf8427e");
  if (v_hash == "d41d8cd98f00b204e9800998ecf8427e") {
  setverdict(pass);
  }
  else {
     setverdict(fail, "MD5 Hash test failed");
  } 
}

testcase tc_HMACMD5() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("key");
  
  while (lengthof(key) < 64) {
     key := key & '00'O;
  }
  var octetstring hash := f_calculateHMACMD5(msg, key);
  log("HMAC MD5 Hash: ", hash);
  log("Expected: ", '80070713463e7749b90c2dc24911e275'O);
  if(hash == '80070713463e7749b90c2dc24911e275'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "MD5 Hash test failed");
  }  
}

testcase tc_HMACMD5_2() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("key");
  
  var octetstring hash := f_calculate_HMAC_MD5(key,msg,16);
  log("HMAC MD5 Hash: ", hash);
  log("Expected: ", '80070713463e7749b90c2dc24911e275'O);
  if(hash == '80070713463e7749b90c2dc24911e275'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "MD5 Hash test 2  failed");
  }
}

testcase tc_HMACMD5_3() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("key");
  
  var octetstring hash := f_calculate_HMAC_MD5(key,msg,8);
  log("HMAC MD5 Hash: ", hash);
  log("Expected: ", '80070713463e7749'O);
  if(hash == '80070713463e7749'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "MD5 Hash test 2  failed");
  }
}

testcase tc_HMACMD5_4() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("01234567890123456789012345678901234567890123456789012345678901234");
  
  var octetstring hash := f_calculate_HMAC_MD5(key,msg,16);
  log("HMAC MD5 Hash: ", hash);
  log("Expected: ", '6c5f927cd3311e7d2cc569d8f2bfcf98'O);
  if(hash == '6c5f927cd3311e7d2cc569d8f2bfcf98'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "MD5 Hash test 2  failed");
  }
}

testcase tc_HMAC_SHA1() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("key");
  
  var octetstring hash := f_calculate_HMAC_SHA1(key,msg,20);
  log("HMAC SHA1Hash: ", hash);                     
  log("Expected: ", 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9'O);
  if(hash == 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "SHA1 Hash test 2  failed");
  }
}

testcase tc_HMAC_SHA256() runs on Security_CT
{
  var octetstring msg := char2oct("The quick brown fox jumps over the lazy dog");
  var octetstring key := char2oct("key");
  
  var octetstring hash := f_calculate_HMAC_SHA256(key,msg,32);
  log("HMAC SHA256Hash: ", hash);                     
  log("Expected: ", 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'O);                     
  if(hash == 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'O) {
    setverdict(pass);
  }
  else {
    setverdict(fail, "SHA256 Hash test 2  failed");
  }
}

// test tc_AKA_functions function
testcase tc_AKA_functions() runs on Security_CT
{
  log(" ----------- tc_AKA_functions ----------- ");

  aka_input := 
  {
    OP := '00'O,
    k := str2oct("1234567890123456"),
    rand := int2oct(9876, 16),
    sqn := int2oct(1234, 6), 
    amf := '0000'O
  }

log("AMF: ", str2oct("12"));
  log("Data to compute AKA output from: ", aka_input);
  log("f_IMSAKA_f1 output MAC-A: ", 
      f_IMSAKA_f1
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand,
        aka_input.sqn,
        aka_input.amf
       )
      );
  log("f_IMSAKA_f2 output RES: ", 
      f_IMSAKA_f2
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand
       )
      );
  log("f_IMSAKA_f3 output CK: ", 
      f_IMSAKA_f3
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand
       )
      );
  log("f_IMSAKA_f4 output IK: ", 
      f_IMSAKA_f4
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand
       )
      );
  log("f_IMSAKA_f5 output AK: ", 
      f_IMSAKA_f5
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand
       )
      );
    log("f_IMSAKA_f1star output MAC-S: ", 
      f_IMSAKA_f1star
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand,
        aka_input.sqn,
        aka_input.amf
       )
      );
  log("f_IMSAKA_f5star output AK-S: ", 
      f_IMSAKA_f5star
      (
        aka_input.OP,
        aka_input.k,
        aka_input.rand
       )
  );
  log("f_IMSAKA_calculateAUTN output AUTN: ", 
      f_IMSAKA_calculateAUTN
      (
        aka_input.sqn,
        f_IMSAKA_f5(aka_input.OP,aka_input.k,aka_input.rand),
      aka_input.amf,
      f_IMSAKA_f1(aka_input.OP,aka_input.k,aka_input.rand,aka_input.sqn,aka_input.amf)
       )
  );
  
  f_EAPSIM_A3A8(aka_input.k, aka_input.rand, sim_output.sres, sim_output.kc)
  log("sim_output.sres: ", sim_output.sres, " sim_output.sres: ", sim_output.kc);
  
  setverdict(pass);
}

testcase tc_EIA() runs on Security_CT
{
 var BIT_32 v_MAC := f_calculate128_EIA3
 (   
  '00000000000000000000000000000000'O, //key  
  '00000000'O,  
  0,
  '0'B,
  '0'B
 )
 log(v_MAC);
 if (v_MAC == oct2bit('c8a9595e'O))
 {setverdict(pass)}
 else {setverdict(fail)}
}

testcase tc_EEA() runs on Security_CT
{ 
  var bitstring v_oct := f_calculate128_EEA3
  (
   '173d14ba5003731d7a60049470f00a29'O,   
   '66035492'O,  
    15,
    '0'B,  
    oct2bit('6cf65340735552ab0c9752fa6f9025fe0bd675d9005875b2'O) & '0'B 
  )
  log(v_oct);
  
  if (v_oct == ( oct2bit('a6c85fc66afb8533aafc2518dfe784940ee1e4b030238cc8'O) & '0'B))
  {setverdict(pass)}
  else {setverdict(fail)}
}

testcase tc_3des_ecb() runs on Security_CT
{
  var octetstring vl_key := '000102030405060708090A0B0C0D0E0F0011223344556677'O
  
  var octetstring vl_data := '61A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF523973DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047'O
  log(vl_data)
  var octetstring vl_encrypted_data := ef_3DES_ECB_Encrypt(vl_data, vl_key);
  log(vl_encrypted_data)
  
  var octetstring vl_decrypted_data := ef_3DES_ECB_Decrypt(vl_encrypted_data, vl_key);
  log(vl_decrypted_data)
  
  if(match(vl_data, vl_decrypted_data))
  {
    setverdict(pass);
  } else {
    log(match(vl_data, vl_decrypted_data))
    setverdict(fail);
  }
}

testcase tc_DH1024() runs on IKEv2_CT
{    
  var octetstring vl_key_other := '73DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047E90E4E5013F173AE9E61A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF5239'O
  log("Public key:")
  log(vl_key_other)
  
  var octetstring vl_priv_key := '9FCF731129397EF7DC51562D71DD819DE35891B739BD6BE7A5177F676F1A06775A0E915E3758130FE5493B95C7A67F11F45E4C541DDD2834E4A9248F18EE2597936499C97D25227C4A4B78BABD4F33BBC3E3A2C591369A3A4FAF3D851839249E23E90D15051268986E562D76D756F7FAF942FFBC4669199A3C04E31335E2BD70'O
  log("Private key:")
  log(vl_priv_key)
  
  var octetstring vl_shared_secret := ef_DH_shared_secret(vl_key_other, vl_priv_key);
  log("Shared secret:")
  log(vl_shared_secret)
}

testcase tc_DH2048() runs on IKEv2_CT
{
  var octetstring vl_key_other := '73DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047E90E4E5013F173AE9E61A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF523961A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF523973DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047E90E4E5013F173AE9E'O
  log("Public key:")
  log(vl_key_other)
  
  var octetstring vl_priv_key := '61A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF523973DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047E90E4E5013F173AE9E0E915E3758130FE5493B95C7A67F11F45E4C541DDD2834E4A9248F18EE2597936499C97D25227C4A4B789FCF731129397EF7DC51562D71DD819DE35891B739BD6BE7A5177F676F1A06775ABABD4F33BBC3E3A2C591369A3A4FAF3D851839249E23E90D15051268986E562D76D756F7FAF942FFBC4669199A3C04E31335E2BD70'O
  log("Private key:")
  log(vl_priv_key)
  
  var octetstring vl_shared_secret := ef_DH_shared_secret(vl_key_other, vl_priv_key);
  log("Shared secret:")
  log(vl_shared_secret)
}

testcase tc_3DES_CBC() runs on IKEv2_CT
{
  var octetstring vl_data := '61A7D3BEAA4C7DBD1FA3B2237A8CC92AE6575BADF894A34643D74AFF502BF523973DF1637453388CC4C06EC02D8AB44E3EDC866555BC0FDC56D0B2029110D7A1A1F585B65FB84D3674EC87B30BF5E7E8F747330549C77A9CCD348B7898825302408CE53D25ED62D56CA0FFACC0DFECDC9CFCBD03279047'O
  var octetstring vl_key := '000102030405060708090A0B0C0D0E0F0011223344556677'O
  var octetstring vl_iv := '0001020304050607'O
  
  var octetstring vl_encrypted := ef_3DES_CBC_Encrypt(vl_data, vl_key, vl_iv);
  log("Encrypted data: ")
  log(vl_encrypted)
  
  var octetstring vl_decrypted := ef_3DES_CBC_Decrypt(vl_encrypted, vl_key, vl_iv);
  log("Decrypted data: ")
  log(vl_decrypted)

  log("Original data: ")
  log(vl_data)

  if(match(vl_data, vl_decrypted))
  {
    setverdict(pass);
  } else {
    log(match(vl_data, vl_decrypted))
    setverdict(fail);
  }
}

testcase tc_AES_XCBC_128_no_data() runs on IKEv2_CT
{
  var octetstring vl_data := ''O
  var octetstring vl_key := '000102030405060708090a0b0c0d0e0f'O
  
  var octetstring vl_computed_value := ef_Calculate_AES_XCBC_128(vl_data, vl_key, 16);
  log("Computed value: ")
  log(vl_computed_value)
  
  var octetstring vl_xcbc_value := '75f0251d528ac01c4573dfd584d79f29'O
  log("XCBC value: ")
  log(vl_xcbc_value)

  if(match(vl_computed_value, vl_xcbc_value))
  {
    setverdict(pass);
  } else {
    log(match(vl_computed_value, vl_xcbc_value))
    setverdict(fail);
  }
}

testcase tc_AES_XCBC_128_20byte_data() runs on IKEv2_CT
{
  var octetstring vl_data := '000102030405060708090a0b0c0d0e0f10111213'O
  var octetstring vl_key := '000102030405060708090a0b0c0d0e0f'O
  
  var octetstring vl_computed_value := ef_Calculate_AES_XCBC_128(vl_data, vl_key, 16);
  log("Computed value: ")
  log(vl_computed_value)
  
  var octetstring vl_xcbc_value := '47f51b4564966215b8985c63055ed308'O
  log("XCBC value: ")
  log(vl_xcbc_value)

  if(match(vl_computed_value, vl_xcbc_value))
  {
    setverdict(pass);
  } else {
    log(match(vl_computed_value, vl_xcbc_value))
    setverdict(fail);
  }
}

testcase tc_test_f_calculate128_EEA1() runs on Security_CT{
  var OCT_16 key := '5ACB1D644C0D51204EA5F1451010D852'O
  var OCT_4 count := 'FA556B26'O
  var INT_5 bearer := 3
  var BIT_1 direction := '1'B
  var BIT_1_65504 msg_in := oct2bit('AD9C441F890B38C457A49D421407E8'O)
  var BIT_1_65504 msg_out:= f_calculate128_EEA1(key,count,bearer,direction,msg_in);
  log(msg_out)
  if(msg_out=='101110100000111100110001001100000000001100110100110001010110101101010010101001110100100101111100101110101100000001000110'B){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
}

testcase tc_test_f_calculate128_EIA1() runs on Security_CT{
  var OCT_16 key := '2BD6459F82C5B300952C49104881FF48'O
  var OCT_4 count := '38A6F056'O
  var integer bearer := 31;
  var BIT_1 direction := '0'B
  var BIT_1_65504 msg_in := '0011001100110010001101000110001001100011001110010011100001100001001101110011010001111001'B  //substr(oct2bit('6B227737296F393C8079353EDC87E2E805D2EC49A4F2D8E0'O),0,88);
  var BIT_1_65504 msg_out:= f_calculate128_EIA1(key,count,bearer,direction,msg_in);
  log(msg_out)
  if(msg_out=='01110011000111110001000101100101'B){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
  
  
}

testcase tc_test_f_calculate128_EIA2_1() runs on Security_CT{
  var OCT_16 key := 'd3c5d592327fb11c4035c6680af8c6d1'O
  var OCT_4 count := '398a59b4'O
  var integer bearer := 26;
  var BIT_1 direction := '1'B
  var octetstring msg_in := '484583d5afe082ae'O
  var octetstring msg_out:= f_calculate128_EIA2(key,count,bearer,direction,msg_in);
  log("Result   ",msg_out)
  log("Expected ",'B93787E6'O)
  if(msg_out=='B93787E6'O){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
  
  
}
testcase tc_test_f_calculate128_EIA2_2() runs on Security_CT{
  var OCT_16 key := 'b3120ffdb2cf6af4e73eaf2ef4ebec69'O
  var OCT_4 count := '296f393c'O
  var integer bearer := 11;
  var BIT_1 direction := '1'B
  var octetstring msg_in := '[encoded data, 4112 characters]'O
  var octetstring msg_out:= f_calculate128_EIA2(key,count,bearer,direction,msg_in);
  log("Result   ",msg_out)
  log("Expected ",'ebd5ccb0'O)
  if(msg_out=='ebd5ccb0'O){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
  
  
}
testcase tc_test_f_calculate128_EIA2_3() runs on Security_CT{
  var OCT_16 key := '83fd23a244a74cf358da3019f1722635'O
  var OCT_4 count := '36af6144'O
  var integer bearer := 15;
  var BIT_1 direction := '1'B
  var octetstring msg_in:='35c68716633c66fb750c266865d53c11ea05b1e9fa49c8398d48e1efa5909d3947902837f5ae96d5a05bc8d61ca8dbef1b13a4b4abfe4fb1006045b674bb54729304c382be53a5af05556176f6eaa2ef1d05e4b083181ee674cda5a485f74d7a'O  var octetstring msg_out:= f_calculate128_EIA2(key,count,bearer,direction,msg_in);
  log("Result   ",msg_out)
  log("Expected ",'e657e182'O)
  if(msg_out=='e657e182'O){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
  
  
}
testcase tc_test_f_calculate128_EEA2() runs on Security_CT{
  var OCT_16 key := 'd3c5d592327fb11c4035c6680af8c6d1'O
  var OCT_4 count := '398a59b4'O
  var integer bearer := 21;
  var BIT_1 direction := '1'B
  var octetstring msg_in := '981ba6824c1bfb1ab485472029b71d808ce33e2cc3c0b5fc1f3de8a6dc66b1f0'O
  var octetstring msg_out:= f_calculate128_EEA2(key,count,bearer,direction,msg_in);
  log(msg_out)
  
  if(msg_out=='E9FED8A63D155304D71DF20BF3E82214B20ED7DAD2F233DC3C22D7BDEEED8E78'O){
    setverdict(pass)
  } else {
    setverdict(fail)
  }
  
  
}


// execute security tests
control
{
  log(" ################### Security ################### ");

  execute(f_test_digestresponse()); 
  execute(f_test_MD5());
  execute(tc_AKA_functions());
  execute(tc_HMACMD5());  
  execute(tc_HMACMD5_2()); 
  execute(tc_HMACMD5_3()); 
  execute(tc_HMACMD5_4());
  execute(tc_HMAC_SHA1()); 
  execute(tc_HMAC_SHA256());       
  execute(tc_EIA());
  execute(tc_EEA()); 
  execute(tc_3des_ecb());  
  execute(tc_DH1024());  
  execute(tc_DH2048());  
  execute(tc_3DES_CBC());  
  execute(tc_AES_XCBC_128_no_data());
  execute(tc_AES_XCBC_128_20byte_data());
  execute(tc_test_f_calculate128_EEA1())
  execute(tc_test_f_calculate128_EIA1())
  execute(tc_test_f_calculate128_EIA2_1())
  execute(tc_test_f_calculate128_EIA2_2())
  execute(tc_test_f_calculate128_EIA2_3())
  execute(tc_test_f_calculate128_EEA2())
}

} with {extension "version R32A"}
