protected byte[] EncryptSinglecastCommandInternal(SinglecastKey sckey, SpanTable spanTable, byte senderNodeId, byte receiverNodeId, byte[] homeId, byte[] plainData, Extensions extentions, SubstituteSettings substituteSettings)
        {
            Extensions          ext        = extentions ?? new Extensions();
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(senderNodeId, receiverNodeId);
            var spanContainer = spanTable.GetContainer(peerNodeId);
            var spanExtension = GetPersonalizationArray(sckey, spanContainer);

            if (spanExtension != null)
            {
                ext.AddSpanExtension(spanExtension);
            }
            spanContainer.NextNonce();
            spanTable.UpdateTxSequenceNumber(peerNodeId);

            var iv             = GetPropertyIV(spanContainer.Span);
            var sequenceNumber = GetPropertySequenceNo(spanContainer.TxSequenceNumber);
            var reserved       = GetPropertyReserved(0);

            FillExtensions(ext, true);
            byte[] encryptedData = EncryptS2(sckey.CcmKey,
                                             sequenceNumber,
                                             plainData,
                                             senderNodeId,
                                             receiverNodeId,
                                             homeId,
                                             iv,
                                             reserved,
                                             ext);
            if (plainData != null && encryptedData != null)
            {
                SaveDataForRetransmission(peerNodeId, plainData, substituteSettings, sckey.SecurityScheme);
            }
            return(encryptedData);
        }
 protected virtual byte[] GetPersonalizationArray(SinglecastKey sckey, SpanContainer spanContainer)
 {
     byte[] senderNonce = null;
     if (spanContainer.SpanState == SpanStates.ReceiversNonce)
     {
         senderNonce = GetRandomData(); // Generate sender nonce.
         spanContainer.InstantiateWithSenderNonce(senderNonce, sckey.Personalization);
     }
     return(senderNonce);
 }
        public byte[] EncryptSinglecastCommand(SinglecastKey sckey, SpanTable spanTable, byte senderNodeId, byte receiverNodeId, byte[] homeId, byte[] plainData, Extensions extentions, SubstituteSettings substituteSettings)
        {
            byte[] encryptedData           = null;
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(senderNodeId, receiverNodeId);
            var spanContainer = spanTable.GetContainer(peerNodeId);

            if (spanContainer != null)
            {
                encryptedData = EncryptSinglecastCommandInternal(sckey, spanTable, senderNodeId, receiverNodeId, homeId, plainData, extentions, substituteSettings);
            }
            else
            {
            }
            return(encryptedData);
        }
        public static bool DecryptSinglecastFrame(
            SpanContainer spanContainer,
            SinglecastKey singlecastKey,
            byte sourceNodeId,
            byte destNodeId,
            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;
            bool isDecryptSucceeded        = false;
            InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(destNodeId, sourceNodeId);

            extensionsList = cmd.vg1;
            if (spanContainer != null && singlecastKey != null)
            {
                spanContainer.RxSequenceNumber = cmd.sequenceNumber;
                if (spanContainer.SpanState == SpanStates.ReceiversNonce)
                {
                    #region SpanStates.ReceiversNonce
                    // Establish nonce synchronization.
                    byte[] senderEntropyInput = null;
                    if (cmd.properties1.extension == 1)
                    {
                        foreach (var extData in cmd.vg1)
                        {
                            if (extData.properties1.type == (byte)ExtensionTypes.Span &&
                                extData.extensionLength == 18 &&
                                extData.extension.Count == 16)
                            {
                                senderEntropyInput = extData.extension.ToArray();
                                break;
                            }
                        }
                    }

                    if (senderEntropyInput != null)
                    {
                        var receiverEntropyInput = spanContainer.ReceiversNonce;
                        spanContainer.InstantiateWithSenderNonce(senderEntropyInput, singlecastKey.Personalization);
                        byte[] plainData;
                        spanContainer.NextNonce();
                        isDecryptSucceeded = DecryptS2(singlecastKey.CcmKey,
                                                       spanContainer.Span,
                                                       sourceNodeId,
                                                       destNodeId,
                                                       homeId,
                                                       cmd,
                                                       out plainData,
                                                       out encryptedExtensionsList);
                        if (isDecryptSucceeded)
                        {
                            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
                        {
                            extensions = new Extensions
                            {
                                ExtensionsList          = extensionsList ?? new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(),
                                EncryptedExtensionsList = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>()
                            };
                            spanContainer.SetReceiversNonceState();
                        }
                    }

                    #endregion
                }
                else if (spanContainer.SpanState == SpanStates.Span)
                {
                    #region SpanStates.Span
                    // Check nonce synchronization.
                    int    attemptsCount = 5;
                    byte[] plainData     = null;
                    while (!isDecryptSucceeded && attemptsCount > 0)
                    {
                        spanContainer.NextNonce();
                        attemptsCount--;
                        if (spanContainer != null)
                        {
                            isDecryptSucceeded = DecryptS2(singlecastKey.CcmKey,
                                                           spanContainer.Span,
                                                           sourceNodeId,
                                                           destNodeId,
                                                           homeId,
                                                           cmd,
                                                           out plainData,
                                                           out encryptedExtensionsList);
                        }
                    }
                    if (isDecryptSucceeded)
                    {
                        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;
                    }
                    #endregion
                }
                else
                {
                    throw new InvalidOperationException("Unexpected nonce state");
                }
            }
            return(ret);
        }