mirror of
https://github.com/intel/linux-sgx
synced 2026-06-08 14:49:32 +00:00
8a22317709
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>
336 lines
9.2 KiB
C++
336 lines
9.2 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 <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <resolv.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
|
|
#include "sgx_utls.h"
|
|
#include <string.h>
|
|
|
|
#include <openssl/bio.h>
|
|
#include <openssl/err.h>
|
|
#include <openssl/pem.h>
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/x509.h>
|
|
#include <openssl/x509_vfy.h>
|
|
|
|
#include "../common/common.h"
|
|
|
|
int verify_callback(int preverify_ok, X509_STORE_CTX* ctx);
|
|
int create_socket(char* server_name, char* server_port);
|
|
|
|
int parse_arguments(
|
|
int argc,
|
|
char** argv,
|
|
char** server_name,
|
|
char** server_port)
|
|
{
|
|
int ret = 1;
|
|
const char* option = nullptr;
|
|
unsigned int param_len = 0;
|
|
|
|
if (argc != 3)
|
|
goto print_usage;
|
|
|
|
option = "-server:";
|
|
param_len = strlen(option);
|
|
if (strncmp(argv[1], option, param_len) != 0)
|
|
goto print_usage;
|
|
*server_name = (char*)(argv[1] + param_len);
|
|
|
|
option = "-port:";
|
|
param_len = strlen(option);
|
|
if (strncmp(argv[2], option, param_len) != 0)
|
|
goto print_usage;
|
|
|
|
*server_port = (char*)(argv[2] + param_len);
|
|
ret = 0;
|
|
goto done;
|
|
|
|
print_usage:
|
|
printf(TLS_CLIENT "Usage: %s -server:<name> -port:<port>\n", argv[0]);
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
// This routine conducts a simple HTTP request/response communication with
|
|
// server
|
|
int communicate_with_server(SSL* ssl)
|
|
{
|
|
unsigned char buf[200];
|
|
int ret = 1;
|
|
int error = 0;
|
|
unsigned int len = 0;
|
|
int bytes_written = 0;
|
|
int bytes_read = 0;
|
|
|
|
// Write an GET request to the server
|
|
printf(TLS_CLIENT "-----> Write to server:\n");
|
|
len = snprintf((char*)buf, sizeof(buf) - 1, CLIENT_PAYLOAD);
|
|
while ((bytes_written = SSL_write(ssl, buf, (size_t)len)) <= 0)
|
|
{
|
|
error = SSL_get_error(ssl, bytes_written);
|
|
if (error == SSL_ERROR_WANT_WRITE)
|
|
continue;
|
|
printf(TLS_CLIENT "Failed! SSL_write returned %d\n", error);
|
|
if (bytes_written == 0) ret = -1;
|
|
else ret = bytes_written;
|
|
goto done;
|
|
}
|
|
|
|
printf(TLS_CLIENT "%d bytes written\n", bytes_written);
|
|
|
|
// Read the HTTP response from server
|
|
printf(TLS_CLIENT "<---- Read from server:\n");
|
|
do
|
|
{
|
|
len = sizeof(buf) - 1;
|
|
memset(buf, 0, sizeof(buf));
|
|
bytes_read = SSL_read(ssl, buf, (size_t)len);
|
|
if (bytes_read <= 0)
|
|
{
|
|
int error = SSL_get_error(ssl, bytes_read);
|
|
if (error == SSL_ERROR_WANT_READ)
|
|
continue;
|
|
|
|
printf(TLS_CLIENT "Failed! SSL_read returned error=%d\n", error);
|
|
if (bytes_read == 0) ret = -1;
|
|
else ret = bytes_read;
|
|
goto done;
|
|
}
|
|
|
|
printf(TLS_CLIENT " %d bytes read\n", bytes_read);
|
|
|
|
// check to to see if received payload is expected
|
|
// Note that if you want to use client here but server from other
|
|
// applications, you need to ignore this check for SERVER_PAYLOAD_SIZE
|
|
// which need to be adjusted for an actual value
|
|
if ((bytes_read != SERVER_PAYLOAD_SIZE) ||
|
|
(memcmp(SERVER_PAYLOAD, buf, bytes_read) != 0))
|
|
{
|
|
printf(
|
|
TLS_CLIENT "ERROR: expected reading %lu bytes but only "
|
|
"received %d bytes\n",
|
|
SERVER_PAYLOAD_SIZE,
|
|
bytes_read);
|
|
ret = bytes_read;
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
printf(TLS_CLIENT
|
|
" received all the expected data from server\n\n");
|
|
ret = 0;
|
|
printf("Verified: the contents of server payload were expected\n\n");
|
|
break;
|
|
}
|
|
} while (1);
|
|
ret = 0;
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
// create a socket and connect to the server_name:server_port
|
|
int create_socket(char* server_name, char* server_port)
|
|
{
|
|
int sockfd = -1;
|
|
struct addrinfo hints, *dest_info, *curr_di;
|
|
int res;
|
|
|
|
hints = {0};
|
|
hints.ai_family = AF_INET;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
if ((res = getaddrinfo(server_name, server_port, &hints, &dest_info)) != 0)
|
|
{
|
|
printf(
|
|
TLS_CLIENT "Error: Cannot resolve hostname %s. %s\n",
|
|
server_name,
|
|
gai_strerror(res));
|
|
goto done;
|
|
}
|
|
|
|
curr_di = dest_info;
|
|
while (curr_di)
|
|
{
|
|
if (curr_di->ai_family == AF_INET)
|
|
{
|
|
break;
|
|
}
|
|
|
|
curr_di = curr_di->ai_next;
|
|
}
|
|
|
|
if (!curr_di)
|
|
{
|
|
printf(
|
|
TLS_CLIENT "Error: Cannot get address for hostname %s.\n",
|
|
server_name);
|
|
goto done;
|
|
}
|
|
|
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sockfd == -1)
|
|
{
|
|
printf(TLS_CLIENT "Error: Cannot create socket %d.\n", errno);
|
|
goto done;
|
|
}
|
|
|
|
if (connect(
|
|
sockfd,
|
|
(struct sockaddr*)curr_di->ai_addr,
|
|
sizeof(struct sockaddr)) == -1)
|
|
{
|
|
printf(
|
|
TLS_CLIENT "failed to connect to %s:%s (errno=%d)\n",
|
|
server_name,
|
|
server_port,
|
|
errno);
|
|
close(sockfd);
|
|
sockfd = -1;
|
|
goto done;
|
|
}
|
|
printf(TLS_CLIENT "connected to %s:%s\n", server_name, server_port);
|
|
|
|
done:
|
|
if (dest_info)
|
|
freeaddrinfo(dest_info);
|
|
|
|
return sockfd;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
int ret = 1;
|
|
SSL_CTX* ctx = nullptr;
|
|
SSL* ssl = nullptr;
|
|
int serversocket = 0;
|
|
char* server_name = nullptr;
|
|
char* server_port = nullptr;
|
|
int error = 0;
|
|
|
|
printf("\nStarting" TLS_CLIENT "\n\n\n");
|
|
if ((error = parse_arguments(argc, argv, &server_name, &server_port)) != 0)
|
|
{
|
|
printf(
|
|
TLS_CLIENT "TLS client:parse input parmeter failed (%d)!\n", error);
|
|
goto done;
|
|
}
|
|
|
|
// initialize openssl library and register algorithms
|
|
OpenSSL_add_all_algorithms();
|
|
ERR_load_crypto_strings();
|
|
SSL_load_error_strings();
|
|
|
|
if (SSL_library_init() < 0)
|
|
{
|
|
printf(TLS_CLIENT
|
|
"TLS client: could not initialize the OpenSSL library !\n");
|
|
goto done;
|
|
}
|
|
|
|
if ((ctx = SSL_CTX_new(SSLv23_client_method())) == nullptr)
|
|
{
|
|
printf(TLS_CLIENT "TLS client: unable to create a new SSL context\n");
|
|
goto done;
|
|
}
|
|
|
|
// choose TLSv1.2 by excluding SSLv2, SSLv3 ,TLS 1.0 and TLS 1.1
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1);
|
|
// specify the verify_callback for custom verification
|
|
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, &verify_callback);
|
|
|
|
if ((ssl = SSL_new(ctx)) == nullptr)
|
|
{
|
|
printf(TLS_CLIENT
|
|
"Unable to create a new SSL connection state object\n");
|
|
goto done;
|
|
}
|
|
|
|
serversocket = create_socket(server_name, server_port);
|
|
if (serversocket == -1)
|
|
{
|
|
printf(
|
|
TLS_CLIENT
|
|
"create a socket and initate a TCP connect to server: %s:%s "
|
|
"(errno=%d)\n",
|
|
server_name,
|
|
server_port,
|
|
errno);
|
|
goto done;
|
|
}
|
|
|
|
printf(
|
|
TLS_CLIENT
|
|
"create a socket and initate a TCP connect to server: %s:%s "
|
|
"\n",
|
|
server_name,
|
|
server_port);
|
|
// setup ssl socket and initiate TLS connection with TLS server
|
|
SSL_set_fd(ssl, serversocket);
|
|
if ((error = SSL_connect(ssl)) != 1)
|
|
{
|
|
printf(
|
|
TLS_CLIENT "Error: Could not establish an SSL session ret2=%d "
|
|
"SSL_get_error()=%d\n",
|
|
error,
|
|
SSL_get_error(ssl, error));
|
|
goto done;
|
|
}
|
|
printf(
|
|
TLS_CLIENT "successfully established TLS channel:%s\n",
|
|
SSL_get_version(ssl));
|
|
|
|
// start the client server communication
|
|
if ((error = communicate_with_server(ssl)) != 0)
|
|
{
|
|
printf(TLS_CLIENT "Failed: communicate_with_server (ret=%d)\n", error);
|
|
goto done;
|
|
}
|
|
|
|
// Free the structures we don't need anymore
|
|
ret = 0;
|
|
done:
|
|
if (serversocket != -1)
|
|
close(serversocket);
|
|
|
|
if (ssl)
|
|
SSL_free(ssl);
|
|
|
|
if (ctx)
|
|
SSL_CTX_free(ctx);
|
|
|
|
printf(TLS_CLIENT " %s\n", (ret == 0) ? "success" : "failed");
|
|
return (ret);
|
|
}
|