@ -31,6 +31,10 @@
# include "fw_env.h"
# include <aes.h>
# define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
# define WHITESPACE(c) ((c == '\t') || (c == ' '))
# define min(x, y) ({ \
@ -98,6 +102,11 @@ static struct environment environment = {
. flag_scheme = FLAG_NONE ,
} ;
/* Is AES encryption used? */
static int aes_flag ;
static uint8_t aes_key [ AES_KEY_LENGTH ] = { 0 } ;
static int env_aes_cbc_crypt ( char * data , const int enc ) ;
static int HaveRedundEnv = 0 ;
static unsigned char active_flag = 1 ;
@ -120,6 +129,10 @@ static inline ulong getenvsize (void)
if ( HaveRedundEnv )
rc - = sizeof ( char ) ;
if ( aes_flag )
rc & = ~ ( AES_KEY_LENGTH - 1 ) ;
return rc ;
}
@ -191,6 +204,36 @@ char *fw_getdefenv(char *name)
return NULL ;
}
static int parse_aes_key ( char * key )
{
char tmp [ 5 ] = { ' 0 ' , ' x ' , 0 , 0 , 0 } ;
unsigned long ul ;
int i ;
if ( strnlen ( key , 64 ) ! = 32 ) {
fprintf ( stderr ,
" ## Error: '-a' option requires 16-byte AES key \n " ) ;
return - 1 ;
}
for ( i = 0 ; i < 16 ; i + + ) {
tmp [ 2 ] = key [ 0 ] ;
tmp [ 3 ] = key [ 1 ] ;
errno = 0 ;
ul = strtoul ( tmp , NULL , 16 ) ;
if ( errno ) {
fprintf ( stderr ,
" ## Error: '-a' option requires valid AES key \n " ) ;
return - 1 ;
}
aes_key [ i ] = ul & 0xff ;
key + = 2 ;
}
aes_flag = 1 ;
return 0 ;
}
/*
* Print the current definition of one , or more , or all
* environment variables
@ -201,6 +244,19 @@ int fw_printenv (int argc, char *argv[])
int i , n_flag ;
int rc = 0 ;
if ( argc > = 2 & & strcmp ( argv [ 1 ] , " -a " ) = = 0 ) {
if ( argc < 3 ) {
fprintf ( stderr ,
" ## Error: '-a' option requires AES key \n " ) ;
return - 1 ;
}
rc = parse_aes_key ( argv [ 2 ] ) ;
if ( rc )
return rc ;
argv + = 2 ;
argc - = 2 ;
}
if ( fw_env_open ( ) )
return - 1 ;
@ -266,6 +322,16 @@ int fw_printenv (int argc, char *argv[])
int fw_env_close ( void )
{
int ret ;
if ( aes_flag ) {
ret = env_aes_cbc_crypt ( environment . data , 1 ) ;
if ( ret ) {
fprintf ( stderr ,
" Error: can't encrypt env for flash \n " ) ;
return ret ;
}
}
/*
* Update CRC
*/
@ -413,7 +479,7 @@ int fw_env_write(char *name, char *value)
*/
int fw_setenv ( int argc , char * argv [ ] )
{
int i ;
int i , rc ;
size_t len ;
char * name ;
char * value = NULL ;
@ -423,6 +489,24 @@ int fw_setenv(int argc, char *argv[])
return - 1 ;
}
if ( strcmp ( argv [ 1 ] , " -a " ) = = 0 ) {
if ( argc < 3 ) {
fprintf ( stderr ,
" ## Error: '-a' option requires AES key \n " ) ;
return - 1 ;
}
rc = parse_aes_key ( argv [ 2 ] ) ;
if ( rc )
return rc ;
argv + = 2 ;
argc - = 2 ;
}
if ( argc < 2 ) {
errno = EINVAL ;
return - 1 ;
}
if ( fw_env_open ( ) ) {
fprintf ( stderr , " Error: environment not initialized \n " ) ;
return - 1 ;
@ -900,6 +984,28 @@ static int flash_flag_obsolete (int dev, int fd, off_t offset)
return rc ;
}
/* Encrypt or decrypt the environment before writing or reading it. */
static int env_aes_cbc_crypt ( char * payload , const int enc )
{
uint8_t * data = ( uint8_t * ) payload ;
const int len = getenvsize ( ) ;
uint8_t key_exp [ AES_EXPAND_KEY_LENGTH ] ;
uint32_t aes_blocks ;
/* First we expand the key. */
aes_expand_key ( aes_key , key_exp ) ;
/* Calculate the number of AES blocks to encrypt. */
aes_blocks = DIV_ROUND_UP ( len , AES_KEY_LENGTH ) ;
if ( enc )
aes_cbc_encrypt_blocks ( key_exp , data , data , aes_blocks ) ;
else
aes_cbc_decrypt_blocks ( key_exp , data , data , aes_blocks ) ;
return 0 ;
}
static int flash_write ( int fd_current , int fd_target , int dev_target )
{
int rc ;
@ -923,6 +1029,7 @@ static int flash_write (int fd_current, int fd_target, int dev_target)
fprintf ( stderr , " Writing new environment at 0x%lx on %s \n " ,
DEVOFFSET ( dev_target ) , DEVNAME ( dev_target ) ) ;
# endif
rc = flash_write_buf ( dev_target , fd_target , environment . image ,
CUR_ENVSIZE , DEVOFFSET ( dev_target ) ,
DEVTYPE ( dev_target ) ) ;
@ -981,8 +1088,10 @@ static int flash_read (int fd)
rc = flash_read_buf ( dev_current , fd , environment . image , CUR_ENVSIZE ,
DEVOFFSET ( dev_current ) , mtdinfo . type ) ;
if ( rc ! = CUR_ENVSIZE )
return - 1 ;
return ( rc ! = CUR_ENVSIZE ) ? - 1 : 0 ;
return 0 ;
}
static int flash_io ( int mode )
@ -1075,6 +1184,8 @@ int fw_env_open(void)
unsigned char flag1 ;
void * addr1 ;
int ret ;
struct env_image_single * single ;
struct env_image_redundant * redundant ;
@ -1109,6 +1220,13 @@ int fw_env_open(void)
return - 1 ;
crc0 = crc32 ( 0 , ( uint8_t * ) environment . data , ENV_SIZE ) ;
if ( aes_flag ) {
ret = env_aes_cbc_crypt ( environment . data , 0 ) ;
if ( ret )
return ret ;
}
crc0_ok = ( crc0 = = * environment . crc ) ;
if ( ! HaveRedundEnv ) {
if ( ! crc0_ok ) {
@ -1159,6 +1277,13 @@ int fw_env_open(void)
}
crc1 = crc32 ( 0 , ( uint8_t * ) redundant - > data , ENV_SIZE ) ;
if ( aes_flag ) {
ret = env_aes_cbc_crypt ( redundant - > data , 0 ) ;
if ( ret )
return ret ;
}
crc1_ok = ( crc1 = = redundant - > crc ) ;
flag1 = redundant - > flags ;