-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathvm_payload.h
More file actions
399 lines (368 loc) · 17.5 KB
/
Copy pathvm_payload.h
File metadata and controls
399 lines (368 loc) · 17.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/cdefs.h>
#include "vm_main.h"
__BEGIN_DECLS
typedef struct AIBinder AIBinder;
/**
* Introduced in API 35.
* Remote attestation result if the attestation succeeds.
*/
typedef struct AVmAttestationResult AVmAttestationResult;
/**
* Introduced in API 35.
* Remote attestation status types returned from remote attestation functions.
*/
typedef enum AVmAttestationStatus : int32_t {
/** The remote attestation completes successfully. */
ATTESTATION_OK = 0,
/** The challenge size is not between 0 and 64. */
ATTESTATION_ERROR_INVALID_CHALLENGE = -10001,
/** Failed to attest the VM. Please retry at a later time. */
ATTESTATION_ERROR_ATTESTATION_FAILED = -10002,
/** Remote attestation is not supported in the current environment. */
ATTESTATION_ERROR_UNSUPPORTED = -10003,
} AVmAttestationStatus;
/**
* Introduced in API 36.
* Status type used to indicate error while accessing RollbackProtectedSecret.
*/
typedef enum AVmAccessRollbackProtectedSecretStatus : int32_t {
/**
* Relevant Entry not found. This can happen either due to no value was ever written or because
* it was deleted by host.
*/
AVMACCESSROLLBACKPROTECTEDSECRETSTATUS_ENTRY_NOT_FOUND = -1,
/** Requested access size is not supported by the implementation */
AVMACCESSROLLBACKPROTECTEDSECRETSTATUS_BAD_SIZE = -2,
/** Access failed, this could be due to lacking support from Hardware */
AVMACCESSROLLBACKPROTECTEDSECRETSTATUS_ACCESS_FAILED = -3,
} AVmAccessRollbackProtectedSecretStatus;
/**
* Introduced in API 37.
* Status codes for AVmPayload_mountEncryptedAssets.
*/
typedef enum AVmMountEncryptedAssetsStatus : int32_t {
/** The operation completed successfully. */
AVMMOUNTENCRYPTEDASSETSSTATUS_OK = 0,
/**
* An invalid argument was provided. This includes but is not limited to:
* - Invalid image_path (e.g., not under APK assets, not found).
* - Unsupported fs_type or cipher.
* - Invalid sector_size (e.g., not a power of two, out of range).
* - Invalid key_size for the chosen cipher.
* - mount_point buffer being too small.
*/
AVMMOUNTENCRYPTEDASSETSSTATUS_ILLEGAL_ARGUMENT = -1,
/**
* An internal error occurred during the setup or mount process.
* This can indicate issues with loop device setup, dm-crypt mapping, or the mount system call
* itself.
*/
AVMMOUNTENCRYPTEDASSETSSTATUS_INTERNAL_ERROR = -2,
} AVmMountEncryptedAssetsStatus;
/**
* Notifies the host that the payload is ready.
*
* If the host app has set a `VirtualMachineCallback` for the VM, its
* `onPayloadReady` method will be called.
*
* Note that subsequent calls to this function after the first have no effect;
* `onPayloadReady` is never called more than once.
*/
void AVmPayload_notifyPayloadReady(void);
/**
* Runs a binder RPC server, serving the supplied binder service implementation on the unix
* domain socket.
*
* This function creates the Unix domain socket with the given name and binds it.
* Starts the server listening on the socket with the service Binder.
*
* Note that this function does not return. The calling thread joins the binder
* thread pool to handle incoming messages.
*
* \param name the null-terminated name of the unix domain socket, UTF-8 encoded.
* \param service the service to bind to the socket.
* \param on_ready the callback to execute once the server is ready for connections. If not null the
* callback will be called at most once.
* \param param parameter to be passed to the `on_ready` callback.
*/
__attribute__((noreturn)) void AVmPayload_runUnixDomainRpcServer(
const char* _Nonnull name, AIBinder* _Nonnull service,
void (*_Nullable on_ready)(void* _Nullable param), void* _Nullable param)
__INTRODUCED_IN(37);
/**
* Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
* port.
*
* If and when the server is ready for connections (it is listening on the port), `on_ready` is
* called to allow appropriate action to be taken - e.g. to notify clients that they may now
* attempt to connect with `AVmPayload_notifyPayloadReady`.
*
* Note that this function does not return. The calling thread joins the binder
* thread pool to handle incoming messages.
*
* \param service the service to bind to the given port.
* \param port vsock port.
* \param on_ready the callback to execute once the server is ready for connections. If not null the
* callback will be called at most once.
* \param param parameter to be passed to the `on_ready` callback.
*/
__attribute__((noreturn)) void AVmPayload_runVsockRpcServer(
AIBinder* _Nonnull service, uint32_t port,
void (*_Nullable on_ready)(void* _Nullable param), void* _Nullable param);
/**
* Returns all or part of a 32-byte secret that is bound to this unique VM
* instance and the supplied identifier. The secret can be used e.g. as an
* encryption key.
*
* Every VM has a secret that is derived from a device-specific value known to
* the hypervisor, the code that runs in the VM and its non-modifiable
* configuration; it is not made available to the host OS.
*
* This function performs a further derivation from the VM secret and the
* supplied identifier. As long as the VM identity doesn't change the same value
* will be returned for the same identifier, even if the VM is stopped &
* restarted or the device rebooted.
*
* If multiple secrets are required for different purposes, a different
* identifier should be used for each. The identifiers otherwise are arbitrary
* byte sequences and do not need to be kept secret; typically they are
* hardcoded in the calling code.
*
* The secret is linked to the instance & will be created for a new instance.
* Callers should check `AVmPayload_isNewInstance()` to meaningfully use the secret.
* For ex, decryption of any old data is meaningless with the returned secret of a new
* VM instance with fresh keys.
*
* \param identifier identifier of the secret to return.
* \param identifier_size size of the secret identifier.
* \param secret pointer to size bytes where the secret is written.
* \param size number of bytes of the secret to get, <= 32.
*/
void AVmPayload_getVmInstanceSecret(const void* _Nonnull identifier, size_t identifier_size,
void* _Nonnull secret, size_t size);
/**
* Gets the path to the APK contents. It is a directory, under which are
* the unzipped contents of the APK containing the payload, all read-only
* but accessible to the payload.
*
* \return the path to the APK contents. The returned string should not be
* deleted or freed by the application. The string remains valid for the
* lifetime of the VM.
*/
const char* _Nonnull AVmPayload_getApkContentsPath(void);
/**
* Gets the path to the encrypted persistent storage for the VM, if any. This is
* a directory under which any files or directories created will be stored on
* behalf of the VM by the host app. All data is encrypted using a key known
* only to the VM, so the host cannot decrypt it, but may delete it.
*
* \return the path to the encrypted storage directory, or NULL if no encrypted
* storage was requested in the VM configuration. If non-null the returned
* string should not be deleted or freed by the application and remains valid
* for the lifetime of the VM.
*/
const char* _Nullable AVmPayload_getEncryptedStoragePath(void);
/**
* Requests the remote attestation of the client VM.
*
* The challenge will be included in the certificate chain in the attestation result,
* serving as proof of the freshness of the result.
*
* \param challenge A pointer to the challenge buffer.
* \param challenge_size size of the challenge. The maximum supported challenge size is
* 64 bytes. The status ATTESTATION_ERROR_INVALID_CHALLENGE will be returned if
* an invalid challenge is passed.
* \param result The remote attestation result will be filled here if the attestation
* succeeds. The result remains valid until it is freed with
* `AVmPayload_freeAttestationResult`.
*
* \return ATTESTATION_OK upon successful attestation.
*/
AVmAttestationStatus AVmPayload_requestAttestation(const void* _Nonnull challenge,
size_t challenge_size,
AVmAttestationResult* _Nullable* _Nonnull result)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Converts the return value from `AVmPayload_requestAttestation` to a text string
* representing the status code.
*
* \return a constant string value representing the status code. The string should not
* be deleted or freed by the application and remains valid for the lifetime of the VM.
*/
const char* _Nonnull AVmAttestationStatus_toString(AVmAttestationStatus status)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Frees all the data owned by the provided attestation result, including the result itself.
*
* Callers should ensure to invoke this API only once on a valid attestation result
* returned by `AVmPayload_requestAttestation` to avoid undefined behavior.
*
* \param result A pointer to the attestation result.
*/
void AVmAttestationResult_free(AVmAttestationResult* _Nullable result)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Reads the DER-encoded ECPrivateKey structure specified in [RFC 5915 s3] for the
* EC P-256 private key from the provided attestation result.
*
* \param result A pointer to the attestation result filled in
* `AVmPayload_requestAttestation` when the attestation succeeds.
* \param data A pointer to the memory where the private key will be written
* (can be null if size is 0).
* \param size The maximum number of bytes that can be written to the data buffer.
* If `size` is smaller than the total size of the private key, the key data will be
* truncated to this `size`.
*
* \return The total size of the private key.
*
* [RFC 5915 s3]: https://datatracker.ietf.org/doc/html/rfc5915#section-3
*/
size_t AVmAttestationResult_getPrivateKey(const AVmAttestationResult* _Nonnull result,
void* _Nullable data, size_t size)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Signs the given message using ECDSA P-256, the message is first hashed with SHA-256 and
* then it is signed with the attested EC P-256 private key in the attestation result.
*
* \param result A pointer to the attestation result filled in
* `AVmPayload_requestAttestation` when the attestation succeeds.
* \param message A pointer to the message buffer.
* \param message_size size of the message.
* \param data A pointer to the memory where the signature will be written
* (can be null if size is 0). The signature is a DER-encoded ECDSASignature structure
* detailed in the [RFC 6979].
* \param size The maximum number of bytes that can be written to the data buffer.
* If `size` is smaller than the total size of the signature, the signature will be
* truncated to this `size`.
*
* \return The size of the signature, or the size needed if the supplied buffer is too small.
*
* [RFC 6979]: https://datatracker.ietf.org/doc/html/rfc6979
*/
size_t AVmAttestationResult_sign(const AVmAttestationResult* _Nonnull result,
const void* _Nonnull message, size_t message_size,
void* _Nullable data, size_t size)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Gets the number of certificates in the certificate chain.
*
* The certificate chain consists of a sequence of DER-encoded X.509 certificates that form
* the attestation key's certificate chain. It starts with a leaf certificate covering the attested
* public key and ends with a root certificate.
*
* \param result A pointer to the attestation result obtained from `AVmPayload_requestAttestation`
* when the attestation succeeds.
*
* \return The number of certificates in the certificate chain.
*/
size_t AVmAttestationResult_getCertificateCount(const AVmAttestationResult* _Nonnull result)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Retrieves the certificate at the given `index` from the certificate chain in the provided
* attestation result.
*
* The certificate chain consists of a sequence of DER-encoded X.509 certificates that form
* the attestation key's certificate chain. It starts with a leaf certificate covering the attested
* public key and ends with a root certificate.
*
* \param result A pointer to the attestation result obtained from `AVmPayload_requestAttestation`
* when the attestation succeeds.
* \param index Index of the certificate to retrieve. The `index` must be within the range of
* [0, number of certificates). The number of certificates can be obtained with
* `AVmAttestationResult_getCertificateCount`.
* \param data A pointer to the memory where the certificate will be written
* (can be null if size is 0).
* \param size The maximum number of bytes that can be written to the data buffer. If `size`
* is smaller than the total size of the certificate, the certificate will be
* truncated to this `size`.
*
* \return The total size of the certificate at the given `index`.
*/
size_t AVmAttestationResult_getCertificateAt(const AVmAttestationResult* _Nonnull result,
size_t index, void* _Nullable data, size_t size)
__INTRODUCED_IN(__ANDROID_API_V__);
/**
* Writes up to n bytes from buffer starting at `buf`, on behalf of the payload, to rollback
* detectable storage. The data is written from the start. The number of bytes written may be less
* than n if, for example, the underlying storage has size constraints. This stored data is
* confidential to the VM instance.
*
* \param buf A pointer to data to be written. This should have the size of at least n bytes.
* \param n The maximum number of bytes to be filled in `buf`.
*
* \return On success, the number of bytes written is returned. On error, appropriate
* AVmAccessRollbackProtectedSecretStatus (negative number) is returned.
*/
int32_t AVmPayload_writeRollbackProtectedSecret(const void* _Nonnull buf, size_t n)
__INTRODUCED_IN(36);
/**
* Read the first n bytes of payload's data in rollback detectable storage into `buf`.
*
* \param buf A pointer to buffer where the requested data is written. This should have the size of
* at least n bytes.
* \param n The maximum number of bytes to be read.
*
* \return On success, the number of bytes that would have been written to `buf` if n was
* sufficiently large. On error, appropriate AVmAccessRollbackProtectedSecretStatus(a negative
* number) is returned.
*/
int32_t AVmPayload_readRollbackProtectedSecret(void* _Nullable buf, size_t n) __INTRODUCED_IN(36);
/**
* Checks whether the VM instance is new - i.e., if this is the first run of an instance.
* This is an indication of fresh new VM secrets. Payload can use this to setup the fresh
* instance if needed.
*
* \return true if this is the first run of an instance, false otherwise.
*/
bool AVmPayload_isNewInstance(void) __INTRODUCED_IN(36);
/**
* Creates a dm-crypt mapping over an encrypted image file and mounts the contained filesystem.
*
* This function allows a payload to mount a read-only filesystem image that is encrypted.
* The image must be located within the APK's assets directory.
* The filesystem is mounted read-only and executable.
*
* See also https://docs.kernel.org/admin-guide/device-mapper/dm-crypt.html for detailed information
* about the related parameters.
*
* \param image_path Absolute path to the encrypted filesystem image file, UTF-8 encoded.
* Must be under the APK assets directory.
* \param fs_type The filesystem type of the image, UTF-8 encoded.
* Currently only "erofs" is supported.
* \param cipher The encryption cipher to use for dm-crypt, UTF-8 encoded.
* Supported values are "aes-xts-plain64" and "aes-hctr2-plain64".
* \param key Pointer to the raw encryption key bytes.
* \param key_size Size of the encryption key in bytes.
* \param sector_size The logical sector size of the block device in bytes.
* Must be a power of two between 512 and 4096.
* \param mount_point Output buffer to write the null-terminated absolute path of the mount point,
* UTF-8 encoded.
* \param mount_point_size Size of the mount_point buffer, should be at least `PATH_MAX`.
*
* \return AVMMOUNTENCRYPTEDASSETSSTATUS_OK on success,
* or a negative error code in AVmMountEncryptedAssetsStatus on failure.
*/
AVmMountEncryptedAssetsStatus AVmPayload_mountEncryptedAssets(
const char* _Nonnull image_path, const char* _Nonnull fs_type, const char* _Nonnull cipher,
const void* _Nonnull key, size_t key_size, int32_t sector_size, char* _Nonnull mount_point,
size_t mount_point_size) __INTRODUCED_IN(37);
__END_DECLS