internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out TbsCertificateAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
public override DecryptorPal Decode( byte[] encodedMessage, out int version, out ContentInfo contentInfo, out AlgorithmIdentifier contentEncryptionAlgorithm, out X509Certificate2Collection originatorCerts, out CryptographicAttributeObjectCollection unprotectedAttributes) { // Read using BER because the CMS specification says the encoding is BER. AsnValueReader reader = new AsnValueReader(encodedMessage, AsnEncodingRules.BER); ContentInfoAsn.Decode( ref reader, encodedMessage, out ContentInfoAsn parsedContentInfo); if (parsedContentInfo.ContentType != Oids.Pkcs7Enveloped) { throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType); } byte[] copy = parsedContentInfo.Content.ToArray(); EnvelopedDataAsn data = EnvelopedDataAsn.Decode(copy, AsnEncodingRules.BER); version = data.Version; contentInfo = new ContentInfo( new Oid(data.EncryptedContentInfo.ContentType), data.EncryptedContentInfo.EncryptedContent?.ToArray() ?? Array.Empty <byte>()); contentEncryptionAlgorithm = data.EncryptedContentInfo.ContentEncryptionAlgorithm.ToPresentationObject(); originatorCerts = new X509Certificate2Collection(); if (data.OriginatorInfo.HasValue && data.OriginatorInfo.Value.CertificateSet != null) { foreach (CertificateChoiceAsn certChoice in data.OriginatorInfo.Value.CertificateSet) { if (certChoice.Certificate != null) { originatorCerts.Add(new X509Certificate2(certChoice.Certificate.Value.ToArray())); } } } unprotectedAttributes = SignerInfo.MakeAttributeCollection(data.UnprotectedAttributes); var recipientInfos = new List <RecipientInfo>(); foreach (RecipientInfoAsn recipientInfo in data.RecipientInfos) { if (recipientInfo.Ktri.HasValue) { recipientInfos.Add(new KeyTransRecipientInfo(new ManagedKeyTransPal(recipientInfo.Ktri.Value))); } else if (recipientInfo.Kari.HasValue) { for (int i = 0; i < recipientInfo.Kari.Value.RecipientEncryptedKeys.Length; i++) { recipientInfos.Add( new KeyAgreeRecipientInfo(new ManagedKeyAgreePal(recipientInfo.Kari.Value, i))); } } else { Debug.Fail($"{nameof(RecipientInfoAsn)} deserialized with an unknown recipient type"); throw new CryptographicException(); } } return(new ManagedDecryptorPal(copy, data, new RecipientInfoCollection(recipientInfos))); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out KeyTransRecipientInfoAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out RecipientEncryptedKeyAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out SignedDataAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out OtherKeyAttributeAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out Rfc3161TimeStampReq decoded) { decoded = default; AsnValueReader sequenceReader = reader.ReadSequence(expectedTag); AsnValueReader defaultReader; AsnValueReader collectionReader; ReadOnlySpan <byte> rebindSpan = rebind.Span; int offset; ReadOnlySpan <byte> tmpSpan; if (!sequenceReader.TryReadInt32(out decoded.Version)) { sequenceReader.ThrowIfNotEmpty(); } System.Security.Cryptography.Pkcs.Asn1.MessageImprint.Decode(ref sequenceReader, rebind, out decoded.MessageImprint); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.ObjectIdentifier)) { decoded.ReqPolicy = sequenceReader.ReadObjectIdentifier(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Integer)) { tmpSpan = sequenceReader.ReadIntegerBytes(); decoded.Nonce = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean)) { decoded.CertReq = sequenceReader.ReadBoolean(); } else { defaultReader = new AsnValueReader(DefaultCertReq, AsnEncodingRules.DER); decoded.CertReq = defaultReader.ReadBoolean(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { // Decode SEQUENCE OF for Extensions { collectionReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>(); System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.Extensions = tmpList.ToArray(); } } sequenceReader.ThrowIfNotEmpty(); }
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"); try { AsnValueReader reader = new AsnValueReader(extensionBytes, AsnEncodingRules.DER); AsnValueReader sequenceReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { GeneralNameAsn.Decode(ref sequenceReader, extensionBytes, out GeneralNameAsn generalName); switch (matchType) { case GeneralNameType.OtherName: // If the OtherName OID didn't match, move to the next entry. if (generalName.OtherName.HasValue && generalName.OtherName.Value.TypeId == otherOid) { // Currently only UPN is supported, which is a UTF8 string per // https://msdn.microsoft.com/en-us/library/ff842518.aspx AsnValueReader nameReader = new AsnValueReader( generalName.OtherName.Value.Value.Span, AsnEncodingRules.DER); string udnName = nameReader.ReadCharacterString(UniversalTagNumber.UTF8String); nameReader.ThrowIfNotEmpty(); return(udnName); } break; case GeneralNameType.Rfc822Name: if (generalName.Rfc822Name != null) { return(generalName.Rfc822Name); } break; case GeneralNameType.DnsName: if (generalName.DnsName != null) { return(generalName.DnsName); } break; case GeneralNameType.UniformResourceIdentifier: if (generalName.Uri != null) { return(generalName.Uri); } break; } } } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } return(null); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out DistributionPointAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
private void Decode(ReadOnlySpan <byte> rawData) { _keyIdentifier = null; _simpleIssuer = null; _rawIssuer = null; _serialNumber = null; // https://datatracker.ietf.org/doc/html/rfc3280#section-4.2.1.1 // AuthorityKeyIdentifier ::= SEQUENCE { // keyIdentifier[0] KeyIdentifier OPTIONAL, // authorityCertIssuer[1] GeneralNames OPTIONAL, // authorityCertSerialNumber[2] CertificateSerialNumber OPTIONAL } // // KeyIdentifier::= OCTET STRING try { AsnValueReader reader = new AsnValueReader(rawData, AsnEncodingRules.DER); AsnValueReader aki = reader.ReadSequence(); reader.ThrowIfNotEmpty(); Asn1Tag nextTag = default; if (aki.HasData) { nextTag = aki.PeekTag(); } if (nextTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { _keyIdentifier = aki.ReadOctetString(nextTag); if (aki.HasData) { nextTag = aki.PeekTag(); } } if (nextTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { byte[] rawIssuer = aki.PeekEncodedValue().ToArray(); _rawIssuer = rawIssuer; AsnValueReader generalNames = aki.ReadSequence(nextTag); bool foundIssuer = false; // Walk all of the entities to make sure they decode legally, so no early abort. while (generalNames.HasData) { GeneralNameAsn.Decode(ref generalNames, rawIssuer, out GeneralNameAsn decoded); if (decoded.DirectoryName.HasValue) { if (!foundIssuer) { // Only ever try reading the first one. // Don't just use a null check or we would load the last of an odd number. foundIssuer = true; _simpleIssuer = new X500DistinguishedName( decoded.DirectoryName.GetValueOrDefault().Span); } else { _simpleIssuer = null; } } } if (aki.HasData) { nextTag = aki.PeekTag(); } } if (nextTag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) { _serialNumber = aki.ReadIntegerBytes(nextTag).ToArray(); } aki.ThrowIfNotEmpty(); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } _decoded = true; }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out OriginatorPublicKeyAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out MessageImprint decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out EnvelopedDataAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
private bool ProcessResponse( ReadOnlyMemory <byte> source, [NotNullWhen(true)] out Rfc3161TimestampToken?token, out Rfc3161RequestResponseStatus status, out int bytesConsumed, bool shouldThrow) { status = Rfc3161RequestResponseStatus.Unknown; token = null; Rfc3161TimeStampResp resp; try { AsnValueReader reader = new AsnValueReader(source.Span, AsnEncodingRules.DER); int localBytesRead = reader.PeekEncodedValue().Length; Rfc3161TimeStampResp.Decode(ref reader, source, out resp); bytesConsumed = localBytesRead; } catch (CryptographicException) when(!shouldThrow) { bytesConsumed = 0; status = Rfc3161RequestResponseStatus.DoesNotParse; return(false); } // bytesRead will be set past this point PkiStatus pkiStatus = (PkiStatus)resp.Status.Status; if (pkiStatus != PkiStatus.Granted && pkiStatus != PkiStatus.GrantedWithMods) { if (shouldThrow) { throw new CryptographicException( SR.Format( SR.Cryptography_TimestampReq_Failure, pkiStatus, resp.Status.FailInfo.GetValueOrDefault())); } status = Rfc3161RequestResponseStatus.RequestFailed; return(false); } if (!Rfc3161TimestampToken.TryDecode(resp.TimeStampToken.GetValueOrDefault(), out token, out _)) { if (shouldThrow) { throw new CryptographicException(SR.Cryptography_TimestampReq_BadResponse); } bytesConsumed = 0; status = Rfc3161RequestResponseStatus.DoesNotParse; return(false); } status = ValidateResponse(token, shouldThrow); return(status == Rfc3161RequestResponseStatus.Accepted); }
private static string?GetCdpUrl(SafeX509Handle cert) { ArraySegment <byte> crlDistributionPoints = OpenSslX509CertificateReader.FindFirstExtension(cert, Oids.CrlDistributionPoints); if (crlDistributionPoints.Array == null) { if (OpenSslX509ChainEventSource.Log.IsEnabled()) { OpenSslX509ChainEventSource.Log.NoCdpFound(cert); } return(null); } try { AsnValueReader reader = new AsnValueReader(crlDistributionPoints, AsnEncodingRules.DER); AsnValueReader sequenceReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { DistributionPointAsn.Decode(ref sequenceReader, crlDistributionPoints, out DistributionPointAsn distributionPoint); // Only distributionPoint is supported // Only fullName is supported, nameRelativeToCRLIssuer is for LDAP-based lookup. if (distributionPoint.DistributionPoint.HasValue && distributionPoint.DistributionPoint.Value.FullName != null) { foreach (GeneralNameAsn name in distributionPoint.DistributionPoint.Value.FullName) { if (name.Uri != null) { if (Uri.TryCreate(name.Uri, UriKind.Absolute, out Uri? uri) && uri.Scheme == "http") { return(name.Uri); } else { if (OpenSslX509ChainEventSource.Log.IsEnabled()) { OpenSslX509ChainEventSource.Log.NonHttpCdpEntry(name.Uri); } } } } if (OpenSslX509ChainEventSource.Log.IsEnabled()) { OpenSslX509ChainEventSource.Log.NoMatchingCdpEntry(); } } } } catch (CryptographicException) { // Treat any ASN errors as if the extension was missing. } catch (AsnContentException) { // Treat any ASN errors as if the extension was missing. } finally { // The data came from a certificate, so it's public. CryptoPool.Return(crlDistributionPoints.Array, clearSize: 0); } return(null); }
public static Pkcs12Info Decode( ReadOnlyMemory <byte> encodedBytes, out int bytesConsumed, bool skipCopy = false) { AsnReader reader = new AsnReader(encodedBytes, AsnEncodingRules.BER); // Trim it to the first value encodedBytes = reader.PeekEncodedValue(); ReadOnlyMemory <byte> maybeCopy = skipCopy ? encodedBytes : encodedBytes.ToArray(); PfxAsn pfx = PfxAsn.Decode(maybeCopy, AsnEncodingRules.BER); // https://tools.ietf.org/html/rfc7292#section-4 only defines version 3. if (pfx.Version != 3) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } ReadOnlyMemory <byte> authSafeBytes = ReadOnlyMemory <byte> .Empty; Pkcs12IntegrityMode mode = Pkcs12IntegrityMode.Unknown; if (pfx.AuthSafe.ContentType == Oids.Pkcs7Data) { authSafeBytes = PkcsHelpers.DecodeOctetStringAsMemory(pfx.AuthSafe.Content); if (pfx.MacData.HasValue) { mode = Pkcs12IntegrityMode.Password; } else { mode = Pkcs12IntegrityMode.None; } } else if (pfx.AuthSafe.ContentType == Oids.Pkcs7Signed) { SignedDataAsn signedData = SignedDataAsn.Decode(pfx.AuthSafe.Content, AsnEncodingRules.BER); mode = Pkcs12IntegrityMode.PublicKey; if (signedData.EncapContentInfo.ContentType == Oids.Pkcs7Data) { authSafeBytes = signedData.EncapContentInfo.Content.GetValueOrDefault(); } if (pfx.MacData.HasValue) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } } if (mode == Pkcs12IntegrityMode.Unknown) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } List <ContentInfoAsn> authSafeData = new List <ContentInfoAsn>(); AsnValueReader authSafeReader = new AsnValueReader(authSafeBytes.Span, AsnEncodingRules.BER); AsnValueReader sequenceReader = authSafeReader.ReadSequence(); authSafeReader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { ContentInfoAsn.Decode(ref sequenceReader, authSafeBytes, out ContentInfoAsn contentInfo); authSafeData.Add(contentInfo); } ReadOnlyCollection <Pkcs12SafeContents> authSafe; if (authSafeData.Count == 0) { authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(Array.Empty <Pkcs12SafeContents>()); } else { Pkcs12SafeContents[] contentsArray = new Pkcs12SafeContents[authSafeData.Count]; for (int i = 0; i < contentsArray.Length; i++) { contentsArray[i] = new Pkcs12SafeContents(authSafeData[i]); } authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(contentsArray); } bytesConsumed = encodedBytes.Length; return(new Pkcs12Info { AuthenticatedSafe = authSafe, IntegrityMode = mode, _decoded = pfx, _authSafeContents = authSafeBytes, }); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out BasicConstraintsAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out PolicyInformation decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out Rfc3161TstInfo decoded) { decoded = default; AsnValueReader sequenceReader = reader.ReadSequence(expectedTag); AsnValueReader explicitReader; AsnValueReader defaultReader; AsnValueReader collectionReader; ReadOnlySpan <byte> rebindSpan = rebind.Span; int offset; ReadOnlySpan <byte> tmpSpan; if (!sequenceReader.TryReadInt32(out decoded.Version)) { sequenceReader.ThrowIfNotEmpty(); } decoded.Policy = sequenceReader.ReadObjectIdentifier(); System.Security.Cryptography.Pkcs.Asn1.MessageImprint.Decode(ref sequenceReader, rebind, out decoded.MessageImprint); tmpSpan = sequenceReader.ReadIntegerBytes(); decoded.SerialNumber = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); decoded.GenTime = sequenceReader.ReadGeneralizedTime(); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence)) { System.Security.Cryptography.Pkcs.Asn1.Rfc3161Accuracy tmpAccuracy; System.Security.Cryptography.Pkcs.Asn1.Rfc3161Accuracy.Decode(ref sequenceReader, rebind, out tmpAccuracy); decoded.Accuracy = tmpAccuracy; } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean)) { decoded.Ordering = sequenceReader.ReadBoolean(); } else { defaultReader = new AsnValueReader(DefaultOrdering, AsnEncodingRules.DER); decoded.Ordering = defaultReader.ReadBoolean(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Integer)) { tmpSpan = sequenceReader.ReadIntegerBytes(); decoded.Nonce = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); System.Security.Cryptography.Asn1.GeneralNameAsn tmpTsa; System.Security.Cryptography.Asn1.GeneralNameAsn.Decode(ref explicitReader, rebind, out tmpTsa); decoded.Tsa = tmpTsa; explicitReader.ThrowIfNotEmpty(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { // Decode SEQUENCE OF for Extensions { collectionReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>(); System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.Extensions = tmpList.ToArray(); } } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out SignedDataAsn decoded) { decoded = default; AsnValueReader sequenceReader = reader.ReadSequence(expectedTag); AsnValueReader collectionReader; ReadOnlySpan <byte> rebindSpan = rebind.Span; int offset; ReadOnlySpan <byte> tmpSpan; if (!sequenceReader.TryReadInt32(out decoded.Version)) { sequenceReader.ThrowIfNotEmpty(); } // Decode SEQUENCE OF for DigestAlgorithms { collectionReader = sequenceReader.ReadSetOf(); var tmpList = new List <System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn>(); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.DigestAlgorithms = tmpList.ToArray(); } System.Security.Cryptography.Pkcs.Asn1.EncapsulatedContentInfoAsn.Decode(ref sequenceReader, rebind, out decoded.EncapContentInfo); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { // Decode SEQUENCE OF for CertificateSet { collectionReader = sequenceReader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0)); var tmpList = new List <System.Security.Cryptography.Pkcs.Asn1.CertificateChoiceAsn>(); System.Security.Cryptography.Pkcs.Asn1.CertificateChoiceAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Pkcs.Asn1.CertificateChoiceAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.CertificateSet = tmpList.ToArray(); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { // Decode SEQUENCE OF for Crls { collectionReader = sequenceReader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 1)); var tmpList = new List <ReadOnlyMemory <byte> >(); ReadOnlyMemory <byte> tmpItem; while (collectionReader.HasData) { tmpSpan = collectionReader.ReadEncodedValue(); tmpItem = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); tmpList.Add(tmpItem); } decoded.Crls = tmpList.ToArray(); } } // Decode SEQUENCE OF for SignerInfos { collectionReader = sequenceReader.ReadSetOf(); var tmpList = new List <System.Security.Cryptography.Pkcs.Asn1.SignerInfoAsn>(); System.Security.Cryptography.Pkcs.Asn1.SignerInfoAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Pkcs.Asn1.SignerInfoAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.SignerInfos = tmpList.ToArray(); } sequenceReader.ThrowIfNotEmpty(); }
private string?FormatSubjectAlternativeName(byte[] rawData) { // Because SubjectAlternativeName is a commonly parsed structure, we'll // specifically format this one. And we'll match the OpenSSL format, which // includes not localizing any of the values (or respecting the multiLine boolean) // // The intent here is to be functionally equivalent to OpenSSL GENERAL_NAME_print. try { StringBuilder output = new StringBuilder(); AsnValueReader reader = new AsnValueReader(rawData, AsnEncodingRules.DER); AsnValueReader collectionReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (collectionReader.HasData) { GeneralNameAsn.Decode(ref collectionReader, rawData, out GeneralNameAsn generalName); if (output.Length != 0) { output.Append(", "); } if (generalName.OtherName.HasValue) { output.Append("othername:<unsupported>"); } else if (generalName.Rfc822Name != null) { output.Append("email:"); output.Append(generalName.Rfc822Name); } else if (generalName.DnsName != null) { output.Append("DNS:"); output.Append(generalName.DnsName); } else if (generalName.X400Address != null) { output.Append("X400Name:<unsupported>"); } else if (generalName.DirectoryName != null) { // OpenSSL supports printing one of these, but the logic lives in X509Certificates, // and it isn't very common. So we'll skip this one until someone asks for it. output.Append("DirName:<unsupported>"); } else if (generalName.EdiPartyName != null) { output.Append("EdiPartyName:<unsupported>"); } else if (generalName.Uri != null) { output.Append("URI:"); output.Append(generalName.Uri); } else if (generalName.IPAddress.HasValue) { ReadOnlySpan <byte> ipAddressBytes = generalName.IPAddress.Value.Span; output.Append("IP Address"); if (ipAddressBytes.Length == 4) { // Add the colon and dotted-decimal representation of IPv4. output.Append( $":{ipAddressBytes[0]}.{ipAddressBytes[1]}.{ipAddressBytes[2]}.{ipAddressBytes[3]}"); } else if (ipAddressBytes.Length == 16) { // Print the IP Address value as colon separated UInt16 hex values without leading zeroes. // 20 01 0D B8 AC 10 FE 01 00 00 00 00 00 00 00 00 // // IP Address:2001:DB8:AC10:FE01:0:0:0:0 for (int i = 0; i < ipAddressBytes.Length; i += 2) { output.Append($":{ipAddressBytes[i] << 8 | ipAddressBytes[i + 1]:X}"); } } else { output.Append(":<invalid>"); } } else if (generalName.RegisteredId != null) { output.Append("Registered ID:"); output.Append(generalName.RegisteredId); } else { // A new extension to GeneralName could legitimately hit this, // but it's correct to say that until we know what that is that // the pretty-print has failed, and we should fall back to hex. // // But it could also simply be poorly encoded user data. return(null); } } return(output.ToString()); } catch (AsnContentException) { return(null); } }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out EncapsulatedContentInfoAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out AccessDescriptionAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
private static List <Pkcs12SafeBag> ReadBags(ReadOnlyMemory <byte> serialized) { List <SafeBagAsn> serializedBags = new List <SafeBagAsn>(); try { AsnValueReader reader = new AsnValueReader(serialized.Span, AsnEncodingRules.BER); AsnValueReader sequenceReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { SafeBagAsn.Decode(ref sequenceReader, serialized, out SafeBagAsn serializedBag); serializedBags.Add(serializedBag); } if (serializedBags.Count == 0) { return(new List <Pkcs12SafeBag>(0)); } } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } List <Pkcs12SafeBag> bags = new List <Pkcs12SafeBag>(serializedBags.Count); for (int i = 0; i < serializedBags.Count; i++) { ReadOnlyMemory <byte> bagValue = serializedBags[i].BagValue; Pkcs12SafeBag? bag = null; try { switch (serializedBags[i].BagId) { case Oids.Pkcs12KeyBag: bag = new Pkcs12KeyBag(bagValue); break; case Oids.Pkcs12ShroudedKeyBag: bag = new Pkcs12ShroudedKeyBag(bagValue); break; case Oids.Pkcs12CertBag: bag = Pkcs12CertBag.DecodeValue(bagValue); break; case Oids.Pkcs12CrlBag: // Known, but no first-class support currently. break; case Oids.Pkcs12SecretBag: bag = Pkcs12SecretBag.DecodeValue(bagValue); break; case Oids.Pkcs12SafeContentsBag: bag = Pkcs12SafeContentsBag.Decode(bagValue); break; } } catch (AsnContentException) { } catch (CryptographicException) { } if (bag == null) { bag = new Pkcs12SafeBag.UnknownBag(serializedBags[i].BagId, bagValue); } bag.Attributes = SignerInfo.MakeAttributeCollection(serializedBags[i].BagAttributes); bags.Add(bag); } return(bags); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out IssuerAndSerialNumberAsn decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out Rfc3161Accuracy decoded) { Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded); }
/// <summary> /// Decodes the specified Certificate Revocation List (CRL) and produces /// a <see cref="CertificateRevocationListBuilder" /> with all of the revocation /// entries from the decoded CRL. /// </summary> /// <param name="currentCrl"> /// The DER-encoded CRL to decode. /// </param> /// <param name="currentCrlNumber"> /// When this method returns, contains the CRL sequence number from the decoded CRL. /// This parameter is treated as uninitialized. /// </param> /// <param name="bytesConsumed"> /// When this method returns, contains the number of bytes that were read from /// <paramref name="currentCrl"/> while decoding. /// </param> /// <returns> /// A new builder that has the same revocation entries as the decoded CRL. /// </returns> /// <exception cref="CryptographicException"> /// <paramref name="currentCrl" /> could not be decoded. /// </exception> public static CertificateRevocationListBuilder Load( ReadOnlySpan <byte> currentCrl, out BigInteger currentCrlNumber, out int bytesConsumed) { List <RevokedCertificate> list = new(); BigInteger crlNumber = 0; int payloadLength; try { AsnValueReader reader = new AsnValueReader(currentCrl, AsnEncodingRules.DER); payloadLength = reader.PeekEncodedValue().Length; AsnValueReader certificateList = reader.ReadSequence(); AsnValueReader tbsCertList = certificateList.ReadSequence(); AlgorithmIdentifierAsn.Decode(ref certificateList, ReadOnlyMemory <byte> .Empty, out _); if (!certificateList.TryReadPrimitiveBitString(out _, out _)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } certificateList.ThrowIfNotEmpty(); int version = 0; if (tbsCertList.PeekTag().HasSameClassAndValue(Asn1Tag.Integer)) { // https://datatracker.ietf.org/doc/html/rfc5280#section-5.1 says the only // version values are v1 (0) and v2 (1). // // Since v1 (0) is supposed to not write down the version value, v2 (1) is the // only legal value to read. if (!tbsCertList.TryReadInt32(out version) || version != 1) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } } AlgorithmIdentifierAsn.Decode(ref tbsCertList, ReadOnlyMemory <byte> .Empty, out _); // X500DN tbsCertList.ReadSequence(); // thisUpdate ReadX509Time(ref tbsCertList); // nextUpdate ReadX509TimeOpt(ref tbsCertList); AsnValueReader revokedCertificates = default; if (tbsCertList.HasData && tbsCertList.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence)) { revokedCertificates = tbsCertList.ReadSequence(); } if (version > 0 && tbsCertList.HasData) { AsnValueReader crlExtensionsExplicit = tbsCertList.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); AsnValueReader crlExtensions = crlExtensionsExplicit.ReadSequence(); crlExtensionsExplicit.ThrowIfNotEmpty(); while (crlExtensions.HasData) { AsnValueReader extension = crlExtensions.ReadSequence(); Oid? extnOid = Oids.GetSharedOrNullOid(ref extension); if (extnOid is null) { extension.ReadObjectIdentifier(); } if (extension.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean)) { extension.ReadBoolean(); } if (!extension.TryReadPrimitiveOctetString(out ReadOnlySpan <byte> extnValue)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } // Since we're only matching against OIDs that come from GetSharedOrNullOid // we can use ReferenceEquals and skip the Value string equality check in // the Oid.ValueEquals extension method (as it will always be preempted by // the ReferenceEquals or will evaulate to false). if (ReferenceEquals(extnOid, Oids.CrlNumberOid)) { AsnValueReader crlNumberReader = new AsnValueReader( extnValue, AsnEncodingRules.DER); crlNumber = crlNumberReader.ReadInteger(); crlNumberReader.ThrowIfNotEmpty(); } } } tbsCertList.ThrowIfNotEmpty(); while (revokedCertificates.HasData) { RevokedCertificate revokedCertificate = new RevokedCertificate(ref revokedCertificates, version); list.Add(revokedCertificate); } } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } bytesConsumed = payloadLength; currentCrlNumber = crlNumber; return(new CertificateRevocationListBuilder(list)); }
private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out TbsCertificateAsn decoded) { decoded = default; AsnValueReader sequenceReader = reader.ReadSequence(expectedTag); AsnValueReader explicitReader; AsnValueReader defaultReader; AsnValueReader collectionReader; ReadOnlySpan <byte> rebindSpan = rebind.Span; int offset; ReadOnlySpan <byte> tmpSpan; if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); if (!explicitReader.TryReadInt32(out decoded.Version)) { explicitReader.ThrowIfNotEmpty(); } explicitReader.ThrowIfNotEmpty(); } else { defaultReader = new AsnValueReader(DefaultVersion, AsnEncodingRules.DER); if (!defaultReader.TryReadInt32(out decoded.Version)) { defaultReader.ThrowIfNotEmpty(); } } tmpSpan = sequenceReader.ReadIntegerBytes(); decoded.SerialNumber = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.SignatureAlgorithm); if (!sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag((UniversalTagNumber)16))) { throw new CryptographicException(); } tmpSpan = sequenceReader.ReadEncodedValue(); decoded.Issuer = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); System.Security.Cryptography.X509Certificates.Asn1.ValidityAsn.Decode(ref sequenceReader, rebind, out decoded.Validity); if (!sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag((UniversalTagNumber)16))) { throw new CryptographicException(); } tmpSpan = sequenceReader.ReadEncodedValue(); decoded.Subject = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); System.Security.Cryptography.Asn1.SubjectPublicKeyInfoAsn.Decode(ref sequenceReader, rebind, out decoded.SubjectPublicKeyInfo); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { if (sequenceReader.TryReadPrimitiveBitString(out _, out tmpSpan, new Asn1Tag(TagClass.ContextSpecific, 1))) { decoded.IssuerUniqueId = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); } else { decoded.IssuerUniqueId = sequenceReader.ReadBitString(out _, new Asn1Tag(TagClass.ContextSpecific, 1)); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) { if (sequenceReader.TryReadPrimitiveBitString(out _, out tmpSpan, new Asn1Tag(TagClass.ContextSpecific, 2))) { decoded.SubjectUniqueId = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray(); } else { decoded.SubjectUniqueId = sequenceReader.ReadBitString(out _, new Asn1Tag(TagClass.ContextSpecific, 2)); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3)); // Decode SEQUENCE OF for Extensions { collectionReader = explicitReader.ReadSequence(); var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>(); System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.Extensions = tmpList.ToArray(); } explicitReader.ThrowIfNotEmpty(); } sequenceReader.ThrowIfNotEmpty(); }
private static unsafe CertificateRequest LoadSigningRequest( ReadOnlySpan <byte> pkcs10, bool permitTrailingData, HashAlgorithmName signerHashAlgorithm, out int bytesConsumed, CertificateRequestLoadOptions options, RSASignaturePadding?signerSignaturePadding) { ArgumentException.ThrowIfNullOrEmpty(signerHashAlgorithm.Name, nameof(signerHashAlgorithm)); if ((options & ~AllOptions) != 0) { throw new ArgumentOutOfRangeException(nameof(options), options, SR.Argument_InvalidFlag); } bool skipSignatureValidation = (options & CertificateRequestLoadOptions.SkipSignatureValidation) != 0; bool unsafeLoadCertificateExtensions = (options & CertificateRequestLoadOptions.UnsafeLoadCertificateExtensions) != 0; try { AsnValueReader outer = new AsnValueReader(pkcs10, AsnEncodingRules.DER); int encodedLength = outer.PeekEncodedValue().Length; AsnValueReader pkcs10Asn = outer.ReadSequence(); CertificateRequest req; if (!permitTrailingData) { outer.ThrowIfNotEmpty(); } fixed(byte *p10ptr = pkcs10) { using (PointerMemoryManager <byte> manager = new PointerMemoryManager <byte>(p10ptr, encodedLength)) { ReadOnlyMemory <byte> rebind = manager.Memory; ReadOnlySpan <byte> encodedRequestInfo = pkcs10Asn.PeekEncodedValue(); CertificationRequestInfoAsn requestInfo; AlgorithmIdentifierAsn algorithmIdentifier; ReadOnlySpan <byte> signature; int signatureUnusedBitCount; CertificationRequestInfoAsn.Decode(ref pkcs10Asn, rebind, out requestInfo); AlgorithmIdentifierAsn.Decode(ref pkcs10Asn, rebind, out algorithmIdentifier); if (!pkcs10Asn.TryReadPrimitiveBitString(out signatureUnusedBitCount, out signature)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } pkcs10Asn.ThrowIfNotEmpty(); if (requestInfo.Version < 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } // They haven't bumped from v0 to v1 as of 2022. const int MaxSupportedVersion = 0; if (requestInfo.Version != MaxSupportedVersion) { throw new CryptographicException( SR.Format( SR.Cryptography_CertReq_Load_VersionTooNew, requestInfo.Version, MaxSupportedVersion)); } PublicKey publicKey = PublicKey.DecodeSubjectPublicKeyInfo(ref requestInfo.SubjectPublicKeyInfo); if (!skipSignatureValidation) { // None of the supported signature algorithms support signatures that are not full bytes. // So, shortcut the verification on the bit length if (signatureUnusedBitCount != 0 || !VerifyX509Signature(encodedRequestInfo, signature, publicKey, algorithmIdentifier)) { throw new CryptographicException(SR.Cryptography_CertReq_SignatureVerificationFailed); } } X500DistinguishedName subject = new X500DistinguishedName(requestInfo.Subject.Span); req = new CertificateRequest( subject, publicKey, signerHashAlgorithm, signerSignaturePadding); if (requestInfo.Attributes is not null) { bool foundCertExt = false; foreach (AttributeAsn attr in requestInfo.Attributes) { if (attr.AttrType == Oids.Pkcs9ExtensionRequest) { if (foundCertExt) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } foundCertExt = true; if (attr.AttrValues.Length != 1) { throw new CryptographicException( SR.Cryptography_CertReq_Load_DuplicateExtensionRequests); } AsnValueReader extsReader = new AsnValueReader( attr.AttrValues[0].Span, AsnEncodingRules.DER); AsnValueReader exts = extsReader.ReadSequence(); extsReader.ThrowIfNotEmpty(); // Minimum length is 1, so do..while do { X509ExtensionAsn.Decode(ref exts, rebind, out X509ExtensionAsn extAsn); if (unsafeLoadCertificateExtensions) { X509Extension ext = new X509Extension( extAsn.ExtnId, extAsn.ExtnValue.Span, extAsn.Critical); X509Extension?rich = X509Certificate2.CreateCustomExtensionIfAny(extAsn.ExtnId); if (rich is not null) { rich.CopyFrom(ext); req.CertificateExtensions.Add(rich); } else { req.CertificateExtensions.Add(ext); } } } while (exts.HasData); } else { if (attr.AttrValues.Length == 0) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } foreach (ReadOnlyMemory <byte> val in attr.AttrValues) { req.OtherRequestAttributes.Add( new AsnEncodedData(attr.AttrType, val.Span)); } } } } } } bytesConsumed = encodedLength; return(req); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } }