public byte[] EncryptMulticastCommand(MulticastKey mckey, MpanTable mpanTable, NodeGroupId nodeGroupId, byte[] homeId, byte[] plainData)
        {
            byte[] encryptedData = null;
            var    mpan          = new byte[16];

            if (IncrementMpan(mpanTable, mckey, nodeGroupId, mpan)) // Spec [CC:009F.01.00.11.028]
            {
                var iv             = GetPropertyIV(mpan);
                var sequenceNumber = GetPropertySequenceNo(mpanTable[nodeGroupId].SequenceNumber);
                var reserved       = GetPropertyReserved(0);

                var extentions = new Extensions();
                extentions.AddMpanGrpExtension(nodeGroupId.GroupId);
                FillExtensions(extentions, false);
                encryptedData = EncryptS2(mckey.CcmKey,
                                          sequenceNumber,
                                          plainData,
                                          nodeGroupId.NodeId,
                                          nodeGroupId.GroupId,
                                          homeId,
                                          iv,
                                          reserved,
                                          extentions);
                LastSentMulticastGroupId = nodeGroupId.GroupId;
            }
            return(encryptedData);
        }
 public static bool DecrementMpan(MpanTable mpanTable, MulticastKey multicastKey, NodeGroupId nodeGroupId, byte[] outMpan)
 {
     if (mpanTable.CheckMpanExists(nodeGroupId) && !mpanTable.IsRecordInMOSState(nodeGroupId))
     {
         var container = mpanTable[nodeGroupId];
         SecurityS2Utils.Aes128EcbEncrypt(container.MpanState, multicastKey.MpanKey, outMpan);
         container.DecrementMpanState();
         return(true);
     }
     return(false);
 }
        public static bool DecryptMulticastFrame(MpanTable mpanTable, MulticastKey multicastKey, NodeGroupId nodeGroupId, byte[] homeId, COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION cmd, out byte[] data, out Extensions extensions)
        {
            List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1> encryptedExtensionsList = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>();
            List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1> extensionsList          = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>();

            extensions = null;
            data       = null;
            bool ret = false;

            extensionsList = cmd.vg1;

            if (mpanTable.CheckMpanExists(nodeGroupId) && !mpanTable.IsRecordInMOSState(nodeGroupId))
            {
                // Backup mpan.
                byte   seqNo      = mpanTable[nodeGroupId].SequenceNumber;
                byte[] mpanBackup = new byte[mpanTable[nodeGroupId].MpanState.Length];
                Array.Copy(mpanTable[nodeGroupId].MpanState, mpanBackup, mpanTable[nodeGroupId].MpanState.Length);
                // Try to decrypt.
                bool   decryptSucceeded = false;
                int    attempts         = 0;
                byte[] plainData        = null;
                while (!decryptSucceeded && attempts < MaxMpanIterations)
                {
                    var mpan = new byte[16];
                    if (IncrementMpan(mpanTable, multicastKey, nodeGroupId, mpan))
                    {
                        decryptSucceeded = DecryptS2(multicastKey.CcmKey,
                                                     mpan,
                                                     nodeGroupId.NodeId,
                                                     nodeGroupId.GroupId,
                                                     homeId,
                                                     cmd,
                                                     out plainData,
                                                     out encryptedExtensionsList);
                    }
                    attempts++;
                }
                if (decryptSucceeded)
                {
                    extensions = new Extensions
                    {
                        ExtensionsList          = extensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(),
                        EncryptedExtensionsList = encryptedExtensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>()
                    };
                    ret  = true;
                    data = plainData;
                }
                else
                {
                    var restoredMpanContainer = mpanTable.AddOrReplace(nodeGroupId, seqNo, null, mpanBackup);
                }
            }
            return(ret);
        }