Files
Li, Xun 8a22317709 Linux 2.22 Open Source Gold Release
Upgraded to OpenSSL 3.0.10.
Added interoperable RA-TLS support which follows CCC design.
Enhanced Protect File System performance and added additional dependency
  `libsgx_pthread.a`.
Added the Constant Time instruction Decoder (CTD) into the default AEX-Notify
  mitigation handler in order to prevent the introduction of any additional
  subtle sidechannel leakages within the default handler.
Added Mistletoe 3 mitigations to the IPP Cryptography Library to the AES-ECB,
  AESGCM, and AES-CMAC algorithms. These have been incorporated transparently
  into the `sgx_tcrypto` library.
Resigned all Intel® SGX Architecture Enclaves.
Upgraded Intel SGX Quote Verification Enclave to integrate OpenSSL/SgxSSL 3.0.10.
Added Attestation Library support for Intel(R) TDX Migration TD.
Added Rust wrapper for low-level Quote Generation APIs.
Enabled `SE_TRACE` log in release binary.
Updated Rust QVL wrapper to use native Rust structure for quote verification
  collateral.
Added a limitation in the DCAP QVL to only allow the user to set the QvE load
  policy once.
Fixed bugs.

Signed-off-by: Li, Xun <xun.li@intel.com>
2023-10-24 11:05:23 +08:00

315 lines
9.3 KiB
C++

/**
*
* MIT License
*
* Copyright (c) Open Enclave SDK contributors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*/
#include "openssl_utility.h"
sgx_status_t generate_certificate_and_pkey(X509*& certificate, EVP_PKEY*& pkey)
{
quote3_error_t qresult = SGX_QL_SUCCESS;
sgx_status_t result = SGX_ERROR_UNEXPECTED;
uint8_t* output_certificate = NULL;
size_t output_certificate_size = 0;
uint8_t* private_key_buffer = nullptr;
size_t private_key_buffer_size = 0;
uint8_t* public_key_buffer = nullptr;
size_t public_key_buffer_size = 0;
const unsigned char* certificate_buffer_ptr = nullptr;
BIO* mem = nullptr;
int key_type = EC_TYPE;
if (key_type) {
PRINT(" generating keys by EC P-384\n");
}
else
{
PRINT(" generating keys by RSA 3072\n");
}
result = generate_key_pair(
key_type, &public_key_buffer,
&public_key_buffer_size,
&private_key_buffer,
&private_key_buffer_size);
if (result != SGX_SUCCESS)
{
PRINT(" failed to generate RSA key pair\n");
goto done;
}
PRINT("public_key_buf_size:[%ld]\n", public_key_buffer_size);
PRINT("%s\n", public_key_buffer);
PRINT("private_key_buf_size:[%ld]\n", private_key_buffer_size);
PRINT("%s\n", private_key_buffer);
qresult = tee_get_certificate_with_evidence(
certificate_subject_name,
private_key_buffer,
private_key_buffer_size,
public_key_buffer,
public_key_buffer_size,
&output_certificate,
&output_certificate_size);
if (qresult != SGX_QL_SUCCESS || output_certificate == nullptr)
{
if (output_certificate == nullptr)
PRINT(" null certificate\n");
p_sgx_tls_qe_err_msg(qresult);
goto done;
}
// temporary buffer required as if d2i_x509 call is successful
// certificate_buffer_ptr is incremented to the byte following the parsed
// data. sending certificate_buffer_ptr as argument will keep
// output_certificate pointer undisturbed.
certificate_buffer_ptr = output_certificate;
if ((certificate = d2i_X509(
nullptr,
&certificate_buffer_ptr,
(long)output_certificate_size)) == nullptr)
{
PRINT("Failed to convert DER format certificate to X509 structure\n");
goto done;
}
mem = BIO_new_mem_buf((void*)private_key_buffer, -1);
if (!mem)
{
PRINT("Failed to convert private key buf into BIO_mem\n");
goto done;
}
if ((pkey = PEM_read_bio_PrivateKey(mem, nullptr, 0, nullptr)) == nullptr)
{
PRINT("Failed to convert private key buffer into EVP_KEY format\n");
goto done;
}
result = SGX_SUCCESS;
done:
if (private_key_buffer)
free(private_key_buffer);
if (public_key_buffer)
free(public_key_buffer);
certificate_buffer_ptr = nullptr;
if (mem)
BIO_free(mem);
if (output_certificate)
tee_free_certificate(output_certificate);
return result;
}
sgx_status_t load_tls_certificates_and_keys(
SSL_CTX* ctx,
X509*& certificate,
EVP_PKEY*& pkey)
{
sgx_status_t result = SGX_ERROR_UNEXPECTED;
if (generate_certificate_and_pkey(certificate, pkey) != SGX_SUCCESS)
{
PRINT("Cannot generate certificate and pkey\n");
goto exit;
}
if (certificate == nullptr)
{
PRINT("null cert\n");
goto exit;
}
if (!SSL_CTX_use_certificate(ctx, certificate))
{
PRINT("Cannot load certificate on the server\n");
goto exit;
}
if (!SSL_CTX_use_PrivateKey(ctx, pkey))
{
PRINT("Cannot load private key on the server\n");
goto exit;
}
/* verify private key */
if (!SSL_CTX_check_private_key(ctx))
{
PRINT("Private key does not match the public certificate\n");
goto exit;
}
result = SGX_SUCCESS;
exit:
return result;
}
sgx_status_t initalize_ssl_context(SSL_CONF_CTX*& ssl_conf_ctx, SSL_CTX*& ctx)
{
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
// Configure the SSL context based on Open Enclave's security guidance.
const char* cipher_list_tlsv12_below =
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-"
"AES128-GCM-SHA256:"
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-"
"AES256-SHA384:"
"ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384";
const char* cipher_list_tlsv13 =
"TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256";
const char* supported_curves = "P-521:P-384:P-256";
SSL_CONF_CTX_set_ssl_ctx(ssl_conf_ctx, ctx);
SSL_CONF_CTX_set_flags(
ssl_conf_ctx,
SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CLIENT);
int ssl_conf_return_value = -1;
if ((ssl_conf_return_value =
SSL_CONF_cmd(ssl_conf_ctx, "MinProtocol", "TLSv1.2")) < 0)
{
PRINT(
"Setting MinProtocol for ssl context configuration failed with "
"error %d \n",
ssl_conf_return_value);
goto exit;
}
if ((ssl_conf_return_value =
SSL_CONF_cmd(ssl_conf_ctx, "MaxProtocol", "TLSv1.3")) < 0)
{
PRINT(
"Setting MaxProtocol for ssl context configuration failed with "
"error %d \n",
ssl_conf_return_value);
goto exit;
}
if ((ssl_conf_return_value = SSL_CONF_cmd(
ssl_conf_ctx, "CipherString", cipher_list_tlsv12_below)) < 0)
{
PRINT(
"Setting CipherString for ssl context configuration failed with "
"error %d \n",
ssl_conf_return_value);
goto exit;
}
if ((ssl_conf_return_value = SSL_CONF_cmd(
ssl_conf_ctx, "Ciphersuites", cipher_list_tlsv13)) < 0)
{
PRINT(
"Setting Ciphersuites for ssl context configuration failed with "
"error %d \n",
ssl_conf_return_value);
goto exit;
}
if ((ssl_conf_return_value =
SSL_CONF_cmd(ssl_conf_ctx, "Curves", supported_curves)) < 0)
{
PRINT(
"Setting Curves for ssl context configuration failed with error %d "
"\n",
ssl_conf_return_value);
goto exit;
}
if (!SSL_CONF_CTX_finish(ssl_conf_ctx))
{
PRINT("Error finishing ssl context configuration \n");
goto exit;
}
ret = SGX_SUCCESS;
exit:
return ret;
}
int read_from_session_peer(
SSL*& ssl_session,
const char* payload,
size_t payload_length)
{
int ret = -1;
unsigned char buffer[200]; // the expected payload to be read from peer is
// at maximum of size 200
int bytes_read = 0;
do
{
unsigned int len = sizeof(buffer) - 1;
memset(buffer, 0, sizeof(buffer));
bytes_read = SSL_read(ssl_session, buffer, (size_t)len);
if (bytes_read <= 0)
{
int error = SSL_get_error(ssl_session, bytes_read);
if (error == SSL_ERROR_WANT_READ)
continue;
PRINT("Failed! SSL_read returned error=%d\n", error);
ret = bytes_read;
break;
}
PRINT(" %d bytes read from session peer\n", bytes_read);
// check to see if received payload is expected
if ((bytes_read != payload_length) ||
(memcmp(payload, buffer, bytes_read) != 0))
{
PRINT(
"ERROR: expected reading %lu bytes but only "
"received %d bytes\n",
payload_length,
bytes_read);
ret = bytes_read;
goto exit;
}
else
{
PRINT(" received all the expected data from the session peer\n\n");
ret = 0;
break;
}
} while (1);
exit:
return ret;
}
int write_to_session_peer(
SSL*& ssl_session,
const char* payload,
size_t payload_length)
{
int bytes_written = 0;
int ret = 0;
while ((bytes_written = SSL_write(ssl_session, payload, payload_length)) <=
0)
{
int error = SSL_get_error(ssl_session, bytes_written);
if (error == SSL_ERROR_WANT_WRITE)
continue;
PRINT("Failed! SSL_write returned %d\n", error);
ret = bytes_written;
goto exit;
}
PRINT("%lu bytes written to session peer\n\n", payload_length);
exit:
return ret;
}