Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transport Encryption for Mitosis #18

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
918b005
Implement crypto building blocks, HMAC and HKDF
rossica Jun 24, 2019
6ec4ed1
Add basic known-answer test (KAT) for HMAC-SHA256 implementation.
rossica Jun 28, 2019
5b01d1a
Add more test cases.
rossica Jun 28, 2019
9905636
Add one more HMAC test case
rossica Jun 29, 2019
7742501
Add tests for HKDF functions.
rossica Jun 29, 2019
38504ca
Add AES-CTR mode and tests.
rossica Jul 1, 2019
7c1e7ff
Expand and simplify AES-CTR tests
rossica Jul 1, 2019
48614e6
Change names to match style of project.
rossica Jul 1, 2019
769cc4f
Add code to generate keyboard keys/nonces.
rossica Aug 31, 2019
f76724e
Fix a few issues and use a more-sane initialization function.
rossica Aug 31, 2019
c3da54a
Start building crypto code with rest of project.
rossica Aug 31, 2019
f5a6dec
Add simple test to verify generated keys work.
rossica Sep 4, 2019
1723a53
Integrate encrypted transport with the rest of Mitosis.
rossica Sep 6, 2019
a464c63
Add end-to-end test.
rossica Sep 6, 2019
b98ccd2
Add .gitignore to skip the build output.
rossica Sep 13, 2019
e522055
Fix memory alignment issue, and add debugging variables.
rossica Sep 13, 2019
8e1cf2e
Add precompiled firmware for crypto version.
rossica Sep 13, 2019
9e9d288
Add more debugging variables.
rossica Sep 15, 2019
133039a
Implement CMAC and create tests.
rossica Sep 16, 2019
75174f4
Integrate CMAC into mitosis transport.
rossica Sep 16, 2019
2836577
Small performance improvements.
rossica Sep 21, 2019
0736aa8
Implement CKDF and add tests.
rossica Nov 1, 2019
4a54985
Fix read-beyond-buffer issue in CMAC/CKDF.
rossica Nov 2, 2019
800563c
Pass prk len to mitosis_cmac_init
Detegr Nov 28, 2019
3f7cbb9
Experimental re-key work. VERY UNSTABLE.
rossica Nov 30, 2019
47a0c77
Still unstable, but seems more stable. Might try re-keying with this …
rossica Nov 30, 2019
818bfef
Fix bug in mitosis_cmac_complete().
rossica Dec 30, 2019
3c52e4b
Key refresh working and stable!
rossica Dec 30, 2019
cae4a8f
Simplify rekey code.
rossica Dec 30, 2019
476ef48
Rekeying working for both halves of the keyboard.
rossica Dec 31, 2019
cd8fbaf
Remove commented code.
rossica Dec 31, 2019
0d33b98
More code clean up and renaming.
rossica Dec 31, 2019
272db35
Reformat code to have consistent style across project.
rossica Jan 1, 2020
57ccf3d
Update master secret seed and precompiled files.
rossica Jan 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_build/
48 changes: 48 additions & 0 deletions mitosis-crypto/mitosis-aes-ctr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "mitosis-aes-ctr.h"

bool mitosis_aes_ctr_init(const uint8_t* key, const uint8_t* nonce, mitosis_encrypt_context_t* context)
{
memset(context, 0, sizeof(*context));
memcpy(context->ctr.key, key, sizeof(context->ctr.key));
memcpy(context->ctr.iv_bytes, nonce, sizeof(context->ctr.iv_bytes));
return mitosis_aes_ecb_init(&context->ecb);
}

static inline
void xor(const uint8_t* left, const uint8_t* right, size_t len, uint8_t* out)
{
int idx = 0;
for (; len >= 4; idx += 4, len -= 4)
{
*((uint32_t*) &out[idx]) = *((uint32_t*) &left[idx]) ^ *((uint32_t*) &right[idx]);
}
if (len >= 2)
{
*((uint16_t*) &out[idx]) = *((uint16_t*) &left[idx]) ^ *((uint16_t*) &right[idx]);
idx += 2;
len -= 2;
}
if (len > 0)
{
out[idx] = left[idx] ^ right[idx];
}
}

bool mitosis_aes_ctr_encrypt(mitosis_encrypt_context_t* context, uint32_t datalen, const uint8_t* plaintext, uint8_t* ciphertext)
{
if (datalen > AES_BLOCK_SIZE)
{
return false;
}

if (!mitosis_aes_ecb_encrypt(&context->ecb))
{
return false;
}
xor(plaintext, context->ctr.scratch, datalen, ciphertext);

return true;
}
32 changes: 32 additions & 0 deletions mitosis-crypto/mitosis-aes-ctr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Interface for AES in CTR mode for mitosis
*/
#include "mitosis-aes-ecb.h"

typedef struct _mitosis_aes_ctr_context_t {
uint8_t key[AES_BLOCK_SIZE];
union {
struct {
uint8_t nonce[AES_BLOCK_SIZE - sizeof(uint32_t)];
uint32_t counter;
} iv;
uint8_t iv_bytes[AES_BLOCK_SIZE];
};
uint8_t scratch[AES_BLOCK_SIZE];
} mitosis_aes_ctr_context_t;

_Static_assert(sizeof(mitosis_aes_ctr_context_t) == sizeof(mitosis_aes_ecb_context_t));

typedef union _mitosis_encrypt_context_t {
mitosis_aes_ecb_context_t ecb;
mitosis_aes_ctr_context_t ctr;
} mitosis_encrypt_context_t;

/*
Key and nonce are 16 bytes for consistency.
*/
bool mitosis_aes_ctr_init(const uint8_t* key, const uint8_t* nonce, mitosis_encrypt_context_t* context);

bool mitosis_aes_ctr_encrypt(mitosis_encrypt_context_t* context, uint32_t datalen, const uint8_t* plaintext, uint8_t* ciphertext);

#define mitosis_aes_ctr_decrypt(context, datalen, ciphertext, plaintext) mitosis_aes_ctr_encrypt(context, datalen, ciphertext, plaintext)
57 changes: 57 additions & 0 deletions mitosis-crypto/mitosis-aes-ecb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <nrf.h>
#include "mitosis-aes-ecb.h"

#define ENCRYPT_WAIT 0x1000000

static uint32_t wait_counts = 0;
static uint32_t encrypt_count = 0;

bool mitosis_aes_ecb_init(mitosis_aes_ecb_context_t* state)
{
if (state == NULL)
{
return false;
}

NRF_ECB->ECBDATAPTR = (uint32_t) state;
return true;
}

bool mitosis_aes_ecb_encrypt(mitosis_aes_ecb_context_t* state)
{
if (state == NULL)
{
return false;
}

if (NRF_ECB->ECBDATAPTR != (uint32_t) state)
{
NRF_ECB->ECBDATAPTR = (uint32_t) state;
}

uint32_t wait_counter = ENCRYPT_WAIT;

NRF_ECB->EVENTS_ERRORECB = 0;
NRF_ECB->EVENTS_ENDECB = 0;
NRF_ECB->TASKS_STARTECB = 1;
while (!(NRF_ECB->EVENTS_ENDECB | NRF_ECB->EVENTS_ERRORECB))
{
wait_counter--;
if(wait_counter == 0)
{
return false;
}
}
++encrypt_count;
wait_counts += (ENCRYPT_WAIT - wait_counter);
NRF_ECB->EVENTS_ENDECB = 0;
if (NRF_ECB->EVENTS_ERRORECB)
{
NRF_ECB->EVENTS_ERRORECB = 0;
return false;
}
return true;
}
21 changes: 21 additions & 0 deletions mitosis-crypto/mitosis-aes-ecb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
This file provides an alternate interface to the underlying AES engine.
The point is to reduce the number of calls to memcpy().
*/

#ifndef _MITOSIS_AES_ECB
#define _MITOSIS_AES_ECB

#define AES_BLOCK_SIZE 16

typedef struct _mitosis_aes_ecb_context_t {
uint8_t key[AES_BLOCK_SIZE];
uint8_t plaintext[AES_BLOCK_SIZE];
uint8_t ciphertext[AES_BLOCK_SIZE];
} mitosis_aes_ecb_context_t;

bool mitosis_aes_ecb_init(mitosis_aes_ecb_context_t* state);

bool mitosis_aes_ecb_encrypt(mitosis_aes_ecb_context_t* state);

#endif
85 changes: 85 additions & 0 deletions mitosis-crypto/mitosis-ckdf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <mitosis-cmac.h>
#include "mitosis-ckdf.h"

bool mitosis_ckdf_extract(const uint8_t* ikm, size_t ikm_len, const uint8_t* salt, size_t salt_len, uint8_t* prk)
{
mitosis_cmac_context_t state;

if (!mitosis_cmac_init(&state, salt, salt_len))
{
return false;
}
return mitosis_cmac_compute(&state, ikm, ikm_len, prk);
}

bool
mitosis_ckdf_expand(const uint8_t* prk, size_t prk_len, const uint8_t* info, size_t info_len, uint8_t* okm, size_t okm_len)
{
mitosis_cmac_context_t state;
uint8_t scratch[AES_BLOCK_SIZE];
uint8_t iterations;
uint16_t offset = 0;

if (okm_len > 255 * AES_BLOCK_SIZE)
{
return false;
}

if (okm_len % AES_BLOCK_SIZE)
{
iterations = (uint8_t)(okm_len / AES_BLOCK_SIZE) + 1;
}
else
{
iterations = (uint8_t)(okm_len / AES_BLOCK_SIZE);
}

// i starts at 1 so it can be used to save the memory needed for a separate
// block counter.
for (uint8_t i = 1; i <= iterations && i > 0; ++i)
{
if (!mitosis_cmac_init(&state, prk, prk_len))
{
return false;
}

if (i > 1)
{
if (!mitosis_cmac_hash(&state, scratch, sizeof(scratch)))
{
return false;
}
}

if (!mitosis_cmac_hash(&state, info, info_len))
{
return false;
}

if (!mitosis_cmac_hash(&state, &i, 1))
{
return false;
}

if (!mitosis_cmac_complete(&state, scratch))
{
return false;
}

if (okm_len > sizeof(scratch))
{
memcpy(okm + offset, scratch, sizeof(scratch));
okm_len -= sizeof(scratch);
offset += sizeof(scratch);
}
else
{
memcpy(okm + offset, scratch, okm_len);
}
}
return true;
}
10 changes: 10 additions & 0 deletions mitosis-crypto/mitosis-ckdf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
CKDF interface for Mitosis keyboard

Based on draft-agl-ckdf-01 (https://tools.ietf.org/html/draft-agl-ckdf-01)
*/


bool mitosis_ckdf_extract(const uint8_t* ikm, size_t ikm_len, const uint8_t* salt, size_t salt_len, uint8_t* prk);

bool mitosis_ckdf_expand(const uint8_t* prk, size_t prk_len, const uint8_t* info, size_t info_len, uint8_t* okm, size_t okm_len);
Loading