public static AsyncCertificateRequest Parse(ProtocolVersion version, IByteBuffer data)
        {
            int numTypes = data.ReadByte() & 0x0FF;

            byte[] certificateTypes = new byte[numTypes];
            for (int i = 0; i < numTypes; ++i)
            {
                certificateTypes[i] = data.ReadByte();
            }

            IList supportedSignatureAlgorithms = null;

            if (ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion()))
            {
                supportedSignatureAlgorithms = DtlsHelper.ParseSupportedSignatureAlgorithms(false, data);
            }

            IList certificateAuthorities = new List <X509Name>();
            int   remainingBytes         = data.ReadUnsignedShort();

            while (remainingBytes > 0)
            {
                byte[] derEncoding = new byte[data.ReadUnsignedShort()];
                data.ReadBytes(derEncoding);
                Asn1InputStream asn1   = new Asn1InputStream(derEncoding);
                Asn1Object      result = asn1.ReadObject();
                asn1.Close();

                if (null == result)
                {
                    throw new TlsFatalAlert(AlertDescription.decode_error);
                }

                if (null != asn1.ReadObject())
                {
                    throw new TlsFatalAlert(AlertDescription.decode_error);
                }

                certificateAuthorities.Add(X509Name.GetInstance(result));
                remainingBytes -= 2 + derEncoding.Length;
            }

            return(new AsyncCertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities));
        }
예제 #2
0
 private CrlIdentifier(Asn1Sequence seq)
 {
     //IL_000e: Unknown result type (might be due to invalid IL or missing references)
     //IL_0040: Unknown result type (might be due to invalid IL or missing references)
     if (seq == null)
     {
         throw new ArgumentNullException("seq");
     }
     if (seq.Count < 2 || seq.Count > 3)
     {
         throw new ArgumentException(string.Concat((object)"Bad sequence size: ", (object)seq.Count), "seq");
     }
     crlIssuer     = X509Name.GetInstance(seq[0]);
     crlIssuedTime = DerUtcTime.GetInstance(seq[1]);
     if (seq.Count > 2)
     {
         crlNumber = DerInteger.GetInstance(seq[2]);
     }
 }
예제 #3
0
        internal TbsCertificateStructure(Asn1Sequence seq)
        {
            int num = 0;

            this.seq = seq;
            if (seq[0] is DerTaggedObject)
            {
                version = DerInteger.GetInstance((Asn1TaggedObject)seq[0], isExplicit: true);
            }
            else
            {
                num     = -1;
                version = new DerInteger(0);
            }
            serialNumber = DerInteger.GetInstance(seq[num + 1]);
            signature    = AlgorithmIdentifier.GetInstance(seq[num + 2]);
            issuer       = X509Name.GetInstance(seq[num + 3]);
            Asn1Sequence asn1Sequence = (Asn1Sequence)seq[num + 4];

            startDate            = Time.GetInstance(asn1Sequence[0]);
            endDate              = Time.GetInstance(asn1Sequence[1]);
            subject              = X509Name.GetInstance(seq[num + 5]);
            subjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(seq[num + 6]);
            for (int num2 = seq.Count - (num + 6) - 1; num2 > 0; num2--)
            {
                DerTaggedObject derTaggedObject = (DerTaggedObject)seq[num + 6 + num2];
                switch (derTaggedObject.TagNo)
                {
                case 1:
                    issuerUniqueID = DerBitString.GetInstance(derTaggedObject, isExplicit: false);
                    break;

                case 2:
                    subjectUniqueID = DerBitString.GetInstance(derTaggedObject, isExplicit: false);
                    break;

                case 3:
                    extensions = X509Extensions.GetInstance(derTaggedObject);
                    break;
                }
            }
        }
예제 #4
0
        private string GetResponderName(ResponderID responderId, ref bool byKey)
        {
            DerTaggedObject derTaggedObject = (DerTaggedObject)responderId.ToAsn1Object();

            if (derTaggedObject.TagNo != 1)
            {
                if (derTaggedObject.TagNo != 2)
                {
                    return(null);
                }
                Asn1TaggedObject asn1TaggedObject = (Asn1TaggedObject)responderId.ToAsn1Object();
                Asn1OctetString  asn1OctetString  = (Asn1OctetString)asn1TaggedObject.GetObject();
                byKey = true;
                return(Convert.ToBase64String(asn1OctetString.GetOctets()));
            }
            X509Name instance = X509Name.GetInstance(derTaggedObject.GetObject());

            byKey = false;
            return(instance.ToString());
        }
예제 #5
0
        private CrlIdentifier(
            Asn1Sequence seq)
        {
            if (seq == null)
            {
                throw new ArgumentNullException("seq");
            }
            if (seq.Count < 2 || seq.Count > 3)
            {
                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
            }

            this.crlIssuer     = X509Name.GetInstance(seq[0]);
            this.crlIssuedTime = DerUtcTime.GetInstance(seq[1]);

            if (seq.Count > 2)
            {
                this.crlNumber = DerInteger.GetInstance(seq[2]);
            }
        }
예제 #6
0
 public static ResponderID GetInstance(object obj)
 {
     if (obj == null || obj is ResponderID)
     {
         return((ResponderID)obj);
     }
     if (obj is DerOctetString)
     {
         return(new ResponderID((DerOctetString)obj));
     }
     if (obj is Asn1TaggedObject)
     {
         Asn1TaggedObject asn1TaggedObject = (Asn1TaggedObject)obj;
         if (asn1TaggedObject.TagNo == 1)
         {
             return(new ResponderID(X509Name.GetInstance(asn1TaggedObject, explicitly: true)));
         }
         return(new ResponderID(Asn1OctetString.GetInstance(asn1TaggedObject, isExplicit: true)));
     }
     return(new ResponderID(X509Name.GetInstance(obj)));
 }
 private bool MatchesDN(X509Name subject, GeneralNames targets)
 {
     GeneralName[] names = targets.GetNames();
     for (int num = 0; num != names.Length; num++)
     {
         GeneralName generalName = names[num];
         if (generalName.TagNo == 4)
         {
             try
             {
                 if (X509Name.GetInstance(generalName.Name).Equivalent(subject))
                 {
                     return(true);
                 }
             }
             catch (Exception)
             {
             }
         }
     }
     return(false);
 }
예제 #8
0
        public static ResponderID GetInstance(object obj)
        {
            if ((obj == null) || (obj is ResponderID))
            {
                return((ResponderID)obj);
            }
            if (obj is DerOctetString)
            {
                return(new ResponderID((DerOctetString)obj));
            }
            if (!(obj is Asn1TaggedObject))
            {
                return(new ResponderID(X509Name.GetInstance(obj)));
            }
            Asn1TaggedObject obj2 = (Asn1TaggedObject)obj;

            if (obj2.TagNo == 1)
            {
                return(new ResponderID(X509Name.GetInstance(obj2, true)));
            }
            return(new ResponderID(Asn1OctetString.GetInstance(obj2, true)));
        }
        /// <summary>
        /// Generates the certificate request by params
        /// </summary>
        /// <param name="param">Certificate request params</param>
        public void Generate(CertificateRequestParams param, RSA key)
        {
            //Requested Certificate Name
            X509Name name = string.IsNullOrEmpty(param.CommonName) ? X509Name.GetInstance(new DerSequence(new DerSet())) : new X509Name(param.CommonName);

            string signatureAlgorithm = param.SignatureAlgorithm.ToString();

            var keyPair = DotNetUtilities.GetRsaKeyPair(key);

            //Attributes
            Asn1Set attr = null;

            if (param.Attributes != null)
            {
                attr = new DerSet(param.Attributes.Select(o => Asn1Object.FromByteArray(o.Export())).ToArray());
            }

            //PKCS #10 Certificate Signing Request
            var bcCSR = new Pkcs10CertificationRequest(signatureAlgorithm, name, keyPair.Public, attr, keyPair.Private);

            Import(bcCSR.GetEncoded());
        }
예제 #10
0
        private object[] GetNames()
        {
            GeneralNames name;

            if (form is V2Form)
            {
                name = ((V2Form)form).IssuerName;
            }
            else
            {
                name = (GeneralNames)form;
            }

            GeneralName[] names = name.GetNames();

            int count = 0;

            for (int i = 0; i != names.Length; i++)
            {
                if (names[i].TagNo == GeneralName.DirectoryName)
                {
                    ++count;
                }
            }

            object[] result = new object[count];

            int pos = 0;

            for (int i = 0; i != names.Length; i++)
            {
                if (names[i].TagNo == GeneralName.DirectoryName)
                {
                    result[pos++] = X509Name.GetInstance(names[i].Name);
                }
            }

            return(result);
        }
예제 #11
0
 private bool MatchesDN(X509Name subject, GeneralNames targets)
 {
     GeneralName[] names = targets.GetNames();
     for (int i = 0; i != names.Length; i++)
     {
         GeneralName generalName = names[i];
         if (generalName.TagNo != 4)
         {
             continue;
         }
         try
         {
             if (X509Name.GetInstance(generalName.Name).Equivalent(subject))
             {
                 return(true);
             }
         }
         catch (global::System.Exception)
         {
         }
     }
     return(false);
 }
예제 #12
0
        private object[] GetNames(GeneralName[] names)
        {
            int num = 0;

            for (int i = 0; i != names.Length; i++)
            {
                if (names[i].TagNo == 4)
                {
                    num++;
                }
            }
            object[] array = new object[num];
            int      num2  = 0;

            for (int j = 0; j != names.Length; j++)
            {
                if (names[j].TagNo == 4)
                {
                    array[num2++] = X509Name.GetInstance(names[j].Name);
                }
            }
            return(array);
        }
        private object[] GetNames(GeneralName[] names)
        {
            int num = 0;

            for (int num2 = 0; num2 != names.Length; num2++)
            {
                if (names[num2].TagNo == 4)
                {
                    num++;
                }
            }
            object[] array = new object[num];
            int      num3  = 0;

            for (int num4 = 0; num4 != names.Length; num4++)
            {
                if (names[num4].TagNo == 4)
                {
                    array[num3++] = X509Name.GetInstance(names[num4].Name);
                }
            }
            return(array);
        }
예제 #14
0
 internal static void GetCrlIssuersFromDistributionPoint(DistributionPoint dp, global::System.Collections.ICollection issuerPrincipals, X509CrlStoreSelector selector, PkixParameters pkixParams)
 {
     //IL_0045: Expected O, but got Unknown
     global::System.Collections.IList list = Platform.CreateArrayList();
     if (dp.CrlIssuer != null)
     {
         GeneralName[] names = dp.CrlIssuer.GetNames();
         for (int i = 0; i < names.Length; i++)
         {
             if (names[i].TagNo == 4)
             {
                 try
                 {
                     list.Add((object)X509Name.GetInstance(names[i].Name.ToAsn1Object()));
                 }
                 catch (IOException val)
                 {
                     IOException val2 = val;
                     throw new global::System.Exception("CRL issuer information from distribution point cannot be decoded.", (global::System.Exception)(object) val2);
                 }
             }
         }
     }
     else
     {
         if (dp.DistributionPointName == null)
         {
             throw new global::System.Exception("CRL issuer is omitted from distribution point but no distributionPoint field present.");
         }
         global::System.Collections.IEnumerator enumerator = ((global::System.Collections.IEnumerable)issuerPrincipals).GetEnumerator();
         while (enumerator.MoveNext())
         {
             list.Add((object)(X509Name)enumerator.get_Current());
         }
     }
     selector.Issuers = (global::System.Collections.ICollection)list;
 }
예제 #15
0
        private LinkedCertificate(Asn1Sequence seq)
        {
            this.mDigest       = DigestInfo.GetInstance(seq[0]);
            this.mCertLocation = GeneralName.GetInstance(seq[1]);

            for (int i = 2; i < seq.Count; ++i)
            {
                Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[i]);

                switch (tagged.TagNo)
                {
                case 0:
                    this.mCertIssuer = X509Name.GetInstance(tagged, false);
                    break;

                case 1:
                    this.mCACerts = GeneralNames.GetInstance(tagged, false);
                    break;

                default:
                    throw new ArgumentException("unknown tag in tagged field");
                }
            }
        }
예제 #16
0
        internal static void GetCrlIssuersFromDistributionPoint(DistributionPoint dp, ICollection issuerPrincipals, X509CrlStoreSelector selector, PkixParameters pkixParams)
        {
            IList list = Platform.CreateArrayList();

            if (dp.CrlIssuer != null)
            {
                GeneralName[] names = dp.CrlIssuer.GetNames();
                for (int i = 0; i < names.Length; i++)
                {
                    if (names[i].TagNo == 4)
                    {
                        try
                        {
                            list.Add(X509Name.GetInstance(names[i].Name.ToAsn1Object()));
                        }
                        catch (IOException innerException)
                        {
                            throw new Exception("CRL issuer information from distribution point cannot be decoded.", innerException);
                        }
                    }
                }
            }
            else
            {
                if (dp.DistributionPointName == null)
                {
                    throw new Exception("CRL issuer is omitted from distribution point but no distributionPoint field present.");
                }
                IEnumerator enumerator = issuerPrincipals.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    list.Add((X509Name)enumerator.Current);
                }
            }
            selector.Issuers = list;
        }
예제 #17
0
    public override string ToString()
    {
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.Append(tag);
        stringBuilder.Append(": ");
        switch (tag)
        {
        case 1:
        case 2:
        case 6:
            stringBuilder.Append(DerIA5String.GetInstance(obj).GetString());
            break;

        case 4:
            stringBuilder.Append(X509Name.GetInstance(obj).ToString());
            break;

        default:
            stringBuilder.Append(obj.ToString());
            break;
        }
        return(stringBuilder.ToString());
    }
        private CertificationRequestInfo(
            Asn1Sequence seq)
        {
            version = (DerInteger)seq[0];

            subject       = X509Name.GetInstance(seq[1]);
            subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[2]);

            //
            // some CertificationRequestInfo objects seem to treat this field
            // as optional.
            //
            if (seq.Count > 3)
            {
                DerTaggedObject tagobj = (DerTaggedObject)seq[3];
                attributes = Asn1Set.GetInstance(tagobj, false);
            }

            if (subject == null || version == null || subjectPKInfo == null)
            {
                throw new ArgumentException(
                          "Not all mandatory fields set in CertificationRequestInfo generator.");
            }
        }
        ///// <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="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 static SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName,
                                                             byte[] serialNumber, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore,
                                                             DateTime notAfter, SystemX509.X509ExtensionCollection extensions)
        {
            SecureRandom random = new SecureRandom();
            X509V3CertificateGenerator builder      = new X509V3CertificateGenerator();
            AsymmetricCipherKeyPair    bcSubjectKey = CreateRSAKey(keySize, random);
            AsymmetricCipherKeyPair    bcSignKey    = issuer == null ? bcSubjectKey : issuer.GetBCPrivateKey();

            if (bcSignKey == null)
            {
                throw new ArgumentException("issuer");
            }

            X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData))
                                         : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData));

            X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData));

            BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray());
            BigInteger issuerSerial  = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber());

            builder.SetIssuerDN(issuerNameObj);
            builder.SetSubjectDN(subjectNameObj);
            builder.SetSerialNumber(subjectSerial);
            builder.SetNotBefore(notBefore.ToUniversalTime());
            builder.SetNotAfter(notAfter.ToUniversalTime());
            builder.SetPublicKey(bcSubjectKey.Public);

            SubjectPublicKeyInfo   info         = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public);
            AuthorityKeyIdentifier authKeyId    = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial);
            SubjectKeyIdentifier   subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public));

            builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId);
            builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid);

            if (extensions != null)
            {
                foreach (SystemX509.X509Extension ext in extensions)
                {
                    if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2))
                    {
                        Asn1InputStream istm = new Asn1InputStream(ext.RawData);
                        Asn1Object      obj  = istm.ReadObject();
                        builder.AddExtension(ext.Oid.Value, ext.Critical, obj);
                    }
                }
            }

            X509Certificate cert = builder.Generate(CreateSignatureFactory(hashAlgorithm, bcSignKey, random));

            Pkcs12StoreBuilder   pkcs  = new Pkcs12StoreBuilder();
            Pkcs12Store          store = pkcs.Build();
            X509CertificateEntry entry = new X509CertificateEntry(cert);

            store.SetCertificateEntry("main", entry);

            AsymmetricKeyEntry key_entry = new AsymmetricKeyEntry(bcSubjectKey.Private);

            store.SetKeyEntry("main", key_entry, new[] { entry });
            MemoryStream stm = new MemoryStream();

            store.Save(stm, new char[0], new SecureRandom());
            return(new SystemX509.X509Certificate2(stm.ToArray(), String.Empty, SystemX509.X509KeyStorageFlags.Exportable));
        }
        /**
         * Validate the time stamp token.
         * <p>
         * To be valid the token must be signed by the passed in certificate and
         * the certificate must be the one referred to by the SigningCertificate
         * attribute included in the hashed attributes of the token. The
         * certificate must also have the ExtendedKeyUsageExtension with only
         * KeyPurposeID.IdKPTimeStamping and have been valid at the time the
         * timestamp was created.
         * </p>
         * <p>
         * A successful call to validate means all the above are true.
         * </p>
         */
        public void Validate(
            X509Certificate cert)
        {
            try
            {
                byte[] hash = DigestUtilities.CalculateDigest(
                    certID.GetHashAlgorithm(), cert.GetEncoded());

                if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash))
                {
                    throw new TspValidationException("certificate hash does not match certID hash.");
                }

                if (certID.IssuerSerial != null)
                {
                    if (!certID.IssuerSerial.Serial.Value.Equals(cert.SerialNumber))
                    {
                        throw new TspValidationException("certificate serial number does not match certID for signature.");
                    }

                    GeneralName[] names     = certID.IssuerSerial.Issuer.GetNames();
                    X509Name      principal = PrincipalUtilities.GetIssuerX509Principal(cert);
                    bool          found     = false;

                    for (int i = 0; i != names.Length; i++)
                    {
                        if (names[i].TagNo == 4 &&
                            X509Name.GetInstance(names[i].Name).Equivalent(principal))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        throw new TspValidationException("certificate name does not match certID for signature. ");
                    }
                }

                TspUtil.ValidateCertificate(cert);

                cert.CheckValidity(tstInfo.GenTime);

                if (!tsaSignerInfo.Verify(cert))
                {
                    throw new TspValidationException("signature not created by certificate.");
                }
            }
            catch (CmsException e)
            {
                if (e.InnerException != null)
                {
                    throw new TspException(e.Message, e.InnerException);
                }

                throw new TspException("CMS exception: " + e, e);
            }
            catch (CertificateEncodingException e)
            {
                throw new TspException("problem processing certificate: " + e, e);
            }
            catch (SecurityUtilityException e)
            {
                throw new TspException("cannot find algorithm: " + e.Message, e);
            }
        }
예제 #21
0
 internal static X509Name GetIssuerX509Name(Asn1Sequence issuerAndSerialNumber)
 {
     return(X509Name.GetInstance(issuerAndSerialNumber[0]));
 }
예제 #22
0
 public IssuerAndSerialNumber(
     Asn1Sequence seq)
 {
     this.name         = X509Name.GetInstance(seq[0]);
     this.serialNumber = (DerInteger)seq[1];
 }
예제 #23
0
        /**
         * Checks if an attribute certificate is revoked.
         *
         * @param attrCert Attribute certificate to check if it is revoked.
         * @param paramsPKIX PKIX parameters.
         * @param issuerCert The issuer certificate of the attribute certificate
         *            <code>attrCert</code>.
         * @param validDate The date when the certificate revocation status should
         *            be checked.
         * @param certPathCerts The certificates of the certification path to be
         *            checked.
         *
         * @throws CertPathValidatorException if the certificate is revoked or the
         *             status cannot be checked or some error occurs.
         */
        internal static void CheckCrls(
            IX509AttributeCertificate attrCert,
            PkixParameters paramsPKIX,
            X509Certificate issuerCert,
            DateTime validDate,
            IList certPathCerts)
        {
            if (!paramsPKIX.IsRevocationEnabled)
            {
                return;
            }

            // check if revocation is available
            if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) != null)
            {
                if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null ||
                    attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null)
                {
                    throw new PkixCertPathValidatorException(
                              "No rev avail extension is set, but also an AC revocation pointer.");
                }

                return;
            }

            CrlDistPoint crldp = null;

            try
            {
                crldp = CrlDistPoint.GetInstance(
                    PkixCertPathValidatorUtilities.GetExtensionValue(
                        attrCert, X509Extensions.CrlDistributionPoints));
            }
            catch (Exception e)
            {
                throw new PkixCertPathValidatorException(
                          "CRL distribution point extension could not be read.", e);
            }
            try
            {
                PkixCertPathValidatorUtilities
                .AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
            }
            catch (Exception e)
            {
                throw new PkixCertPathValidatorException(
                          "No additional CRL locations could be decoded from CRL distribution point extension.", e);
            }

            CertStatus  certStatus  = new CertStatus();
            ReasonsMask reasonsMask = new ReasonsMask();

            Exception lastException = null;
            bool      validCrlFound = false;

            // for each distribution point
            if (crldp != null)
            {
                DistributionPoint[] dps = null;
                try
                {
                    dps = crldp.GetDistributionPoints();
                }
                catch (Exception e)
                {
                    throw new PkixCertPathValidatorException(
                              "Distribution points could not be read.", e);
                }
                try
                {
                    for (int i = 0; i < dps.Length &&
                         certStatus.Status == CertStatus.Unrevoked &&
                         !reasonsMask.IsAllReasons; i++)
                    {
                        PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX
                                                         .Clone();
                        CheckCrl(dps[i], attrCert, paramsPKIXClone,
                                 validDate, issuerCert, certStatus, reasonsMask,
                                 certPathCerts);
                        validCrlFound = true;
                    }
                }
                catch (Exception e)
                {
                    lastException = new Exception(
                        "No valid CRL for distribution point found.", e);
                }
            }

            /*
             * If the revocation status has not been determined, repeat the
             * process above with any available CRLs not specified in a
             * distribution point but issued by the certificate issuer.
             */

            if (certStatus.Status == CertStatus.Unrevoked &&
                !reasonsMask.IsAllReasons)
            {
                try
                {
                    /*
                     * assume a DP with both the reasons and the cRLIssuer
                     * fields omitted and a distribution point name of the
                     * certificate issuer.
                     */
                    X509Name issuer;
                    try
                    {
                        issuer = X509Name.GetInstance(attrCert.Issuer.GetPrincipals()[0].GetEncoded());
                    }
                    catch (Exception e)
                    {
                        throw new Exception(
                                  "Issuer from certificate for CRL could not be reencoded.",
                                  e);
                    }
                    DistributionPoint dp = new DistributionPoint(
                        new DistributionPointName(0, new GeneralNames(
                                                      new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
                    PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();
                    CheckCrl(dp, attrCert, paramsPKIXClone, validDate,
                             issuerCert, certStatus, reasonsMask, certPathCerts);
                    validCrlFound = true;
                }
                catch (Exception e)
                {
                    lastException = new Exception(
                        "No valid CRL for distribution point found.", e);
                }
            }

            if (!validCrlFound)
            {
                throw new PkixCertPathValidatorException(
                          "No valid CRL found.", lastException);
            }
            if (certStatus.Status != CertStatus.Unrevoked)
            {
                // This format is enforced by the NistCertPath tests
                string formattedDate = certStatus.RevocationDate.Value.ToString(
                    "ddd MMM dd HH:mm:ss K yyyy");
                string message = "Attribute certificate revocation after "
                                 + formattedDate;
                message += ", reason: "
                           + Rfc3280CertPathUtilities.CrlReasons[certStatus.Status];
                throw new PkixCertPathValidatorException(message);
            }
            if (!reasonsMask.IsAllReasons &&
                certStatus.Status == CertStatus.Unrevoked)
            {
                certStatus.Status = CertStatus.Undetermined;
            }
            if (certStatus.Status == CertStatus.Undetermined)
            {
                throw new PkixCertPathValidatorException(
                          "Attribute certificate status could not be determined.");
            }
        }
예제 #24
0
        private void ProcessHandshakeMessage(HandshakeType type, byte[] buf)
        {
            MemoryStream inStr = new MemoryStream(buf, false);

            /*
             * Check the type.
             */
            switch (type)
            {
            case HandshakeType.certificate:
            {
                switch (connection_state)
                {
                case CS_SERVER_HELLO_RECEIVED:
                {
                    // Parse the Certificate message and send to cipher suite

                    Certificate serverCertificate = Certificate.Parse(inStr);

                    AssertEmpty(inStr);

                    this.keyExchange.ProcessServerCertificate(serverCertificate);

                    this.authentication = tlsClient.GetAuthentication();
                    this.authentication.NotifyServerCertificate(serverCertificate);

                    break;
                }

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    break;
                }

                connection_state = CS_SERVER_CERTIFICATE_RECEIVED;
                break;
            }

            case HandshakeType.finished:
                switch (connection_state)
                {
                case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED:
                    /*
                     * Read the checksum from the finished message, it has always 12 bytes.
                     */
                    byte[] serverVerifyData = new byte[12];
                    TlsUtilities.ReadFully(serverVerifyData, inStr);

                    AssertEmpty(inStr);

                    /*
                     * Calculate our own checksum.
                     */
                    byte[] expectedServerVerifyData = TlsUtilities.PRF(
                        securityParameters.masterSecret, "server finished",
                        rs.GetCurrentHash(), 12);

                    /*
                     * Compare both checksums.
                     */
                    if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData))
                    {
                        /*
                         * Wrong checksum in the finished message.
                         */
                        this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
                    }

                    connection_state = CS_DONE;

                    /*
                     * We are now ready to receive application data.
                     */
                    this.appDataReady = true;
                    break;

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    break;
                }
                break;

            case HandshakeType.server_hello:
                switch (connection_state)
                {
                case CS_CLIENT_HELLO_SEND:
                    /*
                     * Read the server hello message
                     */
                    TlsUtilities.CheckVersion(inStr, this);

                    /*
                     * Read the server random
                     */
                    securityParameters.serverRandom = new byte[32];
                    TlsUtilities.ReadFully(securityParameters.serverRandom, inStr);

                    byte[] sessionID = TlsUtilities.ReadOpaque8(inStr);
                    if (sessionID.Length > 32)
                    {
                        this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
                    }

                    this.tlsClient.NotifySessionID(sessionID);

                    /*
                     * Find out which CipherSuite the server has chosen and check that
                     * it was one of the offered ones.
                     */
                    CipherSuite selectedCipherSuite = (CipherSuite)TlsUtilities.ReadUint16(inStr);
                    if (!ArrayContains(offeredCipherSuites, selectedCipherSuite) ||
                        selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
                    {
                        this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
                    }

                    this.tlsClient.NotifySelectedCipherSuite(selectedCipherSuite);

                    /*
                     * Find out which CompressionMethod the server has chosen and check that
                     * it was one of the offered ones.
                     */
                    CompressionMethod selectedCompressionMethod = (CompressionMethod)TlsUtilities.ReadUint8(inStr);
                    if (!ArrayContains(offeredCompressionMethods, selectedCompressionMethod))
                    {
                        this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
                    }

                    this.tlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod);

                    /*
                     * RFC3546 2.2 The extended server hello message format MAY be
                     * sent in place of the server hello message when the client has
                     * requested extended functionality via the extended client hello
                     * message specified in Section 2.1.
                     * ...
                     * Note that the extended server hello message is only sent in response
                     * to an extended client hello message.  This prevents the possibility
                     * that the extended server hello message could "break" existing TLS 1.0
                     * clients.
                     */

                    /*
                     * TODO RFC 3546 2.3
                     * If [...] the older session is resumed, then the server MUST ignore
                     * extensions appearing in the client hello, and send a server hello
                     * containing no extensions.
                     */

                    // ExtensionType -> byte[]
                    IDictionary serverExtensions = Platform.CreateHashtable();

                    if (inStr.Position < inStr.Length)
                    {
                        // Process extensions from extended server hello
                        byte[] extBytes = TlsUtilities.ReadOpaque16(inStr);

                        MemoryStream ext = new MemoryStream(extBytes, false);
                        while (ext.Position < ext.Length)
                        {
                            ExtensionType extType  = (ExtensionType)TlsUtilities.ReadUint16(ext);
                            byte[]        extValue = TlsUtilities.ReadOpaque16(ext);

                            // Note: RFC 5746 makes a special case for EXT_RenegotiationInfo
                            if (extType != ExtensionType.renegotiation_info &&
                                !clientExtensions.Contains(extType))
                            {
                                /*
                                 * RFC 3546 2.3
                                 * Note that for all extension types (including those defined in
                                 * future), the extension type MUST NOT appear in the extended server
                                 * hello unless the same extension type appeared in the corresponding
                                 * client hello.  Thus clients MUST abort the handshake if they receive
                                 * an extension type in the extended server hello that they did not
                                 * request in the associated (extended) client hello.
                                 */
                                this.FailWithError(AlertLevel.fatal, AlertDescription.unsupported_extension);
                            }

                            if (serverExtensions.Contains(extType))
                            {
                                /*
                                 * RFC 3546 2.3
                                 * Also note that when multiple extensions of different types are
                                 * present in the extended client hello or the extended server hello,
                                 * the extensions may appear in any order. There MUST NOT be more than
                                 * one extension of the same type.
                                 */
                                this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
                            }

                            serverExtensions.Add(extType, extValue);
                        }
                    }

                    AssertEmpty(inStr);

                    /*
                     * RFC 5746 3.4. When a ServerHello is received, the client MUST check if it
                     * includes the "renegotiation_info" extension:
                     */
                    {
                        bool secure_negotiation = serverExtensions.Contains(ExtensionType.renegotiation_info);

                        /*
                         * If the extension is present, set the secure_renegotiation flag
                         * to TRUE.  The client MUST then verify that the length of the
                         * "renegotiated_connection" field is zero, and if it is not, MUST
                         * abort the handshake (by sending a fatal handshake_failure
                         * alert).
                         */
                        if (secure_negotiation)
                        {
                            byte[] renegExtValue = (byte[])serverExtensions[ExtensionType.renegotiation_info];

                            if (!Arrays.ConstantTimeAreEqual(renegExtValue,
                                                             CreateRenegotiationInfo(emptybuf)))
                            {
                                this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
                            }
                        }

                        tlsClient.NotifySecureRenegotiation(secure_negotiation);
                    }

                    if (clientExtensions != null)
                    {
                        tlsClient.ProcessServerExtensions(serverExtensions);
                    }

                    this.keyExchange = tlsClient.GetKeyExchange();

                    connection_state = CS_SERVER_HELLO_RECEIVED;
                    break;

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    break;
                }
                break;

            case HandshakeType.server_hello_done:
                switch (connection_state)
                {
                case CS_SERVER_CERTIFICATE_RECEIVED:
                case CS_SERVER_KEY_EXCHANGE_RECEIVED:
                case CS_CERTIFICATE_REQUEST_RECEIVED:

                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
                    {
                        // There was no server key exchange message; check it's OK
                        this.keyExchange.SkipServerKeyExchange();
                    }

                    AssertEmpty(inStr);

                    connection_state = CS_SERVER_HELLO_DONE_RECEIVED;

                    TlsCredentials clientCreds = null;
                    if (certificateRequest == null)
                    {
                        this.keyExchange.SkipClientCredentials();
                    }
                    else
                    {
                        clientCreds = this.authentication.GetClientCredentials(certificateRequest);

                        Certificate clientCert;
                        if (clientCreds == null)
                        {
                            this.keyExchange.SkipClientCredentials();
                            clientCert = Certificate.EmptyChain;
                        }
                        else
                        {
                            this.keyExchange.ProcessClientCredentials(clientCreds);
                            clientCert = clientCreds.Certificate;
                        }

                        SendClientCertificate(clientCert);
                    }

                    /*
                     * Send the client key exchange message, depending on the key
                     * exchange we are using in our CipherSuite.
                     */
                    SendClientKeyExchange();

                    connection_state = CS_CLIENT_KEY_EXCHANGE_SEND;

                    if (clientCreds != null && clientCreds is TlsSignerCredentials)
                    {
                        TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds;
                        byte[] md5andsha1 = rs.GetCurrentHash();
                        byte[] clientCertificateSignature = signerCreds.GenerateCertificateSignature(
                            md5andsha1);
                        SendCertificateVerify(clientCertificateSignature);

                        connection_state = CS_CERTIFICATE_VERIFY_SEND;
                    }

                    /*
                     * Now, we send change cipher state
                     */
                    byte[] cmessage = new byte[1];
                    cmessage[0] = 1;
                    rs.WriteMessage(ContentType.change_cipher_spec, cmessage, 0, cmessage.Length);

                    connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND;

                    /*
                     * Calculate the master_secret
                     */
                    byte[] pms = this.keyExchange.GeneratePremasterSecret();

                    securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret",
                                                                       TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom),
                                                                       48);

                    // TODO Is there a way to ensure the data is really overwritten?

                    /*
                     * RFC 2246 8.1. The pre_master_secret should be deleted from
                     * memory once the master_secret has been computed.
                     */
                    Array.Clear(pms, 0, pms.Length);

                    /*
                     * Initialize our cipher suite
                     */
                    rs.ClientCipherSpecDecided(tlsClient.GetCompression(), tlsClient.GetCipher());

                    /*
                     * Send our finished message.
                     */
                    byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret,
                                                               "client finished", rs.GetCurrentHash(), 12);

                    MemoryStream bos = new MemoryStream();
                    TlsUtilities.WriteUint8((byte)HandshakeType.finished, bos);
                    TlsUtilities.WriteOpaque24(clientVerifyData, bos);
                    byte[] message = bos.ToArray();

                    rs.WriteMessage(ContentType.handshake, message, 0, message.Length);

                    this.connection_state = CS_CLIENT_FINISHED_SEND;
                    break;

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
                    break;
                }
                break;

            case HandshakeType.server_key_exchange:
            {
                switch (connection_state)
                {
                case CS_SERVER_HELLO_RECEIVED:
                case CS_SERVER_CERTIFICATE_RECEIVED:
                {
                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_HELLO_RECEIVED)
                    {
                        // There was no server certificate message; check it's OK
                        this.keyExchange.SkipServerCertificate();
                        this.authentication = null;
                    }

                    this.keyExchange.ProcessServerKeyExchange(inStr);

                    AssertEmpty(inStr);
                    break;
                }

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    break;
                }

                this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED;
                break;
            }

            case HandshakeType.certificate_request:
                switch (connection_state)
                {
                case CS_SERVER_CERTIFICATE_RECEIVED:
                case CS_SERVER_KEY_EXCHANGE_RECEIVED:
                {
                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
                    {
                        // There was no server key exchange message; check it's OK
                        this.keyExchange.SkipServerKeyExchange();
                    }

                    if (this.authentication == null)
                    {
                        /*
                         * RFC 2246 7.4.4. It is a fatal handshake_failure alert
                         * for an anonymous server to request client identification.
                         */
                        this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
                    }

                    int numTypes = TlsUtilities.ReadUint8(inStr);
                    ClientCertificateType[] certificateTypes = new ClientCertificateType[numTypes];
                    for (int i = 0; i < numTypes; ++i)
                    {
                        certificateTypes[i] = (ClientCertificateType)TlsUtilities.ReadUint8(inStr);
                    }

                    byte[] authorities = TlsUtilities.ReadOpaque16(inStr);

                    AssertEmpty(inStr);

                    IList authorityDNs = Platform.CreateArrayList();

                    MemoryStream bis = new MemoryStream(authorities, false);
                    while (bis.Position < bis.Length)
                    {
                        byte[] dnBytes = TlsUtilities.ReadOpaque16(bis);
                        // TODO Switch to X500Name when available
                        authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes)));
                    }

                    this.certificateRequest = new CertificateRequest(certificateTypes,
                                                                     authorityDNs);
                    this.keyExchange.ValidateCertificateRequest(this.certificateRequest);

                    break;
                }

                default:
                    this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    break;
                }

                this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED;
                break;

            case HandshakeType.hello_request:
                /*
                 * RFC 2246 7.4.1.1 Hello request
                 * This message will be ignored by the client if the client is currently
                 * negotiating a session. This message may be ignored by the client if it
                 * does not wish to renegotiate a session, or the client may, if it wishes,
                 * respond with a no_renegotiation alert.
                 */
                if (connection_state == CS_DONE)
                {
                    // Renegotiation not supported yet
                    SendAlert(AlertLevel.warning, AlertDescription.no_renegotiation);
                }
                break;

            case HandshakeType.client_key_exchange:
            case HandshakeType.certificate_verify:
            case HandshakeType.client_hello:
            default:
                // We do not support this!
                this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                break;
            }
        }
        /**
         * Add the CRL issuers from the cRLIssuer field of the distribution point or
         * from the certificate if not given to the issuer criterion of the
         * <code>selector</code>.
         * <p>
         * The <code>issuerPrincipals</code> are a collection with a single
         * <code>X500Principal</code> for <code>X509Certificate</code>s. For
         * {@link X509AttributeCertificate}s the issuer may contain more than one
         * <code>X500Principal</code>.
         * </p>
         *
         * @param dp The distribution point.
         * @param issuerPrincipals The issuers of the certificate or attribute
         *            certificate which contains the distribution point.
         * @param selector The CRL selector.
         * @param pkixParams The PKIX parameters containing the cert stores.
         * @throws Exception if an exception occurs while processing.
         * @throws ClassCastException if <code>issuerPrincipals</code> does not
         * contain only <code>X500Principal</code>s.
         */
        internal static void GetCrlIssuersFromDistributionPoint(
            DistributionPoint dp,
            ICollection issuerPrincipals,
            X509CrlStoreSelector selector,
            PkixParameters pkixParams)
        {
            IList issuers = Platform.CreateArrayList();

            // indirect CRL
            if (dp.CrlIssuer != null)
            {
                GeneralName[] genNames = dp.CrlIssuer.GetNames();
                // look for a DN
                for (int j = 0; j < genNames.Length; j++)
                {
                    if (genNames[j].TagNo == GeneralName.DirectoryName)
                    {
                        try
                        {
                            issuers.Add(X509Name.GetInstance(genNames[j].Name.ToAsn1Object()));
                        }
                        catch (IOException e)
                        {
                            throw new Exception(
                                      "CRL issuer information from distribution point cannot be decoded.",
                                      e);
                        }
                    }
                }
            }
            else
            {
                /*
                 * certificate issuer is CRL issuer, distributionPoint field MUST be
                 * present.
                 */
                if (dp.DistributionPointName == null)
                {
                    throw new Exception(
                              "CRL issuer is omitted from distribution point but no distributionPoint field present.");
                }

                // add and check issuer principals
                for (IEnumerator it = issuerPrincipals.GetEnumerator(); it.MoveNext();)
                {
                    issuers.Add((X509Name)it.Current);
                }
            }
            // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
            // distributionPoint
            //        if (dp.getDistributionPoint() != null)
            //        {
            //            // look for nameRelativeToCRLIssuer
            //            if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
            //            {
            //                // append fragment to issuer, only one
            //                // issuer can be there, if this is given
            //                if (issuers.size() != 1)
            //                {
            //                    throw new AnnotatedException(
            //                        "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
            //                }
            //                DEREncodable relName = dp.getDistributionPoint().getName();
            //                Iterator it = issuers.iterator();
            //                List issuersTemp = new ArrayList(issuers.size());
            //                while (it.hasNext())
            //                {
            //                    Enumeration e = null;
            //                    try
            //                    {
            //                        e = ASN1Sequence.getInstance(
            //                            new ASN1InputStream(((X500Principal) it.next())
            //                                .getEncoded()).readObject()).getObjects();
            //                    }
            //                    catch (IOException ex)
            //                    {
            //                        throw new AnnotatedException(
            //                            "Cannot decode CRL issuer information.", ex);
            //                    }
            //                    ASN1EncodableVector v = new ASN1EncodableVector();
            //                    while (e.hasMoreElements())
            //                    {
            //                        v.add((DEREncodable) e.nextElement());
            //                    }
            //                    v.add(relName);
            //                    issuersTemp.add(new X500Principal(new DERSequence(v)
            //                        .getDEREncoded()));
            //                }
            //                issuers.clear();
            //                issuers.addAll(issuersTemp);
            //            }
            //        }

            selector.Issuers = issuers;
        }
예제 #26
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 SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName,
                                                      byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore,
                                                      DateTime notAfter, SystemX509.X509ExtensionCollection extensions)
        {
            X509V3CertificateGenerator builder    = new X509V3CertificateGenerator();
            AsymmetricAlgorithm        subjectKey = CreateRSAKey(keySize, signature);
            AsymmetricAlgorithm        signKey    = issuer == null ? subjectKey : issuer.PrivateKey;

            if (signKey == null)
            {
                throw new ArgumentException(Properties.Resources.CreateCert_NoPrivateKey);
            }

            AsymmetricCipherKeyPair bcSubjectKey = GetRsaKeyPair((RSACryptoServiceProvider)subjectKey);
            AsymmetricCipherKeyPair bcSignKey    = GetRsaKeyPair((RSACryptoServiceProvider)signKey);

            X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData))
                                         : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData));

            X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData));

            BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray());
            BigInteger issuerSerial  = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber());

            builder.SetIssuerDN(issuerNameObj);
            builder.SetSubjectDN(subjectNameObj);
            builder.SetSerialNumber(subjectSerial);
            builder.SetSignatureAlgorithm(HashAlgorithmToName(hashAlgorithm));
            builder.SetNotBefore(notBefore.ToUniversalTime());
            builder.SetNotAfter(notAfter.ToUniversalTime());
            builder.SetPublicKey(bcSubjectKey.Public);

            SubjectPublicKeyInfo   info         = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public);
            AuthorityKeyIdentifier authKeyId    = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial);
            SubjectKeyIdentifier   subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public));

            builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId);
            builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid);

            if (extensions != null)
            {
                foreach (SystemX509.X509Extension ext in extensions)
                {
                    if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2))
                    {
                        Asn1InputStream istm = new Org.BouncyCastle.Asn1.Asn1InputStream(ext.RawData);
                        Asn1Object      obj  = istm.ReadObject();
                        builder.AddExtension(ext.Oid.Value, ext.Critical, obj);
                    }
                }
            }

            X509Certificate cert = builder.Generate(bcSignKey.Private);

            SystemX509.X509Certificate2 ret = new SystemX509.X509Certificate2(cert.GetEncoded(), (string)null, SystemX509.X509KeyStorageFlags.Exportable);

            ret.PrivateKey = subjectKey;

            return(ret);
        }
예제 #27
0
        public override void PerformTest()
        {
            doTestEncodingPrintableString(X509Name.C, "AU");
            doTestEncodingPrintableString(X509Name.SerialNumber, "123456");
            doTestEncodingPrintableString(X509Name.DnQualifier, "123456");
            doTestEncodingIA5String(X509Name.EmailAddress, "*****@*****.**");
            doTestEncodingIA5String(X509Name.DC, "test");
            // correct encoding
            doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "#180F32303032303132323132323232305A");
            // compatability encoding
            doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "20020122122220Z");

            //
            // composite
            //
            IDictionary attrs = new Hashtable();

            attrs.Add(X509Name.C, "AU");
            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
            attrs.Add(X509Name.L, "Melbourne");
            attrs.Add(X509Name.ST, "Victoria");
            attrs.Add(X509Name.E, "*****@*****.**");

            IList order = new ArrayList();

            order.Add(X509Name.C);
            order.Add(X509Name.O);
            order.Add(X509Name.L);
            order.Add(X509Name.ST);
            order.Add(X509Name.E);

            X509Name name1 = new X509Name(order, attrs);

            if (!name1.Equivalent(name1))
            {
                Fail("Failed same object test");
            }

            if (!name1.Equivalent(name1, true))
            {
                Fail("Failed same object test - in Order");
            }

            X509Name name2 = new X509Name(order, attrs);

            if (!name1.Equivalent(name2))
            {
                Fail("Failed same name test");
            }

            if (!name1.Equivalent(name2, true))
            {
                Fail("Failed same name test - in Order");
            }

            if (name1.GetHashCode() != name2.GetHashCode())
            {
                Fail("Failed same name test - in Order");
            }

            IList ord1 = new ArrayList();

            ord1.Add(X509Name.C);
            ord1.Add(X509Name.O);
            ord1.Add(X509Name.L);
            ord1.Add(X509Name.ST);
            ord1.Add(X509Name.E);

            IList ord2 = new ArrayList();

            ord2.Add(X509Name.E);
            ord2.Add(X509Name.ST);
            ord2.Add(X509Name.L);
            ord2.Add(X509Name.O);
            ord2.Add(X509Name.C);

            name1 = new X509Name(ord1, attrs);
            name2 = new X509Name(ord2, attrs);

            if (!name1.Equivalent(name2))
            {
                Fail("Failed reverse name test");
            }

            // FIXME Sort out X509Name hashcode problem
//			if (name1.GetHashCode() != name2.GetHashCode())
//			{
//				Fail("Failed reverse name test GetHashCode");
//			}

            if (name1.Equivalent(name2, true))
            {
                Fail("Failed reverse name test - in Order");
            }

            if (!name1.Equivalent(name2, false))
            {
                Fail("Failed reverse name test - in Order false");
            }

            IList oids = name1.GetOidList();

            if (!CompareVectors(oids, ord1))
            {
                Fail("oid comparison test");
            }

            IList val1 = new ArrayList();

            val1.Add("AU");
            val1.Add("The Legion of the Bouncy Castle");
            val1.Add("Melbourne");
            val1.Add("Victoria");
            val1.Add("*****@*****.**");

            name1 = new X509Name(ord1, val1);

            IList values = name1.GetValueList();

            if (!CompareVectors(values, val1))
            {
                Fail("value comparison test");
            }

            ord2 = new ArrayList();

            ord2.Add(X509Name.ST);
            ord2.Add(X509Name.ST);
            ord2.Add(X509Name.L);
            ord2.Add(X509Name.O);
            ord2.Add(X509Name.C);

            name1 = new X509Name(ord1, attrs);
            name2 = new X509Name(ord2, attrs);

            if (name1.Equivalent(name2))
            {
                Fail("Failed different name test");
            }

            ord2 = new ArrayList();

            ord2.Add(X509Name.ST);
            ord2.Add(X509Name.L);
            ord2.Add(X509Name.O);
            ord2.Add(X509Name.C);

            name1 = new X509Name(ord1, attrs);
            name2 = new X509Name(ord2, attrs);

            if (name1.Equivalent(name2))
            {
                Fail("Failed subset name test");
            }


            compositeTest();


            //
            // getValues test
            //
            IList v1 = name1.GetValueList(X509Name.O);

            if (v1.Count != 1 || !v1[0].Equals("The Legion of the Bouncy Castle"))
            {
                Fail("O test failed");
            }

            IList v2 = name1.GetValueList(X509Name.L);

            if (v2.Count != 1 || !v2[0].Equals("Melbourne"))
            {
                Fail("L test failed");
            }

            //
            // general subjects test
            //
            for (int i = 0; i != subjects.Length; i++)
            {
                X509Name name        = new X509Name(subjects[i]);
                byte[]   encodedName = name.GetEncoded();
                name = X509Name.GetInstance(Asn1Object.FromByteArray(encodedName));

                if (!name.ToString().Equals(subjects[i]))
                {
                    Fail("Failed regeneration test " + i);
                }
            }

            //
            // sort test
            //
            X509Name unsorted = new X509Name("SERIALNUMBER=BBB + CN=AA");

            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("CN=AA+SERIALNUMBER=BBB"))
            {
                Fail("Failed sort test 1");
            }

            unsorted = new X509Name("CN=AA + SERIALNUMBER=BBB");

            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("CN=AA+SERIALNUMBER=BBB"))
            {
                Fail("Failed sort test 2");
            }

            unsorted = new X509Name("SERIALNUMBER=B + CN=AA");

            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("SERIALNUMBER=B+CN=AA"))
            {
                Fail("Failed sort test 3");
            }

            unsorted = new X509Name("CN=AA + SERIALNUMBER=B");

            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("SERIALNUMBER=B+CN=AA"))
            {
                Fail("Failed sort test 4");
            }

            //
            // equality tests
            //
            equalityTest(new X509Name("CN=The     Legion"), new X509Name("CN=The Legion"));
            equalityTest(new X509Name("CN=   The Legion"), new X509Name("CN=The Legion"));
            equalityTest(new X509Name("CN=The Legion   "), new X509Name("CN=The Legion"));
            equalityTest(new X509Name("CN=  The     Legion "), new X509Name("CN=The Legion"));
            equalityTest(new X509Name("CN=  the     legion "), new X509Name("CN=The Legion"));

            // # test

            X509Name n1 = new X509Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
            X509Name n2 = new X509Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
            X509Name n3 = new X509Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");

            equalityTest(n1, n2);
            equalityTest(n2, n3);
            equalityTest(n3, n1);

            n1 = new X509Name(true, "2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
            n2 = new X509Name(true, "SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
            n3 = X509Name.GetInstance(Asn1Object.FromByteArray(Hex.Decode("3063310b3009060355040613024c54312f302d060355040a1326"
                                                                          + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));

            equalityTest(n1, n2);
            equalityTest(n2, n3);
            equalityTest(n3, n1);

            n1 = new X509Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
            n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");

            if (n1.Equivalent(n2))
            {
                Fail("empty inequality check failed");
            }

            n1 = new X509Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
            n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");

            equalityTest(n1, n2);

            //
            // inequality to sequences
            //
            name1 = new X509Name("CN=The Legion");

            if (name1.Equals(DerSequence.Empty))
            {
                Fail("inequality test with sequence");
            }

            if (name1.Equals(new DerSequence(DerSet.Empty)))
            {
                Fail("inequality test with sequence and set");
            }

            Asn1EncodableVector v = new Asn1EncodableVector(
                new DerObjectIdentifier("1.1"),
                new DerObjectIdentifier("1.1"));

            if (name1.Equals(new DerSequence(new DerSet(new DerSet(v)))))
            {
                Fail("inequality test with sequence and bad set");
            }

//			if (name1.Equals(new DerSequence(new DerSet(new DerSet(v))), true))
//			{
//				Fail("inequality test with sequence and bad set");
//			}
            try
            {
                X509Name.GetInstance(new DerSequence(new DerSet(new DerSet(v))));
                Fail("GetInstance should reject bad sequence");
            }
            catch (ArgumentException)
            {
                //expected
            }

            if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty))))
            {
                Fail("inequality test with sequence and short sequence");
            }

//			if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty)), true))
//			{
//				Fail("inequality test with sequence and short sequence");
//			}
            try
            {
                X509Name.GetInstance(new DerSequence(new DerSet(DerSequence.Empty)));
                Fail("GetInstance should reject short sequence");
            }
            catch (ArgumentException)
            {
                //expected
            }

            v = new Asn1EncodableVector(
                new DerObjectIdentifier("1.1"),
                DerSequence.Empty);

            if (name1.Equals(new DerSequence(new DerSet(new DerSequence(v)))))
            {
                Fail("inequality test with sequence and bad sequence");
            }

            if (name1.Equivalent(null))
            {
                Fail("inequality test with null");
            }

            if (name1.Equivalent(null, true))
            {
                Fail("inequality test with null");
            }

            //
            // this is contrived but it checks sorting of sets with equal elements
            //
            unsorted = new X509Name("CN=AA + CN=AA + CN=AA");

            //
            // tagging test - only works if CHOICE implemented
            //

            /*
             * ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X509Name("CN=AA"));
             *
             * if (!tag.isExplicit())
             * {
             *  Fail("failed to explicitly tag CHOICE object");
             * }
             *
             * X509Name name = X509Name.getInstance(tag, false);
             *
             * if (!name.equals(new X509Name("CN=AA")))
             * {
             *  Fail("failed to recover tagged name");
             * }
             */

            DerUtf8String testString = new DerUtf8String("The Legion of the Bouncy Castle");

            byte[] encodedBytes     = testString.GetEncoded();
            string hexEncodedString = "#" + Hex.ToHexString(encodedBytes);

            DerUtf8String converted = (DerUtf8String)
                                      new X509DefaultEntryConverter().GetConvertedValue(
                X509Name.L, hexEncodedString);

            if (!converted.Equals(testString))
            {
                Fail("Failed X509DefaultEntryConverter test");
            }

            //
            // try escaped.
            //
            converted = (DerUtf8String) new X509DefaultEntryConverter().GetConvertedValue(
                X509Name.L, "\\" + hexEncodedString);

            if (!converted.Equals(new DerUtf8String(hexEncodedString)))
            {
                Fail("Failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
            }

            //
            // try a weird value
            //
            X509Name n = new X509Name("CN=\\#nothex#string");

            if (!n.ToString().Equals("CN=\\#nothex#string"))
            {
                Fail("# string not properly escaped.");
            }

            IList vls = n.GetValueList(X509Name.CN);

            if (vls.Count != 1 || !vls[0].Equals("#nothex#string"))
            {
                Fail("Escaped # not reduced properly");
            }

            n = new X509Name("CN=\"a+b\"");

            vls = n.GetValueList(X509Name.CN);
            if (vls.Count != 1 || !vls[0].Equals("a+b"))
            {
                Fail("Escaped + not reduced properly");
            }

            n = new X509Name("CN=a\\+b");

            vls = n.GetValueList(X509Name.CN);
            if (vls.Count != 1 || !vls[0].Equals("a+b"))
            {
                Fail("Escaped + not reduced properly");
            }

            if (!n.ToString().Equals("CN=a\\+b"))
            {
                Fail("+ in string not properly escaped.");
            }

            n = new X509Name("CN=a\\=b");

            vls = n.GetValueList(X509Name.CN);
            if (vls.Count != 1 || !vls[0].Equals("a=b"))
            {
                Fail("Escaped = not reduced properly");
            }

            if (!n.ToString().Equals("CN=a\\=b"))
            {
                Fail("= in string not properly escaped.");
            }

            n = new X509Name("TELEPHONENUMBER=\"+61999999999\"");

            vls = n.GetValueList(X509Name.TelephoneNumber);
            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
            {
                Fail("telephonenumber escaped + not reduced properly");
            }

            n = new X509Name("TELEPHONENUMBER=\\+61999999999");

            vls = n.GetValueList(X509Name.TelephoneNumber);
            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
            {
                Fail("telephonenumber escaped + not reduced properly");
            }

            n = new X509Name(@"TELEPHONENUMBER=\+61999999999");

            vls = n.GetValueList(X509Name.TelephoneNumber);
            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
            {
                Fail("telephonenumber escaped + not reduced properly");
            }
        }
예제 #28
0
 private static X509Name FromBytes(
     byte[] bytes)
 {
     return(X509Name.GetInstance(Asn1Object.FromByteArray(bytes)));
 }
 /// <summary>
 /// Comprueba si dos DN son equivalentes
 /// </summary>
 /// <param name="dn"></param>
 /// <param name="other"></param>
 /// <returns></returns>
 private bool EquivalentDN(X500DistinguishedName dn, X500DistinguishedName other)
 {
     return(X509Name.GetInstance(Asn1Object.FromByteArray(dn.RawData)).Equivalent(X509Name.GetInstance(Asn1Object.FromByteArray(other.RawData))));
 }
예제 #30
0
        private void ProcessHandshakeMessage(short type, byte[] buf)
        {
            MemoryStream inStr = new MemoryStream(buf, false);

            /*
             * Check the type.
             */
            switch (type)
            {
            case HP_CERTIFICATE:
            {
                switch (connection_state)
                {
                case CS_SERVER_HELLO_RECEIVED:
                {
                    // Parse the Certificate message and send to cipher suite

                    Certificate serverCertificate = Certificate.Parse(inStr);

                    AssertEmpty(inStr);

                    this.keyExchange.ProcessServerCertificate(serverCertificate);

                    break;
                }

                default:
                    this.FailWithError(AL_fatal, AP_unexpected_message);
                    break;
                }

                connection_state = CS_SERVER_CERTIFICATE_RECEIVED;
                break;
            }

            case HP_FINISHED:
                switch (connection_state)
                {
                case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED:
                    /*
                     * Read the checksum from the finished message, it has always 12 bytes.
                     */
                    byte[] serverVerifyData = new byte[12];
                    TlsUtilities.ReadFully(serverVerifyData, inStr);

                    AssertEmpty(inStr);

                    /*
                     * Calculate our own checksum.
                     */
                    byte[] expectedServerVerifyData = TlsUtilities.PRF(
                        securityParameters.masterSecret, "server finished",
                        rs.GetCurrentHash(), 12);

                    /*
                     * Compare both checksums.
                     */
                    if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData))
                    {
                        /*
                         * Wrong checksum in the finished message.
                         */
                        this.FailWithError(AL_fatal, AP_handshake_failure);
                    }

                    connection_state = CS_DONE;

                    /*
                     * We are now ready to receive application data.
                     */
                    this.appDataReady = true;
                    break;

                default:
                    this.FailWithError(AL_fatal, AP_unexpected_message);
                    break;
                }
                break;

            case HP_SERVER_HELLO:
                switch (connection_state)
                {
                case CS_CLIENT_HELLO_SEND:
                    /*
                     * Read the server hello message
                     */
                    TlsUtilities.CheckVersion(inStr, this);

                    /*
                     * Read the server random
                     */
                    securityParameters.serverRandom = new byte[32];
                    TlsUtilities.ReadFully(securityParameters.serverRandom, inStr);

                    /*
                     * Currently, we don't support session ids
                     */
                    byte[] sessionID = TlsUtilities.ReadOpaque8(inStr);
                    if (sessionID.Length > 32)
                    {
                        this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter);
                    }

                    this.tlsClient.NotifySessionID(sessionID);

                    /*
                     * Find out which ciphersuite the server has chosen and check that
                     * it was one of the offered ones.
                     */
                    int selectedCipherSuite = TlsUtilities.ReadUint16(inStr);
                    if (!WasCipherSuiteOffered(selectedCipherSuite))
                    {
                        this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter);
                    }

                    this.tlsClient.NotifySelectedCipherSuite(selectedCipherSuite);

                    /*
                     * We support only the null compression which means no
                     * compression.
                     */
                    short compressionMethod = TlsUtilities.ReadUint8(inStr);
                    if (compressionMethod != 0)
                    {
                        this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter);
                    }

                    /*
                     * RFC4366 2.2 The extended server hello message format MAY be
                     * sent in place of the server hello message when the client has
                     * requested extended functionality via the extended client hello
                     * message specified in Section 2.1.
                     */
                    if (extendedClientHello)
                    {
                        // Integer -> byte[]
                        Hashtable serverExtensions = new Hashtable();

                        if (inStr.Position < inStr.Length)
                        {
                            // Process extensions from extended server hello
                            byte[] extBytes = TlsUtilities.ReadOpaque16(inStr);

                            MemoryStream ext = new MemoryStream(extBytes, false);
                            while (ext.Position < ext.Length)
                            {
                                int    extType  = TlsUtilities.ReadUint16(ext);
                                byte[] extValue = TlsUtilities.ReadOpaque16(ext);

                                serverExtensions.Add(extType, extValue);
                            }
                        }

                        // TODO[RFC 5746] If renegotiation_info was sent in client hello, check here

                        tlsClient.ProcessServerExtensions(serverExtensions);
                    }

                    AssertEmpty(inStr);

                    this.keyExchange = tlsClient.CreateKeyExchange();

                    connection_state = CS_SERVER_HELLO_RECEIVED;
                    break;

                default:
                    this.FailWithError(AL_fatal, AP_unexpected_message);
                    break;
                }
                break;

            case HP_SERVER_HELLO_DONE:
                switch (connection_state)
                {
                case CS_SERVER_CERTIFICATE_RECEIVED:
                case CS_SERVER_KEY_EXCHANGE_RECEIVED:
                case CS_CERTIFICATE_REQUEST_RECEIVED:

                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
                    {
                        // There was no server key exchange message; check it's OK
                        this.keyExchange.SkipServerKeyExchange();
                    }

                    AssertEmpty(inStr);

                    bool isClientCertificateRequested = (connection_state == CS_CERTIFICATE_REQUEST_RECEIVED);

                    connection_state = CS_SERVER_HELLO_DONE_RECEIVED;

                    if (isClientCertificateRequested)
                    {
                        SendClientCertificate(tlsClient.GetCertificate());
                    }

                    /*
                     * Send the client key exchange message, depending on the key
                     * exchange we are using in our ciphersuite.
                     */
                    SendClientKeyExchange(this.keyExchange.GenerateClientKeyExchange());

                    connection_state = CS_CLIENT_KEY_EXCHANGE_SEND;

                    if (isClientCertificateRequested)
                    {
                        byte[] clientCertificateSignature = tlsClient.GenerateCertificateSignature(rs.GetCurrentHash());
                        if (clientCertificateSignature != null)
                        {
                            SendCertificateVerify(clientCertificateSignature);

                            connection_state = CS_CERTIFICATE_VERIFY_SEND;
                        }
                    }

                    /*
                     * Now, we send change cipher state
                     */
                    byte[] cmessage = new byte[1];
                    cmessage[0] = 1;
                    rs.WriteMessage(RL_CHANGE_CIPHER_SPEC, cmessage, 0, cmessage.Length);

                    connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND;

                    /*
                     * Calculate the master_secret
                     */
                    byte[] pms = this.keyExchange.GeneratePremasterSecret();

                    securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret",
                                                                       TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom),
                                                                       48);

                    // TODO Is there a way to ensure the data is really overwritten?

                    /*
                     * RFC 2246 8.1. "The pre_master_secret should be deleted from
                     * memory once the master_secret has been computed."
                     */
                    Array.Clear(pms, 0, pms.Length);

                    /*
                     * Initialize our cipher suite
                     */
                    rs.ClientCipherSpecDecided(tlsClient.CreateCipher(securityParameters));

                    /*
                     * Send our finished message.
                     */
                    byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret,
                                                               "client finished", rs.GetCurrentHash(), 12);

                    MemoryStream bos = new MemoryStream();
                    TlsUtilities.WriteUint8(HP_FINISHED, bos);
                    TlsUtilities.WriteOpaque24(clientVerifyData, bos);
                    byte[] message = bos.ToArray();

                    rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length);

                    this.connection_state = CS_CLIENT_FINISHED_SEND;
                    break;

                default:
                    this.FailWithError(AL_fatal, AP_handshake_failure);
                    break;
                }
                break;

            case HP_SERVER_KEY_EXCHANGE:
            {
                switch (connection_state)
                {
                case CS_SERVER_HELLO_RECEIVED:
                case CS_SERVER_CERTIFICATE_RECEIVED:
                {
                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_HELLO_RECEIVED)
                    {
                        // There was no server certificate message; check it's OK
                        this.keyExchange.SkipServerCertificate();
                    }

                    this.keyExchange.ProcessServerKeyExchange(inStr, securityParameters);

                    AssertEmpty(inStr);
                    break;
                }

                default:
                    this.FailWithError(AL_fatal, AP_unexpected_message);
                    break;
                }

                this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED;
                break;
            }

            case HP_CERTIFICATE_REQUEST:
                switch (connection_state)
                {
                case CS_SERVER_CERTIFICATE_RECEIVED:
                case CS_SERVER_KEY_EXCHANGE_RECEIVED:
                {
                    // NB: Original code used case label fall-through
                    if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
                    {
                        // There was no server key exchange message; check it's OK
                        this.keyExchange.SkipServerKeyExchange();
                    }

                    byte[] types       = TlsUtilities.ReadOpaque8(inStr);
                    byte[] authorities = TlsUtilities.ReadOpaque16(inStr);

                    AssertEmpty(inStr);

                    ArrayList authorityDNs = new ArrayList();

                    MemoryStream bis = new MemoryStream(authorities, false);
                    while (bis.Position < bis.Length)
                    {
                        byte[] dnBytes = TlsUtilities.ReadOpaque16(bis);
                        authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes)));
                    }

                    this.tlsClient.ProcessServerCertificateRequest(types, authorityDNs);

                    break;
                }

                default:
                    this.FailWithError(AL_fatal, AP_unexpected_message);
                    break;
                }

                this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED;
                break;

            case HP_HELLO_REQUEST:
                /*
                 * RFC 2246 7.4.1.1 Hello request
                 * "This message will be ignored by the client if the client is currently
                 * negotiating a session. This message may be ignored by the client if it
                 * does not wish to renegotiate a session, or the client may, if it wishes,
                 * respond with a no_renegotiation alert."
                 */
                if (connection_state == CS_DONE)
                {
                    // Renegotiation not supported yet
                    SendAlert(AL_warning, AP_no_renegotiation);
                }
                break;

            case HP_CLIENT_KEY_EXCHANGE:
            case HP_CERTIFICATE_VERIFY:
            case HP_CLIENT_HELLO:
            default:
                // We do not support this!
                this.FailWithError(AL_fatal, AP_unexpected_message);
                break;
            }
        }