36#ifndef _CC32xxAESCCM_HXX_
37#define _CC32xxAESCCM_HXX_
41#include "inc/hw_types.h"
42#include "inc/hw_memmap.h"
43#include "inc/hw_aes.h"
44#include "inc/hw_dthe.h"
45#include "driverlib/prcm.h"
46#include "driverlib/rom.h"
47#include "driverlib/rom_map.h"
48#include "driverlib/aes.h"
70 static void decrypt(
const std::string &aes_key,
const std::string &nonce,
71 const std::string &auth_data,
const std::string &cipher,
72 std::string *plain, std::string *tag)
75 h.
decrypt_init(aes_key, nonce, auth_data, cipher.size(), tag->size());
76 unsigned ofs = cipher.size() / 3;
100 static void encrypt(
const std::string &aes_key,
const std::string &nonce,
101 const std::string &auth_data,
const std::string &plain,
102 unsigned tag_len, std::string *cipher, std::string *tag)
104 static_encrypt_init(aes_key, nonce, auth_data, plain.size(), tag_len);
105 cipher->resize(plain.size() + 15);
106 int len = plain.size();
111 (
const uint8_t *)&plain[ofs], (uint8_t *)&(*cipher)[ofs]);
118 memset(buf, 0,
sizeof(buf));
119 memcpy(buf, &plain[ofs], len);
122 cipher->resize(plain.size());
123 tag->resize(tag_len);
141 void decrypt_init(
const std::string &aes_key,
const std::string &nonce,
142 const std::string &auth_data,
unsigned data_len, uint8_t tag_len)
149 static void static_decrypt_init(
const std::string &aes_key,
150 const std::string &nonce,
const std::string &auth_data,
151 unsigned data_len, uint8_t tag_len)
155 unsigned mode = AES_CFG_DIR_DECRYPT | AES_CFG_MODE_CCM |
156 AES_CFG_CTR_WIDTH_32 |
157 get_mode(aes_key.size(), nonce.size(), tag_len);
158 MAP_AESConfigSet(AES_BASE, mode);
164 while (real_iv.size() < 16)
166 real_iv.push_back(0);
168 MAP_AESIVSet(AES_BASE, (uint8_t *)real_iv.data());
171 MAP_AESKey1Set(AES_BASE, (uint8_t *)aes_key.data(),
173 MAP_AESDataLengthSet(AES_BASE, data_len);
174 MAP_AESAuthDataLengthSet(AES_BASE, auth_data.size());
177 for (
unsigned ofs = 0; ofs < auth_data.size(); ofs += 16)
179 MAP_AESDataWrite(AES_BASE, (uint8_t *)&auth_data[ofs],
180 std::min(16u, auth_data.size() - ofs));
184 static void static_encrypt_init(
const std::string &aes_key,
185 const std::string &nonce,
const std::string &auth_data,
186 unsigned data_len, uint8_t tag_len)
190 unsigned mode = AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_CCM |
191 AES_CFG_CTR_WIDTH_32 |
192 get_mode(aes_key.size(), nonce.size(), tag_len);
193 MAP_AESConfigSet(AES_BASE, mode);
199 while (real_iv.size() < 16)
201 real_iv.push_back(0);
203 MAP_AESIVSet(AES_BASE, (uint8_t *)real_iv.data());
206 MAP_AESKey1Set(AES_BASE, (uint8_t *)aes_key.data(),
208 MAP_AESDataLengthSet(AES_BASE, data_len);
209 MAP_AESAuthDataLengthSet(AES_BASE, auth_data.size());
212 for (
unsigned ofs = 0; ofs < auth_data.size(); ofs += 16)
214 MAP_AESDataWrite(AES_BASE, (uint8_t *)&auth_data[ofs],
215 std::min(16u, auth_data.size() - ofs));
224 void data_process(
const std::string &payload, std::string *payload_out)
226 payload_out->clear();
227 payload_out->reserve(payload.size() + 16);
230 HASSERT(ret == (ssize_t)payload.size());
239 payload_out->clear();
268 const std::string &nonce,
const std::string &auth_data,
269 unsigned data_len, uint8_t tag_len,
SyncStream *consumer,
270 std::string *tag_out,
const std::string* expected_tag)
272 static_decrypt_init(aes_key, nonce, auth_data, data_len, tag_len);
273 tag_out->resize(tag_len);
286 , expectedTag_(expected_tag)
290 ssize_t
write(
const void *data,
size_t len)
override
295 auto rp = (
const uint8_t *)(data);
296 auto wp = (uint8_t *)(data);
312 if (expectedTag_ && (*expectedTag_ != *tagOut_)) {
319 std::string *tagOut_;
320 const std::string *expectedTag_;
327 MAP_PRCMPeripheralClkDisable(PRCM_DTHE, PRCM_RUN_MODE_CLK);
329 MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK);
331 while (!MAP_PRCMPeripheralStatusGet(PRCM_DTHE))
344 return AES_CFG_KEY_SIZE_128BIT;
346 return AES_CFG_KEY_SIZE_192BIT;
348 return AES_CFG_KEY_SIZE_256BIT;
350 DIE(
"Unknown key length");
377 unsigned key_len,
unsigned nonce_len,
unsigned tag_len)
384 ret |= AES_CFG_CCM_L_2;
387 ret |= AES_CFG_CCM_L_4;
390 ret |= AES_CFG_CCM_L_8;
393 DIE(
"unsupported nonce length");
399 ret |= AES_CFG_CCM_M_4;
402 ret |= AES_CFG_CCM_M_6;
405 ret |= AES_CFG_CCM_M_8;
408 ret |= AES_CFG_CCM_M_10;
411 ret |= AES_CFG_CCM_M_12;
414 ret |= AES_CFG_CCM_M_14;
417 ret |= AES_CFG_CCM_M_16;
420 DIE(
"Unsupported tag length");
431 MAP_AESDataWrite(AES_BASE, (uint8_t *)din, 16);
432 MAP_AESDataRead(AES_BASE, dout, 16);
443 while ((AES_CTRL_SVCTXTRDY & (HWREG(AES_BASE + AES_O_CTRL))) == 0)
447 MAP_AESTagRead(AES_BASE, tag);
448 tag_out->assign((
const char*)tag, tag_out->size());
int finalize(int status) override
Called once after all data has been written to close the stream and release resources.
ssize_t write(const void *data, size_t len) override
Main entry point to the data consumption.
Helper class for doing CCM encryption-with-authentication using the CC32xx's hardware AES engine.
void data_finalize(std::string *payload_out, std::string *tag_out)
Completes the streaming operation.
std::unique_ptr< SyncStream > decryptorStream_
Implementation object.
static unsigned get_mode(unsigned key_len, unsigned nonce_len, unsigned tag_len)
Computes mode bits for the AES engine.
static void reset()
Resets / turns on the AES engine.
static void decrypt(const std::string &aes_key, const std::string &nonce, const std::string &auth_data, const std::string &cipher, std::string *plain, std::string *tag)
Performs authenticated decryption using CCM in one call.
void data_process(const std::string &payload, std::string *payload_out)
Process streaming encryption data.
static SyncStream * create_decryptor_stream(const std::string &aes_key, const std::string &nonce, const std::string &auth_data, unsigned data_len, uint8_t tag_len, SyncStream *consumer, std::string *tag_out, const std::string *expected_tag)
Creates a stream for on-the-fly receiving encrypted data and passing on decrypted data to a consumer ...
static void process_block(const uint8_t *din, uint8_t *dout)
Performs encryption (or decryption) on a single block of data.
void decrypt_init(const std::string &aes_key, const std::string &nonce, const std::string &auth_data, unsigned data_len, uint8_t tag_len)
Initializes streaming decryption.
StringAppendStream * outputStream_
Stream that catches the decrypted output in the user-provided strings.
std::string tagOut_
Variable that will receive the output tag.
static uint32_t interpret_key_size(unsigned key_len)
Computes the internal constant used for the configuration of the key size.
static void encrypt(const std::string &aes_key, const std::string &nonce, const std::string &auth_data, const std::string &plain, unsigned tag_len, std::string *cipher, std::string *tag)
Performs authenticated encryption using CCM in one call.
static void read_tag(std::string *tag_out)
Finalizes encyrption/decryption and reads out the checksum tag.
static int nonce_length_to_l(unsigned nonce_len)
Compute the size of the L parameter in bytes from the nonce length.
Stream wrapper that limits the number of bytes sent to the child stream, and reports EOF after the gi...
Stream wrapper that contains a small internal buffer to ensure that all writes are at least a certain...
Simple stream implementation that appends all data to a given std::string.
Helper class for defining streams that forward data to another stream internally.
int finalize(int status) override
Called once after all data has been written to close the stream and release resources.
std::unique_ptr< SyncStream > delegate_
Where to write the data to.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define DIE(MSG)
Unconditionally terminates the current process with a message.