Example #1
0
        /// <summary>
        /// Find a typed extension in a extension collection.
        /// </summary>
        /// <typeparam name="T">The type of the extension.</typeparam>
        /// <param name="extensions">The extensions to search.</param>
        public static T FindExtension <T>(this X509ExtensionCollection extensions) where T : X509Extension
        {
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }
            lock (extensions.SyncRoot)
            {
                // search known custom extensions
                if (typeof(T) == typeof(X509AuthorityKeyIdentifierExtension))
                {
                    var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => (
                                                                                         e.Oid.Value == X509AuthorityKeyIdentifierExtension.AuthorityKeyIdentifierOid ||
                                                                                         e.Oid.Value == X509AuthorityKeyIdentifierExtension.AuthorityKeyIdentifier2Oid)
                                                                                     );
                    if (extension != null)
                    {
                        return(new X509AuthorityKeyIdentifierExtension(extension, extension.Critical) as T);
                    }
                }

                if (typeof(T) == typeof(X509SubjectAltNameExtension))
                {
                    var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => (
                                                                                         e.Oid.Value == X509SubjectAltNameExtension.SubjectAltNameOid ||
                                                                                         e.Oid.Value == X509SubjectAltNameExtension.SubjectAltName2Oid)
                                                                                     );
                    if (extension != null)
                    {
                        return(new X509SubjectAltNameExtension(extension, extension.Critical) as T);
                    }
                }

                if (typeof(T) == typeof(X509CrlNumberExtension))
                {
                    var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => (
                                                                                         e.Oid.Value == X509CrlNumberExtension.CrlNumberOid)
                                                                                     );
                    if (extension != null)
                    {
                        return(new X509CrlNumberExtension(extension, extension.Critical) as T);
                    }
                }

                // search builtin extension
                return(extensions.OfType <T>().FirstOrDefault());
            }
        }
Example #2
0
        public static byte[] GetAppleAttestationExtensionValue(X509ExtensionCollection exts)
        {
            var appleExtension = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value == "1.2.840.113635.100.8.2");

            if (appleExtension == null || appleExtension.RawData == null || appleExtension.RawData.Length < 0x26)
            {
                throw new VerificationException("Extension with OID 1.2.840.113635.100.8.2 not found on Apple attestation credCert");
            }

            try
            {
                var appleAttestationASN = AsnElt.Decode(appleExtension.RawData);
                appleAttestationASN.CheckConstructed();
                appleAttestationASN.CheckTag(AsnElt.SEQUENCE);
                appleAttestationASN.CheckNumSub(1);

                var sequence = appleAttestationASN.GetSub(0);
                sequence.CheckConstructed();
                sequence.CheckNumSub(1);

                var context = sequence.GetSub(0);
                context.CheckPrimitive();
                context.CheckTag(AsnElt.OCTET_STRING);

                return(context.GetOctetString());
            }

            catch (Exception ex)
            {
                throw new VerificationException("Apple attestation extension has invalid data", ex);
            }
        }
        internal static byte U2FTransportsFromAttnCert(X509ExtensionCollection exts)
        {
            var u2ftransports = new byte();
            var ext           = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "1.3.6.1.4.1.45724.2.1.1");

            if (ext != null)
            {
                var decodedU2Ftransports = Asn1Element.Decode(ext.RawData);
                decodedU2Ftransports.CheckPrimitive();

                // some certificates seem to have this encoded as an octet string
                // instead of a bit string, attempt to correct
                if (decodedU2Ftransports.Tag == Asn1Tag.PrimitiveOctetString)
                {
                    ext.RawData[0]       = (byte)UniversalTagNumber.BitString;
                    decodedU2Ftransports = Asn1Element.Decode(ext.RawData);
                }

                decodedU2Ftransports.CheckTag(Asn1Tag.PrimitiveBitString);

                u2ftransports = decodedU2Ftransports.GetBitString()[0];
            }

            return(u2ftransports);
        }
Example #4
0
        public static byte[] GetAppleAttestationExtensionValue(X509ExtensionCollection exts)
        {
            var appleExtension = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid !.Value is "1.2.840.113635.100.8.2");

            if (appleExtension is null || appleExtension.RawData is null || appleExtension.RawData.Length < 0x26)
            {
                throw new Fido2VerificationException("Extension with OID 1.2.840.113635.100.8.2 not found on Apple attestation credCert");
            }

            try
            {
                var appleAttestationASN = Asn1Element.Decode(appleExtension.RawData);
                appleAttestationASN.CheckTag(new Asn1Tag(UniversalTagNumber.Sequence, isConstructed: true));
                appleAttestationASN.CheckExactSequenceLength(1);

                var appleAttestationASNSequence = appleAttestationASN[0];
                appleAttestationASNSequence.CheckConstructed();
                appleAttestationASNSequence.CheckExactSequenceLength(1);

                appleAttestationASNSequence[0].CheckTag(Asn1Tag.PrimitiveOctetString);

                return(appleAttestationASNSequence[0].GetOctetString());
            }

            catch (Exception ex)
            {
                throw new Fido2VerificationException("Apple attestation extension has invalid data", ex);
            }
        }
        public static X509Extension[] ToArray(this X509ExtensionCollection exts)
        {
            if (exts == null)
            {
                return(null);
            }
            List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>());

            return(e.ToArray());
        }
        internal static bool IsAttnCertCACert(X509ExtensionCollection exts)
        {
            var ext = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "2.5.29.19");

            if (ext is X509BasicConstraintsExtension baseExt)
            {
                return(baseExt.CertificateAuthority);
            }

            return(true);
        }
        internal static void RemoveAt(this X509ExtensionCollection exts, Int32 index)
        {
            if (exts == null || index >= exts.Count)
            {
                return;
            }
            List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>());

            e.RemoveAt(index);
            exts = new X509ExtensionCollection();
            foreach (X509Extension ext in e)
            {
                exts.Add(ext);
            }
        }
        internal static byte[] AaguidFromAttnCertExts(X509ExtensionCollection exts)
        {
            byte[] aaguid = null;
            var    ext    = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "1.3.6.1.4.1.45724.1.1.4"); // id-fido-gen-ce-aaguid

            if (ext != null)
            {
                var decodedAaguid = Asn1Element.Decode(ext.RawData);
                decodedAaguid.CheckTag(Asn1Tag.PrimitiveOctetString);
                aaguid = decodedAaguid.GetOctetString();

                // The extension MUST NOT be marked as critical
                if (ext.Critical)
                {
                    throw new Fido2VerificationException("extension MUST NOT be marked as critical");
                }
            }

            return(aaguid);
        }
        public static void Insert(this X509ExtensionCollection exts, Int32 index, X509Extension extension)
        {
            if (extension == null)
            {
                throw new ArgumentNullException(nameof(extension));
            }
            if (exts == null)
            {
                return;
            }
            if (index < 0 || index >= exts.Count)
            {
                throw new OverflowException();
            }
            List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>());

            e.Insert(index, extension);
            exts = new X509ExtensionCollection();
            exts.AddRange(e);
        }
Example #10
0
        internal static byte U2FTransportsFromAttnCert(X509ExtensionCollection exts)
        {
            var u2ftransports = new byte();
            var ext           = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value == "1.3.6.1.4.1.45724.2.1.1");

            if (null != ext)
            {
                var decodedU2Ftransports = AsnElt.Decode(ext.RawData);
                decodedU2Ftransports.CheckPrimitive();

                // some certificates seem to have this encoded as an octet string
                // instead of a bit string, attempt to correct
                if (AsnElt.OCTET_STRING == decodedU2Ftransports.TagValue)
                {
                    ext.RawData[0]       = AsnElt.BIT_STRING;
                    decodedU2Ftransports = AsnElt.Decode(ext.RawData);
                }
                decodedU2Ftransports.CheckTag(AsnElt.BIT_STRING);
                u2ftransports = decodedU2Ftransports.GetBitString()[0];
            }

            return(u2ftransports);
        }
Example #11
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
        {
            CryptoApiMethods.CERT_INFO certInfo   = new CryptoApiMethods.CERT_INFO();
            RSACryptoServiceProvider   key        = CreateRSAKey(keySize, signature);
            IntPtr               publicKeyInfoPtr = IntPtr.Zero;
            X509Certificate2     cert             = null;
            List <X509Extension> newExts          = null;

            if (extensions != null)
            {
                foreach (X509Extension ext in extensions)
                {
                    if (ext.RawData == null)
                    {
                        throw new ArgumentException(Properties.Resources.CreateCert_NeedEncodedData);
                    }
                }
            }

            try
            {
                if (serialNumber == null)
                {
                    serialNumber = Guid.NewGuid().ToByteArray();
                }

                certInfo.dwVersion    = (uint)CryptoApiMethods.CertVersion.CERT_V3;
                certInfo.SerialNumber = new CryptoApiMethods.CRYPTOAPI_BLOB(serialNumber);
                certInfo.Subject      = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);

                if (issuer == null)
                {
                    // Self-signed
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);
                }
                else
                {
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(issuer.SubjectName.RawData);
                }

                // Never seems to need these set to anything valid?
                certInfo.SubjectUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB();
                certInfo.IssuerUniqueId  = new CryptoApiMethods.CRYPT_BIT_BLOB();

                certInfo.NotBefore = DateTimeToFileTime(notBefore);
                certInfo.NotAfter  = DateTimeToFileTime(notAfter);

                certInfo.SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
                // Doesn't seem to work properly with standard szOID_RSA_SHA1RSA
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
                certInfo.SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

                // Add extension fields
                publicKeyInfoPtr = ExportPublicKeyInfo(key);
                certInfo.SubjectPublicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO));

                newExts = new List <X509Extension>();

                if (extensions != null)
                {
                    // Filter out some extensions we don't want
                    newExts.AddRange(
                        extensions.Cast <X509Extension>().Where(
                            x =>
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_SUBJECT_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER2)));
                }

                if (issuer != null)
                {
                    newExts.Add(CreateAuthorityKeyInfo2(issuer.GetSerialNumber(), issuer.SubjectName, (RSACryptoServiceProvider)issuer.PrivateKey));
                }
                else
                {
                    newExts.Add(CreateAuthorityKeyInfo2(serialNumber, subjectName, key));
                }

                newExts.Add(new X509SubjectKeyIdentifierExtension(HashPublicKeyInfo(key), false));

                certInfo.rgExtension = MarshalExtensions(newExts.ToArray());
                certInfo.cExtension  = (uint)newExts.Count;

                byte[] certData = EncodeAndSignCertInfo(issuer != null ? issuer.PrivateKey as RSACryptoServiceProvider : key, certInfo, hashAlgorithm);

                cert            = new X509Certificate2(certData, (string)null, X509KeyStorageFlags.Exportable);
                cert.PrivateKey = key;
            }
            finally
            {
                if (certInfo.rgExtension != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(certInfo.rgExtension);
                }

                if (certInfo.Subject != null)
                {
                    certInfo.Subject.Release();
                }

                if (certInfo.Issuer != null)
                {
                    certInfo.Issuer.Release();
                }

                if (publicKeyInfoPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(publicKeyInfoPtr);
                }
            }

            return(cert);
        }