diff --git a/.gitignore b/.gitignore index 6ab29f5..c66b444 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,7 @@ pubkey.c.txt *.__i *.__ia release/ +workers/ *~ *.DS_Store diff --git a/firmware/src/cert.c b/firmware/src/cert.c new file mode 100644 index 0000000..abab4a0 --- /dev/null +++ b/firmware/src/cert.c @@ -0,0 +1,24 @@ +// generated +#include + +code uint8_t __attest[] = +"\x30\x82\x01\x5a\x30\x82\x01\x00\x02\x01\x01\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d" +"\x04\x03\x02\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14" +"\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43" +"\x31\x14\x30\x12\x06\x03\x55\x04\x03\x0c\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63" +"\x6f\x6d\x30\x1e\x17\x0d\x31\x36\x30\x37\x32\x34\x30\x35\x33\x34\x35\x30\x5a\x17" +"\x0d\x32\x32\x30\x37\x32\x33\x30\x35\x33\x34\x35\x30\x5a\x30\x39\x31\x0b\x30\x09" +"\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b" +"\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03" +"\x0c\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07\x2a" +"\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04" +"\x80\xfe\xb0\x59\x0d\xad\x1a\x96\x5d\xd6\x66\xdd\x77\x67\x90\xb5\xfa\x70\xb3\x1d" +"\x51\xb3\x0f\xf5\x5d\xbe\x08\x60\x73\x76\x38\x02\x21\xf6\x19\x8f\x37\x91\x80\x4a" +"\xa9\xd5\x39\x12\x97\x20\x86\x34\x52\x3c\xb0\x76\x95\x2b\x02\xcb\x9f\x10\xd7\xa5" +"\x77\xbc\xe9\xf9\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00\x30" +"\x45\x02\x20\x5a\x06\x89\xd5\xfc\x1f\x15\x29\x54\x8b\x09\x10\x65\x53\x9f\xe8\x30" +"\x81\xae\x91\x6b\xca\x93\x32\x1f\x9d\xf6\xca\x0e\x8a\x1e\x21\x02\x21\x00\xf7\x78" +"\x14\xb1\xe6\x24\x17\x13\xbf\xd9\x0d\xcd\x27\x1a\xc3\x28\xa4\xcb\xd8\x2e\x84\x1f" +"\x0c\xa9\x2a\x9e\x65\x31\xca\x4a\x3d\xeb" +; +const uint16_t __attest_size = sizeof(__attest)-1; diff --git a/firmware/src/descriptors.c b/firmware/src/descriptors.c index 1a98cf5..58158db 100644 --- a/firmware/src/descriptors.c +++ b/firmware/src/descriptors.c @@ -126,8 +126,9 @@ SI_SEGMENT_VARIABLE(configDesc[], #define LANG_STRING htole16( SLAB_USB_LANGUAGE ) #define MFR_STRING "Silicon Labs" #define PROD_STRING "U2F Zero" -#define SER_STRING "0123456789ABCDEF" -#define INT0_STRING "HID Keyboard" +#define SER_STRING "CAFEBABEFFFFFFFD" +#define INT0_STRING "U2F Zero" + LANGID_STATIC_CONST_STRING_DESC( langDesc[], LANG_STRING ); UTF16LE_PACKED_STATIC_CONST_STRING_DESC( mfrDesc[], MFR_STRING ); diff --git a/tools/flashing/erase.sh b/tools/flashing/erase.sh index 667e507..07e97d9 100644 --- a/tools/flashing/erase.sh +++ b/tools/flashing/erase.sh @@ -1,4 +1,3 @@ #!/bin/bash - # silabs utility debugger debugger id C2 -FlashUtilCL.exe FLASHEraseUSB "EC3004BCC9E" 1 +FlashUtilCL.exe FLASHEraseUSB "$1" 1 diff --git a/tools/flashing/program.sh b/tools/flashing/program.sh index 216b102..4783a6d 100644 --- a/tools/flashing/program.sh +++ b/tools/flashing/program.sh @@ -1,4 +1,4 @@ #!/bin/bash # silabs utility debugger file debugger id power C2 -FlashUtilCL.exe DownloadUSB -R $1 "EC3004BCC9E" 0 1 +FlashUtilCL.exe DownloadUSB -R $1 "$2" 0 1 diff --git a/tools/monitor.sh b/tools/monitor.sh new file mode 100644 index 0000000..be08f9e --- /dev/null +++ b/tools/monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash + + +export PATH=$PATH:`pwd`/flashing:../../../u2f_zero_client:../../../gencert + +key=gencert/ca/key.pem +adapters[0]=0 +num_adapters=0 +firmware=../firmware +setup=setup_device.sh + +for i in `seq 1 100` ; do + + adapters[$i]=$(FlashUtilCL.exe DeviceSN $i) + + if [[ ${adapters[$i]} = *"out of range"* ]] + then + break + fi + + num_adapters=$(($num_adapters + 1)) +done + +rm -rf workers +mkdir workers + +for i in `seq 1 $num_adapters` ; do + echo ${adapters[$i]} + mkdir workers/${adapters[$i]} + mkdir workers/${adapters[$i]}/worker + cp -rf $firmware workers/${adapters[$i]} + cp $setup workers/${adapters[$i]}/worker +done + +cd workers/${adapters[1]}/worker && ./$setup ../../../$key ${adapters[1]} CAFEBABE00000001 + + + + diff --git a/tools/setup_device.sh b/tools/setup_device.sh index 383f327..f0c9987 100755 --- a/tools/setup_device.sh +++ b/tools/setup_device.sh @@ -2,16 +2,26 @@ SETUP_HEX=../firmware/SETUP.hex FINAL_HEX=../firmware/release/u2f-firmware.hex -FLASH_TOOLS=0 +FLASH_TOOLS=1 +SN= +SN_build= -if [[ $# != "1" ]] +if [[ $# != "1" ]] && [[ $# != "2" ]] && [[ $# != "3" ]] then - echo "usage: $0 " + echo "usage: $0 [debugger-SN] [new-SN-for-U2F-token]" exit 1 fi + +if [[ $# != "1" ]] ; then + SN=$2 + if [[ $# = "3" ]] ; then + SN_build=$3 + fi +fi + export PATH=$PATH:gencert:u2f_zero_client:flashing if [[ $FLASH_TOOLS = 1 ]] @@ -19,22 +29,27 @@ then # setup atecc echo "erasing..." - erase.sh + erase.sh $SN while [[ "$?" -ne "0" ]] ; do sleep .1 - erase.sh + erase.sh $SN done echo "programming setup..." - program.sh $SETUP_HEX + program.sh $SETUP_HEX $SN [[ "$?" -ne "0" ]] && exit 1 fi echo "configuring..." -client.py configure pubkey.hex >/dev/null + +if [[ -n $SN_build ]] ; then + client.py configure pubkey.hex -s $SN_build >/dev/null +else + client.py configure pubkey.hex >/dev/null +fi while [[ "$?" -ne "0" ]] ; do sleep .2 @@ -47,6 +62,14 @@ gencert.sh "$1" "$(cat pubkey.hex)" attest.der > ../firmware/src/cert.c [[ "$?" -ne "0" ]] && exit 1 +if [[ -n $SN_build ]] ; then + sed -i "/#define SER_STRING.*/c\#define SER_STRING \"$SN_build\"" ../firmware/src/descriptors.c + rm ../firmware/release/u2f-firmware.omf +fi + +sed -i "s/firmware.*src.*cert.c/tools\/workers\/$SN\/firmware\/src\/cert.c/g" ../firmware/release/src/cert.__i +sed -i "s/firmware.*src.*descriptors.c/tools\/workers\/$SN\/firmware\/src\/descriptors.c/g" ../firmware/release/src/descriptors.__i + echo "done." echo "building..." @@ -60,20 +83,21 @@ then fi PATH1=$PATH -cd ../firmware/release && make all && cd ../../tools -export PATH=$PATH1 - +cur=`pwd` +cd ../firmware/release && make all && cd $cur [[ "$?" -ne "0" ]] && exit 1 +export PATH=$PATH1 + echo "programming final build..." cp $FINAL_HEX prog.hex -program.sh prog.hex +program.sh prog.hex $SN #rm prog.hex while [[ "$?" -ne "0" ]] ; do sleep .2 - program.sh prog.hex + program.sh prog.hex $SN done [[ "$?" -ne "0" ]] && exit 1 diff --git a/tools/u2f_zero_client/client.py b/tools/u2f_zero_client/client.py index 7524dcf..e268466 100755 --- a/tools/u2f_zero_client/client.py +++ b/tools/u2f_zero_client/client.py @@ -65,28 +65,40 @@ class commands: U2F_CUSTOM_IDLE_COLOR = 0x25 U2F_CUSTOM_IDLE_COLORP = 0x26 -if len(sys.argv) not in [2,3,4]: - print('usage: %s []' % sys.argv[0]) +if len(sys.argv) not in [2,3,4,5,6]: + print('usage: %s [] [-s serial-number]' % sys.argv[0]) print('actions: ') print(' configure : setup the device configuration. must specify pubkey output.') print(' rng: Continuously dump random numbers from the devices hardware RNG.') print(' seed: update the hardware RNG seed with input from stdin') print(' wipe: wipe all registered keys on U2F Zero. Must also press button 5 times. Not reversible.') + print(' list: list all connected U2F Zero tokens.') sys.exit(1) -def open_u2f(): +def open_u2f(SN=None): h = hid.device() try: - h.open(0x10c4,0x8acf) + h.open(0x10c4,0x8acf,unicode(SN)) except IOError as ex: try: h.open(0x10c4,0x8acf) except: print( ex) - print( 'U2F Zero not found') + if SN is None: print( 'U2F Zero not found') + else: print ('U2F Zero %s not found' % SN) sys.exit(1) return h + +def do_list(): + for d in hid.enumerate(0x10c4, 0x8acf): + keys = d.keys() + keys.sort() + for key in keys: + print("%s : %s" % (key, d[key])) + print('') + + def die(msg): print( msg) sys.exit(1) @@ -191,6 +203,7 @@ def do_rng(h): else: data = array.array('B',rng[6+1:6+1+32]).tostring() sys.stdout.write(data) + sys.stdout.flush() def do_seed(h): cmd = cmd_prefix + [ commands.U2F_CUSTOM_SEED, 0,20] @@ -269,26 +282,40 @@ def set_led_pulse(h,s): h.close() + if __name__ == '__main__': action = sys.argv[1].lower() - h = open_u2f() + h = None + SN = None + if '-s' in sys.argv: + if sys.argv.index('-s') + 1 > len(sys.argv): + print('need serial number') + sys.exit(1) + SN = sys.argv[sys.argv.index('-s') + 1] + if action == 'configure': + h = open_u2f(SN) if len(sys.argv) != 3: print( 'error: need output file') h.close() sys.exit(1) do_configure(h, sys.argv[2]) elif action == 'rng': + h = open_u2f(SN) do_rng(h) elif action == 'seed': + h = open_u2f(SN) do_seed(h) elif action == 'wipe': + h = open_u2f(SN) do_wipe(h) + elif action == 'list': + do_list() else: print( 'error: invalid action: ', action) - h.close() sys.exit(1) - h.close() + + if h is not None: h.close()