kopia lustrzana https://github.com/conorpp/u2f-zero
identify key handle by 8 byte hmac addition
rodzic
c3bb8ce57e
commit
aafd0539be
|
@ -38,7 +38,9 @@
|
|||
#define U2F_APDU_SIZE 7
|
||||
#define U2F_CHALLENGE_SIZE 32
|
||||
#define U2F_APPLICATION_SIZE 32
|
||||
#define U2F_KEY_HANDLE_SIZE 36
|
||||
#define U2F_KEY_HANDLE_ID_SIZE 8
|
||||
#define U2F_KEY_HANDLE_KEY_SIZE 36
|
||||
#define U2F_KEY_HANDLE_SIZE (U2F_KEY_HANDLE_KEY_SIZE+U2F_KEY_HANDLE_ID_SIZE)
|
||||
#define U2F_REGISTER_REQUEST_SIZE (U2F_CHALLENGE_SIZE+U2F_APPLICATION_SIZE)
|
||||
#define U2F_MAX_REQUEST_PAYLOAD (1 + U2F_CHALLENGE_SIZE+U2F_APPLICATION_SIZE + 1 + U2F_KEY_HANDLE_SIZE)
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ int8_t atecc_recv(uint8_t * buf, uint8_t buflen, struct atecc_response* res)
|
|||
if (SMB_FLAGS & SMB_READ_TRUNC)
|
||||
{
|
||||
set_app_error(ERROR_READ_TRUNCATED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pkt_len <= buflen && pkt_len >= 4)
|
||||
|
|
|
@ -141,8 +141,6 @@ int16_t main(void) {
|
|||
uint16_t ms_grad;
|
||||
uint8_t winks = 0, light = 1, grad_dir = 0;
|
||||
int8_t grad_inc = 0;
|
||||
int8_t ii;
|
||||
uint16_t i;
|
||||
data uint8_t xdata * clear = 0;
|
||||
|
||||
enter_DefaultMode_from_RESET();
|
||||
|
@ -162,7 +160,7 @@ int16_t main(void) {
|
|||
|
||||
if (RSTSRC & RSTSRC_WDTRSF__SET)
|
||||
{
|
||||
error = ERROR_DAMN_WATCHDOG;
|
||||
//error = ERROR_DAMN_WATCHDOG;
|
||||
}
|
||||
|
||||
run_tests();
|
||||
|
@ -259,9 +257,9 @@ int16_t main(void) {
|
|||
{
|
||||
u2f_printx("error: ", 1, (uint16_t)error);
|
||||
#ifdef U2F_BLINK_ERRORS
|
||||
for (ii=0; ii < 8; ii++)
|
||||
for (ms_grad=0; ms_grad < 8; ms_grad++)
|
||||
{
|
||||
if (error & (1<<ii))
|
||||
if (error & (1<<ms_grad))
|
||||
{
|
||||
rgb_hex(U2F_DEFAULT_COLOR_INPUT_SUCCESS);
|
||||
}
|
||||
|
@ -277,17 +275,16 @@ int16_t main(void) {
|
|||
#else
|
||||
rgb_hex(U2F_DEFAULT_COLOR_ERROR);
|
||||
// wipe ram
|
||||
for (i=0; i<0x400;i++)
|
||||
for (ms_grad=0; ms_grad<0x400;ms_grad++)
|
||||
{
|
||||
*(clear++) = 0x0;
|
||||
watchdog();
|
||||
}
|
||||
#endif
|
||||
error = 0;
|
||||
while(!ms_since(ms_heart,500))
|
||||
{
|
||||
watchdog();
|
||||
}
|
||||
|
||||
// wait for watchdog to reset
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||
if (control == U2F_AUTHENTICATE_CHECK)
|
||||
{
|
||||
u2f_hid_set_len(2);
|
||||
if (u2f_load_key(req->kh) == 0 )//&& u2f_appid_eq(req->kh, req->app) == 0)
|
||||
if (u2f_appid_eq(req->kh, req->app) == 0)
|
||||
{
|
||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
|
@ -155,12 +155,13 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||
return U2F_SW_WRONG_DATA;
|
||||
}
|
||||
}
|
||||
if (
|
||||
if (
|
||||
control != U2F_AUTHENTICATE_SIGN ||
|
||||
req->khl != U2F_KEY_HANDLE_SIZE ||
|
||||
u2f_load_key(req->kh, req->app) != 0 //||
|
||||
//u2f_appid_eq(req->kh, req->app) != 0
|
||||
)
|
||||
u2f_appid_eq(req->kh, req->app) != 0 || // Order of checks is important
|
||||
u2f_load_key(req->kh, req->app) != 0
|
||||
|
||||
)
|
||||
{
|
||||
u2f_hid_set_len(2);
|
||||
return U2F_SW_WRONG_PAYLOAD;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
*/
|
||||
|
||||
#include "app.h"
|
||||
|
||||
#undef U2F_DISABLE
|
||||
#ifndef U2F_DISABLE
|
||||
#include "bsp.h"
|
||||
#include "u2f.h"
|
||||
|
@ -38,6 +40,7 @@
|
|||
#include "atecc508a.h"
|
||||
|
||||
|
||||
static void gen_u2f_zero_tag(uint8_t * dst, uint8_t * appid);
|
||||
|
||||
static struct u2f_hid_msg res;
|
||||
static uint8_t* resbuf = (uint8_t*)&res;
|
||||
|
@ -152,14 +155,14 @@ static int atecc_prep_encryption()
|
|||
appdata.tmp, 32,
|
||||
appdata.tmp, 40, &res) != 0 )
|
||||
{
|
||||
u2f_prints("pass through to tempkey failed\r\n");
|
||||
// u2f_prints("pass through to tempkey failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
if( atecc_send_recv(ATECC_CMD_GENDIG,
|
||||
ATECC_RW_DATA, U2F_MASTER_KEY_SLOT, NULL, 0,
|
||||
appdata.tmp, 40, &res) != 0)
|
||||
{
|
||||
u2f_prints("GENDIG failed\r\n");
|
||||
// u2f_prints("GENDIG failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -233,7 +236,6 @@ int8_t u2f_ecdsa_sign(uint8_t * dest, uint8_t * handle, uint8_t * appid)
|
|||
}
|
||||
|
||||
|
||||
|
||||
// bad if this gets interrupted
|
||||
int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey)
|
||||
{
|
||||
|
@ -242,6 +244,8 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey)
|
|||
int i;
|
||||
|
||||
watchdog();
|
||||
// u2f_prints("new key appid,khandle\r\n");
|
||||
// dump_hex(appid,32);
|
||||
|
||||
if (atecc_send_recv(ATECC_CMD_RNG,ATECC_RNG_P1,ATECC_RNG_P2,
|
||||
NULL, 0,
|
||||
|
@ -270,7 +274,7 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey)
|
|||
}
|
||||
watchdog();
|
||||
compute_key_hash(private_key, WMASK);
|
||||
memmove(handle+4, res_digest.buf, 32); // size of key handle must be 36
|
||||
memmove(handle+4, res_digest.buf, 32); // size of key handle must be 36+8
|
||||
|
||||
|
||||
if ( atecc_privwrite(U2F_TEMP_KEY_SLOT, private_key, WMASK, handle+4) != 0)
|
||||
|
@ -289,15 +293,21 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey)
|
|||
|
||||
memmove(pubkey, res.buf, 64);
|
||||
|
||||
// the + 8
|
||||
gen_u2f_zero_tag(handle + U2F_KEY_HANDLE_KEY_SIZE, appid);
|
||||
//dump_hex(handle,U2F_KEY_HANDLE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t u2f_load_key(uint8_t * handle, uint8_t * appid)
|
||||
{
|
||||
struct atecc_response res;
|
||||
uint8_t private_key[36];
|
||||
int i;
|
||||
|
||||
// u2f_prints("load key appid,rnum\r\n");
|
||||
// dump_hex(appid,32);
|
||||
// dump_hex(handle,4);
|
||||
SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT;
|
||||
SHA_FLAGS = ATECC_SHA_HMACSTART;
|
||||
u2f_sha256_start();
|
||||
|
@ -316,30 +326,24 @@ int8_t u2f_load_key(uint8_t * handle, uint8_t * appid)
|
|||
return atecc_privwrite(U2F_TEMP_KEY_SLOT, private_key, WMASK, handle+4);
|
||||
}
|
||||
|
||||
static void gen_u2f_zero_tag(uint8_t * dst, uint8_t * appid)
|
||||
{
|
||||
const char * u2f_zero_const = "\xc1\xff\x67\x0d\x66\xe5\x55\xbb\xdc\x56\xaf\x7b\x41\x27\x4a\x21";
|
||||
SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT;
|
||||
SHA_FLAGS = ATECC_SHA_HMACSTART;
|
||||
u2f_sha256_start();
|
||||
u2f_sha256_update(appid,32);
|
||||
u2f_sha256_update(u2f_zero_const,16);
|
||||
SHA_FLAGS = ATECC_SHA_HMACEND;
|
||||
u2f_sha256_finish();
|
||||
|
||||
if (dst) memmove(dst, res_digest.buf, U2F_KEY_HANDLE_ID_SIZE);
|
||||
}
|
||||
|
||||
int8_t u2f_appid_eq(uint8_t * handle, uint8_t * appid)
|
||||
{
|
||||
// struct atecc_response res;
|
||||
// uint8_t private_key[36];
|
||||
// int i;
|
||||
//
|
||||
// SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT;
|
||||
// SHA_FLAGS = ATECC_SHA_HMACSTART;
|
||||
// u2f_sha256_start();
|
||||
// u2f_sha256_update(appid,32);
|
||||
// SHA_FLAGS = ATECC_SHA_HMACEND;
|
||||
// u2f_sha256_finish();
|
||||
//
|
||||
// memset(private_key,0,4);
|
||||
// memmove(private_key+4, res_digest.buf, 32);
|
||||
//
|
||||
// for (i=4; i<36; i++)
|
||||
// {
|
||||
// private_key[i] ^= RMASK[i];
|
||||
// }
|
||||
//
|
||||
// compute_key_hash(private_key, WMASK);
|
||||
// return memcmp(handle, res_digest.buf, U2F_KEY_HANDLE_SIZE);
|
||||
return 0;
|
||||
gen_u2f_zero_tag(NULL,appid);
|
||||
return memcmp(handle+U2F_KEY_HANDLE_KEY_SIZE, res_digest.buf, U2F_KEY_HANDLE_ID_SIZE);
|
||||
}
|
||||
|
||||
uint32_t u2f_count()
|
||||
|
|
|
@ -77,7 +77,7 @@ static struct hid_layer_param
|
|||
// total length of response in bytes
|
||||
uint16_t res_len;
|
||||
|
||||
#define BUFFER_SIZE 270
|
||||
#define BUFFER_SIZE (270 - 70)
|
||||
uint8_t buffer[BUFFER_SIZE];
|
||||
|
||||
} hid_layer;
|
||||
|
@ -87,7 +87,7 @@ uint32_t _hid_lockt = 0;
|
|||
uint32_t _hid_lock_cid = 0;
|
||||
#endif
|
||||
|
||||
static struct CID CIDS[5];
|
||||
static struct CID CIDS[4];
|
||||
|
||||
static uint8_t CID_NUM = 0;
|
||||
|
||||
|
@ -149,7 +149,6 @@ void u2f_hid_writeback(uint8_t * payload, uint16_t len)
|
|||
|
||||
do
|
||||
{
|
||||
|
||||
if (_hid_offset == 0)
|
||||
{
|
||||
r->cid = hid_layer.current_cid;
|
||||
|
@ -354,24 +353,19 @@ static uint8_t hid_u2f_parse(struct u2f_hid_msg* req)
|
|||
|
||||
break;
|
||||
case U2FHID_MSG:
|
||||
|
||||
if (U2FHID_LEN(req) < 4)
|
||||
{
|
||||
stamp_error(hid_layer.current_cid, ERR_INVALID_LEN);
|
||||
goto fail;
|
||||
}
|
||||
// buffer 2 payloads (120 bytes) to get full U2F message
|
||||
// assuming key handle is < 45 bytes
|
||||
// 7 bytes for apdu header
|
||||
// 7 + 66 bytes + key handle for authenticate message
|
||||
// 7 + 64 for register message
|
||||
if (hid_layer.bytes_buffered == 0)
|
||||
{
|
||||
if (U2FHID_LEN(req) < 4)
|
||||
{
|
||||
stamp_error(hid_layer.current_cid, ERR_INVALID_LEN);
|
||||
goto fail;
|
||||
}
|
||||
start_buffering(req);
|
||||
if (hid_layer.bytes_buffered >= U2FHID_LEN(req))
|
||||
{
|
||||
u2f_request((struct u2f_request_apdu *)hid_layer.buffer);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -380,6 +374,7 @@ static uint8_t hid_u2f_parse(struct u2f_hid_msg* req)
|
|||
{
|
||||
u2f_request((struct u2f_request_apdu *)hid_layer.buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
# silabs utility debugger debugger id C2
|
||||
FlashUtilCL.exe FLASHEraseUSB "$1" 1
|
|
@ -1,4 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
# silabs utility debugger file debugger id power C2
|
||||
FlashUtilCL.exe DownloadUSB -R $1 "$2" 0 1
|
||||
|
||||
ret=$(curl --request POST http://127.0.0.1:4040/ --data "port=$2" --data "firmware=$(cat "$1")")
|
||||
|
||||
if [[ $ret != *"Success"* ]]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
#export FW=$2
|
||||
|
||||
#PORT=$1 python - <<END
|
||||
|
||||
#import requests, sys, os
|
||||
|
||||
|
||||
#url = 'http://127.0.0.1:4040/'
|
||||
|
||||
#payload = {'port': os.environ['PORT'], 'firmware': open(os.environ['FW'], 'r').read()}
|
||||
|
||||
#print requests.post(url, data = payload)
|
||||
|
||||
#END
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
export PATH=$PATH:`pwd`/flashing:../../../u2f_zero_client:../../../gencert
|
||||
|
||||
export attest_priv=gencert/ca/key.pem
|
||||
export attest_pub=gencert/ca/cert.der
|
||||
export attest_pub=gencert/ca/attest.der
|
||||
adapters[0]=0
|
||||
num_adapters=0
|
||||
adapters[1]=COM3
|
||||
adapters[2]=COM4
|
||||
num_adapters=2
|
||||
firmware=../firmware
|
||||
export setup=setup_device.sh
|
||||
export starting_SN=CAFEBABE00000000
|
||||
export starting_SN=DAFE1E340AB70000
|
||||
setup_SNs=(0 CAFEBABEFFFFFFF0 CAFEBABEFFFFFFF1 CAFEBABEFFFFFFF2)
|
||||
|
||||
if [[ -n "$1" ]] ; then
|
||||
|
@ -57,17 +59,17 @@ function start_programming {
|
|||
}
|
||||
|
||||
|
||||
for i in `seq 1 100` ; do
|
||||
#for i in `seq 1 100` ; do
|
||||
|
||||
adapters[$i]=$(FlashUtilCL.exe DeviceSN $i)
|
||||
#adapters[$i]=$(FlashUtilCL.exe DeviceSN $i)
|
||||
|
||||
if [[ ${adapters[$i]} = *"out of range"* ]]
|
||||
then
|
||||
break
|
||||
fi
|
||||
#if [[ ${adapters[$i]} = *"out of range"* ]]
|
||||
#then
|
||||
#break
|
||||
#fi
|
||||
|
||||
num_adapters=$(($num_adapters + 1))
|
||||
done
|
||||
#num_adapters=$(($num_adapters + 1))
|
||||
#done
|
||||
|
||||
export num_adapters=$num_adapters
|
||||
export adapters=$adapters
|
||||
|
|
|
@ -32,19 +32,17 @@ if [[ $FLASH_TOOLS = 1 ]]
|
|||
then
|
||||
|
||||
# setup atecc
|
||||
echo "erasing..."
|
||||
erase.sh $SN
|
||||
|
||||
while [[ "$?" -ne "0" ]] ; do
|
||||
echo "$SN is retrying erase ... "
|
||||
sleep 0.2
|
||||
erase.sh $SN
|
||||
done
|
||||
#echo "erasing..."
|
||||
#erase.sh $SN
|
||||
|
||||
echo "programming setup..."
|
||||
program.sh $SETUP_HEX $SN
|
||||
|
||||
[[ "$?" -ne "0" ]] && exit 1
|
||||
|
||||
while [[ "$?" -ne "0" ]] ; do
|
||||
echo "$SN is retrying program... "
|
||||
sleep 0.2
|
||||
program.sh $SETUP_HEX $SN
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ import logging as log
|
|||
import json
|
||||
import traceback
|
||||
import argparse
|
||||
import binascii
|
||||
|
||||
from u2flib_server.utils import websafe_encode, websafe_decode
|
||||
|
||||
|
||||
def get_origin(environ):
|
||||
|
@ -126,6 +129,10 @@ class U2FServer(object):
|
|||
user = self.users[username]
|
||||
enroll = user.pop('_u2f_enroll_')
|
||||
device, cert = complete_registration(enroll, data, [self.facet])
|
||||
print
|
||||
print 'device, ' , device
|
||||
print 'key handle', binascii.hexlify(websafe_decode(device['keyHandle']))
|
||||
print
|
||||
user.setdefault('_u2f_devices_', []).append(device.json)
|
||||
|
||||
log.info("U2F device enrolled. Username: %s", username)
|
||||
|
|
Ładowanie…
Reference in New Issue