123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #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.Ocsp;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
- {
- public sealed class CertificateStatus
- {
- private readonly short m_statusType;
- private readonly object m_response;
- public CertificateStatus(short statusType, object response)
- {
- if (!IsCorrectType(statusType, response))
- throw new ArgumentException("not an instance of the correct type", "response");
- this.m_statusType = statusType;
- this.m_response = response;
- }
- public short StatusType
- {
- get { return m_statusType; }
- }
- public object Response
- {
- get { return m_response; }
- }
- public OcspResponse OcspResponse
- {
- get
- {
- if (!IsCorrectType(CertificateStatusType.ocsp, m_response))
- throw new InvalidOperationException("'response' is not an OCSPResponse");
- return (OcspResponse)m_response;
- }
- }
- /// <summary>an <see cref="IList"/> of (possibly null) <see cref="Asn1.Ocsp.OcspResponse"/>.</summary>
- public IList OcspResponseList
- {
- get
- {
- if (!IsCorrectType(CertificateStatusType.ocsp_multi, m_response))
- throw new InvalidOperationException("'response' is not an OCSPResponseList");
- return (IList)m_response;
- }
- }
- /// <summary>Encode this <see cref="CertificateStatus"/> to a <see cref="Stream"/>.</summary>
- /// <param name="output">the <see cref="Stream"/> to encode to.</param>
- /// <exception cref="IOException"/>
- public void Encode(Stream output)
- {
- TlsUtilities.WriteUint8(m_statusType, output);
- switch (m_statusType)
- {
- case CertificateStatusType.ocsp:
- {
- OcspResponse ocspResponse = (OcspResponse)m_response;
- byte[] derEncoding = ocspResponse.GetEncoded(Asn1Encodable.Der);
- TlsUtilities.WriteOpaque24(derEncoding, output);
- break;
- }
- case CertificateStatusType.ocsp_multi:
- {
- IList ocspResponseList = (IList)m_response;
- int count = ocspResponseList.Count;
- IList derEncodings = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(count);
- long totalLength = 0;
- foreach (OcspResponse ocspResponse in ocspResponseList)
- {
- if (ocspResponse == null)
- {
- derEncodings.Add(TlsUtilities.EmptyBytes);
- }
- else
- {
- byte[] derEncoding = ocspResponse.GetEncoded(Asn1Encodable.Der);
- derEncodings.Add(derEncoding);
- totalLength += derEncoding.Length;
- }
- totalLength += 3;
- }
- TlsUtilities.CheckUint24(totalLength);
- TlsUtilities.WriteUint24((int)totalLength, output);
- foreach (byte[] derEncoding in derEncodings)
- {
- TlsUtilities.WriteOpaque24(derEncoding, output);
- }
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
- /// <summary>Parse a <see cref="CertificateStatus"/> 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="CertificateStatus"/> object.</returns>
- /// <exception cref="IOException"/>
- public static CertificateStatus Parse(TlsContext context, Stream input)
- {
- SecurityParameters securityParameters = context.SecurityParameters;
- Certificate peerCertificate = securityParameters.PeerCertificate;
- if (null == peerCertificate || peerCertificate.IsEmpty
- || CertificateType.X509 != peerCertificate.CertificateType)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- int certificateCount = peerCertificate.Length;
- int statusRequestVersion = securityParameters.StatusRequestVersion;
- short status_type = TlsUtilities.ReadUint8(input);
- object response;
- switch (status_type)
- {
- case CertificateStatusType.ocsp:
- {
- RequireStatusRequestVersion(1, statusRequestVersion);
- byte[] derEncoding = TlsUtilities.ReadOpaque24(input, 1);
- Asn1Object derObject = TlsUtilities.ReadDerObject(derEncoding);
- response = OcspResponse.GetInstance(derObject);
- break;
- }
- case CertificateStatusType.ocsp_multi:
- {
- RequireStatusRequestVersion(2, statusRequestVersion);
- byte[] ocsp_response_list = TlsUtilities.ReadOpaque24(input, 1);
- MemoryStream buf = new MemoryStream(ocsp_response_list, false);
- IList ocspResponseList = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- while (buf.Position < buf.Length)
- {
- if (ocspResponseList.Count >= certificateCount)
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- int length = TlsUtilities.ReadUint24(buf);
- if (length < 1)
- {
- ocspResponseList.Add(null);
- }
- else
- {
- byte[] derEncoding = TlsUtilities.ReadFully(length, buf);
- Asn1Object derObject = TlsUtilities.ReadDerObject(derEncoding);
- OcspResponse ocspResponse = OcspResponse.GetInstance(derObject);
- ocspResponseList.Add(ocspResponse);
- }
- }
- // Match IList capacity to actual size
- response = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(ocspResponseList);
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- return new CertificateStatus(status_type, response);
- }
- private static bool IsCorrectType(short statusType, Object response)
- {
- switch (statusType)
- {
- case CertificateStatusType.ocsp:
- return response is OcspResponse;
- case CertificateStatusType.ocsp_multi:
- return IsOcspResponseList(response);
- default:
- throw new ArgumentException("unsupported CertificateStatusType", "statusType");
- }
- }
- private static bool IsOcspResponseList(object response)
- {
- if (!(response is IList))
- return false;
- IList v = (IList)response;
- int count = v.Count;
- if (count < 1)
- return false;
- foreach (object e in v)
- {
- if (null != e && !(e is OcspResponse))
- return false;
- }
- return true;
- }
- /// <exception cref="IOException"/>
- private static void RequireStatusRequestVersion(int minVersion, int statusRequestVersion)
- {
- if (statusRequestVersion < minVersion)
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- }
- }
- #pragma warning restore
- #endif
|