0

I'm trying to load a public key that I've gotten from an SGX enclave into an OpenSSL Elliptic Curve Public Key object.

The crypto library built into the SGX SDK uses points on SECP256R1 for public keys, and represents them as an (x,y) pair. So I attempted to do the following:

1) Extract the affine coordinates (x,y) from the SGX object.

2) Create an OpenSSL public key object on SECP256R1.

3) Set it to (x,y).

The last call however, fails with error message: "error:1007C06B:elliptic curve routines:EC_POINT_set_affine_coordinates_GFp:point is not on curve". Where can this have gone wrong? Can it be an endianness issue?

#include <stdio.h>

#include <sgx_tcrypto.h>

#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <openssl/err.h>

const sgx_ec256_public_t sgx_pk;
const sgx_ec256_private_t sgx_sk;

int main()
{
    //init openssl objects
    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); //assuming this the same as secp256r1
    BN_CTX *bn_ctx = BN_CTX_new();

    //extract affine coordinates from sgx object
    BIGNUM *x = BN_bin2bn((uint8_t*)&sgx_pk.gx, sizeof(sgx_pk) / 2, NULL);
    BIGNUM *y = BN_bin2bn((uint8_t*)&sgx_pk.gy, sizeof(sgx_pk) / 2, NULL);

    //create openssl key and load the coordinates into it
    EC_KEY *ec_key = EC_KEY_new();
    EC_KEY_set_group(ec_key, group);
    EC_KEY_set_public_key_affine_coordinates(ec_key, x, y);

    //last call fails. extract error
    long error_code = ERR_get_error();
    char error_string[300];
    ERR_error_string_n(error_code, error_string, sizeof(error_string));
    puts(error_string);

    return 0;
}

For reference, a sample key pair is defined here:

const sgx_ec256_private_t sgx_sk =
{
    0xc1, 0xe7, 0x59, 0x90, 0x4e, 0x80, 0xa5, 0x52,
    0x45, 0x25, 0xec, 0x2a, 0xc, 0x98, 0x89, 0x6e,
    0x63, 0x96, 0x4d, 0x5d, 0x58, 0x48, 0x86, 0xf4,
    0x9b, 0x70, 0xad, 0xb5, 0xa2, 0x56, 0xe9, 0x13
};

const sgx_ec256_public_t sgx_pk =
{
    0x82, 0xcb, 0x6f, 0x41, 0x3a, 0xd4, 0xfa, 0x57,
    0x6c, 0xc4, 0x1b, 0x77, 0xf6, 0xd9, 0x51, 0xc1,
    0xbc, 0x17, 0x7a, 0x88, 0xd0, 0x2e, 0x94, 0xd6,
    0x91, 0xa3, 0x1d, 0x75, 0xc, 0xbf, 0xa9, 0xca,
    0x8, 0x6c, 0xf3, 0x78, 0x92, 0xdb, 0x2f, 0x52,
    0x0, 0x44, 0x20, 0xd6, 0xa, 0xd3, 0x58, 0x3,
    0xb2, 0x35, 0xda, 0xe2, 0x1b, 0xdb, 0x2b, 0xd2,
    0xb0, 0xaf, 0x5e, 0x29, 0xc8, 0xb4, 0x93, 0x41
};
Arya Pourtabatabaie
  • 705
  • 2
  • 7
  • 22

1 Answers1

1

It was indeed an endianness issue. The following C++ code works:

#include <stdio.h>
#include <algorithm>

#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <openssl/err.h>

#include <sgx_tcrypto.h>

extern const sgx_ec256_public_t sgx_pk;
extern const sgx_ec256_private_t sgx_sk;

int main()
{
  //init openssl objects
  EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 
  //assuming this the same as secp256r1
  BN_CTX *bn_ctx = BN_CTX_new();

  //extract affine coordinates from sgx object
  sgx_ec256_public_t sgx_pk_reversed;
  constexpr size_t COORDINATE_SIZE = sizeof(sgx_ec256_public_t) / 2;
  std::reverse_copy(sgx_pk.gx, sgx_pk.gx + COORDINATE_SIZE, sgx_pk_reversed.gx);
  std::reverse_copy(sgx_pk.gy, sgx_pk.gy + COORDINATE_SIZE, sgx_pk_reversed.gy);

  BIGNUM *x = BN_bin2bn((uint8_t*)&sgx_pk_reversed.gx, COORDINATE_SIZE, NULL);
  BIGNUM *y = BN_bin2bn((uint8_t*)&sgx_pk_reversed.gy, COORDINATE_SIZE, NULL);

  //create openssl key and load the coordinates into it
  EC_KEY *ec_key = EC_KEY_new();
  EC_KEY_set_group(ec_key, group);

  if (1 == EC_KEY_set_public_key_affine_coordinates(ec_key, x, y))
    puts("Holy shit it worked.");

  return 0;
}
Arya Pourtabatabaie
  • 705
  • 2
  • 7
  • 22