Certificate.pm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. # Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License 2.0 (the "License"). You may not use
  4. # this file except in compliance with the License. You can obtain a copy
  5. # in the file LICENSE in the source distribution or at
  6. # https://www.openssl.org/source/license.html
  7. use strict;
  8. package TLSProxy::Certificate;
  9. use vars '@ISA';
  10. push @ISA, 'TLSProxy::Message';
  11. sub new
  12. {
  13. my $class = shift;
  14. my ($isdtls,
  15. $server,
  16. $msgseq,
  17. $msgfrag,
  18. $msgfragoffs,
  19. $data,
  20. $records,
  21. $startoffset,
  22. $message_frag_lens) = @_;
  23. my $self = $class->SUPER::new(
  24. $isdtls,
  25. $server,
  26. TLSProxy::Message::MT_CERTIFICATE,
  27. $msgseq,
  28. $msgfrag,
  29. $msgfragoffs,
  30. $data,
  31. $records,
  32. $startoffset,
  33. $message_frag_lens);
  34. $self->{first_certificate} = "";
  35. $self->{extension_data} = "";
  36. $self->{remaining_certdata} = "";
  37. return $self;
  38. }
  39. sub parse
  40. {
  41. my $self = shift;
  42. if (TLSProxy::Proxy->is_tls13()) {
  43. my $context_len = unpack('C', $self->data);
  44. my $context = substr($self->data, 1, $context_len);
  45. my $remdata = substr($self->data, 1 + $context_len);
  46. my ($hicertlistlen, $certlistlen) = unpack('Cn', $remdata);
  47. $certlistlen += ($hicertlistlen << 16);
  48. $remdata = substr($remdata, 3);
  49. die "Invalid Certificate List length"
  50. if length($remdata) != $certlistlen;
  51. my ($hicertlen, $certlen) = unpack('Cn', $remdata);
  52. $certlen += ($hicertlen << 16);
  53. die "Certificate too long" if ($certlen + 3) > $certlistlen;
  54. $remdata = substr($remdata, 3);
  55. my $certdata = substr($remdata, 0, $certlen);
  56. $remdata = substr($remdata, $certlen);
  57. my $extensions_len = unpack('n', $remdata);
  58. $remdata = substr($remdata, 2);
  59. die "Extensions too long"
  60. if ($certlen + 3 + $extensions_len + 2) > $certlistlen;
  61. my $extension_data = "";
  62. if ($extensions_len != 0) {
  63. $extension_data = substr($remdata, 0, $extensions_len);
  64. if (length($extension_data) != $extensions_len) {
  65. die "Invalid extension length\n";
  66. }
  67. }
  68. my %extensions = ();
  69. while (length($extension_data) >= 4) {
  70. my ($type, $size) = unpack("nn", $extension_data);
  71. my $extdata = substr($extension_data, 4, $size);
  72. $extension_data = substr($extension_data, 4 + $size);
  73. $extensions{$type} = $extdata;
  74. }
  75. $remdata = substr($remdata, $extensions_len);
  76. $self->context($context);
  77. $self->first_certificate($certdata);
  78. $self->extension_data(\%extensions);
  79. $self->remaining_certdata($remdata);
  80. print " Context:".$context."\n";
  81. print " Certificate List Len:".$certlistlen."\n";
  82. print " Certificate Len:".$certlen."\n";
  83. print " Extensions Len:".$extensions_len."\n";
  84. } else {
  85. my ($hicertlistlen, $certlistlen) = unpack('Cn', $self->data);
  86. $certlistlen += ($hicertlistlen << 16);
  87. my $remdata = substr($self->data, 3);
  88. die "Invalid Certificate List length"
  89. if length($remdata) != $certlistlen;
  90. my ($hicertlen, $certlen) = unpack('Cn', $remdata);
  91. $certlen += ($hicertlen << 16);
  92. die "Certificate too long" if ($certlen + 3) > $certlistlen;
  93. $remdata = substr($remdata, 3);
  94. my $certdata = substr($remdata, 0, $certlen);
  95. $remdata = substr($remdata, $certlen);
  96. $self->first_certificate($certdata);
  97. $self->remaining_certdata($remdata);
  98. print " Certificate List Len:".$certlistlen."\n";
  99. print " Certificate Len:".$certlen."\n";
  100. }
  101. }
  102. #Reconstruct the on-the-wire message data following changes
  103. sub set_message_contents
  104. {
  105. my $self = shift;
  106. my $data;
  107. my $extensions = "";
  108. if (TLSProxy::Proxy->is_tls13()) {
  109. foreach my $key (keys %{$self->extension_data}) {
  110. my $extdata = ${$self->extension_data}{$key};
  111. $extensions .= pack("n", $key);
  112. $extensions .= pack("n", length($extdata));
  113. $extensions .= $extdata;
  114. }
  115. $data = pack('C', length($self->context()));
  116. $data .= $self->context;
  117. my $certlen = length($self->first_certificate);
  118. my $certlistlen = $certlen + length($extensions)
  119. + length($self->remaining_certdata);
  120. my $hi = $certlistlen >> 16;
  121. $certlistlen = $certlistlen & 0xffff;
  122. $data .= pack('Cn', $hi, $certlistlen);
  123. $hi = $certlen >> 16;
  124. $certlen = $certlen & 0xffff;
  125. $data .= pack('Cn', $hi, $certlen);
  126. $data .= pack('n', length($extensions));
  127. $data .= $extensions;
  128. $data .= $self->remaining_certdata();
  129. $self->data($data);
  130. } else {
  131. my $certlen = length($self->first_certificate);
  132. my $certlistlen = $certlen + length($self->remaining_certdata);
  133. my $hi = $certlistlen >> 16;
  134. $certlistlen = $certlistlen & 0xffff;
  135. $data .= pack('Cn', $hi, $certlistlen);
  136. $hi = $certlen >> 16;
  137. $certlen = $certlen & 0xffff;
  138. $data .= pack('Cn', $hi, $certlen);
  139. $data .= $self->remaining_certdata();
  140. $self->data($data);
  141. }
  142. }
  143. #Read/write accessors
  144. sub context
  145. {
  146. my $self = shift;
  147. if (@_) {
  148. $self->{context} = shift;
  149. }
  150. return $self->{context};
  151. }
  152. sub first_certificate
  153. {
  154. my $self = shift;
  155. if (@_) {
  156. $self->{first_certificate} = shift;
  157. }
  158. return $self->{first_certificate};
  159. }
  160. sub remaining_certdata
  161. {
  162. my $self = shift;
  163. if (@_) {
  164. $self->{remaining_certdata} = shift;
  165. }
  166. return $self->{remaining_certdata};
  167. }
  168. sub extension_data
  169. {
  170. my $self = shift;
  171. if (@_) {
  172. $self->{extension_data} = shift;
  173. }
  174. return $self->{extension_data};
  175. }
  176. sub set_extension
  177. {
  178. my ($self, $ext_type, $ext_data) = @_;
  179. $self->{extension_data}{$ext_type} = $ext_data;
  180. }
  181. sub delete_extension
  182. {
  183. my ($self, $ext_type) = @_;
  184. delete $self->{extension_data}{$ext_type};
  185. }
  186. 1;