SE050 Driver
API reference
Loading...
Searching...
No Matches
se050_rfc3394.hpp
Go to the documentation of this file.
1
13#pragma once
14
15#include "se050_types.hpp"
16
17#include <cstddef>
18#include <cstdint>
19#include <cstring>
20
21namespace se050::rfc3394 {
22
23inline constexpr std::uint64_t kIntegrityIv = 0xA6A6A6A6A6A6A6A6ULL;
24inline constexpr std::size_t kAes256CekLen = 32U;
25inline constexpr std::size_t kAes256WrappedLen = 40U;
26
28using AesBlockFn = Error (*)(const std::uint8_t in[16], std::uint8_t out[16], void* ctx);
29
30[[nodiscard]] inline std::uint64_t LoadBe64(const std::uint8_t* p) noexcept {
31 return (static_cast<std::uint64_t>(p[0]) << 56) | (static_cast<std::uint64_t>(p[1]) << 48) |
32 (static_cast<std::uint64_t>(p[2]) << 40) | (static_cast<std::uint64_t>(p[3]) << 32) |
33 (static_cast<std::uint64_t>(p[4]) << 24) | (static_cast<std::uint64_t>(p[5]) << 16) |
34 (static_cast<std::uint64_t>(p[6]) << 8) | static_cast<std::uint64_t>(p[7]);
35}
36
37inline void StoreBe64(std::uint8_t* p, std::uint64_t v) noexcept {
38 p[0] = static_cast<std::uint8_t>(v >> 56);
39 p[1] = static_cast<std::uint8_t>(v >> 48);
40 p[2] = static_cast<std::uint8_t>(v >> 40);
41 p[3] = static_cast<std::uint8_t>(v >> 32);
42 p[4] = static_cast<std::uint8_t>(v >> 24);
43 p[5] = static_cast<std::uint8_t>(v >> 16);
44 p[6] = static_cast<std::uint8_t>(v >> 8);
45 p[7] = static_cast<std::uint8_t>(v);
46}
47
52[[nodiscard]] inline Error Unwrap(const std::uint8_t* wrapped, std::size_t wrapped_len, std::uint8_t* out,
53 std::size_t out_cap, std::size_t* out_len, AesBlockFn decrypt,
54 void* ctx) noexcept {
55 if (out_len == nullptr) {
57 }
58 *out_len = 0;
59 if (wrapped == nullptr || out == nullptr || decrypt == nullptr) {
61 }
62 if ((wrapped_len < 24U) || ((wrapped_len % 8U) != 0U)) {
64 }
65 const std::size_t n = (wrapped_len / 8U) - 1U;
66 const std::size_t plain_len = n * 8U;
67 if (out_cap < plain_len) {
69 }
70 std::uint64_t a = LoadBe64(wrapped);
71 std::uint64_t r[8]{};
72 if (n > 8U) {
74 }
75 for (std::size_t i = 0; i < n; ++i) {
76 r[i] = LoadBe64(wrapped + 8U * (i + 1U));
77 }
78 for (int j = 5; j >= 0; --j) {
79 for (std::size_t i = n; i >= 1U; --i) {
80 const std::uint64_t t = static_cast<std::uint64_t>(n) * static_cast<std::uint64_t>(j) + i;
81 a ^= t;
82 std::uint8_t block[16]{};
83 StoreBe64(block, a);
84 StoreBe64(block + 8, r[i - 1U]);
85 std::uint8_t outb[16]{};
86 const Error e = decrypt(block, outb, ctx);
87 if (e != Error::Ok) {
88 return e;
89 }
90 a = LoadBe64(outb);
91 r[i - 1U] = LoadBe64(outb + 8);
92 }
93 }
94 if (a != kIntegrityIv) {
95 return Error::Protocol;
96 }
97 for (std::size_t i = 0; i < n; ++i) {
98 StoreBe64(out + 8U * i, r[i]);
99 }
100 *out_len = plain_len;
101 return Error::Ok;
102}
103
108[[nodiscard]] inline Error Wrap(const std::uint8_t* plain, std::size_t plain_len, std::uint8_t* out,
109 std::size_t out_cap, std::size_t* out_len, AesBlockFn encrypt,
110 void* ctx) noexcept {
111 if (out_len == nullptr) {
113 }
114 *out_len = 0;
115 if (plain == nullptr || out == nullptr || encrypt == nullptr) {
117 }
118 if ((plain_len < 16U) || ((plain_len % 8U) != 0U)) {
120 }
121 const std::size_t n = plain_len / 8U;
122 const std::size_t wrapped_len = (n + 1U) * 8U;
123 if (n > 8U) {
125 }
126 if (out_cap < wrapped_len) {
128 }
129 std::uint64_t a = kIntegrityIv;
130 std::uint64_t r[8]{};
131 for (std::size_t i = 0; i < n; ++i) {
132 r[i] = LoadBe64(plain + 8U * i);
133 }
134 for (int j = 0; j <= 5; ++j) {
135 for (std::size_t i = 1U; i <= n; ++i) {
136 std::uint8_t block[16]{};
137 StoreBe64(block, a);
138 StoreBe64(block + 8, r[i - 1U]);
139 std::uint8_t outb[16]{};
140 const Error e = encrypt(block, outb, ctx);
141 if (e != Error::Ok) {
142 return e;
143 }
144 a = LoadBe64(outb);
145 const std::uint64_t t = static_cast<std::uint64_t>(n) * static_cast<std::uint64_t>(j) + i;
146 a ^= t;
147 r[i - 1U] = LoadBe64(outb + 8);
148 }
149 }
150 StoreBe64(out, a);
151 for (std::size_t i = 0; i < n; ++i) {
152 StoreBe64(out + 8U * (i + 1U), r[i]);
153 }
154 *out_len = wrapped_len;
155 return Error::Ok;
156}
157
158} // namespace se050::rfc3394
Definition se050_rfc3394.hpp:21
constexpr std::size_t kAes256CekLen
Definition se050_rfc3394.hpp:24
std::uint64_t LoadBe64(const std::uint8_t *p) noexcept
Definition se050_rfc3394.hpp:30
constexpr std::uint64_t kIntegrityIv
Definition se050_rfc3394.hpp:23
Error Unwrap(const std::uint8_t *wrapped, std::size_t wrapped_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, AesBlockFn decrypt, void *ctx) noexcept
RFC 3394 unwrap. wrapped_len must be 8*(n+1) with n >= 2.
Definition se050_rfc3394.hpp:52
Error Wrap(const std::uint8_t *plain, std::size_t plain_len, std::uint8_t *out, std::size_t out_cap, std::size_t *out_len, AesBlockFn encrypt, void *ctx) noexcept
RFC 3394 wrap. plain_len must be 8*n with n >= 2.
Definition se050_rfc3394.hpp:108
Error(*)(const std::uint8_t in[16], std::uint8_t out[16], void *ctx) AesBlockFn
AES-ECB encrypt or decrypt of one 16-byte block (KEK size is the oracle's).
Definition se050_rfc3394.hpp:28
void StoreBe64(std::uint8_t *p, std::uint64_t v) noexcept
Definition se050_rfc3394.hpp:37
constexpr std::size_t kAes256WrappedLen
Definition se050_rfc3394.hpp:25
Error
Definition se050_types.hpp:14
Shared types, limits, and error codes for the HF-SE050 driver.