/*@!Encoding:1252*/
includes
{
  
}

variables
{
  long shVersion ;          // either 111                or 121               or 131
  char shPcolDesc[16] ;     // either "geo_sh"           or "geo_sh_121"      or "wssv3"
}

void evalShVersion()
{
  // the configuration contains three root certificates, "Demo Root 1.3.1", "Demo Root 1.2.1", "Demo Root 1.1.1"
  // depending on the version configured in CANoe one of them is visible.
  if (C2xSecCertificateGetHandle("Vector Demo Root 1.3.1") != 0)
  {
    shVersion = 131 ;
    strncpy(shPcolDesc    , "wssv3"          , elcount(shPcolDesc    )) ;
    SysSetVariableString(sysvar::ShVersion, "ETSI 103 097 1.3.1") ;
  }
  else if (C2xSecCertificateGetHandle("Vector Demo Root 1.2.1") != 0)
  {
    shVersion = 121 ;
    strncpy(shPcolDesc    , "geo_sh_121"          , elcount(shPcolDesc    )) ;
    SysSetVariableString(sysvar::ShVersion, "ETSI 103 097 1.2.1") ;
  }
  else if (C2xSecCertificateGetHandle("Vector Demo Root 1.1.1") != 0)
  {
    shVersion = 111 ;
    strncpy(shPcolDesc    , "geo_sh"          , elcount(shPcolDesc    )) ;
    SysSetVariableString(sysvar::ShVersion, "ETSI 103 097 1.1.1") ;
  }
}

void sysVarReset()
{
  SysSetVariableString(sysvar::Receiver::certName, "") ;
  SysSetVariableString(sysvar::Receiver::certDigest, "") ;
  SysSetVariableString(sysvar::Receiver::pcaName, "") ;
  SysSetVariableString(sysvar::Receiver::pcaDigest, "") ;
  SysSetVariableString(sysvar::Receiver::rcaName, "") ;
  SysSetVariableString(sysvar::Receiver::rcaDigest, "") ;
  SysSetVariableString(sysvar::Receiver::securityProfile, "") ;
  SysSetVariableString(sysvar::Receiver::signerType, "") ;
  SysSetVariableString(sysvar::Receiver::signatureStatus, "") ;
}

on start
{
  // register the receive callback
  C2xRegisterCallback(0, "OnC2xPacket");

  evalShVersion() ;
  sysVarReset() ;  
}

// output signature status
void SignatureStatus(long packet)
{
  long signatureStatus ;
  char buffer[100] ;
  long buffOffset ;

  buffOffset = 0 ;
  
  signatureStatus = C2xSecPacketGetStatus(packet);

  switch (signatureStatus & 0x0f00) // mask the certificate subject type
  {
  case 0x0100: strncpy(buffer, "Root CA certificate: "  , elcount(buffer)) ; break;
  case 0x0200: strncpy(buffer, "PCA certificate: "      , elcount(buffer)) ; break;
  case 0x0300: strncpy(buffer, "LTCA certificate: "     , elcount(buffer)) ; break;
  case 0x0400: strncpy(buffer, "Pseudonym certificate: ", elcount(buffer)) ; break;
  case 0x0500: strncpy(buffer, "Longterm certificate: " , elcount(buffer)) ; break;
  case 0x0600: strncpy(buffer, "CRL certificate: "      , elcount(buffer)) ; break;
  case 0x0700: strncpy(buffer, "Message: "              , elcount(buffer)) ; break;
  default: buffer[0] = 0 ; break ;
  }

  buffOffset = strlen(buffer) ;
  
  switch (signatureStatus & 0xf000) // mask the signature status
  {
  case 0x1000: // unknown
    strncpy_off(buffer, + buffOffset, "unknown", elcount(buffer) - buffOffset);
    break;

  case 0x2000: // invalid
    switch (signatureStatus & 0x00ff) // mask the signature status sub cause
    {
    case 0x0001: strncpy_off(buffer, + buffOffset, "invalid signature"  , elcount(buffer) - buffOffset) ; break;
    case 0x0002: strncpy_off(buffer, + buffOffset, "invalid signer type", elcount(buffer) - buffOffset) ; break;
    case 0x0003: strncpy_off(buffer, + buffOffset, "root untrusted"     , elcount(buffer) - buffOffset) ; break;
    default:     strncpy_off(buffer, + buffOffset, "invalid"            , elcount(buffer) - buffOffset) ; break;
    }
    break;

  case 0x3000: // valid
    strncpy_off(buffer, + buffOffset, "trusted"  , elcount(buffer) - buffOffset);
    break;

  default: // error
    strncpy_off(buffer, + buffOffset, "error"  , elcount(buffer) - buffOffset);
    break;
  }
  SysSetVariableString(sysvar::Receiver::signatureStatus, buffer) ;
}

void CertInfo(long packet)
{
  long certHdl ;
  byte hashedId8[8] ;
  char buffer[100] ;
  
  // its certificate
  certHdl = C2xSecPacketGetSignerHandle(packet) ; // get signer cert of message
  if (!certHdl)
    return ;
  
  C2xSecCertificateGetName(certHdl, elcount(buffer), buffer) ; // get name
  sysSetVariableString(sysvar::Receiver::certName, buffer) ;

  C2xSecCertificateGetHashedId8(certHdl, hashedId8) ; // get hashedId8
  snprintf(buffer, elcount(buffer), "%02X %02X %02X %02X %02X %02X %02X %02X ",
    hashedId8[0], hashedId8[1], hashedId8[2], hashedId8[3], 
    hashedId8[4], hashedId8[5], hashedId8[6], hashedId8[7]) ;
  sysSetVariableString(sysvar::Receiver::certDigest, buffer) ;
  
  // pca certificate  
  certHdl = C2xSecCertificateGetSignerHandle(certHdl) ; // get signer cert of its cert
  if (!certHdl)
    return ;
  
  C2xSecCertificateGetName(certHdl, elcount(buffer), buffer) ; // get name
  sysSetVariableString(sysvar::Receiver::pcaName, buffer) ;
  
  C2xSecCertificateGetHashedId8(certHdl, hashedId8) ; // get hashedId8
  snprintf(buffer, elcount(buffer), "%02X %02X %02X %02X %02X %02X %02X %02X ",
    hashedId8[0], hashedId8[1], hashedId8[2], hashedId8[3], 
    hashedId8[4], hashedId8[5], hashedId8[6], hashedId8[7]) ;
  sysSetVariableString(sysvar::Receiver::pcaDigest, buffer) ;
  
  // rca certificate  
  certHdl = C2xSecCertificateGetSignerHandle(certHdl) ; // get signer cert of pca cert
  if (!certHdl)
    return ;
  
  C2xSecCertificateGetName(certHdl, elcount(buffer), buffer) ; // get name
  sysSetVariableString(sysvar::Receiver::rcaName, buffer) ;

  C2xSecCertificateGetHashedId8(certHdl, hashedId8) ; // get hashedId8
  snprintf(buffer, elcount(buffer), "%02X %02X %02X %02X %02X %02X %02X %02X ",
    hashedId8[0], hashedId8[1], hashedId8[2], hashedId8[3], 
    hashedId8[4], hashedId8[5], hashedId8[6], hashedId8[7]) ;
  sysSetVariableString(sysvar::Receiver::rcaDigest, buffer) ;
}

void OnC2xPacket( LONG channel, LONG dir, LONG radioChannel, LONG signalStrength, LONG signalQuality, LONG packet )
{
  long signerType ;
  long securityProfile ;
  long itsAid ;
  
  // reset receiver panel fields
  sysVarReset() ;
  
  SignatureStatus(packet) ; // calculate status
  CertInfo(packet) ;        // calculate cert hierarchy
  
  // signer type
  signerType = C2xGetTokenInt(packet, shPcolDesc, "signerType") ;
  switch (signerType)
  {
    case 1: sysSetVariableString(sysvar::Receiver::signerType, "HashedId8 (Digest)") ; break ;
    case 2: sysSetVariableString(sysvar::Receiver::signerType, "Certificate"       ) ; break ;
    case 3: sysSetVariableString(sysvar::Receiver::signerType, "Certificate Chain" ) ; break ;
  }
  
  // security profile
  switch (shVersion)
  {
  case 111:
    securityProfile = C2xGetTokenInt(packet, "geo_sh", "securityProfile") ;
    switch (securityProfile)
    {
    case 1: sysSetVariableString(sysvar::Receiver::securityProfile, "CAM"    ) ; break ;
    case 2: sysSetVariableString(sysvar::Receiver::securityProfile, "DENM"   ) ; break ;
    case 3: sysSetVariableString(sysvar::Receiver::securityProfile, "Generic") ; break ;
    }
    break ;
  case 121:
    itsAid = C2xGetTokenInt(packet, "geo_sh_121", "itsAid") ;
    switch (itsAid)
    {
    case 36: sysSetVariableString(sysvar::Receiver::securityProfile, "CAM"    ) ; break ;
    case 37: sysSetVariableString(sysvar::Receiver::securityProfile, "DENM"   ) ; break ;
    default:sysSetVariableString(sysvar::Receiver::securityProfile, "?"      ) ; break ;
    }
    break ;
  case 131:
    itsAid = C2xGetTokenInt(packet, "wssv3", "psid") ;
    switch (itsAid)
    {
    case 36: sysSetVariableString(sysvar::Receiver::securityProfile, "CAM"    ) ; break ;
    case 37: sysSetVariableString(sysvar::Receiver::securityProfile, "DENM"   ) ; break ;
    default:sysSetVariableString(sysvar::Receiver::securityProfile, "?"      ) ; break ;
    }
    break ;
  }
}
