github.com/transparency-dev/armored-witness-applet@v0.1.1/trusted_applet/internal/update/rpc/update_client.go (about) 1 // Copyright 2023 The Armored Witness Applet 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 // Package rpc provides an RPC-based update client. 16 package rpc 17 18 import ( 19 "github.com/coreos/go-semver/semver" 20 "github.com/transparency-dev/armored-witness-boot/config" 21 "github.com/transparency-dev/armored-witness-common/release/firmware" 22 "github.com/transparency-dev/armored-witness-os/api/rpc" 23 "github.com/usbarmory/GoTEE/syscall" 24 "k8s.io/klog/v2" 25 ) 26 27 const fwUpdateChunkSize = 1 << 20 28 29 // Client is an implementation of the Local interface which uses RPCs to the TrustedOS 30 // to perform the updates. 31 type Client struct { 32 } 33 34 // GetInstalledVersions returns the semantic versions of the OS and Applet 35 // installed on this device. These will be the same versions that are 36 // currently running. 37 func (r Client) GetInstalledVersions() (os, applet semver.Version, err error) { 38 iv := &rpc.InstalledVersions{} 39 err = syscall.Call("RPC.GetInstalledVersions", nil, iv) 40 return iv.OS, iv.Applet, err 41 42 } 43 44 // InstallOS updates the OS to the version contained in the firmware bundle. 45 // If the update is successful, the RPC will not return. 46 func (r Client) InstallOS(fb firmware.Bundle) error { 47 return sendChunkedUpdate("OS", "RPC.InstallOS", fb) 48 } 49 50 // InstallApplet updates the Applet to the version contained in the firmware bundle. 51 // If the update is successful, the RPC will not return. 52 func (r Client) InstallApplet(fb firmware.Bundle) error { 53 return sendChunkedUpdate("applet", "RPC.InstallApplet", fb) 54 } 55 56 // sendChunkedUpdate sends a chunked OS or Applet firmware update request via one or 57 // more RPCs to the OS. 58 func sendChunkedUpdate(t string, rpcName string, fb firmware.Bundle) error { 59 klog.Infof("Requesting %s install from OS...", t) 60 fu := &rpc.FirmwareUpdate{} 61 for i := uint(0); ; i++ { 62 fu.Sequence = i 63 size := fwUpdateChunkSize 64 if rem := len(fb.Firmware); size >= rem { 65 fu.Proof = config.ProofBundle{ 66 Checkpoint: fb.Checkpoint, 67 LogIndex: fb.Index, 68 InclusionProof: fb.InclusionProof, 69 Manifest: fb.Manifest, 70 } 71 size = rem 72 } 73 fu.Image = fb.Firmware[:size] 74 fb.Firmware = fb.Firmware[size:] 75 klog.Infof("Sending %s chunk %d", t, i) 76 if err := syscall.Call(rpcName, fu, nil); err != nil { 77 return err 78 } 79 } 80 } 81 82 // Reboot instructs the device to reboot after new firmware is installed. 83 // This call will not return and deferred functions will not be run. 84 func (r Client) Reboot() { 85 _ = syscall.Call("RPC.Reboot", nil, nil) 86 }