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

Add Proxy Attestation example #1849

Merged
merged 2 commits into from
Feb 11, 2021
Merged

Conversation

ipetr0v
Copy link
Contributor

@ipetr0v ipetr0v commented Jan 27, 2021

This change adds Proxy Attestation example.
It consists of:

  • experimental/proxy_attestation: CA that can create signed certificates based on certificate signing requests
  • examples/proxy_attestation/client: Client that can request the CA root certificate and use it to connect to an Oak application
  • examples/proxy_attestation/module: Simple example Oak application

Certificate signing requests are created by oak_loader.

Fixes #1860
Ref #1374

@google-cla google-cla bot added the cla: yes label Jan 27, 2021
@ipetr0v ipetr0v added the WIP Work in progress label Jan 27, 2021
@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

@tiziano88
Copy link
Collaborator

Why are you trying to use SSL from Wasm?

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

I needed a crate that could create x509 certificates based on a certificate request.

@tiziano88
Copy link
Collaborator

But why in Wasm?

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

Because we need to create it inside Oak (i.e. backend server sends Oak a certificate request, and Oak creates a corresponding certificate using its root key).
So Oak application works as a CA.

@tiziano88
Copy link
Collaborator

That's not what I was expecting. The CA would be a separate stand-alone binary that has nothing to do with Oak. Its job is to verify remote attestation quotes, and sign certs based on that. The impl of the gRPC server pseudo node would obtain such signature from the CA enclave, and then start listening over gRPC using that cert. No Wasm is involved, and definitely no other Oak-specific functionality.

What is your plan instead?

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

I thought the original idea was to make clients trust that the backend was attested and correct certificates were signed. And in order to enforce that, the CA and the attestor should be in Oak (or at least as a separate app in TEE), so they themselves could be remotely attestable (by clients).

And I tried to make it all in Wasm just to have a Proxy Attestation Service as an Oak application, and not making it a part of Runtime.

@tiziano88
Copy link
Collaborator

I thought the original idea was to make clients trust that the backend was attested and correct certificates were signed. And in order to enforce that, the CA and the attestor should be in Oak (or at least as a separate app in TEE), so they themselves could be remotely attestable (by clients).

How would this make them remotely attestable? In fact I think this makes it impossible for a client to make sure that a particular application is actually running in Oak. And additionally, how would the application remotely attest to the CA? Even if it works, the layering of Oak runtime + Oak application seems completely unnecessary and overengineered, and makes the TCB of the CA massive. I thought we agreed that the solution should be minimal and independent of Oak.

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

So neither the CA nor a backend app should use Oak, right?

Also, in the case when a backup application uses Oak, it would still need to create a certificate signing request (using something different from openssl-rust).

@tiziano88
Copy link
Collaborator

So neither the CA nor a backend app should use Oak, right?

Correct. The goal is to have a proxy for remote attestation, no more, no less.

Also, in the case when a backup application uses Oak, it would still need to create a certificate signing request (using something different from openssl-rust).

I am not sure what you mean by "backup application", could you clarify?

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

I am not sure what you mean by "backup application", could you clarify?

I have written "backup" instead of "backend" :^)
But basically, it's the application that wants to be attested by the proxy.

@tiziano88
Copy link
Collaborator

The Oak loader will generate a cert / key, attest itself to the proxy, get its certificate signed by the proxy (which verifies the remote attestation claim with Intel / AMD, for instance), then use that cert / key to terminate TLS for the gRPC connection of a gRPC server pseudo-node.

This way a client connecting to the Oak loader (running any Oak application) would know that it is talking to a VM that has been remotely attested by the CA enclave. There is still the question of what exactly does the CA enclave do when signing the worker enclave cert, e.g. does it need to put the remote attestation quote in a special field, or does it store it locally, or something else?

@ipetr0v
Copy link
Contributor Author

ipetr0v commented Jan 27, 2021

I don't think the quote should be stored by the Proxy, because after the attestation this quote is only needed by the client - to check that it's talking to a specific application that they intended to. So this quote should be in the TLS certificate used by the backend application.

Also, we probably don't even need a quote, because clients do not operate with backend TEE credentials (such as EPID remote attestation keys and etc.) of the backend application. In our case MRENCLAVE or Image Hash will be enough.

@tiziano88
Copy link
Collaborator

I don't think the quote should be stored by the Proxy, because after the attestation this quote is only needed by the client - to check that it's talking to a specific application that they intended to. So this quote should be in the TLS certificate used by the backend application.

Yes, but now we need to find a field in the TLS cert to store it. BTW, have you looked at how Intel does this in SGX? I think we talked about the fact that we should try and be compatible with what they do, if at all possible.

Also, we probably don't even need a quote, because clients do not operate with backend TEE credentials (such as EPID remote attestation keys and etc.) of the backend application. In our case MRENCLAVE or Image Hash will be enough.

Why limit to a single field? Also I don't think it will be enough. For instance, a client may want to know the SGX version number, or whether the enclave is in debug mode, or anything else. We should just leave the quote as it is, and replace its signature with that of the CA enclave, which is also conceptually a simple operation. CA enclave gets a quote, checks the remote attestation signature, then throws it away and replaces it with its own signature.

@conradgrobler
Copy link
Collaborator

BTW, have you looked at how Intel does this in SGX?

FYI, I think this has quite a bit of detail on the topic: https://arxiv.org/pdf/1801.05863.pdf

let mut cert_name = X509NameBuilder::new()?;
// CN refers to Common Name.
// https://tools.ietf.org/html/rfc5280
cert_name.append_entry_by_text("CN", &get_tee_measurements())?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes sure that this is putting a real measurement in this field? AFAICT this is completely unrelated to the actual attestation with the proxy, so why would anyone trust it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proxy will attest the backend and only sign a certificate that has a correct measurement in it.
But proxy probably should be the one who puts these measurements in the cert (in the end it will be identical cert).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not possible for the CA enclave to add those fields and sign them in its part of the cert, instead of double checking them from the self-signed cert from the worker enclave?

@ipetr0v ipetr0v removed the WIP Work in progress label Feb 2, 2021
@ipetr0v ipetr0v marked this pull request as ready for review February 2, 2021 16:06
experimental/proxy_attestation/src/certificate.rs Outdated Show resolved Hide resolved
const CERTIFICATE_EXPIRATION_INTERVAL_IN_DAYS: u32 = 1;
const TEST_TEE_QUOTE: &str = "Test TEE quote";

/// Placeholder function for collecting quotes of remotely attested TEEs.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what quotes this function is supposed to collect. Do you mean it is expected to extract the quote from the remotely attested channel from which the TEE is connecting? If so, I guess this would have something related to the connection as parameter (even if unused for now). If it is really a top-level function with no param, then I think I completely misunderstand how it's supposed to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct, TEE quotes will most likely be accessible from the gRPC connection.
But we will most likely not use tonic connection, since after implementing remote attestation we might drop tonic and use a custom gRPC library.
For now added a placeholder tonic::Request parameter.

Comment on lines 178 to 185
let subject_alt_name = SubjectAlternativeName::new()
.dns("project-oak.local")
.dns("localhost")
.ip("127.0.0.1")
.ip("::1")
// `10.0.2.2` is routed to the host machine by the Android emulator.
.ip("10.0.2.2")
.build(&builder.x509v3_context(Some(&self.root_certificate), None))?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these need to be the actual host names / IPs of the application?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, otherwise tonic shows an error:

transport error: error trying to connect: invalid certificate: CertNotValidForName

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, added a TODO(#1869) to load CSRs from PEM files (so we wouldn't need to hardcode IPs)

experimental/proxy_attestation/src/main.rs Outdated Show resolved Hide resolved
experimental/proxy_attestation/src/main.rs Outdated Show resolved Hide resolved
Comment on lines 37 to 38
//! - Client checks that the certificate was signed by the root certificate and establishes a secure
//! connection
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point here I guess the client actually checks the remote attestation details on the certificate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment
Also created an issue #1861, since it might require to write a custom tower client (separate PR)

experimental/proxy_attestation/src/main.rs Outdated Show resolved Hide resolved

let mut name = X509NameBuilder::new()?;
name.append_entry_by_text("O", "Oak")?;
name.append_entry_by_text("CN", "Example Application")?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these final values or placeholders?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, these are temporary, since we need to load them from a PEM file.
Added a TODO(#1869)

experimental/proxy_attestation/src/main.rs Outdated Show resolved Hide resolved
experimental/proxy_attestation/src/main.rs Outdated Show resolved Hide resolved
experimental/proxy_attestation/src/main.rs Show resolved Hide resolved
//! The work cycle of the proxy is represented in 2 stages.
//! First stage corresponds to the backend server attestation:
//! - TEE application connects to the proxy
//! - Proxy attests the application using a corresponding remote attestation protocol
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the plan to use EKEP here? I don't think a modified TLS works unless it does modified mutual attesation, since the application is initiating the connection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, current plan is to use EKEP once it's ready

log = "*"
oak_abi = { path = "../oak_abi" }
oak_runtime = { path = "../oak_runtime", default-features = false }
oak_proxy_attestation = { path = "../experimental/proxy_attestation" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to add an "oak_experimental" feature that is not enabled by default so that the oak server only depends on experimental crates (and their dependencies) if it is explicitly requested to be an experimental build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an oak_attestation feature, and it's running as part of the --server-variant=experimental which is now default in CI.

@ipetr0v ipetr0v requested a review from conradgrobler February 5, 2021 12:39
@ipetr0v ipetr0v force-pushed the proxy_attestation branch 4 times, most recently from c4f6440 to 4a449e7 Compare February 10, 2021 14:21
Move proxy out of Oak

Format

Move Proxy Attestation to experimental

Use Proxy Attestation in oak_loader

Fix certificate signing

Add comments

Remove old tests

Remove old gRPC

Change rustls version

Update comments

Use an X509 extension

Format

Format

Update after review

Add oak_attestation feature

Fix dependencies

Remove Cargo.lock duplicates

Remove unused deps

Remove default

Update Cargo.lock

Update oak_attestation feature

Format

Add experimental to CI
@ipetr0v ipetr0v merged commit a32e7b0 into project-oak:main Feb 11, 2021
@ipetr0v ipetr0v deleted the proxy_attestation branch February 11, 2021 20:18
@github-actions
Copy link

Reproducibility Index:

8c72eaa14887bd90799f215faf0641d497b0e0007d9853289a7e3dfbc177ed5f  ./examples/abitest/bin/abitest_0_frontend.wasm
ba8998cfb93ef6f5eaa56f2c68f252cbb52314a0fe218e11bee9ca67906e0cc9  ./examples/abitest/bin/abitest_1_backend.wasm
108864ffe7e2e478429dd29ea832b34ff59d2ad311f5b2cb8355767614172919  ./examples/aggregator/bin/aggregator.wasm
a507ddc9397f99732c5f2a93b0cc67329ec75ec93cca1c1764b735e0551c1ce6  ./examples/chat/bin/chat.wasm
6c998f3e14e09638d9fe7ea35cd8fde0242ffeb8fcda6976632bfc0e689421e9  ./examples/hello_world/bin/hello_world.wasm
18c1587164a465bfb060b51092419a81e341be58807624f35053291121eee922  ./examples/hello_world/bin/translator.wasm
ddd753b53270d23ca0717a2bbcb404ecd91cdb81f0d3918a856d0b383ce8f479  ./examples/http_server/bin/http_server.wasm
19c63f06e2648dfbd3aa57b6c866edaa5a9e33971b9e6082f3607e8b9bff4c97  ./examples/injection/bin/injection.wasm
bd603a81ca1d3c51504116803753b148b24e0363f883a4719d85aff4620c231a  ./examples/private_set_intersection/bin/private_set_intersection.wasm
40a1795df36da525d78d872bba92685fb78adaaf509d86e6d6edf310c86af348  ./examples/private_set_intersection/bin/private_set_intersection_handler.wasm
5d446e200c0a96092c946db8bc36f0a1347dc223d13dac79f7b36f5cfbbdc671  ./examples/proxy_attestation/bin/proxy_attestation_example.wasm
18c1587164a465bfb060b51092419a81e341be58807624f35053291121eee922  ./examples/translator/bin/translator.wasm
d35e7c4f85d875ef443b75097e1ef39d025e8df334a60ca5d5cfdde4d0cac1b9  ./examples/trusted_database/bin/trusted_database.wasm
f35ed23ca8506f2c27cb664f457ed09483ebe79130d9b59872cd3369a3ba643e  ./oak_loader/bin/oak_loader

Reproducibility Index diff:

diff --git a/reproducibility_index b/reproducibility_index
index 1a0c4a7..807b81a 100644
--- a/reproducibility_index
+++ b/reproducibility_index
@@ -8,6 +8,7 @@ ddd753b53270d23ca0717a2bbcb404ecd91cdb81f0d3918a856d0b383ce8f479  ./examples/htt
 19c63f06e2648dfbd3aa57b6c866edaa5a9e33971b9e6082f3607e8b9bff4c97  ./examples/injection/bin/injection.wasm
 bd603a81ca1d3c51504116803753b148b24e0363f883a4719d85aff4620c231a  ./examples/private_set_intersection/bin/private_set_intersection.wasm
 40a1795df36da525d78d872bba92685fb78adaaf509d86e6d6edf310c86af348  ./examples/private_set_intersection/bin/private_set_intersection_handler.wasm
+5d446e200c0a96092c946db8bc36f0a1347dc223d13dac79f7b36f5cfbbdc671  ./examples/proxy_attestation/bin/proxy_attestation_example.wasm
 18c1587164a465bfb060b51092419a81e341be58807624f35053291121eee922  ./examples/translator/bin/translator.wasm
 d35e7c4f85d875ef443b75097e1ef39d025e8df334a60ca5d5cfdde4d0cac1b9  ./examples/trusted_database/bin/trusted_database.wasm
-01ceeeeca197ad6ea36777ab72a9c21dfa561a18f78504f86fb606945683ada9  ./oak_loader/bin/oak_loader
+f35ed23ca8506f2c27cb664f457ed09483ebe79130d9b59872cd3369a3ba643e  ./oak_loader/bin/oak_loader

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Proxy Attestation Service example
4 participants