Author: wmb Date: Fri May 13 00:09:17 2011 New Revision: 2198 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2198
Log: OLPC RTC anti-rollback - working version.
Modified: cpu/x86/pc/olpc/guardrtc.fth cpu/x86/pc/olpc/security.fth
Modified: cpu/x86/pc/olpc/guardrtc.fth ============================================================================== --- cpu/x86/pc/olpc/guardrtc.fth Tue May 10 19:56:01 2011 (r2197) +++ cpu/x86/pc/olpc/guardrtc.fth Fri May 13 00:09:17 2011 (r2198) @@ -70,6 +70,7 @@ flash-open ( ) (put-mfg-data) ( ) flash-close ( ) + d# 1000 ms ( ) \ Give the EC time to restart ; : flash-write-some ( adr len offset -- ) flash-open ( adr len offset ) @@ -142,31 +143,41 @@ update-timestamp ( status ) ;
-1 buffer: byte-buf -: encode-byte ( b -- ) byte-buf c! byte-buf 1 encode-bytes ; : +encode-bytes ( prop$ $ -- prop$' ) encode-bytes encode+ ;
-: make-timestamp-property ( -- ) - rtc-timestamp 0= if exit then - " /chosen" find-package drop push-package ( ) - rtc-timestamp unix-seconds> ( s m h d m y ) - push-decimal ( s m h d m y ) - #timestamps (.) encode-bytes ( s m h d m y prop$ ) - " ," +encode-bytes rot (.4) +encode-bytes ( s m h d m prop$ ) - " -" +encode-bytes rot (.2) +encode-bytes ( s m h d prop$' ) - " -" +encode-bytes rot (.2) +encode-bytes ( s m h prop$' ) - " @" +encode-bytes rot (.2) +encode-bytes ( s m prop$' ) - " :" +encode-bytes rot (.2) +encode-bytes ( s prop$' ) - " :" +encode-bytes rot (.2) +encode-bytes ( prop$' ) - " "(00)" +encode-bytes ( prop$' ) - pop-base ( ) - - " rtc-timestamp" (property) ( ) - pop-package -; -: make-status-property ( value$ -- ) - " /chosen" find-package drop push-package ( value$ ) +string-array rtc-status-names + ," ok" + ," empty" + ," residue" + ," rollback" +end-string-array + +: make-rtc-properties ( status -- ) + " /chosen" find-package drop push-package ( status ) + + rtc-status-names count encode-string " rtc-status" (property) ( ) + + rtc-timestamp if + rtc-timestamp unix-seconds> ( s m h d m y ) + push-decimal ( s m h d m y ) + (.4) encode-bytes ( s m h d m prop$ ) + rot (.2) +encode-bytes ( s m h d prop$' ) + rot (.2) +encode-bytes ( s m h prop$' ) + " T" +encode-bytes ( s m h prop$' ) + rot (.2) +encode-bytes ( s m prop$' ) + rot (.2) +encode-bytes ( s prop$' ) + rot (.2) +encode-bytes ( prop$' ) + " Z"(00)" +encode-bytes ( prop$' ) + pop-base ( ) + + " rtc-timestamp" (property) ( ) + then + + push-decimal + #timestamps (.) encode-bytes " rtc-count" (property) ( ) + pop-base + pop-package ;
@@ -178,24 +189,19 @@ then ( flag ) ;
-: rtc-rollback? ( -- flag ) +: rtc-rollback? ( -- error? ) rtcar-enabled? 0= if exit then
find-timestamp ( status ) ?update-timestamp ( status' ) - make-timestamp-property ( status ) - case - 0 of " ok" make-status-property false endof - 1 of " empty" make-status-property false endof - 2 of " residue" make-status-property true endof - 3 of " rollback" make-status-property true endof - ( default ) true swap - endcase + dup make-rtc-properties ( status ) + 2 >= ( error? ) ;
-: parse-field ( val$ delimiter expected-length -- val$' field$ ) - >r left-parse-string ( val$' field$ ) - dup r> <> throw +: parse-field ( val$ length -- val$' field$ ) + 2dup < throw ( val$ length ) + >r over r@ ( val$ adr length r: length ) + 2swap r> /string 2swap ( val$' field$ ) ; \ Throws an error if either a number is unparsable or out of range : decode-number ( field$ min max -- n ) @@ -206,48 +212,47 @@ ;
: decode-timestamp ( val$ -- s m h d m y ) - [char] - 4 parse-field d# 2000 d# 2099 decode-number >r ( val$' r: y ) - [char] - 2 parse-field 1 d# 12 decode-number >r ( val$' r: y m ) - [char] @ 2 parse-field 1 d# 31 decode-number >r ( val$' r: y m d ) - [char] : 2 parse-field 0 d# 23 decode-number >r ( val$' r: y m d h ) - [char] : 2 parse-field 0 d# 59 decode-number >r ( val$' r: y m d h m ) - dup 2 <> throw 0 d# 59 decode-number >r ( r: y m d h m s ) - r> r> r> r> r> r> ( s m h d m y ) -; -: fix-rtc-timestamps ( data$ -- ) \ "count old-ts new-ts" e.g. 2011-10-12,00:23:45 - bl left-parse-string ( rem$ count$ ) - - 0 h# 7fffffff ['] decode-number catch if ( rem$ x x x x ) - 4drop 2drop ." Bad count format" cr ( ) - exit ( -- ) - then ( rem$ count ) - -rot ( count rem$ ) - - find-timestamp ( count rem$ ) - - bl left-parse-string ( count rem$ old-timestamp$ ) - 2dup " no-timestamp" $= if ( count rem$ old-timestamp$ ) - 2drop ( count rem$ ) - rtc-timestamp if ( count rem$ ) - 3drop ( ) + 4 parse-field d# 2000 d# 2099 decode-number >r ( val$' r: y ) + 2 parse-field 1 d# 12 decode-number >r ( val$' r: y m ) + 2 parse-field 1 d# 31 decode-number >r ( val$' r: y m d ) + 1 parse-field drop c@ [char] T <> throw ( val$' r: y m d ) + 2 parse-field 0 d# 23 decode-number >r ( val$' r: y m d h ) + 2 parse-field 0 d# 59 decode-number >r ( val$' r: y m d h m ) + 2 parse-field 0 d# 59 decode-number >r ( val$' r: y m d h m s ) + 1 parse-field drop c@ [char] Z <> throw ( val$' r: y m d h m s ) + nip 0<> throw ( r: y m d h m s ) + r> r> r> r> r> r> ( s m h d m y ) +; +: fix-rtc-timestamps ( newrtc$ nonce$ -- currentrtc$ ) + find-timestamp drop ( newrtc$ nonce$ currentrtc$ ) + + 2dup " 00000000T000000Z" $= if ( newrtc$ nonce$ currentrtc$ ) + 2drop ( newrtc$ nonce$ ) + rtc-timestamp if ( newrtc$ nonce$ ) + 4drop ( ) ." Old timestamp mismatch" cr ( ) exit ( -- ) - then - else ( count rem$ old-timestamp$ ) - ['] decode-timestamp catch if ( count rem$ x x ) - 5drop ( ) + then ( newrtc$ nonce$ ) + else ( newrtc$ nonce$ currentrtc$ ) + ['] decode-timestamp catch if ( newrtc$ nonce$ x x ) + 2drop 4drop ( ) ." Bad timestamp format" cr ( ) exit ( -- ) - then ( count rem$ s m h d m y ) - then ( count rem$ s m h d m y ) + then ( newrtc$ nonce$ s m h d m y ) + >unix-seconds ( newrtc$ nonce$ timestamp ) + rtc-timestamp <> if ( newrtc$ nonce$ ) + 4drop ( ) + ." Old timestamp mismatch" cr ( ) + exit ( -- ) + then ( newrtc$ nonce$ ) + then ( newrtc$ nonce$ )
- >unix-seconds ( count rem$ old-timestamp ) - rtc-timestamp <> if ( count rem$ ) - 3drop ( ) - ." Old timestamp mismatch" cr ( ) + 0 h# 7fffffff ['] decode-number catch if ( newrtc$ x x x x ) + 4drop 2drop ." Bad count format" cr ( ) exit ( -- ) - then ( count rem$ ) - rot init-timestamp-area ( rem$ ) + then ( newrtc$ count ) + + init-timestamp-area ( newrtc$ )
['] decode-timestamp catch if ( x x ) 2drop ." Bad timestamp format" cr ( )
Modified: cpu/x86/pc/olpc/security.fth ============================================================================== --- cpu/x86/pc/olpc/security.fth Tue May 10 19:56:01 2011 (r2197) +++ cpu/x86/pc/olpc/security.fth Fri May 13 00:09:17 2011 (r2198) @@ -955,37 +955,102 @@ r> to debug-security? ;
-: fix-rtc-history ( data$ -- ) \ SN UUID counter timestamp newtimestamp - \ Isolate data from first line + +0 [if] +\ SN : UUID : currrtc : nonce : newrtc +\ 0 11 12 48 49 65 66 76 77 (93) +d# 11 1+ d# 36 + 1+ d# 16 + 1+ d# 10 + 1+ d# 16 + +constant /rtc-signature +/rtc-signature buffer: rtc-signature-buf + +: check-rtc-signature ( sig$ currentrtc$ nonce$ newrtc$ -- good? ) + + rtc-signature-buf d# 77 + swap move ( sig$ currentrtc$ nonce$ ) + [char] : rtc-signature-buf d# 76 + c! ( sig$ currentrtc$ nonce$ ) + + rtc-signature-buf d# 66 + swap move ( sig$ currentrtc$ ) + [char] : rtc-signature-buf d# 65 + c! ( sig$ currentrtc$ ) + + rtc-signature-buf d# 49 + swap move ( sig$ ) + + \ Copy SN:UUID: from machine-id-buf to rtc-signature-buf + machine-id-buf d# 49 rtc-signature-buf move ( sig$ ) + + rtc-signature-buf /rtc-signature 2swap ( data$ sig$ ) + " sha256" signature-good? ( good? ) +; + newrtc$ rtc-signature-buf d# 77 + swap move ( ) + [char] : rtc-signature-buf d# 76 + c! ( ) + + nonce$ rtc-signature-buf d# 66 + swap move ( ) + [char] : rtc-signature-buf d# 65 + c! ( ) + + currentrtc$ rtc-signature-buf d# 49 + swap move ( ) + [char] : rtc-signature-buf d# 48 + c! ( ) + +[then] + +0 0 2value currentrtc$ +0 0 2value newrtc$ +0 0 2value nonce$ +0 0 2value rtcsig$ +: rtc-format-error ( -- done? ) + ." RTC Reset format error" ?lease-error-cr true +; +: check-rtc-key ( data$ -- done? ) \ rtc01: SN currentrtc nonce newrtc sig0N: ... + \ Isolate data from line newline left-parse-string 2nip ( rem$ )
+ bl left-parse-string " rtc01:" $= 0= if ( rem$ ) + ." Unknown format" ?lease-error-cr ( rem$ ) + 2drop true exit ( -- true ) + then ( rem$ ) + bl left-parse-string ( rem$ serial$ ) my-sn$ $= 0= if ( rem$ ) - ." Wrong serial number" ?lease-error-cr ( rem$ ) - 2drop exit ( -- ) +\ ." Wrong serial number" ?lease-error-cr ( rem$ ) + 2drop false exit ( -- false ) then ( rem$ )
- \ Ignore UUID for now - bl left-parse-string ( rem$ uuid$ ) - 2drop ( rem$ ) - - fix-rtc-timestamps ( ) + bl left-parse-string to currentrtc$ ( rem$' ) + bl left-parse-string to nonce$ ( rem$' ) + bl left-parse-string to newrtc$ ( rem$' ) + to rtcsig$ ( ) + + currentrtc$ nip d# 16 <> if rtc-format-error exit then + nonce$ nip d# 10 <> if rtc-format-error exit then + newrtc$ nip d# 16 <> if rtc-format-error exit then + + newrtc$ nonce$ currentrtc$ machine-id-buf d# 48 " %s:%s:%s:%s" sprintf ( data$ ) + + rtcsig$ " sha256" signature-good? if ( ) + newrtc$ nonce$ currentrtc$ fix-rtc-timestamps ( ) + else + ." Bad signature " ?lease-error-cr ( ) + then ( ) + true ( done? ) ;
: ?rtc-update ( -- ) rtcar-enabled? 0= if exit then show-dot null$ cn-buf place - " rtcreset" bundle-present? if + " rtcreset.sig" open-security? if exit then >r ( r: ih ) " RTCRESET found - " ?lease-debug + load-started leasekey$ to pubkey$ - img$ sig$ sha-valid? if - img$ fix-rtc-history - show-unlock - else - show-lock - then - then + begin + sec-line-buf /sec-line-max r@ read-line if ( actual -eof? ) + 2drop r> close-file drop exit + then ( actual -eof? ) + while ( actual ) + sec-line-buf swap check-rtc-key if ( ) + r> close-file drop exit ( -- ) + then ( ) + repeat ( actual ) + drop ( ) + " No matching records" ?lease-error-cr ( ) + r> close-file drop false ( false ) ;
: load-from-device ( devname$ -- done? )