diff options
| author | Keith Packard <keithp@keithp.com> | 2011-07-15 18:51:33 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2011-08-27 12:33:46 -0700 | 
| commit | a731d240f802d37524ce84c3c6acf22bcda4d522 (patch) | |
| tree | 54a7e25a354c43ceb32c1feb651acf18432dcd5c /src | |
| parent | f145be3fc4ee94fdb5c1e2406b6c11d38bdbbd9b (diff) | |
altos: Start work on AES and raw radio interfaces.
We probably don't want this raw radio interface, but it's a start.
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ao_aes.c | 122 | ||||
| -rw-r--r-- | src/ao_radio_cmac.c | 100 | ||||
| -rw-r--r-- | src/cc1111/ao_pins.h | 4 | ||||
| -rw-r--r-- | src/cc1111/cc1111.h | 24 | ||||
| -rw-r--r-- | src/core/ao.h | 26 | 
5 files changed, 275 insertions, 1 deletions
| diff --git a/src/ao_aes.c b/src/ao_aes.c new file mode 100644 index 00000000..649eda06 --- /dev/null +++ b/src/ao_aes.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t	ao_aes_done; +__xdata uint8_t	ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ +	S0CON = 0; +	if (ENCCCS & ENCCCS_RDY) { +		ao_aes_done = 1; +		ao_wakeup(&ao_aes_done); +	} +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ +	ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ +	ao_dma_set_transfer(ao_aes_dma_in, +			    in, +			    &ENCDIXADDR, +			    7, +			    DMA_CFG0_WORDSIZE_8 | +			    DMA_CFG0_TMODE_SINGLE | +			    DMA_CFG0_TRIGGER_ENC_DW, +			    DMA_CFG1_SRCINC_1 | +			    DMA_CFG1_DESTINC_0 | +			    DMA_CFG1_PRIORITY_LOW); +	ao_aes_done = 0; +	ENCCCS = ENCCCS_MODE_CBC_MAC | +		ENCCCS_CMD_LOAD_KEY | +		ENCCCS_START; +	while (!ao_aes_done) +		ao_sleep(&ao_aes_done); +} + +void +ao_aes_run(__xdata uint8_t *in, +	   __xdata uint8_t *out) +{ +	uint8_t	b; +	if (in) { +		ao_dma_set_transfer(ao_aes_dma_in, +				    in, +				    &ENCDIXADDR, +				    7, +				    DMA_CFG0_WORDSIZE_8 | +				    DMA_CFG0_TMODE_SINGLE | +				    DMA_CFG0_TRIGGER_ENC_DW, +				    DMA_CFG1_SRCINC_1 | +				    DMA_CFG1_DESTINC_0 | +				    DMA_CFG1_PRIORITY_LOW); +	} +	if (out) { +		ao_dma_set_transfer(ao_aes_dma_out, +				    &ENCDOXADDR, +				    out, +				    7, +				    DMA_CFG0_WORDSIZE_8 | +				    DMA_CFG0_TMODE_SINGLE | +				    DMA_CFG0_TRIGGER_ENC_UP, +				    DMA_CFG1_SRCINC_0 | +				    DMA_CFG1_DESTINC_1 | +				    DMA_CFG1_PRIORITY_LOW); +	} +	switch (ao_aes_current_mode) { +	case ao_aes_mode_cbc_mac: +		if (out) +			b = (ENCCCS_MODE_CBC | +			     ENCCCS_CMD_ENCRYPT | +			     ENCCCS_START); +		else +			b = (ENCCCS_MODE_CBC_MAC | +			     ENCCCS_CMD_ENCRYPT | +			     ENCCCS_START); +		break; +	default: +		return; +	} +	ao_aes_done = 0; +	ENCCCS = b; +	if (out) +		while (!ao_aes_dma_out_done) +			ao_sleep(&ao_aes_dma_out_done); +	else +		while (!ao_aes_done) +			ao_sleep(&ao_aes_done); +} + +void +ao_aes_init(void) +{ +	ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); +	ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); +	ENCIE = 1; +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c new file mode 100644 index 00000000..4b118d02 --- /dev/null +++ b/src/ao_radio_cmac.c @@ -0,0 +1,100 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define AO_CMAC_KEY_LEN		16 +#define AO_CMAC_MAX_LEN		(128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; + +static uint8_t +getnibble(void) +{ +	__pdata char	c; + +	c = getchar(); +	if ('0' <= c && c <= '9') +		return c - '0'; +	if ('a' <= c && c <= 'f') +		return c - ('a' - 10); +	if ('A' <= c && c <= 'F') +		return c - ('A' - 10); +	ao_cmd_status = ao_cmd_lex_error; +	return 0; +} + +static void +ao_radio_cmac_key(void) __reentrant +{ +	uint8_t	i; + +	for (i = 0; i < AO_CMAC_KEY_LEN; i++) { +		ao_cmd_hex(); +		if (ao_cmd_status != ao_cmd_success) +			return; +		cmac_key[i] = ao_cmd_lex_i; +	} +} + +static void +ao_radio_cmac_send(void) __reentrant +{ +	uint8_t	i, b; + +	ao_cmd_hex(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { +		ao_cmd_status = ao_cmd_syntax_error; +		return; +	} +	for (i = 0; i < ao_cmd_lex_i; i++) { +		b = getnibble() << 4; +		b |= getnibble(); +		if (ao_cmd_status != ao_cmd_success) +			return; +		cmac_data[i] = b; +	} +	ao_mutex_get(&ao_aes_mutex); +	ao_aes_set_mode(ao_aes_mode_cbc_mac); +	ao_aes_set_key(cmac_key); +	for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { +		if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) +			ao_aes_run(&cmac_data[i], NULL); +		else +			ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); +	} +	ao_mutex_put(&ao_aes_mutex); +	ao_set_monitor(0); +	ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +} + +__code struct ao_cmds ao_radio_cmac_cmds[] = { +	{ ao_radio_cmac_key,	"k <byte> ...\0Set AES-CMAC key." }, +	{ ao_radio_cmac_send,	"s <length>\0Send AES-CMAC packet. Bytes to send follow on next line" }, +	{ ao_radio_cmac_recv,	"S <length> <timeout>\0Receive AES-CMAC packet. Timeout in ms" }, +	{ 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ +	ao_cmd_register(&ao_radio_cmac_cmds[0]); +	 +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 19ea0cfd..9e9b3bf6 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -108,6 +108,7 @@  	#define SPI_CS_ON_P0		0  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_AES			1  #endif  #if defined(TELEMINI_V_1_0) @@ -212,6 +213,7 @@  	#define SPI_CS_ON_P0		1  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_AES			1  #endif  #if defined(TIDONGLE) @@ -235,6 +237,7 @@  	#define SPI_CS_ON_P0		1  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_AES			1  #endif  #if defined(TELEBT_V_0_0) @@ -300,6 +303,7 @@  	#define BT_LINK_PIN_INDEX	7  	#define BT_LINK_PIN		P1_7  	#define HAS_MONITOR		1 +	#define HAS_AES			1  #endif  #if defined(TELELAUNCH_V_0_1) diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index e52aa79f..11ea8bbb 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -768,7 +768,7 @@ struct cc_dma_channel {  # define DMA_CFG0_TRIGGER_ADC_CH7	28  # define DMA_CFG0_TRIGGER_I2STX		28  # define DMA_CFG0_TRIGGER_ENC_DW	29 -# define DMA_CFG0_TRIGGER_DNC_UP	30 +# define DMA_CFG0_TRIGGER_ENC_UP	30  # define DMA_CFG1_SRCINC_MASK		(3 << 6)  # define DMA_CFG1_SRCINC_0		(0 << 6) @@ -1303,4 +1303,26 @@ __xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;  __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;  #define RF_VCO_VC_DAC_OFF	0x3d +/* AES engine */ + +__sfr at 0xB1 ENCDI; +__sfr at 0xB2 ENCDO; +__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; + +__sfr at 0xB3 ENCCCS; + +#define ENCCCS_MODE_CBC		(0 << 4) +#define ENCCCS_MODE_CFB		(1 << 4) +#define ENCCCS_MODE_OFB		(2 << 4) +#define ENCCCS_MODE_CTR		(3 << 4) +#define ENCCCS_MODE_ECB		(4 << 4) +#define ENCCCS_MODE_CBC_MAC	(5 << 4) +#define ENCCCS_RDY		(1 << 3) +#define ENCCCS_CMD_ENCRYPT	(0 << 1) +#define ENCCCS_CMD_DECRYPT	(1 << 1) +#define ENCCCS_CMD_LOAD_KEY	(2 << 1) +#define ENCCCS_CMD_LOAD_IV	(3 << 1) +#define ENCCCS_START		(1 << 0) +  #endif diff --git a/src/core/ao.h b/src/core/ao.h index 0cff0436..0275cad1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1629,4 +1629,30 @@ ao_companion_init(void);  void  ao_lcd_init(void); +/* ao_aes.c */ + +__xdata uint8_t ao_aes_mutex; + +enum ao_aes_mode { +	ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_run(__xdata uint8_t *in, +	   __xdata uint8_t *out); + +void +ao_aes_init(void); +  #endif /* _AO_H_ */ | 
