137 lines
3.3 KiB
C
137 lines
3.3 KiB
C
|
#include <errno.h>
|
||
|
#include <sgx_urts.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "employee.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
#include <openssl/core_names.h>
|
||
|
#include <openssl/evp.h>
|
||
|
#include <openssl/pem.h>
|
||
|
|
||
|
#define HASH_BYTES 32
|
||
|
#define HASH_CHUNK_BYTES 32
|
||
|
#define KEY_BYTES 32
|
||
|
|
||
|
struct EmployeeArgs {
|
||
|
char* key_path;
|
||
|
char* firmware_path;
|
||
|
};
|
||
|
|
||
|
char* employee_syntax(void) {
|
||
|
return
|
||
|
"employee mock up implementation of the employee binary\n"
|
||
|
" outputs signature on stdout\n"
|
||
|
" WARNING: output is in binary format, may mess up terminal\n"
|
||
|
" -ekey <path> file path of the PEM encoded private key of the employee\n"
|
||
|
" -firm <path> path of the firmware\n";
|
||
|
}
|
||
|
|
||
|
int handle_employee(int argc, char** argv) {
|
||
|
struct EmployeeArgs args = {
|
||
|
NULL,
|
||
|
NULL
|
||
|
};
|
||
|
FILE* key_file = NULL;
|
||
|
uint8_t* firmware_buf;
|
||
|
size_t firmware_len;
|
||
|
EVP_PKEY* key = NULL;
|
||
|
EVP_MD_CTX *mdctx = NULL;
|
||
|
size_t sig_len;
|
||
|
unsigned char* sig = NULL;
|
||
|
|
||
|
/*
|
||
|
* Parse Input
|
||
|
*/
|
||
|
|
||
|
int i = 0;
|
||
|
while(i < argc) {
|
||
|
if(strcmp(argv[i], "-ekey")==0 && argc-i >=2){
|
||
|
args.key_path = argv[i+1];
|
||
|
i += 2;
|
||
|
}else if(strcmp(argv[i], "-firm")==0 && argc-i >=2){
|
||
|
args.firmware_path = argv[i+1];
|
||
|
i += 2;
|
||
|
}else
|
||
|
syntax_exit();
|
||
|
}
|
||
|
|
||
|
if(args.key_path == NULL)
|
||
|
syntax_exit();
|
||
|
|
||
|
/*
|
||
|
* Load Signing Key
|
||
|
*/
|
||
|
|
||
|
key_file = fopen(args.key_path, "rb");
|
||
|
if(key_file == NULL){
|
||
|
perror("Error opening key file");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
key = PEM_read_PrivateKey(key_file, &key, NULL, NULL);
|
||
|
if(key == NULL) {
|
||
|
fprintf(stderr, "failed to read key\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
fclose(key_file);
|
||
|
|
||
|
/*
|
||
|
* Sign Firmware
|
||
|
*/
|
||
|
|
||
|
|
||
|
mdctx = EVP_MD_CTX_new();
|
||
|
if (EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key) != 1) {
|
||
|
fprintf(stderr, "Message digest initialization failed.\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if (load_file(args.firmware_path, &firmware_buf, &firmware_len) != 0) {
|
||
|
fprintf(stderr, "failed to read firmware\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
if (EVP_DigestSignUpdate(mdctx, firmware_buf, firmware_len) != 1) {
|
||
|
printf("Message digest update failed.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
free(firmware_buf);
|
||
|
|
||
|
// call with empty sig to get length
|
||
|
if (EVP_DigestSignFinal(mdctx, NULL, &sig_len) != 1) {
|
||
|
printf("Message digest finalization failed.\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
// allocate signature buffer
|
||
|
sig = malloc(sizeof(unsigned char) * sig_len);
|
||
|
if(sig == NULL){
|
||
|
perror("could not initialize digest buffer");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
// load signature into buffer
|
||
|
if (EVP_DigestSignFinal(mdctx, sig, &sig_len) != 1) {
|
||
|
printf("Message digest finalization failed.\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
fwrite(sig, sig_len, 1, stdout);
|
||
|
if (ferror(stdout) != 0) {
|
||
|
fprintf(stdout, "failed to write signature to stdout\n");
|
||
|
exit (EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
fflush(stdout);
|
||
|
|
||
|
// free all allocated resources
|
||
|
free(sig);
|
||
|
EVP_MD_CTX_free(mdctx);
|
||
|
EVP_PKEY_free(key);
|
||
|
exit (EXIT_SUCCESS);
|
||
|
}
|