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