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

Added cert generation and verification APIs for attested TLS #1761

Merged
merged 17 commits into from
May 26, 2019

Conversation

soccerGB
Copy link
Contributor

@soccerGB soccerGB commented May 3, 2019

This is certification generation (oe_gen_tls_cert) and verification (oe_verify_tls_cert) part of attested tls feature.
#1325

I am hoping to preliminary feedback whether the implementation of those two new APIs impacts other features/refactoring activities under construction.

End-2-end test and samples will come in a separate PR once its depending components (socket) are ready.

@soccerGB soccerGB added the do not merge Indicates a PR should not be merged until removed. label May 3, 2019
common/sgx/tlsverifier.c Outdated Show resolved Hide resolved
enclave/cert.c Show resolved Hide resolved
enclave/cert.c Outdated Show resolved Hide resolved
common/sgx/tlsverifier.c Outdated Show resolved Hide resolved
@soccerGB soccerGB requested a review from anitagov May 4, 2019 00:30
3rdparty/mbedtls/mbedtls/library/x509write_crt.c Outdated Show resolved Hide resolved
3rdparty/mbedtls/mbedtls/library/x509write_crt.c Outdated Show resolved Hide resolved
common/sgx/tlsverifier.c Outdated Show resolved Hide resolved
enclave/tls_cert.c Show resolved Hide resolved
enclave/tls_cert.c Outdated Show resolved Hide resolved
@soccerGB soccerGB force-pushed the soccerl/tls_cert_api branch from e029a6f to b8424b2 Compare May 6, 2019 20:30
if (n)
*dest = '\0';

return ret;
Copy link
Contributor

Choose a reason for hiding this comment

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

@mikbras @soccerGB @CodeMonkeyLeet @paulcallen @gupta-ak
The need to implement and review oe_strncpy is one of the reasons why corelibc is more trouble than it is worth.

This implementation of oe_strncpy looks correct - copy at most n characters from src to dst - a bounded string-copy.

However this implementation is incorrect because, counterintuitively, strncpy has different semantics according to the C standard. strncpy requires that the destination be padded with null characters if the src contains less that n characters.

From strncpy C++ reference

Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

From Ansi C Rationale

strncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. strncpy is not by origin a ``bounded strcpy,'' and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use.

C libraries take great pains to implement the standard; no matter how counter-intuitive the standard is. Take for example MUSL's implementation of which strncpy forwards to:
https://github.com/microsoft/openenclave/blob/fe0c6af59d1d3ec038c47cda52555cdf351b10f8/3rdparty/musl/musl/src/string/stpncpy.c#L10-L29

MUSL's strncpy follows the C standard by null-padding the destination bytes. Additionally, when used as a glibc replacement, it does glibc compatible optimizations.

Since crypto is a key component in writing secure code, we need to shy away from writing new code in the hot path. Instead we need to rely on battle tested code like MUSL or GLIBC (along with their security fixes).
If we start implementing libc functions, when we are already using a full fledged libc implementation like MUSL, we ought to lock down each C function we implement rigorously with tests and prove to ourselves that we are standards compliant. At this moment I don't see rigorous tests for corelibc.

Copy link
Contributor

Choose a reason for hiding this comment

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

@anakrish This is a really good observation, can you please spin up an issue to track this? It suggests a broader scope of work we should tackle more comprehensively in terms of the implementation of corelibc which also intersects with @mikbras work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with Anand here.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1. If we have a POSIX name we must adhere to the standard. strncpy as specified in the standard is dangerous since it does not guarantee null termination (as explained at the link Anand cites). As such, if we make oe_strncpy be public, then it should probably be marked as deprecated or unsafe or something, so it will generate warnings if an app tries to use it. strncpy_s is the safer API to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is strncpy was added for the purpose getting mbedtls built on top of corelibc, where once we starting building mbedtls on top of the musl, this direct corelibc dependency will be removed thus the concern raised will be gone because this strncpy will become no longer needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you open an issue to keep track of removing this strncpy implementation or fixing it to be libc compliant before the next release? Otherwise, we would increase the risk of unpredictable behavior/potential security vulnerability.

@soccerGB
Copy link
Contributor Author

soccerGB commented May 7, 2019

bors try

@andyleejordan andyleejordan added this to the v0.6 milestone May 7, 2019
@andyleejordan andyleejordan added the functionality Issue describes an enhancement or addition of functionality to Open Enclave SDK label May 7, 2019
@soccerGB
Copy link
Contributor Author

soccerGB commented May 7, 2019

bors try

@oe-bors
Copy link

oe-bors bot commented May 7, 2019

try

Not awaiting review

oe-bors bot pushed a commit that referenced this pull request May 7, 2019
@oe-bors
Copy link

oe-bors bot commented May 8, 2019

try

Build failed

Copy link
Contributor

@CodeMonkeyLeet CodeMonkeyLeet left a comment

Choose a reason for hiding this comment

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

We should probably have a full review on the new additions to the public API surface.

@@ -161,6 +161,13 @@ OE_STATIC_ASSERT(sizeof(oe_report_header_t) == 16);
OE_STATIC_ASSERT(
OE_OFFSETOF(oe_report_header_t, report) == sizeof(oe_report_header_t));

// ISO(1).ANSI(2).USA(840).Microsoft(113556).ACC(10).Classes(103).Subclass(1)
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment doesn't match the OID we're using. (Classes is 1, not 103)

Have we registered this with the OID range owners in MS to avoid collisions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mismatched class id fixed.
Still figuring out how to register this OID

include/openenclave/host.h Outdated Show resolved Hide resolved
include/openenclave/host.h Outdated Show resolved Hide resolved
3rdparty/mbedtls/mbedtls/library/x509write_crt.c Outdated Show resolved Hide resolved
if (n)
*dest = '\0';

return ret;
Copy link
Contributor

Choose a reason for hiding this comment

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

@anakrish This is a really good observation, can you please spin up an issue to track this? It suggests a broader scope of work we should tackle more comprehensively in terms of the implementation of corelibc which also intersects with @mikbras work.

include/openenclave/enclave.h Outdated Show resolved Hide resolved
include/openenclave/enclave.h Show resolved Hide resolved
include/openenclave/enclave.h Outdated Show resolved Hide resolved
include/openenclave/host.h Outdated Show resolved Hide resolved
include/openenclave/internal/cert.h Outdated Show resolved Hide resolved
common/sgx/tlsverifier.c Outdated Show resolved Hide resolved
3rdparty/mbedtls/mbedtls/library/x509write_crt.c Outdated Show resolved Hide resolved
3rdparty/mbedtls/mbedtls/library/x509write_crt.c Outdated Show resolved Hide resolved
OE_RAISE(OE_INVALID_PARAMETER);

/* Allocate memory for the certificate */
if (!(crt = mbedtls_calloc(1, sizeof(mbedtls_x509_crt))))
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally I think it's bad for a core OE file to directly hard code mbedTLS specific API calls instead of going through an abstraction layer. I thought that was being addressed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This cert.c is part of the crypto implementation for the enclave, which depends solely on the mbedtls library.
Before that dependency was replaced/removed, we will have to keep it this way.

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't parse the last sentence in your reply. Do you mean "Until that is done"? meaning it's future work to fix this? Or what? I still maintain its bad to call mbedtls APIs directly from OE core code.

if (n)
*dest = '\0';

return ret;
Copy link
Contributor

Choose a reason for hiding this comment

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

+1. If we have a POSIX name we must adhere to the standard. strncpy as specified in the standard is dangerous since it does not guarantee null termination (as explained at the link Anand cites). As such, if we make oe_strncpy be public, then it should probably be marked as deprecated or unsafe or something, so it will generate warnings if an app tries to use it. strncpy_s is the safer API to use.

enclave/tls_cert.c Outdated Show resolved Hide resolved
tests/tls_apis/enc/enc.cpp Outdated Show resolved Hide resolved
tests/tls_apis/enc/enc.cpp Outdated Show resolved Hide resolved
tests/tls_apis/enc/enc.cpp Outdated Show resolved Hide resolved
tests/tls_apis/host/host.cpp Outdated Show resolved Hide resolved
tests/tls_apis/host/host.cpp Outdated Show resolved Hide resolved
@@ -724,6 +724,76 @@ oe_enclave_t* oe_get_enclave(void);
*/
oe_result_t oe_random(void* data, size_t size);

/**
* oe_generate_attestation_cert.
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't use abbreviations ("cert") in non-POSIX API names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for spotting this.
Renamed to
oe_generate_attestation_certificate
oe_free_attestation_certificate
oe_verify_attestation_certificate

/**
* oe_generate_attestation_cert.
*
* This function generates a self-signed x509 certificate with an embedded
Copy link
Contributor

Choose a reason for hiding this comment

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

x509 -> X.509

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for spotting this. Fixed.

* This function generates a self-signed x509 certificate with an embedded
* quote from the underlying enclave.
*
* @param[in] subject_name a string contains contain an X.509 distinguished
Copy link
Contributor

Choose a reason for hiding this comment

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

"contains contain" -> "containing"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for spotting this. Fixed.

* See RFC5280 (https://tools.ietf.org/html/rfc5280) specification for details.
* Example value "CN=Open Enclave SDK,O=OESDK TLS,C=US"
*
* @param[in] private_key a private key used to sign this certificate
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: some lines end in period (740, 742) and some don't (739, 741). Be consistent throughout this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for spotting this. Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit is not yet fixed. See line 742

/**
* oe_verify_attestation_cert
*
* This function preform a custom validation on the input certificate. This
Copy link
Contributor

Choose a reason for hiding this comment

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

"preform" -> "perform"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for spotting this. Fixed.

include/openenclave/enclave.h Show resolved Hide resolved
* @param[in] cert_in_der_len size of certificate buffer above
* @param[in] enclave_identity_callback callback routine for custom identity
* checking
* @param[in] arg optional argument
Copy link
Contributor

Choose a reason for hiding this comment

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

what is "arg" used for? "optional argument" is not a helpful description

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rephrased to

  • @param[in] arg an optional context pointer argument specified by the
  • application when setting callback

* oe_verify_attestation_cert
*
* This function preform a custom validation on the input certificate. This
* validation includes extracting a quote extension from the certificate before
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the term "quote" is SGX specific and does not belong in the doxygen comments at all, unless used in an example where it's clear it's using SGX as the example

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point.
I replaced "quote" with "attestation evidence".

/**
* oe_verify_attestation_cert
*
* This function preform a custom validation on the input certificate. This
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comments in host.h as I added into enclave.h

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed

@soccerGB soccerGB force-pushed the soccerl/tls_cert_api branch from 4313fed to 043eede Compare May 25, 2019 00:11
@soccerGB soccerGB dismissed stale reviews from anakrish, dthaler, and CodeMonkeyLeet May 25, 2019 00:12

all feedback were addressed

@soccerGB
Copy link
Contributor Author

bors r+

oe-bors bot pushed a commit that referenced this pull request May 25, 2019
1761: Added cert generation and verification APIs for attested TLS r=soccerGB a=soccerGB

This is certification generation (oe_gen_tls_cert) and verification (oe_verify_tls_cert) part of attested tls feature.
#1325

I am hoping to preliminary feedback whether the implementation of those two new APIs impacts other features/refactoring activities under construction.


End-2-end test and samples will come in a separate PR once its depending components (socket) are ready.

Co-authored-by: Cheng-mean Liu <[email protected]>
@oe-bors
Copy link

oe-bors bot commented May 25, 2019

Build failed

common/sgx/tlsverifier.c Show resolved Hide resolved
enclave/cert.c Outdated Show resolved Hide resolved
enclave/cert.c Outdated Show resolved Hide resolved
enclave/cert.c Outdated Show resolved Hide resolved
enclave/cert.c Show resolved Hide resolved
include/openenclave/internal/cert.h Outdated Show resolved Hide resolved
include/openenclave/internal/cert.h Outdated Show resolved Hide resolved
include/openenclave/internal/cert.h Outdated Show resolved Hide resolved

target_include_directories(tls_enc PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/include/openenclave/corelibc)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is corelibc part of the includes if you're already linking with oelibc? You should have the headers from musl.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is an internal test case, where a couple of internal oe_* api, defined in oecorelibc, were used. That's why corelibc path was included.
In the upcoming external same code, it will solely base on the musl headers.

/* Only map CHAR_BIT out of limits.h to scope potential standard definition
* name conflicts in enclave sources.
*/
#if !defined(CHAR_BIT)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need to do this if you remove the corelibc includes.

@soccerGB
Copy link
Contributor Author

bors try

oe-bors bot pushed a commit that referenced this pull request May 25, 2019
@oe-bors
Copy link

oe-bors bot commented May 25, 2019

try

Build failed

@soccerGB soccerGB force-pushed the soccerl/tls_cert_api branch from 2ebf7eb to a66362f Compare May 25, 2019 23:54
@soccerGB
Copy link
Contributor Author

bors r+

oe-bors bot pushed a commit that referenced this pull request May 26, 2019
1761: Added cert generation and verification APIs for attested TLS r=soccerGB a=soccerGB

This is certification generation (oe_gen_tls_cert) and verification (oe_verify_tls_cert) part of attested tls feature.
#1325

I am hoping to preliminary feedback whether the implementation of those two new APIs impacts other features/refactoring activities under construction.


End-2-end test and samples will come in a separate PR once its depending components (socket) are ready.

Co-authored-by: Cheng-mean Liu <[email protected]>
@oe-bors
Copy link

oe-bors bot commented May 26, 2019

Build succeeded

@oe-bors oe-bors bot merged commit a66362f into master May 26, 2019
@oe-bors oe-bors bot deleted the soccerl/tls_cert_api branch May 26, 2019 00:41
oe-bors bot pushed a commit that referenced this pull request May 26, 2019
1818: Remove OE_USE_LIBSGX on verifying report. r=soccerGB a=gupta-ak

This allows remote quote verification without `OE_USE_LIBSGX`. It's essentially a piece of PR #1575 to unblock Cheng-mean's PR #1761.

A way to test this is to run the report test with a pre-generated report. That test should now pass.

Co-authored-by: Akash Gupta <[email protected]>
sig_oid, sig_oid_len, sig, sig_len ) );

if( len > (size_t)( c2 - buf ) )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

@soccerGB The previous version returned MBEDTLS_ERR_ASN1_BUF_TOO_SMALL.
I cannot spot where the new version returns the same error code.

int rc = 0;

/* Clear the implementation */
if (impl)
Copy link
Contributor

Choose a reason for hiding this comment

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

If an impl already exists, then shouldn't we be cleaning up contents of the impl rather than just doing memset?

@@ -665,7 +707,7 @@ oe_result_t oe_cert_verify(
}

/* Check for invalid chain parameter */
if (!_cert_chain_is_valid(chain_impl))
if (chain && !_cert_chain_is_valid(chain_impl))
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be chain_impl && ?

*/
c = tmp_buf + sizeof( tmp_buf );
c = buf + size;
Copy link
Contributor

Choose a reason for hiding this comment

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

These look like changes to mbedtls itself. Are they being contributed back upstream to the master mbedtls? If not, why not? If so, what's the link to the pull request or commit?

OE_RAISE(OE_INVALID_PARAMETER);

/* Allocate memory for the certificate */
if (!(crt = mbedtls_calloc(1, sizeof(mbedtls_x509_crt))))
Copy link
Contributor

Choose a reason for hiding this comment

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

I can't parse the last sentence in your reply. Do you mean "Until that is done"? meaning it's future work to fix this? Or what? I still maintain its bad to call mbedtls APIs directly from OE core code.

#define ISSUER_NAME "CN=Open Enclave SDK,O=OESDK TLS,C=UK"
#define SUBJECT_NAME ISSUER_NAME
#define DATE_NOT_VALID_BEFORE "20190501000000"
#define DATE_NOT_VALID_AFTER "20501231235959"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's bad to hard code any timestamps in code, as opposed to in admin-configurable policy.

* See RFC5280 (https://tools.ietf.org/html/rfc5280) specification for details.
* Example value "CN=Open Enclave SDK,O=OESDK TLS,C=US"
*
* @param[in] private_key a private key used to sign this certificate
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit is not yet fixed. See line 742

* Free the given cert
* @param[in] cert If not NULL, the buffer to free.
*/
void oe_free_attestation_certificate(uint8_t* cert);
Copy link
Contributor

Choose a reason for hiding this comment

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

style comment: In Microsoft public headers and sample code, we try to avoid abbreviations not just in method names, but also variable/parameter names. "cert" should be expanded to "certificate" in 755, 756, 760, 762, etc., for consistency with the method name. (Acronyms on the other hand are fine, so "der" is perfectly fine in 794.) There are a very small number of exceptions where abbreviations are ok. Those include "app" and "arg" (which is used in this file and is ok.)

- **Host Side**
1. Create an enclave
2. Issue an ecall (get_tls_cert) into enclave for getting a self-signed certificate embedded with an quote of the enclave
3. Once the certificate is received, call oe_verify_attestation_cert to verify the certificate and quote
Copy link
Contributor

Choose a reason for hiding this comment

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

cert -> certificate (and same in oe_generate_attestation_cert on line 12)

#define TEST_RSA_KEY 1
#define SKIP_RETURN_CODE 2

// This is the identity validation callback. An TLS connecting party (client or
Copy link
Contributor

Choose a reason for hiding this comment

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

grammar nit: "An TLS" -> "A TLS"

"./cert_%s.der",
test_type == TEST_RSA_KEY ? "rsa" : "ec");
OE_TRACE_INFO(
"Host: Log quote embedded certificate to file: [%s]\n", filename);
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe the term "quote" is SGX specific. Use platform agnostic terms in trace output from non-SGX-specific code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
functionality Issue describes an enhancement or addition of functionality to Open Enclave SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants