Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow passing the witness identity counter to the Trusted Applet. #142

Merged
merged 20 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ ARG OS_PUBLIC_KEY1
ARG OS_PUBLIC_KEY2
ARG GIT_SEMVER_TAG
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 @@ -34,6 +36,8 @@ ENV LOG_ORIGIN=${LOG_ORIGIN} \
OS_PUBLIC_KEY1="/tmp/os1.pub" \
OS_PUBLIC_KEY2="/tmp/os2.pub" \
GIT_SEMVER_TAG=${GIT_SEMVER_TAG} \
DEBUG=${DEBUG}
DEBUG=${DEBUG} \
FAKE_RPMB=${FAKE_RPMB} \
FAKE_STORAGE=${FAKE_STORAGE}

RUN make trusted_os_release
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 @@ -211,3 +218,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)
}
41 changes: 39 additions & 2 deletions trusted_os/rpmb_fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,26 @@ 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{}, nil
r := &RPMB{}
jiggoha marked this conversation as resolved.
Show resolved Hide resolved
for i := 0; i < numSectors; i++ {
r.mem[i] = make([]byte, sectorLength)
}
return r, nil
}

func parseVersion(s string) (version uint32, err error) {
Expand Down Expand Up @@ -130,3 +139,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)
}
Loading