Botan  1.10.9
selftest.cpp
Go to the documentation of this file.
1 /*
2 * Startup Self Tests
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/selftest.h>
9 #include <botan/filters.h>
10 #include <botan/internal/core_engine.h>
11 #include <botan/internal/stl_util.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 /*
18 * Perform a Known Answer Test
19 */
20 bool test_filter_kat(Filter* filter,
21  const std::string& input,
22  const std::string& expected_output)
23  {
24  Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder);
25  pipe.process_msg(input);
26 
27  const std::string output = pipe.read_all_as_string();
28 
29  return (output == expected_output);
30  }
31 
32 }
33 
34 /*
35 * Run a set of KATs
36 */
37 std::map<std::string, bool>
39  const std::map<std::string, std::string>& vars,
41  {
42  const std::string& algo = algo_name.algo_name_and_args();
43 
44  std::vector<std::string> providers = af.providers_of(algo);
45  std::map<std::string, bool> all_results;
46 
47  if(providers.empty()) // no providers, nothing to do
48  return all_results;
49 
50  const std::string input = search_map(vars, std::string("input"));
51  const std::string output = search_map(vars, std::string("output"));
52 
53  SymmetricKey key(search_map(vars, std::string("key")));
54  InitializationVector iv(search_map(vars, std::string("iv")));
55 
56  for(size_t i = 0; i != providers.size(); ++i)
57  {
58  const std::string provider = providers[i];
59 
60  if(const HashFunction* proto =
61  af.prototype_hash_function(algo, provider))
62  {
63  Filter* filt = new Hash_Filter(proto->clone());
64  all_results[provider] = test_filter_kat(filt, input, output);
65  }
66  else if(const MessageAuthenticationCode* proto =
67  af.prototype_mac(algo, provider))
68  {
69  Keyed_Filter* filt = new MAC_Filter(proto->clone(), key);
70  all_results[provider] = test_filter_kat(filt, input, output);
71  }
72  else if(const StreamCipher* proto =
73  af.prototype_stream_cipher(algo, provider))
74  {
75  Keyed_Filter* filt = new StreamCipher_Filter(proto->clone());
76  filt->set_key(key);
77  filt->set_iv(iv);
78 
79  all_results[provider] = test_filter_kat(filt, input, output);
80  }
81  else if(const BlockCipher* proto =
82  af.prototype_block_cipher(algo, provider))
83  {
85  algo_name.cipher_mode(),
86  algo_name.cipher_mode_pad());
87 
89  algo_name.cipher_mode(),
90  algo_name.cipher_mode_pad());
91 
92  if(!enc || !dec)
93  {
94  delete enc;
95  delete dec;
96  continue;
97  }
98 
99  enc->set_key(key);
100 
101  if(enc->valid_iv_length(iv.length()))
102  enc->set_iv(iv);
103  else if(!enc->valid_iv_length(0))
104  throw Invalid_IV_Length(algo, iv.length());
105 
106  dec->set_key(key);
107 
108  if(dec->valid_iv_length(iv.length()))
109  dec->set_iv(iv);
110  else if(!dec->valid_iv_length(0))
111  throw Invalid_IV_Length(algo, iv.length());
112 
113  bool enc_ok = test_filter_kat(enc, input, output);
114  bool dec_ok = test_filter_kat(dec, output, input);
115 
116  all_results[provider] = enc_ok && dec_ok;
117  }
118  }
119 
120  return all_results;
121  }
122 
123 namespace {
124 
125 void verify_results(const std::string& algo,
126  const std::map<std::string, bool>& results)
127  {
128  for(std::map<std::string, bool>::const_iterator i = results.begin();
129  i != results.end(); ++i)
130  {
131  if(!i->second)
132  throw Self_Test_Failure(algo + " self-test failed, provider "+
133  i->first);
134  }
135  }
136 
137 void hash_test(Algorithm_Factory& af,
138  const std::string& name,
139  const std::string& in,
140  const std::string& out)
141  {
142  std::map<std::string, std::string> vars;
143  vars["input"] = in;
144  vars["output"] = out;
145 
146  verify_results(name, algorithm_kat(name, vars, af));
147  }
148 
149 void mac_test(Algorithm_Factory& af,
150  const std::string& name,
151  const std::string& in,
152  const std::string& out,
153  const std::string& key)
154  {
155  std::map<std::string, std::string> vars;
156  vars["input"] = in;
157  vars["output"] = out;
158  vars["key"] = key;
159 
160  verify_results(name, algorithm_kat(name, vars, af));
161  }
162 
163 /*
164 * Perform a KAT for a cipher
165 */
166 void cipher_kat(Algorithm_Factory& af,
167  const std::string& algo,
168  const std::string& key_str,
169  const std::string& iv_str,
170  const std::string& in,
171  const std::string& ecb_out,
172  const std::string& cbc_out,
173  const std::string& cfb_out,
174  const std::string& ofb_out,
175  const std::string& ctr_out)
176  {
177  SymmetricKey key(key_str);
178  InitializationVector iv(iv_str);
179 
180  std::map<std::string, std::string> vars;
181  vars["key"] = key_str;
182  vars["iv"] = iv_str;
183  vars["input"] = in;
184 
185  std::map<std::string, bool> results;
186 
187  vars["output"] = ecb_out;
188  verify_results(algo + "/ECB", algorithm_kat(algo + "/ECB", vars, af));
189 
190  vars["output"] = cbc_out;
191  verify_results(algo + "/CBC",
192  algorithm_kat(algo + "/CBC/NoPadding", vars, af));
193 
194  vars["output"] = cfb_out;
195  verify_results(algo + "/CFB", algorithm_kat(algo + "/CFB", vars, af));
196 
197  vars["output"] = ofb_out;
198  verify_results(algo + "/OFB", algorithm_kat(algo + "/OFB", vars, af));
199 
200  vars["output"] = ctr_out;
201  verify_results(algo + "/CTR", algorithm_kat(algo + "/CTR-BE", vars, af));
202  }
203 
204 }
205 
206 /*
207 * Perform Self Tests
208 */
210  {
211  try
212  {
214  }
215  catch(Self_Test_Failure)
216  {
217  return false;
218  }
219 
220  return true;
221  }
222 
223 /*
224 * Perform Self Tests
225 */
227  {
228  cipher_kat(af, "DES",
229  "0123456789ABCDEF", "1234567890ABCDEF",
230  "4E6F77206973207468652074696D6520666F7220616C6C20",
231  "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53",
232  "E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6",
233  "F3096249C7F46E51A69E839B1A92F78403467133898EA622",
234  "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3",
235  "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75");
236 
237  cipher_kat(af, "TripleDES",
238  "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
239  "C141B5FCCD28DC8A",
240  "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
241  "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
242  "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
243  "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
244  "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
245  "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
246 
247  cipher_kat(af, "AES-128",
248  "2B7E151628AED2A6ABF7158809CF4F3C",
249  "000102030405060708090A0B0C0D0E0F",
250  "6BC1BEE22E409F96E93D7E117393172A"
251  "AE2D8A571E03AC9C9EB76FAC45AF8E51",
252  "3AD77BB40D7A3660A89ECAF32466EF97"
253  "F5D3D58503B9699DE785895A96FDBAAF",
254  "7649ABAC8119B246CEE98E9B12E9197D"
255  "5086CB9B507219EE95DB113A917678B2",
256  "3B3FD92EB72DAD20333449F8E83CFB4A"
257  "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
258  "3B3FD92EB72DAD20333449F8E83CFB4A"
259  "7789508D16918F03F53C52DAC54ED825",
260  "3B3FD92EB72DAD20333449F8E83CFB4A"
261  "010C041999E03F36448624483E582D0E");
262 
263  hash_test(af, "SHA-1",
264  "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709");
265 
266  hash_test(af, "SHA-1",
267  "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D");
268 
269  hash_test(af, "SHA-1",
270  "6162636462636465636465666465666765666768666768696768696A"
271  "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
272  "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
273 
274  mac_test(af, "HMAC(SHA-1)",
275  "4869205468657265",
276  "B617318655057264E28BC0B6FB378C8EF146BE00",
277  "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
278 
279  hash_test(af, "SHA-256",
280  "",
281  "E3B0C44298FC1C149AFBF4C8996FB924"
282  "27AE41E4649B934CA495991B7852B855");
283 
284  hash_test(af, "SHA-256",
285  "616263",
286  "BA7816BF8F01CFEA414140DE5DAE2223"
287  "B00361A396177A9CB410FF61F20015AD");
288 
289  hash_test(af, "SHA-256",
290  "6162636462636465636465666465666765666768666768696768696A"
291  "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
292  "248D6A61D20638B8E5C026930C3E6039"
293  "A33CE45964FF2167F6ECEDD419DB06C1");
294 
295  mac_test(af, "HMAC(SHA-256)",
296  "4869205468657265",
297  "198A607EB44BFBC69903A0F1CF2BBDC5"
298  "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7",
299  "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"
300  "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
301  }
302 
303 }
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
Definition: stl_util.h:43
std::string cipher_mode() const
Definition: scan_name.h:80
void confirm_startup_self_tests(Algorithm_Factory &af)
Definition: selftest.cpp:226
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
virtual void set_iv(const InitializationVector &iv)
Definition: basefilt.cpp:13
size_t length() const
Definition: symkey.h:25
virtual void set_key(const SymmetricKey &key)=0
const HashFunction * prototype_hash_function(const std::string &algo_spec, const std::string &provider="")
OctetString SymmetricKey
Definition: symkey.h:147
std::string algo_name
Definition: ossl_md.cpp:42
std::string cipher_mode_pad() const
Definition: scan_name.h:86
const MessageAuthenticationCode * prototype_mac(const std::string &algo_spec, const std::string &provider="")
virtual bool valid_iv_length(size_t length) const
Definition: key_filt.h:48
std::map< std::string, bool > algorithm_kat(const SCAN_Name &algo_name, const std::map< std::string, std::string > &vars, Algorithm_Factory &af)
Definition: selftest.cpp:38
std::vector< std::string > providers_of(const std::string &algo_spec)
std::string algo_name_and_args() const
Definition: scan_name.cpp:131
Keyed_Filter * get_cipher_mode(const BlockCipher *block_cipher, Cipher_Dir direction, const std::string &mode, const std::string &padding)
Definition: core_modes.cpp:77
OctetString InitializationVector
Definition: symkey.h:152
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
bool passes_self_tests(Algorithm_Factory &af)
Definition: selftest.cpp:209