Author: wmb Date: 2007-10-04 10:19:30 +0200 (Thu, 04 Oct 2007) New Revision: 666
Added: cpu/x86/pc/olpc/fsupdate.fth Modified: cpu/x86/pc/olpc/copynand.fth cpu/x86/pc/olpc/crypto.bth cpu/x86/pc/olpc/crypto.fth cpu/x86/pc/olpc/fw.bth cpu/x86/pc/olpc/loaddropins.fth cpu/x86/pc/olpc/security.fth cpu/x86/pc/olpc/versions.fth Log: OLPC - Secure NAND file system update.
Modified: cpu/x86/pc/olpc/copynand.fth =================================================================== --- cpu/x86/pc/olpc/copynand.fth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/copynand.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -198,6 +198,8 @@ defer show-done ' cr to show-done
+: >eblock# ( page# -- eblock# ) nand-pages/block / ; + : copy-nand ( "devspec" -- ) open-nand get-img-filename @@ -206,7 +208,7 @@
['] noop to show-progress
- #nand-pages nand-pages/block / dup show-init ( #eblocks ) + #nand-pages >eblock# dup show-init ( #eblocks )
show-erasing ( ) ['] show-bad ['] show-erased ['] show-bbt-block " (wipe)" $call-nand @@ -219,7 +221,7 @@ load-base " copy-block" $call-nand ( page# error? ) " Error writing to NAND FLASH" ?nand-abort ( page# ) ?skip-oob - nand-pages/block / show-written ( ) + >eblock# show-written ( ) loop
show-cleaning @@ -319,7 +321,7 @@ ;
: alloc-crc-buf ( -- ) - #nand-pages nand-pages/block / to #crc-records + #nand-pages >eblock# to #crc-records #crc-records /l* alloc-mem to crc-buf ;
@@ -370,7 +372,7 @@ \ The stack is empty at the end of each line unless otherwise noted dump-oob? if #nand-pages else " usable-page-limit" $call-nand then 0 do - (cr i nand-pages/block / . + (cr i >eblock# . load-base i nand-pages/block " read-blocks" $call-nand nand-pages/block = if load-base /nand-block written? if
Modified: cpu/x86/pc/olpc/crypto.bth =================================================================== --- cpu/x86/pc/olpc/crypto.bth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/crypto.bth 2007-10-04 08:19:30 UTC (rev 666) @@ -6,9 +6,9 @@ fload ${BP}/cpu/x86/pc/olpc/versions.fth
" wget http://dev.laptop.org/pub/firmware/crypto/bios_verify-$%7BCRYPTO_VERSION%7D.... -O verify.img" expand$ $sh -" wget http://dev.laptop.org/pub/firmware/crypto/bios_hash-$%7BCRYPTO_VERSION%7D.im... -O hasher.img" expand$ $sh " wget http://dev.laptop.org/pub/firmware/crypto/testkeys/os.public -O os.public" expand$ $sh " wget http://dev.laptop.org/pub/firmware/crypto/testkeys/fw.public -O fw.public" expand$ $sh +" wget http://dev.laptop.org/pub/firmware/crypto/testkeys/fs.public -O fs.public" expand$ $sh " wget http://dev.laptop.org/pub/firmware/crypto/testkeys/lease.public -O lease.public" expand$ $sh " wget http://dev.laptop.org/pub/firmware/crypto/testkeys/developer.public -O developer.public" expand$ $sh
Modified: cpu/x86/pc/olpc/crypto.fth =================================================================== --- cpu/x86/pc/olpc/crypto.fth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/crypto.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -5,29 +5,6 @@ h# d0000 constant verify-bss \ The address the code is linked to run at h# 10000 constant /verify-bss
-1 [if] -h# 70000 constant hasher-base \ The address the code is linked to run at -h# 80000 constant hasher-bss -h# 18000 constant /hasher-bss -variable hashlen -d# 128 buffer: hashbuf - -: get-hasher ( -- ) - " hasher" find-drop-in 0= if 4drop true exit then ( prog$ ) - 2dup hasher-base swap move free-mem ( hashname$ ) -; - -: hash ( data$ hashname$ -- result$ ) - d# 128 hashlen ! - $cstr hashbuf hashlen ( databuf datalen hashname-cstr resbuf &reslen ) - - hasher-bss /hasher-bss erase - - hasher-base dup h# 10 - sp-call abort" Hash failed" drop 4drop ( ) - hashbuf hashlen @ -; -[then] - 0 value crypto-loaded? : load-crypto ( -- error? ) crypto-loaded? if false exit then @@ -43,14 +20,23 @@ $cstr verify-bss /verify-bss erase ( data$ sig$ key$ 'hashname ) verify-base dup h# 10 - sp-call >r 3drop 4drop r> ( result ) - -\ XXX free-mem in suspend.fth and fw.bth after find-drop-in -\ XXX clean out dead code in usb.fth ;
-: getbin " usb8388.bin" find-drop-in 0= abort" No usb8388.bin" ; -: getsig " usb8388.sig" find-drop-in 0= abort" No usb8388.sig" ; +\ This is a hack that saves a lot of memory. The crypto verifier +\ code has a mode where it will just compute and return the hash value, +\ instead of going on to verify the hash's signature. In that mode, +\ we use sig$ for the address and length of the result buffer, key-adr +\ to return the actual return length, and pass in key-len = 0 to denote +\ that we want only hashing.
+variable hashlen +d# 128 buffer: hashbuf +: hash ( data$ hashname$ -- result$ ) + 2>r hashbuf d# 128 hashlen 0 2r> ( data$ sig$ key$ hashname$ ) + signature-bad? abort" Hash failed" ( ) + hashbuf hashlen @ +; + \ LICENSE_BEGIN \ Copyright (c) 2007 FirmWorks \
Added: cpu/x86/pc/olpc/fsupdate.fth =================================================================== --- cpu/x86/pc/olpc/fsupdate.fth (rev 0) +++ cpu/x86/pc/olpc/fsupdate.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -0,0 +1,125 @@ +purpose: Secure NAND updater + +\ Depends on words from security.fth and copynand.fth + +: get-hex# ( -- n ) + safe-parse-word + push-hex + $number " Bad number" ?nand-abort + pop-base +; + +\ XXX implement this +: map-eblock# ( block# -- block#' ) ; + + +vocabulary nand-commands +also nand-commands definitions + +: data: ( "filename" -- ) + safe-parse-word fn-buf place + bundle-name$ image-name-buf place + open-img +; + +: erase-all ( -- ) + #nand-pages >eblock# show-erasing + ['] show-bad ['] show-erased ['] show-bbt-block " (wipe)" $call-nand + #image-eblocks show-writing +; + +: eblock: ( "eblock#" "hashname" "hash-of-128KiB" -- ) + get-hex# ( eblock# ) + read-image-block + load-base /nand-block safe-parse-word ( eblock# data$ hashname$ ) + hash ( eblock# result$ ) + safe-parse-word hex-decode " Malformed hash string" ?nand-abort + $= if ( eblock# ) + drop + else ( eblock# ) + ." Bad hash for eblock# " .x cr + abort + then ( ) + + load-base " copy-block" $call-nand ( page# error? ) + " Error writing to NAND FLASH" ?nand-abort ( page# ) + >eblock# show-written ( ) +; + +: bytes: ( "eblock#" "page#" "offset" "length" "data" -- ) + get-hex# get-hex# 2>r ( r: eblock# page# ) + get-hex# get-hex# ( offset length r: eblock# page# ) + 2dup + h# 840 >= abort" Offset + length exceeds page + OOB size" + safe-parse-word hex-decode ( offset length data$ ) + rot over <> abort" Length mismatch" ( offset data$ ) + r> r> map-eblock# nand-pages/block * + ( offset data$ page#') + -rot 2swap swap ( data$ page# offset ) + " pio-write-raw" $call-nand abort" NAND write error" +; + +: cleanmarkers ( -- ) + show-cleaning + ['] show-clean " put-cleanmarkers" $call-nand +; + +: mark-pending: ( "eblock#" -- ) + get-hex# map-eblock# nand-pages/block * ( page# ) + " COMP" rot h# 838 + " pio-write-raw" $call-nand abort" NAND write error" +; + +: mark-complete: ( "eblock#" -- ) + get-hex# map-eblock# nand-pages/block * + " LETE" rot h# 83c + " pio-write-raw" $call-nand abort" NAND write error" +; + +previous definitions + +: do-fs-update ( img$ -- ) + tuck load-base h# 100000 + swap move ( len ) + load-base h# 100000 + swap + open-nand + ['] noop to show-progress + #nand-pages >eblock# show-init + +\ clear-context nand-commands +also nand-commands + + ['] include-buffer catch if nip nip .error security-failure then + +previous +\ only forth also definitions + + show-done + close-nand-ihs +; + +: fs-update-from-list ( devlist$ -- ) + load-crypto if visible ." Crytpo load failed" cr show-sad security-failure then + + visible ( devlist$ ) + begin dup while ( rem$ ) + bl left-parse-string ( rem$ dev$ ) + dn-buf place ( rem$ ) + + null$ pn-buf place ( rem$ ) + null$ cn-buf place ( rem$ ) + " fs" bundle-present? if ( rem$ ) + " Filesystem image found - " ?lease-debug + fskey$ to pubkey$ ( rem$ ) + img$ sig$ sha-valid? if ( rem$ ) + 2drop ( ) + show-unlock ( ) + img$ do-fs-update ( ) + exit + then ( rem$ ) + show-lock ( rem$ ) + then ( rem$ ) + repeat ( rem$ ) + 2drop +; +: try-fs-update ( -- ) + ." Searching for a NAND file system update image." cr + all-devices$ fs-update-from-list +;
Modified: cpu/x86/pc/olpc/fw.bth =================================================================== --- cpu/x86/pc/olpc/fw.bth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/fw.bth 2007-10-04 08:19:30 UTC (rev 666) @@ -334,6 +334,7 @@ fload ${BP}/cpu/x86/pc/olpc/gamekeys.fth fload ${BP}/cpu/x86/pc/olpc/linux.fth fload ${BP}/cpu/x86/pc/olpc/security.fth +fload ${BP}/cpu/x86/pc/olpc/fsupdate.fth fload ${BP}/cpu/x86/pc/olpc/setwp.fth fload ${BP}/ofw/gui/ofpong.fth fload ${BP}/cpu/x86/pc/olpc/life.fth @@ -496,6 +497,12 @@ time&date 5drop 1 and if pong else life-demo then then ; +: ?fs-update ( -- ) + button-check button-x or button-o or button-square or ( mask ) + game-key-mask over and = if + try-fs-update + then +; : open-keyboard ( -- ) " keyboard" open-dev ?dup if set-stdin then ; @@ -521,6 +528,7 @@ ['] false to interrupt-auto-boot? probe-usb interpreter-init + ?fs-update secure-startup ['] (interrupt-auto-boot?) to interrupt-auto-boot? screen-ih stdout !
Modified: cpu/x86/pc/olpc/loaddropins.fth =================================================================== --- cpu/x86/pc/olpc/loaddropins.fth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/loaddropins.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -55,6 +55,7 @@ " verify.img" " verify" $add-deflated-dropin " os.public" " ospubkey" $add-dropin \ Incompressible " fw.public" " fwpubkey" $add-dropin \ Incompressible + " fs.public" " fspubkey" $add-dropin \ Incompressible " lease.public" " leasepubkey" $add-dropin \ Incompressible " developer.public" " develpubkey" $add-dropin \ Incompressible
Modified: cpu/x86/pc/olpc/security.fth =================================================================== --- cpu/x86/pc/olpc/security.fth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/security.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -3,8 +3,6 @@
\ Specs at http://wiki.laptop.org/go/Firmware_Security
-: boot-device-list " disk sd nand" ; - true value debug-security? : ?lease-debug ( msg$ -- ) debug-security? if type else 2drop then @@ -53,6 +51,7 @@ then rot >r 2dup r> 2! ( key$ ) ; +" fspubkey" key: fskey$ " ospubkey" key: oskey$ " fwpubkey" key: fwkey$ " develpubkey" key: develkey$ @@ -73,10 +72,6 @@ \ binary form at sig-buf. It returns the adr,len of the binary string.
: hex-decode ( hex$ -- true | sig$ false ) - dup /sig 2* <> if - ( ." Bad signature length" cr ) - 2drop true exit - then ( hex$ ) sig-buf -rot ( adr hex$ ) bounds ?do ( adr ) i 2 push-hex $number pop-base if ( adr ) @@ -97,6 +92,8 @@ bl left-parse-string dup d# 6 <> if 4drop true exit then 2swap ( hash$ rem$ ) bl left-parse-string nip d# 64 <> if 4drop true exit then ( hash$ rem$ ) newline left-parse-string 2swap nip 0<> if 4drop true exit then ( hash$ data$ ) + dup /sig 2* <> if ( ." Bad signature length" cr ) 2drop true exit then ( hash$ data$ ) + hex-decode if 2drop true else false then ;
@@ -141,8 +138,6 @@ \ hashname remembers the most recently used hashname to guard against \ attacks based on reuse of the same (presumably compromized) hash.
-d# 32 buffer: hashname - \ invalid? checks the validity of data$ against the ASCII signature \ record sig01$, using the public key that pubkey$ points to. \ It also verifies that the hashname contained in sig01$ is the @@ -344,7 +339,6 @@ \ a tree-state flag; see check-lease.)
: check-machine-signature ( sig$ expiration$ -- -1|1 ) - 0 hashname c! machine-id-buf d# 51 + swap move ( sig$ ) machine-id-buf d# 67 2swap sha-valid? if 1 else -1 then ; @@ -510,7 +504,6 @@ r> to load-path
" RD found - " ?lease-debug - 0 hashname c! img$ sig$ sha-valid? if show-unlock load-base to ramdisk-adr @@ -606,7 +599,6 @@ else " minus" show-icon " new - " ?lease-debug - 0 hashname c! fwkey$ to pubkey$ img$ sig$ fw-valid? if visible @@ -617,6 +609,12 @@ true to file-loaded? " Updating firmware" ?lease-debug-cr
+ ['] ?enough-power catch ?dup if + visible + .error + security-failure + then + \ Latch alternate? flag for next startup alternate? if [char] A h# 82 cmos! then
@@ -636,7 +634,6 @@ d# 16 0 +icon-xy show-dot " os" bundle-present? if " OS found - " ?lease-debug - 0 hashname c! oskey$ to pubkey$ img$ sig$ sha-valid? if img$ tuck load-base swap move !load-size @@ -667,17 +664,18 @@ icon-xy to base-xy icon-xy image-width 0 d+ to next-xy ( list$ )
- filesystem-present? if + filesystem-present? if ( list$ )
- d# 5 d# 77 +icon-xy show-dot - has-developer-key? if + d# 5 d# 77 +icon-xy show-dot ( list$ ) + has-developer-key? if ( list$ ) + 2drop ( ) visible show-unlock true exit - then + then ( list$ )
- load-from-device if - 2drop + load-from-device if ( list$ ) + 2drop ( ) ['] secure-load-ramdisk to load-ramdisk " init-program" $find if execute show-going go @@ -685,12 +683,12 @@ show-x security-failure then - then + then ( list$ )
- next-xy to icon-xy + next-xy to icon-xy ( list$ ) repeat ( list$ ) - " sad" show-icon - 2drop false + " sad" show-icon ( list$ ) + 2drop false ( ) ;
: persistent-devkey? ( -- flag ) " dk" find-tag dup if nip nip then ;
Modified: cpu/x86/pc/olpc/versions.fth =================================================================== --- cpu/x86/pc/olpc/versions.fth 2007-10-02 07:52:21 UTC (rev 665) +++ cpu/x86/pc/olpc/versions.fth 2007-10-04 08:19:30 UTC (rev 666) @@ -2,7 +2,7 @@
\ The overall firmware revision macro: FW_MAJOR C -macro: FW_MINOR 28 +macro: FW_MINOR 28b
\ The EC microcode macro: EC_VERSION c24 @@ -16,4 +16,4 @@ macro: WLAN_VERSION 5.110.16.p1
\ The bios_verify image -macro: CRYPTO_VERSION 0.1 +macro: CRYPTO_VERSION 0.2