blob: 4161f0d15116805871eab00e106502885a4981cf [file] [log] [blame]
Julian Halle76ade82020-11-25 03:07:21 +01001Service Access Protocols
2========================
3
4A trusted service is accessed by calling service-specific methods via an RPC mechanism. The set of callable methods forms the
5public interface exposed by a service. This section is concerned with interface conventions and protocols used for serializing
6method parameters and return values. It is anticipated that there will be a need to support different parameter serialization
7schemes to suite different needs. The project accommodates this with the following:
8
9 - The Protocols directory structure allows for different protocol definitions for the same service.
10 - Message serialization code is decoupled from service provider code using an abstract 'serializer' interface. Alternative
11 concrete serializers may provide implementations of the interface.
12
13RPC Session
14-----------
15
16Before a client can call trusted service methods, an RPC session must be established where an association is made between an RPC
17Caller and a call endpoint that corresponds to the required service provider instance. To establish the session, the client
18must provide:
19
20 - An identifier for the service provider instance.
21 - Any client credentials that allow RPC layer access control to be applied if needed.
22
23.. uml:: uml/RpcSessionClassDiagram.puml
24
25Once the RPC session is established, the client may call service methods via an abstract RPC Caller interface that takes the
26following parameters:
27
28 - The opcode that identifies the method to call.
29 - A buffer for the serialized method parameters.
30 - A buffer for the serialized return values.
31
32A deployment independent interface for locating services and establishing RPC sessions is described here: :ref:`Service Locator`
33
34Status Codes
35------------
36
37On returning from a request to invoke a service method, two status codes are returned as follows:
38
39 - *RPC status* - A generic status code that corresponds to the RPC call transaction. RPC status codes are standardized across
40 all services.
41 - *Operation status* - a service specific status code.
42
43Separation of status codes by layer allows service specific status codes to be accommodated while keeping RPC status codes
44common.
45
46A client should only check the returned operation status if the returned RPC status value is RPC_CALL_ACCEPTED. All other RPC
47status values indicate that an error occurred in delivering the RPC request. An RPC status of RPC_CALL_ACCEPTED does not
48indicate that the service operation was successful. It merely indicates that the request was delivered, a suitable handler was
49identified and the request parameters were understood.
50
51Service Access Protocol Definition Conventions
52----------------------------------------------
53
54A service access protocol defines the following:
55
56 - Opcodes used for identifying service methods.
57 - Request parameters for each method.
58 - Response parameters for method return values.
59 - Operation status code.
60
61Details of how public interface definition files for trusted services are organized, see: :ref:`Project Structure`
62
63It is possible that for certain deployments, it will be necessary to customize which parameter encoding scheme is used. Many
64schemes are possible such as Protocol Buffers, CBOR, JSON, TLV, TPM commands or packed C structures. To make scheme
65customization straight forward, serilize/deserialize operations should be encapsulated behind a common interface to decouple
66service provider code from any particular serialization scheme. A section below describes a pattern for achieving this.
67
68Service Namespace
69'''''''''''''''''
70
71Definitions that form a service access protocol should live within a namespace that is unique for the particular service. Using
72a namespace for service definitions avoids possible clashes between similarly named definitions that belong to different
73services. How the namespace is implemented depends on how the access protocol is defined. For example, the Protocol Buffers
74definitions for the crypto service all live within the ts_crypto package. The recommended convention for forming a trusted
75service namespace is as follows::
76
77 ts_<service_name>
78
79 e.g.
80 ts_crypto
81 ts_secure_storage
82
83Language Independent Protocol Definitions
84'''''''''''''''''''''''''''''''''''''''''
85
86By defining service access protocols using an interface description language (IDL) with good support for different programming
87languages, it should be straight forward to access trusted services from clients written in a range of languages. On Arm
88Cortex-A deployments, it is common for user applications to be implemented using a range of languages such as Go, Python or
89Java. Rather than relying on a binding to a C client library, native client code may be generated from the formal protocol
90definition files. Initial protocol definitions use Google Protocol Buffers as the IDL. The project structure allows for use of
91alternative definition schemes and serializations.
92
93Opcode Definition
94`````````````````
95
96Opcodes are integer values that identify methods implemented by a service endpoint. Opcodes only need to be unique within the
97scope of a particular service. The mapping of opcode to method is an important part of a service interface definition and
98should be readily available to clients written in a variety of programming languages. For a Protocol Buffers based definition,
99opcodes are defined in a file called::
100
101 opcodes.proto
102
103For example, for the Crypto trusted service, the Protocol Buffers opcode definitions are in::
104
105 protocols/service/crypto/protobuf/opcodes.proto
106
107Alternative definitions for light-weight C clients using the packed-c scheme are in::
108
109 protocols/service/crypto/packed-c/opcodes.h
110
111Parameter Definition
112````````````````````
113
114The convention used for serializing method parameters and return values may be specific to a particular service. The definition
115file will include message definitions for both request and response parameters. Common objects that are used for multiple
116methods should be defined in separate files. When using Protobufs, the following naming convention for method parameter files
117should be used::
118
119 <method_name>.proto
120
121For example, the Crypto export_public_key method is defined in a file called::
122
123 protocols/service/crypto/protobuf/export_public_key.proto
124
125RPC Status Codes
126````````````````
127
128Generic RPC status code definitions using different definition schemes are defined here::
129
130 protocols/rpc/common/protobuf/status.proto
131 protocols/rpc/common/packed-c/status.h
132
133Service Status Codes
134````````````````````
135
136Service specific status code definitions using different definition schemes are defined here (using crypto service as an
137example)::
138
139 protocols/service/crypto/protobuf/status.proto
140 protocols/service/crypto/packed-c/status.h
141
142Status code definitions may also be shared between services. For example, services that conform to PSA API conventions will use
143standardized PSA status codes, defined here::
144
145 protocols/service/psa/protobuf/status.proto
146 protocols/service/psa/packed-c/status.h
147
148Use of Protocol Buffers
149-----------------------
150
151When Protocol Buffers is used for protocol definition and parameter serialization, the following conventions have been adopted.
152
153.proto File Style Guide
154'''''''''''''''''''''''
155
156The style of the .proto files should follow Google's Protocol Buffers Style Guide.
157
158Protocol Buffer Library for Trusted Services
159''''''''''''''''''''''''''''''''''''''''''''
160
161Protocol Buffers standardizes how service interfaces are defined and the on-wire encoding for messages. Because of this, service
162clients and service providers are free to use any conformant implementation. However for trusted services that may be deployed
163across a range of environments, some of which may be resource constrained, a lightweight library should be used for C/C++ code
164that implement or use trusted services. For this purpose, Nanobp (https://github.com/nanopb/nanopb) should be used.
165
166Serialization Protocol Flexibility
167----------------------------------
168
169Many different serialization protocols exist for encoding and decoding message parameters. Hard-wiring a particular protocol
170into a trusted service provider implementation isn't desirable for the following reasons:
171
172 - Depending on the complexity of serialization operations, mixing serialization logic with protocol-independent code makes
173 trusted service provider code bigger and more difficult to maintain.
174 - Different protocols may be needed for different deployments. It should be possible to make a build-time or even a
175 run-time selection of which protocol to use.
176 - The number of supported serializations protocols is likely to grow. Adding a new protocol shouldn't require you to make
177 extensive code changes and definitely shouldn't break support for existing protocols.
178
179These problems can be avoided by implementing protocol specific operations behind a common interface. Serialize/deserialize
180operations will have the following pattern::
181
182 int serialize_for_method(msg_buffer *buf, in args...);
183 int deserialize_for_method(const msg_buffer *buf, out args...);
184
185To extend a service provider to support a new serialization encoding, the following steps are required:
186
187 1. Define a new encoding identifier string if a suitable one doesn't exist. Currently used identifiers are protobuf and
188 packed-c. The identifier will be used as a directory name so it needs to be filename-friendly. Some likely candidate
189 identifiers could be cbor and json.
190 2. Add a new RPC encoding ID to *protocols/rpc/common/packed-c/encoding.h*. This is used by a caller to identify the encoding
191 used for RPC parameters. This is analogous to the content-type header parameter used in HTTP.
192 3. Under the protocols parent directory, add a new access protocol definition for the service that needs extending. This will
193 be a representation of existing service access protocols but using a definition notation compatible with the new encoding.
194 4. Add a new serializer implementation under the service provider's serializer directory e.g. for the crypto service -
195 *components/service/crypto/provider/serializer*.
196 5. Add registration of the new serializer to any deployment initialization code where the new encoding is needed.
197
198--------------
199
200*Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.*
201
202SPDX-License-Identifier: BSD-3-Clause