public async Task <byte[]> GenerateCKC(byte[] spc, object info = null) { var buffer = new ReadOnlyMemory <byte>(spc); // We try to read SPC message. SPCMessage request = null; try { request = new SPCMessage(buffer); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_0001", "Unable to parse SPC. See 'innerException' for more information.", ex); } FPProvider provider = null; try { provider = this.Providers.First(p => Enumerable.SequenceEqual(p.Hash, request.ProviderHash)); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidProviderException("EXC_0002", "Received SPCMessage contains a unregistered FairPlay provider.", ex); } CKCMessage response = null; try { response = await GenerateCKC(provider, request, info); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_0003", "Unable to process SPC. See 'innerException' for more information.", ex); } return(response.Binary); }
public IContentKey FetchKey(byte[] spc, byte[] ckc) { var spcBuffer = new ReadOnlyMemory <byte>(spc); var ckcBuffer = new ReadOnlyMemory <byte>(ckc); // We try to read SPC message. SPCMessage request = null; try { request = new SPCMessage(spcBuffer); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2001", "Unable to parse SPC. See 'innerException' for more information.", ex); } CKCMessage response = null; try { response = new CKCMessage(ckcBuffer); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2002", "Unable to parse CKC. See 'innerException' for more information.", ex); } FPProvider provider = null; try { provider = this.Providers.First(p => Enumerable.SequenceEqual(p.Hash, request.ProviderHash)); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidProviderException("EXC_2003", "Received SPCMessage contains a unregistered FairPlay provider.", ex); } return(FetchKey(provider, request, response)); }
private byte[] FetchId(FPProvider provider, SPCMessage spc, CKCMessage ckc) { IEnumerable <TLLVSlab> spcSlabs = null; try { spcSlabs = TLLVSlab.FromBuffer(spc.UnscrambledPayload(provider.RSAKey)); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2030", "Unable to process inspection. See 'innerException' for more information.", ex); } AssetPayload AssetPayload = null; try { AssetPayload = spcSlabs.First(p => p.Tag.Same(TLLVTag.Id.Asset)).Payload <AssetPayload>(); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2031", "Unable to process inspection. See 'innerException' for more information.", ex); } byte[] ID = null; try { ID = AssetPayload.Identifier; } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2032", "Unable to process inspection. See 'innerException' for more information.", ex); } return(ID); }
public static byte[] UnscrambledPayload(this CKCMessage message, byte[] key) { ArgumentThrow.IfNull(message, $"Invalid {typeof(CKCMessage).Name} to unscramble. Message can not be null.", nameof(message)); ArgumentThrow.IfLengthNot(key, 16, "Invalid key to unscramble. Key buffer should be 16 bytes.", nameof(key)); using (var aes = Aes.Create()) { aes.IV = message.IV; aes.Key = key; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.None; using (var decryptor = aes.CreateDecryptor()) using (var memoryStream = new MemoryStream()) using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write)) { cryptoStream.Write(message.ContentPayload); return(memoryStream.ToArray()); } } }
private IContentKey FetchKey(FPProvider provider, SPCMessage spc, CKCMessage ckc) { IEnumerable <TLLVSlab> spcSlabs = null; try { spcSlabs = TLLVSlab.FromBuffer(spc.UnscrambledPayload(provider.RSAKey)); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2010", "Unable to process inspection. See 'innerException' for more information.", ex); } byte[] DASk = null; try { DASk = new DFunction(provider.ASKey).DeriveBytes(spcSlabs.First(p => p.Tag.Same(TLLVTag.Id.R2)).Payload <R2Payload>().R2); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2011", "Unable to process inspection. See 'innerException' for more information.", ex); } SKR1Payload SessionRandom1Payload = null; try { SessionRandom1Payload = spcSlabs.First(p => p.Tag.Same(TLLVTag.Id.SKR1)).Payload <SKR1Payload>(); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2012", "Unable to process inspection. See 'innerException' for more information.", ex); } SKR1IntegrityPayload SessionRandom1IntegrityPayload = null; try { SessionRandom1IntegrityPayload = spcSlabs.First(p => p.Tag.Same(TLLVTag.Id.SKR1Integrity)).Payload <SKR1IntegrityPayload>(); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2013", "Unable to process inspection. See 'innerException' for more information.", ex); } SKR1Parcel SessionRandom1Parcel = null; try { SessionRandom1Parcel = new SKR1Parcel(new ReadOnlyMemory <byte>(SessionRandom1Payload.UnscrambledParcel(DASk))); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2014", "Unable to process inspection. See 'innerException' for more information.", ex); } if (Enumerable.SequenceEqual(SessionRandom1Parcel.Integrity, SessionRandom1IntegrityPayload.Integrity) == false) { throw new FPContextIntegrityViolatedException("EXC_0034", "Unable to process SPC. SPC integrity violated."); } byte[] seed = null; try { seed = spcSlabs.First(s => s.Tag.Same(TLLVTag.Id.AR)).Payload <ARPayload>().Seed; } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2015", "Unable to process inspection. See 'innerException' for more information.", ex); } byte[] random = null; try { random = SessionRandom1Parcel.R1; } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2016", "Unable to process inspection. See 'innerException' for more information.", ex); } byte[] key = null; try { using (var sha = SHA1.Create()) using (var aes = Aes.Create()) { // aes.IV = new byte[16]; aes.Key = sha.ComputeHash(random).Take(16).ToArray(); aes.Mode = CipherMode.ECB; aes.Padding = PaddingMode.None; using (var encryptor = aes.CreateEncryptor()) using (var memoryStream = new MemoryStream()) using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(seed); key = memoryStream.ToArray(); } } } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2017", "Unable to process inspection. See 'innerException' for more information.", ex); } IEnumerable <TLLVSlab> ckcSlabs = null; try { ckcSlabs = TLLVSlab.FromBuffer(ckc.UnscrambledPayload(key)); } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2018", "Unable to process inspection. See 'innerException' for more information.", ex); } byte[] SK = null; try { SK = SessionRandom1Parcel.SK; } catch (FPException) { throw; } catch (Exception ex) { throw new FPInvalidContextException("EXC_2019", "Unable to process inspection. See 'innerException' for more information.", ex); } return(FetchKey(spcSlabs, ckcSlabs, SK)); }