Made preparations for unscrambling TS Packets in case the key is known.
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 3m17s
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 3m17s
This commit is contained in:
parent
cd2055a07a
commit
376201cfa5
62
skyscraper8/Mpeg2/PacketFilter/BissDescrambleFilter.cs
Normal file
62
skyscraper8/Mpeg2/PacketFilter/BissDescrambleFilter.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.src.Mpeg2.PacketFilter;
|
||||
using skyscraper8.Skyscraper.Security.Cryptography;
|
||||
|
||||
namespace skyscraper8.Mpeg2.PacketFilter
|
||||
{
|
||||
internal class BissDescrambleFilter : IPacketFilter
|
||||
{
|
||||
public BissDescrambleFilter(byte[] key, params uint[] pids)
|
||||
{
|
||||
this.key = key;
|
||||
if (pids != null)
|
||||
{
|
||||
if (pids.Length > 0)
|
||||
{
|
||||
_pidsToDescramble = new List<uint>();
|
||||
_pidsToDescramble.AddRange(pids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] key;
|
||||
private List<uint> _pidsToDescramble;
|
||||
private bool CheckPid(uint pid)
|
||||
{
|
||||
if (_pidsToDescramble == null)
|
||||
return true;
|
||||
else
|
||||
return _pidsToDescramble.Contains(pid);
|
||||
}
|
||||
|
||||
private DvbCsa2 csa2;
|
||||
|
||||
public bool PassPacket(TsPacket packet)
|
||||
{
|
||||
if (packet.TSC == 0)
|
||||
return true;
|
||||
|
||||
if (!CheckPid(packet.PID))
|
||||
return true;
|
||||
|
||||
//Okay, we actually need to do something...
|
||||
if (csa2 == null)
|
||||
{
|
||||
csa2 = new DvbCsa2(key.Length == 8 ? DvbCsa2.EntropyMode.FULL_CW : DvbCsa2.EntropyMode.REDUCE_ENTROPY);
|
||||
csa2.SetKeyImpl(key);
|
||||
}
|
||||
|
||||
int retsize = 0;
|
||||
byte[] unscrambled = new byte[packet.Payload.Length];
|
||||
csa2.DecryptImpl(packet.Payload, packet.Payload.Length, unscrambled, unscrambled.Length, ref retsize);
|
||||
|
||||
packet.SetUnscrambled(unscrambled);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,18 +48,18 @@ namespace skyscraper5.Mpeg2
|
||||
//Unit start
|
||||
}
|
||||
|
||||
int payloadOffset = 4;
|
||||
PayloadOffset = 4;
|
||||
if (PayloadUnitStart)
|
||||
{
|
||||
PayloadStartOffset = buffer[4] & 0xff;
|
||||
payloadOffset++;
|
||||
PayloadOffset++;
|
||||
}
|
||||
|
||||
switch (AdaptionFieldControl)
|
||||
{
|
||||
case 1:
|
||||
br.Position = payloadOffset;
|
||||
long PayloadLengthB = 188 - payloadOffset;
|
||||
br.Position = PayloadOffset;
|
||||
long PayloadLengthB = 188 - PayloadOffset;
|
||||
Payload = br.ReadBytes(PayloadLengthB);
|
||||
break;
|
||||
case 2:
|
||||
@ -74,9 +74,9 @@ namespace skyscraper5.Mpeg2
|
||||
TEI = true;
|
||||
break;
|
||||
}
|
||||
payloadOffset += Adaption.Length;
|
||||
br.Position = payloadOffset;
|
||||
long PayloadLength = (188 - payloadOffset);
|
||||
PayloadOffset += Adaption.Length;
|
||||
br.Position = PayloadOffset;
|
||||
long PayloadLength = (188 - PayloadOffset);
|
||||
Payload = br.ReadBytes((int)PayloadLength);
|
||||
break;
|
||||
default:
|
||||
@ -99,7 +99,7 @@ namespace skyscraper5.Mpeg2
|
||||
/// 2 = scrambled, even key
|
||||
/// 3 = scrambled, odd key
|
||||
/// </summary>
|
||||
public uint TSC { get; private set; }
|
||||
public uint TSC { get; internal set; }
|
||||
public uint AdaptionFieldControl { get; private set; }
|
||||
public uint Continuity { get; private set; }
|
||||
public int PayloadStartOffset { get; private set; }
|
||||
@ -108,6 +108,8 @@ namespace skyscraper5.Mpeg2
|
||||
public byte[] RawPacket { get; private set; }
|
||||
public ulong Serial { get; private set; }
|
||||
|
||||
public int PayloadOffset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieving the raw packet, including adaption field and Payload, but without the four byte header.
|
||||
/// </summary>
|
||||
@ -118,5 +120,13 @@ namespace skyscraper5.Mpeg2
|
||||
Array.Copy(RawPacket, 4, buffer, 0, 184);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void SetUnscrambled(byte[] unscrambledPayload)
|
||||
{
|
||||
TSC = 0;
|
||||
Payload = unscrambledPayload;
|
||||
Array.Copy(unscrambledPayload, 0, RawPacket, PayloadOffset, unscrambledPayload.Length);
|
||||
RawPacket[3] &= 0x3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ using skyscraper5.Skyscraper.IO.TunerInterface;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.RecordingImporter;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.FrameGrabber;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
|
||||
using skyscraper5.Skyscraper.Webserver;
|
||||
@ -24,15 +23,9 @@ using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using skyscraper5.Mpeg2.Descriptors;
|
||||
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
||||
using skyscraper8;
|
||||
using skyscraper8.GSE;
|
||||
using skyscraper8.SatIp;
|
||||
using skyscraper8.SatIp.RtspResponses;
|
||||
using skyscraper8.SimpleServiceDiscoveryProtocol;
|
||||
using skyscraper8.Skyscraper.Math;
|
||||
using skyscraper8.Skyscraper;
|
||||
using skyscraper8.Skyscraper.Security.AccessControl;
|
||||
@ -46,40 +39,42 @@ namespace skyscraper5
|
||||
|
||||
private static void IntegrationTest()
|
||||
{
|
||||
/*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
|
||||
foreach (SsdpDevice ssdpDevice in ssdpDevices)
|
||||
{
|
||||
Console.WriteLine("SSDP device: {0}", ssdpDevice.Server);
|
||||
}*/
|
||||
SoftcamTestProgram softcamTestProgram = new SoftcamTestProgram();
|
||||
softcamTestProgram.Run();
|
||||
/*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
|
||||
foreach (SsdpDevice ssdpDevice in ssdpDevices)
|
||||
{
|
||||
Console.WriteLine("SSDP device: {0}", ssdpDevice.Server);
|
||||
}*/
|
||||
|
||||
//"urn:ses-com:device:SatIPServer:1"
|
||||
/*PluginManager pluginManager = PluginManager.GetInstance();
|
||||
StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
|
||||
ObjectStorageFactory objectStorageFactory = storageConnectionManager.GetDefaultObjectStorageFactory();
|
||||
ObjectStorage objectStorage = objectStorageFactory.CreateObjectStorage();*/
|
||||
//"urn:ses-com:device:SatIPServer:1"
|
||||
/*PluginManager pluginManager = PluginManager.GetInstance();
|
||||
StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
|
||||
ObjectStorageFactory objectStorageFactory = storageConnectionManager.GetDefaultObjectStorageFactory();
|
||||
ObjectStorage objectStorage = objectStorageFactory.CreateObjectStorage();*/
|
||||
|
||||
/*url = RtspClient.MakeUrl(DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A | DiSEqC_Opcode.DISEQC_HORIZONTAL, 11141, true, 23500);
|
||||
describe = rtspClient.GetDescribe(url);
|
||||
sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
||||
/*url = RtspClient.MakeUrl(DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A | DiSEqC_Opcode.DISEQC_HORIZONTAL, 11141, true, 23500);
|
||||
describe = rtspClient.GetDescribe(url);
|
||||
sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
||||
|
||||
rtcps = 0;
|
||||
rtps = 0;
|
||||
rtcps = 0;
|
||||
rtps = 0;
|
||||
|
||||
setup = rtspClient.GetSetup(url);
|
||||
setup.OnRtcpPacket += ((data, length) =>
|
||||
rtcps++);
|
||||
setup.OnRtpPacket += (data, length) =>
|
||||
rtps++;
|
||||
setup = rtspClient.GetSetup(url);
|
||||
setup.OnRtcpPacket += ((data, length) =>
|
||||
rtcps++);
|
||||
setup.OnRtpPacket += (data, length) =>
|
||||
rtps++;
|
||||
|
||||
play = rtspClient.GetPlay(setup);
|
||||
play = rtspClient.GetPlay(setup);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
Thread.Sleep(5000);
|
||||
|
||||
rtspClient.AutoReconnect = false;
|
||||
rtspClient.GetTeardown(setup);
|
||||
Console.WriteLine("{0} RTCPs", rtcps);
|
||||
Console.WriteLine("{0} RTPs", rtps);*/
|
||||
//rtspClient.Dispose();
|
||||
rtspClient.AutoReconnect = false;
|
||||
rtspClient.GetTeardown(setup);
|
||||
Console.WriteLine("{0} RTCPs", rtcps);
|
||||
Console.WriteLine("{0} RTPs", rtps);*/
|
||||
//rtspClient.Dispose();
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
@ -365,7 +360,7 @@ namespace skyscraper5
|
||||
catalogueGenerator.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Passing passing = new Passing();
|
||||
if (!passing.Boot())
|
||||
|
||||
@ -38,5 +38,10 @@ namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
return (int)Coordinate;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("F {0:X8} 00000000 {1}", Coordinate, BitConverter.ToString(Key).Replace("-", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,5 +213,22 @@ namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
|
||||
private HashSet<BissKey> _bissKeys;
|
||||
public IReadOnlySet<BissKey> BissKeys => _bissKeys;
|
||||
|
||||
public byte[] FindBissKey(ushort transportStreamId, ushort networkId)
|
||||
{
|
||||
if (_bissKeys == null)
|
||||
return null;
|
||||
|
||||
byte[] transportStreamIdBytes = BitConverter.GetBytes(transportStreamId);
|
||||
byte[] networkIdBytes = BitConverter.GetBytes(networkId);
|
||||
byte[] keyBytes = new byte[] { networkIdBytes[0], networkIdBytes[1], transportStreamIdBytes[0], transportStreamIdBytes[1] };
|
||||
uint coordinate = BitConverter.ToUInt32(keyBytes);
|
||||
|
||||
BissKey bissKey = _bissKeys.FirstOrDefault(x => x.Coordinate == coordinate);
|
||||
if (bissKey != null)
|
||||
return bissKey.Key;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper8.Mpeg2.PacketFilter;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class SoftcamTestProgram
|
||||
{
|
||||
public void Run()
|
||||
{
|
||||
SoftcamKeyset softcamKeyset = SoftcamKeyset.GetInstance();
|
||||
softcamKeyset.InitializeFromFile();
|
||||
byte[] bissKey = softcamKeyset.FindBissKey(2, 85);
|
||||
|
||||
BissDescrambleFilter descrambler = new BissDescrambleFilter(bissKey);
|
||||
|
||||
FileInfo inputFile = new FileInfo("C:\\devel\\12380h_filtered.ts");
|
||||
FileStream fileStream = inputFile.OpenRead();
|
||||
byte[] buffer = new byte[188];
|
||||
for (long i = 0; i < fileStream.Length; i += 188)
|
||||
{
|
||||
fileStream.Read(buffer, 0, 188);
|
||||
TsPacket packet = new TsPacket(buffer);
|
||||
descrambler.PassPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
public const int KEY_BITS = 64; //!< DVB CSA-2 control words size in bits.
|
||||
public const int KEY_SIZE = KEY_BITS / 8; //!< DVB CSA-2 control words size in bytes.
|
||||
public const int BLOCK_SIZE = 8;
|
||||
public const int MAX_NBLOCKS = (184 / 8);
|
||||
|
||||
public enum EntropyMode
|
||||
{
|
||||
@ -101,7 +102,7 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
return new Tuple<string, int, int>("DVB-CSA2", BLOCK_SIZE, KEY_SIZE);
|
||||
}
|
||||
|
||||
protected bool SetKeyImpl(byte[] newKey)
|
||||
public bool SetKeyImpl(byte[] newKey)
|
||||
{
|
||||
// Only one possible key size.
|
||||
if (newKey.Length != KEY_SIZE)
|
||||
@ -132,16 +133,134 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static bool EncryptImpl(Span<byte> plain, int plain_length, Span<byte> cipher, int cipher_maxsize, ref int cipher_length)
|
||||
protected bool EncryptImpl(Span<byte> input, int inputLength, Span<byte> output, int size, ref int retsize)
|
||||
{
|
||||
if (size < inputLength)
|
||||
return false;
|
||||
|
||||
size = inputLength;
|
||||
if (retsize != 0)
|
||||
retsize = size;
|
||||
|
||||
if (input != output)
|
||||
{
|
||||
input.CopyTo(output);
|
||||
}
|
||||
|
||||
Span<byte> data = output;
|
||||
int nblocks = size / 8;
|
||||
int rsize = size % 8;
|
||||
|
||||
if (data == null || nblocks > MAX_NBLOCKS || !_init)
|
||||
return false;
|
||||
|
||||
if (size < 8)
|
||||
return true;
|
||||
|
||||
DvbStreamCipher stream_ctx;
|
||||
byte[] iblock = new byte[8];
|
||||
byte[][] ib = new byte[MAX_NBLOCKS + 1][];
|
||||
for (int i = 0; i < ib.Length; i++)
|
||||
ib[i] = new byte[8];
|
||||
byte[] ostream = new byte[8];
|
||||
|
||||
Array.Clear(ib[nblocks]);
|
||||
for (int i = nblocks - 1; i >= 0; i--)
|
||||
{
|
||||
xor_8(iblock, data.Slice(8 * i), ib[i + 1]);
|
||||
_block.Encipher(iblock, ib[i]);
|
||||
}
|
||||
|
||||
memcpy_8(data, ib[0]);
|
||||
|
||||
stream_ctx = _stream;
|
||||
stream_ctx.Cipher(ib[0], ostream);
|
||||
|
||||
for (int i = 1; i < nblocks; i++)
|
||||
{
|
||||
stream_ctx.Cipher(null, ostream);
|
||||
xor_8(data.Slice(8 * i), ib[i], ostream);
|
||||
}
|
||||
|
||||
if (rsize > 0)
|
||||
{
|
||||
stream_ctx.Cipher(null, ostream);
|
||||
for (int i = 0; i < rsize; i++)
|
||||
{
|
||||
data[8 * nblocks + i] ^= ostream[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DecryptImpl(Span<byte> input, int inputLength, Span<byte> output, int size, ref int retsize)
|
||||
{
|
||||
if (size < inputLength)
|
||||
return false;
|
||||
|
||||
size = inputLength;
|
||||
if (retsize != 0)
|
||||
retsize = size;
|
||||
|
||||
if (input != output)
|
||||
input.CopyTo(output);
|
||||
|
||||
Span<byte> data = output;
|
||||
int nblocks = size / 8;
|
||||
int rsize = size % 8;
|
||||
|
||||
if (data == null || nblocks > MAX_NBLOCKS || !_init)
|
||||
return false;
|
||||
|
||||
if (size < 8)
|
||||
return true;
|
||||
|
||||
DvbStreamCipher stream_ctx;
|
||||
byte[] ostream = new byte[8];
|
||||
byte[] ib = new byte[8];
|
||||
byte[] oblock = new byte[8];
|
||||
|
||||
stream_ctx = _stream;
|
||||
stream_ctx.Cipher(data, ib);
|
||||
|
||||
for (int i = 1; i < nblocks; i++)
|
||||
{
|
||||
_block.Decipher(ib, oblock);
|
||||
stream_ctx.Cipher(null, ostream);
|
||||
xor_8(ib, data.Slice(8 * i), ostream);
|
||||
xor_8(data.Slice(8 * (i - 1)), ib, oblock);
|
||||
}
|
||||
|
||||
_block.Decipher(ib, data.Slice(8 * (nblocks - 1)));
|
||||
|
||||
if (rsize > 0)
|
||||
{
|
||||
stream_ctx.Cipher(null, ostream);
|
||||
for (int i = 0; i < rsize; i++)
|
||||
{
|
||||
data[8 * nblocks + 1] ^= ostream[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void xor_8(Span<byte> iblock, byte[] slice, byte[] ostream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected bool DecryptImpl(Span<byte> cipher, int cipher_length, Span<byte> plain, int plain_maxsize, ref int plain_length)
|
||||
private void memcpy_8(Span<byte> data, byte[] bytes)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void xor_8(byte[] res, Span<byte> a, byte[] b)
|
||||
{
|
||||
res[0] = (byte)(a[0] ^ b[0]);
|
||||
}
|
||||
|
||||
private class DvbBlockCipher
|
||||
{
|
||||
private readonly byte[] key_perm = {
|
||||
@ -235,6 +354,8 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
private int[] _kk; //57 items
|
||||
public void Init(Span<byte> key)
|
||||
{
|
||||
_kk = new int[57];
|
||||
|
||||
int i, j, k;
|
||||
int[] bit = new int[64];
|
||||
int[] newbit = new int[64];
|
||||
@ -394,6 +515,9 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
|
||||
public void Init(Span<byte> key)
|
||||
{
|
||||
A = new int[11];
|
||||
B = new int[11];
|
||||
|
||||
A[1] = (key[0] >> 4) & 0x0F;
|
||||
A[2] = (key[0] >> 0) & 0x0F;
|
||||
A[3] = (key[1] >> 4) & 0x0F;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user