-
Notifications
You must be signed in to change notification settings - Fork 114
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
Conversation
So looks like rust-openssl doesn't support WASM yet: |
Why are you trying to use SSL from Wasm? |
I needed a crate that could create x509 certificates based on a certificate request. |
But why in Wasm? |
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). |
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? |
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. |
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. |
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 |
Correct. The goal is to have a proxy for remote attestation, no more, no less.
I am not sure what you mean by "backup application", could you clarify? |
I have written "backup" instead of "backend" :^) |
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? |
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 |
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.
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. |
FYI, I think this has quite a bit of detail on the topic: https://arxiv.org/pdf/1801.05863.pdf |
oak_loader/src/attestation.rs
Outdated
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())?; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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?
9bd094f
to
d9195b4
Compare
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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))?; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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)
//! - Client checks that the certificate was signed by the root certificate and establishes a secure | ||
//! connection |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
|
||
let mut name = X509NameBuilder::new()?; | ||
name.append_entry_by_text("O", "Oak")?; | ||
name.append_entry_by_text("CN", "Example Application")?; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
//! 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
899d5df
to
162c752
Compare
oak_loader/Cargo.toml
Outdated
log = "*" | ||
oak_abi = { path = "../oak_abi" } | ||
oak_runtime = { path = "../oak_runtime", default-features = false } | ||
oak_proxy_attestation = { path = "../experimental/proxy_attestation" } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
c4f6440
to
4a449e7
Compare
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
b23bfeb
to
559dc27
Compare
Reproducibility Index:
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
|
This change adds Proxy Attestation example.
It consists of:
experimental/proxy_attestation
: CA that can create signed certificates based on certificate signing requestsexamples/proxy_attestation/client
: Client that can request the CA root certificate and use it to connect to an Oak applicationexamples/proxy_attestation/module
: Simple example Oak applicationCertificate signing requests are created by
oak_loader
.Fixes #1860
Ref #1374