1 /*
2 * (C) 2018 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6
7 #include "fuzzers.h"
8 #include <botan/mode_pad.h>
9 #include <botan/internal/tls_cbc.h>
10
11 namespace {
12
ref_pkcs7_unpad(const uint8_t in[],size_t len)13 size_t ref_pkcs7_unpad(const uint8_t in[], size_t len)
14 {
15 if(len <= 2)
16 return len;
17
18 const size_t padding_length = in[len-1];
19
20 if(padding_length == 0 || padding_length > len)
21 return len;
22
23 const size_t padding_start = len - padding_length;
24
25 for(size_t i = padding_start; i != len; ++i)
26 {
27 if(in[i] != padding_length)
28 return len;
29 }
30
31 return len - padding_length;
32 }
33
ref_x923_unpad(const uint8_t in[],size_t len)34 size_t ref_x923_unpad(const uint8_t in[], size_t len)
35 {
36 if(len <= 2)
37 return len;
38
39 const size_t padding_length = in[len-1];
40
41 if(padding_length == 0 || padding_length > len)
42 return len;
43 const size_t padding_start = len - padding_length;
44
45 for(size_t i = padding_start; i != len - 1; ++i)
46 {
47 if(in[i] != 0)
48 {
49 return len;
50 }
51 }
52
53 return len - padding_length;
54 }
55
ref_oneandzero_unpad(const uint8_t in[],size_t len)56 size_t ref_oneandzero_unpad(const uint8_t in[], size_t len)
57 {
58 if(len <= 2)
59 return len;
60
61 size_t idx = len - 1;
62
63 for(;;)
64 {
65 if(in[idx] == 0)
66 {
67 if(idx == 0)
68 return len;
69 idx -= 1;
70 continue;
71 }
72 else if(in[idx] == 0x80)
73 {
74 return idx;
75 }
76 else
77 return len;
78 }
79
80 return len;
81 }
82
ref_esp_unpad(const uint8_t in[],size_t len)83 size_t ref_esp_unpad(const uint8_t in[], size_t len)
84 {
85 if(len <= 2)
86 return len;
87
88 const size_t padding_bytes = in[len - 1];
89
90 if(padding_bytes == 0 || padding_bytes > len)
91 {
92 return len;
93 }
94
95 const size_t padding_start = len - padding_bytes;
96 for(size_t i = padding_start; i != len; ++i)
97 {
98 if(in[i] != (i - padding_start + 1))
99 {
100 return len;
101 }
102 }
103
104 return len - padding_bytes;
105 }
106
ref_tls_cbc_unpad(const uint8_t in[],size_t len)107 uint16_t ref_tls_cbc_unpad(const uint8_t in[], size_t len)
108 {
109 if(len == 0)
110 return 0;
111
112 const size_t padding_length = in[(len-1)];
113
114 if(padding_length >= len)
115 return 0;
116
117 /*
118 * TLS v1.0 and up require all the padding bytes be the same value
119 * and allows up to 255 bytes.
120 */
121 for(size_t i = 0; i != 1 + padding_length; ++i)
122 {
123 if(in[(len-i-1)] != padding_length)
124 return 0;
125 }
126 return padding_length + 1;
127 }
128
129 }
130
fuzz(const uint8_t in[],size_t len)131 void fuzz(const uint8_t in[], size_t len)
132 {
133 static Botan::PKCS7_Padding pkcs7;
134 static Botan::ANSI_X923_Padding x923;
135 static Botan::OneAndZeros_Padding oneandzero;
136 static Botan::ESP_Padding esp;
137
138 if(pkcs7.valid_blocksize(len))
139 {
140 const size_t ct_pkcs7 = pkcs7.unpad(in, len);
141 const size_t ref_pkcs7 = ref_pkcs7_unpad(in, len);
142 FUZZER_ASSERT_EQUAL(ct_pkcs7, ref_pkcs7);
143 }
144
145 if(x923.valid_blocksize(len))
146 {
147 const size_t ct_x923 = x923.unpad(in, len);
148 const size_t ref_x923 = ref_x923_unpad(in, len);
149 FUZZER_ASSERT_EQUAL(ct_x923, ref_x923);
150 }
151
152 if(oneandzero.valid_blocksize(len))
153 {
154 const size_t ct_oneandzero = oneandzero.unpad(in, len);
155 const size_t ref_oneandzero = ref_oneandzero_unpad(in, len);
156 FUZZER_ASSERT_EQUAL(ct_oneandzero, ref_oneandzero);
157 }
158
159 if(esp.valid_blocksize(len))
160 {
161 const size_t ct_esp = esp.unpad(in, len);
162 const size_t ref_esp = ref_esp_unpad(in, len);
163 FUZZER_ASSERT_EQUAL(ct_esp, ref_esp);
164 }
165
166 const uint16_t ct_cbc = Botan::TLS::check_tls_cbc_padding(in, len);
167 const uint16_t ref_cbc = ref_tls_cbc_unpad(in, len);
168 FUZZER_ASSERT_EQUAL(ct_cbc, ref_cbc);
169 }
170