[client-vm] Build client VM CSR and sign the CSR with two keys
This cl builds the CSR that a client VM sends to the RKP VM for
remote attestation and adjusted the API accordingly as discussed
in the doc go/pvm-remote-attestation
The CSR payload is signed with both the CDI_Leaf_Priv of the
client VM's DICE chain and the attestation key. RKP VM should
verify the signature later with the CDI_Leaf_Pub extracted
from the same DICE chain in the CSR and the attestation public
key.
The new unit tests are added to config at cl/577763874.
Bug: 303807447
Test: run ServiceVmClientTestApp
Test: atest libservice_vm_comm.test
Test: atest microdroid_manager_test
Change-Id: Ic2c09e7339d9981edda028e2694fa551c911a274
diff --git a/vm_payload/include/vm_payload.h b/vm_payload/include/vm_payload.h
index c28cd42..2dfa2cb 100644
--- a/vm_payload/include/vm_payload.h
+++ b/vm_payload/include/vm_payload.h
@@ -30,6 +30,27 @@
typedef struct AIBinder AIBinder;
/**
+ * Introduced in API 35.
+ * Remote attestation result if the attestation succeeds.
+ */
+struct AVmAttestationResult;
+
+/**
+ * Introduced in API 35.
+ * Remote attestation status types returned from remote attestation functions.
+ */
+typedef enum attestation_status_t : int32_t {
+ /** The remote attestation completes successfully. */
+ ATTESTATION_OK = 0,
+
+ /** The remote attestation has failed due to an unspecified cause. */
+ ATTESTATION_UNKNOWN_ERROR = -10000,
+
+ /** The challenge size is not between 0 and 64. */
+ ATTESTATION_ERROR_INVALID_CHALLENGE = -10001,
+} attestation_status_t;
+
+/**
* Notifies the host that the payload is ready.
*
* If the host app has set a `VirtualMachineCallback` for the VM, its
@@ -112,4 +133,129 @@
*/
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.
+ */
+attestation_status_t AVmPayload_requestAttestation(
+ const void* _Nonnull challenge, size_t challenge_size,
+ struct 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 AVmAttestationResult_resultToString(attestation_status_t 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(struct 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 struct 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 total size of the signature.
+ *
+ * [RFC 6979]: https://datatracker.ietf.org/doc/html/rfc6979
+ */
+size_t AVmAttestationResult_sign(const struct 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 root certificate and ends with a
+ * leaf certificate covering the attested public key.
+ *
+ * \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 struct 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 root certificate and ends with a
+ * leaf certificate covering the attested public key.
+ *
+ * \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 struct AVmAttestationResult* _Nonnull result,
+ size_t index, void* _Nullable data, size_t size)
+ __INTRODUCED_IN(__ANDROID_API_V__);
+
__END_DECLS