Assignment 7 #4

Merged
saschato merged 75 commits from Assignment-7 into master 2024-07-08 11:19:51 +02:00
7 changed files with 212 additions and 60 deletions
Showing only changes of commit 88f7609783 - Show all commits

View file

@ -28,6 +28,9 @@ char *embedded_device_syntax(void) {
" -firm <path> path of to firmware binary\n";
}
/*
* read secp256r1 public key and return it as EVP_PKEY*
*/
static EVP_PKEY *read_public_key(char *public_key_file_path, EVP_PKEY **key) {
if(public_key_file_path == NULL) {
fprintf(stderr, "public_key_file_path is a null pointer!\n");
@ -46,6 +49,9 @@ static EVP_PKEY *read_public_key(char *public_key_file_path, EVP_PKEY **key) {
return *key;
}
/*
* hash the firmware
*/
static void hash_firmware(uint8_t *firmware_path, EVP_MD_CTX **ctx) {
if(firmware_path == NULL) {
fprintf(stderr, "firmware_path is a null pointer!\n");
@ -68,11 +74,13 @@ static void hash_firmware(uint8_t *firmware_path, EVP_MD_CTX **ctx) {
}
int handle_embedded_device(int argc, char **argv) {
uint8_t status = EXIT_SUCCESS;
embedded_device_args args = {
.firmware_path = NULL,
.public_key_path = NULL
};
// parse parameters
for(int i = 0; i < argc; i += 2) {
if((strcmp(argv[i], "-ppub") == 0) && (argc - i >= 2)) {
args.public_key_path = argv[i+1];
@ -83,42 +91,53 @@ int handle_embedded_device(int argc, char **argv) {
}
}
// handle invalid parameters
if((args.firmware_path == NULL) || (args.public_key_path == NULL)) {
fprintf(stderr, "failed to parse arguments");
exit(EXIT_FAILURE);
}
// read the public key of the enclave
// normally, key would be hardcoded during production
EVP_PKEY *key = NULL;
if(read_public_key(args.public_key_path, &key) == NULL) {
fprintf(stderr, "failed to import public key");
status = EXIT_FAILURE;
goto clean;
}
// initialize the context
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, key) != 1) {
fprintf(stderr, "failed to initialize context\n");
status = EXIT_FAILURE;
goto clean;
}
// read the firmwares signature
uint8_t signature[BUFSIZE] = {0};
size_t signature_size = read(0, signature, BUFSIZE);
if(signature_size < 70) {
fprintf(stderr, "failed to read firmware signature\n");
status = EXIT_FAILURE;
goto clean;
}
// hash the firmware and verify the signature
hash_firmware(args.firmware_path, &ctx);
if (EVP_DigestVerifyFinal(ctx, signature, signature_size) != 1) {
fprintf(stderr, "failed to verify firmware signature\n");
fprintf(stderr, "failed to verify firmware signature or signature invalid\n");
status = EXIT_FAILURE;
}else {
printf("successfully verified firmware signature\n");
printf("Firmware is valid! Update starts in 5 4 3...\n");
}
// cleanup
clean: ;
if(key != NULL)
EVP_PKEY_free(key);
if(ctx != NULL)
EVP_MD_CTX_free(ctx);
return 0;
return status;
}

View file

@ -3,8 +3,21 @@
#include <stdint.h>
/*
* @brief getter for embedded subcommand syntax string
*
* @returns null-terminated syntax string
*/
char *embedded_device_syntax(void);
/*
* @brief CLI implementation for the "embedded" subcommand
*
* @param argc number of arguments with command and subcommand stripped
* @param argv arguments with command and subcommand stripped
*
* @returns 0 on success, else error with output on stderr
*/
int handle_embedded_device(int argc, char **argv);
#endif

View file

@ -58,11 +58,23 @@
#define SI_SIZE 2*SK_SIZE
#endif
/*
* Bobs and Alices public keys
*/
const sgx_ec256_public_t authorized[2] = {
{
0,
0
.gx = {
0x9c, 0x72, 0x2b, 0x52, 0x0e, 0xff, 0x07, 0xdc,
0x7a, 0x32, 0x19, 0xbb, 0xd8, 0x41, 0x94, 0x2c,
0xee, 0x17, 0xb2, 0xf6, 0x2e, 0x08, 0x61, 0xab,
0xbc, 0x50, 0xaf, 0xb6, 0x2e, 0xf9, 0x2c, 0xee
},
.gy = {
0x8c, 0x84, 0x2f, 0xb5, 0x94, 0xca, 0x60, 0x94,
0xb0, 0xdc, 0x8a, 0xcf, 0x17, 0x91, 0xd3, 0xab,
0x29, 0x0e, 0x81, 0x8c, 0xf6, 0x95, 0xc6, 0x92,
0x87, 0x0e, 0x1d, 0x76, 0x56, 0xba, 0x51, 0xbb
}
},
{
.gx = {
@ -101,6 +113,9 @@ int get_private_key_size() {
return SK_SIZE;
}
/*
* seals a key pair
*/
static sgx_status_t seal_key_pair(const sgx_ec256_private_t *private, const sgx_ec256_public_t *public, uint8_t **sealed) {
// allocate temporary buffers on stack
uint8_t pk[PK_SIZE] = {0};
@ -114,6 +129,9 @@ static sgx_status_t seal_key_pair(const sgx_ec256_private_t *private, const sgx_
return sgx_seal_data(PK_SIZE, (const uint8_t *)pk, SK_SIZE, (const uint8_t *)sk, get_sealed_size(), (sgx_sealed_data_t *) *sealed);
}
/*
* unseals a key pair
*/
static sgx_status_t unseal_key_pair(const uint8_t *sealed, sgx_ec256_private_t *private, sgx_ec256_public_t *public) {
// invalid parameter handling
if(sealed == NULL) {
@ -166,12 +184,12 @@ sgx_status_t generate_key_pair(uint8_t *sealed, uint32_t sealed_size) {
return status;
}
// create ecc keypair
// create ecc key pair
if((status = sgx_ecc256_create_key_pair(&private, &public, ecc_handle)) != SGX_SUCCESS) {
goto exit;
}
// seal keypair
// seal key pair
status = seal_key_pair(&private, &public, &sealed);
exit: ;
@ -197,9 +215,12 @@ sgx_status_t get_public_key(const uint8_t *sealed, uint32_t sealed_size, uint8_t
return status;
}
static sgx_status_t verify_signature(const uint8_t *data, uint32_t data_size, const sgx_ec256_public_t *public, const sgx_ec256_signature_t* ecc_signature) {
/*
* verifies an ecdsa signature
*/
static sgx_status_t verify_signature(const uint8_t *firmware, uint32_t firmware_size, const sgx_ec256_public_t *public, const sgx_ec256_signature_t* ecc_signature) {
// invalid parameter handling
if((data == NULL) || (data_size == 0) || (public == NULL) || (ecc_signature == NULL)) {
if((firmware == NULL) || (firmware_size == 0) || (public == NULL) || (ecc_signature == NULL)) {
return SGX_ERROR_INVALID_PARAMETER;
}
@ -214,7 +235,7 @@ static sgx_status_t verify_signature(const uint8_t *data, uint32_t data_size, co
// verify signature
uint8_t result;
sgx_status_t verification_status = sgx_ecdsa_verify(data, data_size, public, ecc_signature, &result, ecc_handle);
sgx_status_t verification_status = sgx_ecdsa_verify(firmware, firmware_size, public, ecc_signature, &result, ecc_handle);
// handle failed verification process
if(verification_status != SGX_SUCCESS) {
@ -226,9 +247,9 @@ static sgx_status_t verify_signature(const uint8_t *data, uint32_t data_size, co
return result;
}
sgx_status_t sign_firmware(const uint8_t *data, uint32_t data_size, const uint8_t *sealed, uint32_t sealed_size, uint8_t *public_key, uint8_t *signature) {
sgx_status_t sign_firmware(const uint8_t *firmware, uint32_t firmware_size, const uint8_t *sealed, uint32_t sealed_size, uint8_t *public_key, uint8_t *signature) {
// invalid parameter handling
if((data == NULL) || (data_size == 0)) {
if((firmware == NULL) || (firmware_size == 0)) {
return SGX_ERROR_INVALID_PARAMETER;
} else if((public_key == NULL) || (signature == NULL)) {
return SGX_ERROR_INVALID_PARAMETER;
@ -258,7 +279,7 @@ sgx_status_t sign_firmware(const uint8_t *data, uint32_t data_size, const uint8_
}
// verify request
if((status = verify_signature(data, data_size, (const sgx_ec256_public_t *)public_key, (const sgx_ec256_signature_t *)signature)) != SGX_EC_VALID) {
if((status = verify_signature(firmware, firmware_size, (const sgx_ec256_public_t *)public_key, (const sgx_ec256_signature_t *)signature)) != SGX_EC_VALID) {
goto exit;
}
@ -268,7 +289,7 @@ sgx_status_t sign_firmware(const uint8_t *data, uint32_t data_size, const uint8_
}
// create signature
if((status = sgx_ecdsa_sign(data, data_size, &private, &ecc_signature, ecc_handle)) != SGX_SUCCESS) {
if((status = sgx_ecdsa_sign(firmware, firmware_size, &private, &ecc_signature, ecc_handle)) != SGX_SUCCESS) {
goto exit;
}
@ -281,9 +302,9 @@ sgx_status_t sign_firmware(const uint8_t *data, uint32_t data_size, const uint8_
return status;
}
sgx_status_t verify_firmware(const uint8_t *data, uint32_t data_size, const uint8_t *sealed, uint32_t sealed_size, const uint8_t *public_key, const uint8_t *signature) {
sgx_status_t verify_firmware(const uint8_t *firmware, uint32_t firmware_size, const uint8_t *sealed, uint32_t sealed_size, const uint8_t *public_key, const uint8_t *signature) {
// invalid parameter handling
if((data == NULL) || (data_size == 0) || (signature == NULL)) {
if((firmware == NULL) || (firmware_size == 0) || (signature == NULL)) {
return SGX_ERROR_INVALID_PARAMETER;
} else if((sealed == NULL) && (public_key == NULL)) {
return SGX_ERROR_INVALID_PARAMETER;
@ -318,5 +339,5 @@ sgx_status_t verify_firmware(const uint8_t *data, uint32_t data_size, const uint
}
// verify signature and return result
return verify_signature(data, data_size, &public, (const sgx_ec256_signature_t *)signature);
return verify_signature(firmware, firmware_size, &public, (const sgx_ec256_signature_t *)signature);
}

View file

@ -47,8 +47,8 @@ enclave {
public int get_private_key_size();
public sgx_status_t generate_key_pair([out, size=sealed_size]uint8_t *sealed, uint32_t sealed_size);
public sgx_status_t get_public_key([in, size=sealed_size]const uint8_t *sealed, uint32_t sealed_size, [out, size=64]uint8_t *public_key);
public sgx_status_t sign_firmware([in, size=data_size]const uint8_t *data, uint32_t data_size, [in, size=sealed_size]const uint8_t *sealed, uint32_t sealed_size, [in, out, size=64]uint8_t *public_key, [in, out, size=64]uint8_t *signature);
public sgx_status_t verify_firmware([in, size=data_size]const uint8_t *data, uint32_t data_size, [in, size=sealed_size]const uint8_t *sealed, uint32_t sealed_size, [in, size=64]const uint8_t *public_key, [in, size=64]const uint8_t *signature);
public sgx_status_t sign_firmware([in, size=firmware_size]const uint8_t *firmware, uint32_t firmware_size, [in, size=sealed_size]const uint8_t *sealed, uint32_t sealed_size, [in, out, size=64]uint8_t *public_key, [in, out, size=64]uint8_t *signature);
public sgx_status_t verify_firmware([in, size=firmware_size]const uint8_t *firmware, uint32_t firmware_size, [in, size=sealed_size]const uint8_t *sealed, uint32_t sealed_size, [in, size=64]const uint8_t *public_key, [in, size=64]const uint8_t *signature);
};
/*

View file

@ -36,15 +36,78 @@
#include <stdint.h>
#include <sgx_error.h>
/*
* returns the size of the sealed key pair
*/
int get_sealed_size();
/*
* returns the length of the hash used in the signature
*/
int get_digest_size();
/*
* returns the size of the signature created by the enclave
*/
int get_signature_size();
/*
* returns the size of the public key
*/
int get_public_key_size();
/*
* returns the size of the private key
*/
int get_private_key_size();
/*
* @brief generates a secp256r1 key pair and returns it sealed by the TEE
*
* @param sealed buffer to hold the sealed key pair
* @param sealed_size size of the sealed key pair
*
* @returns SGX_SUCCESS on success, else sgx error code
*/
sgx_status_t generate_key_pair(uint8_t *sealed, uint32_t sealed_size);
/*
* @brief returns the public key of the sealed key pair provided to the enclave
*
* @param sealed buffer containing the sealed key pair
* @param sealed_size size of the sealed key pair
* @param public_key buffer to hold the public key
*
* @returns SGX_SUCCESS on success, SGX_ERROR_INVALID_PARAMETER for invalid parameters, else sgx error code
*/
sgx_status_t get_public_key(const uint8_t *sealed, const uint32_t sealed_size, uint8_t *public_key);
sgx_status_t sign_firmware(const uint8_t *data, uint32_t data_size, const uint8_t *sealed, uint32_t sealed_size, uint8_t *public_key, uint8_t *signature);
sgx_status_t verify_firmware(const uint8_t *data, uint32_t data_size, const uint8_t *sealed, uint32_t sealed_size, const uint8_t *public_key, const uint8_t *signature);
/*
* @brief signs the firmware provided by an authorized employee
*
* @param firmware buffer containing the firmware
* @param firmware_size size of the sealed key pair
* @param sealed buffer containing the sealed key pair
* @param sealed_size size of the sealed key pair
* @param public_key buffer with the employees public key; holds enclaves public key after successful signing
* @param signature buffer with the employees signature; holds the enclaves signature after successful signing
*
* @returns SGX_SUCCESS on success, SGX_ERROR_INVALID_PARAMETER for invalid parameters, else sgx error code
*/
sgx_status_t sign_firmware(const uint8_t *firmware, uint32_t firmware_size, const uint8_t *sealed, uint32_t sealed_size, uint8_t *public_key, uint8_t *signature);
/*
* @brief verifies a firmware signature provided by an authorized employee or enclave
*
* @param firmware buffer containing the firmware
* @param firmware_size size of the sealed key pair or NULL
* @param sealed buffer containing the sealed key pair
* @param sealed_size size of the sealed key pair
* @param public_key buffer with the employees public key or NULL
* @param signature buffer with the employees signature
*
* @returns SGX_EC_VALID on success, SGX_EC_INVALID for invalid signatures, SGX_ERROR_INVALID_PARAMETER for invalid parameters, else sgx error code
*/
sgx_status_t verify_firmware(const uint8_t *firmware, uint32_t firmware_size, const uint8_t *sealed, uint32_t sealed_size, const uint8_t *public_key, const uint8_t *signature);
#endif /* !_ENCLAVE_H_ */

74
7-SGX_Hands-on/src/simulate Executable file
View file

@ -0,0 +1,74 @@
#!/usr/bin/env sh
set -u
# colors
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# helper function
print_and_execute() {
local color=$1
shift
echo "⚡ ${color}$@${NC}"
eval "$@"
return $?
}
# setup
TMP=/tmp/signatureproxy
KEYDIR=../employee_keys
mkdir -p $TMP
########### Disclaimer #################
# Die Story wurde von ChatGPT erstellt #
########################################
# simulation
print_and_execute "$GREEN" "./signatureproxy proxysetup -pkey $TMP/proxy_private.bin > $TMP/proxy_public.pem"
echo "At Embedded Solutions Inc., security was paramount. The company specialized in creating firmware for a wide range of embedded devices used in critical industries, from medical equipment to automotive systems. To protect their firmware, they had implemented a sophisticated signature proxy system using Intel's SGX enclave technology."
echo "One bright morning, Alice, a senior engineer known for her meticulous work, arrived at her desk. She was tasked with signing the latest stable version of a critical medical device firmware that she had finished the previous night."
echo "With the proxy ready, Alice compiled their latest stable version. This firmware would soon run on life-saving medical devices, a fact that weighed heavily on her as she meticulously checked every detail."
print_and_execute "$GREEN" "dd if=/dev/urandom of=$TMP/firmware.bin bs=1M count=1 2> /dev/null"
echo "Once satisfied with the build, Alice signed the firmware with her private key as an assurance to the company that the firmware came from a trusted source."
print_and_execute "$GREEN" "./signatureproxy employee -ekey $KEYDIR/alice_private.pem -firm $TMP/firmware.bin > $TMP/signature_alice.der"
echo "The firmware, along with Alice's signature, was then sent to the signature proxy. The proxy, acting as a vigilant guardian, verified Alice's signature against a list of authorized keys. Her identity confirmed, the proxy resigned the firmware with its own private key."
print_and_execute "$GREEN" "cat $TMP/signature_alice.der | ./signatureproxy proxy -pkey $TMP/proxy_private.bin -epub $KEYDIR/alice_public.pem -firm $TMP/firmware.bin > $TMP/signature_for_alice.der"
echo "The final step was crucial: verifying the signed firmware to ensure it was ready for deployment. The team couldn't afford any mistakes, knowing the firmware's destination were life-saving medical devices."
print_and_execute "$GREEN" "cat $TMP/signature_for_alice.der | ./signatureproxy embedded -ppub $TMP/proxy_public.pem -firm $TMP/firmware.bin > /dev/null"
echo "\nMeanwhile, in a dark corner of the tech world, Oskar, a disgruntled former employee, was plotting his revenge. He had managed to get his hands on an old private key. With malicious intent, he set out to sign a modified version of the firmware, hoping to bypass the security measures."
echo "Oskar, driven by his vendetta, signed the firmware with his old private key, intending to trick the system and cause havoc."
print_and_execute "$RED" "./signatureproxy employee -ekey $KEYDIR/oskar_private.pem -firm $TMP/firmware.bin > $TMP/signature_oskar.der"
echo "With a smug grin, he tried to pass his signed firmware through the proxy. But the system was built to withstand such threats. The proxy, ever vigilant, scrutinized the incoming data."
print_and_execute "$RED" "cat $TMP/signature_oskar.der | ./signatureproxy proxy -pkey $TMP/proxy_private.bin -epub $KEYDIR/oskar_public.pem -firm $TMP/firmware.bin > $TMP/signature_for_oskar.der"
status=$?
if [ $status -eq 0 ]; then
echo "Oskar's firmware signing attempt seemed successful. :("
exit 1
else
echo "The proxy detected Oskar's unauthorized key and rejected the firmware. His malicious intent was thwarted, and the firmware remained secure."
fi
echo "With Oskar's attempt foiled, Embedded Solutions could breathe a sigh of relief. The integrity of their firmware was intact, safeguarded by the robust security measures of their signature proxy system. Alice and her team could continue their work with confidence, knowing that their systems were safe from internal and external threats."
echo "\nIn the meantime, Bob, another trusted engineer, was working on a firmware update for the automotive sector. This update was equally critical and needed the same level of security scrutiny."
print_and_execute "$GREEN" "dd if=/dev/urandom of=$TMP/firmware2.bin bs=1M count=1 2> /dev/null"
echo "Bob finished his work and, following the security protocols, signed the new firmware with his private key."
print_and_execute "$GREEN" "./signatureproxy employee -ekey $KEYDIR/bob_private.pem -firm $TMP/firmware2.bin > $TMP/signature_bob.der"
echo "The signed firmware was then sent to the signature proxy. As expected, the proxy verified Bob's signature and signed the firmware with its private key, ensuring the update's authenticity."
print_and_execute "$GREEN" "cat $TMP/signature_bob.der | ./signatureproxy proxy -pkey $TMP/proxy_private.bin -epub $KEYDIR/bob_public.pem -firm $TMP/firmware2.bin > $TMP/signature_for_bob.der"
echo "The final verification process confirmed that Bob's firmware update was secure and ready for deployment."
print_and_execute "$GREEN" "cat $TMP/signature_for_bob.der | ./signatureproxy embedded -ppub $TMP/proxy_public.pem -firm $TMP/firmware2.bin > /dev/null"
echo "This concludes the story of Alice, Oskar, Bob, and the secure firmware signing process at Embedded Solutions Inc. Through the diligent efforts of trusted employees and advanced security technology, the integrity and safety of their embedded devices were preserved."

View file

@ -1,38 +0,0 @@
#!/usr/bin/env sh
set -eu
TMP=/tmp/signatureproxy
KEYDIR=../employee_keys
mkdir -p $TMP
echo "At Embedded Solutions Inc., security was paramount. The company specialized in creating firmware for a wide range of embedded devices used in critical industries, from medical equipment to automotive systems. To protect their firmware, they had implemented a sophisticated signature proxy system using Intel's SGX enclave technology."
echo "One bright morning, Alice, a senior engineer known for her meticulous work, arrived at her desk. She was tasked with signing the latest stable version of a critical medical device firmware that she had finished engineering the previous night."
echo "As she settled in, the IT team, always vigilant, prepared the signature proxy. They initialized it with a secret key stored securely within the enclave, ensuring that only authorized firmware could pass through."
./signatureproxy proxysetup -pkey $TMP/proxy_private.bin > $TMP/proxy_public.pem
echo "The proxy was now ready to guard the integrity of their firmware."
echo "With the proxy ready, Alice compiled the latest stable version of the firmware. This firmware would soon run on life-saving medical devices, a fact that weighed heavily on her as she meticulously checked every detail."
dd if=/dev/urandom of=$TMP/firmware.bin bs=1M count=1 2> /dev/null
echo "Once satisfied with the build, Alice signed the firmware with her private key. This was her mark, an assurance to the company that the firmware came from a trusted source."
./signatureproxy employee -ekey $KEYDIR/alice_private.pem -firm $TMP/firmware.bin > $TMP/signature_alice.der
echo "The signed firmware, along with Alice's signature, was then sent to the signature proxy. The proxy, acting as a vigilant guardian, verified Alice's signature against a list of authorized keys. Her identity confirmed, the proxy signed the firmware with its own private key, adding an extra layer of security."
cat $TMP/signature_alice.der | ./signatureproxy proxy -pkey $TMP/proxy_private.bin -epub $KEYDIR/alice_public.pem -firm $TMP/firmware.bin > $TMP/signature_for_alice.der
echo "The final step was crucial: verifying the signed firmware to ensure it was ready for deployment. The team couldn't afford any mistakes, knowing the firmware's destination were life-saving medical devices."
cat $TMP/signature_for_alice.der | ./signatureproxy embedded -ppub $TMP/proxy_public.pem -firm $TMP/firmware.bin
echo "Meanwhile, in a dark corner of the tech world, Oskar, a disgruntled former employee, was plotting his revenge. He had managed to get his hands on an old private key. With malicious intent, he set out to sign a modified version of the firmware, hoping to bypass the security measures."
echo "Oskar, driven by his vendetta, signed the firmware with his private key, intending to trick the system and cause havoc."
./signatureproxy employee -ekey $KEYDIR/oskar_private.pem -firm $TMP/firmware.bin > $TMP/signature_oskar.der
echo "With a smug grin, he tried to pass his signed firmware through the proxy. But the system was built to withstand such threats. The proxy, ever vigilant, scrutinized the incoming data."
cat $TMP/signature_oskar.der | ./signatureproxy proxy -pkey $TMP/proxy_private.bin -epub $KEYDIR/oskar_public.pem -firm $TMP/firmware.bin > $TMP/signature_oskar.der 2> /dev/null && echo "Oskar's firmware signing attempt seemed successful. (This should not happen in a secure system!)" || echo "The proxy detected Oskar's unauthorized key and rejected the firmware. His malicious intent was thwarted, and the firmware remained secure."
echo "With Oskar's attempt foiled, Embedded Solutions could breathe a sigh of relief. The integrity of their firmware was intact, safeguarded by the robust security measures of their signature proxy system. Alice and her team could continue their work with confidence, knowing that their systems were safe from internal and external threats."
echo "This concludes the story of Alice, Oskar, and the secure firmware signing process at Embedded Solutions Inc. Through the diligent efforts of trusted employees and advanced security technology, the integrity and safety of their embedded devices were preserved."