Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design an attestation syscall #966

Closed
haraldh opened this issue Oct 1, 2020 · 17 comments
Closed

Design an attestation syscall #966

haraldh opened this issue Oct 1, 2020 · 17 comments
Assignees

Comments

@haraldh
Copy link
Member

haraldh commented Oct 1, 2020

Attestation Syscall - User Space

syscall number 0xEA01

NAME

get_attestation - get the attestation from the CPU

SYNOPSIS

For C

ssize_t get_attestation(void *nonce, size_t nonce_length, void *buf, size_t buf_length, size_t *technology);

Note: a C wrapper has to store the second return value in rdx into technology and a negative rax in errno.

RETURN VALUE

On error a negative number is returned as -errno.

On success, this call returns the number of bytes placed in buf.

technology is filled in with

value TEE technology identifier
0 NONE
1 SEV
2 SGX

LOW LEVEL INTERFACE

Inputs

  1. rdi - input data buffer (const)
  2. rsi - input data buffer length
  3. rdx - output data buffer
  4. r10 - output data buffer length

Outputs

  1. rax - number of bytes written or negative errno (per Linux convention)
  2. rdx - TEE technology identifier (enum)

Special Case

When rdx (input) is 0 (i.e. NULL):

  • r10 is ignored
  • no data is written (since the buffer is non-existent)
  • other outputs are the same as if the call had succeeded with a large enough buffer

Format of buf

Serialization is done on the host and deserialization is done in the Wasmtime code payload. Both have access to full std, so
all features of serde should be used to ensure a safe data transfer from the untrusted host data.

rdx or technology from thegetatt() call decides which of the union members to use.

Example union for buf:

#[repr(C)]
pub union Attestation {
    Sev_PrivateKeyInfo,
    Sgx_Attestation,
    // … to be extended
}

Suggested serde formats:

  • json - best maintained - most languages have bindings
  • cbor - smaller transfer - standardized, a lot of languages have bindings
  • bincode - smaller transfer

ERRORS

EFAULT: buf extends outside the process's allocated address space.

EINVAL: bufsiz is not positive.

EIO: an error occurred getting the attestation

EMSGSIZE: provided buffer too small

Attestation Syscall - Shim to Host

Because the method of attestation differs for every architecture, the internal syscall handling differs for each.

SEV - pre attestation - Shim

buf provided to the host is the shim physical address, where the host places encrypted bytes received from the tenant.
This is not an address in the unencrypted sallyport::Block.

The shim validates the returned slice length and copies the buf from encrypted address space to the userspace buf.

SEV - pre attestation - Host

The Loader gets a private key (encrypted with the attestation) from the tenant and places the encrypted bytes
at the address given by the shim.

SGX - post attestation - Shim

No special handling besides the usual is needed.

SGX - post attestation - Host

The Loader requests the attestation with the nonce included and places the result at the address given by the shim.

@haraldh
Copy link
Member Author

haraldh commented Oct 1, 2020

@npmccallum you know more about the preferred key / cert formats

@npmccallum
Copy link
Member

  1. I think we should structure the syscall so that the shims avoid parsing altogether. The wasmldr payload has full std access. So we can do any parsing we need there. If we do this right, the shims don't need to gain any dependencies.

  2. The syscall input should be an opaque byte array that will be included in the attestation report. In the pre-attestation case, this input will be ignored.

  3. The syscall should output a tagged union containing one of the following outputs types:

    1. SGX: An opaque blob containing the platform specific attestation type.
    2. SEV: A DER-encoded RFC 5208 PrivateKeyInfo
  4. In the pre-attestation cases (i.e. SEV, PEF), it is the responsibility of the tenant to deliver a valid, DER-encoded RFC 5208 PrivateKeyInfo. For example, under SEV this data structure will be delivered via LAUNCH_SECRET. The SEV shim merely needs to deal with an opaque byte slice.

cc @ueno @connorkuehl @lkatalin

@npmccallum
Copy link
Member

@ueno @simo5 Could you review the choice of PrivateKeyInfo here? Is this the right data type for transferring a private key from the tenant to the keep (so that it can be used as the basis for an X.509 certificate?

@simo5
Copy link

simo5 commented Oct 1, 2020

Not everybody likes to use ASN.1/DER, but from the POV of an interface having a standard and extensible format is definitely a good thing. I expect this to be extended relatively soon for PQC private key definitions as soon as they get standardized by a standards body after NIST's competition has winners. And this format should allow to describe those too.

@haraldh
Copy link
Member Author

haraldh commented Oct 2, 2020

@npmccallum - fixed...

You are right, we can treat the buffers as opaque byte slices in the shims. Only the Loader and the Payload (wasmtime) need to share a serde enum.

@ueno
Copy link
Contributor

ueno commented Oct 2, 2020

Using PrivateKeyInfo seems like a sensible choice (flexible enough and encoding overhead is nonsignificant).

so that it can be used as the basis for an X.509 certificate?

Is my understanding correct that the private key is used sorely for signing a Wasm workload?

@haraldh
Copy link
Member Author

haraldh commented Oct 2, 2020

To be discussed:

Should the data be consumable from C?

@npmccallum
Copy link
Member

Not everybody likes to use ASN.1/DER, but from the POV of an interface having a standard and extensible format is definitely a good thing. I expect this to be extended relatively soon for PQC private key definitions as soon as they get standardized by a standards body after NIST's competition has winners. And this format should allow to describe those too.

@simo5 Agreed. In this case, the private key delivered over this mechanism becomes the foundation for a self-signed TLS cert. So we don't really have a choice about ASN.1/DER.

@simo5
Copy link

simo5 commented Oct 2, 2020

If it is a self-signed cert you are after ... why don't you just generate the private key in the keep and share out the certificate with the public key ?
I would think sharing a symmetric key would be more useful if what you are after is secure communication, you can use symmetric keys with TLS-PSK.

@npmccallum
Copy link
Member

Is my understanding correct that the private key is used sorely for signing a Wasm workload?

No. Enarx deployment is three-phase:

  1. Provisioning - Tenant <=> Host - bring up an empty Keep (pre-attestation happens here)
  2. Deployment - Tenant <=> Keep - populate the Keep with wasm code and data (post-attestation happens here)
  3. Execution - execute the provided code

During the deployment phase is where the tenant validates the attestation (before delivering code and data). All of the necessary data for the tenant to validate the host attestation is contained in the Keep's TLS certificate. This comes in two flavors.

In the pre-attestation flavor, the tenant securely delivered the private key to the keep during the provisioning phase. Therefore, the tenant knows the public key of the TLS certificate it expects.

In the post-attestation flavor, the per-hardware attestation metadata is contained in an X.509 certificate extension. The tenant can validate that the attestation metadata is (1) valid and (2) bound to the Keep's public key. This proves that the private key for the Keep's certificate was generated inside a hardware enforced keep.

In short, the PrivateKeyInfo is essentially a keypair generated by the tenant and delivered to the Keep through the secure attestation process for use in a TLS certificate governing all future tenant/Keep communications.

@npmccallum
Copy link
Member

npmccallum commented Oct 2, 2020

If it is a self-signed cert you are after ... why don't you just generate the private key in the keep and share out the certificate with the public key ?

That's basically what we do in the post-attestation case. This depends on the ability to bind the public key to the attestation process. For pre-attestation, the attestation process concludes before the Keep is executing. Therefore, there is no opportunity to generate a keypair before attestation concludes. Both AMD SEV (pre-SNP) and IBM POWER PEF are pre-attestation workflows.

I would think sharing a symmetric key would be more useful if what you are after is secure communication, you can use symmetric keys with TLS-PSK.

This would be in some regards simpler. However, it also means that the tenant has to keep a secret as state versus keeping public key material as state. Disclosure of a symmetric key means that anyone can spoof a Keep to that tenant. The idea here is that the tenant generates the keypair, delivers the private key and then retains only the public key. This reduces the attack surface under the conditions that the attacker has the ability to read tenant state.

(Keep in mind that this state might be stored in something like etcd.)

@npmccallum
Copy link
Member

npmccallum commented Oct 2, 2020

To be discussed:

Should the data be consumable from C?

Yes. I propose the following syscall interface:

Inputs

  1. rdi - input data buffer (const)
  2. rsi - input data buffer length
  3. rdx - output data buffer
  4. r10 - output data buffer length

Outputs

  1. rax - number of bytes written or negative errno (per Linux convention)
  2. rdx - TEE technology identifier (enum)

Special Case

When rdx (input) is 0 (i.e. NULL):

  • r10 is ignored
  • no data is written (since the buffer is non-existent)
  • other outputs are the same as if the call had succeeded with a large enough buffer

@haraldh
Copy link
Member Author

haraldh commented Oct 5, 2020

Yes. I propose the following syscall interface:

I meant the serialized opaque buffer.

@npmccallum
Copy link
Member

Yes. I propose the following syscall interface:

I meant the serialized opaque buffer.

I presume the output buffer? Its contents are dictated by the technology.

@npmccallum
Copy link
Member

@haraldh The format of buf section needs to be removed as it no longer applies.

@haraldh
Copy link
Member Author

haraldh commented Oct 21, 2020

@haraldh The format of buf section needs to be removed as it no longer applies.

I don't think so. Although for the syscall it is transparent, we might want to specify some kind of format in the future.

@connorkuehl connorkuehl removed their assignment Dec 7, 2020
@connorkuehl
Copy link
Contributor

connorkuehl commented Jan 5, 2021

This has been demonstrated. I will move its contents into our wiki and close this issue.

edit: This has been moved to the wiki.

@connorkuehl connorkuehl assigned connorkuehl and unassigned npmccallum and haraldh Jan 5, 2021
@nickvidal nickvidal transferred this issue from enarx-archive/enarx-keepldr Sep 29, 2021
haraldh added a commit to haraldh/enarx that referenced this issue Mar 7, 2022
according to enarx#966

Signed-off-by: Harald Hoyer <harald@profian.com>
haraldh added a commit to haraldh/enarx that referenced this issue Mar 7, 2022
according to enarx#966

Signed-off-by: Harald Hoyer <harald@profian.com>
haraldh added a commit to haraldh/enarx that referenced this issue Mar 8, 2022
according to enarx#966

Signed-off-by: Harald Hoyer <harald@profian.com>
haraldh added a commit to haraldh/enarx that referenced this issue Mar 8, 2022
according to enarx#966

Signed-off-by: Harald Hoyer <harald@profian.com>
haraldh added a commit to haraldh/enarx that referenced this issue Mar 9, 2022
according to enarx#966

Signed-off-by: Harald Hoyer <harald@profian.com>
enarxbot pushed a commit that referenced this issue Mar 9, 2022
according to #966

Signed-off-by: Harald Hoyer <harald@profian.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Planning
  
Done
Sprint
  
Done
Development

No branches or pull requests

5 participants