utils.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "utils.h"
  2. #define HASH_LENGTH 32
  3. #define NONCE_LENGTH 16
  4. #define KEY_LENGTH 16
  5. #define MILLION 1E6
  6. #define IV_LENGTH 12
  7. #define EC_KEY_SIZE 32
  8. #define KEY_LENGTH 16
  9. #define TAG_SIZE 16
  10. #define CLOCKS_PER_MS (CLOCKS_PER_SEC/1000)
  11. #define AES_GCM_BLOCK_SIZE_IN_BYTES 16
  12. #define PRIME256V1_KEY_SIZE 32
  13. int AES_GCM_128_encrypt (unsigned char *plaintext, int plaintext_len, unsigned char *aad,
  14. int aad_len, unsigned char *key, unsigned char *iv, int iv_len,
  15. unsigned char *ciphertext, unsigned char *tag)
  16. {
  17. EVP_CIPHER_CTX *ctx;
  18. int len;
  19. int ciphertext_len;
  20. /* Create and initialise the context */
  21. if(!(ctx = EVP_CIPHER_CTX_new())) {
  22. printf("Failed context intialization for OpenSSL EVP\n");
  23. }
  24. /* Initialise the encryption operation. */
  25. if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)){
  26. printf("Failed AES_GCM_128 intialization for OpenSSL EVP\n");
  27. }
  28. /* Set IV length if default 12 bytes (96 bits) is not appropriate */
  29. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)){
  30. printf("Failed IV config\n");
  31. }
  32. /* Initialise key and IV */
  33. if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
  34. printf("Failed intialization for key and IV for AES_GCM\n");
  35. }
  36. /* Provide any AAD data. This can be called zero or more times as
  37. * required
  38. */
  39. //if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
  40. // printf("Failed AAD\n");
  41. /* Provide the message to be encrypted, and obtain the encrypted output.
  42. * EVP_EncryptUpdate can be called multiple times if necessary
  43. */
  44. //printf("Error code = %d\n\n", EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len));
  45. if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
  46. printf("Failed AES_GCM encrypt\n");
  47. }
  48. ciphertext_len = len;
  49. /* Finalise the encryption. Normally ciphertext bytes may be written at
  50. * this stage, but this does not occur in GCM mode
  51. */
  52. if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)){
  53. printf("Failed Finalizing ciphertext\n");
  54. }
  55. ciphertext_len += len;
  56. /* Get the tag */
  57. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag))
  58. printf("Failed tag for AES_GCM_encrypt\n");
  59. /* Clean up */
  60. EVP_CIPHER_CTX_free(ctx);
  61. return ciphertext_len;
  62. }
  63. int AES_GCM_128_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
  64. int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
  65. int iv_len, unsigned char *plaintext)
  66. {
  67. EVP_CIPHER_CTX *ctx;
  68. int len;
  69. int plaintext_len;
  70. int ret;
  71. /* Create and initialise the context */
  72. if(!(ctx = EVP_CIPHER_CTX_new()))
  73. printf("Failed context intialization for OpenSSL EVP\n");
  74. /* Initialise the decryption operation. */
  75. if(!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL))
  76. printf("Failed AES_GCM_128 intialization for OpenSSL EVP\n");
  77. /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
  78. if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
  79. printf("Failed IV config\n");
  80. /* Initialise key and IV */
  81. if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
  82. printf("Failed intialization for key and IV for AES_GCM_128\n");
  83. /* Provide any AAD data. This can be called zero or more times as
  84. * required
  85. */
  86. //if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
  87. // printf("Failed AAD\n");
  88. /* Provide the message to be decrypted, and obtain the plaintext output.
  89. * EVP_DecryptUpdate can be called multiple times if necessary
  90. */
  91. if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
  92. printf("Failed AES_GCM decrypt\n");
  93. plaintext_len = len;
  94. /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
  95. if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_SIZE, tag))
  96. printf("Failed tag for AES_GCM_decrypt\n");
  97. /* Finalise the decryption. A positive return value indicates success,
  98. * anything else is a failure - the plaintext is not trustworthy.
  99. */
  100. ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
  101. /* Clean up */
  102. EVP_CIPHER_CTX_free(ctx);
  103. if(ret > 0)
  104. {
  105. /* Success */
  106. plaintext_len += len;
  107. return plaintext_len;
  108. }
  109. else
  110. {
  111. /* Verify failed */
  112. return -1;
  113. }
  114. }
  115. int serializedSizeLSORAMRequest(uint32_t key_size, uint32_t value_size) {
  116. uint32_t serialized_request_size = key_size + value_size + 2*sizeof(uint32_t);
  117. return serialized_request_size;
  118. }
  119. /*
  120. Inputs: a target pub key, a seriailzed request and request size.
  121. Outputs: instantiates and populates serialized_request
  122. */
  123. int32_t serializeLSORAMRequest(unsigned char *key, uint32_t key_size,
  124. unsigned char *value, uint32_t value_size, unsigned char** serialized_request) {
  125. // SerializedRequest:
  126. // key_size, key bytes, value_size, value bytes
  127. uint32_t serialized_request_size = serializedSizeLSORAMRequest(key_size, value_size);
  128. *serialized_request = (unsigned char*) malloc(serialized_request_size);
  129. unsigned char* req_ptr = *serialized_request;
  130. memcpy(req_ptr, &key_size, sizeof(uint32_t));
  131. req_ptr+=sizeof(uint32_t);
  132. memcpy(req_ptr, key, key_size);
  133. req_ptr+=key_size;
  134. memcpy(req_ptr, &value_size, sizeof(uint32_t));
  135. req_ptr+=sizeof(uint32_t);
  136. memcpy(req_ptr, value, value_size);
  137. req_ptr+=value_size;
  138. return serialized_request_size;
  139. }
  140. int ECDH_encrypt(const string &request, uint32_t request_size, const string &params, string &shared_secret, string &pirquery){
  141. /*
  142. 1) Extracts Enclave public key from params
  143. 2) Samples a public key for itself
  144. 3) Performs ECDH with enclave public key and stores to encrypted_request:
  145. <client_sampled_public_key, request> encrypted with shared_secret
  146. */
  147. int ret;
  148. EC_KEY *ephemeral_key = NULL;
  149. BIGNUM *x, *y;
  150. x = BN_new();
  151. y = BN_new();
  152. BN_CTX *bn_ctx = BN_CTX_new();
  153. const EC_GROUP *curve = NULL;
  154. if(NULL == (curve = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)))
  155. printf("Setting EC_GROUP failed \n");
  156. ephemeral_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
  157. if(ephemeral_key==NULL)
  158. printf("Client: EC_KEY_new_by_curve_name Fail\n");
  159. ret = EC_KEY_generate_key(ephemeral_key);
  160. if(ret!=1)
  161. printf("Client: EC_KEY_generate_key Fail\n");
  162. const EC_POINT *pub_point;
  163. pub_point = EC_KEY_get0_public_key((const EC_KEY *) ephemeral_key);
  164. if(pub_point == NULL)
  165. printf("Client: EC_KEY_get0_public_key Fail\n");
  166. ret = EC_POINT_get_affine_coordinates_GFp(curve, pub_point, x, y, bn_ctx);
  167. if(ret==0)
  168. printf("Client: EC_POINT_get_affine_coordinates_GFp Failed \n");
  169. unsigned char *bin_x, *bin_y;
  170. uint32_t size_bin_x = BN_num_bytes(x);
  171. uint32_t size_bin_y = BN_num_bytes(y);
  172. bin_x = (unsigned char*) malloc(size_bin_x);
  173. bin_y = (unsigned char*) malloc(size_bin_y);
  174. BN_bn2bin(x, bin_x);
  175. BN_bn2bin(y, bin_y);
  176. unsigned char *serialized_client_public_key = (unsigned char*) malloc(size_bin_x + size_bin_y);
  177. memcpy(serialized_client_public_key, bin_x, size_bin_x);
  178. memcpy(serialized_client_public_key + size_bin_x, bin_y, size_bin_y);
  179. //Done with serializeing sampled client public key
  180. /*TEST snippet for key comparison at client and enclave
  181. const EC_POINT *point = EC_KEY_get0_public_key(ENCLAVE_PUBLIC_KEY);
  182. BIGNUM *x1, *y1;
  183. x1 = BN_new();
  184. y1 = BN_new();
  185. ret = EC_POINT_get_affine_coordinates_GFp(curve, point, x1, y1, bn_ctx);
  186. unsigned char *bin_point = (unsigned char*) malloc(32*2);
  187. BN_bn2bin(x1,bin_point);
  188. BN_bn2bin(y1,bin_point+32);
  189. printf("Serialized Client's Public Key at Client :\n");
  190. for(int t = 0; t < size_bin_x+size_bin_y; t++)
  191. printf("%02X", (*serialized_client_public_key)[t]);
  192. printf("\n");
  193. printf("Serialized Enclave's Public Key at Client :\n");
  194. for(int t = 0; t < size_bin_x+size_bin_y; t++)
  195. printf("%02X", bin_point[t]);
  196. printf("\n");
  197. */
  198. //Load Enclave public key from string params
  199. EC_KEY *ENCLAVE_PUBLIC_KEY;
  200. ENCLAVE_PUBLIC_KEY = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
  201. BIGNUM *x_enclave, *y_enclave;
  202. EC_POINT *pub_point_enclave = EC_POINT_new(curve);
  203. x_enclave = BN_new();
  204. y_enclave = BN_new();
  205. unsigned char *bin_x_enclave = (unsigned char*) malloc(PRIME256V1_KEY_SIZE);
  206. unsigned char *bin_y_enclave = (unsigned char*) malloc(PRIME256V1_KEY_SIZE);
  207. for(uint32_t i=0; i<PRIME256V1_KEY_SIZE; i++){
  208. bin_x_enclave[i] = params[i];
  209. bin_y_enclave[i] = params[PRIME256V1_KEY_SIZE+i];
  210. }
  211. x_enclave = BN_bin2bn(bin_x_enclave, PRIME256V1_KEY_SIZE, NULL);
  212. y_enclave = BN_bin2bn(bin_y_enclave, PRIME256V1_KEY_SIZE, NULL);
  213. if(EC_POINT_set_affine_coordinates_GFp(curve, pub_point_enclave, x_enclave, y_enclave, bn_ctx)==0)
  214. printf("EC_POINT_set_affine_coordinates FAILED \n");
  215. if(EC_KEY_set_public_key(ENCLAVE_PUBLIC_KEY, pub_point_enclave)==0)
  216. printf("EC_KEY_set_public_key FAILED \n");
  217. //Do the ECDH And encrypt request
  218. uint32_t field_size = EC_GROUP_get_degree(EC_KEY_get0_group(ENCLAVE_PUBLIC_KEY));
  219. uint32_t secret_len = (field_size+7)/8;
  220. unsigned char *secret = (unsigned char*) malloc(secret_len);
  221. //Returns a 32 byte secret
  222. secret_len = ECDH_compute_key(secret, secret_len, EC_KEY_get0_public_key(ENCLAVE_PUBLIC_KEY),
  223. ephemeral_key, NULL);
  224. unsigned char *ecdh_shared_aes_key = (unsigned char *) malloc(KEY_LENGTH);
  225. unsigned char *ecdh_iv = (unsigned char*) malloc(IV_LENGTH);
  226. memcpy(ecdh_shared_aes_key, secret, KEY_LENGTH);
  227. memcpy(ecdh_iv, secret + KEY_LENGTH, IV_LENGTH);
  228. //
  229. /*
  230. printf("Secret computed by Client :\n");
  231. for(int t = 0; t < secret_len; t++)
  232. printf("%02X", secret[t]);
  233. printf("\n");
  234. */
  235. int encrypted_request_size = request_size;
  236. unsigned char *request_cstr = (unsigned char*) malloc (request_size);
  237. for(uint32_t i = 0; i<request_size; i++)
  238. request_cstr[i] = request[i];
  239. unsigned char *encrypted_request_cstr = (unsigned char*) malloc (request_size);
  240. unsigned char *tag_cstr = (unsigned char*) malloc (TAG_SIZE);
  241. encrypted_request_size = AES_GCM_128_encrypt(request_cstr, request_size, NULL, 0, (unsigned char*) ecdh_shared_aes_key, ecdh_iv, IV_LENGTH, encrypted_request_cstr, tag_cstr);
  242. //pirquery = aes_key||iv||plainquery_{aes_key}||tag
  243. pirquery.assign((const char*) ecdh_shared_aes_key, PRIME256V1_KEY_SIZE);
  244. pirquery.append((const char*) ecdh_iv, IV_LENGTH);
  245. pirquery.append((const char*) encrypted_request_cstr, encrypted_request_size);
  246. pirquery.append((const char*) tag_cstr, TAG_SIZE);
  247. BN_CTX_free(bn_ctx);
  248. free(request_cstr);
  249. free(ecdh_shared_aes_key);
  250. free(ecdh_iv);
  251. free(encrypted_request_cstr);
  252. free(tag_cstr);
  253. return encrypted_request_size;
  254. }
  255. //hybridEncrypt();