HandshakeCertificate.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Debug.h>
  7. #include <AK/Endian.h>
  8. #include <AK/Random.h>
  9. #include <LibCore/Timer.h>
  10. #include <LibCrypto/ASN1/DER.h>
  11. #include <LibTLS/TLSv12.h>
  12. namespace TLS {
  13. ssize_t TLSv12::handle_certificate(ReadonlyBytes buffer)
  14. {
  15. ssize_t res = 0;
  16. if (buffer.size() < 3) {
  17. dbgln_if(TLS_DEBUG, "not enough certificate header data");
  18. return (i8)Error::NeedMoreData;
  19. }
  20. u32 certificate_total_length = buffer[0] * 0x10000 + buffer[1] * 0x100 + buffer[2];
  21. dbgln_if(TLS_DEBUG, "total length: {}", certificate_total_length);
  22. if (certificate_total_length <= 4)
  23. return 3 * certificate_total_length;
  24. res += 3;
  25. if (certificate_total_length > buffer.size() - res) {
  26. dbgln_if(TLS_DEBUG, "not enough data for claimed total cert length");
  27. return (i8)Error::NeedMoreData;
  28. }
  29. size_t size = certificate_total_length;
  30. bool valid_certificate = false;
  31. while (size > 0) {
  32. if (buffer.size() - res < 3) {
  33. dbgln_if(TLS_DEBUG, "not enough data for certificate length");
  34. return (i8)Error::NeedMoreData;
  35. }
  36. size_t certificate_size = buffer[res] * 0x10000 + buffer[res + 1] * 0x100 + buffer[res + 2];
  37. res += 3;
  38. if (buffer.size() - res < certificate_size) {
  39. dbgln_if(TLS_DEBUG, "not enough data for certificate body");
  40. return (i8)Error::NeedMoreData;
  41. }
  42. auto res_cert = res;
  43. auto remaining = certificate_size;
  44. do {
  45. if (remaining <= 3) {
  46. dbgln("Ran out of data");
  47. break;
  48. }
  49. if (buffer.size() < (size_t)res_cert + 3) {
  50. dbgln("not enough data to read cert size ({} < {})", buffer.size(), res_cert + 3);
  51. break;
  52. }
  53. size_t certificate_size_specific = buffer[res_cert] * 0x10000 + buffer[res_cert + 1] * 0x100 + buffer[res_cert + 2];
  54. res_cert += 3;
  55. remaining -= 3;
  56. if (certificate_size_specific > remaining) {
  57. dbgln("invalid certificate size (expected {} but got {})", remaining, certificate_size_specific);
  58. break;
  59. }
  60. remaining -= certificate_size_specific;
  61. auto certificate = Certificate::parse_certificate(buffer.slice(res_cert, certificate_size_specific), false);
  62. if (!certificate.is_error()) {
  63. m_context.certificates.empend(certificate.value());
  64. valid_certificate = true;
  65. } else {
  66. dbgln("Failed to parse client cert: {}", certificate.error());
  67. dbgln("{:hex-dump}", buffer.slice(res_cert, certificate_size_specific));
  68. dbgln("");
  69. }
  70. res_cert += certificate_size_specific;
  71. } while (remaining > 0);
  72. if (remaining) {
  73. dbgln("extraneous {} bytes left over after parsing certificates", remaining);
  74. }
  75. size -= certificate_size + 3;
  76. res += certificate_size;
  77. }
  78. if (!valid_certificate)
  79. return (i8)Error::UnsupportedCertificate;
  80. if ((size_t)res != buffer.size())
  81. dbgln("some data left unread: {} bytes out of {}", res, buffer.size());
  82. return res;
  83. }
  84. ssize_t TLSv12::handle_certificate_verify(ReadonlyBytes)
  85. {
  86. dbgln("FIXME: parse_verify");
  87. return 0;
  88. }
  89. }