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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
#include "tests.h"
#include <iostream>
#if defined(BOTAN_HAS_OCB)
#include <botan/ocb.h>
#include <botan/hex.h>
#include <botan/sha2_32.h>
#include <botan/aes.h>
using namespace Botan;
// something like this should be in the library
namespace {
std::vector<byte> ocb_decrypt(const SymmetricKey& key,
const std::vector<byte>& nonce,
const byte ct[], size_t ct_len,
const byte ad[], size_t ad_len)
{
OCB_Decryption ocb(new AES_128);
ocb.set_key(key);
ocb.set_associated_data(ad, ad_len);
ocb.start(&nonce[0], nonce.size());
secure_vector<byte> buf(ct, ct+ct_len);
ocb.finish(buf, 0);
return unlock(buf);
}
std::vector<byte> ocb_encrypt(const SymmetricKey& key,
const std::vector<byte>& nonce,
const byte pt[], size_t pt_len,
const byte ad[], size_t ad_len)
{
OCB_Encryption ocb(new AES_128);
ocb.set_key(key);
ocb.set_associated_data(ad, ad_len);
ocb.start(&nonce[0], nonce.size());
secure_vector<byte> buf(pt, pt+pt_len);
ocb.finish(buf, 0);
try
{
std::vector<byte> pt2 = ocb_decrypt(key, nonce, &buf[0], buf.size(), ad, ad_len);
if(pt_len != pt2.size() || !same_mem(pt, &pt2[0], pt_len))
std::cout << "OCB failed to decrypt correctly\n";
}
catch(std::exception& e)
{
std::cout << "OCB round trip error - " << e.what() << "\n";
}
return unlock(buf);
}
template<typename Alloc, typename Alloc2>
std::vector<byte> ocb_encrypt(const SymmetricKey& key,
const std::vector<byte>& nonce,
const std::vector<byte, Alloc>& pt,
const std::vector<byte, Alloc2>& ad)
{
return ocb_encrypt(key, nonce, &pt[0], pt.size(), &ad[0], ad.size());
}
template<typename Alloc, typename Alloc2>
std::vector<byte> ocb_decrypt(const SymmetricKey& key,
const std::vector<byte>& nonce,
const std::vector<byte, Alloc>& pt,
const std::vector<byte, Alloc2>& ad)
{
return ocb_decrypt(key, nonce, &pt[0], pt.size(), &ad[0], ad.size());
}
std::vector<byte> ocb_encrypt(OCB_Encryption& ocb,
const std::vector<byte>& nonce,
const std::vector<byte>& pt,
const std::vector<byte>& ad)
{
ocb.set_associated_data(&ad[0], ad.size());
ocb.start(&nonce[0], nonce.size());
secure_vector<byte> buf(pt.begin(), pt.end());
ocb.finish(buf, 0);
return unlock(buf);
}
size_t test_ocb_long(size_t taglen, const std::string &expected)
{
OCB_Encryption ocb(new AES_128, taglen/8);
ocb.set_key(SymmetricKey("00000000000000000000000000000000"));
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);
N[11] = i;
C += ocb_encrypt(ocb, N, S, S);
C += ocb_encrypt(ocb, N, S, empty);
C += ocb_encrypt(ocb, N, empty, S);
}
N[11] = 0;
const std::vector<byte> cipher = ocb_encrypt(ocb, N, empty, C);
const std::string cipher_hex = hex_encode(cipher);
if(cipher_hex != expected)
{
std::cout << "OCB AES-128 long test mistmatch " << cipher_hex << " != " << expected << "\n";
return 1;
}
return 0;
}
}
#endif
size_t test_ocb()
{
size_t fails = 0;
#if defined(BOTAN_HAS_OCB)
fails += test_ocb_long(128, "B2B41CBF9B05037DA7F16C24A35C1C94");
fails += test_ocb_long(96, "1A4F0654277709A5BDA0D380");
fails += test_ocb_long(64, "B7ECE9D381FE437F");
test_report("OCB long", 3, fails);
#endif
return fails;
}
|