Skip to content

Commit

Permalink
Allow passing the witness identity counter to the Trusted Applet. (#142)
Browse files Browse the repository at this point in the history
* Remove storage from RPMB struct.

* Add fake RPMB.

* Make counter read optional for RPMB.

* Use 2D memory array for fake RPMB.

* Add sector constants and read/write for MMC blocks related to new witness identity.

* Call increment when new witness identity for both MMC and RPMB cases.

* Add RPCs for reading the witness identity counter.

* Use fake RPMB to implement the counter.

* Add identity counter to witness status data structures.

* Move identity counter out of WitnessStatus.

* Set identity counter in status.

* Fix getStatus.

* Don't need to pass in RPMB to ctl.

* Fix compilation errors.

* Add env vars for toggling fake storage to Dockerfile.

* Add back / fix fake rpmb init()
  • Loading branch information
jiggoha authored Feb 12, 2024
1 parent 5aa0efe commit b123db5
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ ARG OS_PUBLIC_KEY2
ARG GIT_SEMVER_TAG
ARG BEE
ARG DEBUG
ARG FAKE_RPMB=1
ARG FAKE_STORAGE=0

# Install dependencies.
RUN apt-get update && apt-get install -y make wget u-boot-tools binutils-arm-none-eabi
Expand All @@ -35,6 +37,8 @@ ENV LOG_ORIGIN=${LOG_ORIGIN} \
OS_PUBLIC_KEY1="/tmp/os1.pub" \
OS_PUBLIC_KEY2="/tmp/os2.pub" \
GIT_SEMVER_TAG=${GIT_SEMVER_TAG} \
FAKE_RPMB=${FAKE_RPMB} \
FAKE_STORAGE=${FAKE_STORAGE} \
BEE=${BEE} \
DEBUG=${DEBUG}

Expand Down
18 changes: 15 additions & 3 deletions trusted_os/ctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type controlInterface struct {
ota *otaBuffer
}

func getStatus() (s *api.Status) {
func (ctl *controlInterface) getStatus() (s *api.Status) {
version, _ := parseVersion(Version)

s = &api.Status{
Expand All @@ -61,8 +61,20 @@ func getStatus() (s *api.Status) {
Build: Build,
Version: version,
Runtime: fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH),
// TODO(jayhou): set IdentityCounter here.
}

rpmb := ctl.RPC.RPMB
if rpmb == nil {
log.Printf("cannot get witness identity counter because RPMB is nil")
} else {
count, err := rpmb.witnessIdentityCounter()
if err != nil {
log.Printf("cannot get witness identity counter: %v", err)
} else {
s.IdentityCounter = count
}
}

if witnessStatus != nil {
s.Witness = &api.WitnessStatus{
Identity: witnessStatus.Identity,
Expand All @@ -87,7 +99,7 @@ func (ctl *controlInterface) HandleMessage(_ []byte) (_ []byte) {
}

func (ctl *controlInterface) Status(_ []byte) (res []byte) {
res, _ = proto.Marshal(getStatus())
res, _ = proto.Marshal(ctl.getStatus())
return
}

Expand Down
20 changes: 12 additions & 8 deletions trusted_os/flash.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ import (

const (
expectedBlockSize = 512 // Expected size of MMC block in bytes
otaLimit = 31457280
taConfBlock = 0x200000
taBlockA = 0x200050
taBlockB = 0x2FD050
osConfBlock = 0x5000
osBlockA = 0x5050
osBlockB = 0x102828
batchSize = 2048

otaLimit = 31457280

taConfBlock = 0x200000
taBlockA = 0x200050
taBlockB = 0x2FD050

osConfBlock = 0x5000
osBlockA = 0x5050
osBlockB = 0x102828

batchSize = 2048
)

const (
Expand Down
17 changes: 16 additions & 1 deletion trusted_os/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package main
import (
"crypto/aes"
"crypto/sha256"
"encoding/binary"
"errors"
"log"
"net"
Expand All @@ -40,6 +41,7 @@ type RPC struct {
Storage Card
Ctx *monitor.ExecCtx
Cfg []byte
Ctl controlInterface
Diversifier [32]byte
}

Expand Down Expand Up @@ -104,7 +106,7 @@ func (r *RPC) Status(_ any, status *api.Status) error {
return errors.New("invalid argument")
}

s := getStatus()
s := r.Ctl.getStatus()
*status = *s

return nil
Expand Down Expand Up @@ -171,6 +173,19 @@ func (r *RPC) ReadRPMB(buf []byte, n *uint32) error {
return r.RPMB.transfer(taUserSector, buf, n, false)
}

// ReadIdentityCounterRPMB performs an authenticated data transfer from the card RPMB
// partition sector allocated to the witness identity counter. It returns the
// value stored in this area.
func (r *RPC) ReadIdentityCounterRPMB(_ any, counter *uint32) error {
buf := make([]byte, witnessIdentityCounterLength)
if err := r.RPMB.transfer(witnessIdentityCounterSector, buf, nil, false); err != nil {
return err
}

*counter = binary.BigEndian.Uint32(buf)
return nil
}

// DeriveKey derives a hardware unique key in a manner equivalent to PKCS#11
// C_DeriveKey with CKM_AES_CBC_ENCRYPT_DATA.
//
Expand Down
43 changes: 43 additions & 0 deletions trusted_os/rpmb.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,26 @@ import (
const (
// RPMB sector for CVE-2020-13799 mitigation
dummySector = 0

// version epoch length
versionLength = 4
// RPMB sector for OS rollback protection
osVersionSector = 1
// RPMB sector for TA rollback protection
taVersionSector = 2

// RPMB sector for TA use
taUserSector = 3
// RPMB OTP flag bank
rpmbFuseBank = 4
// RPMB OTP flag word
rpmbFuseWord = 6

// witness identity counter length - uint32
witnessIdentityCounterLength = 4
// RPMB sector for witness identity counter
witnessIdentityCounterSector = 7

diversifierMAC = "ArmoryWitnessMAC"
iter = 4096
)
Expand Down Expand Up @@ -216,3 +223,39 @@ func (r *RPMB) transfer(offset uint16, buf []byte, n *uint32, write bool) (err e

return
}

// witnessIdentityCounter gets the witness identity counter from the RPMB area.
func (r *RPMB) witnessIdentityCounter() (counter uint32, err error) {
if r.partition == nil {
return 0, errors.New("RPMB has not been initialized")
}

rBuf := make([]byte, witnessIdentityCounterLength)
if err = r.partition.Read(witnessIdentityCounterSector, rBuf); err != nil {
return 0, err
}
return binary.BigEndian.Uint32(rBuf), nil
}

// incrementWitnessIdentityCounter increments the counter in the RPMB area to
// differentiate a new witness identity.
func (r *RPMB) incrementWitnessIdentityCounter() (err error) {
if r.partition == nil {
return errors.New("RPMB has not been initialized")
}

// Read
rBuf := make([]byte, witnessIdentityCounterLength)
if err = r.partition.Read(witnessIdentityCounterSector, rBuf); err != nil {
return err
}
counter := binary.BigEndian.Uint32(rBuf)

// Increment
counter++

// Write
wBuf := make([]byte, witnessIdentityCounterLength)
binary.BigEndian.PutUint32(wBuf, counter)
return r.partition.Write(witnessIdentityCounterSector, wBuf)
}
45 changes: 40 additions & 5 deletions trusted_os/rpmb_fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,29 @@ const (
// RPMB sector for TA use
taUserSector = 3

// witness identity counter length - uint32
witnessIdentityCounterLength = 4
// RPMB sector for witness identity counter
witnessIdentityCounterSector = 4

sectorLength = 256
numSectors = 16
)

type RPMB struct {
mem [numSectors][sectorLength]byte
mem [numSectors][]byte
counter uint32
}

func newRPMB(_ Card) (*RPMB, error) {
return &RPMB{
mem: make(map[numSectors][sectorLength]byte),
}, nil
r := &RPMB{}
for i := 0; i < numSectors; i++ {
r.mem[i] = make([]byte, sectorLength)
}
return r, nil
}

func r (*RPMB) init() error {
func (r *RPMB) init() error {
return nil
}

Expand Down Expand Up @@ -135,3 +142,31 @@ func (r *RPMB) transfer(sector uint16, buf []byte, n *uint32, write bool) (err e
}
return
}

// witnessIdentityCounter gets the witness identity counter from the RPMB area.
func (r *RPMB) witnessIdentityCounter() (counter uint32, err error) {
rBuf := make([]byte, witnessIdentityCounterLength)
if err := r.transfer(witnessIdentityCounterSector, rBuf, nil, false); err != nil {
return 0, err
}
return binary.BigEndian.Uint32(rBuf), nil
}

// incrementWitnessIdentityCounter increments the counter in the RPMB area to
// differentiate a new witness identity.
func (r *RPMB) incrementWitnessIdentityCounter() error {
// Read
rBuf := make([]byte, witnessIdentityCounterLength)
if err := r.transfer(witnessIdentityCounterSector, rBuf, nil, false); err != nil {
return err
}
counter := binary.BigEndian.Uint32(rBuf)

// Increment
counter++

// Write
wBuf := make([]byte, witnessIdentityCounterLength)
binary.BigEndian.PutUint32(wBuf, counter)
return r.transfer(witnessIdentityCounterSector, wBuf, nil, true)
}

0 comments on commit b123db5

Please sign in to comment.