internal Rfc3161TimestampTokenInfo(IntPtr pTsContext) { var context = (Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)Marshal.PtrToStructure(pTsContext, typeof(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)); byte[] encoded = new byte[context.cbEncoded]; Marshal.Copy(context.pbEncoded, encoded, 0, context.cbEncoded); var cms = new SignedCms(); cms.Decode(encoded); if (!string.Equals(cms.ContentInfo.ContentType.Value, Oids.TSTInfoContentType, StringComparison.Ordinal)) { throw new CryptographicException(Strings.InvalidAsn1); } RawData = cms.ContentInfo.Content; _decoded = TstInfo.Read(RawData); }
public Rfc3161TimestampTokenInfo( string policyId, Oid hashAlgorithmId, byte[] messageHash, byte[] serialNumber, DateTimeOffset timestamp, long?accuracyInMicroseconds = null, bool isOrdering = false, byte[] nonce = null, byte[] tsaName = null, X509ExtensionCollection extensions = null) : base(TimestampTokenInfoId, new byte[] { }) { if (policyId == null) { throw new ArgumentNullException(nameof(policyId)); } if (!Rfc3161TimestampUtils.IsLegalOid(policyId)) { throw new ArgumentException("Policy identifier does not represent a legal value", nameof(hashAlgorithmId)); } if (hashAlgorithmId == null) { throw new ArgumentNullException(nameof(hashAlgorithmId)); } if (!Rfc3161TimestampUtils.IsLegalOid(hashAlgorithmId.Value)) { throw new ArgumentException("Hash algorithm does not represent a legal value", nameof(hashAlgorithmId)); } if (messageHash == null) { throw new ArgumentNullException(nameof(messageHash)); } if (messageHash.Length == 0) { throw new ArgumentException("Non-empty array is required", nameof(messageHash)); } if (serialNumber == null) { throw new ArgumentNullException(nameof(serialNumber)); } if (serialNumber.Length == 0) { throw new ArgumentException("Non-empty array is required", nameof(serialNumber)); } var accuracy = accuracyInMicroseconds.GetValueOrDefault(); if (accuracy < 0 || accuracy > 4294967295000000) { throw new ArgumentOutOfRangeException(nameof(accuracyInMicroseconds)); } var tstInfo = new TstInfo { Version = 1, PolicyId = policyId, HashAlgorithmId = new Oid(hashAlgorithmId.Value, hashAlgorithmId.FriendlyName), HashedMessage = (byte[])messageHash.Clone(), SerialNumber = (byte[])serialNumber.Clone(), Timestamp = timestamp.ToUniversalTime(), AccuracyInMicroseconds = accuracyInMicroseconds, IsOrdering = isOrdering, Nonce = (byte[])nonce?.Clone(), TsaName = (byte[])tsaName?.Clone(), Extensions = ShallowCopy(extensions, preserveNull: true), }; RawData = Encode(tstInfo); _decoded = tstInfo; }
private static unsafe byte[] Encode(TstInfo tstInfo) { var algOid = tstInfo.HashAlgorithmId.Value; var policyOidBytes = new byte[tstInfo.PolicyId.Length + 1]; var algOidBytes = new byte[algOid.Length + 1]; var serialNumberBigEndian = tstInfo.SerialNumber; var serialNumberLittleEndian = new byte[serialNumberBigEndian.Length]; for (var i = 0; i < serialNumberLittleEndian.Length; i++) { serialNumberLittleEndian[i] = serialNumberBigEndian[serialNumberBigEndian.Length - i - 1]; } var filetime = tstInfo.Timestamp.ToFileTime(); fixed(byte *pbPolicyOid = policyOidBytes) fixed(char *pszPolicyOid = tstInfo.PolicyId) fixed(byte *pbHashedMessage = tstInfo.HashedMessage) fixed(byte *pbSerialNumber = serialNumberLittleEndian) fixed(char *pszAlgOid = algOid) fixed(byte *pbAlgOid = algOidBytes) fixed(byte *pbNonce = tstInfo.Nonce) fixed(byte *pbTsaName = tstInfo.TsaName) { Encoding.ASCII.GetBytes(pszPolicyOid, tstInfo.PolicyId.Length, pbPolicyOid, policyOidBytes.Length); Encoding.ASCII.GetBytes(pszAlgOid, algOid.Length, pbAlgOid, algOidBytes.Length); var info = new Rfc3161TimestampWin32.CRYPT_TIMESTAMP_INFO { dwVersion = tstInfo.Version, pszTSAPolicyId = (IntPtr)pbPolicyOid, fOrdering = tstInfo.IsOrdering, }; var accuracy = default(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_ACCURACY); info.HashAlgorithm.pszOid = (IntPtr)pbAlgOid; info.HashedMessage.cbData = (uint)tstInfo.HashedMessage.Length; info.HashedMessage.pbData = (IntPtr)pbHashedMessage; info.SerialNumber.cbData = (uint)serialNumberLittleEndian.Length; info.SerialNumber.pbData = (IntPtr)pbSerialNumber; info.ftTime.dwLowDateTime = (int)(filetime & 0xFFFFFFFF); info.ftTime.dwHighDateTime = (int)(filetime >> 32); if (tstInfo.AccuracyInMicroseconds.HasValue) { var val = tstInfo.AccuracyInMicroseconds.Value; val = Math.DivRem(val, 1000, out var rem); accuracy.dwMicros = (int)rem; val = Math.DivRem(val, 1000, out rem); accuracy.dwMillis = (int)rem; if (val > int.MaxValue) { Debug.Fail($"accuracy value {tstInfo.AccuracyInMicroseconds.Value} had seconds component {val}, which should have been stopped"); throw new CryptographicException(); } accuracy.dwSeconds = (int)val; info.pvAccuracy = (IntPtr)(&accuracy); } if (tstInfo.Nonce != null) { info.Nonce.cbData = (uint)tstInfo.Nonce.Length; info.Nonce.pbData = (IntPtr)pbNonce; } if (tstInfo.TsaName != null) { info.Tsa.cbData = (uint)tstInfo.TsaName.Length; info.Tsa.pbData = (IntPtr)pbTsaName; } if (tstInfo.Extensions != null) { throw new NotImplementedException(); } var encodedDataPtr = IntPtr.Zero; uint cbEncoded = 0; try { if (!Rfc3161TimestampWin32.CryptEncodeObjectEx( Rfc3161TimestampWin32.CryptEncodingTypes.X509_ASN_ENCODING, Rfc3161TimestampWin32.TIMESTAMP_INFO, (IntPtr)(&info), Rfc3161TimestampWin32.CryptEncodeObjectFlags.CRYPT_ENCODE_ALLOC_FLAG, IntPtr.Zero, (IntPtr)(&encodedDataPtr), ref cbEncoded)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } var encoded = new byte[cbEncoded]; Marshal.Copy(encodedDataPtr, encoded, 0, (int)cbEncoded); return(encoded); } finally { if (encodedDataPtr != IntPtr.Zero) { Rfc3161TimestampWin32.LocalFree(encodedDataPtr); } } } }
private static TstInfo ReadTstInfo(IntPtr pTstInfo) { var info = (Rfc3161TimestampWin32.CRYPT_TIMESTAMP_INFO)Marshal.PtrToStructure(pTstInfo, typeof(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_INFO)); var tstInfo = new TstInfo { Version = info.dwVersion, PolicyId = Marshal.PtrToStringAnsi(info.pszTSAPolicyId), HashedMessage = CopyFromNative(ref info.HashedMessage), SerialNumber = CopyFromNative(ref info.SerialNumber), IsOrdering = info.fOrdering, Nonce = CopyFromNative(ref info.Nonce), TsaName = CopyFromNative(ref info.Tsa), }; // Convert to BigEndian. Array.Reverse(tstInfo.SerialNumber); var hashAlgOidValue = Marshal.PtrToStringAnsi(info.HashAlgorithm.pszOid); Oid hashAlgOid; try { hashAlgOid = Oid.FromOidValue(hashAlgOidValue, OidGroup.HashAlgorithm); } catch (CryptographicException) { hashAlgOid = new Oid(hashAlgOidValue, hashAlgOidValue); } tstInfo.HashAlgorithmId = hashAlgOid; long filetime = info.ftTime.dwHighDateTime; filetime <<= 32; filetime |= (info.ftTime.dwLowDateTime & 0xFFFFFFFFL); tstInfo.Timestamp = DateTimeOffset.FromFileTime(filetime).ToUniversalTime(); if (info.pvAccuracy != IntPtr.Zero) { var accuracy = (Rfc3161TimestampWin32.CRYPT_TIMESTAMP_ACCURACY)Marshal.PtrToStructure(info.pvAccuracy, typeof(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_ACCURACY)); var accuracyMicroSeconds = accuracy.dwSeconds * 1_000_000L + accuracy.dwMillis * 1000L + accuracy.dwSeconds; tstInfo.AccuracyInMicroseconds = accuracyMicroSeconds; } if (info.cExtension > 0) { throw new NotImplementedException(); } if (tstInfo.HashedMessage == null || tstInfo.SerialNumber == null) { throw new CryptographicException(); } return(tstInfo); }
public override void CopyFrom(AsnEncodedData asnEncodedData) { _decoded = null; base.CopyFrom(asnEncodedData); }