public static void LoadBigExponentRequest_PemString(CertificateRequestLoadOptions options, bool multiPem)
        {
            string pem = TestData.BigExponentPkcs10Pem;

            if (multiPem)
            {
                pem = $@"
-----BEGIN UNRELATED-----
abcd
-----END UNRELATED-----
-----BEGIN CERTIFICATE REQUEST-----
!!!!!INVALID!!!!!
-----END CERTIFICATE REQUEST-----
-----BEGIN MORE UNRELATED-----
efgh
-----END MORE UNRELATED-----
{pem}
-----BEGIN CERTIFICATE REQUEST-----
!!!!!INVALID!!!!!
-----END CERTIFICATE REQUEST-----";
            }

            CertificateRequest req = CertificateRequest.LoadSigningRequestPem(
                pem,
                HashAlgorithmName.SHA512,
                options);

            Assert.Equal(HashAlgorithmName.SHA512, req.HashAlgorithm);
            VerifyBigExponentRequest(req, options);
        }
        public static void LoadBigExponentRequest_Bytes(CertificateRequestLoadOptions options)
        {
            CertificateRequest req = CertificateRequest.LoadSigningRequest(
                TestData.BigExponentPkcs10Bytes,
                HashAlgorithmName.SHA384,
                options);

            Assert.Equal(HashAlgorithmName.SHA384, req.HashAlgorithm);
            VerifyBigExponentRequest(req, options);
        }
        public static void LoadBigExponentRequest_Bytes_Oversized(CertificateRequestLoadOptions options)
        {
            byte[] pkcs10 = TestData.BigExponentPkcs10Bytes;
            Array.Resize(ref pkcs10, pkcs10.Length + 1);

            Assert.Throws <CryptographicException>(
                () => CertificateRequest.LoadSigningRequest(
                    pkcs10,
                    HashAlgorithmName.SHA384,
                    options));
        }
예제 #4
0
        public static CertificateRequest LoadSigningRequestPem(
            string pkcs10Pem,
            HashAlgorithmName signerHashAlgorithm,
            CertificateRequestLoadOptions options      = CertificateRequestLoadOptions.Default,
            RSASignaturePadding?signerSignaturePadding = null)
        {
            ArgumentNullException.ThrowIfNull(pkcs10Pem);

            return(LoadSigningRequestPem(
                       pkcs10Pem.AsSpan(),
                       signerHashAlgorithm,
                       options,
                       signerSignaturePadding));
        }
예제 #5
0
 public static CertificateRequest LoadSigningRequest(
     ReadOnlySpan <byte> pkcs10,
     HashAlgorithmName signerHashAlgorithm,
     out int bytesConsumed,
     CertificateRequestLoadOptions options      = CertificateRequestLoadOptions.Default,
     RSASignaturePadding?signerSignaturePadding = null)
 {
     return(LoadSigningRequest(
                pkcs10,
                permitTrailingData: true,
                signerHashAlgorithm,
                out bytesConsumed,
                options,
                signerSignaturePadding));
 }
예제 #6
0
        public static CertificateRequest LoadSigningRequest(
            byte[] pkcs10,
            HashAlgorithmName signerHashAlgorithm,
            CertificateRequestLoadOptions options      = CertificateRequestLoadOptions.Default,
            RSASignaturePadding?signerSignaturePadding = null)
        {
            ArgumentNullException.ThrowIfNull(pkcs10);

            return(LoadSigningRequest(
                       pkcs10,
                       permitTrailingData: false,
                       signerHashAlgorithm,
                       out _,
                       options,
                       signerSignaturePadding));
        }
예제 #7
0
        public static CertificateRequest LoadSigningRequestPem(
            ReadOnlySpan <char> pkcs10Pem,
            HashAlgorithmName signerHashAlgorithm,
            CertificateRequestLoadOptions options      = CertificateRequestLoadOptions.Default,
            RSASignaturePadding?signerSignaturePadding = null)
        {
            ArgumentException.ThrowIfNullOrEmpty(signerHashAlgorithm.Name, nameof(signerHashAlgorithm));

            if ((options & ~AllOptions) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options), options, SR.Argument_InvalidFlag);
            }

            foreach ((ReadOnlySpan <char> contents, PemFields fields) in new PemEnumerator(pkcs10Pem))
            {
                if (contents[fields.Label].SequenceEqual(PemLabels.Pkcs10CertificateRequest))
                {
                    byte[] rented = ArrayPool <byte> .Shared.Rent(fields.DecodedDataLength);

                    if (!Convert.TryFromBase64Chars(contents[fields.Base64Data], rented, out int bytesWritten) ||
                        bytesWritten != fields.DecodedDataLength)
                    {
                        Debug.Fail("Base64Decode failed, but PemEncoding said it was legal");
                        throw new UnreachableException();
                    }

                    try
                    {
                        return(LoadSigningRequest(
                                   rented.AsSpan(0, bytesWritten),
                                   permitTrailingData: false,
                                   signerHashAlgorithm,
                                   out _,
                                   options,
                                   signerSignaturePadding));
                    }
                    finally
                    {
                        ArrayPool <byte> .Shared.Return(rented);
                    }
                }
            }

            throw new CryptographicException(
                      SR.Format(SR.Cryptography_NoPemOfLabel, PemLabels.Pkcs10CertificateRequest));
        }
        public static void LoadBigExponentRequest_Span(CertificateRequestLoadOptions options, bool oversized)
        {
            byte[] pkcs10 = TestData.BigExponentPkcs10Bytes;

            if (oversized)
            {
                Array.Resize(ref pkcs10, pkcs10.Length + 22);
            }

            CertificateRequest req = CertificateRequest.LoadSigningRequest(
                new ReadOnlySpan <byte>(pkcs10),
                HashAlgorithmName.SHA256,
                out int bytesConsumed,
                options);

            Assert.Equal(TestData.BigExponentPkcs10Bytes.Length, bytesConsumed);
            Assert.Equal(HashAlgorithmName.SHA256, req.HashAlgorithm);
            VerifyBigExponentRequest(req, options);
        }
        public static void LoadWithUnknownOptions(int optionsValue)
        {
            CertificateRequestLoadOptions options       = (CertificateRequestLoadOptions)optionsValue;
            HashAlgorithmName             hashAlgorithm = HashAlgorithmName.SHA256;
            ArgumentOutOfRangeException   ex;

            ex = Assert.Throws <ArgumentOutOfRangeException>(
                "options",
                () => CertificateRequest.LoadSigningRequest(Array.Empty <byte>(), hashAlgorithm, options));

            Assert.Equal(options, ex.ActualValue);

            {
                int consumed = -1;

                ex = Assert.Throws <ArgumentOutOfRangeException>(
                    "options",
                    () => CertificateRequest.LoadSigningRequest(
                        ReadOnlySpan <byte> .Empty,
                        hashAlgorithm,
                        out consumed,
                        options));

                Assert.Equal(-1, consumed);
                Assert.Equal(options, ex.ActualValue);
            }

            ex = Assert.Throws <ArgumentOutOfRangeException>(
                "options",
                () => CertificateRequest.LoadSigningRequestPem(string.Empty, hashAlgorithm, options));

            Assert.Equal(options, ex.ActualValue);

            ex = Assert.Throws <ArgumentOutOfRangeException>(
                "options",
                () => CertificateRequest.LoadSigningRequestPem(
                    ReadOnlySpan <char> .Empty,
                    hashAlgorithm,
                    options));

            Assert.Equal(options, ex.ActualValue);
        }
예제 #10
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);
            }
        }