protected static byte[] EncryptS2(byte[] key, byte sequenceNumber, byte[] cmdData, byte senderNodeId, byte receiverNodeId, byte[] homeId, byte[] iv, byte reserved, Extensions extensions) { var dataToEncrypt = new List <byte>(); var ret = new COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION { sequenceNumber = sequenceNumber, vg1 = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>() }; if (extensions != null) { if (!extensions.ExtensionsList.IsNullOrEmpty()) { ret.properties1.extension = 1; ret.vg1.AddRange(extensions.ExtensionsList); } if (!extensions.EncryptedExtensionsList.IsNullOrEmpty()) { ret.properties1.encryptedExtension = 1; foreach (var encExt in extensions.EncryptedExtensionsList) { dataToEncrypt.Add(encExt.extensionLength); dataToEncrypt.Add(encExt.properties1); if (encExt.extension != null && encExt.extension.Count > 0) { dataToEncrypt.AddRange(encExt.extension); } } } } if (!cmdData.IsNullOrEmpty()) { dataToEncrypt.AddRange(cmdData); } ret.properties1.reserved = reserved; byte[] extensionData = new byte[0]; if (ret.properties1.extension == 1) { var tempExtDataList = new List <byte>(); foreach (var ext in ret.vg1) { tempExtDataList.AddRange(new byte[] { ext.extensionLength, ext.properties1 }); if (ext.extension != null) { tempExtDataList.AddRange(ext.extension); } } extensionData = tempExtDataList.ToArray(); } var payloadLength = (ushort)(4 + extensionData.Length + dataToEncrypt.Count + SecurityS2Utils.AUTH_DATA_HEADER_LENGTH); var cipherData = EncryptS2Internal(key, iv, senderNodeId, receiverNodeId, homeId, payloadLength, ret.sequenceNumber, ret.properties1, extensionData, dataToEncrypt.ToArray()); ret.ccmCiphertextObject = new List <byte>(cipherData); return(ret); }
public static byte[] EncryptPayload(byte senderId, byte receiverId, byte[] homeId, byte sequenceNumber, byte[] receiverNonce, byte[] senderNonce, byte[] networkKey, byte[] textToEncrypt, int generationCount, bool isRealKey) { var ret = new COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION { sequenceNumber = sequenceNumber }; InvariantPeerNodeId peerNodeId = new InvariantPeerNodeId(0); var mpanKey = new byte[SecurityS2Utils.KEY_SIZE]; var ccmKey = new byte[SecurityS2Utils.KEY_SIZE]; var personalization = new byte[SecurityS2Utils.PERSONALIZATION_SIZE]; if (isRealKey) { SecurityS2Utils.NetworkKeyExpand(networkKey, ccmKey, personalization, mpanKey); } else { SecurityS2Utils.TempKeyExpand(networkKey, ccmKey, personalization, mpanKey); } SpanTable spanTable = new SpanTable(); spanTable.Add(peerNodeId, receiverNonce, 0, 0); SpanContainer spanContainer = spanTable.GetContainer(peerNodeId); spanContainer.InstantiateWithSenderNonce(senderNonce, personalization); for (int i = 0; i < generationCount; i++) { spanContainer.NextNonce(); } AAD aad = new AAD { SenderNodeId = senderId, ReceiverNodeId = receiverId, HomeId = homeId, PayloadLength = (ushort)(textToEncrypt.Length + SecurityS2Utils.AUTH_DATA_HEADER_LENGTH), SequenceNumber = sequenceNumber }; aad.PayloadLength += (ushort)((byte[])ret).Length; var cipherData = SecurityS2Utils.CcmEncryptAndAuth(ccmKey, spanContainer.Span, aad, textToEncrypt); if (cipherData != null && cipherData.Length > 0) { ret.ccmCiphertextObject = new List <byte>(cipherData); } else { ret = null; } return(ret); }
public static bool DecryptS2( byte[] key, byte[] iv, byte senderNodeId, byte receiverNodeId, byte[] homeId, COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION cmd, out byte[] decryptedPayload, out List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1> decryptedExtensions) { var cipherData = cmd.ccmCiphertextObject.ToArray(); decryptedPayload = new byte[0]; decryptedExtensions = new List <COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1>(); if (cipherData.Length == SecurityS2Utils.AUTH_DATA_HEADER_LENGTH) { return(true); } var payloadLength = (ushort)((byte[])cmd).Length; var sequenceNumber = cmd.sequenceNumber; var statusByte = cmd.properties1; byte[] extensionData = new byte[0]; if (cmd.properties1.extension == 1) { var dataList = new List <byte>(); foreach (var vg1 in cmd.vg1) { dataList.AddRange(new byte[] { vg1.extensionLength, vg1.properties1 }); dataList.AddRange(vg1.extension); } extensionData = dataList.ToArray(); } var decryptedData = DecryptS2Internal(key, iv, senderNodeId, receiverNodeId, homeId, payloadLength, sequenceNumber, statusByte, extensionData, cipherData); var isDecryptSucceeded = decryptedData.Length > 0; if (isDecryptSucceeded) { if (cmd.properties1.encryptedExtension == 1) { try { int ind = 0; while (ind + 2 <= decryptedData.Length && ind + decryptedData[ind] <= decryptedData.Length) { COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1 ext = new COMMAND_CLASS_SECURITY_2.SECURITY_2_MESSAGE_ENCAPSULATION.TVG1 { extensionLength = decryptedData[ind], properties1 = decryptedData[ind + 1] }; if (ind + ext.extensionLength <= decryptedData.Length) { ext.extension = decryptedData.Skip(ind + 2).Take(ext.extensionLength - 2).ToList(); } else { ext.extension = new List <byte>(0); } decryptedExtensions.Add(ext); ind += ext.extensionLength; if (ext.properties1.moreToFollow == 0) { break; } } if (ind < decryptedData.Length) // Has payload. { decryptedPayload = decryptedData.Skip(ind).ToArray(); } } catch (IndexOutOfRangeException) { } catch (ArgumentOutOfRangeException) { } catch (ArgumentException) { } } else { decryptedPayload = decryptedData; } } return(isDecryptSucceeded); }
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); }
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); }