diff --git a/P25/P25Crypto.cs b/P25/P25Crypto.cs
index a4e82e0..f11833f 100644
--- a/P25/P25Crypto.cs
+++ b/P25/P25Crypto.cs
@@ -93,7 +93,7 @@ namespace fnecore.P25
}
///
- ///
+ /// Helper to set the Key Info
///
///
///
@@ -109,7 +109,7 @@ namespace fnecore.P25
}
///
- ///
+ /// Helper to check if the key we have is null
///
///
///
@@ -119,7 +119,7 @@ namespace fnecore.P25
}
///
- ///
+ /// Helper to create key streams based on Algorithm Id
///
///
///
@@ -144,6 +144,12 @@ namespace fnecore.P25
GenerateAESKeystream();
return true;
}
+ if (algid == P25Defines.P25_ALGO_DES)
+ {
+ keystream = new byte[224];
+ GenerateDESKeystream();
+ return true;
+ }
else if (algid == P25Defines.P25_ALGO_ARC4)
{
keystream = new byte[469];
@@ -169,21 +175,83 @@ namespace fnecore.P25
{
P25Defines.P25_ALGO_AES => AESProcess(imbe, duid),
P25Defines.P25_ALGO_ARC4 => ARC4Process(imbe, duid),
+ P25Defines.P25_ALGO_DES => DESProcess(imbe, duid),
_ => false
};
}
///
- ///
+ /// Create DES keystream.
///
- ///
- ///
- ///
- private void Swap(byte[] a, int i1, int i2)
+ private void GenerateDESKeystream()
{
- byte temp = a[i1];
- a[i1] = a[i2];
- a[i2] = temp;
+ if (currentKey == null)
+ return;
+
+ byte[] desKey = new byte[8];
+ int padLen = Math.Max(8 - currentKey.Key.Length, 0);
+ for (int i = 0; i < padLen; i++)
+ desKey[i] = 0;
+ for (int i = padLen; i < 8; i++)
+ desKey[i] = currentKey.Key[i - padLen];
+
+ byte[] iv = new byte[8];
+ Array.Copy(messageIndicator, iv, 8);
+
+ using (var des = DES.Create())
+ {
+ des.Mode = CipherMode.ECB;
+ des.Padding = PaddingMode.None;
+ des.Key = desKey;
+
+ using (var encryptor = des.CreateEncryptor())
+ {
+ byte[] input = iv;
+ byte[] output = new byte[8];
+
+ for (int i = 0; i < 28; i++)
+ {
+ encryptor.TransformBlock(input, 0, 8, output, 0);
+ Array.Copy(output, 0, keystream, i * 8, 8);
+ input = output.ToArray();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Create AES keystream.
+ ///
+ private void GenerateAESKeystream()
+ {
+ if (currentKey == null)
+ return;
+
+ byte[] key = currentKey.Key;
+ byte[] iv = ExpandMIToIV(messageIndicator);
+
+ using (var aes = Aes.Create())
+ {
+ aes.KeySize = 256;
+ aes.BlockSize = 128;
+ aes.Key = key.Length == 32 ? key : key.Concat(new byte[32 - key.Length]).ToArray();
+ aes.Mode = CipherMode.ECB;
+ aes.Padding = PaddingMode.None;
+
+ using (var encryptor = aes.CreateEncryptor())
+ {
+ byte[] input = new byte[16];
+ Array.Copy(iv, input, 16);
+ byte[] output = new byte[16];
+
+ for (int i = 0; i < keystream.Length / 16; i++)
+ {
+ encryptor.TransformBlock(input, 0, 16, output, 0);
+ Buffer.BlockCopy(output, 0, keystream, i * 16, 16);
+ Array.Copy(output, input, 16);
+ }
+ }
+ }
}
///
@@ -246,38 +314,25 @@ namespace fnecore.P25
}
///
- /// Create AES keystream.
+ /// Helper to process IMBE audio using DES-OFB
///
- private void GenerateAESKeystream()
+ ///
+ ///
+ ///
+ private bool DESProcess(byte[] imbe, P25DUID duid)
{
- if (currentKey == null)
- return;
+ int offset = 8;
- byte[] key = currentKey.Key;
- byte[] iv = ExpandMIToIV(messageIndicator);
+ if (duid == P25DUID.LDU2)
+ offset += 101;
- using (var aes = Aes.Create())
- {
- aes.KeySize = 256;
- aes.BlockSize = 128;
- aes.Key = key.Length == 32 ? key : key.Concat(new byte[32 - key.Length]).ToArray();
- aes.Mode = CipherMode.ECB;
- aes.Padding = PaddingMode.None;
+ offset += (ksPosition * IMBE_BUF_LEN) + IMBE_BUF_LEN + (ksPosition < 8 ? 0 : 2);
+ ksPosition = (ksPosition + 1) % 9;
- using (var encryptor = aes.CreateEncryptor())
- {
- byte[] input = new byte[16];
- Array.Copy(iv, input, 16);
- byte[] output = new byte[16];
+ for (int j = 0; j < IMBE_BUF_LEN; ++j)
+ imbe[j] ^= keystream[j + offset];
- for (int i = 0; i < keystream.Length / 16; i++)
- {
- encryptor.TransformBlock(input, 0, 16, output, 0);
- Buffer.BlockCopy(output, 0, keystream, i * 16, 16);
- Array.Copy(output, input, 16);
- }
- }
- }
+ return true;
}
///
@@ -322,6 +377,19 @@ namespace fnecore.P25
return true;
}
+ ///
+ /// Swap two elements in a byte array
+ ///
+ ///
+ ///
+ ///
+ private void Swap(byte[] a, int i1, int i2)
+ {
+ byte temp = a[i1];
+ a[i1] = a[i2];
+ a[i2] = temp;
+ }
+
///
/// Cycle P25 LFSR
///