1
0
Fork 0

Initial Commit

This commit is contained in:
Shawn Nock 2016-06-01 15:07:50 -04:00
commit 1f80a3a3dc
20 changed files with 1068 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_build

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
# List all source files the application uses.
APPLICATION_SRCS = $(notdir $(wildcard ./*.c))
PROJECT_NAME = cmac_aes128_test
VERSION = 0.1
DEVICE = NRF51
#USE_SOFTDEVICE = s110
SDK_PATH = $(HOME)/devel/nrf-sdk/10.0/
TEMPLATE_PATH = ./template/
CFLAGS = -Os -Wall -Werror -flto -g
LDFLAGS = -Os -flto -g
include $(TEMPLATE_PATH)Makefile

26
README.md Normal file
View File

@ -0,0 +1,26 @@
# CMAC-AES128 for nRF51
- Uses AES-ECB hardware peripheral
- Includes target test app that runs the NIST 800-38B Examples
- Includes host test app that checks the NIST 800-38B Examples
(requires OpenSSL)
## Usage
1. Edit `Makefile`, special note to edit the path to the NRF-SDK
(tested against SDK 10.0)
2. Edit main.c:
> #define ERROR_LED_PIN 12
> #define ERROR_LED_ACTIVE LOW
3. `make`:
Output files in `_build` directory. Program to nRF51 dev. board to
run tests on target.
4. `make test`:
Fakes AES128 peripheral using openssl, then runs tests on host.

41
aes.c Normal file
View File

@ -0,0 +1,41 @@
#include "aes.h"
#include "block.h"
#ifndef HOST_BUILD
#include "nrf.h"
#else
#include <openssl/evp.h>
#endif /* HOST_BUILD */
#include <string.h>
static ecbdata_t g_ecbdata;
void aes128_init(uint8_t *key) {
memmove(g_ecbdata.key, key, 16);
#ifndef HOST_BUILD
NRF_ECB->ECBDATAPTR = (uint32_t)&g_ecbdata;
#endif /* HOST_BUILD */
return;
}
block_t aes128_ecb(block_t const * const in) {
#ifdef HOST_BUILD
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, g_ecbdata.key, NULL);
int outlen, tmplen;
EVP_EncryptUpdate(ctx, g_ecbdata.out, &outlen, in->ui8, 16);
EVP_EncryptFinal_ex(ctx, g_ecbdata.out + outlen, &tmplen);
/* Why the fuck does this segfault... I don't care. It's for testing
on the host only. Let it leak */
//EVP_CIPHER_CTX_free(ctx);
#else
memmove(g_ecbdata.in, in, 16);
NRF_ECB->TASKS_STARTECB = 1;
while (!NRF_ECB->EVENTS_ENDECB);
NRF_ECB->EVENTS_ENDECB = 0;
#endif /* HOST_BUILD */
return *((block_t *)g_ecbdata.out);
}

15
aes.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "block.h"
#include <stdint.h>
typedef struct {
uint8_t key[16];
uint8_t in[16];
uint8_t out[16];
} ecbdata_t;
void aes128_init(uint8_t *);
block_t aes128_ecb(block_t const * const);

71
block.c Normal file
View File

@ -0,0 +1,71 @@
/* Utility functions for manipulating block_t structures; 128bit
blocks of data for AES & CMAC */
#include "block.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
bool block_cmp(block_t const * const a, block_t const * const b) {
for (uint_fast8_t i = 0; i < 4; i++) {
if (a->ui32[i] != b->ui32[i]) {
return false;
}
}
return true;
}
void block_print(char const * const label,
block_t const * const b) {
if (label != NULL) {
printf("\n%s: ", label);
} else {
printf("\n");
}
for(int i = 0; i < 16; i++) {
printf("%.2x", b->ui8[i]);
if (!((i+1) % 4)) {
printf(" ");
}
}
printf("\n");
return;
}
block_t block_xor(block_t const * const a, block_t const * const b) {
block_t c;
for (uint_fast8_t i = 0; i < 4; i++) {
c.ui32[i] = a->ui32[i] ^ b->ui32[i];
}
return c;
}
block_t block_shiftr(block_t const * const a, uint_fast8_t const num) {
block_t c;
uint_fast8_t n = (num <= 8 ? num : 8);
for (int_fast8_t i = 15; i >= 0; i--) {
/* Shift right from LSB to MSB */
c.ui8[i] = a->ui8[i] >> n;
if (i != 0) {
/* If theres a more significant uint32, we need to pull in its lsb */
c.ui8[i] |= (a->ui8[i-1] << (8 - n));
}
}
return (num - n == 0 ? c : block_shiftr(&c, num - n));
}
block_t block_shiftl(block_t const * const a, uint_fast8_t const num) {
/* Shifts block b right by num bits (where num <= 32) */
block_t c;
uint_fast8_t n = (num <= 8 ? num : 8);
for (int_fast8_t i = 0; i < 16; i++) {
/* Shift right from LSB to MSB */
c.ui8[i] = a->ui8[i] << n;
if (i != 15) {
/* If theres a less significant uint32, we need to pull in its msb */
c.ui8[i] |= (a->ui8[i+1] >> (8 - n));
}
}
return (num - n == 0 ? c : block_shiftl(&c, num - n));
}

16
block.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef union {
uint32_t ui32[4];
uint8_t ui8[16];
} block_t;
bool block_cmp(block_t const * const, block_t const * const);
void block_print(char const * const, block_t const * const);
block_t block_shiftl(block_t const * const, uint_fast8_t);
block_t block_shiftr(block_t const * const, uint_fast8_t);
block_t block_xor(block_t const * const, block_t const * const);

92
cmac.c Normal file
View File

@ -0,0 +1,92 @@
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "aes.h"
#include "block.h"
#include "cmac.h"
static const block_t zeros = {.ui32={0,0,0,0}};
static block_t g_k[2];
void cmac_aes128_init(block_t *key) {
aes128_init(key->ui8);
cmac_aes128_expand_key(key, g_k);
}
void cmac_aes128_expand_key(block_t *key, block_t *out) {
/* Given AES key k, generate the subkeys needed for CMAC */
block_t *k1 = out,
*k2 = (out+1);
block_t l = {0},
Rb = {.ui8={0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x87}};
l = aes128_ecb(&zeros);
if ((l.ui8[0] >> 7) == 0) {
*k1 = block_shiftl(&l, 1);
} else {
block_t tmp = block_shiftl(&l, 1);
*k1 = block_xor(&tmp, &Rb);
}
if (!(k1->ui8[0] >> 7)) {
*k2 = block_shiftl(k1, 1);
} else {
fflush(stdout);
block_t tmp = block_shiftl(k1, 1);
*k2 = block_xor(&tmp, &Rb);
}
}
void cmac_truncate_tag(uint8_t *dest, block_t *tag, uint_fast8_t tag_len_bits) {
uint_fast8_t num_bytes = tag_len_bits / 8,
last_byte_mask = 0xff << (8 - tag_len_bits % 8);
memcpy(dest, tag->ui8, num_bytes);
dest[num_bytes] = tag->ui8[num_bytes] & last_byte_mask;
}
/* Address of the first uint8_t in a particular message block */
#define BLOCK(x) (&alt_msg[x-1])
block_t cmac_aes128(uint8_t *msg, size_t msg_len) {
/* Simulate ceiling integer division by adding a block if remainder */
block_t *k1 = &g_k[0],
*k2 = &g_k[1];
uint_fast16_t num_blocks = msg_len / 16 + (msg_len % 16 ? 1 : 0);
bool last_block_complete = !(msg_len % 16 ? 1 : 0);
if (msg_len == 0) {
num_blocks = 1;
last_block_complete = false;
}
block_t alt_msg[num_blocks];
memset(&alt_msg, 0, num_blocks*16);
memcpy(&alt_msg, msg, msg_len);
if (!last_block_complete) {
/* Padding is single 1 bit, run out on 0s.. find the next byte,
set it to 0b1000000 */
alt_msg[num_blocks-1].ui8[msg_len % 16] = 0x80;
alt_msg[num_blocks-1] = block_xor(BLOCK(num_blocks), k2);
} else {
alt_msg[num_blocks-1] = block_xor(BLOCK(num_blocks), k1);
}
block_t x = { .ui32={0, 0, 0, 0}},
y = { .ui32={0, 0, 0, 0}};
/* CBC */
for (uint32_t i = 1; i <= num_blocks - 1; i++) {
y = block_xor(&x, BLOCK(i));
x = aes128_ecb(&y);
}
y = block_xor(&x, BLOCK(num_blocks));
block_t tag = aes128_ecb(&y);
return tag;
}

11
cmac.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <stdbool.h>
#include <strings.h>
#include "block.h"
block_t cmac_aes128(uint8_t *, size_t);
void cmac_aes128_expand_key(block_t *, block_t *);
void cmac_aes128_init(block_t *);
void cmac_truncate_tag(uint8_t *, block_t *, uint_fast8_t);

82
main.c Normal file
View File

@ -0,0 +1,82 @@
/* Copyright (c) 2016 Jaycon Systems, LLC. All Rights Reserved */
#include <stdint.h>
#include "nrf.h"
#include "nrf_gpio.h"
#include "cmac.h"
#define ERROR_LED_PIN 12
#define ERROR_LED_ACTIVE LOW
#if (ERROR_LED_ACTIVE == LOW)
#define ERROR_LED_OFF nrf_gpio_pin_set(ERROR_LED_PIN)
#define ERROR_LED_ON nrf_gpio_pin_clear(ERROR_LED_PIN)
#else
#define ERROR_LED_OFF nrf_gpio_pin_clear(ERROR_LED_PIN)
#define ERROR_LED_ON nrf_gpio_pin_set(ERROR_LED_PIN)
#endif /* ERROR_LET_ACTIVE */
void test_cmac(void) {
/* NIST Examples */
block_t k = { .ui8={0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}};
cmac_aes128_init(&k);
/* Test Null Message, NIST Example */
uint8_t msg1[] = "";
block_t case1 = {.ui8={0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46}};
block_t tag = cmac_aes128(msg1, 0);
if (!block_cmp(&tag, &case1)) {
ERROR_LED_ON;
while(1);
}
/* 16b example */
uint8_t msg2[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a};
block_t case2 = {.ui8={0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c}};
tag = cmac_aes128(msg2, sizeof(msg2));
if (!block_cmp(&tag, &case2)) {
ERROR_LED_ON;
while(1);
}
/* 40b example */
uint8_t msg3[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11};
block_t case3 = {.ui8={0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27}};
tag = cmac_aes128(msg3, sizeof(msg3));
if (!block_cmp(&tag, &case3)) {
ERROR_LED_ON;
while(1);
}
/* 64b example */
uint8_t msg4[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10};
block_t case4 = {.ui8={0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe}};
tag = cmac_aes128(msg4, sizeof(msg4));
if (!block_cmp(&tag, &case4)) {
ERROR_LED_ON;
while(1);
}
}
int main(void) {
nrf_gpio_cfg_output(ERROR_LED_PIN);
ERROR_LED_OFF;
for (;;) {
test_cmac();
}
}

174
template/Makefile Normal file
View File

@ -0,0 +1,174 @@
TOOLCHAIN_PREFIX ?= arm-none-eabi
AS = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-as
CC = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-gcc
LD = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-gcc
OBJCOPY = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-objcopy
OBJDUMP = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-objdump
SIZE = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-size
GDB = $(TOOLCHAIN_PATH)$(TOOLCHAIN_PREFIX)-gdb
START_CODE ?= startup_nrf51.s
SYSTEM_FILE ?= system_nrf51.c
ifdef DEV_BOARD
CFLAGS += -DDEV_BOARD
endif
ifeq ($(USE_SOFTDEVICE), s110)
CFLAGS += -DS110
USE_BLE = 1
endif
ifeq ($(USE_SOFTDEVICE), s120)
CFLAGS += -DS120
USE_BLE = 1
endif
ifeq ($(USE_SOFTDEVICE), s310)
USE_BLE = 1
USE_ANT = 1
CFLAGS += -DS310
endif
LIBRARY_PATHS += $(TEMPLATE_PATH)
LIBRARY_PATHS += $(SDK_PATH)components/toolchain/gcc/
LIBRARY_PATHS += $(SDK_PATH)components/toolchain/
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/libraries/*/)
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/ble_flash/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/clock/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/common/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/config/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/delay/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/gpiote/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/hal/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/lpcomp/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/ppi/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/pstorage/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/qdec/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/radio_config/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/rng/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/rtc/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/sdio/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/spi_master/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/spi_slave/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/swi/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/timer/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/twi_master/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/uart/
LIBRARY_PATHS += $(SDK_PATH)/components/drivers_nrf/wdt/
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/device/)
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/serialization/*/)
ifdef USE_BLE
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/ble/*/)
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/ble/ble_services/*/)
CFLAGS += -DBLE_STACK_SUPPORT_REQD
endif
ifdef USE_ANT
CFLAGS += -DANT_STACK_SUPPORT_REQD
endif
ifdef USE_SOFTDEVICE
CFLAGS += -DSOFTDEVICE_PRESENT
LIBRARY_PATHS += $(SDK_PATH)components/softdevice/common/softdevice_handler/
LIBRARY_PATHS += $(SDK_PATH)components/softdevice/$(USE_SOFTDEVICE)/headers/
else
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/drivers_nrf/nrf_soc_nosd/)
USE_SOFTDEVICE = blank
endif
LINKER_SCRIPT ?= gcc_nrf51_$(USE_SOFTDEVICE).ld
OUTPUT_NAME ?= $(addsuffix _$(USE_SOFTDEVICE)_$(VERSION), $(PROJECT_NAME))
ifdef USE_EXT_SENSORS
LIBRARY_PATHS += $(wildcard $(SDK_PATH)components/ext_sensors/*/)
endif
LIBRARY_INCLUDES = $(addprefix -I,$(LIBRARY_PATHS))
VPATH = $(LIBRARY_PATHS)
OUTPUT_PATH = _build/
CPUFLAGS += -mthumb -mcpu=cortex-m0 -mabi=aapcs -mfloat-abi=soft
ifdef BOARD
CFLAGS += -DBOARD=$(BOARD)
endif
CFLAGS += -std=gnu99 -c $(CPUFLAGS) -Wall -D$(DEVICE) $(LIBRARY_INCLUDES) -MD
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin --short-enums
# keep every function in separate section. This will allow linker to dump unused functions
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m0
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys
LDFLAGS += -Wl,-Map=$(OUTPUT_PATH)$(OUTPUT_NAME).Map
HEX = $(OUTPUT_PATH)$(OUTPUT_NAME).hex
ELF = $(OUTPUT_PATH)$(OUTPUT_NAME).elf
BIN = $(OUTPUT_PATH)$(OUTPUT_NAME).bin
SRCS = $(SYSTEM_FILE) $(notdir $(APPLICATION_SRCS))
OBJS = $(addprefix $(OUTPUT_PATH), $(SRCS:.c=.o)) $(addprefix $(OUTPUT_PATH),$(APPLICATION_LIBS))
DEPS = $(addprefix $(OUTPUT_PATH), $(SRCS:.c=.d))
SRCS_AS = $(START_CODE)
OBJS_AS = $(addprefix $(OUTPUT_PATH), $(SRCS_AS:.s=.os))
JLINK_OPTIONS = -device nrf51822 -if swd -speed 1000
all: $(OBJS) $(OBJS_AS) $(HEX)
rebuild: clean all
bootloader: clean
make -C bootloader
combined: bootloader all
srec_cat \
softdevice/softdevice.hex -intel \
bootloader/_build/sdk10_bootloader_s110.hex -intel -exclude 0x3FC00 0x3FC04 \
_build/hiro_s110_$(VERSION).hex -intel \
-generate 0x3FC00 0x3FC04 -const-le 0x01 4 \
-output bulk-program/$(PROJECT_NAME)-combined-$(VERSION).hex -intel
ln bulk-program/$(PROJECT_NAME)-combined-$(VERSION).hex bulk-program/$(PROJECT_NAME)-combined.hex
# combined: rebuild
# srec_cat \
# softdevice/softdevice.hex -intel \
# _build/$(PROJECT_NAME)_$(USE_SOFTDEVICE)_$(VERSION).hex -intel \
# -output bulk-program/combined.hex -intel
# ln -s bulk-program/combined.hex bulk-program/$(PROJECT_NAME)-$(VERSION)-combined.hex
ifeq ($(OS),Windows_NT)
include $(TEMPLATE_PATH)Makefile.windows
else
include $(TEMPLATE_PATH)Makefile.posix
endif
$(HEX): $(OBJS) $(OBJS_AS)
$(LD) $(LDFLAGS) $(OBJS_AS) $(OBJS) -o $(ELF)
$(OBJCOPY) -Oihex $(ELF) $(HEX)
$(OBJCOPY) -Obinary $(ELF) $(BIN)
$(SIZE) $(ELF)
size: $(ELF)
$(SIZE) $(ELF)
$(OUTPUT_PATH)%.o: %.c
$(MAKE_BUILD_FOLDER)
$(CC) $(LDFLAGS) $(CFLAGS) $< -o $@
$(OUTPUT_PATH)%.os: %.s
$(MAKE_BUILD_FOLDER)
$(AS) $< -o $@
-include $(DEPS)
.PHONY: all clean rebuild size

83
template/Makefile.posix Normal file
View File

@ -0,0 +1,83 @@
# Set toolchain path if arm-none-eabi- binaries are not in user path
#TOOLCHAIN_PATH ?=
TERMINAL ?= gnome-terminal -e
FLASH_START_ADDRESS = $(shell $(OBJDUMP) -h $(ELF) -j .text | grep .text | awk '{print $$4}')
ifdef SEGGER_SERIAL
JLINKEXE_OPTION = -SelectEmuBySn $(SEGGER_SERIAL)
JLINKGDBSERVER_OPTION = -select USB=$(SEGGER_SERIAL)
endif
MAKE_BUILD_FOLDER = mkdir -p $(OUTPUT_PATH)
JLINK = -JLinkExe $(JLINK_OPTIONS) $(JLINKEXE_OPTION)
JLINKGDBSERVER = JLinkGDBServer $(JLINK_OPTIONS) $(JLINKGDBSERVER_OPTION)
SOFTDEVICE_OUTPUT = $(OUTPUT_PATH)$(notdir $(SOFTDEVICE))
clean:
rm -rf $(OUTPUT_PATH)
rm -f *.jlink
rm -f JLink.log
rm -f .gdbinit
rm -f bulk-program/*.hex
flash: all flash.jlink
$(JLINK) flash.jlink
flash.jlink:
printf "r\nloadbin $(BIN) $(FLASH_START_ADDRESS)\nr\ng\nexit\n" > flash.jlink
flash-softdevice: erase-all flash-softdevice.jlink
ifndef SOFTDEVICE
$(error "You need to set the SOFTDEVICE command-line parameter to a path (without spaces) to the softdevice hex-file")
endif
$(OBJCOPY) -Iihex -Obinary $(SOFTDEVICE) $(SOFTDEVICE_OUTPUT:.hex=.bin)
$(JLINK) flash-softdevice.jlink
flash-softdevice.jlink:
# Write to NVMC to enable write. Write mainpart, write UICR. Assumes device is erased.
printf "w4 4001e504 1\nloadbin \"$(SOFTDEVICE_OUTPUT:.hex=.bin)\" 0\nr\ng\nexit\n" > flash-softdevice.jlink
recover: recover.jlink erase-all.jlink pin-reset.jlink
$(JLINK) recover.jlink
$(JLINK) erase-all.jlink
$(JLINK) pin-reset.jlink
recover.jlink:
printf "si 0\nt0\nsleep 1\ntck1\nsleep 1\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\nt0\nsleep 2\nt1\nsleep 2\ntck0\nsleep 100\nsi 1\nr\nexit\n" > recover.jlink
pin-reset.jlink:
printf "w4 40000544 1\nr\nexit\n" > pin-reset.jlink
pin-reset: pin-reset.jlink
$(JLINK) pin-reset.jlink
reset: reset.jlink
$(JLINK) reset.jlink
reset.jlink:
printf "r\ng\nexit\n" > reset.jlink
erase-all: erase-all.jlink
$(JLINK) erase-all.jlink
erase-all.jlink:
# Write to NVMC to enable erase, do erase all, wait for completion. reset
printf "w4 4001e504 2\nw4 4001e50c 1\nsleep 100\nr\nexit\n" > erase-all.jlink
startdebug: debug-gdbinit
$(TERMINAL) "$(JLINKGDBSERVER) -port $(GDB_PORT_NUMBER)"
sleep 1
$(TERMINAL) "$(GDB) $(ELF)"
debug-gdbinit:
printf "target remote localhost:$(GDB_PORT_NUMBER)\nbreak main\n" > .gdbinit
.PHONY: flash flash-softdevice erase-all startdebug
test:
gcc -g -std=gnu99 -Wall -Werror -I.. -DHOST_BUILD -lcrypto block.c aes.c cmac.c tests/test_cmac.c -o tests/test_cmac
./tests/test_cmac

51
template/Makefile.windows Normal file
View File

@ -0,0 +1,51 @@
TOOLCHAIN_PATH = "c:\Program Files (x86)\GNU Tools ARM Embedded\4.8 2013q4\bin\"
JLINK_PATH = "C:\Program Files (x86)\SEGGER\JLinkARM_V480\"
MAKE_BUILD_FOLDER = if not exist $(OUTPUT_PATH:/=\\) mkdir $(OUTPUT_PATH:/=\\)
# Make GDB server die after one run.
JLINKGDBSERVER_OPTION = -s
ifdef SEGGER_SERIAL
NRFJPROG_OPTIONS = --snr $(SEGGER_SERIAL)
JLINKGDBSERVER_OPTION += -select USB=$(SEGGER_SERIAL)
endif
NRFJPROG = nrfjprog $(NRFJPROG_OPTIONS)
clean:
if exist .\$(OUTPUT_PATH:/=\\) rmdir /Q /S $(OUTPUT_PATH:/=)
if exist *.jlink del /q *.jlink
if exist JLink.log del /q JLink.log
if exist .gdbinit del /q .gdbinit
$(OUTPUT_PATH):
if not exist .\$(OUTPUT_PATH:/=\\) md $(OUTPUT_PATH)
flash:
$(NRFJPROG) --program $(HEX) -r
flash-softdevice:
ifndef SOFTDEVICE
$(error "You need to set the SOFTDEVICE command-line parameter to a path (without spaces) to the softdevice hex-file")
endif
$(NRFJPROG) -e --programs "$(SOFTDEVICE)"
recover:
$(NRFJPROG) --recover
pin-reset:
$(NRFJPROG) --pinreset
reset:
$(NRFJPROG) --reset
startdebug: debug-gdbinit
start /D $(JLINK_PATH) JLinkGDBServer $(JLINKGDBSERVER_OPTION) $(JLINK_OPTIONS) -port $(GDB_PORT_NUMBER)
timeout /t 1
$(GDB) $(ELF) -x gdbinit
debug-gdbinit:
@(echo target remote localhost:$(GDB_PORT_NUMBER) & echo break main) > gdbinit
.PHONY: clean flash startdebug debug-gdbinit

View File

@ -0,0 +1,7 @@
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x40000 /* 256k */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000 /* 16k */
}
INCLUDE "gcc_nrf51_common.ld"

View File

@ -0,0 +1,140 @@
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE (__preinit_array_start = .);
*(.preinit_array)
PROVIDE (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM
.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy :
{
*(.stack)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

View File

@ -0,0 +1,7 @@
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x0 + 96K, LENGTH = 128K - 96K /* 88 kB is taken by S110, rest for app. */
RAM (rwx) : ORIGIN = 0x20000000 + 8K, LENGTH = 16K - 8K /* 8 kB is taken by S110, 8 kB for app. */
}
INCLUDE "gcc_nrf51_common.ld"

View File

@ -0,0 +1,7 @@
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x18000, LENGTH = 0x27000 /* 96 kB is taken by S120, 160 kB for app. */
RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0x1800 /* 10 kB is taken by S120, 6 kB for app. */
}
INCLUDE "gcc_nrf51_common.ld"

View File

@ -0,0 +1,7 @@
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0xC000, LENGTH = 0x34000 /* 48 kB is taken by S210, 80 kB for app. */
RAM (rwx) : ORIGIN = 0x20000900, LENGTH = 0x3700 /* 2.25 kB is taken by S210, 13.75 kB for app. */
}
INCLUDE "gcc_nrf51_common.ld"

View File

@ -0,0 +1,7 @@
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x20000, LENGTH = 0x20000 /* 128 kB is taken by S310, 128 kB for app. */
RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0x1800 /* 10 kB is taken by S310, 6 kB for app. */
}
INCLUDE "gcc_nrf51_common.ld"

212
template/startup_nrf51.s Normal file
View File

@ -0,0 +1,212 @@
/* File: startup_ARMCM0.S
* Purpose: startup file for Cortex-M0 devices. Should use with
* GCC for ARM Embedded Processors
* Version: V1.2
* Date: 15 Nov 2011
*
* Copyright (c) 2011, ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the ARM Limited nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.syntax unified
.arch armv6-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0xc00
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x100
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.space Heap_Size
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __Vectors
__Vectors:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts */
.long POWER_CLOCK_IRQHandler /* POWER_CLOCK */
.long RADIO_IRQHandler /* RADIO */
.long UART0_IRQHandler /* UART0 */
.long SPI0_TWI0_IRQHandler /* SPI0_TWI0 */
.long SPI1_TWI1_IRQHandler /* SPI1_TWI1 */
.long 0 /* Reserved */
.long GPIOTE_IRQHandler /* GPIOTE */
.long ADC_IRQHandler /* ADC */
.long TIMER0_IRQHandler /* TIMER0 */
.long TIMER1_IRQHandler /* TIMER1 */
.long TIMER2_IRQHandler /* TIMER2 */
.long RTC0_IRQHandler /* RTC0 */
.long TEMP_IRQHandler /* TEMP */
.long RNG_IRQHandler /* RNG */
.long ECB_IRQHandler /* ECB */
.long CCM_AAR_IRQHandler /* CCM_AAR */
.long WDT_IRQHandler /* WDT */
.long RTC1_IRQHandler /* RTC1 */
.long QDEC_IRQHandler /* QDEC */
.long 0 /* Reserved */
.long SWI0_IRQHandler /* SWI0 */
.long SWI1_IRQHandler /* SWI1 */
.long SWI2_IRQHandler /* SWI2 */
.long SWI3_IRQHandler /* SWI3 */
.long SWI4_IRQHandler /* SWI4 */
.long SWI5_IRQHandler /* SWI5 */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.size __Vectors, . - __Vectors
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
.equ NRF_POWER_RAMON_ADDRESS, 0x40000524
.equ NRF_POWER_RAMON_RAM1ON_ONMODE_Msk, 0x3
ldr r0, =NRF_POWER_RAMON_ADDRESS
ldr r2, [r0]
movs r1, #NRF_POWER_RAMON_RAM1ON_ONMODE_Msk
orrs r2, r1
str r2, [r0]
/* Loop to copy data from read only memory to RAM. The ranges
* of copy from/to are specified by following symbols evaluated in
* linker script.
* __etext: End of code section, i.e., begin of data sections to copy from.
* __data_start__/__data_end__: RAM address range that data should be
* copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
subs r3, r2
ble .flash_to_ram_loop_end
movs r4, 0
.flash_to_ram_loop:
ldr r0, [r1,r4]
str r0, [r2,r4]
adds r4, 4
cmp r4, r3
blt .flash_to_ram_loop
.flash_to_ram_loop_end:
ldr r0, =SystemInit
blx r0
ldr r0, =_start
bx r0
.pool
.size Reset_Handler, . - Reset_Handler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_default_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
def_default_handler NMI_Handler
def_default_handler HardFault_Handler
def_default_handler SVC_Handler
def_default_handler PendSV_Handler
def_default_handler SysTick_Handler
def_default_handler Default_Handler
def_default_handler POWER_CLOCK_IRQHandler
def_default_handler RADIO_IRQHandler
def_default_handler UART0_IRQHandler
def_default_handler SPI0_TWI0_IRQHandler
def_default_handler SPI1_TWI1_IRQHandler
def_default_handler GPIOTE_IRQHandler
def_default_handler ADC_IRQHandler
def_default_handler TIMER0_IRQHandler
def_default_handler TIMER1_IRQHandler
def_default_handler TIMER2_IRQHandler
def_default_handler RTC0_IRQHandler
def_default_handler TEMP_IRQHandler
def_default_handler RNG_IRQHandler
def_default_handler ECB_IRQHandler
def_default_handler CCM_AAR_IRQHandler
def_default_handler WDT_IRQHandler
def_default_handler RTC1_IRQHandler
def_default_handler QDEC_IRQHandler
def_default_handler SWI0_IRQHandler
def_default_handler SWI1_IRQHandler
def_default_handler SWI2_IRQHandler
def_default_handler SWI3_IRQHandler
def_default_handler SWI4_IRQHandler
def_default_handler SWI5_IRQHandler
.weak DEF_IRQHandler
.set DEF_IRQHandler, Default_Handler
.end