remove unused code, fix ps1 multi-disc gen `__sce_ebootpbp` failed.

This commit is contained in:
SquallATF 2023-04-30 08:34:40 +08:00
parent 299b042dd9
commit c96b43031a
23 changed files with 1625 additions and 3861 deletions

View File

@ -369,7 +369,7 @@ namespace PbpResign
AMCTRL.sceDrmBBCipherInit(out var ckey, 1, 2, npHdr.HeaderKey, vkey, 0);
AMCTRL.sceDrmBBCipherUpdate(ref ckey, psarBuff[0x40..], 0x60);
AMCTRL.sceDrmBBCipherFinal(ref ckey);
npHdr = Utils.AsRef<NpUmdImgHdr>(psarBuff);
npHdr = MemoryMarshal.AsRef<NpUmdImgHdr>(psarBuff);
var lbasize = npHdr.Body.LbaEnd - npHdr.Body.LbaStart + 1;
if (npHdr.BlockBasis == 0)
@ -1059,7 +1059,7 @@ namespace PbpResign
return false;
}
ref var npHdr = ref Utils.AsRef<NpUmdImgHdr>(psarBuff);
ref var npHdr = ref MemoryMarshal.AsRef<NpUmdImgHdr>(psarBuff);
if (npHdr.Magic0 == 0x4d55504e && npHdr.Magic1 == 0x474d4944)
{
@ -1189,7 +1189,7 @@ namespace PbpResign
return;
}
var pbpHdr = Utils.AsRef<PbpHeader>(hdr);
var pbpHdr = MemoryMarshal.AsRef<PbpHeader>(hdr);
if (pbpHdr.Sig != 0x50425000)
{
Console.WriteLine("Wrong pbp sig");

View File

@ -67,7 +67,7 @@ namespace PspCrypto
static int Kirk4(Span<byte> buf, int size, int type)
{
int retv;
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
hdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
hdr.keyseed = type;
hdr.data_size = size;
@ -83,7 +83,7 @@ namespace PspCrypto
static int Kirk5(Span<byte> buf, int size)
{
int retv;
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
hdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
hdr.keyseed = 0x0100;
hdr.data_size = size;
@ -99,7 +99,7 @@ namespace PspCrypto
static int Kirk7(Span<byte> buf, int size, int type)
{
int retv;
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
hdr.mode = KIRKEngine.KIRK_MODE_DECRYPT_CBC;
hdr.keyseed = type;
hdr.data_size = size;
@ -115,7 +115,7 @@ namespace PspCrypto
static int Kirk8(Span<byte> buf, int size)
{
int retv;
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
hdr.mode = KIRKEngine.KIRK_MODE_DECRYPT_CBC;
hdr.keyseed = 0x0100;
hdr.data_size = size;
@ -553,7 +553,7 @@ namespace PspCrypto
public static int sceDrmBBMacFinal2(Span<byte> mkey, ReadOnlySpan<byte> hash, ReadOnlySpan<byte> vkey)
{
int i, retv, type;
int retv, type;
byte[] tmp = new byte[16];
int kbuf;
ref MAC_KEY macKey = ref MemoryMarshal.AsRef<MAC_KEY>(mkey);

View File

@ -35,7 +35,7 @@ namespace PspCrypto
data[..dataSize].CopyTo(pgdData[dataOffset..]);
ref var pgdHdr = ref Utils.AsRef<PgdHeader>(pgdData);
ref var pgdHdr = ref MemoryMarshal.AsRef<PgdHeader>(pgdData);
pgdHdr.Magic = 0x44475000;
pgdHdr.KeyIndex = keyIndex;
pgdHdr.DrmType = drmType;
@ -81,7 +81,7 @@ namespace PspCrypto
}
// Set the decryption parameters in the decrypted header.
ref var pgdDesc = ref Utils.AsRef<PgdDesc>(pgdHdr.PgdDesc);
ref var pgdDesc = ref MemoryMarshal.AsRef<PgdDesc>(pgdHdr.PgdDesc);
pgdDesc.DataSize = dataSize;
pgdDesc.BlockSize = blockSize;
pgdDesc.DataOffset = dataOffset;

View File

@ -169,7 +169,7 @@ namespace PspCrypto
{
throw new ArgumentException("stream too small", nameof(stream));
}
var header = Utils.AsRef<PgdHeader>(hdr);
var header = MemoryMarshal.AsRef<PgdHeader>(hdr);
_keyIndex = header.KeyIndex;
if (_keyIndex == 1)
{
@ -234,7 +234,7 @@ namespace PspCrypto
throw new IOException("Wrong MAC 0x80");
}
if (!Utils.isEmpty(_versionKey, 0x10))
if (!Utils.IsEmpty(_versionKey, 0x10))
{
ret = CheckBBMac(hdr, 0x70, _versionKey, header.Hash70, macType);
}
@ -253,7 +253,7 @@ namespace PspCrypto
{
throw new IOException($"Error 0x{ret:X8}");
}
var desc = Utils.AsRef<PgdDesc>(header.PgdDesc);
var desc = MemoryMarshal.AsRef<PgdDesc>(header.PgdDesc);
if (desc.Version != 0)
{
throw new IOException($"Error 0x{8051020:X8}");

View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PspCrypto.Security.Cryptography;
using System;
using System.Security.Cryptography;
using System.Text;
using PspCrypto.Security.Cryptography;
namespace PspCrypto
{
@ -68,17 +65,6 @@ namespace PspCrypto
return new ECDsaManaged(par, ebootPbp, type);
}
public static ECDsa CreateNet(ECCurve curve, byte[] privateKey, byte[] pubx, byte[] puby)
{
var par = new ECParameters
{
Curve = curve,
D = privateKey,
Q = { X = pubx, Y = puby }
};
return ECDsa.Create(par);
}
public static void SignNpImageHeader(Span<byte> npHdr)
{
var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
@ -103,8 +89,8 @@ namespace PspCrypto
using var ecdsa = Create(curve, KeyVault.EdatPirv, KeyVault.EdatPx, KeyVault.EdatPy);
var sig = ecdsa.SignData(edat[..0x58].ToArray(), HashAlgorithmName.SHA1);
sig.CopyTo(edat[0x58..]);
}
}
public static void SignParamSfo(ReadOnlySpan<byte> param, Span<byte> sig)
{
var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,

View File

@ -1,65 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using ECDsaTest.SafeHandles;
internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumDestroy")]
internal static extern void BigNumDestroy(IntPtr a);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumToBinary")]
private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte* to);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetBigNumBytes")]
private static extern int GetBigNumBytes(SafeBignumHandle a);
internal static byte[] ExtractBignum(IntPtr bignum, int targetSize)
{
// Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle
// to ensure that we don't destroy the key after extraction.
using (SafeBignumHandle handle = new SafeBignumHandle(bignum, ownsHandle: false))
{
return ExtractBignum(handle, targetSize);
}
}
private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSize)
{
if (bignum == null || bignum.IsInvalid)
{
return null;
}
int compactSize = GetBigNumBytes(bignum);
if (targetSize < compactSize)
{
targetSize = compactSize;
}
// OpenSSL BIGNUM values do not record leading zeroes.
// Windows Crypt32 does.
//
// Since RSACryptoServiceProvider already checks that RSAParameters.DP.Length is
// exactly half of RSAParameters.Modulus.Length, we need to left-pad (big-endian)
// the array with zeroes.
int offset = targetSize - compactSize;
byte[] buf = new byte[targetSize];
fixed (byte* to = buf)
{
byte* start = to + offset;
BigNumToBinary(bignum, start);
}
return buf;
}
}
}

View File

@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrClearError")]
internal static extern ulong ErrClearError();
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrGetErrorAlloc")]
private static extern ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrErrorStringN")]
private static extern unsafe void ErrErrorStringN(ulong e, byte* buf, int len);
private static unsafe string ErrErrorStringN(ulong error)
{
var buffer = new byte[1024];
fixed (byte* buf = &buffer[0])
{
ErrErrorStringN(error, buf, buffer.Length);
return Marshal.PtrToStringAnsi((IntPtr)buf);
}
}
internal static Exception CreateOpenSslCryptographicException()
{
// The Windows cryptography library reports error codes through
// Marshal.GetLastWin32Error, which has a single value when the
// function exits, last writer wins.
//
// OpenSSL maintains an error queue. Calls to ERR_get_error read
// values out of the queue in the order that ERR_set_error wrote
// them. Nothing enforces that a single call into an OpenSSL
// function will guarantee at-most one error being set.
//
// In order to maintain parity in how error flows look between the
// Windows code and the OpenSSL-calling code, drain the queue
// whenever an Exception is desired, and report the exception
// related to the last value in the queue.
bool isAllocFailure;
ulong error = ErrGetErrorAlloc(out isAllocFailure);
ulong lastRead = error;
bool lastIsAllocFailure = isAllocFailure;
// 0 (there's no named constant) is only returned when the calls
// to ERR_get_error exceed the calls to ERR_set_error.
while (lastRead != 0)
{
error = lastRead;
isAllocFailure = lastIsAllocFailure;
lastRead = ErrGetErrorAlloc(out lastIsAllocFailure);
}
// If we're in an error flow which results in an Exception, but
// no calls to ERR_set_error were made, throw the unadorned
// CryptographicException.
if (error == 0)
{
return new CryptographicException();
}
if (isAllocFailure)
{
return new OutOfMemoryException();
}
// Even though ErrGetError returns ulong (C++ unsigned long), we
// really only expect error codes in the UInt32 range
Debug.Assert(error <= uint.MaxValue, "ErrGetError should only return error codes in the UInt32 range.");
// If there was an error code, and it wasn't something handled specially,
// use the OpenSSL error string as the message to a CryptographicException.
return new OpenSslCryptographicException(unchecked((int)error), ErrErrorStringN(error));
}
private sealed class OpenSslCryptographicException : CryptographicException
{
internal OpenSslCryptographicException(int errorCode, string message)
: base(message)
{
HResult = errorCode;
}
}
}
}

View File

@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using ECDsaTest.SafeHandles;
internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByExplicitParameters")]
internal static extern SafeEcKeyHandle EcKeyCreateByExplicitParameters(
ECCurve.ECCurveType curveType,
byte[] qx, int qxLength,
byte[] qy, int qyLength,
byte[] d, int dLength,
byte[] p, int pLength,
byte[] a, int aLength,
byte[] b, int bLength,
byte[] gx, int gxLength,
byte[] gy, int gyLength,
byte[] order, int nLength,
byte[] cofactor, int cofactorLength,
byte[] seed, int seedLength);
internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve)
{
byte[] p;
if (curve.IsPrime)
{
p = curve.Prime;
}
else if (curve.IsCharacteristic2)
{
p = curve.Polynomial;
}
else
{
throw new PlatformNotSupportedException(string.Format("The specified curve '{0}' or its parameters are not valid for this platform.", curve.CurveType.ToString()));
}
SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByExplicitParameters(
curve.CurveType,
null, 0,
null, 0,
null, 0,
p, p.Length,
curve.A, curve.A.Length,
curve.B, curve.B.Length,
curve.G.X, curve.G.X.Length,
curve.G.Y, curve.G.Y.Length,
curve.Order, curve.Order.Length,
curve.Cofactor, curve.Cofactor.Length,
curve.Seed, curve.Seed == null ? 0 : curve.Seed.Length);
if (key == null || key.IsInvalid)
{
if (key != null)
key.Dispose();
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
// EcKeyCreateByExplicitParameters may have polluted the error queue, but key was good in the end.
// Clean up the error queue.
Interop.Crypto.ErrClearError();
return key;
}
}
}

View File

@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using ECDsaTest;
using ECDsaTest.SafeHandles;
internal static partial class Interop
{
internal static partial class Crypto
{
internal static bool EcDsaSignEx(ReadOnlySpan<byte> dgst, Span<byte> sig, [In, Out] ref int siglen,
ReadOnlySpan<byte> kinv, ReadOnlySpan<byte> rp, SafeEcKeyHandle ecKey) => EcDsaSignEx(
ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sig), ref siglen,
ref MemoryMarshal.GetReference(kinv), kinv.Length, ref MemoryMarshal.GetReference(rp), rp.Length, ecKey);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSignEx")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EcDsaSignEx(ref byte dgst, int dlen, ref byte sig, [In, Out] ref int siglen,
ref byte kinv, int kinvlen, ref byte rp, int rplen, SafeEcKeyHandle ecKey);
// returns the maximum length of a DER encoded ECDSA signature created with this key.
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSize")]
private static extern int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey);
internal static int EcDsaSize(SafeEcKeyHandle ecKey)
{
int ret = CryptoNative_EcDsaSize(ecKey);
if (ret == 0)
{
throw CreateOpenSslCryptographicException();
}
return ret;
}
internal static PspParameter EcPspParameter(SafeEcKeyHandle key, ReadOnlySpan<byte> sha256, int len)
{
SafeBignumHandle kinv_bn, rp_bn;
int kinvlen, rplen;
bool refAdded = false;
try
{
key.DangerousAddRef(ref refAdded);
var ret = EcPspParameter(key, ref MemoryMarshal.GetReference(sha256), len, out kinv_bn, out kinvlen,
out rp_bn, out rplen);
if (!ret)
{
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
using (kinv_bn)
using (rp_bn)
{
var par = new PspParameter
{
Kinv = Crypto.ExtractBignum(kinv_bn, kinvlen),
Rp = Crypto.ExtractBignum(rp_bn, rplen)
};
return par;
}
}
finally
{
if (refAdded)
key.DangerousRelease();
}
}
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcPspParameter")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EcPspParameter(SafeEcKeyHandle ecKey, ref byte sha256, int len, out SafeBignumHandle kinv,
out int kinvlen, out SafeBignumHandle rp, out int rplen);
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyDestroy")]
internal static extern void EcKeyDestroy(IntPtr a);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyUpRef")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EcKeyUpRef(IntPtr r);
}
}

View File

@ -762,7 +762,7 @@ namespace PspCrypto
static int kirk_CMD0(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size, bool generate_trash)
{
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(outbuff);
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(outbuff);
// header_keys keys = Utils.AsRef<header_keys>(outbuff);
int chk_size;
Aes k1;
@ -817,7 +817,7 @@ namespace PspCrypto
static int kirk_CMD1(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
{
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(inbuff);
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(inbuff);
// header_keys keys; //0-15 AES key, 16-31 CMAC key
Aes k1;
@ -831,7 +831,7 @@ namespace PspCrypto
if (header.ecdsa_hash == 1)
{
KIRK_CMD1_ECDSA_HEADER eheader = Utils.AsRef<KIRK_CMD1_ECDSA_HEADER>(inbuff);
KIRK_CMD1_ECDSA_HEADER eheader = MemoryMarshal.AsRef<KIRK_CMD1_ECDSA_HEADER>(inbuff);
var curve = ECDsaHelper.SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b1, KeyVault.ec_N1, KeyVault.Gx1,
KeyVault.Gy1);
unsafe
@ -867,7 +867,7 @@ namespace PspCrypto
static int kirk_CMD4(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
{
KIRK_AES128CBC_HEADER header = Utils.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
KIRK_AES128CBC_HEADER header = MemoryMarshal.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
byte[] key;
Aes aes;
@ -892,7 +892,7 @@ namespace PspCrypto
static int kirk_CMD7(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
{
KIRK_AES128CBC_HEADER header = Utils.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
KIRK_AES128CBC_HEADER header = MemoryMarshal.AsRef<KIRK_AES128CBC_HEADER>(inbuff);
byte[] key;
Aes aes;
@ -915,7 +915,7 @@ namespace PspCrypto
static int kirk_CMD10(ReadOnlySpan<byte> inbuff, int insize)
{
KIRK_CMD1_HEADER header = Utils.AsRef<KIRK_CMD1_HEADER>(inbuff);
KIRK_CMD1_HEADER header = MemoryMarshal.AsRef<KIRK_CMD1_HEADER>(inbuff);
// header_keys keys; //0-15 AES key, 16-31 CMAC key
Span<byte> cmac_header_hash = stackalloc byte[16];
Span<byte> cmac_data_hash = stackalloc byte[16];
@ -951,7 +951,7 @@ namespace PspCrypto
static int kirk_CMD11(Span<byte> outbuff, ReadOnlySpan<byte> inbuff, int size)
{
KIRK_SHA1_HEADER header = Utils.AsRef<KIRK_SHA1_HEADER>(inbuff);
KIRK_SHA1_HEADER header = MemoryMarshal.AsRef<KIRK_SHA1_HEADER>(inbuff);
if (!is_kirk_initialized) return KIRK_NOT_INITIALIZED;
if (header.data_size == 0 || size == 0) return KIRK_DATA_SIZE_ZERO;
@ -1044,7 +1044,7 @@ namespace PspCrypto
static int kirk_CMD16(Span<byte> outbuff, int outsize, ReadOnlySpan<byte> inbuff, int insize)
{
byte[] dec_private = new byte[0x20];
KIRK_CMD16_BUFFER signbuf = Utils.AsRef<KIRK_CMD16_BUFFER>(inbuff);
KIRK_CMD16_BUFFER signbuf = MemoryMarshal.AsRef<KIRK_CMD16_BUFFER>(inbuff);
//ECDSA_SIG sig = BufferToStruct<ECDSA_SIG>(outbuff);
if (insize != 0x34) return KIRK_INVALID_SIZE;
@ -1071,7 +1071,7 @@ namespace PspCrypto
static int kirk_CMD17(ReadOnlySpan<byte> inbuff, int insize)
{
KIRK_CMD17_BUFFER sig = Utils.AsRef<KIRK_CMD17_BUFFER>(inbuff);
KIRK_CMD17_BUFFER sig = MemoryMarshal.AsRef<KIRK_CMD17_BUFFER>(inbuff);
if (insize != 0x64) return KIRK_INVALID_SIZE;

View File

@ -1,38 +0,0 @@
using System;
using System.Security.Cryptography;
namespace PspCrypto
{
public class RijndaelMod : Aes
{
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
{
return CreateTransform(rgbKey, encrypting: false);
}
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
{
return CreateTransform(rgbKey, encrypting: true);
}
public override void GenerateIV()
{
}
public override void GenerateKey()
{
byte[] key = new byte[KeySize / BitsPerByte];
RandomNumberGenerator.Fill(key);
Key = key;
}
private ICryptoTransform CreateTransform(byte[] rgbKey, bool encrypting)
{
if (rgbKey == null)
throw new ArgumentNullException(nameof(rgbKey));
return new RijndaelModTransform(rgbKey, BlockSizeValue, encrypting);
}
private const int BitsPerByte = 8;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,272 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using PspCrypto.Security.Cryptography;
namespace PspCrypto
{
public class SHA224Managed_OLD : SHA224
{
private const int BLOCK_SIZE_BYTES = 64;
private uint[] _H;
private ulong count;
private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
private uint[] buff;
public SHA224Managed_OLD()
{
_H = new uint[8];
_ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
buff = new uint[64];
Initialize();
}
private uint Ch(uint u, uint v, uint w)
{
return (u & v) ^ (~u & w);
}
private uint Maj(uint u, uint v, uint w)
{
return (u & v) ^ (u & w) ^ (v & w);
}
private uint Ro0(uint x)
{
return ((x >> 7) | (x << 25))
^ ((x >> 18) | (x << 14))
^ (x >> 3);
}
private uint Ro1(uint x)
{
return ((x >> 17) | (x << 15))
^ ((x >> 19) | (x << 13))
^ (x >> 10);
}
private uint Sig0(uint x)
{
return ((x >> 2) | (x << 30))
^ ((x >> 13) | (x << 19))
^ ((x >> 22) | (x << 10));
}
private uint Sig1(uint x)
{
return ((x >> 6) | (x << 26))
^ ((x >> 11) | (x << 21))
^ ((x >> 25) | (x << 7));
}
public void HashData2(ReadOnlySpan<byte> data, Span<byte> hash)
{
var tmp = ComputeHash(data.ToArray());
tmp.CopyTo(hash);
}
protected override void HashCore(byte[] rgb, int start, int size)
{
int i;
State = 1;
if (_ProcessingBufferCount != 0)
{
if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount))
{
System.Buffer.BlockCopy(rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
_ProcessingBufferCount += size;
return;
}
else
{
i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
System.Buffer.BlockCopy(rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
ProcessBlock(_ProcessingBuffer, 0);
_ProcessingBufferCount = 0;
start += i;
size -= i;
}
}
for (i = 0; i < size - size % BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES)
{
ProcessBlock(rgb, start + i);
}
if (size % BLOCK_SIZE_BYTES != 0)
{
System.Buffer.BlockCopy(rgb, size - size % BLOCK_SIZE_BYTES + start, _ProcessingBuffer, 0, size % BLOCK_SIZE_BYTES);
_ProcessingBufferCount = size % BLOCK_SIZE_BYTES;
}
}
protected override byte[] HashFinal()
{
byte[] hash = new byte[28];
int i, j;
ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
for (i = 0; i < 7; i++)
{
for (j = 0; j < 4; j++)
{
hash[i * 4 + j] = (byte)(_H[i] >> (24 - j * 8));
}
}
State = 0;
return hash;
}
public override void Initialize()
{
count = 0;
_ProcessingBufferCount = 0;
_H[0] = 0xC1059ED8;
_H[1] = 0x367CD507;
_H[2] = 0x3070DD17;
_H[3] = 0xF70E5939;
_H[4] = 0xFFC00B31;
_H[5] = 0x68581511;
_H[6] = 0x64F98FA7;
_H[7] = 0xBEFA4FA4;
}
private void ProcessBlock(byte[] inputBuffer, int inputOffset)
{
uint a, b, c, d, e, f, g, h;
uint t1, t2;
int i;
uint[] K1 = _K1;
uint[] buff = this.buff;
count += BLOCK_SIZE_BYTES;
for (i = 0; i < 16; i++)
{
buff[i] = (uint)(((inputBuffer[inputOffset + 4 * i]) << 24)
| ((inputBuffer[inputOffset + 4 * i + 1]) << 16)
| ((inputBuffer[inputOffset + 4 * i + 2]) << 8)
| ((inputBuffer[inputOffset + 4 * i + 3])));
}
for (i = 16; i < 64; i++)
{
t1 = buff[i - 15];
t1 = (((t1 >> 7) | (t1 << 25)) ^ ((t1 >> 18) | (t1 << 14)) ^ (t1 >> 3));
t2 = buff[i - 2];
t2 = (((t2 >> 17) | (t2 << 15)) ^ ((t2 >> 19) | (t2 << 13)) ^ (t2 >> 10));
buff[i] = t2 + buff[i - 7] + t1 + buff[i - 16];
}
a = _H[0];
b = _H[1];
c = _H[2];
d = _H[3];
e = _H[4];
f = _H[5];
g = _H[6];
h = _H[7];
for (i = 0; i < 64; i++)
{
t1 = h + (((e >> 6) | (e << 26)) ^ ((e >> 11) | (e << 21)) ^ ((e >> 25) | (e << 7))) + ((e & f) ^ (~e & g)) + K1[i] + buff[i];
t2 = (((a >> 2) | (a << 30)) ^ ((a >> 13) | (a << 19)) ^ ((a >> 22) | (a << 10)));
t2 = t2 + ((a & b) ^ (a & c) ^ (b & c));
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
_H[0] += a;
_H[1] += b;
_H[2] += c;
_H[3] += d;
_H[4] += e;
_H[5] += f;
_H[6] += g;
_H[7] += h;
}
private void ProcessFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
{
ulong total = count + (ulong)inputCount;
int paddingSize = (56 - (int)(total % BLOCK_SIZE_BYTES));
if (paddingSize < 1)
paddingSize += BLOCK_SIZE_BYTES;
byte[] fooBuffer = new byte[inputCount + paddingSize + 8];
for (int i = 0; i < inputCount; i++)
{
fooBuffer[i] = inputBuffer[i + inputOffset];
}
fooBuffer[inputCount] = 0x80;
for (int i = inputCount + 1; i < inputCount + paddingSize; i++)
{
fooBuffer[i] = 0x00;
}
// I deal in bytes. The algorithm deals in bits.
ulong size = total << 3;
AddLength(size, fooBuffer, inputCount + paddingSize);
ProcessBlock(fooBuffer, 0);
if (inputCount + paddingSize + 8 == 128)
{
ProcessBlock(fooBuffer, 64);
}
}
internal void AddLength(ulong length, byte[] buffer, int position)
{
buffer[position++] = (byte)(length >> 56);
buffer[position++] = (byte)(length >> 48);
buffer[position++] = (byte)(length >> 40);
buffer[position++] = (byte)(length >> 32);
buffer[position++] = (byte)(length >> 24);
buffer[position++] = (byte)(length >> 16);
buffer[position++] = (byte)(length >> 8);
buffer[position] = (byte)(length);
}
// SHA-224/256 Constants
// Represent the first 32 bits of the fractional parts of the
// cube roots of the first sixty-four prime numbers
public readonly static uint[] _K1 = {
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
};
}
}

View File

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace ECDsaTest.SafeHandles
{
internal sealed class SafeBignumHandle : SafeHandle
{
private SafeBignumHandle() :
base(IntPtr.Zero, ownsHandle: true)
{
}
internal SafeBignumHandle(IntPtr handle, bool ownsHandle)
: base(handle, ownsHandle)
{
}
protected override bool ReleaseHandle()
{
Interop.Crypto.BigNumDestroy(handle);
SetHandle(IntPtr.Zero);
return true;
}
public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}
}
}

View File

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ECDsaTest.SafeHandles
{
internal sealed class SafeEcKeyHandle : SafeHandle
{
private SafeEcKeyHandle() :
base(IntPtr.Zero, ownsHandle: true)
{
}
protected override bool ReleaseHandle()
{
Interop.Crypto.EcKeyDestroy(handle);
SetHandle(IntPtr.Zero);
return true;
}
public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}
internal static SafeEcKeyHandle DuplicateHandle(IntPtr handle)
{
Debug.Assert(handle != IntPtr.Zero);
// Reliability: Allocate the SafeHandle before calling EC_KEY_up_ref so
// that we don't lose a tracked reference in low-memory situations.
SafeEcKeyHandle safeHandle = new SafeEcKeyHandle();
if (!Interop.Crypto.EcKeyUpRef(handle))
{
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
safeHandle.SetHandle(handle);
return safeHandle;
}
}
}

View File

@ -438,7 +438,7 @@ namespace PspCrypto
static int Kirk8(Span<byte> buf, int size, int use_polling)
{
int retv;
ref var hdr = ref Utils.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
ref var hdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(buf);
hdr.mode = KIRKEngine.KIRK_MODE_DECRYPT_CBC;
hdr.keyseed = 0x0100;
hdr.data_size = size;

File diff suppressed because it is too large Load Diff

View File

@ -1,222 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace System.Formats.Asn1
{
internal ref struct AsnValueReader
{
private static readonly byte[] s_singleByte = new byte[1];
private ReadOnlySpan<byte> _span;
private readonly AsnEncodingRules _ruleSet;
internal AsnValueReader(ReadOnlySpan<byte> span, AsnEncodingRules ruleSet)
{
_span = span;
_ruleSet = ruleSet;
}
internal bool HasData => !_span.IsEmpty;
internal void ThrowIfNotEmpty()
{
if (!_span.IsEmpty)
{
new AsnReader(s_singleByte, _ruleSet).ThrowIfNotEmpty();
}
}
internal Asn1Tag PeekTag()
{
return Asn1Tag.Decode(_span, out _);
}
internal ReadOnlySpan<byte> PeekContentBytes()
{
AsnDecoder.ReadEncodedValue(
_span,
_ruleSet,
out int contentOffset,
out int contentLength,
out _);
return _span.Slice(contentOffset, contentLength);
}
internal ReadOnlySpan<byte> PeekEncodedValue()
{
AsnDecoder.ReadEncodedValue(_span, _ruleSet, out _, out _, out int consumed);
return _span.Slice(0, consumed);
}
internal ReadOnlySpan<byte> ReadEncodedValue()
{
ReadOnlySpan<byte> value = PeekEncodedValue();
_span = _span.Slice(value.Length);
return value;
}
internal bool ReadBoolean(Asn1Tag? expectedTag = default)
{
bool ret = AsnDecoder.ReadBoolean(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal BigInteger ReadInteger(Asn1Tag? expectedTag = default)
{
BigInteger ret = AsnDecoder.ReadInteger(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal bool TryReadInt32(out int value, Asn1Tag? expectedTag = default)
{
bool ret = AsnDecoder.TryReadInt32(_span, _ruleSet, out value, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal ReadOnlySpan<byte> ReadIntegerBytes(Asn1Tag? expectedTag = default)
{
ReadOnlySpan<byte> ret = AsnDecoder.ReadIntegerBytes(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal bool TryReadPrimitiveBitString(
out int unusedBitCount,
out ReadOnlySpan<byte> value,
Asn1Tag? expectedTag = default)
{
bool ret = AsnDecoder.TryReadPrimitiveBitString(
_span,
_ruleSet,
out unusedBitCount,
out value,
out int consumed,
expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal byte[] ReadBitString(out int unusedBitCount, Asn1Tag? expectedTag = default)
{
byte[] ret = AsnDecoder.ReadBitString(
_span,
_ruleSet,
out unusedBitCount,
out int consumed,
expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal TFlagsEnum ReadNamedBitListValue<TFlagsEnum>(Asn1Tag? expectedTag = default) where TFlagsEnum : Enum
{
TFlagsEnum ret = AsnDecoder.ReadNamedBitListValue<TFlagsEnum>(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal bool TryReadPrimitiveOctetString(
out ReadOnlySpan<byte> value,
Asn1Tag? expectedTag = default)
{
bool ret = AsnDecoder.TryReadPrimitiveOctetString(
_span,
_ruleSet,
out value,
out int consumed,
expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal byte[] ReadOctetString(Asn1Tag? expectedTag = default)
{
byte[] ret = AsnDecoder.ReadOctetString(
_span,
_ruleSet,
out int consumed,
expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal string ReadObjectIdentifier(Asn1Tag? expectedTag = default)
{
string ret = AsnDecoder.ReadObjectIdentifier(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal AsnValueReader ReadSequence(Asn1Tag? expectedTag = default)
{
AsnDecoder.ReadSequence(
_span,
_ruleSet,
out int contentOffset,
out int contentLength,
out int bytesConsumed,
expectedTag);
ReadOnlySpan<byte> content = _span.Slice(contentOffset, contentLength);
_span = _span.Slice(bytesConsumed);
return new AsnValueReader(content, _ruleSet);
}
internal AsnValueReader ReadSetOf(Asn1Tag? expectedTag = default, bool skipSortOrderValidation = false)
{
AsnDecoder.ReadSetOf(
_span,
_ruleSet,
out int contentOffset,
out int contentLength,
out int bytesConsumed,
skipSortOrderValidation: skipSortOrderValidation,
expectedTag: expectedTag);
ReadOnlySpan<byte> content = _span.Slice(contentOffset, contentLength);
_span = _span.Slice(bytesConsumed);
return new AsnValueReader(content, _ruleSet);
}
internal DateTimeOffset ReadUtcTime(Asn1Tag? expectedTag = default)
{
DateTimeOffset ret = AsnDecoder.ReadUtcTime(_span, _ruleSet, out int consumed, expectedTag: expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal DateTimeOffset ReadGeneralizedTime(Asn1Tag? expectedTag = default)
{
DateTimeOffset ret = AsnDecoder.ReadGeneralizedTime(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal string ReadCharacterString(UniversalTagNumber encodingType, Asn1Tag? expectedTag = default)
{
string ret = AsnDecoder.ReadCharacterString(_span, _ruleSet, encodingType, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
internal TEnum ReadEnumeratedValue<TEnum>(Asn1Tag? expectedTag = null) where TEnum : Enum
{
TEnum ret = AsnDecoder.ReadEnumeratedValue<TEnum>(_span, _ruleSet, out int consumed, expectedTag);
_span = _span.Slice(consumed);
return ret;
}
}
}

View File

@ -1,137 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Formats.Asn1;
namespace PspCrypto.Security.Cryptography
{
//
// Common infrastructure for AsymmetricAlgorithm-derived classes that layer on OpenSSL.
//
internal static partial class AsymmetricAlgorithmHelpers
{
// private static readonly Func<ReadOnlyMemory<byte>, ReadOnlyMemory<byte>[]> ReaderAsn;
// static AsymmetricAlgorithmHelpers()
// {
// var assembly = typeof(Aes).Assembly;
// var r = assembly.GetType("System.Security.Cryptography.Asn1.AsnReader");
// var par1Type = typeof(ReadOnlyMemory<byte>);
// var par2Type = assembly.GetType("System.Security.Cryptography.Asn1.AsnEncodingRules");
// var asn1TagType = assembly.GetType("System.Security.Cryptography.Asn1.Asn1Tag");
// var constructor = r.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis,
// new[] { par1Type, par2Type }, new ParameterModifier[0]);
// if (constructor == null)
// {
// throw new NotImplementedException();
// }
// var readSequence = r.GetMethod("ReadSequence");
// if (readSequence == null)
// {
// throw new NotImplementedException();
// }
// var throwIfNotEmpty = r.GetMethod("ThrowIfNotEmpty");
// if (throwIfNotEmpty == null)
// {
// throw new NotImplementedException();
// }
// var readIntegerBytes = r.GetMethod("ReadIntegerBytes", BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new Type[0], new ParameterModifier[0]);
// if (readIntegerBytes == null)
// {
// throw new NotImplementedException();
// }
// var par1 = Expression.Parameter(par1Type, "data");
// var derField = par2Type.GetField("DER");
// var readerVar = Expression.Variable(r, "reader");
// var sequenceReaderVar = Expression.Variable(r, "sequenceReader");
// var rDerVar = Expression.Variable(typeof(ReadOnlyMemory<byte>), "rDer");
// var sDerVar = Expression.Variable(typeof(ReadOnlyMemory<byte>), "sDer");
// var sequenceField = asn1TagType.GetField("Sequence");
// var expBlock = Expression.Block(new[] { readerVar, sequenceReaderVar, rDerVar, sDerVar },
// Expression.Assign(readerVar, Expression.New(constructor, par1, Expression.Field(null, derField))),
// Expression.Assign(sequenceReaderVar, Expression.Call(readerVar, readSequence, Expression.Field(null, sequenceField))),
// Expression.Call(readerVar, throwIfNotEmpty),
// Expression.Assign(rDerVar, Expression.Call(sequenceReaderVar, readIntegerBytes)),
// Expression.Assign(sDerVar, Expression.Call(sequenceReaderVar, readIntegerBytes)),
// Expression.Call(sequenceReaderVar, throwIfNotEmpty),
// Expression.NewArrayInit(typeof(ReadOnlyMemory<byte>), rDerVar, sDerVar));
// ReaderAsn = Expression.Lambda<Func<ReadOnlyMemory<byte>, ReadOnlyMemory<byte>[]>>(expBlock, par1).Compile();
// }
/// <summary>
/// Convert Der format of (r, s) to Ieee1363 format
/// </summary>
public static byte[] ConvertDerToIeee1363(ReadOnlySpan<byte> input, int fieldSizeBits)
{
int fieldSizeBytes = BitsToBytes(fieldSizeBits);
int encodedSize = 2 * fieldSizeBytes;
byte[] response = new byte[encodedSize];
ConvertDerToIeee1363(input, fieldSizeBits, response);
return response;
}
internal static int ConvertDerToIeee1363(ReadOnlySpan<byte> input, int fieldSizeBits, Span<byte> destination)
{
int fieldSizeBytes = BitsToBytes(fieldSizeBits);
int encodedSize = 2 * fieldSizeBytes;
Debug.Assert(destination.Length >= encodedSize);
try
{
AsnValueReader reader = new AsnValueReader(input, AsnEncodingRules.DER);
AsnValueReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
ReadOnlySpan<byte> rDer = sequenceReader.ReadIntegerBytes();
ReadOnlySpan<byte> sDer = sequenceReader.ReadIntegerBytes();
sequenceReader.ThrowIfNotEmpty();
CopySignatureField(rDer, destination.Slice(0, fieldSizeBytes));
CopySignatureField(sDer, destination.Slice(fieldSizeBytes, fieldSizeBytes));
return encodedSize;
}
catch (AsnContentException e)
{
throw new CryptographicException("ASN1 corrupted data.", e);
}
}
public static int BitsToBytes(int bitLength)
{
int byteLength = (bitLength + 7) / 8;
return byteLength;
}
private static void CopySignatureField(ReadOnlySpan<byte> signatureField, Span<byte> response)
{
if (signatureField.Length > response.Length)
{
if (signatureField.Length != response.Length + 1 ||
signatureField[0] != 0 ||
signatureField[1] <= 0x7F)
{
// The only way this should be true is if the value required a zero-byte-pad.
Debug.Fail($"A signature field was longer ({signatureField.Length}) than expected ({response.Length})");
throw new CryptographicException();
}
signatureField = signatureField.Slice(1);
}
// If the field is too short then it needs to be prepended
// with zeroes in the response. Since the array was already
// zeroed out, just figure out where we need to start copying.
int writeOffset = response.Length - signatureField.Length;
response.Slice(0, writeOffset).Clear();
signatureField.CopyTo(response.Slice(writeOffset));
}
}
}

View File

@ -1,171 +1,170 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using System;
namespace PspCrypto.Security.Cryptography
{
internal class ECDsaManaged : System.Security.Cryptography.ECDsa
{
private ECKeyParameters _ecKeyParameters;
private readonly bool _ebootPbp;
private readonly int _type;
public ECDsaManaged()
{
}
public ECDsaManaged(System.Security.Cryptography.ECParameters parameters, bool ebootPbp, int type)
{
_ebootPbp = ebootPbp;
_type = type;
var gx = new BigInteger(1, parameters.Curve.G.X);
var gy = new BigInteger(1, parameters.Curve.G.Y);
var curve = ConvertECCurve(parameters.Curve);
var g = curve.CreatePoint(gx, gy);
var domainParameters = new ECDomainParameters(curve, g, curve.Order);
if (parameters.D != null)
{
var privateKey = new BigInteger(1, parameters.D);
_ecKeyParameters = new ECPrivateKeyParameters(privateKey, domainParameters);
}
else if (parameters.Q.X != null && parameters.Q.Y != null)
{
var publicKey = curve.CreatePoint(new BigInteger(1, parameters.Q.X), new BigInteger(1, parameters.Q.Y));
_ecKeyParameters = new ECPublicKeyParameters(publicKey, domainParameters);
}
else
{
throw new ArgumentException("invalid parameters", nameof(parameters));
}
}
public override byte[] SignHash(byte[] hash)
{
if (_ecKeyParameters is not ECPrivateKeyParameters)
{
throw new ArgumentException("key is not private Key");
}
var signer = CreateSigner();
signer.Init(true, _ecKeyParameters);
signer.BlockUpdate(hash);
return signer.GenerateSignature();
}
public override bool VerifyHash(byte[] hash, byte[] signature)
{
var signer = CreateSigner();
if (_ecKeyParameters is ECPrivateKeyParameters ecPrivateKeyParameters)
{
var publicKey = new ECPublicKeyParameters(
ecPrivateKeyParameters.Parameters.G.Multiply(ecPrivateKeyParameters.D),
ecPrivateKeyParameters.Parameters);
signer.Init(false, publicKey);
}
else
{
signer.Init(false, _ecKeyParameters);
}
signer.BlockUpdate(hash);
return signer.VerifySignature(signature);
}
protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm)
{
var dataSpan = data.AsSpan().Slice(offset, count);
if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA256)
{
return System.Security.Cryptography.SHA256.HashData(dataSpan);
}
else if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA1)
{
return System.Security.Cryptography.SHA1.HashData(dataSpan);
}
else
{
throw new NotSupportedException($"{hashAlgorithm} not supported");
}
}
private ISigner CreateSigner()
{
IDigest digest = DigestUtilities.GetDigest("NONE");
IDsa dsa = _ebootPbp ? new ECDsaSigner(new EbootPbpKCalculator(_type)) : new ECDsaSigner();
var signer = new DsaDigestSigner(dsa, digest, PlainDsaEncoding.Instance);
return signer;
}
private FpCurve _fpCurve;
public override void GenerateKey(System.Security.Cryptography.ECCurve curve)
{
_fpCurve = ConvertECCurve(curve);
var gx = new BigInteger(1, curve.G.X);
var gy = new BigInteger(1, curve.G.Y);
var g = _fpCurve.CreatePoint(gx, gy);
var domainParameters = new ECDomainParameters(_fpCurve, g, _fpCurve.Order);
var gen = new ECKeyPairGenerator();
gen.Init(new ECKeyGenerationParameters(domainParameters, new SecureRandom()));
var keyPair = gen.GenerateKeyPair();
_ecKeyParameters = (ECKeyParameters)keyPair.Private;
}
public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters)
{
var normalG = _ecKeyParameters.Parameters.G;
var curve = new System.Security.Cryptography.ECCurve
{
A = _fpCurve.A.ToBigInteger().ToByteArrayUnsigned(),
B = _fpCurve.B.ToBigInteger().ToByteArrayUnsigned(),
Prime = _fpCurve.Q.ToByteArrayUnsigned(),
Order = _fpCurve.Order.ToByteArrayUnsigned(),
Cofactor = _fpCurve.Cofactor.ToByteArrayUnsigned(),
G = new System.Security.Cryptography.ECPoint
{
X = normalG.XCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = normalG.YCoord.ToBigInteger().ToByteArrayUnsigned()
}
};
var parameters = new System.Security.Cryptography.ECParameters
{
Curve = curve
};
if (includePrivateParameters && _ecKeyParameters is ECPrivateKeyParameters privateKeyParameters)
{
parameters.D = privateKeyParameters.D.ToByteArrayUnsigned();
Console.WriteLine(privateKeyParameters.D.ToString(16).ToUpper());
var publicKey = privateKeyParameters.Parameters.G.Multiply(privateKeyParameters.D).Normalize();
parameters.Q = new System.Security.Cryptography.ECPoint
{
X = publicKey.XCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = publicKey.YCoord.ToBigInteger().ToByteArrayUnsigned()
};
}
else if (_ecKeyParameters is ECPublicKeyParameters publicKeyParameters)
{
var publicKey = publicKeyParameters.Q;
parameters.Q = new System.Security.Cryptography.ECPoint
{
X = publicKey.XCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = publicKey.YCoord.ToBigInteger().ToByteArrayUnsigned()
};
}
return parameters;
}
private static FpCurve ConvertECCurve(System.Security.Cryptography.ECCurve curve)
{
var p = new BigInteger(1, curve.Prime);
var a = new BigInteger(1, curve.A);
var b = new BigInteger(1, curve.B);
var n = new BigInteger(1, curve.Order);
var fpCurve = new FpCurve(p, a, b, n, BigInteger.One);
return fpCurve;
}
}
}
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using System;
namespace PspCrypto.Security.Cryptography
{
internal class ECDsaManaged : System.Security.Cryptography.ECDsa
{
private ECKeyParameters _ecKeyParameters;
private readonly bool _ebootPbp;
private readonly int _type;
public ECDsaManaged()
{
}
public ECDsaManaged(System.Security.Cryptography.ECParameters parameters, bool ebootPbp, int type)
{
_ebootPbp = ebootPbp;
_type = type;
var gx = new BigInteger(1, parameters.Curve.G.X);
var gy = new BigInteger(1, parameters.Curve.G.Y);
var curve = ConvertECCurve(parameters.Curve);
var g = curve.CreatePoint(gx, gy);
var domainParameters = new ECDomainParameters(curve, g, curve.Order);
if (parameters.D != null)
{
var privateKey = new BigInteger(1, parameters.D);
_ecKeyParameters = new ECPrivateKeyParameters(privateKey, domainParameters);
}
else if (parameters.Q.X != null && parameters.Q.Y != null)
{
var publicKey = curve.CreatePoint(new BigInteger(1, parameters.Q.X), new BigInteger(1, parameters.Q.Y));
_ecKeyParameters = new ECPublicKeyParameters(publicKey, domainParameters);
}
else
{
throw new ArgumentException("invalid parameters", nameof(parameters));
}
}
public override byte[] SignHash(byte[] hash)
{
if (_ecKeyParameters is not ECPrivateKeyParameters)
{
throw new ArgumentException("key is not private Key");
}
var signer = CreateSigner();
signer.Init(true, _ecKeyParameters);
signer.BlockUpdate(hash);
return signer.GenerateSignature();
}
public override bool VerifyHash(byte[] hash, byte[] signature)
{
var signer = CreateSigner();
if (_ecKeyParameters is ECPrivateKeyParameters ecPrivateKeyParameters)
{
var publicKey = new ECPublicKeyParameters(
ecPrivateKeyParameters.Parameters.G.Multiply(ecPrivateKeyParameters.D),
ecPrivateKeyParameters.Parameters);
signer.Init(false, publicKey);
}
else
{
signer.Init(false, _ecKeyParameters);
}
signer.BlockUpdate(hash);
return signer.VerifySignature(signature);
}
protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm)
{
var dataSpan = new ReadOnlySpan<byte>(data, offset, count);
if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA256)
{
return System.Security.Cryptography.SHA256.HashData(dataSpan);
}
else if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA1)
{
return System.Security.Cryptography.SHA1.HashData(dataSpan);
}
else
{
throw new NotSupportedException($"{hashAlgorithm} not supported");
}
}
private ISigner CreateSigner()
{
IDigest digest = DigestUtilities.GetDigest("NONE");
IDsa dsa = _ebootPbp ? new ECDsaSigner(new EbootPbpKCalculator(_type)) : new ECDsaSigner();
var signer = new DsaDigestSigner(dsa, digest, PlainDsaEncoding.Instance);
return signer;
}
private FpCurve _fpCurve;
public override void GenerateKey(System.Security.Cryptography.ECCurve curve)
{
_fpCurve = ConvertECCurve(curve);
var gx = new BigInteger(1, curve.G.X);
var gy = new BigInteger(1, curve.G.Y);
var g = _fpCurve.CreatePoint(gx, gy);
var domainParameters = new ECDomainParameters(_fpCurve, g, _fpCurve.Order);
var gen = new ECKeyPairGenerator();
gen.Init(new ECKeyGenerationParameters(domainParameters, new SecureRandom()));
var keyPair = gen.GenerateKeyPair();
_ecKeyParameters = (ECKeyParameters)keyPair.Private;
}
public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters)
{
var normalG = _ecKeyParameters.Parameters.G;
var curve = new System.Security.Cryptography.ECCurve
{
A = _fpCurve.A.ToBigInteger().ToByteArrayUnsigned(),
B = _fpCurve.B.ToBigInteger().ToByteArrayUnsigned(),
Prime = _fpCurve.Q.ToByteArrayUnsigned(),
Order = _fpCurve.Order.ToByteArrayUnsigned(),
Cofactor = _fpCurve.Cofactor.ToByteArrayUnsigned(),
G = new System.Security.Cryptography.ECPoint
{
X = normalG.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = normalG.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
}
};
var parameters = new System.Security.Cryptography.ECParameters
{
Curve = curve
};
if (includePrivateParameters && _ecKeyParameters is ECPrivateKeyParameters privateKeyParameters)
{
parameters.D = privateKeyParameters.D.ToByteArrayUnsigned();
var publicKey = _ecKeyParameters.Parameters.G.Multiply(privateKeyParameters.D).Normalize();
parameters.Q = new System.Security.Cryptography.ECPoint
{
X = publicKey.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = publicKey.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
};
}
else if (_ecKeyParameters is ECPublicKeyParameters publicKeyParameters)
{
var publicKey = publicKeyParameters.Q.Normalize();
parameters.Q = new System.Security.Cryptography.ECPoint
{
X = publicKey.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = publicKey.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
};
}
return parameters;
}
private static FpCurve ConvertECCurve(System.Security.Cryptography.ECCurve curve)
{
var p = new BigInteger(1, curve.Prime);
var a = new BigInteger(1, curve.A);
var b = new BigInteger(1, curve.B);
var n = new BigInteger(1, curve.Order);
var fpCurve = new FpCurve(p, a, b, n, BigInteger.One);
return fpCurve;
}
}
}

View File

@ -1,103 +1,103 @@
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using System;
namespace PspCrypto.Security.Cryptography
{
internal class EbootPbpKCalculator : IDsaKCalculator
{
private int _type;
private BigInteger _n;
public EbootPbpKCalculator(int type)
{
_type = type;
}
public bool IsDeterministic => true;
private readonly Memory<byte> _hash = new byte[0x40];
public void Init(BigInteger n, SecureRandom random)
{
throw new NotImplementedException();
}
public void Init(BigInteger n, BigInteger d, byte[] message)
{
_n = n;
Span<byte> hmacIn = stackalloc byte[0x38];
message[..0x1C].CopyTo(hmacIn);
KeyVault.Eboot_priv[_type].CopyTo(hmacIn[0x1C..]);
var hmac = new HMac(new Sha256Digest());
hmac.Init(new KeyParameter(KeyVault.Eboot_hmacKey));
hmac.BlockUpdate(hmacIn);
var hmac_hash_iv = new byte[hmac.GetMacSize()];
hmac.DoFinal(hmac_hash_iv);
int ret;
do
{
ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span);
if (ret != 0 || (ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span[0x20..])) != 0)
{
throw new Exception();
}
} while (ret != 0);
}
public BigInteger NextK()
{
var bn = new BigInteger(1, _hash.Span[..0x3c]);
var ret = bn.Mod(_n);
return ret;
}
private static int can_be_reversed_80C17A(Span<byte> src, int some_size, Span<byte> iv,
Span<byte> src_xored_digest)
{
Span<byte> src_xored = stackalloc byte[0x20];
iv.CopyTo(src_xored);
if (some_size > 0x20)
{
return 0x12;
}
for (int i = 0; i < some_size; i++)
{
src_xored[i] ^= src[i];
}
using var sha256 = System.Security.Cryptography.SHA256.Create();
var hash = sha256.ComputeHash(src_xored.ToArray());
hash.CopyTo(src_xored_digest);
for (int i = 0; i < 0x20; i++)
{
iv[i] ^= src_xored_digest[i];
}
for (int i = 0; i < 0x20; i++)
{
if (iv[i] != 0xFF)
{
iv[i] += 1;
break;
}
iv[i] = 0;
}
return 0;
}
}
}
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using System;
namespace PspCrypto.Security.Cryptography
{
internal class EbootPbpKCalculator : IDsaKCalculator
{
private int _type;
private BigInteger _n;
public EbootPbpKCalculator(int type)
{
_type = type;
}
public bool IsDeterministic => true;
private readonly Memory<byte> _hash = new byte[0x40];
public void Init(BigInteger n, SecureRandom random)
{
throw new NotImplementedException();
}
public void Init(BigInteger n, BigInteger d, byte[] message)
{
_n = n;
Span<byte> hmacIn = stackalloc byte[0x38];
message[..0x1C].CopyTo(hmacIn);
KeyVault.Eboot_priv[_type].CopyTo(hmacIn[0x1C..]);
var hmac = new HMac(new Sha256Digest());
hmac.Init(new KeyParameter(KeyVault.Eboot_hmacKey));
hmac.BlockUpdate(hmacIn);
var hmac_hash_iv = new byte[hmac.GetMacSize()];
hmac.DoFinal(hmac_hash_iv);
int ret;
do
{
ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span);
if (ret != 0 || (ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span[0x20..])) != 0)
{
throw new Exception();
}
} while (ret != 0);
}
public BigInteger NextK()
{
var bn = new BigInteger(1, _hash.Span[..0x3c]);
var ret = bn.Mod(_n);
return ret;
}
private static int can_be_reversed_80C17A(Span<byte> src, int some_size, Span<byte> iv,
Span<byte> src_xored_digest)
{
Span<byte> src_xored = stackalloc byte[0x20];
iv.CopyTo(src_xored);
if (some_size > 0x20)
{
return 0x12;
}
for (int i = 0; i < some_size; i++)
{
src_xored[i] ^= src[i];
}
using var sha256 = System.Security.Cryptography.SHA256.Create();
var hash = sha256.ComputeHash(src_xored.ToArray());
hash.CopyTo(src_xored_digest);
for (int i = 0; i < 0x20; i++)
{
iv[i] ^= src_xored_digest[i];
}
for (int i = 0; i < 0x20; i++)
{
if (iv[i] != 0xFF)
{
iv[i] += 1;
break;
}
iv[i] = 0;
}
return 0;
}
}
}

View File

@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Runtime.InteropServices;
namespace PspCrypto
{
public static class Utils
{
public static bool isEmpty(Span<byte> buf, int buf_size)
public static bool IsEmpty(Span<byte> buf, int buf_size)
{
if (buf != null && buf.Length >= buf_size)
{
@ -21,58 +18,10 @@ namespace PspCrypto
return true;
}
/// <summary>
/// Re-interprets a span of bytes as a reference to structure of type T.
/// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
/// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T AsRef<T>(Span<byte> span)
where T : struct
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(
$"Cannot use type '{typeof(T)}'. Only value types without pointers or references are supported.");
}
if (Unsafe.SizeOf<T>() > (uint)span.Length)
{
throw new ArgumentOutOfRangeException("length");
}
return ref Unsafe.As<byte, T>(ref MemoryMarshal.GetReference(span));
}
/// <summary>
/// Re-interprets a span of bytes as a reference to structure of type T.
/// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
/// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T AsRef<T>(ReadOnlySpan<byte> span)
where T : struct
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(
$"Cannot use type '{typeof(T)}'. Only value types without pointers or references are supported.");
}
if (Unsafe.SizeOf<T>() > (uint)span.Length)
{
throw new ArgumentOutOfRangeException("length");
}
return ref Unsafe.As<byte, T>(ref MemoryMarshal.GetReference(span));
}
public static void BuildDrmBBMacFinal2(Span<byte> mac)
{
Span<byte> checksum = new byte[20 + 0x10];
ref var aesHdr = ref AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(checksum);
ref var aesHdr = ref MemoryMarshal.AsRef<KIRKEngine.KIRK_AES128CBC_HEADER>(checksum);
aesHdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
aesHdr.keyseed = 0x63;
aesHdr.data_size = 0x10;