22#define PLUSAES_VERSION 0x01000000
30const int kWordSize = 4;
31typedef unsigned int Word;
33const int kBlockSize = 4;
37 Word & operator[](
const int index) {
40 const Word & operator[](
const int index)
const {
45const int kStateSize = 16;
46typedef State RoundKey;
47typedef std::vector<RoundKey> RoundKeys;
49inline void add_round_key(
const RoundKey &key, State &state) {
50 for (
int i = 0; i < kBlockSize; ++i) {
55const unsigned char kSbox[] = {
56 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
57 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
58 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
59 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
60 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
61 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
62 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
63 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
64 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
65 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
66 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
67 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
68 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
69 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
70 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
71 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
74const unsigned char kInvSbox[] = {
75 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
76 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
77 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
78 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
79 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
80 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
81 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
82 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
83 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
84 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
85 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
86 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
87 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
88 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
89 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
90 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
93inline Word sub_word(
const Word w) {
94 return kSbox[(w >> 0) & 0xFF] << 0 |
95 kSbox[(w >> 8) & 0xFF] << 8 |
96 kSbox[(w >> 16) & 0xFF] << 16 |
97 kSbox[(w >> 24) & 0xFF] << 24;
100inline Word inv_sub_word(
const Word w) {
101 return kInvSbox[(w >> 0) & 0xFF] << 0 |
102 kInvSbox[(w >> 8) & 0xFF] << 8 |
103 kInvSbox[(w >> 16) & 0xFF] << 16 |
104 kInvSbox[(w >> 24) & 0xFF] << 24;
107inline void sub_bytes(State &state) {
108 for (
int i = 0; i < kBlockSize; ++i) {
109 state[i] = sub_word(state[i]);
113inline void inv_sub_bytes(State &state) {
114 for (
int i = 0; i < kBlockSize; ++i) {
115 state[i] = inv_sub_word(state[i]);
119inline void shift_rows(State &state) {
120 const State ori = { state[0], state[1], state[2], state[3] };
121 for (
int r = 1; r < kWordSize; ++r) {
122 const Word m2 = 0xFF << (r * 8);
124 for (
int c = 0; c < kBlockSize; ++c) {
125 state[c] = (state[c] & m1) | (ori[(c + r) % kBlockSize] & m2);
130inline void inv_shift_rows(State &state) {
131 const State ori = { state[0], state[1], state[2], state[3] };
132 for (
int r = 1; r < kWordSize; ++r) {
133 const Word m2 = 0xFF << (r * 8);
135 for (
int c = 0; c < kBlockSize; ++c) {
136 state[c] = (state[c] & m1) | (ori[(c + kBlockSize - r) % kWordSize] & m2);
141inline unsigned char mul2(
const unsigned char b) {
142 unsigned char m2 = b << 1;
150inline unsigned char mul(
const unsigned char b,
const unsigned char m) {
153 for (
int i = 0; i < 8; ++i) {
154 if ((m >> i) & 0x01) {
164inline void mix_columns(State &state) {
165 for (
int i = 0; i < kBlockSize; ++i) {
166 const unsigned char v0_1 = (state[i] >> 0) & 0xFF;
167 const unsigned char v1_1 = (state[i] >> 8) & 0xFF;
168 const unsigned char v2_1 = (state[i] >> 16) & 0xFF;
169 const unsigned char v3_1 = (state[i] >> 24) & 0xFF;
171 const unsigned char v0_2 = mul2(v0_1);
172 const unsigned char v1_2 = mul2(v1_1);
173 const unsigned char v2_2 = mul2(v2_1);
174 const unsigned char v3_2 = mul2(v3_1);
176 const unsigned char v0_3 = v0_2 ^ v0_1;
177 const unsigned char v1_3 = v1_2 ^ v1_1;
178 const unsigned char v2_3 = v2_2 ^ v2_1;
179 const unsigned char v3_3 = v3_2 ^ v3_1;
182 (v0_2 ^ v1_3 ^ v2_1 ^ v3_1) << 0 |
183 (v0_1 ^ v1_2 ^ v2_3 ^ v3_1) << 8 |
184 (v0_1 ^ v1_1 ^ v2_2 ^ v3_3) << 16 |
185 (v0_3 ^ v1_1 ^ v2_1 ^ v3_2) << 24;
189inline void inv_mix_columns(State &state) {
190 for (
int i = 0; i < kBlockSize; ++i) {
191 const unsigned char v0 = (state[i] >> 0) & 0xFF;
192 const unsigned char v1 = (state[i] >> 8) & 0xFF;
193 const unsigned char v2 = (state[i] >> 16) & 0xFF;
194 const unsigned char v3 = (state[i] >> 24) & 0xFF;
197 (mul(v0, 0x0E) ^ mul(v1, 0x0B) ^ mul(v2, 0x0D) ^ mul(v3, 0x09)) << 0 |
198 (mul(v0, 0x09) ^ mul(v1, 0x0E) ^ mul(v2, 0x0B) ^ mul(v3, 0x0D)) << 8 |
199 (mul(v0, 0x0D) ^ mul(v1, 0x09) ^ mul(v2, 0x0E) ^ mul(v3, 0x0B)) << 16 |
200 (mul(v0, 0x0B) ^ mul(v1, 0x0D) ^ mul(v2, 0x09) ^ mul(v3, 0x0E)) << 24;
204inline Word rot_word(
const Word v) {
205 return ((v >> 8) & 0x00FFFFFF) | ((v & 0xFF) << 24);
212inline unsigned int get_round_count(
const int key_size) {
221 throw std::invalid_argument(
"Invalid key size");
229inline RoundKeys expand_key(
const unsigned char *key,
const int key_size) {
230 if (key_size != 16 && key_size != 24 && key_size != 32) {
231 throw std::invalid_argument(
"Invalid key size");
234 const Word rcon[] = {
235 0x00, 0x01, 0x02, 0x04, 0x08, 0x10,
236 0x20, 0x40, 0x80, 0x1b, 0x36
239 const int nb = kBlockSize;
240 const int nk = key_size / nb;
241 const int nr = get_round_count(key_size);
243 std::vector<Word> w(nb * (nr + 1));
244 for (
int i = 0; i < nk; ++ i) {
245 memcpy(&w[i], key + (i * kWordSize), kWordSize);
248 for (
int i = nk; i < nb * (nr + 1); ++i) {
251 t = sub_word(rot_word(t)) ^ rcon[i / nk];
253 else if (nk > 6 && i % nk == 4) {
257 w[i] = t ^ w[i - nk];
260 RoundKeys keys(nr + 1);
261 memcpy(&keys[0], &w[0], w.size() * kWordSize);
266inline void copy_bytes_to_state(
const unsigned char data[16], State &state) {
267 memcpy(&state[0], data + 0, kWordSize);
268 memcpy(&state[1], data + 4, kWordSize);
269 memcpy(&state[2], data + 8, kWordSize);
270 memcpy(&state[3], data + 12, kWordSize);
273inline void copy_state_to_bytes(
const State &state,
unsigned char buf[16]) {
274 memcpy(buf + 0, &state[0], kWordSize);
275 memcpy(buf + 4, &state[1], kWordSize);
276 memcpy(buf + 8, &state[2], kWordSize);
277 memcpy(buf + 12, &state[3], kWordSize);
280inline void xor_data(
unsigned char data[kStateSize],
const unsigned char v[kStateSize]) {
281 for (
int i = 0; i < kStateSize; ++i) {
287inline void incr_counter(
unsigned char counter[kStateSize]) {
288 unsigned n = kStateSize, c = 1;
297inline void encrypt_state(
const RoundKeys &rkeys,
const unsigned char data[16],
unsigned char encrypted[16]) {
299 copy_bytes_to_state(data, s);
301 add_round_key(rkeys[0], s);
303 for (
unsigned int i = 1; i < rkeys.size() - 1; ++i) {
307 add_round_key(rkeys[i], s);
312 add_round_key(rkeys.back(), s);
314 copy_state_to_bytes(s, encrypted);
317inline void decrypt_state(
const RoundKeys &rkeys,
const unsigned char data[16],
unsigned char decrypted[16]) {
319 copy_bytes_to_state(data, s);
321 add_round_key(rkeys.back(), s);
325 for (std::size_t i = rkeys.size() - 2; i > 0; --i) {
326 add_round_key(rkeys[i], s);
332 add_round_key(rkeys[0], s);
334 copy_state_to_bytes(s, decrypted);
338std::vector<unsigned char>
key_from_string(
const char (*key_str)[KeyLen]) {
339 std::vector<unsigned char> key(KeyLen - 1);
340 memcpy(&key[0], *key_str, KeyLen - 1);
344inline bool is_valid_key_size(
const std::size_t key_size) {
345 if (key_size != 16 && key_size != 24 && key_size != 32) {
356const int kBlockBitSize = 128;
357const int kBlockByteSize = kBlockBitSize / 8;
365typedef std::bitset<kBlockBitSize> bitset128;
392 Block(
const unsigned char * bytes,
const unsigned long bytes_size) {
393 init_v(bytes, bytes_size);
396 Block(
const std::vector<unsigned char> & bytes) {
397 init_v(&bytes[0], bytes.size());
400 Block(
const std::bitset<128> & bits) {
402 const std::bitset<128> mask(0xFF);
403 for (std::size_t i = 0; i < 16; ++i) {
404 v_[15 - i] =
static_cast<unsigned char>(((bits >> (i * 8)) & mask).to_ulong());
408 inline unsigned char * data() {
412 inline const unsigned char* data()
const {
416 inline std::bitset<128> to_bits()
const {
417 std::bitset<128> bits;
418 for (
int i = 0; i < 16; ++i) {
426 inline Block operator^(
const Block & b)
const {
428 for (
int i = 0; i < 16; ++i) {
429 r.data()[i] = data()[i] ^ b.data()[i];
435 unsigned char v_[16];
437 inline void init_v(
const unsigned char * bytes,
const std::size_t bytes_size) {
438 memset(v_, 0,
sizeof(v_));
440 const std::size_t cs = (std::min)(bytes_size,
static_cast<std::size_t
>(16));
441 for (std::size_t i = 0; i < cs; ++i) {
448unsigned long ceil(
const T v) {
449 return static_cast<unsigned long>(std::ceil(v) + 0.5);
452template<std::
size_t N1, std::
size_t N2>
453std::bitset<N1 + N2> operator||(
const std::bitset<N1> &v1,
const std::bitset<N2> &v2) {
454 std::bitset<N1 + N2> ret(v1.to_string() + v2.to_string());
458template<std::
size_t S, std::
size_t N>
459std::bitset<S> lsb(
const std::bitset<N> &X) {
461 for (std::size_t i = 0; i < S; ++i) {
467template<std::
size_t S, std::
size_t N>
468std::bitset<S> msb(
const std::bitset<N> &X) {
470 for (std::size_t i = 0; i < S; ++i) {
471 r[S - 1 - i] = X[X.size() - 1 - i];
476template<std::
size_t N>
477std::bitset<N> inc32(
const std::bitset<N> X) {
478 const std::size_t S = 32;
480 const auto a = msb<N - S>(X);
481 const std::bitset<S> b((lsb<S>(X).to_ulong() + 1));
490#pragma clang diagnostic push
491#pragma clang diagnostic ignored "-Wself-assign"
495inline Block mul_blocks(
const Block X,
const Block Y) {
496 const bitset128 R = (std::bitset<8>(
"11100001") || std::bitset<120>());
498 bitset128 X_bits = X.to_bits();
500 bitset128 V = Y.to_bits();
501 for (
int i = 127; i >= 0; --i) {
503 if (X_bits[i] ==
false) {
523#pragma clang diagnostic pop
527inline Block ghash(
const Block & H,
const std::vector<unsigned char> & X) {
528 const std::size_t m = X.size() / kBlockByteSize;
530 for (std::size_t i = 0; i < m; ++i) {
531 const Block Xi(&X[i * kBlockByteSize], kBlockByteSize);
532 Ym = mul_blocks((Ym ^ Xi), H);
538template<std::
size_t N>
539std::bitset<N> make_bitset(
const unsigned char * bytes,
const std::size_t bytes_size) {
541 for (
auto i = 0u; i < bytes_size; ++i) {
549inline std::vector<unsigned char> gctr(
const detail::RoundKeys & rkeys,
const Block & ICB,
const unsigned char * X,
const std::size_t X_size){
550 if (!X || X_size == 0) {
551 return std::vector<unsigned char>();
554 const unsigned long n = ceil(X_size * 8.0 / kBlockBitSize);
555 std::vector<unsigned char> Y(X_size);
558 for (std::size_t i = 0; i < n; ++i) {
564 CB = inc32(CB.to_bits());
569 encrypt_state(rkeys, CB.data(), eCB.data());
574 op_size = kBlockByteSize;
577 op_size = (X_size % kBlockByteSize) ? (X_size % kBlockByteSize) : kBlockByteSize;
579 const Block Yi = Block(X + i * kBlockBitSize / 8, op_size) ^ eCB;
580 memcpy(&Y[i * kBlockByteSize], Yi.data(), op_size);
587inline void push_back(std::vector<unsigned char> & bytes,
const unsigned char * data,
const std::size_t data_size) {
588 bytes.insert(bytes.end(), data, data + data_size);
591inline void push_back(std::vector<unsigned char> & bytes,
const std::bitset<64> & bits) {
592 const std::bitset<64> mask(0xFF);
593 for (std::size_t i = 0; i < 8; ++i) {
594 bytes.push_back(
static_cast<unsigned char>(((bits >> ((7 - i) * 8)) & mask).to_ulong()));
598inline void push_back_zero_bits(std::vector<unsigned char>& bytes,
const std::size_t zero_bits_size) {
599 const std::vector<unsigned char> zero_bytes(zero_bits_size / 8);
600 bytes.insert(bytes.end(), zero_bytes.begin(), zero_bytes.end());
603inline Block calc_H(
const RoundKeys & rkeys) {
604 std::vector<unsigned char> H_raw(gcm::kBlockByteSize);
605 encrypt_state(rkeys, &H_raw[0], &H_raw[0]);
606 return gcm::Block(H_raw);
609inline Block calc_J0(
const Block & H,
const unsigned char * iv,
const std::size_t iv_size) {
611 const std::bitset<96> iv_bits = gcm::make_bitset<96>(iv, iv_size);
612 return iv_bits || std::bitset<31>() || std::bitset<1>(1);
615 const auto len_iv = iv_size * 8;
616 const auto s = 128 * gcm::ceil(len_iv / 128.0) - len_iv;
617 std::vector<unsigned char> ghash_in;
618 gcm::push_back(ghash_in, iv, iv_size);
619 gcm::push_back_zero_bits(ghash_in, s + 64);
620 gcm::push_back(ghash_in, std::bitset<64>(len_iv));
622 return gcm::ghash(H, ghash_in);
626inline void calc_gcm_tag(
627 const unsigned char * data,
628 const std::size_t data_size,
629 const unsigned char * aadata,
630 const std::size_t aadata_size,
631 const unsigned char * key,
632 const std::size_t key_size,
633 const unsigned char * iv,
634 const std::size_t iv_size,
636 const std::size_t tag_size
638 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
639 const gcm::Block H = gcm::calc_H(rkeys);
640 const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size);
642 const auto lenC = data_size * 8;
643 const auto lenA = aadata_size * 8;
644 const std::size_t u = 128 * gcm::ceil(lenC / 128.0) - lenC;
645 const std::size_t v = 128 * gcm::ceil(lenA / 128.0) - lenA;
647 std::vector<unsigned char> ghash_in;
648 ghash_in.reserve((aadata_size + v / 8) + (data_size + u / 8) + 8 + 8);
649 gcm::push_back(ghash_in, aadata, aadata_size);
650 gcm::push_back_zero_bits(ghash_in, v);
651 gcm::push_back(ghash_in, data, data_size);
652 gcm::push_back_zero_bits(ghash_in, u);
653 gcm::push_back(ghash_in, std::bitset<64>(lenA));
654 gcm::push_back(ghash_in, std::bitset<64>(lenC));
655 const gcm::Block S = gcm::ghash(H, ghash_in);
656 const std::vector<unsigned char> T = gcm::gctr(rkeys, J0, S.data(), gcm::kBlockByteSize);
659 memcpy(tag, &T[0], (std::min)(tag_size,
static_cast<std::size_t
>(16)));
663inline void crypt_gcm(
664 const unsigned char* data,
665 const std::size_t data_size,
666 const unsigned char* key,
667 const std::size_t key_size,
668 const unsigned char* iv,
669 const std::size_t iv_size,
670 unsigned char* crypted
672 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
673 const gcm::Block H = gcm::calc_H(rkeys);
674 const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size);
676 const std::vector<unsigned char> C = gcm::gctr(rkeys, gcm::inc32(J0.to_bits()), data, data_size);
679 memcpy(crypted, &C[0], data_size);
698 return detail::key_from_string<17>(key_str);
703 return detail::key_from_string<25>(key_str);
708 return detail::key_from_string<33>(key_str);
713 return data_size + detail::kStateSize - (data_size % detail::kStateSize);
719 kErrorInvalidDataSize = 1,
720 kErrorInvalidKeySize,
721 kErrorInvalidBufferSize,
725 kErrorInvalidTagSize,
733inline Error check_encrypt_cond(
734 const unsigned long data_size,
735 const unsigned long key_size,
736 const unsigned long encrypted_size,
739 if (!pads && (data_size % kStateSize != 0)) {
740 return kErrorInvalidDataSize;
744 if (!detail::is_valid_key_size(key_size)) {
745 return kErrorInvalidKeySize;
751 if (encrypted_size < required_size) {
752 return kErrorInvalidBufferSize;
756 if (encrypted_size < data_size) {
757 return kErrorInvalidBufferSize;
763inline Error check_decrypt_cond(
764 const unsigned long data_size,
765 const unsigned long key_size,
766 const unsigned long decrypted_size,
767 const unsigned long * padded_size
770 if (data_size % 16 != 0) {
771 return kErrorInvalidDataSize;
775 if (!detail::is_valid_key_size(key_size)) {
776 return kErrorInvalidKeySize;
781 if (decrypted_size < data_size) {
782 return kErrorInvalidBufferSize;
786 if (decrypted_size < (data_size - kStateSize)) {
787 return kErrorInvalidBufferSize;
794inline bool check_padding(
const unsigned long padding,
const unsigned char data[kStateSize]) {
795 if (padding > kStateSize) {
799 for (
unsigned long i = 0; i < padding; ++i) {
800 if (data[kStateSize - 1 - i] != padding) {
808inline Error check_gcm_cond(
809 const std::size_t key_size,
810 const std::size_t iv_size,
811 const std::size_t tag_size
814 if (!detail::is_valid_key_size(key_size)) {
815 return kErrorInvalidKeySize;
819 return kErrorInvalidIvSize;
823 if ((tag_size < 12 || 16 < tag_size) &&
826 return kErrorInvalidTagSize;
854 const unsigned char * data,
855 const unsigned long data_size,
856 const unsigned char * key,
857 const unsigned long key_size,
858 unsigned char *encrypted,
859 const unsigned long encrypted_size,
862 const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads);
867 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
869 const unsigned long bc = data_size / detail::kStateSize;
870 for (
unsigned long i = 0; i < bc; ++i) {
871 detail::encrypt_state(rkeys, data + (i * detail::kStateSize), encrypted + (i * detail::kStateSize));
875 const int rem = data_size % detail::kStateSize;
876 const char pad_v = detail::kStateSize - rem;
878 std::vector<unsigned char> ib(detail::kStateSize, pad_v), ob(detail::kStateSize);
879 memcpy(&ib[0], data + data_size - rem, rem);
881 detail::encrypt_state(rkeys, &ib[0], &ob[0]);
882 memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize);
902 const unsigned char * data,
903 const unsigned long data_size,
904 const unsigned char * key,
905 const unsigned long key_size,
906 unsigned char * decrypted,
907 const unsigned long decrypted_size,
908 unsigned long * padded_size
910 const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size);
915 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
917 const unsigned long bc = data_size / detail::kStateSize - 1;
918 for (
unsigned long i = 0; i < bc; ++i) {
919 detail::decrypt_state(rkeys, data + (i * detail::kStateSize), decrypted + (i * detail::kStateSize));
922 unsigned char last[detail::kStateSize] = {};
923 detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last);
926 *padded_size = last[detail::kStateSize - 1];
927 const unsigned long cs = detail::kStateSize - *padded_size;
929 if (!detail::check_padding(*padded_size, last)) {
930 return kErrorInvalidKey;
932 else if (decrypted_size >= (bc * detail::kStateSize) + cs) {
933 memcpy(decrypted + (bc * detail::kStateSize), last, cs);
936 return kErrorInvalidBufferSize;
940 memcpy(decrypted + (bc * detail::kStateSize), last,
sizeof(last));
969 const unsigned char * data,
970 const unsigned long data_size,
971 const unsigned char * key,
972 const unsigned long key_size,
973 const unsigned char (* iv)[16],
974 unsigned char * encrypted,
975 const unsigned long encrypted_size,
978 const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads);
983 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
985 unsigned char s[detail::kStateSize] = {};
988 const bool ge16 = (data_size >= detail::kStateSize);
989 const int rem = data_size % detail::kStateSize;
990 const unsigned char pad_v = detail::kStateSize - rem;
994 memcpy(s, data, detail::kStateSize);
997 memset(s, pad_v, detail::kStateSize);
998 memcpy(s, data, data_size);
1001 detail::xor_data(s, *iv);
1003 detail::encrypt_state(rkeys, s, encrypted);
1006 const unsigned long bc = data_size / detail::kStateSize;
1007 for (
unsigned long i = 1; i < bc; ++i) {
1008 const long offset = i * detail::kStateSize;
1009 memcpy(s, data + offset, detail::kStateSize);
1010 detail::xor_data(s, encrypted + offset - detail::kStateSize);
1012 detail::encrypt_state(rkeys, s, encrypted + offset);
1017 std::vector<unsigned char> ib(detail::kStateSize, pad_v), ob(detail::kStateSize);
1018 memcpy(&ib[0], data + data_size - rem, rem);
1020 detail::xor_data(&ib[0], encrypted + (bc - 1) * detail::kStateSize);
1022 detail::encrypt_state(rkeys, &ib[0], &ob[0]);
1023 memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize);
1044 const unsigned char * data,
1045 const unsigned long data_size,
1046 const unsigned char * key,
1047 const unsigned long key_size,
1048 const unsigned char (* iv)[16],
1049 unsigned char * decrypted,
1050 const unsigned long decrypted_size,
1051 unsigned long * padded_size
1053 const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size);
1054 if (e != kErrorOk) {
1058 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
1061 detail::decrypt_state(rkeys, data, decrypted);
1063 detail::xor_data(decrypted, *iv);
1067 const unsigned long bc = data_size / detail::kStateSize - 1;
1068 for (
unsigned long i = 1; i < bc; ++i) {
1069 const long offset = i * detail::kStateSize;
1070 detail::decrypt_state(rkeys, data + offset, decrypted + offset);
1071 detail::xor_data(decrypted + offset, data + offset - detail::kStateSize);
1075 unsigned char last[detail::kStateSize] = {};
1076 if (data_size > detail::kStateSize) {
1077 detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last);
1078 detail::xor_data(last, data + (bc * detail::kStateSize - detail::kStateSize));
1081 memcpy(last, decrypted, data_size);
1082 memset(decrypted, 0, decrypted_size);
1086 *padded_size = last[detail::kStateSize - 1];
1087 const unsigned long cs = detail::kStateSize - *padded_size;
1089 if (!detail::check_padding(*padded_size, last)) {
1090 return kErrorInvalidKey;
1092 else if (decrypted_size >= (bc * detail::kStateSize) + cs) {
1093 memcpy(decrypted + (bc * detail::kStateSize), last, cs);
1096 return kErrorInvalidBufferSize;
1100 memcpy(decrypted + (bc * detail::kStateSize), last,
sizeof(last));
1124 unsigned char * data,
1125 const std::size_t data_size,
1126 const unsigned char * aadata,
1127 const std::size_t aadata_size,
1128 const unsigned char * key,
1129 const std::size_t key_size,
1130 const unsigned char * iv,
1131 const std::size_t iv_size,
1132 unsigned char * tag,
1133 const std::size_t tag_size
1135 const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size);
1136 if (err != kErrorOk) {
1140 detail::gcm::crypt_gcm(data, data_size, key, key_size, iv, iv_size, data);
1141 detail::gcm::calc_gcm_tag(data, data_size, aadata, aadata_size, key, key_size, iv, iv_size, tag, tag_size);
1163 unsigned char * data,
1164 const std::size_t data_size,
1165 const unsigned char * aadata,
1166 const std::size_t aadata_size,
1167 const unsigned char * key,
1168 const std::size_t key_size,
1169 const unsigned char (*iv)[12],
1170 unsigned char (*tag)[16]
1172 return encrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16);
1188 unsigned char * data,
1189 const std::size_t data_size,
1190 const unsigned char * aadata,
1191 const std::size_t aadata_size,
1192 const unsigned char * key,
1193 const std::size_t key_size,
1194 const unsigned char * iv,
1195 const std::size_t iv_size,
1196 const unsigned char * tag,
1197 const std::size_t tag_size
1199 const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size);
1200 if (err != kErrorOk) {
1204 unsigned char * C = data;
1205 const auto C_size = data_size;
1206 unsigned char tagd[16] = {};
1207 detail::gcm::calc_gcm_tag(C, C_size, aadata, aadata_size, key, key_size, iv, iv_size, tagd, 16);
1209 if (memcmp(tag, tagd, tag_size) != 0) {
1210 return kErrorInvalidTag;
1213 detail::gcm::crypt_gcm(C, C_size, key, key_size, iv, iv_size, C);
1237 unsigned char * data,
1238 const std::size_t data_size,
1239 const unsigned char * aadata,
1240 const std::size_t aadata_size,
1241 const unsigned char * key,
1242 const std::size_t key_size,
1243 const unsigned char (*iv)[12],
1244 const unsigned char (*tag)[16]
1246 return decrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16);
1270 unsigned char * data,
1271 const std::size_t data_size,
1272 const unsigned char * key,
1273 const std::size_t key_size,
1274 const unsigned char (*nonce)[16]
1276 if (!detail::is_valid_key_size(key_size))
return kErrorInvalidKeySize;
1277 const detail::RoundKeys rkeys = detail::expand_key(key,
static_cast<int>(key_size));
1279 unsigned long pos = 0;
1280 unsigned long blkpos = detail::kStateSize;
1281 unsigned char blk[detail::kStateSize] = {};
1282 unsigned char counter[detail::kStateSize] = {};
1283 memcpy(counter, nonce, 16);
1285 while (pos < data_size) {
1286 if (blkpos == detail::kStateSize) {
1287 detail::encrypt_state(rkeys, counter, blk);
1288 detail::incr_counter(counter);
1291 data[pos++] ^= blk[blkpos++];
unsigned int version()
Definition: plusaes.hpp:692
std::vector< unsigned char > key_from_string(const char(*key_str)[17])
Definition: plusaes.hpp:697
#define PLUSAES_VERSION
Definition: plusaes.hpp:22
Error
Definition: plusaes.hpp:717
unsigned long get_padded_encrypted_size(const unsigned long data_size)
Definition: plusaes.hpp:712
Error decrypt_cbc(const unsigned char *data, const unsigned long data_size, const unsigned char *key, const unsigned long key_size, const unsigned char(*iv)[16], unsigned char *decrypted, const unsigned long decrypted_size, unsigned long *padded_size)
Definition: plusaes.hpp:1043
Error encrypt_cbc(const unsigned char *data, const unsigned long data_size, const unsigned char *key, const unsigned long key_size, const unsigned char(*iv)[16], unsigned char *encrypted, const unsigned long encrypted_size, const bool pads)
Definition: plusaes.hpp:968
Error crypt_ctr(unsigned char *data, const std::size_t data_size, const unsigned char *key, const std::size_t key_size, const unsigned char(*nonce)[16])
Definition: plusaes.hpp:1269
Error decrypt_ecb(const unsigned char *data, const unsigned long data_size, const unsigned char *key, const unsigned long key_size, unsigned char *decrypted, const unsigned long decrypted_size, unsigned long *padded_size)
Definition: plusaes.hpp:901
Error encrypt_ecb(const unsigned char *data, const unsigned long data_size, const unsigned char *key, const unsigned long key_size, unsigned char *encrypted, const unsigned long encrypted_size, const bool pads)
Definition: plusaes.hpp:853
Error encrypt_gcm(unsigned char *data, const std::size_t data_size, const unsigned char *aadata, const std::size_t aadata_size, const unsigned char *key, const std::size_t key_size, const unsigned char *iv, const std::size_t iv_size, unsigned char *tag, const std::size_t tag_size)
Definition: plusaes.hpp:1123
Error decrypt_gcm(unsigned char *data, const std::size_t data_size, const unsigned char *aadata, const std::size_t aadata_size, const unsigned char *key, const std::size_t key_size, const unsigned char *iv, const std::size_t iv_size, const unsigned char *tag, const std::size_t tag_size)
Definition: plusaes.hpp:1187
Definition: plusaes.hpp:27