| // Copyright 2023 Google LLC |
| // |
| // 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. |
| |
| syntax = "proto3"; |
| |
| package fcp.confidentialcompute; |
| |
| import "google/protobuf/any.proto"; |
| import "proto/micro_rpc/options.proto"; |
| |
| // An interface for a service that transforms data in some way, e.g. as part of |
| // a data processing pipeline. If these services run within externally- |
| // verifiable enclaves, they can be used in combination with a Ledger to |
| // implement externally-verifiable data pipelines. |
| // |
| // This service defines the API for a transform's Oak enclave app. The service |
| // definition is compatible with the Oak microRPC libraries: |
| // https://github.com/project-oak/oak/tree/main/micro_rpc. |
| service PipelineTransform { |
| // Performs configuration of the service that overwrites previous |
| // configuration provided to Initialize or to this method, and attests the |
| // configuration. |
| // This method can be skipped and an attestation previously returned by this |
| // method can be used if the configuration is unchanged. Skipping this method |
| // when the configuration is unchanged minimizes the amount of data that needs |
| // to be sent through the TEE boundary. |
| // method_id: 3 |
| rpc ConfigureAndAttest(ConfigureAndAttestRequest) |
| returns (ConfigureAndAttestResponse) { |
| option (.oak.micro_rpc.method_id) = 3; |
| } |
| |
| // Generates a specified number of nonces that will be used as associated data |
| // to ensure that a given encrypted record is processed exactly once by a |
| // Transform call. For each nonce generated by this method, a single encrypted |
| // record can can be processed successfully by Transform. |
| // method_id: 4 |
| rpc GenerateNonces(GenerateNoncesRequest) returns (GenerateNoncesResponse) { |
| option (.oak.micro_rpc.method_id) = 4; |
| } |
| |
| // Transforms zero or more inputs into zero or more outputs. This method can |
| // be used to implement map (1 -> 1), filter (1 -> 0 or 1), combine (N -> |
| // 1), "do" (1 -> N), or more general (M -> N) operations. |
| // method_id: 2 |
| rpc Transform(TransformRequest) returns (TransformResponse) { |
| option (.oak.micro_rpc.method_id) = 2; |
| } |
| } |
| |
| message ConfigureAndAttestRequest { |
| // Implementation-specific configuration that will override any previous |
| // configuration provided to this method. |
| google.protobuf.Any configuration = 1; |
| } |
| |
| message ConfigureAndAttestResponse { |
| // The CBOR Web Token (CTW; RFC 8392) containing the enclave's public key. The |
| // CWT will contain all the claims and properties required by |
| // `fcp.confidentialcompute.AuthorizeAccessRequest.recipient_public_key`. A |
| // new keypair will be generated whenever the ConfigureAndAttest method is |
| // called with a new configuration. The following additional CWT claims may be |
| // present: |
| // -65538: google.protobuf.Struct containing app-specific config properties |
| bytes public_key = 1; |
| |
| reserved 2, 3; |
| } |
| |
| message GenerateNoncesRequest { |
| // The number of nonces to generate. Each nonce corresponds to a single record |
| // that can be decrypted and processed. |
| int32 nonces_count = 1; |
| } |
| |
| message GenerateNoncesResponse { |
| // Nonces used by the sealed worker application to ensure the same data |
| // access authorized by the ledger cannot be replayed multiple times by a |
| // portion of the stack running outside a Trusted Execution Environment to |
| // cause it to process the same data multiple times. The nonces will be saved |
| // by the sealed worker application, and the sealed application will discard |
| // each one after using it once as part of the associated data to decrypt the |
| // symmetric key, ensuring that another request must be made to the ledger in |
| // order to process the same data again. The number of nonces will match |
| // `nonces_count` in the request. |
| repeated bytes nonces = 3; |
| } |
| |
| // A request providing the inputs to be transformed. |
| message TransformRequest { |
| repeated Record inputs = 1; |
| } |
| |
| // A response providing the results of the transformation. |
| message TransformResponse { |
| repeated Record outputs = 1; |
| |
| // The number of input records that were ignored due to being invalid. |
| int32 num_ignored_inputs = 2; |
| } |
| |
| // A data record used as one of the inputs or outputs of a transform. |
| message Record { |
| oneof kind { |
| bytes unencrypted_data = 1 |
| ; |
| HpkePlusAeadData hpke_plus_aead_data = 2; |
| } |
| |
| // Describes the type of data-unaware compression that has been applied prior |
| // to any encryption. |
| enum CompressionType { |
| COMPRESSION_TYPE_UNSPECIFIED = 0; |
| // No compression was applied. |
| COMPRESSION_TYPE_NONE = 1; |
| // GZIP compression was applied. |
| COMPRESSION_TYPE_GZIP = 2; |
| } |
| |
| CompressionType compression_type = 3; |
| |
| // Information about plaintext encrypted with AEAD, with the symmetric key |
| // then encrypted with HPKE. |
| message HpkePlusAeadData { |
| // The data, encrypted using AES-128-GCM. |
| bytes ciphertext = 1; |
| |
| // The associated data for `ciphertext`. |
| bytes ciphertext_associated_data = 2; |
| |
| // The symmetric key used to encrypt `ciphertext`, encrypted using HPKE. |
| // The key is encoded as a COSE_Key struct (RFC 9052); at least the |
| // following algorithms should be supported: |
| // -65538: AEAD_AES_128_GCM_SIV (fixed nonce) |
| bytes encrypted_symmetric_key = 3; |
| |
| // The associated data for `encrypted_symmetric_key`. |
| oneof symmetric_key_associated_data_components { |
| LedgerAssociatedData ledger_symmetric_key_associated_data = 6; |
| RewrappedAssociatedData rewrapped_symmetric_key_associated_data = 7; |
| } |
| |
| // The ephemeral Diffe-Hellman key needed to derive the symmetric key used |
| // to encrypt `encrypted_secret_key`. |
| bytes encapsulated_public_key = 5; |
| |
| // Components which will be appended together to create the associated data |
| // to be used for decryption of the symmetric key by the Ledger so that it |
| // can check the policy and grant access to worker components. |
| message LedgerAssociatedData { |
| // A serialized `fcp.confidentialcompute.BlobHeader`. |
| bytes record_header = 1; |
| } |
| |
| // Components which will be appended together to create the associated data |
| // to be used for decryption of the symmetric key by a sealed worker |
| // application after the Ledger has checked the policy and rewrapped the |
| // symmetric key for access by the worker. |
| message RewrappedAssociatedData { |
| // If the application will be re-encrypting its output, the CWT for the |
| // public key to use. The CWT has the same required claims and parameters |
| // as `fcp.confidentialcompute.CreateKeyResponse.public_key`. Reusing the |
| // same public key as the input ensures that derived objects have the same |
| // expiration time as the original data. This key can be ignored if the |
| // application doesn't encrypt its outputs (e.g., because it produces |
| // anonymized aggregate results). |
| bytes reencryption_public_key = 1; |
| |
| // Unique nonce for this record to protect against replay attacks by an |
| // unsealed portion of the stack. The sealed worker application will |
| // ensure that it has not already used the nonce before decrypting and |
| // processing the data. |
| bytes nonce = 2; |
| } |
| |
| reserved 4; |
| } |
| } |