public static void ReadIntegers()
        {
            byte[] derEncoded =
            {
                /* SEQUENCE */     0x30, 23,
                /* INTEGER(0) */   0x02, 0x01, 0x00,
                /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00,
                /* INTEGER(-1) */  0x02, 0x01, 0xFF,
                /* Big integer */  0x02, 0x0B, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
            };

            DerSequenceReader reader = new DerSequenceReader(derEncoded);
            Assert.True(reader.HasData);
            Assert.Equal(23, reader.ContentLength);

            int first = reader.ReadInteger();
            Assert.Equal(0, first);

            int second = reader.ReadInteger();
            Assert.Equal(256, second);

            int third = reader.ReadInteger();
            Assert.Equal(-1, third);

            // Reader reads Big-Endian, BigInteger reads Little-Endian
            byte[] fourthBytes = reader.ReadIntegerBytes();
            Array.Reverse(fourthBytes);
            BigInteger fourth = new BigInteger(fourthBytes);
            Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth);

            // And... done.
            Assert.False(reader.HasData);
        }
        public static void ReadOids()
        {
            byte[] derEncoded =
            {
                // Noise
                0x10, 0x20, 0x30, 0x04, 0x05,

                // Data
                0x30, 27,
                0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
                0x06, 0x03, 0x55, 0x04, 0x03,
                0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x07,

                // More noise.
                0x85, 0x71, 0x23, 0x74, 0x01,
            };

            DerSequenceReader reader = new DerSequenceReader(derEncoded, 5, derEncoded.Length - 10);
            Assert.True(reader.HasData);
            Assert.Equal(27, reader.ContentLength);

            Oid first = reader.ReadOid();
            Assert.Equal("1.2.840.113549.1.1.11", first.Value);

            Oid second = reader.ReadOid();
            Assert.Equal("2.5.4.3", second.Value);

            Oid third = reader.ReadOid();
            Assert.Equal("1.3.6.1.4.1.311.21.7", third.Value);

            // And... done.
            Assert.False(reader.HasData);
        }
Beispiel #3
0
        public static void ReadIntegers()
        {
            byte[] derEncoded =
            {
                /* SEQUENCE */ 0x30,       23,
                /* INTEGER(0) */ 0x02,   0x01, 0x00,
                /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00,
                /* INTEGER(-1) */ 0x02,  0x01, 0xFF,
                /* Big integer */ 0x02,  0x0B, 0x03, 0x04,0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
            };

            DerSequenceReader reader = new DerSequenceReader(derEncoded);

            Assert.True(reader.HasData);
            Assert.Equal(23, reader.ContentLength);

            int first = reader.ReadInteger();

            Assert.Equal(0, first);

            int second = reader.ReadInteger();

            Assert.Equal(256, second);

            int third = reader.ReadInteger();

            Assert.Equal(-1, third);

            // Reader reads Big-Endian, BigInteger reads Little-Endian
            byte[] fourthBytes = reader.ReadIntegerBytes();
            Array.Reverse(fourthBytes);
            BigInteger fourth = new BigInteger(fourthBytes);

            Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth);

            // And... done.
            Assert.False(reader.HasData);
        }
        public static byte[] ConvertDerToIeee1363(byte[] input, int inputOffset, int inputCount, int fieldSizeBits)
        {
            int bytes = BitsToBytes(fieldSizeBits);

            try
            {
                DerSequenceReader derSequenceReader =
                    new DerSequenceReader(input, inputOffset, inputCount);

                byte[] signatureField1 = derSequenceReader.ReadIntegerBytes();
                byte[] signatureField2 = derSequenceReader.ReadIntegerBytes();
                byte[] response        = new byte[2 * bytes];

                CopySignatureField(signatureField1, response, 0, bytes);
                CopySignatureField(signatureField2, response, bytes, bytes);

                return(response);
            }
            catch (System.InvalidOperationException ex)
            {
                throw new System.Security.Cryptography.CryptographicException($"Cryptography Exception", ex);
            }
        }
Beispiel #5
0
        internal static NuGetV3ServiceIndexUrl Read(DerSequenceReader reader)
        {
            var urlString = reader.ReadIA5String();

            if (reader.HasData)
            {
                throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid);
            }

            Uri url;

            if (!Uri.TryCreate(urlString, UriKind.Absolute, out url))
            {
                throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid);
            }

            if (!string.Equals(url.Scheme, "https", StringComparison.Ordinal))
            {
                throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid);
            }

            return(new NuGetV3ServiceIndexUrl(url));
        }
        public static void ReadOids()
        {
            byte[] derEncoded =
            {
                // Noise
                0x10, 0x20, 0x30, 0x04, 0x05,

                // Data
                0x30,   27,
                0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
                0x06, 0x03, 0x55, 0x04, 0x03,
                0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x07,

                // More noise.
                0x85, 0x71, 0x23, 0x74, 0x01,
            };

            DerSequenceReader reader = new DerSequenceReader(derEncoded, 5, derEncoded.Length - 10);

            Assert.True(reader.HasData);
            Assert.Equal(27, reader.ContentLength);

            Oid first = reader.ReadOid();

            Assert.Equal("1.2.840.113549.1.1.11", first.Value);

            Oid second = reader.ReadOid();

            Assert.Equal("2.5.4.3", second.Value);

            Oid third = reader.ReadOid();

            Assert.Equal("1.3.6.1.4.1.311.21.7", third.Value);

            // And... done.
            Assert.False(reader.HasData);
        }
Beispiel #7
0
        public static void InteriorLengthTooLong()
        {
            byte[] bytes =
            {
                // CONSTRUCTED SEQUENCE (8 bytes)
                0x30, 0x08,

                // CONSTRUCTED SEQUENCE (2 bytes)
                0x30, 0x02,

                // OCTET STRING (0 bytes)
                0x04, 0x00,

                // OCTET STRING (after the inner sequence, 3 bytes, but that exceeds the sequence bounds)
                0x04, 0x03, 0x01, 0x02, 0x03
            };

            DerSequenceReader reader = new DerSequenceReader(bytes);
            DerSequenceReader nested = reader.ReadSequence();

            Assert.Equal(0, nested.ReadOctetString().Length);
            Assert.False(nested.HasData);
            Assert.Throws <CryptographicException>(() => reader.ReadOctetString());
        }
        internal static NuGetPackageOwners Read(DerSequenceReader reader)
        {
            var packageOwners = new List <string>();
            var ownersReader  = reader.ReadSequence();

            while (ownersReader.HasData)
            {
                var packageOwner = ownersReader.ReadUtf8String();

                if (string.IsNullOrWhiteSpace(packageOwner))
                {
                    throw new SignatureException(Strings.NuGetPackageOwnersInvalid);
                }

                packageOwners.Add(packageOwner);
            }

            if (packageOwners.Count == 0)
            {
                throw new SignatureException(Strings.NuGetPackageOwnersInvalid);
            }

            return(new NuGetPackageOwners(packageOwners));
        }
        /// <summary>
        /// Determines if a certificate is self-issued.
        /// </summary>
        /// <remarks>Warning:  this method does not evaluate certificate trust, revocation status, or validity!
        /// This method attempts to build a chain for the provided certificate, and although revocation status
        /// checking is explicitly skipped, the underlying chain building engine may go online to fetch
        /// additional information (e.g.:  the issuer's certificate).  This method is not a guaranteed offline
        /// check.</remarks>
        /// <param name="certificate">The certificate to check.</param>
        /// <returns><c>true</c> if the certificate is self-issued; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception>
        public static bool IsSelfIssued(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            using (var chainHolder = new X509ChainHolder())
            {
                X509Chain chain = chainHolder.Chain;

                chain.ChainPolicy.RevocationMode    = X509RevocationMode.NoCheck;
                chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority |
                                                      X509VerificationFlags.IgnoreRootRevocationUnknown |
                                                      X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown |
                                                      X509VerificationFlags.IgnoreEndRevocationUnknown;

                CertificateChainUtility.BuildWithPolicy(chain, certificate);

                if (chain.ChainElements.Count != 1)
                {
                    return(false);
                }

                if (chain.ChainStatus.Any(
                        chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) ||
                        chainStatus.Status.HasFlag(X509ChainStatusFlags.PartialChain) ||
                        chainStatus.Status.HasFlag(X509ChainStatusFlags.NotSignatureValid)))
                {
                    return(false);
                }

                if (!certificate.IssuerName.RawData.SequenceEqual(certificate.SubjectName.RawData))
                {
                    return(false);
                }

                var akiExtension = certificate.Extensions[Oids.AuthorityKeyIdentifier];
                var skiExtension = certificate.Extensions[Oids.SubjectKeyIdentifier] as X509SubjectKeyIdentifierExtension;

                if (akiExtension != null && skiExtension != null)
                {
                    var reader           = new DerSequenceReader(akiExtension.RawData);
                    var keyIdentifierTag = (DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificTagFlag;

                    if (reader.HasTag(keyIdentifierTag))
                    {
                        var keyIdentifier = reader.ReadValue(keyIdentifierTag);
#if NETCOREAPP
                        var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", "", StringComparison.Ordinal);
#else
                        var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", "");
#endif

                        return(string.Equals(skiExtension.SubjectKeyIdentifier, akiKeyIdentifier, StringComparison.OrdinalIgnoreCase));
                    }
                }

                return(true);
            }
        }
        private static X509Certificate2 DownloadCertificate(
            byte[] authorityInformationAccess,
            ref TimeSpan remainingDownloadTime)
        {
            // Don't do any work if we're over limit.
            if (remainingDownloadTime <= TimeSpan.Zero)
            {
                return null;
            }

            DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess);

            while (reader.HasData)
            {
                DerSequenceReader innerReader = reader.ReadSequence();

                // If the sequence's first element is a sequence, unwrap it.
                if (innerReader.PeekTag() == ConstructedSequenceTagId)
                {
                    innerReader = innerReader.ReadSequence();
                }

                Oid oid = innerReader.ReadOid();

                if (StringComparer.Ordinal.Equals(oid.Value, Oids.CertificateAuthorityIssuers))
                {
                    string uri = innerReader.ReadIA5String();

                    Uri parsedUri;
                    if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri))
                    {
                        continue;
                    }

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime);
                }
            }

            return null;
        }
        internal static string FindHttpAiaRecord(byte[] authorityInformationAccess, string recordTypeOid)
        {
            DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess);

            while (reader.HasData)
            {
                DerSequenceReader innerReader = reader.ReadSequence();

                // If the sequence's first element is a sequence, unwrap it.
                if (innerReader.PeekTag() == ConstructedSequenceTagId)
                {
                    innerReader = innerReader.ReadSequence();
                }

                Oid oid = innerReader.ReadOid();

                if (StringComparer.Ordinal.Equals(oid.Value, recordTypeOid))
                {
                    string uri = innerReader.ReadIA5String();

                    Uri parsedUri;
                    if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri))
                    {
                        continue;
                    }

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return uri;
                }
            }

            return null;
        }
        public static SigningCertificateV2 Read(byte[] bytes)
        {
            var reader = new DerSequenceReader(bytes);

            return(Read(reader));
        }
Beispiel #13
0
        public static Extensions Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #14
0
        internal static ISet<string> ReadCertPolicyExtension(X509Extension extension)
        {
            DerSequenceReader reader = new DerSequenceReader(extension.RawData);
            HashSet<string> policies = new HashSet<string>();

            while (reader.HasData)
            {
                DerSequenceReader policyInformation = reader.ReadSequence();
                policies.Add(policyInformation.ReadOidAsString());

                // There is an optional policy qualifier here, but it is for information
                // purposes, there is no logic that would be changed.

                // Since reader (the outer one) has already skipped past the rest of the
                // sequence we don't particularly need to drain out here.
            }

            return policies;
        }
Beispiel #15
0
        internal static TstInfo Read(DerSequenceReader reader)
        {
            var tstInfoReader  = reader.ReadSequence();
            var version        = tstInfoReader.ReadInteger();
            var policy         = tstInfoReader.ReadOid();
            var messageImprint = MessageImprint.Read(tstInfoReader);
            var serialNumber   = tstInfoReader.ReadIntegerBytes();

            if (serialNumber == null || serialNumber.Length == 0)
            {
                throw new CryptographicException(Strings.InvalidAsn1);
            }

            var genTime = tstInfoReader.ReadGeneralizedTime();

            Accuracy accuracy = null;

            if (tstInfoReader.HasTag(DerSequenceReader.ConstructedSequence))
            {
                accuracy = Accuracy.Read(tstInfoReader);
            }

            var ordering = false;

            if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Boolean))
            {
                ordering = tstInfoReader.ReadBoolean();
            }

            byte[] nonce = null;

            if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Integer))
            {
                nonce = tstInfoReader.ReadIntegerBytes();
            }

            byte[] tsa = null;

            if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag0))
            {
                tsa = tstInfoReader.ReadValue((DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificConstructedTag0);
            }

            X509ExtensionCollection extensions = null;

            if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag1))
            {
                extensions = new X509ExtensionCollection();

                var rawExtensions = Signing.Extensions.Read(tstInfoReader);

                foreach (var rawExtension in rawExtensions.ExtensionsList)
                {
                    extensions.Add(
                        new X509Extension(
                            rawExtension.Id,
                            rawExtension.Value,
                            rawExtension.Critical));
                }

                if (extensions.Count == 0)
                {
                    throw new CryptographicException(Strings.InvalidAsn1);
                }
            }

            if (tstInfoReader.HasData)
            {
                throw new CryptographicException(Strings.InvalidAsn1);
            }

            return(new TstInfo(
                       version,
                       policy,
                       messageImprint,
                       serialNumber,
                       genTime.ToUniversalTime(),
                       accuracy,
                       ordering,
                       nonce,
                       tsa,
                       extensions));
        }
Beispiel #16
0
        internal DerSequenceReader ReadSequence()
        {
            // DerSequenceReader wants to read its own tag, so don't EatTag here.
            CheckTag(DerTag.Sequence, _data, _position);

            int lengthLength;
            int contentLength = ScanContentLength(_data, _position + 1, out lengthLength);
            int totalLength = 1 + lengthLength + contentLength;

            DerSequenceReader reader = new DerSequenceReader(_data, _position, totalLength);
            _position += totalLength;
            return reader;
        }
Beispiel #17
0
        public static NuGetV3ServiceIndexUrl Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #18
0
        public static MessageImprint Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #19
0
        // DER -> Hash
        private static KeyValuePair <Common.HashAlgorithmName, byte[]> GetESSCertIDv2Entry(DerSequenceReader reader)
        {
            var hashAlgorithm      = CryptoHashUtility.OidToHashAlgorithmName(reader.ReadOidAsString());
            var attributeHashValue = reader.ReadOctetString();

            return(new KeyValuePair <Common.HashAlgorithmName, byte[]>(hashAlgorithm, attributeHashValue));
        }
Beispiel #20
0
        private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy)
        {
            DerSequenceReader reader = new DerSequenceReader(extension.RawData);

            while (reader.HasData)
            {
                // Policy Constraints context specific tag values are defined in RFC 3280 4.2.1.12,
                // and restated (unchanged) in RFC 5280 4.2.1.11.
                switch (reader.PeekTag())
                {
                    case DerSequenceReader.ContextSpecificTagFlag | 0:
                        policy.RequireExplicitPolicyDepth = reader.ReadInteger();
                        break;
                    case DerSequenceReader.ContextSpecificTagFlag | 1:
                        policy.InhibitMappingDepth = reader.ReadInteger();
                        break;
                    default:
                        if (extension.Critical)
                        {
                            // If an unknown value is read, but we're marked as critical,
                            // then we don't know what we're doing and MUST fail validation
                            // (RFC 3280).
                            // If it isn't critical then it means we're allowed to be ignorant
                            // of data defined more recently than we understand.
                            throw new CryptographicException();
                        }

                        break;
                }
            }
        }
        private static DerSequenceReader ReadEncryptedPkcs8Blob(string passphrase, DerSequenceReader reader)
        {
            // EncryptedPrivateKeyInfo::= SEQUENCE {
            //    encryptionAlgorithm EncryptionAlgorithmIdentifier,
            //    encryptedData        EncryptedData }
            //
            // EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
            //
            // EncryptedData ::= OCTET STRING
            DerSequenceReader algorithmIdentifier = reader.ReadSequence();
            string            algorithmOid        = algorithmIdentifier.ReadOidAsString();

            // PBES2 (Password-Based Encryption Scheme 2)
            if (algorithmOid != OidPbes2)
            {
                Debug.Fail($"Expected PBES2 ({OidPbes2}), got {algorithmOid}");
                throw new CryptographicException();
            }

            // PBES2-params ::= SEQUENCE {
            //    keyDerivationFunc AlgorithmIdentifier { { PBES2 - KDFs} },
            //    encryptionScheme AlgorithmIdentifier { { PBES2 - Encs} }
            // }

            DerSequenceReader pbes2Params = algorithmIdentifier.ReadSequence();

            algorithmIdentifier = pbes2Params.ReadSequence();

            string kdfOid = algorithmIdentifier.ReadOidAsString();

            // PBKDF2 (Password-Based Key Derivation Function 2)
            if (kdfOid != OidPbkdf2)
            {
                Debug.Fail($"Expected PBKDF2 ({OidPbkdf2}), got {kdfOid}");
                throw new CryptographicException();
            }

            // PBKDF2-params ::= SEQUENCE {
            //   salt CHOICE {
            //     specified OCTET STRING,
            //     otherSource AlgorithmIdentifier { { PBKDF2 - SaltSources} }
            //   },
            //   iterationCount INTEGER (1..MAX),
            //   keyLength INTEGER(1..MAX) OPTIONAL,
            //   prf AlgorithmIdentifier { { PBKDF2 - PRFs} }  DEFAULT algid - hmacWithSHA1
            // }
            DerSequenceReader pbkdf2Params = algorithmIdentifier.ReadSequence();

            byte[] salt      = pbkdf2Params.ReadOctetString();
            int    iterCount = pbkdf2Params.ReadInteger();
            int    keySize   = -1;

            if (pbkdf2Params.HasData && pbkdf2Params.PeekTag() == (byte)DerSequenceReader.DerTag.Integer)
            {
                keySize = pbkdf2Params.ReadInteger();
            }

            if (pbkdf2Params.HasData)
            {
                string prfOid = pbkdf2Params.ReadOidAsString();

                // SHA-1 is the only hash algorithm our PBKDF2 supports.
                if (prfOid != OidSha1)
                {
                    Debug.Fail($"Expected SHA1 ({OidSha1}), got {prfOid}");
                    throw new CryptographicException();
                }
            }

            DerSequenceReader encryptionScheme = pbes2Params.ReadSequence();
            string            cipherOid        = encryptionScheme.ReadOidAsString();

            // DES-EDE3-CBC (TripleDES in CBC mode)
            if (cipherOid != OidTripleDesCbc)
            {
                Debug.Fail($"Expected DES-EDE3-CBC ({OidTripleDesCbc}), got {cipherOid}");
                throw new CryptographicException();
            }

            byte[] decrypted;

            using (TripleDES des3 = TripleDES.Create())
            {
                if (keySize == -1)
                {
                    foreach (KeySizes keySizes in des3.LegalKeySizes)
                    {
                        keySize = Math.Max(keySize, keySizes.MaxSize);
                    }
                }

                byte[] iv = encryptionScheme.ReadOctetString();

                using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, iterCount))
                    using (ICryptoTransform decryptor = des3.CreateDecryptor(pbkdf2.GetBytes(keySize / 8), iv))
                    {
                        byte[] encrypted = reader.ReadOctetString();
                        decrypted = decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length);
                    }
            }

            DerSequenceReader pkcs8Reader = new DerSequenceReader(decrypted);

            return(pkcs8Reader);
        }
Beispiel #22
0
        private static List<CertificatePolicyMapping> ReadCertPolicyMappingsExtension(X509Extension extension)
        {
            DerSequenceReader reader = new DerSequenceReader(extension.RawData);
            List<CertificatePolicyMapping> mappings = new List<CertificatePolicyMapping>();

            while (reader.HasData)
            {
                DerSequenceReader mappingSequence = reader.ReadSequence();
                mappings.Add(
                    new CertificatePolicyMapping
                    {
                        IssuerDomainPolicy = mappingSequence.ReadOidAsString(),
                        SubjectDomainPolicy = mappingSequence.ReadOidAsString(),
                    });
            }

            return mappings;
        }
        internal static DerSequenceReader SecKeyExport(
            SafeSecKeyRefHandle key,
            bool exportPrivate)
        {
            // Apple requires all private keys to be exported encrypted, but since we're trying to export
            // as parsed structures we will need to decrypt it for the user.
            const string ExportPassword = "******";

            SafeCreateHandle exportPassword = exportPrivate
                ? CoreFoundation.CFStringCreateWithCString(ExportPassword)
                : s_nullExportString;

            int ret;
            SafeCFDataHandle cfData;
            int osStatus;

            try
            {
                ret = AppleCryptoNative_SecKeyExport(
                    key,
                    exportPrivate ? 1 : 0,
                    exportPassword,
                    out cfData,
                    out osStatus);
            }
            finally
            {
                if (exportPassword != s_nullExportString)
                {
                    exportPassword.Dispose();
                }
            }

            byte[] exportedData;

            using (cfData)
            {
                if (ret == 0)
                {
                    throw CreateExceptionForOSStatus(osStatus);
                }

                if (ret != 1)
                {
                    Debug.Fail($"AppleCryptoNative_SecKeyExport returned {ret}");
                    throw new CryptographicException();
                }

                exportedData = CoreFoundation.CFGetData(cfData);
            }

            DerSequenceReader reader = new DerSequenceReader(exportedData);

            if (!exportPrivate)
            {
                return(reader);
            }

            byte tag = reader.PeekTag();

            // PKCS#8 defines two structures, PrivateKeyInfo, which starts with an integer,
            // and EncryptedPrivateKey, which starts with an encryption algorithm (DER sequence).
            if (tag == (byte)DerSequenceReader.DerTag.Integer)
            {
                return(reader);
            }

            const byte ConstructedSequence =
                DerSequenceReader.ConstructedFlag | (byte)DerSequenceReader.DerTag.Sequence;

            if (tag == ConstructedSequence)
            {
                return(ReadEncryptedPkcs8Blob(ExportPassword, reader));
            }

            Debug.Fail($"Data was neither PrivateKey or EncryptedPrivateKey: {tag:X2}");
            throw new CryptographicException();
        }
Beispiel #24
0
        public static IssuerSerial Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #25
0
        public static AlgorithmIdentifier Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
        public static EssCertId Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
        public static CommitmentTypeQualifier Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #28
0
        public static PolicyQualifierInfo Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #29
0
        private static string GetCdpUrl(X509Certificate2 cert)
        {
            byte[] crlDistributionPoints = null;

            foreach (X509Extension extension in cert.Extensions)
            {
                if (StringComparer.Ordinal.Equals(extension.Oid.Value, Oids.CrlDistributionPoints))
                {
                    // If there's an Authority Information Access extension, it might be used for
                    // looking up additional certificates for the chain.
                    crlDistributionPoints = extension.RawData;
                    break;
                }
            }

            if (crlDistributionPoints == null)
            {
                return null;
            }

            // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
            //
            // DistributionPoint ::= SEQUENCE {
            //    distributionPoint       [0]     DistributionPointName OPTIONAL,
            //    reasons                 [1]     ReasonFlags OPTIONAL,
            //    cRLIssuer               [2]     GeneralNames OPTIONAL }
            //
            // DistributionPointName ::= CHOICE {
            //    fullName                [0]     GeneralNames,
            //    nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
            //
            // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
            //
            // GeneralName ::= CHOICE {
            //    otherName                       [0]     OtherName,
            //    rfc822Name                      [1]     IA5String,
            //    dNSName                         [2]     IA5String,
            //    x400Address                     [3]     ORAddress,
            //    directoryName                   [4]     Name,
            //    ediPartyName                    [5]     EDIPartyName,
            //    uniformResourceIdentifier       [6]     IA5String,
            //    iPAddress                       [7]     OCTET STRING,
            //    registeredID                    [8]     OBJECT IDENTIFIER }

            DerSequenceReader cdpSequence = new DerSequenceReader(crlDistributionPoints);

            while (cdpSequence.HasData)
            {
                const byte ContextSpecificFlag = 0x80;
                const byte ContextSpecific0 = ContextSpecificFlag;
                const byte ConstructedFlag = 0x20;
                const byte ContextSpecificConstructed0 = ContextSpecific0 | ConstructedFlag;
                const byte GeneralNameUri = ContextSpecificFlag | 0x06;

                DerSequenceReader distributionPointReader = cdpSequence.ReadSequence();
                byte tag = distributionPointReader.PeekTag();

                // Only distributionPoint is supported
                if (tag != ContextSpecificConstructed0)
                {
                    continue;
                }

                // The DistributionPointName is a CHOICE, not a SEQUENCE, but the reader is the same.
                DerSequenceReader dpNameReader = distributionPointReader.ReadSequence();
                tag = dpNameReader.PeekTag();

                // Only fullName is supported,
                // nameRelativeToCRLIssuer is for LDAP-based lookup.
                if (tag != ContextSpecificConstructed0)
                {
                    continue;
                }

                DerSequenceReader fullNameReader = dpNameReader.ReadSequence();

                while (fullNameReader.HasData)
                {
                    tag = fullNameReader.PeekTag();

                    if (tag != GeneralNameUri)
                    {
                        fullNameReader.SkipValue();
                        continue;
                    }

                    string uri = fullNameReader.ReadIA5String();

                    Uri parsedUri = new Uri(uri);

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return uri;
                }
            }

            return null;
        }
        public void FindByTemplateName(string templateName)
        {
            FindCore(
                cert =>
                {
                    X509Extension ext = FindExtension(cert, Oids.EnrollCertTypeExtension);

                    if (ext != null)
                    {
                        // Try a V1 template structure, just a string:
                        string decodedName = Interop.Crypto.DerStringToManagedString(ext.RawData);

                        // If this doesn't match, maybe a V2 template will
                        if (StringComparer.OrdinalIgnoreCase.Equals(templateName, decodedName))
                        {
                            return true;
                        }
                    }

                    ext = FindExtension(cert, Oids.CertificateTemplate);

                    if (ext != null)
                    {
                        DerSequenceReader reader = new DerSequenceReader(ext.RawData);
                        // SEQUENCE (
                        //     OID oid,
                        //     INTEGER major,
                        //     INTEGER minor OPTIONAL
                        //  )

                        if (reader.PeekTag() == (byte)DerSequenceReader.DerTag.ObjectIdentifier)
                        {
                            Oid oid = reader.ReadOid();

                            if (StringComparer.Ordinal.Equals(templateName, oid.Value))
                            {
                                return true;
                            }
                        }
                    }

                    return false;
                });
        }
        public static NuGetPackageOwners Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #32
0
        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.

            // The end size of this string is hard to predict.
            // * dNSName values have a tag that takes four characters to represent ("DNS:")
            //   and then their payload is ASCII encoded (so one byte -> one char), so they
            //   work out to be about equal (in chars) to their DER encoded length (in bytes).
            // * iPAddress values have a tag that takes 11 characters ("IP Address:") and then
            //   grow from 4 bytes to up to 15 characters for IPv4, or 16 bytes to 47 characters
            //   for IPv6
            //
            // So use a List<string> and just Concat them all when we're done, and we reduce the
            // number of times we copy the header values (vs pointers to the header values).
            List <string> segments = new List <string>();

            try
            {
                // SubjectAltName ::= GeneralNames
                //
                // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
                //
                // GeneralName ::= CHOICE {
                //   otherName                       [0]     OtherName,
                //   rfc822Name                      [1]     IA5String,
                //   dNSName                         [2]     IA5String,
                //   x400Address                     [3]     ORAddress,
                //   directoryName                   [4]     Name,
                //   ediPartyName                    [5]     EDIPartyName,
                //   uniformResourceIdentifier       [6]     IA5String,
                //   iPAddress                       [7]     OCTET STRING,
                //   registeredID                    [8]     OBJECT IDENTIFIER }
                //
                // OtherName::= SEQUENCE {
                //   type - id    OBJECT IDENTIFIER,
                //   value[0] EXPLICIT ANY DEFINED BY type - id }
                DerSequenceReader altNameReader = new DerSequenceReader(rawData);

                while (altNameReader.HasData)
                {
                    if (segments.Count != 0)
                    {
                        segments.Add(CommaSpace);
                    }

                    byte tag = altNameReader.PeekTag();

                    if ((tag & DerSequenceReader.ContextSpecificTagFlag) == 0)
                    {
                        // All GeneralName values need the ContextSpecific flag.
                        return(null);
                    }

                    GeneralNameType nameType = (GeneralNameType)(tag & DerSequenceReader.TagNumberMask);

                    bool needsConstructedFlag = false;

                    switch (nameType)
                    {
                    case GeneralNameType.OtherName:
                    case GeneralNameType.X400Address:
                    case GeneralNameType.DirectoryName:
                    case GeneralNameType.EdiPartyName:
                        needsConstructedFlag = true;
                        break;
                    }

                    if (needsConstructedFlag &&
                        (tag & DerSequenceReader.ConstructedFlag) == 0)
                    {
                        // All of the SEQUENCE types require the constructed bit,
                        // or OpenSSL will have refused to print it.
                        return(null);
                    }

                    switch (nameType)
                    {
                    case GeneralNameType.OtherName:
                        segments.Add("othername:<unsupported>");
                        altNameReader.SkipValue();
                        break;

                    case GeneralNameType.Rfc822Name:
                        segments.Add("email:");
                        segments.Add(altNameReader.ReadIA5String());
                        break;

                    case GeneralNameType.DnsName:
                        segments.Add("DNS:");
                        segments.Add(altNameReader.ReadIA5String());
                        break;

                    case GeneralNameType.X400Address:
                        segments.Add("X400Name:<unsupported>");
                        altNameReader.SkipValue();
                        break;

                    case GeneralNameType.DirectoryName:
                        // 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.
                        segments.Add("DirName:<unsupported>");
                        altNameReader.SkipValue();
                        break;

                    case GeneralNameType.EdiPartyName:
                        segments.Add("EdiPartyName:<unsupported>");
                        altNameReader.SkipValue();
                        break;

                    case GeneralNameType.UniformResourceIdentifier:
                        segments.Add("URI:");
                        segments.Add(altNameReader.ReadIA5String());
                        break;

                    case GeneralNameType.IPAddress:
                        segments.Add("IP Address");

                        byte[] ipAddressBytes = altNameReader.ReadOctetString();

                        if (ipAddressBytes.Length == 4)
                        {
                            // Add the colon and dotted-decimal representation of IPv4.
                            segments.Add(
                                $":{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)
                            {
                                segments.Add($":{ipAddressBytes[i] << 8 | ipAddressBytes[i + 1]:X}");
                            }
                        }
                        else
                        {
                            segments.Add(":<invalid>");
                        }

                        break;

                    case GeneralNameType.RegisteredId:
                        segments.Add("Registered ID:");
                        segments.Add(altNameReader.ReadOidAsString());
                        break;

                    default:
                        // 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(string.Concat(segments));
            }
            catch (CryptographicException)
            {
                return(null);
            }
        }
        public static PolicyInformation Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
        public static Accuracy Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }
Beispiel #35
0
        public static GeneralName Read(byte[] bytes)
        {
            var reader = DerSequenceReader.CreateForPayload(bytes);

            return(Read(reader));
        }