123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections;
- using System.IO;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
- {
- /// <summary>Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.</summary>
- /// <remarks>
- /// <pre>
- /// struct {
- /// ClientCertificateType certificate_types<1..2^8-1>;
- /// DistinguishedName certificate_authorities<3..2^16-1>;
- /// } CertificateRequest;
- /// </pre>
- /// Updated for RFC 5246:
- /// <pre>
- /// struct {
- /// ClientCertificateType certificate_types <1..2 ^ 8 - 1>;
- /// SignatureAndHashAlgorithm supported_signature_algorithms <2 ^ 16 - 1>;
- /// DistinguishedName certificate_authorities <0..2 ^ 16 - 1>;
- /// } CertificateRequest;
- /// </pre>
- /// Revised for RFC 8446:
- /// <pre>
- /// struct {
- /// opaque certificate_request_context <0..2 ^ 8 - 1>;
- /// Extension extensions <2..2 ^ 16 - 1>;
- /// } CertificateRequest;
- /// </pre>
- /// </remarks>
- /// <seealso cref="ClientCertificateType"/>
- /// <seealso cref="X509Name"/>
- public sealed class CertificateRequest
- {
- /// <exception cref="IOException"/>
- private static IList CheckSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms,
- short alertDescription)
- {
- if (null == supportedSignatureAlgorithms)
- throw new TlsFatalAlert(alertDescription, "'signature_algorithms' is required");
- return supportedSignatureAlgorithms;
- }
- private readonly byte[] m_certificateRequestContext;
- private readonly short[] m_certificateTypes;
- private readonly IList m_supportedSignatureAlgorithms;
- private readonly IList m_supportedSignatureAlgorithmsCert;
- private readonly IList m_certificateAuthorities;
- /// <param name="certificateTypes">see <see cref="ClientCertificateType"/> for valid constants.</param>
- /// <param name="supportedSignatureAlgorithms"></param>
- /// <param name="certificateAuthorities">an <see cref="IList"/> of <see cref="X509Name"/>.</param>
- public CertificateRequest(short[] certificateTypes, IList supportedSignatureAlgorithms,
- IList certificateAuthorities)
- : this(null, certificateTypes, supportedSignatureAlgorithms, null, certificateAuthorities)
- {
- }
- // TODO[tls13] Prefer to manage the certificateRequestContext internally only?
- /// <exception cref="IOException"/>
- public CertificateRequest(byte[] certificateRequestContext, IList supportedSignatureAlgorithms,
- IList supportedSignatureAlgorithmsCert, IList certificateAuthorities)
- : this(certificateRequestContext, null,
- CheckSupportedSignatureAlgorithms(supportedSignatureAlgorithms, AlertDescription.internal_error),
- supportedSignatureAlgorithmsCert, certificateAuthorities)
- {
- /*
- * TODO[tls13] Removed certificateTypes, added certificate_request_context, added extensions
- * (required: signature_algorithms, optional: status_request, signed_certificate_timestamp,
- * certificate_authorities, oid_filters, signature_algorithms_cert)
- */
- }
- private CertificateRequest(byte[] certificateRequestContext, short[] certificateTypes,
- IList supportedSignatureAlgorithms, IList supportedSignatureAlgorithmsCert, IList certificateAuthorities)
- {
- if (null != certificateRequestContext && !TlsUtilities.IsValidUint8(certificateRequestContext.Length))
- throw new ArgumentException("cannot be longer than 255", "certificateRequestContext");
- if (null != certificateTypes
- && (certificateTypes.Length < 1 || !TlsUtilities.IsValidUint8(certificateTypes.Length)))
- {
- throw new ArgumentException("should have length from 1 to 255", "certificateTypes");
- }
- this.m_certificateRequestContext = TlsUtilities.Clone(certificateRequestContext);
- this.m_certificateTypes = certificateTypes;
- this.m_supportedSignatureAlgorithms = supportedSignatureAlgorithms;
- this.m_supportedSignatureAlgorithmsCert = supportedSignatureAlgorithmsCert;
- this.m_certificateAuthorities = certificateAuthorities;
- }
- public byte[] GetCertificateRequestContext()
- {
- return TlsUtilities.Clone(m_certificateRequestContext);
- }
- /// <returns>an array of certificate types</returns>
- /// <seealso cref="ClientCertificateType"/>
- public short[] CertificateTypes
- {
- get { return m_certificateTypes; }
- }
- /// <returns>an <see cref="IList"/> of <see cref="SignatureAndHashAlgorithm"/> (or null before TLS 1.2).
- /// </returns>
- public IList SupportedSignatureAlgorithms
- {
- get { return m_supportedSignatureAlgorithms; }
- }
- /// <returns>an optional <see cref="IList"/> of <see cref="SignatureAndHashAlgorithm"/>. May be non-null from
- /// TLS 1.3 onwards.</returns>
- public IList SupportedSignatureAlgorithmsCert
- {
- get { return m_supportedSignatureAlgorithmsCert; }
- }
- /// <returns>an <see cref="IList"/> of <see cref="X509Name"/>.</returns>
- public IList CertificateAuthorities
- {
- get { return m_certificateAuthorities; }
- }
- public bool HasCertificateRequestContext(byte[] certificateRequestContext)
- {
- return Arrays.AreEqual(m_certificateRequestContext, certificateRequestContext);
- }
- /// <summary>Encode this <see cref="CertificateRequest"/> to a <see cref="Stream"/>.</summary>
- /// <param name="context">the <see cref="TlsContext"/> of the current connection.</param>
- /// <param name="output">the <see cref="Stream"/> to encode to.</param>
- /// <exception cref="IOException"/>
- public void Encode(TlsContext context, Stream output)
- {
- ProtocolVersion negotiatedVersion = context.ServerVersion;
- bool isTlsV12 = TlsUtilities.IsTlsV12(negotiatedVersion);
- bool isTlsV13 = TlsUtilities.IsTlsV13(negotiatedVersion);
- if (isTlsV13 != (null != m_certificateRequestContext) ||
- isTlsV13 != (null == m_certificateTypes) ||
- isTlsV12 != (null != m_supportedSignatureAlgorithms) ||
- (!isTlsV13 && (null != m_supportedSignatureAlgorithmsCert)))
- {
- throw new InvalidOperationException();
- }
- if (isTlsV13)
- {
- TlsUtilities.WriteOpaque8(m_certificateRequestContext, output);
- IDictionary extensions = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
- TlsExtensionsUtilities.AddSignatureAlgorithmsExtension(extensions, m_supportedSignatureAlgorithms);
- if (null != m_supportedSignatureAlgorithmsCert)
- {
- TlsExtensionsUtilities.AddSignatureAlgorithmsCertExtension(extensions,
- m_supportedSignatureAlgorithmsCert);
- }
- if (null != m_certificateAuthorities)
- {
- TlsExtensionsUtilities.AddCertificateAuthoritiesExtension(extensions, m_certificateAuthorities);
- }
- byte[] extEncoding = TlsProtocol.WriteExtensionsData(extensions);
- TlsUtilities.WriteOpaque16(extEncoding, output);
- return;
- }
- TlsUtilities.WriteUint8ArrayWithUint8Length(m_certificateTypes, output);
- if (isTlsV12)
- {
- // TODO Check whether SignatureAlgorithm.anonymous is allowed here
- TlsUtilities.EncodeSupportedSignatureAlgorithms(m_supportedSignatureAlgorithms, output);
- }
- if (m_certificateAuthorities == null || m_certificateAuthorities.Count < 1)
- {
- TlsUtilities.WriteUint16(0, output);
- }
- else
- {
- IList derEncodings = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(m_certificateAuthorities.Count);
- int totalLength = 0;
- foreach (X509Name certificateAuthority in m_certificateAuthorities)
- {
- byte[] derEncoding = certificateAuthority.GetEncoded(Asn1Encodable.Der);
- derEncodings.Add(derEncoding);
- totalLength += derEncoding.Length + 2;
- }
- TlsUtilities.CheckUint16(totalLength);
- TlsUtilities.WriteUint16(totalLength, output);
- foreach (byte[] derEncoding in derEncodings)
- {
- TlsUtilities.WriteOpaque16(derEncoding, output);
- }
- }
- }
- /// <summary>Parse a <see cref="CertificateRequest"/> from a <see cref="Stream"/></summary>
- /// <param name="context">the <see cref="TlsContext"/> of the current connection.</param>
- /// <param name="input">the <see cref="Stream"/> to parse from.</param>
- /// <returns>a <see cref="CertificateRequest"/> object.</returns>
- /// <exception cref="IOException"/>
- public static CertificateRequest Parse(TlsContext context, Stream input)
- {
- ProtocolVersion negotiatedVersion = context.ServerVersion;
- bool isTlsV13 = TlsUtilities.IsTlsV13(negotiatedVersion);
- if (isTlsV13)
- {
- byte[] certificateRequestContext = TlsUtilities.ReadOpaque8(input);
- /*
- * TODO[tls13] required: signature_algorithms; optional: status_request,
- * signed_certificate_timestamp, certificate_authorities, oid_filters,
- * signature_algorithms_cert
- */
- byte[] extEncoding = TlsUtilities.ReadOpaque16(input);
- IDictionary extensions = TlsProtocol.ReadExtensionsData13(HandshakeType.certificate_request,
- extEncoding);
- IList supportedSignatureAlgorithms13 = CheckSupportedSignatureAlgorithms(
- TlsExtensionsUtilities.GetSignatureAlgorithmsExtension(extensions),
- AlertDescription.missing_extension);
- IList supportedSignatureAlgorithmsCert13 = TlsExtensionsUtilities
- .GetSignatureAlgorithmsCertExtension(extensions);
- IList certificateAuthorities13 = TlsExtensionsUtilities.GetCertificateAuthoritiesExtension(extensions);
- return new CertificateRequest(certificateRequestContext, supportedSignatureAlgorithms13,
- supportedSignatureAlgorithmsCert13, certificateAuthorities13);
- }
- bool isTLSv12 = TlsUtilities.IsTlsV12(negotiatedVersion);
- short[] certificateTypes = TlsUtilities.ReadUint8ArrayWithUint8Length(input, 1);
- IList supportedSignatureAlgorithms = null;
- if (isTLSv12)
- {
- supportedSignatureAlgorithms = TlsUtilities.ParseSupportedSignatureAlgorithms(input);
- }
- IList certificateAuthorities = null;
- {
- byte[] certAuthData = TlsUtilities.ReadOpaque16(input);
- if (certAuthData.Length > 0)
- {
- certificateAuthorities = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- MemoryStream bis = new MemoryStream(certAuthData, false);
- do
- {
- byte[] derEncoding = TlsUtilities.ReadOpaque16(bis, 1);
- Asn1Object asn1 = TlsUtilities.ReadDerObject(derEncoding);
- certificateAuthorities.Add(X509Name.GetInstance(asn1));
- }
- while (bis.Position < bis.Length);
- }
- }
- return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
- }
- }
- }
- #pragma warning restore
- #endif
|