aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/test_ocb.cpp
blob: 0e31941cbbdd2a3ce84aea96b2a4d2798688f575 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* (C) 2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"
#include <iostream>

#if defined(BOTAN_HAS_AEAD_OCB)
#include <botan/ocb.h>
#include <botan/hex.h>
#include <botan/sha2_32.h>
#include <botan/aes.h>
#include <botan/loadstor.h>
#include <botan/libstate.h>

using namespace Botan;

namespace {

std::vector<byte> ocb_encrypt(OCB_Encryption& enc,
                              OCB_Decryption& dec,
                              const std::vector<byte>& nonce,
                              const std::vector<byte>& pt,
                              const std::vector<byte>& ad)
   {
   enc.set_associated_data(&ad[0], ad.size());

   enc.start(&nonce[0], nonce.size());

   secure_vector<byte> buf(pt.begin(), pt.end());
   enc.finish(buf, 0);

   try
      {
      secure_vector<byte> ct = buf;

      dec.set_associated_data(&ad[0], ad.size());

      dec.start(&nonce[0], nonce.size());

      dec.finish(ct, 0);

      if(ct != pt)
         std::cout << "OCB failed to decrypt correctly\n";
      }
   catch(std::exception& e)
      {
      std::cout << "OCB round trip error - " << e.what() << "\n";
      }

   return unlock(buf);
   }

size_t test_ocb_long(Algorithm_Factory& af,
                     size_t keylen, size_t taglen,
                     const std::string &expected)
   {
   // Test from RFC 7253 Appendix A

   const std::string algo = "AES-" + std::to_string(keylen);

   OCB_Encryption enc(af.make_block_cipher(algo), taglen / 8);

   OCB_Decryption dec(af.make_block_cipher(algo), taglen / 8);

   std::vector<byte> key(keylen/8);
   key[keylen/8-1] = taglen;

   enc.set_key(key);
   dec.set_key(key);

   const std::vector<byte> empty;
   std::vector<byte> N(12);
   std::vector<byte> C;

   for(size_t i = 0; i != 128; ++i)
      {
      const std::vector<byte> S(i);

      store_be(static_cast<u32bit>(3*i+1), &N[8]);
      C += ocb_encrypt(enc, dec, N, S, S);
      store_be(static_cast<u32bit>(3*i+2), &N[8]);
      C += ocb_encrypt(enc, dec, N, S, empty);
      store_be(static_cast<u32bit>(3*i+3), &N[8]);
      C += ocb_encrypt(enc, dec, N, empty, S);
      }

   store_be(static_cast<u32bit>(385), &N[8]);
   const std::vector<byte> cipher = ocb_encrypt(enc, dec, N, empty, C);

   const std::string cipher_hex = hex_encode(cipher);

   if(cipher_hex != expected)
      {
      std::cout << "OCB " << algo << " long test mistmatch "
                << cipher_hex << " != " << expected << "\n";
      return 1;
      }

   return 0;
   }

}
#endif

size_t test_ocb()
   {
   size_t fails = 0;

#if defined(BOTAN_HAS_AEAD_OCB)
   Algorithm_Factory& af = global_state().algorithm_factory();

   fails += test_ocb_long(af, 128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2");
   fails += test_ocb_long(af, 192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17");
   fails += test_ocb_long(af, 256, 128, "D90EB8E9C977C88B79DD793D7FFA161C");
   fails += test_ocb_long(af, 128, 96, "77A3D8E73589158D25D01209");
   fails += test_ocb_long(af, 192, 96, "05D56EAD2752C86BE6932C5E");
   fails += test_ocb_long(af, 256, 96, "5458359AC23B0CBA9E6330DD");
   fails += test_ocb_long(af, 128, 64, "192C9B7BD90BA06A");
   fails += test_ocb_long(af, 192, 64, "0066BC6E0EF34E24");
   fails += test_ocb_long(af, 256, 64, "7D4EA5D445501CBE");
   test_report("OCB long", 9, fails);
#endif

   return fails;
   }