internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out KeyTransRecipientInfoAsn decoded)
        {
            decoded = default;
            AsnValueReader      sequenceReader = reader.ReadSequence(expectedTag);
            ReadOnlySpan <byte> rebindSpan     = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;


            if (!sequenceReader.TryReadInt32(out decoded.Version))
            {
                sequenceReader.ThrowIfNotEmpty();
            }

            RecipientIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.Rid);
            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.KeyEncryptionAlgorithm);

            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
            {
                decoded.EncryptedKey = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else
            {
                decoded.EncryptedKey = sequenceReader.ReadOctetString();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #2
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out SignerInfoAsn 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();
            }

            SignerIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.Sid);
            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.DigestAlgorithm);

            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                tmpSpan = sequenceReader.ReadEncodedValue();
                decoded.SignedAttributes    = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
                decoded.SignedAttributesSet = SignedAttributesSet.Decode(decoded.SignedAttributes.Value, AsnEncodingRules.BER);
            }

            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.SignatureAlgorithm);

            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
            {
                decoded.SignatureValue = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else
            {
                decoded.SignatureValue = sequenceReader.ReadOctetString();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                // Decode SEQUENCE OF for UnsignedAttributes
                {
                    collectionReader = sequenceReader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 1));
                    var          tmpList = new List <AttributeAsn>();
                    AttributeAsn tmpItem;

                    while (collectionReader.HasData)
                    {
                        AttributeAsn.Decode(ref collectionReader, rebind, out tmpItem);
                        tmpList.Add(tmpItem);
                    }

                    decoded.UnsignedAttributes = tmpList.ToArray();
                }
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #3
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out KeyAgreeRecipientInfoAsn decoded)
        {
            decoded = default;
            AsnValueReader      sequenceReader = reader.ReadSequence(expectedTag);
            AsnValueReader      explicitReader;
            AsnValueReader      collectionReader;
            ReadOnlySpan <byte> rebindSpan = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;


            if (!sequenceReader.TryReadInt32(out decoded.Version))
            {
                sequenceReader.ThrowIfNotEmpty();
            }


            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
            OriginatorIdentifierOrKeyAsn.Decode(ref explicitReader, rebind, out decoded.Originator);
            explicitReader.ThrowIfNotEmpty();


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));

                if (explicitReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
                {
                    decoded.Ukm = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
                }
                else
                {
                    decoded.Ukm = explicitReader.ReadOctetString();
                }

                explicitReader.ThrowIfNotEmpty();
            }

            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.KeyEncryptionAlgorithm);

            // Decode SEQUENCE OF for RecipientEncryptedKeys
            {
                collectionReader = sequenceReader.ReadSequence();
                var tmpList = new List <RecipientEncryptedKeyAsn>();
                RecipientEncryptedKeyAsn tmpItem;

                while (collectionReader.HasData)
                {
                    RecipientEncryptedKeyAsn.Decode(ref collectionReader, rebind, out tmpItem);
                    tmpList.Add(tmpItem);
                }

                decoded.RecipientEncryptedKeys = tmpList.ToArray();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #4
0
        internal byte[] ToPkcs10Request(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm)
        {
            // State validation should be runtime checks if/when this becomes public API
            Debug.Assert(signatureGenerator != null);
            Debug.Assert(Subject != null);
            Debug.Assert(PublicKey != null);

            byte[] signatureAlgorithm = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm);
            AlgorithmIdentifierAsn signatureAlgorithmAsn;

            // Deserialization also does validation of the value (except for Parameters, which have to be validated separately).
            signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER);
            if (signatureAlgorithmAsn.Parameters.HasValue)
            {
                Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value.Span);
            }

            SubjectPublicKeyInfoAsn spki = default;

            spki.Algorithm = new AlgorithmIdentifierAsn {
                Algorithm = PublicKey.Oid !.Value !, Parameters = PublicKey.EncodedParameters.RawData
            };
            spki.SubjectPublicKey = PublicKey.EncodedKeyValue.RawData;

            var attributes = new AttributeAsn[Attributes.Count];

            for (int i = 0; i < attributes.Length; i++)
            {
                attributes[i] = new AttributeAsn(Attributes[i]);
            }

            CertificationRequestInfoAsn requestInfo = new CertificationRequestInfoAsn
            {
                Version = 0,
                Subject = this.Subject.RawData,
                SubjectPublicKeyInfo = spki,
                Attributes           = attributes
            };

            AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);

            requestInfo.Encode(writer);
            byte[] encodedRequestInfo = writer.Encode();
            writer.Reset();

            CertificationRequestAsn certificationRequest = new CertificationRequestAsn
            {
                CertificationRequestInfo = requestInfo,
                SignatureAlgorithm       = signatureAlgorithmAsn,
                SignatureValue           = signatureGenerator.SignData(encodedRequestInfo, hashAlgorithm),
            };

            certificationRequest.Encode(writer);
            return(writer.Encode());
        }
    }
Пример #5
0
        static EssCertIdV2()
        {
            EssCertIdV2           decoded = default;
            ReadOnlyMemory <byte> rebind  = default;
            AsnValueReader        reader;

            reader = new AsnValueReader(DefaultHashAlgorithm, AsnEncodingRules.DER);
            AlgorithmIdentifierAsn.Decode(ref reader, rebind, out decoded.HashAlgorithm);
            reader.ThrowIfNotEmpty();
        }
Пример #6
0
        internal byte[] ToPkcs10Request(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm)
        {
            // State validation should be runtime checks if/when this becomes public API
            Debug.Assert(signatureGenerator != null);
            Debug.Assert(Subject != null);
            Debug.Assert(PublicKey != null);

            byte[] signatureAlgorithm = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm);
            AlgorithmIdentifierAsn signatureAlgorithmAsn;

            // Deserialization also does validation of the value (except for Parameters, which have to be validated separately).
            signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER);
            if (signatureAlgorithmAsn.Parameters.HasValue)
            {
                Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value);
            }

            SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn();

            spki.Algorithm = new AlgorithmIdentifierAsn {
                Algorithm = PublicKey.Oid, Parameters = PublicKey.EncodedParameters.RawData
            };
            spki.SubjectPublicKey = PublicKey.EncodedKeyValue.RawData;

            CertificationRequestInfoAsn requestInfo = new CertificationRequestInfoAsn
            {
                Version = 0,
                Subject = this.Subject.RawData,
                SubjectPublicKeyInfo = spki,
                Attributes           = Attributes.Select(a => new AttributeAsn(a)).ToArray(),
            };

            using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
                using (AsnWriter signedWriter = new AsnWriter(AsnEncodingRules.DER))
                {
                    requestInfo.Encode(writer);

                    byte[] encodedRequestInfo = writer.Encode();
                    CertificationRequestAsn certificationRequest = new CertificationRequestAsn
                    {
                        CertificationRequestInfo = requestInfo,
                        SignatureAlgorithm       = signatureAlgorithmAsn,
                        SignatureValue           = signatureGenerator.SignData(encodedRequestInfo, hashAlgorithm),
                    };

                    certificationRequest.Encode(signedWriter);
                    return(signedWriter.Encode());
                }
        }
        /// <summary>
        /// Sign the current certificate request to create a chain-signed or self-signed certificate.
        /// </summary>
        /// <param name="issuerName">The X500DistinguishedName for the Issuer</param>
        /// <param name="generator">
        ///   An <see cref="X509SignatureGenerator"/> representing the issuing certificate authority.
        /// </param>
        /// <param name="notBefore">
        ///   The oldest date and time where this certificate is considered valid.
        ///   Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds.
        /// </param>
        /// <param name="notAfter">
        ///   The date and time where this certificate is no longer considered valid.
        /// </param>
        /// <param name="serialNumber">
        ///   The serial number to use for the new certificate. This value should be unique per issuer.
        ///   The value is interpreted as an unsigned (big) integer in big endian byte ordering.
        /// </param>
        /// <returns>
        ///   An <see cref="X509Certificate2"/> with the specified values. The returned object will
        ///   not assert <see cref="X509Certificate2.HasPrivateKey" />.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="issuerName"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="generator"/> is null.</exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="notAfter"/> represents a date and time before <paramref name="notBefore"/>.
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="serialNumber"/> has length 0.</exception>
        /// <exception cref="CryptographicException">Any error occurs during the signing operation.</exception>
        public X509Certificate2 Create(
            X500DistinguishedName issuerName,
            X509SignatureGenerator generator,
            DateTimeOffset notBefore,
            DateTimeOffset notAfter,
            ReadOnlySpan <byte> serialNumber)
        {
            if (issuerName == null)
            {
                throw new ArgumentNullException(nameof(issuerName));
            }
            if (generator == null)
            {
                throw new ArgumentNullException(nameof(generator));
            }
            if (notAfter < notBefore)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed);
            }
            if (serialNumber == null || serialNumber.Length < 1)
            {
                throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(serialNumber));
            }

            byte[] signatureAlgorithm = generator.GetSignatureAlgorithmIdentifier(HashAlgorithm);
            AlgorithmIdentifierAsn signatureAlgorithmAsn;

            // Deserialization also does validation of the value (except for Parameters, which have to be validated separately).
            signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER);
            if (signatureAlgorithmAsn.Parameters.HasValue)
            {
                Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value);
            }

            ArraySegment <byte> normalizedSerial = NormalizeSerialNumber(serialNumber);

            TbsCertificateAsn tbsCertificate = new TbsCertificateAsn
            {
                Version              = 2,
                SerialNumber         = normalizedSerial,
                SignatureAlgorithm   = signatureAlgorithmAsn,
                Issuer               = issuerName.RawData,
                SubjectPublicKeyInfo = new SubjectPublicKeyInfoAsn
                {
                    Algorithm = new AlgorithmIdentifierAsn
                    {
                        Algorithm  = PublicKey.Oid !.Value !,
                        Parameters = PublicKey.EncodedParameters.RawData,
                    },
Пример #8
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out EssCertIdV2 decoded)
        {
            decoded = default;
            AsnValueReader      sequenceReader = reader.ReadSequence(expectedTag);
            AsnValueReader      defaultReader;
            ReadOnlySpan <byte> rebindSpan = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence))
            {
                AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.HashAlgorithm);
            }
            else
            {
                defaultReader = new AsnValueReader(DefaultHashAlgorithm, AsnEncodingRules.DER);
                AlgorithmIdentifierAsn.Decode(ref defaultReader, rebind, out decoded.HashAlgorithm);
            }


            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
            {
                decoded.Hash = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else
            {
                decoded.Hash = sequenceReader.ReadOctetString();
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence))
            {
                CadesIssuerSerial tmpIssuerSerial;
                CadesIssuerSerial.Decode(ref sequenceReader, rebind, out tmpIssuerSerial);
                decoded.IssuerSerial = tmpIssuerSerial;
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #9
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out KEKRecipientInfoAsn decoded)
        {
            decoded = default;
            KEKIdentifierAsn       kekIdentifier;
            AlgorithmIdentifierAsn algIdentifier;
            AsnValueReader         sequenceReader = reader.ReadSequence(expectedTag);
            int version;

            if (sequenceReader.TryReadInt32(out version))
            {
                decoded.Version = version;
            }


            KEKIdentifierAsn.Decode(ref sequenceReader, Asn1Tag.Sequence, rebind, out kekIdentifier);
            AlgorithmIdentifierAsn.Decode(ref sequenceReader, Asn1Tag.Sequence, rebind, out algIdentifier);
            var encryptedKey = sequenceReader.ReadOctetString();

            decoded.KEKId            = kekIdentifier;
            decoded.KeyEncryptionAlg = algIdentifier;
            decoded.EncryptedKey     = encryptedKey;
        }
Пример #10
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out OriginatorPublicKeyAsn decoded)
        {
            decoded = default;
            AsnValueReader      sequenceReader = reader.ReadSequence(expectedTag);
            ReadOnlySpan <byte> rebindSpan     = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;

            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.Algorithm);

            if (sequenceReader.TryReadPrimitiveBitStringValue(out _, out tmpSpan))
            {
                decoded.PublicKey = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else
            {
                decoded.PublicKey = sequenceReader.ReadBitString(out _);
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #11
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out MessageImprint decoded)
        {
            decoded = default;
            AsnValueReader      sequenceReader = reader.ReadSequence(expectedTag);
            ReadOnlySpan <byte> rebindSpan     = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;

            AlgorithmIdentifierAsn.Decode(ref sequenceReader, rebind, out decoded.HashAlgorithm);

            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
            {
                decoded.HashedMessage = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else
            {
                decoded.HashedMessage = sequenceReader.ReadOctetString();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
        public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out CmsAlgorithmProtectAttributeAsn decoded)
        {
            var sequence = reader.ReadSequence();

            decoded = default;
            AlgorithmIdentifierAsn digestAlgorithm;

            AlgorithmIdentifierAsn.Decode(ref sequence, rebind, out digestAlgorithm);
            decoded.DigestAlgorithm = digestAlgorithm;
            Asn1Tag tag = sequence.PeekTag();

            if (tag.TagValue == 1 && tag.TagClass == TagClass.ContextSpecific)
            {
                AlgorithmIdentifierAsn sigAlg;
                AlgorithmIdentifierAsn.Decode(ref sequence, new Asn1Tag(TagClass.ContextSpecific, 1), rebind, out sigAlg);
                decoded.SignatureAlgorithm = sigAlg;
            }
            else
            {
                AlgorithmIdentifierAsn macAlg;
                AlgorithmIdentifierAsn.Decode(ref sequence, new Asn1Tag(TagClass.ContextSpecific, 2), rebind, out macAlg);
                decoded.MacAlgorithm = macAlg;
            }
        }
Пример #13
0
        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 <AlgorithmIdentifierAsn>();
                AlgorithmIdentifierAsn tmpItem;

                while (collectionReader.HasData)
                {
                    AlgorithmIdentifierAsn.Decode(ref collectionReader, rebind, out tmpItem);
                    tmpList.Add(tmpItem);
                }

                decoded.DigestAlgorithms = tmpList.ToArray();
            }

            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 <CertificateChoiceAsn>();
                    CertificateChoiceAsn tmpItem;

                    while (collectionReader.HasData)
                    {
                        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 <SignerInfoAsn>();
                SignerInfoAsn tmpItem;

                while (collectionReader.HasData)
                {
                    SignerInfoAsn.Decode(ref collectionReader, rebind, out tmpItem);
                    tmpList.Add(tmpItem);
                }

                decoded.SignerInfos = tmpList.ToArray();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
Пример #14
0
        public static bool TryGetRsaOaepEncryptionPadding(
            ReadOnlyMemory <byte>?parameters,
            out RSAEncryptionPadding rsaEncryptionPadding,
            out Exception exception)
        {
            exception            = null;
            rsaEncryptionPadding = null;

            if (parameters == null || parameters.Value.IsEmpty)
            {
                exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                return(false);
            }

            try
            {
                OaepParamsAsn oaepParameters = OaepParamsAsn.Decode(parameters.Value, AsnEncodingRules.DER);

                if (oaepParameters.MaskGenFunc.Algorithm.Value != Oids.Mgf1 ||
                    oaepParameters.MaskGenFunc.Parameters == null ||
                    oaepParameters.PSourceFunc.Algorithm.Value != Oids.PSpecified
                    )
                {
                    exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    return(false);
                }

                AlgorithmIdentifierAsn mgf1AlgorithmIdentifier = AlgorithmIdentifierAsn.Decode(oaepParameters.MaskGenFunc.Parameters.Value, AsnEncodingRules.DER);

                if (mgf1AlgorithmIdentifier.Algorithm.Value != oaepParameters.HashFunc.Algorithm.Value)
                {
                    exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    return(false);
                }

                if (oaepParameters.PSourceFunc.Parameters != null &&
                    !oaepParameters.PSourceFunc.Parameters.Value.Span.SequenceEqual(s_pSpecifiedDefaultParameters))
                {
                    exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    return(false);
                }

                switch (oaepParameters.HashFunc.Algorithm.Value)
                {
                case Oids.Sha1:
                    rsaEncryptionPadding = RSAEncryptionPadding.OaepSHA1;
                    return(true);

                case Oids.Sha256:
                    rsaEncryptionPadding = RSAEncryptionPadding.OaepSHA256;
                    return(true);

                case Oids.Sha384:
                    rsaEncryptionPadding = RSAEncryptionPadding.OaepSHA384;
                    return(true);

                case Oids.Sha512:
                    rsaEncryptionPadding = RSAEncryptionPadding.OaepSHA512;
                    return(true);

                default:
                    exception = new CryptographicException(
                        SR.Cryptography_Cms_UnknownAlgorithm,
                        oaepParameters.HashFunc.Algorithm.Value);
                    return(false);
                }
            }
            catch (CryptographicException e)
            {
                exception = e;
                return(false);
            }
        }
Пример #15
0
        /// <summary>
        /// Sign the current certificate request to create a chain-signed or self-signed certificate.
        /// </summary>
        /// <param name="issuerName">The X500DistinguishedName for the Issuer</param>
        /// <param name="generator">
        ///   An <see cref="X509SignatureGenerator"/> representing the issuing certificate authority.
        /// </param>
        /// <param name="notBefore">
        ///   The oldest date and time where this certificate is considered valid.
        ///   Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds.
        /// </param>
        /// <param name="notAfter">
        ///   The date and time where this certificate is no longer considered valid.
        /// </param>
        /// <param name="serialNumber">
        ///   The serial number to use for the new certificate. This value should be unique per issuer.
        ///   The value is interpreted as an unsigned (big) integer in big endian byte ordering.
        /// </param>
        /// <returns>
        ///   The ASN.1 DER-encoded certificate, suitable to be passed to <see cref="X509Certificate2(byte[])"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="issuerName"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="generator"/> is null.</exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="notAfter"/> represents a date and time before <paramref name="notBefore"/>.
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="serialNumber"/> is null or has length 0.</exception>
        /// <exception cref="CryptographicException">Any error occurs during the signing operation.</exception>
        public X509Certificate2 Create(
            X500DistinguishedName issuerName,
            X509SignatureGenerator generator,
            DateTimeOffset notBefore,
            DateTimeOffset notAfter,
            byte[] serialNumber)
        {
            if (issuerName == null)
            {
                throw new ArgumentNullException(nameof(issuerName));
            }
            if (generator == null)
            {
                throw new ArgumentNullException(nameof(generator));
            }
            if (notAfter < notBefore)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed);
            }
            if (serialNumber == null || serialNumber.Length < 1)
            {
                throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(serialNumber));
            }

            byte[] signatureAlgorithm = generator.GetSignatureAlgorithmIdentifier(HashAlgorithm);
            AlgorithmIdentifierAsn signatureAlgorithmAsn;

            // Deserialization also does validation of the value (except for Parameters, which have to be validated separately).
            signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgorithm, AsnEncodingRules.DER);
            if (signatureAlgorithmAsn.Parameters.HasValue)
            {
                Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.Value);
            }

            TbsCertificateAsn tbsCertificate = new TbsCertificateAsn
            {
                Version              = 2,
                SerialNumber         = NormalizeSerialNumber(serialNumber),
                SignatureAlgorithm   = signatureAlgorithmAsn,
                Issuer               = issuerName.RawData,
                SubjectPublicKeyInfo = new SubjectPublicKeyInfoAsn
                {
                    Algorithm = new AlgorithmIdentifierAsn
                    {
                        Algorithm  = PublicKey.Oid,
                        Parameters = PublicKey.EncodedParameters.RawData,
                    },
                    SubjectPublicKey = PublicKey.EncodedKeyValue.RawData,
                },
                Validity = new ValidityAsn(notBefore, notAfter),
                Subject  = SubjectName.RawData,
            };

            if (CertificateExtensions.Count > 0)
            {
                HashSet <string>        usedOids      = new HashSet <string>(CertificateExtensions.Count);
                List <X509ExtensionAsn> extensionAsns = new List <X509ExtensionAsn>(CertificateExtensions.Count);

                // An interesting quirk of skipping null values here is that
                // Extensions.Count == 0 => no extensions
                // Extensions.ContainsOnly(null) => empty extensions list

                foreach (X509Extension extension in CertificateExtensions)
                {
                    if (extension == null)
                    {
                        continue;
                    }

                    if (!usedOids.Add(extension.Oid.Value))
                    {
                        throw new InvalidOperationException(
                                  SR.Format(SR.Cryptography_CertReq_DuplicateExtension, extension.Oid.Value));
                    }

                    extensionAsns.Add(new X509ExtensionAsn(extension));
                }

                tbsCertificate.Extensions = extensionAsns.ToArray();
            }

            using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
                using (AsnWriter signedWriter = new AsnWriter(AsnEncodingRules.DER))
                {
                    tbsCertificate.Encode(writer);

                    byte[]         encodedTbsCertificate = writer.Encode();
                    CertificateAsn certificate           = new CertificateAsn
                    {
                        TbsCertificate     = tbsCertificate,
                        SignatureAlgorithm = signatureAlgorithmAsn,
                        SignatureValue     = generator.SignData(encodedTbsCertificate, HashAlgorithm),
                    };

                    certificate.Encode(signedWriter);
                    return(new X509Certificate2(signedWriter.Encode()));
                }
        }
        private byte[] Build(
            X500DistinguishedName issuerName,
            X509SignatureGenerator generator,
            BigInteger crlNumber,
            DateTimeOffset nextUpdate,
            DateTimeOffset thisUpdate,
            HashAlgorithmName hashAlgorithm,
            X509AuthorityKeyIdentifierExtension authorityKeyIdentifier)
        {
            ArgumentNullException.ThrowIfNull(issuerName);
            ArgumentNullException.ThrowIfNull(generator);

            if (crlNumber < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(crlNumber), SR.ArgumentOutOfRange_NeedNonNegNum);
            }
            if (nextUpdate <= thisUpdate)
            {
                throw new ArgumentException(SR.Cryptography_CRLBuilder_DatesReversed);
            }

            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
            ArgumentNullException.ThrowIfNull(authorityKeyIdentifier);

            byte[] signatureAlgId = generator.GetSignatureAlgorithmIdentifier(hashAlgorithm);

            {
                AlgorithmIdentifierAsn signatureAlgorithmAsn;

                // Deserialization also does validation of the value (except for Parameters,
                // which have to be validated separately).
                signatureAlgorithmAsn = AlgorithmIdentifierAsn.Decode(signatureAlgId, AsnEncodingRules.DER);

                if (signatureAlgorithmAsn.Parameters.HasValue)
                {
                    Helpers.ValidateDer(signatureAlgorithmAsn.Parameters.GetValueOrDefault().Span);
                }
            }

            AsnWriter writer = (_writer ??= new AsnWriter(AsnEncodingRules.DER));

            writer.Reset();

            // TBSCertList
            using (writer.PushSequence())
            {
                // version v2(1)
                writer.WriteInteger(1);

                // signature (AlgorithmIdentifier)
                writer.WriteEncodedValue(signatureAlgId);

                // issuer
                writer.WriteEncodedValue(issuerName.RawData);

                // thisUpdate
                WriteX509Time(writer, thisUpdate);

                // nextUpdate
                WriteX509Time(writer, nextUpdate);

                // revokedCertificates (don't write down if empty)
                if (_revoked.Count > 0)
                {
                    // SEQUENCE OF
                    using (writer.PushSequence())
                    {
                        foreach (RevokedCertificate revoked in _revoked)
                        {
                            // Anonymous CRL Entry type
                            using (writer.PushSequence())
                            {
                                writer.WriteInteger(revoked.Serial);
                                WriteX509Time(writer, revoked.RevocationTime);

                                if (revoked.Extensions is not null)
                                {
                                    writer.WriteEncodedValue(revoked.Extensions);
                                }
                            }
                        }
                    }
                }

                // extensions [0] EXPLICIT Extensions
                using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 0)))
                {
                    // Extensions (SEQUENCE OF)
                    using (writer.PushSequence())
                    {
                        // Authority Key Identifier Extension
                        using (writer.PushSequence())
                        {
                            writer.WriteObjectIdentifier(authorityKeyIdentifier.Oid !.Value !);

                            if (authorityKeyIdentifier.Critical)
                            {
                                writer.WriteBoolean(true);
                            }

                            byte[] encodedAkid = authorityKeyIdentifier.RawData;
                            Helpers.ValidateDer(encodedAkid);
                            writer.WriteOctetString(encodedAkid);
                        }

                        // CRL Number Extension
                        using (writer.PushSequence())
                        {
                            writer.WriteObjectIdentifier(Oids.CrlNumber);

                            using (writer.PushOctetString())
                            {
                                writer.WriteInteger(crlNumber);
                            }
                        }
                    }
                }
            }

            byte[] tbsCertList = writer.Encode();
            writer.Reset();

            byte[] signature = generator.SignData(tbsCertList, hashAlgorithm);

            // CertificateList
            using (writer.PushSequence())
            {
                writer.WriteEncodedValue(tbsCertList);
                writer.WriteEncodedValue(signatureAlgId);
                writer.WriteBitString(signature);
            }

            byte[] crl = writer.Encode();
            return(crl);
        }
Пример #17
0
        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);
            }
        }
Пример #18
0
        /// <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));
        }