github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/rpmb_fake.go (about) 1 // Copyright 2022 The Armored Witness OS authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build fake_rpmb 16 // +build fake_rpmb 17 18 package main 19 20 import ( 21 "errors" 22 23 "github.com/coreos/go-semver/semver" 24 "github.com/transparency-dev/armored-witness-os/rpmb" 25 ) 26 27 const ( 28 // version epoch length 29 versionLength = 32 30 // RPMB sector for OS rollback protection 31 osVersionSector = 1 32 // RPMB sector for TA rollback protection 33 taVersionSector = 2 34 35 // RPMB sector for TA use 36 taUserSector = 3 37 38 sectorLength = 256 39 numSectors = 16 40 ) 41 42 type RPMB struct { 43 mem [numSectors][sectorLength]byte 44 counter uint32 45 } 46 47 func newRPMB(_ Card) (*RPMB, error) { 48 return &RPMB{ 49 mem: [numSectors][sectorLength]byte{}, 50 }, nil 51 } 52 53 func (r *RPMB) init() error { 54 return nil 55 } 56 57 func parseVersion(s string) (version *semver.Version, err error) { 58 return semver.NewVersion(s) 59 } 60 61 // expectedVersion returns the version epoch stored in a fake RPMB area. 62 func (r *RPMB) expectedVersion(offset uint16) (*semver.Version, error) { 63 v := string(r.mem[offset][:versionLength]) 64 65 return semver.NewVersion(v) 66 } 67 68 // updateVersion writes a new version epoch in a fake RPMB area. 69 func (r *RPMB) updateVersion(offset uint16, version semver.Version) error { 70 copy(r.mem[offset][:], []byte(version.String())) 71 r.counter++ 72 73 return nil 74 } 75 76 // checkVersion verifies version information against RPMB stored data. 77 // 78 // If the passed version is older than the RPMB area information of the 79 // internal eMMC an error is returned. 80 // 81 // If the passed version is more recent than the RPMB area information then the 82 // internal eMMC is updated with it. 83 func (r *RPMB) checkVersion(offset uint16, s string) error { 84 runningVersion, err := parseVersion(s) 85 if err != nil { 86 return err 87 } 88 89 expectedVersion, err := r.expectedVersion(offset) 90 if err != nil { 91 return err 92 } 93 94 switch { 95 case runningVersion.LessThan(*expectedVersion): 96 return errors.New("version mismatch") 97 case expectedVersion.Equal(*runningVersion): 98 return nil 99 case expectedVersion.LessThan(*runningVersion): 100 return r.updateVersion(offset, *runningVersion) 101 } 102 103 return nil 104 } 105 106 // transfer performs a data transfer to the fake RPMB area, 107 // the input buffer can contain up to 256 bytes of data, n can be passed to 108 // retrieve the write counter. 109 func (r *RPMB) transfer(sector uint16, buf []byte, n *uint32, write bool) (err error) { 110 if len(buf) > rpmb.FrameLength/2 { 111 return errors.New("transfer size must not exceed 256 bytes") 112 } 113 114 if write { 115 copy(r.mem[sector][:], buf) 116 r.counter++ 117 } else { 118 copy(buf, r.mem[sector][:]) 119 } 120 121 if n != nil { 122 *n = r.counter 123 } 124 return 125 }