CertificateUrl.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  9. {
  10. /// <summary>RFC 3546 3.3</summary>
  11. public sealed class CertificateUrl
  12. {
  13. private readonly short m_type;
  14. private readonly IList m_urlAndHashList;
  15. /// <param name="type">see <see cref="CertChainType"/> for valid constants.</param>
  16. /// <param name="urlAndHashList">an <see cref="IList"/> of <see cref="UrlAndHash"/>.</param>
  17. public CertificateUrl(short type, IList urlAndHashList)
  18. {
  19. if (!CertChainType.IsValid(type))
  20. throw new ArgumentException("not a valid CertChainType value", "type");
  21. if (urlAndHashList == null || urlAndHashList.Count < 1)
  22. throw new ArgumentException("must have length > 0", "urlAndHashList");
  23. if (type == CertChainType.pkipath && urlAndHashList.Count != 1)
  24. throw new ArgumentException("must contain exactly one entry when type is "
  25. + CertChainType.GetText(type), "urlAndHashList");
  26. this.m_type = type;
  27. this.m_urlAndHashList = urlAndHashList;
  28. }
  29. /// <returns><see cref="CertChainType"/></returns>
  30. public short Type
  31. {
  32. get { return m_type; }
  33. }
  34. /// <returns>an <see cref="IList"/> of <see cref="UrlAndHash"/>.</returns>
  35. public IList UrlAndHashList
  36. {
  37. get { return m_urlAndHashList; }
  38. }
  39. /// <summary>Encode this <see cref="CertificateUrl"/> to a <see cref="Stream"/>.</summary>
  40. /// <param name="output">the <see cref="Stream"/> to encode to.</param>
  41. /// <exception cref="IOException"/>
  42. public void Encode(Stream output)
  43. {
  44. TlsUtilities.WriteUint8(m_type, output);
  45. ListBuffer16 buf = new ListBuffer16();
  46. foreach (UrlAndHash urlAndHash in m_urlAndHashList)
  47. {
  48. urlAndHash.Encode(buf);
  49. }
  50. buf.EncodeTo(output);
  51. }
  52. /// <summary>Parse a <see cref="CertificateUrl"/> from a <see cref="Stream"/>.</summary>
  53. /// <param name="context">the <see cref="TlsContext"/> of the current connection.</param>
  54. /// <param name="input">the <see cref="Stream"/> to parse from.</param>
  55. /// <returns>a <see cref="CertificateUrl"/> object.</returns>
  56. /// <exception cref="IOException"/>
  57. public static CertificateUrl Parse(TlsContext context, Stream input)
  58. {
  59. short type = TlsUtilities.ReadUint8(input);
  60. if (!CertChainType.IsValid(type))
  61. throw new TlsFatalAlert(AlertDescription.decode_error);
  62. int totalLength = TlsUtilities.ReadUint16(input);
  63. if (totalLength < 1)
  64. throw new TlsFatalAlert(AlertDescription.decode_error);
  65. byte[] urlAndHashListData = TlsUtilities.ReadFully(totalLength, input);
  66. MemoryStream buf = new MemoryStream(urlAndHashListData, false);
  67. IList url_and_hash_list = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  68. while (buf.Position < buf.Length)
  69. {
  70. UrlAndHash url_and_hash = UrlAndHash.Parse(context, buf);
  71. url_and_hash_list.Add(url_and_hash);
  72. }
  73. if (type == CertChainType.pkipath && url_and_hash_list.Count != 1)
  74. throw new TlsFatalAlert(AlertDescription.decode_error);
  75. return new CertificateUrl(type, url_and_hash_list);
  76. }
  77. // TODO Could be more generally useful
  78. internal class ListBuffer16
  79. : MemoryStream
  80. {
  81. internal ListBuffer16()
  82. {
  83. // Reserve space for length
  84. TlsUtilities.WriteUint16(0, this);
  85. }
  86. internal void EncodeTo(Stream output)
  87. {
  88. // Patch actual length back in
  89. int length = (int)Length - 2;
  90. TlsUtilities.CheckUint16(length);
  91. Seek(0L, SeekOrigin.Begin);
  92. TlsUtilities.WriteUint16(length, this);
  93. Streams.WriteBufTo(this, output);
  94. BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(this);
  95. }
  96. }
  97. }
  98. }
  99. #pragma warning restore
  100. #endif