TlsCryptoUtilities.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.IO;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  9. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto
  10. {
  11. public abstract class TlsCryptoUtilities
  12. {
  13. // "tls13 "
  14. private static readonly byte[] Tls13Prefix = new byte[] { 0x74, 0x6c, 0x73, 0x31, 0x33, 0x20 };
  15. public static int GetHash(short hashAlgorithm)
  16. {
  17. switch (hashAlgorithm)
  18. {
  19. case HashAlgorithm.md5:
  20. return CryptoHashAlgorithm.md5;
  21. case HashAlgorithm.sha1:
  22. return CryptoHashAlgorithm.sha1;
  23. case HashAlgorithm.sha224:
  24. return CryptoHashAlgorithm.sha224;
  25. case HashAlgorithm.sha256:
  26. return CryptoHashAlgorithm.sha256;
  27. case HashAlgorithm.sha384:
  28. return CryptoHashAlgorithm.sha384;
  29. case HashAlgorithm.sha512:
  30. return CryptoHashAlgorithm.sha512;
  31. default:
  32. throw new ArgumentException("specified HashAlgorithm invalid: " + HashAlgorithm.GetText(hashAlgorithm));
  33. }
  34. }
  35. public static int GetHashForHmac(int macAlgorithm)
  36. {
  37. switch (macAlgorithm)
  38. {
  39. case MacAlgorithm.hmac_md5:
  40. return CryptoHashAlgorithm.md5;
  41. case MacAlgorithm.hmac_sha1:
  42. return CryptoHashAlgorithm.sha1;
  43. case MacAlgorithm.hmac_sha256:
  44. return CryptoHashAlgorithm.sha256;
  45. case MacAlgorithm.hmac_sha384:
  46. return CryptoHashAlgorithm.sha384;
  47. case MacAlgorithm.hmac_sha512:
  48. return CryptoHashAlgorithm.sha512;
  49. default:
  50. throw new ArgumentException("specified MacAlgorithm not an HMAC: " + MacAlgorithm.GetText(macAlgorithm));
  51. }
  52. }
  53. public static int GetHashForPrf(int prfAlgorithm)
  54. {
  55. switch (prfAlgorithm)
  56. {
  57. case PrfAlgorithm.ssl_prf_legacy:
  58. case PrfAlgorithm.tls_prf_legacy:
  59. throw new ArgumentException("legacy PRF not a valid algorithm");
  60. case PrfAlgorithm.tls_prf_sha256:
  61. case PrfAlgorithm.tls13_hkdf_sha256:
  62. return CryptoHashAlgorithm.sha256;
  63. case PrfAlgorithm.tls_prf_sha384:
  64. case PrfAlgorithm.tls13_hkdf_sha384:
  65. return CryptoHashAlgorithm.sha384;
  66. case PrfAlgorithm.tls13_hkdf_sm3:
  67. return CryptoHashAlgorithm.sm3;
  68. default:
  69. throw new ArgumentException("unknown PrfAlgorithm: " + PrfAlgorithm.GetText(prfAlgorithm));
  70. }
  71. }
  72. public static int GetHashInternalSize(int cryptoHashAlgorithm)
  73. {
  74. switch (cryptoHashAlgorithm)
  75. {
  76. case CryptoHashAlgorithm.md5:
  77. case CryptoHashAlgorithm.sha1:
  78. case CryptoHashAlgorithm.sha224:
  79. case CryptoHashAlgorithm.sha256:
  80. case CryptoHashAlgorithm.sm3:
  81. return 64;
  82. case CryptoHashAlgorithm.sha384:
  83. case CryptoHashAlgorithm.sha512:
  84. return 128;
  85. default:
  86. throw new ArgumentException();
  87. }
  88. }
  89. public static int GetHashOutputSize(int cryptoHashAlgorithm)
  90. {
  91. switch (cryptoHashAlgorithm)
  92. {
  93. case CryptoHashAlgorithm.md5:
  94. return 16;
  95. case CryptoHashAlgorithm.sha1:
  96. return 20;
  97. case CryptoHashAlgorithm.sha224:
  98. return 28;
  99. case CryptoHashAlgorithm.sha256:
  100. case CryptoHashAlgorithm.sm3:
  101. return 32;
  102. case CryptoHashAlgorithm.sha384:
  103. return 48;
  104. case CryptoHashAlgorithm.sha512:
  105. return 64;
  106. default:
  107. throw new ArgumentException();
  108. }
  109. }
  110. public static DerObjectIdentifier GetOidForHash(int cryptoHashAlgorithm)
  111. {
  112. switch (cryptoHashAlgorithm)
  113. {
  114. case CryptoHashAlgorithm.md5:
  115. return PkcsObjectIdentifiers.MD5;
  116. case CryptoHashAlgorithm.sha1:
  117. return X509ObjectIdentifiers.IdSha1;
  118. case CryptoHashAlgorithm.sha224:
  119. return NistObjectIdentifiers.IdSha224;
  120. case CryptoHashAlgorithm.sha256:
  121. return NistObjectIdentifiers.IdSha256;
  122. case CryptoHashAlgorithm.sha384:
  123. return NistObjectIdentifiers.IdSha384;
  124. case CryptoHashAlgorithm.sha512:
  125. return NistObjectIdentifiers.IdSha512;
  126. // TODO[RFC 8998]
  127. //case CryptoHashAlgorithm.sm3:
  128. // return GMObjectIdentifiers.sm3;
  129. default:
  130. throw new ArgumentException();
  131. }
  132. }
  133. public static int GetSignature(short signatureAlgorithm)
  134. {
  135. switch (signatureAlgorithm)
  136. {
  137. case SignatureAlgorithm.rsa:
  138. return CryptoSignatureAlgorithm.rsa;
  139. case SignatureAlgorithm.dsa:
  140. return CryptoSignatureAlgorithm.dsa;
  141. case SignatureAlgorithm.ecdsa:
  142. return CryptoSignatureAlgorithm.ecdsa;
  143. case SignatureAlgorithm.rsa_pss_rsae_sha256:
  144. return CryptoSignatureAlgorithm.rsa_pss_rsae_sha256;
  145. case SignatureAlgorithm.rsa_pss_rsae_sha384:
  146. return CryptoSignatureAlgorithm.rsa_pss_rsae_sha384;
  147. case SignatureAlgorithm.rsa_pss_rsae_sha512:
  148. return CryptoSignatureAlgorithm.rsa_pss_rsae_sha512;
  149. case SignatureAlgorithm.ed25519:
  150. return CryptoSignatureAlgorithm.ed25519;
  151. case SignatureAlgorithm.ed448:
  152. return CryptoSignatureAlgorithm.ed448;
  153. case SignatureAlgorithm.rsa_pss_pss_sha256:
  154. return CryptoSignatureAlgorithm.rsa_pss_pss_sha256;
  155. case SignatureAlgorithm.rsa_pss_pss_sha384:
  156. return CryptoSignatureAlgorithm.rsa_pss_pss_sha384;
  157. case SignatureAlgorithm.rsa_pss_pss_sha512:
  158. return CryptoSignatureAlgorithm.rsa_pss_pss_sha512;
  159. case SignatureAlgorithm.ecdsa_brainpoolP256r1tls13_sha256:
  160. return CryptoSignatureAlgorithm.ecdsa_brainpoolP256r1tls13_sha256;
  161. case SignatureAlgorithm.ecdsa_brainpoolP384r1tls13_sha384:
  162. return CryptoSignatureAlgorithm.ecdsa_brainpoolP384r1tls13_sha384;
  163. case SignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512:
  164. return CryptoSignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512;
  165. case SignatureAlgorithm.gostr34102012_256:
  166. return CryptoSignatureAlgorithm.gostr34102012_256;
  167. case SignatureAlgorithm.gostr34102012_512:
  168. return CryptoSignatureAlgorithm.gostr34102012_512;
  169. default:
  170. throw new ArgumentException("specified SignatureAlgorithm invalid: "
  171. + SignatureAlgorithm.GetText(signatureAlgorithm));
  172. }
  173. }
  174. /// <exception cref="IOException"/>
  175. public static TlsSecret HkdfExpandLabel(TlsSecret secret, int cryptoHashAlgorithm, string label,
  176. byte[] context, int length)
  177. {
  178. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  179. return HkdfExpandLabel(secret, cryptoHashAlgorithm, label.AsSpan(), context.AsSpan(), length);
  180. #else
  181. int labelLength = label.Length;
  182. if (labelLength < 1)
  183. throw new TlsFatalAlert(AlertDescription.internal_error);
  184. int contextLength = context.Length;
  185. int expandedLabelLength = Tls13Prefix.Length + labelLength;
  186. byte[] hkdfLabel = new byte[2 + (1 + expandedLabelLength) + (1 + contextLength)];
  187. // uint16 length
  188. {
  189. TlsUtilities.CheckUint16(length);
  190. TlsUtilities.WriteUint16(length, hkdfLabel, 0);
  191. }
  192. // opaque label<7..255>
  193. {
  194. TlsUtilities.CheckUint8(expandedLabelLength);
  195. TlsUtilities.WriteUint8(expandedLabelLength, hkdfLabel, 2);
  196. Array.Copy(Tls13Prefix, 0, hkdfLabel, 2 + 1, Tls13Prefix.Length);
  197. int labelPos = 2 + (1 + Tls13Prefix.Length);
  198. for (int i = 0; i < labelLength; ++i)
  199. {
  200. char c = label[i];
  201. hkdfLabel[labelPos + i] = (byte)c;
  202. }
  203. }
  204. // context
  205. {
  206. TlsUtilities.WriteOpaque8(context, hkdfLabel, 2 + (1 + expandedLabelLength));
  207. }
  208. return secret.HkdfExpand(cryptoHashAlgorithm, hkdfLabel, length);
  209. #endif
  210. }
  211. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  212. /// <exception cref="IOException"/>
  213. public static TlsSecret HkdfExpandLabel(TlsSecret secret, int cryptoHashAlgorithm, ReadOnlySpan<char> label,
  214. ReadOnlySpan<byte> context, int length)
  215. {
  216. int labelLength = label.Length;
  217. if (labelLength < 1)
  218. throw new TlsFatalAlert(AlertDescription.internal_error);
  219. int contextLength = context.Length;
  220. int expandedLabelLength = Tls13Prefix.Length + labelLength;
  221. int hkdfLabelLength = 2 + (1 + expandedLabelLength) + (1 + contextLength);
  222. Span<byte> hkdfLabel = hkdfLabelLength <= 512
  223. ? stackalloc byte[hkdfLabelLength]
  224. : new byte[hkdfLabelLength];
  225. // uint16 length
  226. {
  227. TlsUtilities.CheckUint16(length);
  228. TlsUtilities.WriteUint16(length, hkdfLabel);
  229. }
  230. // opaque label<7..255>
  231. {
  232. TlsUtilities.CheckUint8(expandedLabelLength);
  233. TlsUtilities.WriteUint8(expandedLabelLength, hkdfLabel[2..]);
  234. Tls13Prefix.CopyTo(hkdfLabel[3..]);
  235. int labelPos = 2 + (1 + Tls13Prefix.Length);
  236. for (int i = 0; i < labelLength; ++i)
  237. {
  238. hkdfLabel[labelPos + i] = (byte)label[i];
  239. }
  240. }
  241. // context
  242. {
  243. TlsUtilities.WriteOpaque8(context, hkdfLabel.Slice(2 + (1 + expandedLabelLength)));
  244. }
  245. return secret.HkdfExpand(cryptoHashAlgorithm, hkdfLabel, length);
  246. }
  247. #endif
  248. }
  249. }
  250. #pragma warning restore
  251. #endif