private static string ReadString(DerSequenceReader tavReader) { var tag = (DerSequenceReader.DerTag)tavReader.PeekTag(); switch (tag) { case DerSequenceReader.DerTag.BMPString: return(tavReader.ReadBMPString()); case DerSequenceReader.DerTag.IA5String: return(tavReader.ReadIA5String()); case DerSequenceReader.DerTag.PrintableString: return(tavReader.ReadPrintableString()); case DerSequenceReader.DerTag.UTF8String: return(tavReader.ReadUtf8String()); case DerSequenceReader.DerTag.T61String: return(tavReader.ReadT61String()); default: throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } }
private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); while (reader.HasData) { // Policy Constraints context specific tag values are defined in RFC 3280 4.2.1.12, // and restated (unchanged) in RFC 5280 4.2.1.11. switch (reader.PeekTag()) { case DerSequenceReader.ContextSpecificTagFlag | 0: policy.RequireExplicitPolicyDepth = reader.ReadInteger(); break; case DerSequenceReader.ContextSpecificTagFlag | 1: policy.InhibitMappingDepth = reader.ReadInteger(); break; default: if (extension.Critical) { // If an unknown value is read, but we're marked as critical, // then we don't know what we're doing and MUST fail validation // (RFC 3280). // If it isn't critical then it means we're allowed to be ignorant // of data defined more recently than we understand. throw new CryptographicException(); } break; } } }
protected override string DerStringToManagedString(byte[] anyString) { DerSequenceReader reader = DerSequenceReader.CreateForPayload(anyString); var tag = (DerSequenceReader.DerTag)reader.PeekTag(); string value = null; switch (tag) { case DerSequenceReader.DerTag.BMPString: value = reader.ReadBMPString(); break; case DerSequenceReader.DerTag.IA5String: value = reader.ReadIA5String(); break; case DerSequenceReader.DerTag.PrintableString: value = reader.ReadPrintableString(); break; case DerSequenceReader.DerTag.UTF8String: value = reader.ReadUtf8String(); break; // Ignore anything we don't know how to read. } return(value); }
private static IEnumerable <KeyValuePair <string, string> > ReadReverseRdns(X500DistinguishedName name) { DerSequenceReader x500NameReader = new DerSequenceReader(name.RawData); var rdnReaders = new Stack <DerSequenceReader>(); while (x500NameReader.HasData) { rdnReaders.Push(x500NameReader.ReadSet()); } while (rdnReaders.Count > 0) { DerSequenceReader rdnReader = rdnReaders.Pop(); while (rdnReader.HasData) { DerSequenceReader tavReader = rdnReader.ReadSequence(); string oid = tavReader.ReadOidAsString(); var tag = (DerSequenceReader.DerTag)tavReader.PeekTag(); string value = null; switch (tag) { case DerSequenceReader.DerTag.BMPString: value = tavReader.ReadBMPString(); break; case DerSequenceReader.DerTag.IA5String: value = tavReader.ReadIA5String(); break; case DerSequenceReader.DerTag.PrintableString: value = tavReader.ReadPrintableString(); break; case DerSequenceReader.DerTag.UTF8String: value = tavReader.ReadUtf8String(); break; case DerSequenceReader.DerTag.T61String: value = tavReader.ReadT61String(); break; // Ignore anything we don't know how to read. } if (value != null) { yield return(new KeyValuePair <string, string>(oid, value)); } } } }
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); }
public void FindByTemplateName(string templateName) { FindCore( cert => { X509Extension ext = FindExtension(cert, Oids.EnrollCertTypeExtension); if (ext != null) { // Try a V1 template structure, just a string: string decodedName = Interop.Crypto.DerStringToManagedString(ext.RawData); // If this doesn't match, maybe a V2 template will if (StringComparer.OrdinalIgnoreCase.Equals(templateName, decodedName)) { return(true); } } ext = FindExtension(cert, Oids.CertificateTemplate); if (ext != null) { DerSequenceReader reader = new DerSequenceReader(ext.RawData); // SEQUENCE ( // OID oid, // INTEGER major, // INTEGER minor OPTIONAL // ) if (reader.PeekTag() == (byte)DerSequenceReader.DerTag.ObjectIdentifier) { Oid oid = reader.ReadOid(); if (StringComparer.Ordinal.Equals(templateName, oid.Value)) { return(true); } } } return(false); }); }
public virtual void DecodeX509BasicConstraints2Extension( byte[] encoded, out bool certificateAuthority, out bool hasPathLengthConstraint, out int pathLengthConstraint) { // BasicConstraints ::= SEQUENCE { // cA BOOLEAN DEFAULT FALSE, // pathLenConstraint INTEGER(0..MAX) OPTIONAL } DerSequenceReader constraints = new DerSequenceReader(encoded); if (!constraints.HasData) { certificateAuthority = false; hasPathLengthConstraint = false; pathLengthConstraint = 0; return; } if (constraints.PeekTag() == (byte)DerSequenceReader.DerTag.Boolean) { certificateAuthority = constraints.ReadBoolean(); } else { certificateAuthority = false; } if (constraints.HasData) { pathLengthConstraint = constraints.ReadInteger(); hasPathLengthConstraint = true; } else { pathLengthConstraint = 0; hasPathLengthConstraint = false; } }
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); }
internal CertificateData(byte[] rawData) { #if DEBUG try { #endif DerSequenceReader reader = new DerSequenceReader(rawData); DerSequenceReader tbsCertificate = reader.ReadSequence(); if (tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag0) { DerSequenceReader version = tbsCertificate.ReadSequence(); Version = version.ReadInteger(); } else if (tbsCertificate.PeekTag() != (byte)DerSequenceReader.DerTag.Integer) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } else { Version = 0; } if (Version < 0 || Version > 2) { throw new CryptographicException(); } SerialNumber = tbsCertificate.ReadIntegerBytes(); DerSequenceReader tbsSignature = tbsCertificate.ReadSequence(); TbsSignature.AlgorithmId = tbsSignature.ReadOidAsString(); TbsSignature.Parameters = tbsSignature.HasData ? tbsSignature.ReadNextEncodedValue() : Array.Empty <byte>(); if (tbsSignature.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } Issuer = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue()); DerSequenceReader validity = tbsCertificate.ReadSequence(); NotBefore = validity.ReadX509Date(); NotAfter = validity.ReadX509Date(); if (validity.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } Subject = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue()); SubjectPublicKeyInfo = tbsCertificate.ReadNextEncodedValue(); DerSequenceReader subjectPublicKeyInfo = new DerSequenceReader(SubjectPublicKeyInfo); DerSequenceReader subjectKeyAlgorithm = subjectPublicKeyInfo.ReadSequence(); PublicKeyAlgorithm.AlgorithmId = subjectKeyAlgorithm.ReadOidAsString(); PublicKeyAlgorithm.Parameters = subjectKeyAlgorithm.HasData ? subjectKeyAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>(); if (subjectKeyAlgorithm.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } PublicKey = subjectPublicKeyInfo.ReadBitString(); if (subjectPublicKeyInfo.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } if (Version > 0 && tbsCertificate.HasData && tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag1) { IssuerUniqueId = tbsCertificate.ReadBitString(); } else { IssuerUniqueId = null; } if (Version > 0 && tbsCertificate.HasData && tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag2) { SubjectUniqueId = tbsCertificate.ReadBitString(); } else { SubjectUniqueId = null; } Extensions = new List <X509Extension>(); if (Version > 1 && tbsCertificate.HasData && tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag3) { DerSequenceReader extensions = tbsCertificate.ReadSequence(); extensions = extensions.ReadSequence(); while (extensions.HasData) { DerSequenceReader extensionReader = extensions.ReadSequence(); string oid = extensionReader.ReadOidAsString(); bool critical = false; if (extensionReader.PeekTag() == (byte)DerSequenceReader.DerTag.Boolean) { critical = extensionReader.ReadBoolean(); } byte[] extensionData = extensionReader.ReadOctetString(); Extensions.Add(new X509Extension(oid, extensionData, critical)); if (extensionReader.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } } } if (tbsCertificate.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } DerSequenceReader signatureAlgorithm = reader.ReadSequence(); SignatureAlgorithm.AlgorithmId = signatureAlgorithm.ReadOidAsString(); SignatureAlgorithm.Parameters = signatureAlgorithm.HasData ? signatureAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>(); if (signatureAlgorithm.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } SignatureValue = reader.ReadBitString(); if (reader.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } RawData = rawData; #if DEBUG } catch (Exception e) { throw new CryptographicException( $"Error in reading certificate:{Environment.NewLine}{PemPrintCert(rawData)}", e); } #endif }
private static string FindAltNameMatch(byte[] extensionBytes, GeneralNameType matchType, string otherOid) { // If Other, have OID, else, no OID. Debug.Assert( (otherOid == null) == (matchType != GeneralNameType.OtherName), $"otherOid has incorrect nullarity for matchType {matchType}"); Debug.Assert( matchType == GeneralNameType.UniformResourceIdentifier || matchType == GeneralNameType.DnsName || matchType == GeneralNameType.Email || matchType == GeneralNameType.OtherName, $"matchType ({matchType}) is not currently supported"); Debug.Assert( otherOid == null || otherOid == Oids.UserPrincipalName, $"otherOid ({otherOid}) is not supported"); // SubjectAltName ::= GeneralNames // // IssuerAltName ::= GeneralNames // // 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 } // // OtherName::= SEQUENCE { // type - id OBJECT IDENTIFIER, // value[0] EXPLICIT ANY DEFINED BY type - id } byte expectedTag = (byte)(DerSequenceReader.ContextSpecificTagFlag | (byte)matchType); if (matchType == GeneralNameType.OtherName) { expectedTag |= DerSequenceReader.ConstructedFlag; } DerSequenceReader altNameReader = new DerSequenceReader(extensionBytes); while (altNameReader.HasData) { if (altNameReader.PeekTag() != expectedTag) { altNameReader.SkipValue(); continue; } switch (matchType) { case GeneralNameType.OtherName: { DerSequenceReader otherNameReader = altNameReader.ReadSequence(); string oid = otherNameReader.ReadOidAsString(); if (oid == otherOid) { // Payload is value[0] EXPLICIT, meaning // a) it'll be tagged as ContextSpecific0 // b) that's interpretable as a Sequence (EXPLICIT) // c) the payload will then be retagged as the correct type (EXPLICIT) if (otherNameReader.PeekTag() != DerSequenceReader.ContextSpecificConstructedTag0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } otherNameReader = otherNameReader.ReadSequence(); // Currently only UPN is supported, which is a UTF8 string per // https://msdn.microsoft.com/en-us/library/ff842518.aspx return(otherNameReader.ReadUtf8String()); } // If the OtherName OID didn't match, move to the next entry. continue; } case GeneralNameType.Rfc822Name: case GeneralNameType.DnsName: case GeneralNameType.UniformResourceIdentifier: return(altNameReader.ReadIA5String()); default: altNameReader.SkipValue(); continue; } } 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); }