[openfirmware] r1084 - cpu/x86/pc/olpc
svn at openfirmware.info
svn at openfirmware.info
Wed Jan 28 01:17:24 CET 2009
Author: wmb
Date: 2009-01-28 01:17:24 +0100 (Wed, 28 Jan 2009)
New Revision: 1084
Modified:
cpu/x86/pc/olpc/fsupdate.fth
cpu/x86/pc/olpc/security.fth
cpu/x86/pc/olpc/setwp.fth
Log:
OLPC trac 9045 - added multiple key support as defined by
http://wiki.laptop.org/go/Firmware_security
Modified: cpu/x86/pc/olpc/fsupdate.fth
===================================================================
--- cpu/x86/pc/olpc/fsupdate.fth 2009-01-23 21:57:21 UTC (rev 1083)
+++ cpu/x86/pc/olpc/fsupdate.fth 2009-01-28 00:17:24 UTC (rev 1084)
@@ -169,7 +169,7 @@
null$ cn-buf place ( rem$ )
" fs" bundle-present? if ( rem$ )
" Filesystem image found - " ?lease-debug
- fskey$ to pubkey$ ( rem$ )
+ fskey$ to pubkeylist$ ( rem$ )
img$ sig$ sha-valid? if ( rem$ )
2drop ( )
show-unlock ( )
Modified: cpu/x86/pc/olpc/security.fth
===================================================================
--- cpu/x86/pc/olpc/security.fth 2009-01-23 21:57:21 UTC (rev 1083)
+++ cpu/x86/pc/olpc/security.fth 2009-01-28 00:17:24 UTC (rev 1084)
@@ -101,30 +101,111 @@
: PN pn-buf count ;
previous definitions
+0 0 2value pubkeylist$ \ adr,len of a concatenated sequence of keys
+0 value pubkeylen \ Length of each key in the list
+
+\ Copy a string to allocated memory
+: preserve$ ( $ -- $' )
+ >r ( adr1 r: len )
+ r@ alloc-mem ( adr1 adr2 )
+ tuck r@ move r> ( $' )
+;
+
+\ find-key-tag finds a tag like "s0" or "s8". The caller sets tagname[0]
+\ to 's' and then calls find-key-tag with different "n" arguments.
+
+2 buffer: tagname
+: find-key-tag ( n -- false | value$ true )
+ [char] 0 + tagname 1+ c!
+ tagname 2 find-tag
+;
+
+: ?bad-tag-len ( explen actlen -- )
+ <> if
+ ." Warning - override key length mismatch for tag " tagname 2 type cr
+ then
+;
+
+\ Count the number of additional keys, so we know how much memory to allocate
+
+: #augment-keys ( keylen -- n )
+ 0 d# 10 1 do ( len n )
+ i find-key-tag if ( len n value$ )
+ nip 2 pick ?bad-tag-len ( len n )
+ 1+ ( len n' )
+ then ( len n )
+ loop ( len n )
+ nip
+;
+
+\ Amend the key list string with alternative or additional keys from
+\ manufacturing data.
+
+: augment-key$ ( olpc-key$ mfg-data$ -- key$' )
+ tagname swap move ( key$ )
+
+ 0 find-key-tag if ( key$ value$ )
+ \ If we have an override key with tag suffix 0, replace the OLPC key
+ 2 pick over ?bad-tag-len ( key$ value$ )
+
+ 2swap free-mem ( value$ )
+ preserve$ ( key$' )
+ exit
+ then ( key$ )
+
+ \ Otherwise add augment keys to the list ( key$ )
+ \ First determine how much memory to allocate
+ dup #augment-keys 1+ ( key$ #extra )
+ over * dup alloc-mem swap ( key$ total$ )
+ 2over 2over drop ( key$ total$ key$ total-adr )
+ swap move ( key$ total$ )
+ 2swap tuck free-mem ( total$ keylen )
+ 2 pick over + ( total$ keylen curadr )
+ d# 10 1 do ( total$ keylen curadr )
+ i find-key-tag if ( total$ keylen curadr value$ )
+ drop over 3 pick move ( total$ keylen curadr )
+ over + ( total$ keylen curadr' )
+ then ( total$ keylen curadr )
+ loop ( total$ keylen curadr )
+ 2drop ( total$ )
+;
+
\ key: is a defining word whose children return key strings.
\ Each child word has the name of its key stored in the dictionary.
\ The first time that a child word executes, it uses the key name
\ to find the key value and caches the key value in RAM so subsequent
\ uses are faster.
+\ The key name includes both the name that is used in the dropin
+\ module list (e.g. "fspubkey") and the prefix letter for mfg data
+\ tags (e.g. "s").
+
: key: ( name$ "name" -- key$ )
create 0 , 0 , ", \ adr len name
does> ( apf -- key$ )
dup @ if 2@ exit then ( apf )
dup 2 na+ count ( apf name$ )
- 2dup find-drop-in if ( apf name$ key$ )
- 2nip
- else ( apf name$ )
- ." Can't load key " type cr
+ [char] , left-parse-string ( apf mfg-data$ dropin-name$ )
+ 2dup find-drop-in if ( apf mfg-data$ name$ key$ )
+ 2nip ( apf mfg-data$ key$ )
+ else ( apf mfg-data$ name$ )
+ ." Can't load key " type cr ( apf mfg-data$ )
+ 2drop ( apf )
" Missing Key" ( apf bad-key$ )
- then
+ dup to pubkeylen ( apf bad-key$ )
+ rot >r 2dup r> 2! ( key$ )
+ exit
+ then ( apf mfg-data$ key$ )
+ dup to pubkeylen ( apf mfg-data$ key$ )
+ 2swap ( apf key$ mfg-data$ )
+ augment-key$ ( apf key$' )
rot >r 2dup r> 2! ( key$ )
;
-" fspubkey" key: fskey$
-" ospubkey" key: oskey$
-" fwpubkey" key: fwkey$
-" develpubkey" key: develkey$
-" leasepubkey" key: leasekey$
+" fspubkey,s" key: fskey$
+" ospubkey,o" key: oskey$
+" fwpubkey,w" key: fwkey$
+" develpubkey,d" key: develkey$
+" leasepubkey,a" key: leasekey$
\ pubkey$ is a global variable that points to the currently-selected
\ public key string. It simplifies the stack manipulations for other
@@ -235,29 +316,79 @@
then
;
-: our-pubkey? ( sig01$ -- flag )
- bl left-parse-string " sig01:" $= 0= if 2drop false exit then ( rem$ )
+\ break$ splits a string into an initial substring of length n
+\ (head$) and the residual substring (tail$). If the input
+\ string is shorter than n, head$ is the input string and tail$ is
+\ the null string.
+
+: break$ ( $ n -- tail$ head$ )
+ 2dup < if drop null$ 2swap exit then
+ dup >r /string ( tail$ )
+ over r@ - r> ( tail$ head$ )
+;
+
+: sig01$>key$ ( sig01$ -- true | binary-key$ false )
+ bl left-parse-string " sig01:" $= 0= if 2drop true exit then ( rem$ )
bl left-parse-string 2drop \ Discard hash name ( rem$ )
bl left-parse-string 2nip \ Get key signature ( key$ )
- /sig 2* min hex-decode if 2drop false exit then ( binary-key$ )
- pubkey$ dup 3 pick - 0 max /string $= ( flag )
+ /sig 2* min hex-decode if 2drop true exit then ( binary-key$ )
+ false
;
-\ Look for a line that starts with "sig01: " and whose key signature
+\ True if short$ matches the end of long$
+: tail$= ( short$ long$ -- flag ) 2 pick - + swap comp 0= ;
+
+: key-in-list? ( key$ -- flag ) \ Sets pubkey$ as an important side effect
+ 2>r ( r: key$ )
+ pubkeylist$ begin dup while ( rem$ r: key$ )
+ pubkeylen break$ ( rem$' pubkey$ r: key$ )
+ 2r@ 2over tail$= if ( rem$ pubkey$ r: key$ )
+ to pubkey$ ( rem$ r: key$ )
+ 2r> 4drop true ( true )
+ exit
+ then ( rem$' pubkey$ r: key$ )
+ 2drop ( rem$' r: key$ )
+ repeat ( rem$' r: key$ )
+ 2r> 4drop false
+;
+
+: in-pubkey-list? ( sig01$ -- flag )
+ sig01$>key$ if false exit then ( key$ )
+ key-in-list? ( flag )
+;
+
+: our-pubkey? ( sig01$ -- flag )
+ sig01$>key$ if false exit then ( key$ )
+ pubkey$ tail$= ( flag )
+;
+
+\ Look for a line that starts with "sig01: " whose key signature
+\ matches the trailing bytes of a public key in our current list.
+: next-sig01-in-list$ ( sig$ -- true | rem$ sig01$ false )
+ begin dup while ( rem$ )
+ newline left-parse-string ( rem$' line$ )
+ 2dup in-pubkey-list? if false exit then ( rem$ line$ )
+ 2drop ( rem$ )
+ repeat ( rem$ )
+ " No signature for our key list" ?lease-error-cr
+ 2drop true
+;
+
+\ Look for a line that starts with "sig01: " whose key signature
\ matches the trailing bytes of our currently-selected public key.
: next-sig01$ ( sig$ -- true | rem$ sig01$ false )
- begin dup while ( rem$ )
- newline left-parse-string ( rem$' line$ )
- 2dup our-pubkey? if false exit then ( rem$ line$ )
- 2drop ( rem$ )
- repeat ( rem$ )
+ begin dup while ( rem$ )
+ newline left-parse-string ( rem$' line$ )
+ 2dup our-pubkey? if false exit then ( rem$ line$ )
+ 2drop ( rem$ )
+ repeat ( rem$ )
" No signature for our key" ?lease-error-cr
2drop true
;
\ Find a sig01: line and check its sha256/rsa signature
: sha-valid? ( data$ sig01$ -- okay? )
- next-sig01$ if 2drop false exit then ( data$ rem$ sig01$ )
+ next-sig01-in-list$ if 2drop false exit then ( data$ rem$ sig01$ )
2nip " sha256" invalid? 0=
;
@@ -265,7 +396,7 @@
\ and check their signatures
: fw-valid? ( data$ sig$ -- okay? )
2swap 2>r ( sig$ r: data$ )
- next-sig01$ if 2r> 2drop false exit then ( rem$ sig01$ )
+ next-sig01-in-list$ if 2r> 2drop false exit then ( rem$ sig01$ )
2r@ 2swap sha-valid? 0= if ( rem$ r: data$ )
2r> 4drop false exit
then ( rmd-sig$ r: data$ )
@@ -273,17 +404,6 @@
2nip 2r> 2swap " rmd160" invalid? 0=
;
-\ break$ splits a string into an initial substring of length n
-\ (head$) and the residual substring (tail$). If the input
-\ string is shorter than n, head$ is the input string and tail$ is
-\ the null string.
-
-: break$ ( $ n -- tail$ head$ )
- 2dup < if drop null$ 2swap exit then
- dup >r /string ( tail$ )
- over r@ - r> ( tail$ head$ )
-;
-
\ numfield is a factor used for parsing 2-digit fields from date/time strings.
: numfield ( exp$ min max -- exp$' )
>r >r ( exp$ r: max min )
@@ -417,7 +537,7 @@
\ doesn't match our pubkey.
: check-machine-signature ( sig$ expiration$ -- -1|1 )
- 2over our-pubkey? if ( sig$ exp$ )
+ 2over in-pubkey-list? if ( sig$ exp$ )
machine-id-buf d# 51 + swap move ( sig$ )
machine-id-buf d# 67 2swap ( id$ sig$ )
" sha256" invalid? if -1 else 1 then ( -1|1 )
@@ -487,7 +607,7 @@
" lease.sig" open-security? if drop false exit then >r ( r: ih )
" Lease " ?lease-debug
load-started
- leasekey$ to pubkey$
+ leasekey$ to pubkeylist$
begin
sec-line-buf /sec-line-max r@ read-line if ( actual -eof? )
2drop r> close-file drop false exit
@@ -497,7 +617,8 @@
1 of r> close-file drop " unlock" show-icon true exit endof
-1 of r> close-file drop " lock" show-icon false exit endof
endcase
- repeat
+ repeat ( actual )
+ drop ( )
" No matching records" ?lease-error-cr
r> close-file drop false
;
@@ -622,7 +743,7 @@
" develop.sig" open-security? if drop false exit then >r ( r: ih )
" Devel key " ?lease-debug
load-started
- develkey$ to pubkey$
+ develkey$ to pubkeylist$
begin
sec-line-buf /sec-line-max r@ read-line if ( actual -eof? )
2drop r> close-file drop false exit
@@ -717,6 +838,19 @@
" Reflash returned, unexpectedly" .security-failure
;
+\ Turn off indexed I/O unless the OS is signed with the firmware
+\ key in addition to the OS key.
+
+: ?disable-indexed-io ( -- )
+ debug-security? >r false to debug-security?
+ pubkeylist$ 2>r fwkey$ to pubkeylist$
+
+ img$ sig$ fw-valid? 0= if ec-indexed-io-off then
+
+ 2r> to pubkeylist$
+ r> to debug-security?
+;
+
: load-from-device ( devname$ -- done? )
d# 16 0 +icon-xy show-dot
@@ -730,7 +864,7 @@
else
" minus" show-icon
" new - " ?lease-debug
- fwkey$ to pubkey$
+ fwkey$ to pubkeylist$
img$ sig$ fw-valid? if
img$ do-firmware-update
then
@@ -744,8 +878,9 @@
d# 16 0 +icon-xy show-dot
" os" bundle-present? if
" OS found - " ?lease-debug
- oskey$ to pubkey$
+ oskey$ to pubkeylist$
img$ sig$ sha-valid? if
+\ ?disable-indexed-io
img$ tuck load-base swap move !load-size
show-unlock
true exit
@@ -794,7 +929,8 @@
['] secure-load-ramdisk to load-ramdisk
" init-program" $find if
set-cmdline
- execute show-going go
+ execute
+ show-going go
then
show-x
security-failure
Modified: cpu/x86/pc/olpc/setwp.fth
===================================================================
--- cpu/x86/pc/olpc/setwp.fth 2009-01-23 21:57:21 UTC (rev 1083)
+++ cpu/x86/pc/olpc/setwp.fth 2009-01-28 00:17:24 UTC (rev 1084)
@@ -173,3 +173,18 @@
r> r> h# ff fill ( )
put-mfg-data
;
+
+: delete-tag ( "name" -- ) safe-parse-word $delete-tag ;
+
+: add-tag-from-file ( "name" "filename" -- )
+ safe-parse-word 2>r ( r: name$ )
+ reading ( r: name$ )
+ ifd @ fsize >r ( r: name$ len )
+ r@ alloc-mem ( adr r: name$ len )
+ dup r@ ifd @ fgets ( adr actual r: name$ len )
+ ifd @ fclose ( adr actual r: name$ len )
+ r@ <> abort" File read error" ( adr r: name$ len )
+ r> 2dup 2r> ( data$ data$ name$ )
+ $add-tag ( data$ )
+ free-mem
+;
More information about the openfirmware
mailing list