internal static Accuracy Read(DerSequenceReader reader) { var accuracyReader = reader.ReadSequence(); int?seconds = null; int?milliseconds = null; int?microseconds = null; if (accuracyReader.HasTag(DerSequenceReader.DerTag.Integer)) { seconds = accuracyReader.ReadInteger(); if (seconds < 0) { // The ASN.1 definition does not disallow negative numbers // but it doesn't make sense to allow negative numbers. throw new CryptographicException(Strings.InvalidAsn1); } } if (accuracyReader.HasTag(DerSequenceReader.ContextSpecificTagFlag)) { milliseconds = accuracyReader.ReadInteger(); if (milliseconds < 1 || milliseconds > 999) { throw new CryptographicException(Strings.InvalidAsn1); } } if (accuracyReader.HasTag(DerSequenceReader.ContextSpecificTagFlag | 1)) { microseconds = accuracyReader.ReadInteger(); if (microseconds < 1 || microseconds > 999) { throw new CryptographicException(Strings.InvalidAsn1); } } if (accuracyReader.HasData) { throw new CryptographicException(Strings.InvalidAsn1); } return(new Accuracy(seconds, milliseconds, microseconds)); }
internal static MessageImprint Read(DerSequenceReader reader) { var imprintReader = reader.ReadSequence(); var hashAlgorithm = AlgorithmIdentifier.Read(imprintReader); var hashedMessage = imprintReader.ReadOctetString(); if (hashedMessage == null || hashedMessage.Length == 0) { throw new CryptographicException(Strings.InvalidAsn1); } if (imprintReader.HasData) { throw new CryptographicException(Strings.InvalidAsn1); } return(new MessageImprint(hashAlgorithm, hashedMessage)); }
internal static EssCertId Read(DerSequenceReader reader) { var sequenceReader = reader.ReadSequence(); var hash = sequenceReader.ReadOctetString(); IssuerSerial issuerSerial = null; if (sequenceReader.HasData) { issuerSerial = IssuerSerial.Read(sequenceReader); if (sequenceReader.HasData) { throw new SignatureException(Strings.SigningCertificateInvalid); } } return(new EssCertId(hash, issuerSerial)); }
private static IReadOnlyList <GeneralName> ReadGeneralNames(DerSequenceReader reader) { var sequenceReader = reader.ReadSequence(); var generalNames = new List <GeneralName>(capacity: 1); var generalName = GeneralName.Read(sequenceReader); if (generalName != null) { generalNames.Add(generalName); } if (sequenceReader.HasData) { throw new SignatureException(Strings.InvalidAsn1); } return(generalNames.AsReadOnly()); }
internal static CommitmentTypeQualifier Read(DerSequenceReader reader) { var commitmentTypeQualifierReader = reader.ReadSequence(); var commitmentTypeIdentifier = commitmentTypeQualifierReader.ReadOid(); byte[] qualifier = null; if (commitmentTypeQualifierReader.HasData) { qualifier = commitmentTypeQualifierReader.ReadNextEncodedValue(); if (commitmentTypeQualifierReader.HasData) { throw new SignatureException(Strings.InvalidAsn1); } } return(new CommitmentTypeQualifier(commitmentTypeIdentifier, qualifier)); }
internal static AlgorithmIdentifier Read(DerSequenceReader reader) { var algIdReader = reader.ReadSequence(); var algorithm = algIdReader.ReadOid(); // For all algorithms we currently support, parameter must be null. // However, presence of a DER encoded NULL value is optional. if (algIdReader.HasData) { algIdReader.ReadNull(); if (algIdReader.HasData) { throw new SignatureException(Strings.SigningCertificateV2Invalid); } } return(new AlgorithmIdentifier(algorithm)); }
internal static PolicyQualifierInfo Read(DerSequenceReader reader) { var policyQualifierReader = reader.ReadSequence(); var policyQualifierId = policyQualifierReader.ReadOid(); byte[] qualifier = null; if (policyQualifierReader.HasData) { qualifier = policyQualifierReader.ReadNextEncodedValue(); if (policyQualifierReader.HasData) { throw new SignatureException(Strings.InvalidAsn1); } } return(new PolicyQualifierInfo(policyQualifierId, qualifier)); }
internal static Extensions Read(DerSequenceReader reader) { var extensionsReader = reader.ReadSequence(); var extensions = new List <Extension>(); while (extensionsReader.HasData) { var extension = Extension.Read(extensionsReader); extensions.Add(extension); } if (extensions.Count == 0) { throw new CryptographicException(Strings.InvalidAsn1); } return(new Extensions(extensions)); }
internal static Extension Read(DerSequenceReader reader) { var extensionReader = reader.ReadSequence(); var oid = extensionReader.ReadOid(); var critical = false; if (extensionReader.HasTag(DerSequenceReader.DerTag.Boolean)) { critical = extensionReader.ReadBoolean(); } var value = extensionReader.ReadOctetString(); if (extensionReader.HasData) { throw new CryptographicException(Strings.InvalidAsn1); } return(new Extension(oid, critical, value)); }
public static void InteriorLengthTooLong_Nested() { byte[] bytes = { // CONSTRUCTED SEQUENCE (9 bytes) 0x30, 0x09, // CONSTRUCTED SEQUENCE (2 bytes) 0x30, 0x02, // OCTET STRING (1 byte, but 0 remain for the inner sequence) 0x04, 0x01, // OCTET STRING (in the outer sequence, after the inner sequence, 3 bytes) 0x04, 0x03, 0x01, 0x02, 0x03 }; DerSequenceReader reader = new DerSequenceReader(bytes); DerSequenceReader nested = reader.ReadSequence(); Assert.Throws <CryptographicException>(() => nested.ReadOctetString()); }
public static void InteriorLengthTooLong() { byte[] bytes = { // CONSTRUCTED SEQUENCE (8 bytes) 0x30, 0x08, // CONSTRUCTED SEQUENCE (2 bytes) 0x30, 0x02, // OCTET STRING (0 bytes) 0x04, 0x00, // OCTET STRING (after the inner sequence, 3 bytes, but that exceeds the sequence bounds) 0x04, 0x03, 0x01, 0x02, 0x03 }; DerSequenceReader reader = new DerSequenceReader(bytes); DerSequenceReader nested = reader.ReadSequence(); Assert.Equal(0, nested.ReadOctetString().Length); Assert.False(nested.HasData); Assert.Throws <CryptographicException>(() => reader.ReadOctetString()); }
internal static NuGetPackageOwners Read(DerSequenceReader reader) { var packageOwners = new List <string>(); var ownersReader = reader.ReadSequence(); while (ownersReader.HasData) { var packageOwner = ownersReader.ReadUtf8String(); if (string.IsNullOrWhiteSpace(packageOwner)) { throw new SignatureException(Strings.NuGetPackageOwnersInvalid); } packageOwners.Add(packageOwner); } if (packageOwners.Count == 0) { throw new SignatureException(Strings.NuGetPackageOwnersInvalid); } return(new NuGetPackageOwners(packageOwners)); }
internal static string FindHttpAiaRecord(byte[] authorityInformationAccess, string recordTypeOid) { DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess); while (reader.HasData) { DerSequenceReader innerReader = reader.ReadSequence(); // If the sequence's first element is a sequence, unwrap it. if (innerReader.PeekTag() == ConstructedSequenceTagId) { innerReader = innerReader.ReadSequence(); } Oid oid = innerReader.ReadOid(); if (StringComparer.Ordinal.Equals(oid.Value, recordTypeOid)) { string uri = innerReader.ReadIA5String(); Uri parsedUri; if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri)) { continue; } if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return uri; } } return null; }
private static string GetCdpUrl(X509Certificate2 cert) { byte[] crlDistributionPoints = null; foreach (X509Extension extension in cert.Extensions) { if (StringComparer.Ordinal.Equals(extension.Oid.Value, Oids.CrlDistributionPoints)) { // If there's an Authority Information Access extension, it might be used for // looking up additional certificates for the chain. crlDistributionPoints = extension.RawData; break; } } if (crlDistributionPoints == null) { return null; } // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint // // DistributionPoint ::= SEQUENCE { // distributionPoint [0] DistributionPointName OPTIONAL, // reasons [1] ReasonFlags OPTIONAL, // cRLIssuer [2] GeneralNames OPTIONAL } // // DistributionPointName ::= CHOICE { // fullName [0] GeneralNames, // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } DerSequenceReader cdpSequence = new DerSequenceReader(crlDistributionPoints); while (cdpSequence.HasData) { const byte ContextSpecificFlag = 0x80; const byte ContextSpecific0 = ContextSpecificFlag; const byte ConstructedFlag = 0x20; const byte ContextSpecificConstructed0 = ContextSpecific0 | ConstructedFlag; const byte GeneralNameUri = ContextSpecificFlag | 0x06; DerSequenceReader distributionPointReader = cdpSequence.ReadSequence(); byte tag = distributionPointReader.PeekTag(); // Only distributionPoint is supported if (tag != ContextSpecificConstructed0) { continue; } // The DistributionPointName is a CHOICE, not a SEQUENCE, but the reader is the same. DerSequenceReader dpNameReader = distributionPointReader.ReadSequence(); tag = dpNameReader.PeekTag(); // Only fullName is supported, // nameRelativeToCRLIssuer is for LDAP-based lookup. if (tag != ContextSpecificConstructed0) { continue; } DerSequenceReader fullNameReader = dpNameReader.ReadSequence(); while (fullNameReader.HasData) { tag = fullNameReader.PeekTag(); if (tag != GeneralNameUri) { fullNameReader.SkipValue(); continue; } string uri = fullNameReader.ReadIA5String(); Uri parsedUri = new Uri(uri); if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return uri; } } return null; }
internal static TstInfo Read(DerSequenceReader reader) { var tstInfoReader = reader.ReadSequence(); var version = tstInfoReader.ReadInteger(); var policy = tstInfoReader.ReadOid(); var messageImprint = MessageImprint.Read(tstInfoReader); var serialNumber = tstInfoReader.ReadIntegerBytes(); if (serialNumber == null || serialNumber.Length == 0) { throw new CryptographicException(Strings.InvalidAsn1); } var genTime = tstInfoReader.ReadGeneralizedTime(); Accuracy accuracy = null; if (tstInfoReader.HasTag(DerSequenceReader.ConstructedSequence)) { accuracy = Accuracy.Read(tstInfoReader); } var ordering = false; if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Boolean)) { ordering = tstInfoReader.ReadBoolean(); } byte[] nonce = null; if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Integer)) { nonce = tstInfoReader.ReadIntegerBytes(); } byte[] tsa = null; if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag0)) { tsa = tstInfoReader.ReadValue((DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificConstructedTag0); } X509ExtensionCollection extensions = null; if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag1)) { extensions = new X509ExtensionCollection(); var rawExtensions = Signing.Extensions.Read(tstInfoReader); foreach (var rawExtension in rawExtensions.ExtensionsList) { extensions.Add( new X509Extension( rawExtension.Id, rawExtension.Value, rawExtension.Critical)); } if (extensions.Count == 0) { throw new CryptographicException(Strings.InvalidAsn1); } } if (tstInfoReader.HasData) { throw new CryptographicException(Strings.InvalidAsn1); } return(new TstInfo( version, policy, messageImprint, serialNumber, genTime.ToUniversalTime(), accuracy, ordering, nonce, tsa, extensions)); }
private static DerSequenceReader ReadEncryptedPkcs8Blob(string passphrase, DerSequenceReader reader) { // EncryptedPrivateKeyInfo::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData EncryptedData } // // EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier // // EncryptedData ::= OCTET STRING DerSequenceReader algorithmIdentifier = reader.ReadSequence(); string algorithmOid = algorithmIdentifier.ReadOidAsString(); // PBES2 (Password-Based Encryption Scheme 2) if (algorithmOid != OidPbes2) { Debug.Fail($"Expected PBES2 ({OidPbes2}), got {algorithmOid}"); throw new CryptographicException(); } // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier { { PBES2 - KDFs} }, // encryptionScheme AlgorithmIdentifier { { PBES2 - Encs} } // } DerSequenceReader pbes2Params = algorithmIdentifier.ReadSequence(); algorithmIdentifier = pbes2Params.ReadSequence(); string kdfOid = algorithmIdentifier.ReadOidAsString(); // PBKDF2 (Password-Based Key Derivation Function 2) if (kdfOid != OidPbkdf2) { Debug.Fail($"Expected PBKDF2 ({OidPbkdf2}), got {kdfOid}"); throw new CryptographicException(); } // PBKDF2-params ::= SEQUENCE { // salt CHOICE { // specified OCTET STRING, // otherSource AlgorithmIdentifier { { PBKDF2 - SaltSources} } // }, // iterationCount INTEGER (1..MAX), // keyLength INTEGER(1..MAX) OPTIONAL, // prf AlgorithmIdentifier { { PBKDF2 - PRFs} } DEFAULT algid - hmacWithSHA1 // } DerSequenceReader pbkdf2Params = algorithmIdentifier.ReadSequence(); byte[] salt = pbkdf2Params.ReadOctetString(); int iterCount = pbkdf2Params.ReadInteger(); int keySize = -1; if (pbkdf2Params.HasData && pbkdf2Params.PeekTag() == (byte)DerSequenceReader.DerTag.Integer) { keySize = pbkdf2Params.ReadInteger(); } if (pbkdf2Params.HasData) { string prfOid = pbkdf2Params.ReadOidAsString(); // SHA-1 is the only hash algorithm our PBKDF2 supports. if (prfOid != OidSha1) { Debug.Fail($"Expected SHA1 ({OidSha1}), got {prfOid}"); throw new CryptographicException(); } } DerSequenceReader encryptionScheme = pbes2Params.ReadSequence(); string cipherOid = encryptionScheme.ReadOidAsString(); // DES-EDE3-CBC (TripleDES in CBC mode) if (cipherOid != OidTripleDesCbc) { Debug.Fail($"Expected DES-EDE3-CBC ({OidTripleDesCbc}), got {cipherOid}"); throw new CryptographicException(); } byte[] decrypted; using (TripleDES des3 = TripleDES.Create()) { if (keySize == -1) { foreach (KeySizes keySizes in des3.LegalKeySizes) { keySize = Math.Max(keySize, keySizes.MaxSize); } } byte[] iv = encryptionScheme.ReadOctetString(); using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, iterCount)) using (ICryptoTransform decryptor = des3.CreateDecryptor(pbkdf2.GetBytes(keySize / 8), iv)) { byte[] encrypted = reader.ReadOctetString(); decrypted = decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length); } } DerSequenceReader pkcs8Reader = new DerSequenceReader(decrypted); return(pkcs8Reader); }
private static X509Certificate2 DownloadCertificate( byte[] authorityInformationAccess, ref TimeSpan remainingDownloadTime) { // Don't do any work if we're over limit. if (remainingDownloadTime <= TimeSpan.Zero) { return null; } DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess); while (reader.HasData) { DerSequenceReader innerReader = reader.ReadSequence(); // If the sequence's first element is a sequence, unwrap it. if (innerReader.PeekTag() == ConstructedSequenceTagId) { innerReader = innerReader.ReadSequence(); } Oid oid = innerReader.ReadOid(); if (StringComparer.Ordinal.Equals(oid.Value, Oids.CertificateAuthorityIssuers)) { string uri = innerReader.ReadIA5String(); Uri parsedUri; if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri)) { continue; } if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime); } } return null; }
internal static ISet<string> ReadCertPolicyExtension(X509Extension extension) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); HashSet<string> policies = new HashSet<string>(); while (reader.HasData) { DerSequenceReader policyInformation = reader.ReadSequence(); policies.Add(policyInformation.ReadOidAsString()); // There is an optional policy qualifier here, but it is for information // purposes, there is no logic that would be changed. // Since reader (the outer one) has already skipped past the rest of the // sequence we don't particularly need to drain out here. } return policies; }
private static List<CertificatePolicyMapping> ReadCertPolicyMappingsExtension(X509Extension extension) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); List<CertificatePolicyMapping> mappings = new List<CertificatePolicyMapping>(); while (reader.HasData) { DerSequenceReader mappingSequence = reader.ReadSequence(); mappings.Add( new CertificatePolicyMapping { IssuerDomainPolicy = mappingSequence.ReadOidAsString(), SubjectDomainPolicy = mappingSequence.ReadOidAsString(), }); } return mappings; }