#include #include #include #include #include #include #include #include #include #include #include #include #include "enclave_u.h" #include "proxy.h" #include "util.h" struct ProxysetupArgs { char* sealed_key_file_path; char* sgx_token_path; }; char* proxysetup_syntax(void) { return "proxysetup implementation of the enclave-powered SignatureProxy\n" " outputs public key on stdout\n" " -s file path of the sealed proxy key\n" " -t file path of the sgx token\n"; } static EVP_PKEY *sgx_public_to_EVP_PKEY(const sgx_ec256_public_t *p_public) { EVP_PKEY *evp_key = NULL; EVP_PKEY_CTX *pkey_ctx = NULL; BIGNUM *bn_pub_x = NULL; BIGNUM *bn_pub_y = NULL; EC_POINT *point = NULL; EC_GROUP* group = NULL; OSSL_PARAM_BLD *params_build = NULL; OSSL_PARAM *params = NULL; const char *curvename = NULL; int nid = 0; size_t key_len; unsigned char pub_key[SGX_ECP256_KEY_SIZE+4]; group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); if (group == NULL) return NULL; do { // converts the x value of public key, represented as positive integer in little-endian into a BIGNUM bn_pub_x = BN_lebin2bn((unsigned char*)p_public->gx, sizeof(p_public->gx), bn_pub_x); if (NULL == bn_pub_x) { break; } // converts the y value of public key, represented as positive integer in little-endian into a BIGNUM bn_pub_y = BN_lebin2bn((unsigned char*)p_public->gy, sizeof(p_public->gy), bn_pub_y); if (NULL == bn_pub_y) { break; } // creates new point and assigned the group object that the point relates to point = EC_POINT_new(group); if (NULL == point) { break; } // sets point based on public key's x,y coordinates if (1 != EC_POINT_set_affine_coordinates(group, point, bn_pub_x, bn_pub_y, NULL)) { break; } // check point if the point is on curve if (1 != EC_POINT_is_on_curve(group, point, NULL)) { break; } // convert point to octet string key_len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pub_key, sizeof(pub_key), NULL); if (key_len == 0) { break; } // build OSSL_PARAM params_build = OSSL_PARAM_BLD_new(); if (NULL == params_build) { break; } nid = EC_GROUP_get_curve_name(group); if (nid == NID_undef) { break; } curvename = OBJ_nid2sn(nid); if (curvename == NULL) { break; } if (1 != OSSL_PARAM_BLD_push_utf8_string(params_build, "group", curvename, 0)) { break; } if (1 != OSSL_PARAM_BLD_push_octet_string(params_build, OSSL_PKEY_PARAM_PUB_KEY, pub_key, key_len)) { break; } params = OSSL_PARAM_BLD_to_param(params_build); if (NULL == params) { break; } // get pkey from params pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); if (NULL == pkey_ctx) { break; } if (1 != EVP_PKEY_fromdata_init(pkey_ctx)) { break; } if (1 != EVP_PKEY_fromdata(pkey_ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params)) { EVP_PKEY_free(evp_key); evp_key = NULL; } } while(0); BN_clear_free(bn_pub_x); BN_clear_free(bn_pub_y); EC_POINT_clear_free(point); OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(params_build); EVP_PKEY_CTX_free(pkey_ctx); EC_GROUP_free(group); return evp_key; } static int EVP_PKEY_to_sgx_public(EVP_PKEY* ecdsa_key, sgx_ec256_public_t* sgx_public) { EC_GROUP* group = NULL; EC_POINT *point = NULL; BIGNUM* pub_x = NULL; BIGNUM* pub_y = NULL; size_t ec_key_buf_len = 0; unsigned char ec_key_buf[1024]; int ret; int retval; group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); if (group == NULL) return 1; point = EC_POINT_new(group); if (point == NULL) return 2; ret = EVP_PKEY_get_octet_string_param(ecdsa_key, OSSL_PKEY_PARAM_PUB_KEY, ec_key_buf, 1024, &ec_key_buf_len); if (ret != 1) return 3; ret = EC_POINT_oct2point(group, point, ec_key_buf, ec_key_buf_len, NULL); if (ret != 1){ retval = 4; goto cleanup; } pub_x = BN_new(); pub_y = BN_new(); ret = EC_POINT_get_affine_coordinates(group, point, pub_x, pub_y, NULL); if (ret != 1){ retval = 5; goto cleanup; } ret = BN_bn2lebinpad(pub_x, sgx_public->gx, SGX_ECP256_KEY_SIZE); if (ret == -1){ retval = 6; goto cleanup; } ret = BN_bn2lebinpad(pub_y, sgx_public->gy, SGX_ECP256_KEY_SIZE); if (ret == -1){ retval = 7; goto cleanup; } cleanup: if (pub_x != NULL) BN_clear_free(pub_x); if (pub_y != NULL) BN_clear_free(pub_y); if (point != NULL) EC_POINT_clear_free(point); if (group != NULL) EC_GROUP_free(group); return (retval); } /* sgx_status_t pfz_ecdsa_verify_hash(const uint8_t *p_data, const sgx_ec256_public_t *p_public, const sgx_ec256_signature_t *p_signature, uint8_t *p_result, sgx_ecc_state_handle_t ecc_handle) { if ((ecc_handle == NULL) || (p_public == NULL) || (p_signature == NULL) || (p_data == NULL) || (p_result == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *public_key = NULL; BIGNUM *bn_r = NULL; BIGNUM *bn_s = NULL; ECDSA_SIG *ecdsa_sig = NULL; unsigned char *sig_data = NULL; size_t sig_size = 0; sgx_status_t retval = SGX_ERROR_UNEXPECTED; int ret = -1; *p_result = SGX_EC_INVALID_SIGNATURE; do { public_key = pfz_get_pub_key_from_coords(p_public, ecc_handle); if(NULL == public_key) { break; } // converts the x value of the signature, represented as positive integer in little-endian into a BIGNUM // bn_r = BN_lebin2bn((unsigned char*)p_signature->x, sizeof(p_signature->x), 0); if (NULL == bn_r) { break; } // converts the y value of the signature, represented as positive integer in little-endian into a BIGNUM // bn_s = BN_lebin2bn((unsigned char*)p_signature->y, sizeof(p_signature->y), 0); if (NULL == bn_s) { break; } // allocates a new ECDSA_SIG structure (note: this function also allocates the BIGNUMs) and initialize it // ecdsa_sig = ECDSA_SIG_new(); if (NULL == ecdsa_sig) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // setes the r and s values of ecdsa_sig // calling this function transfers the memory management of the values to the ECDSA_SIG object, // and therefore the values that have been passed in should not be freed directly after this function has been called // if (1 != ECDSA_SIG_set0(ecdsa_sig, bn_r, bn_s)) { ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; break; } sig_size = i2d_ECDSA_SIG(ecdsa_sig, &sig_data); if (sig_size <= 0) { break; } ctx = EVP_PKEY_CTX_new(public_key, NULL); if (!ctx) { break; } if (1 != EVP_PKEY_verify_init(ctx)) { break; } if (1 != EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256())) { break; } ret = EVP_PKEY_verify(ctx, sig_data, sig_size, p_data, SGX_SHA256_HASH_SIZE); if (ret < 0) { break; } // sets the p_result based on verification result // if (ret == 1) *p_result = SGX_EC_VALID; retval = SGX_SUCCESS; } while(0); if (ecdsa_sig) { ECDSA_SIG_free(ecdsa_sig); bn_r = NULL; bn_s = NULL; } if (ctx) EVP_PKEY_CTX_free(ctx); if (public_key) EVP_PKEY_free(public_key); if (bn_r) BN_clear_free(bn_r); if (bn_s) BN_clear_free(bn_s); return retval; } sgx_status_t pfz_ecc256_open_context(sgx_ecc_state_handle_t* p_ecc_handle) { if (p_ecc_handle == NULL) { return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t retval = SGX_SUCCESS; EC_GROUP* ec_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); if (NULL == ec_group) { retval = SGX_ERROR_UNEXPECTED; } else { *p_ecc_handle = (void*)ec_group; } return retval; } sgx_status_t pfz_ecdsa_verify(const uint8_t *p_data, uint32_t data_size, const sgx_ec256_public_t *p_public, const sgx_ec256_signature_t *p_signature, uint8_t *p_result, sgx_ecc_state_handle_t ecc_handle) { if ((ecc_handle == NULL) || (p_public == NULL) || (p_signature == NULL) || (p_data == NULL) || (data_size < 1) || (p_result == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } unsigned char digest[SGX_SHA256_HASH_SIZE] = { 0 }; SHA256((const unsigned char *)p_data, data_size, (unsigned char *)digest); return (pfz_ecdsa_verify_hash(digest, p_public, p_signature, p_result, ecc_handle)); } */ int handle_proxysetup(int argc, char** argv) { struct ProxysetupArgs args = { NULL, NULL }; FILE* sealed_file; sgx_status_t sgx_ret; /* * Parse Input */ int i = 0; while(i < argc) { if(strcmp(argv[i], "-s")==0 && argc-i >=2){ args.sealed_key_file_path = argv[i+1]; i += 2; }else if(strcmp(argv[i], "-t")==0 && argc-i >=2){ args.sgx_token_path = argv[i+1]; i += 2; }else syntax_exit(); } if(args.sealed_key_file_path == NULL) syntax_exit(); /* * Initialize SGX Enclave */ if (initialize_enclave(args.sgx_token_path) != 0) exit(1); /* * Setup Sealed Keypair */ sealed_file = fopen(args.sealed_key_file_path, "wb"); if(sealed_file == NULL){ perror("Error opening sealed_key_file file"); exit(1); } int sealed_size; sgx_ret = get_sealed_size(get_global_eid(), &sealed_size); if (sgx_ret != SGX_SUCCESS) { print_error_message(sgx_ret); exit (1); } uint8_t* sealed = malloc(sizeof(uint8_t)*sealed_size); if (sealed == NULL) { fprintf(stderr, "failed to allocate for sealed key"); exit(1); } /* * Use Enclave To Generate Keypair */ generate_key_pair(get_global_eid(), &sgx_ret, sealed, sealed_size); if (sgx_ret != SGX_SUCCESS) { print_error_message(sgx_ret); exit (1); } /* * Store Sealed Keypair */ if (fwrite(sealed, sealed_size, 1, sealed_file) != 1 || ferror(sealed_file) != 0) { fprintf(stderr, "failed to write sealed key"); exit(1); } fflush(sealed_file); fclose(sealed_file); /* * Fetch Public Key From Enclave And Print */ sgx_ec256_public_t sgx_public_key; get_public_key(get_global_eid(), &sgx_ret, sealed, sealed_size, (uint8_t*)&sgx_public_key); if (sgx_ret != SGX_SUCCESS) { print_error_message(sgx_ret); exit (1); } EVP_PKEY* public_key = sgx_public_to_EVP_PKEY(&sgx_public_key); if (PEM_write_PUBKEY(stdout, public_key, NULL, NULL) != 1) { fprintf(stderr, "could not write publickey\n"); exit (EXIT_FAILURE); } fflush(stdout); EVP_PKEY_free(public_key); free(sealed); exit(0); }