securityframework_ecc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/cal/private/ecc.h>
  6. #include <aws/cal/cal.h>
  7. #include <aws/cal/private/der.h>
  8. #include <Security/SecKey.h>
  9. #include <Security/Security.h>
  10. #if !defined(AWS_OS_IOS)
  11. # include <Security/SecSignVerifyTransform.h>
  12. #endif
  13. struct commoncrypto_ecc_key_pair {
  14. struct aws_ecc_key_pair key_pair;
  15. SecKeyRef priv_key_ref;
  16. SecKeyRef pub_key_ref;
  17. CFAllocatorRef cf_allocator;
  18. };
  19. static uint8_t s_preamble = 0x04;
  20. static size_t s_der_overhead = 8;
  21. static int s_sign_message(
  22. const struct aws_ecc_key_pair *key_pair,
  23. const struct aws_byte_cursor *message,
  24. struct aws_byte_buf *signature_output) {
  25. struct commoncrypto_ecc_key_pair *cc_key = key_pair->impl;
  26. if (!cc_key->priv_key_ref) {
  27. return aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
  28. }
  29. CFDataRef hash_ref = CFDataCreateWithBytesNoCopy(NULL, message->ptr, message->len, kCFAllocatorNull);
  30. AWS_FATAL_ASSERT(hash_ref && "No allocations should have happened here, this function shouldn't be able to fail.");
  31. CFErrorRef error = NULL;
  32. CFDataRef signature =
  33. SecKeyCreateSignature(cc_key->priv_key_ref, kSecKeyAlgorithmECDSASignatureDigestX962, hash_ref, &error);
  34. if (error) {
  35. CFRelease(hash_ref);
  36. return aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
  37. }
  38. struct aws_byte_cursor to_write =
  39. aws_byte_cursor_from_array(CFDataGetBytePtr(signature), CFDataGetLength(signature));
  40. if (aws_byte_buf_append(signature_output, &to_write)) {
  41. CFRelease(signature);
  42. CFRelease(hash_ref);
  43. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  44. }
  45. CFRelease(signature);
  46. CFRelease(hash_ref);
  47. return AWS_OP_SUCCESS;
  48. }
  49. static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) {
  50. return aws_ecc_key_coordinate_byte_size_from_curve_name(key_pair->curve_name) * 2 + s_der_overhead;
  51. }
  52. static int s_verify_signature(
  53. const struct aws_ecc_key_pair *key_pair,
  54. const struct aws_byte_cursor *message,
  55. const struct aws_byte_cursor *signature) {
  56. struct commoncrypto_ecc_key_pair *cc_key = key_pair->impl;
  57. if (!cc_key->pub_key_ref) {
  58. return aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
  59. }
  60. CFDataRef hash_ref = CFDataCreateWithBytesNoCopy(NULL, message->ptr, message->len, kCFAllocatorNull);
  61. CFDataRef signature_ref = CFDataCreateWithBytesNoCopy(NULL, signature->ptr, signature->len, kCFAllocatorNull);
  62. AWS_FATAL_ASSERT(hash_ref && "No allocations should have happened here, this function shouldn't be able to fail.");
  63. AWS_FATAL_ASSERT(
  64. signature_ref && "No allocations should have happened here, this function shouldn't be able to fail.");
  65. CFErrorRef error = NULL;
  66. bool verified = SecKeyVerifySignature(
  67. cc_key->pub_key_ref, kSecKeyAlgorithmECDSASignatureDigestX962, hash_ref, signature_ref, &error);
  68. CFRelease(signature_ref);
  69. CFRelease(hash_ref);
  70. return verified ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
  71. }
  72. static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) {
  73. /* we already have a public key, just lie and tell them we succeeded */
  74. if (key_pair->pub_x.buffer && key_pair->pub_x.len) {
  75. return AWS_OP_SUCCESS;
  76. }
  77. return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
  78. }
  79. static void s_destroy_key(struct aws_ecc_key_pair *key_pair) {
  80. if (key_pair) {
  81. struct commoncrypto_ecc_key_pair *cc_key = key_pair->impl;
  82. if (cc_key->pub_key_ref) {
  83. CFRelease(cc_key->pub_key_ref);
  84. }
  85. if (cc_key->priv_key_ref) {
  86. CFRelease(cc_key->priv_key_ref);
  87. }
  88. if (cc_key->cf_allocator) {
  89. aws_wrapped_cf_allocator_destroy(cc_key->cf_allocator);
  90. }
  91. aws_byte_buf_clean_up_secure(&key_pair->key_buf);
  92. aws_mem_release(key_pair->allocator, cc_key);
  93. }
  94. }
  95. static struct aws_ecc_key_pair_vtable s_key_pair_vtable = {
  96. .sign_message = s_sign_message,
  97. .signature_length = s_signature_length,
  98. .verify_signature = s_verify_signature,
  99. .derive_pub_key = s_derive_public_key,
  100. .destroy = s_destroy_key,
  101. };
  102. static struct commoncrypto_ecc_key_pair *s_alloc_pair_and_init_buffers(
  103. struct aws_allocator *allocator,
  104. enum aws_ecc_curve_name curve_name,
  105. struct aws_byte_cursor pub_x,
  106. struct aws_byte_cursor pub_y,
  107. struct aws_byte_cursor priv_key) {
  108. struct commoncrypto_ecc_key_pair *cc_key_pair =
  109. aws_mem_calloc(allocator, 1, sizeof(struct commoncrypto_ecc_key_pair));
  110. if (!cc_key_pair) {
  111. return NULL;
  112. }
  113. aws_atomic_init_int(&cc_key_pair->key_pair.ref_count, 1);
  114. cc_key_pair->key_pair.impl = cc_key_pair;
  115. cc_key_pair->key_pair.allocator = allocator;
  116. cc_key_pair->cf_allocator = aws_wrapped_cf_allocator_new(allocator);
  117. if (!cc_key_pair->cf_allocator) {
  118. goto error;
  119. }
  120. size_t s_key_coordinate_size = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name);
  121. if (!s_key_coordinate_size) {
  122. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  123. goto error;
  124. }
  125. if ((pub_x.ptr && pub_x.len != s_key_coordinate_size) || (pub_y.ptr && pub_y.len != s_key_coordinate_size) ||
  126. (priv_key.ptr && priv_key.len != s_key_coordinate_size)) {
  127. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  128. goto error;
  129. }
  130. size_t total_buffer_size = s_key_coordinate_size * 3 + 1;
  131. if (aws_byte_buf_init(&cc_key_pair->key_pair.key_buf, allocator, total_buffer_size)) {
  132. goto error;
  133. }
  134. memset(cc_key_pair->key_pair.key_buf.buffer, 0, cc_key_pair->key_pair.key_buf.len);
  135. aws_byte_buf_write_u8(&cc_key_pair->key_pair.key_buf, s_preamble);
  136. if (pub_x.ptr && pub_y.ptr) {
  137. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &pub_x);
  138. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &pub_y);
  139. } else {
  140. cc_key_pair->key_pair.key_buf.len += s_key_coordinate_size * 2;
  141. }
  142. if (priv_key.ptr) {
  143. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &priv_key);
  144. }
  145. if (pub_x.ptr) {
  146. cc_key_pair->key_pair.pub_x =
  147. aws_byte_buf_from_array(cc_key_pair->key_pair.key_buf.buffer + 1, s_key_coordinate_size);
  148. cc_key_pair->key_pair.pub_y =
  149. aws_byte_buf_from_array(cc_key_pair->key_pair.pub_x.buffer + s_key_coordinate_size, s_key_coordinate_size);
  150. }
  151. cc_key_pair->key_pair.priv_d = aws_byte_buf_from_array(
  152. cc_key_pair->key_pair.key_buf.buffer + 1 + (s_key_coordinate_size * 2), s_key_coordinate_size);
  153. cc_key_pair->key_pair.vtable = &s_key_pair_vtable;
  154. cc_key_pair->key_pair.curve_name = curve_name;
  155. return cc_key_pair;
  156. error:
  157. s_destroy_key(&cc_key_pair->key_pair);
  158. return NULL;
  159. }
  160. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key_impl(
  161. struct aws_allocator *allocator,
  162. enum aws_ecc_curve_name curve_name,
  163. const struct aws_byte_cursor *priv_key) {
  164. struct aws_byte_cursor empty_cur;
  165. AWS_ZERO_STRUCT(empty_cur);
  166. struct commoncrypto_ecc_key_pair *cc_key_pair =
  167. s_alloc_pair_and_init_buffers(allocator, curve_name, empty_cur, empty_cur, *priv_key);
  168. if (!cc_key_pair) {
  169. return NULL;
  170. }
  171. CFMutableDictionaryRef key_attributes = NULL;
  172. CFDataRef private_key_data = CFDataCreate(
  173. cc_key_pair->cf_allocator, cc_key_pair->key_pair.key_buf.buffer, cc_key_pair->key_pair.key_buf.len);
  174. if (!private_key_data) {
  175. goto error;
  176. }
  177. key_attributes = CFDictionaryCreateMutable(cc_key_pair->cf_allocator, 6, NULL, NULL);
  178. if (!key_attributes) {
  179. goto error;
  180. }
  181. CFDictionaryAddValue(key_attributes, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
  182. CFDictionaryAddValue(key_attributes, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
  183. CFIndex key_size_bits = cc_key_pair->key_pair.priv_d.len * 8;
  184. CFDictionaryAddValue(key_attributes, kSecAttrKeySizeInBits, &key_size_bits);
  185. CFDictionaryAddValue(key_attributes, kSecAttrCanSign, kCFBooleanTrue);
  186. CFDictionaryAddValue(key_attributes, kSecAttrCanVerify, kCFBooleanFalse);
  187. CFDictionaryAddValue(key_attributes, kSecAttrCanDerive, kCFBooleanTrue);
  188. CFErrorRef error = NULL;
  189. cc_key_pair->priv_key_ref = SecKeyCreateWithData(private_key_data, key_attributes, &error);
  190. if (error) {
  191. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  192. CFRelease(error);
  193. goto error;
  194. }
  195. CFRelease(key_attributes);
  196. CFRelease(private_key_data);
  197. return &cc_key_pair->key_pair;
  198. error:
  199. if (private_key_data) {
  200. CFRelease(private_key_data);
  201. }
  202. if (key_attributes) {
  203. CFRelease(key_attributes);
  204. }
  205. s_destroy_key(&cc_key_pair->key_pair);
  206. return NULL;
  207. }
  208. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key_impl(
  209. struct aws_allocator *allocator,
  210. enum aws_ecc_curve_name curve_name,
  211. const struct aws_byte_cursor *public_key_x,
  212. const struct aws_byte_cursor *public_key_y) {
  213. struct aws_byte_cursor empty_cur;
  214. AWS_ZERO_STRUCT(empty_cur);
  215. struct commoncrypto_ecc_key_pair *cc_key_pair =
  216. s_alloc_pair_and_init_buffers(allocator, curve_name, *public_key_x, *public_key_y, empty_cur);
  217. if (!cc_key_pair) {
  218. return NULL;
  219. }
  220. CFMutableDictionaryRef key_attributes = NULL;
  221. CFDataRef pub_key_data = CFDataCreate(
  222. cc_key_pair->cf_allocator, cc_key_pair->key_pair.key_buf.buffer, cc_key_pair->key_pair.key_buf.len);
  223. if (!pub_key_data) {
  224. goto error;
  225. }
  226. key_attributes = CFDictionaryCreateMutable(cc_key_pair->cf_allocator, 6, NULL, NULL);
  227. if (!key_attributes) {
  228. goto error;
  229. }
  230. CFDictionaryAddValue(key_attributes, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
  231. CFDictionaryAddValue(key_attributes, kSecAttrKeyClass, kSecAttrKeyClassPublic);
  232. CFIndex key_size_bits = cc_key_pair->key_pair.pub_x.len * 8;
  233. CFDictionaryAddValue(key_attributes, kSecAttrKeySizeInBits, &key_size_bits);
  234. CFDictionaryAddValue(key_attributes, kSecAttrCanSign, kCFBooleanFalse);
  235. CFDictionaryAddValue(key_attributes, kSecAttrCanVerify, kCFBooleanTrue);
  236. CFDictionaryAddValue(key_attributes, kSecAttrCanDerive, kCFBooleanFalse);
  237. CFErrorRef error = NULL;
  238. cc_key_pair->pub_key_ref = SecKeyCreateWithData(pub_key_data, key_attributes, &error);
  239. if (error) {
  240. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  241. CFRelease(error);
  242. goto error;
  243. }
  244. CFRelease(key_attributes);
  245. CFRelease(pub_key_data);
  246. return &cc_key_pair->key_pair;
  247. error:
  248. if (key_attributes) {
  249. CFRelease(key_attributes);
  250. }
  251. if (pub_key_data) {
  252. CFRelease(pub_key_data);
  253. }
  254. s_destroy_key(&cc_key_pair->key_pair);
  255. return NULL;
  256. }
  257. #if !defined(AWS_OS_IOS)
  258. struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random(
  259. struct aws_allocator *allocator,
  260. enum aws_ecc_curve_name curve_name) {
  261. struct commoncrypto_ecc_key_pair *cc_key_pair =
  262. aws_mem_calloc(allocator, 1, sizeof(struct commoncrypto_ecc_key_pair));
  263. if (!cc_key_pair) {
  264. return NULL;
  265. }
  266. CFDataRef sec_key_export_data = NULL;
  267. CFStringRef key_size_cf_str = NULL;
  268. CFMutableDictionaryRef key_attributes = NULL;
  269. struct aws_der_decoder *decoder = NULL;
  270. aws_atomic_init_int(&cc_key_pair->key_pair.ref_count, 1);
  271. cc_key_pair->key_pair.impl = cc_key_pair;
  272. cc_key_pair->key_pair.allocator = allocator;
  273. cc_key_pair->cf_allocator = aws_wrapped_cf_allocator_new(allocator);
  274. if (!cc_key_pair->cf_allocator) {
  275. goto error;
  276. }
  277. size_t key_coordinate_size = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name);
  278. if (!key_coordinate_size) {
  279. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  280. goto error;
  281. }
  282. key_attributes = CFDictionaryCreateMutable(cc_key_pair->cf_allocator, 6, NULL, NULL);
  283. if (!key_attributes) {
  284. goto error;
  285. }
  286. CFDictionaryAddValue(key_attributes, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
  287. CFDictionaryAddValue(key_attributes, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
  288. CFIndex key_size_bits = key_coordinate_size * 8;
  289. char key_size_str[32] = {0};
  290. snprintf(key_size_str, sizeof(key_size_str), "%d", (int)key_size_bits);
  291. key_size_cf_str = CFStringCreateWithCString(cc_key_pair->cf_allocator, key_size_str, kCFStringEncodingASCII);
  292. if (!key_size_cf_str) {
  293. goto error;
  294. }
  295. CFDictionaryAddValue(key_attributes, kSecAttrKeySizeInBits, key_size_cf_str);
  296. CFErrorRef error = NULL;
  297. cc_key_pair->priv_key_ref = SecKeyCreateRandomKey(key_attributes, &error);
  298. if (error) {
  299. aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
  300. CFRelease(error);
  301. goto error;
  302. }
  303. cc_key_pair->pub_key_ref = SecKeyCopyPublicKey(cc_key_pair->priv_key_ref);
  304. /* OKAY up to here was incredibly reasonable, after this we get attacked by the bad API design
  305. * dragons.
  306. *
  307. * Summary: Apple assumed we'd never need the raw key data. Apple was wrong. So we have to export each component
  308. * into the OpenSSL format (just fancy words for DER), but the public key and private key are exported separately
  309. * for some reason. Anyways, we export the keys, use our handy dandy DER decoder and grab the raw key data out. */
  310. OSStatus ret_code = SecItemExport(cc_key_pair->priv_key_ref, kSecFormatOpenSSL, 0, NULL, &sec_key_export_data);
  311. if (ret_code != errSecSuccess) {
  312. aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
  313. goto error;
  314. }
  315. /* now we need to DER decode data */
  316. struct aws_byte_cursor key_cur =
  317. aws_byte_cursor_from_array(CFDataGetBytePtr(sec_key_export_data), CFDataGetLength(sec_key_export_data));
  318. decoder = aws_der_decoder_new(allocator, key_cur);
  319. if (!decoder) {
  320. goto error;
  321. }
  322. struct aws_byte_cursor pub_x;
  323. AWS_ZERO_STRUCT(pub_x);
  324. struct aws_byte_cursor pub_y;
  325. AWS_ZERO_STRUCT(pub_y);
  326. struct aws_byte_cursor priv_d;
  327. AWS_ZERO_STRUCT(priv_d);
  328. if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) {
  329. goto error;
  330. }
  331. AWS_ASSERT(
  332. priv_d.len == key_coordinate_size && pub_x.len == key_coordinate_size && pub_y.len == key_coordinate_size &&
  333. "Apple Security Framework had better have exported the full pair.");
  334. size_t total_buffer_size = key_coordinate_size * 3 + 1;
  335. if (aws_byte_buf_init(&cc_key_pair->key_pair.key_buf, allocator, total_buffer_size)) {
  336. goto error;
  337. }
  338. memset(cc_key_pair->key_pair.key_buf.buffer, 0, cc_key_pair->key_pair.key_buf.len);
  339. aws_byte_buf_write_u8(&cc_key_pair->key_pair.key_buf, s_preamble);
  340. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &pub_x);
  341. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &pub_y);
  342. aws_byte_buf_append(&cc_key_pair->key_pair.key_buf, &priv_d);
  343. /* cc_key_pair->key_pair.key_buf is contiguous memory, so just load up the offsets. */
  344. cc_key_pair->key_pair.pub_x =
  345. aws_byte_buf_from_array(cc_key_pair->key_pair.key_buf.buffer + 1, key_coordinate_size);
  346. cc_key_pair->key_pair.pub_y =
  347. aws_byte_buf_from_array(cc_key_pair->key_pair.pub_x.buffer + key_coordinate_size, key_coordinate_size);
  348. cc_key_pair->key_pair.priv_d =
  349. aws_byte_buf_from_array(cc_key_pair->key_pair.pub_y.buffer + key_coordinate_size, key_coordinate_size);
  350. cc_key_pair->key_pair.curve_name = curve_name;
  351. cc_key_pair->key_pair.vtable = &s_key_pair_vtable;
  352. CFRelease(sec_key_export_data);
  353. CFRelease(key_size_cf_str);
  354. CFRelease(key_attributes);
  355. aws_der_decoder_destroy(decoder);
  356. return &cc_key_pair->key_pair;
  357. error:
  358. if (decoder) {
  359. aws_der_decoder_destroy(decoder);
  360. }
  361. if (key_attributes) {
  362. CFRelease(key_attributes);
  363. }
  364. if (sec_key_export_data) {
  365. CFRelease(sec_key_export_data);
  366. }
  367. if (key_size_cf_str) {
  368. CFRelease(key_size_cf_str);
  369. }
  370. s_destroy_key(&cc_key_pair->key_pair);
  371. return NULL;
  372. }
  373. #endif /* AWS_OS_IOS */
  374. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1(
  375. struct aws_allocator *allocator,
  376. const struct aws_byte_cursor *encoded_keys) {
  377. struct aws_ecc_key_pair *key_pair = NULL;
  378. struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys);
  379. CFMutableDictionaryRef key_attributes = NULL;
  380. CFDataRef key_data = NULL;
  381. if (!decoder) {
  382. return NULL;
  383. }
  384. /* we could have private key or a public key, or a full pair. */
  385. struct aws_byte_cursor pub_x;
  386. AWS_ZERO_STRUCT(pub_x);
  387. struct aws_byte_cursor pub_y;
  388. AWS_ZERO_STRUCT(pub_y);
  389. struct aws_byte_cursor priv_d;
  390. AWS_ZERO_STRUCT(priv_d);
  391. enum aws_ecc_curve_name curve_name;
  392. if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) {
  393. goto error;
  394. }
  395. if (!pub_x.ptr && !priv_d.ptr) {
  396. aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
  397. goto error;
  398. }
  399. struct commoncrypto_ecc_key_pair *cc_key_pair =
  400. s_alloc_pair_and_init_buffers(allocator, curve_name, pub_x, pub_y, priv_d);
  401. if (!cc_key_pair) {
  402. goto error;
  403. }
  404. key_pair = &cc_key_pair->key_pair;
  405. key_data = CFDataCreate(
  406. cc_key_pair->cf_allocator, cc_key_pair->key_pair.key_buf.buffer, cc_key_pair->key_pair.key_buf.len);
  407. if (!key_data) {
  408. goto error;
  409. }
  410. key_attributes = CFDictionaryCreateMutable(cc_key_pair->cf_allocator, 6, NULL, NULL);
  411. if (!key_attributes) {
  412. goto error;
  413. }
  414. CFDictionaryAddValue(key_attributes, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
  415. if (priv_d.ptr) {
  416. CFDictionaryAddValue(key_attributes, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
  417. CFDictionaryAddValue(key_attributes, kSecAttrCanSign, kCFBooleanTrue);
  418. CFDictionaryAddValue(key_attributes, kSecAttrCanDerive, kCFBooleanTrue);
  419. if (pub_x.ptr) {
  420. CFDictionaryAddValue(key_attributes, kSecAttrCanVerify, kCFBooleanTrue);
  421. }
  422. } else if (pub_x.ptr) {
  423. CFDictionaryAddValue(key_attributes, kSecAttrKeyClass, kSecAttrKeyClassPublic);
  424. CFDictionaryAddValue(key_attributes, kSecAttrCanSign, kCFBooleanFalse);
  425. CFDictionaryAddValue(key_attributes, kSecAttrCanVerify, kCFBooleanTrue);
  426. }
  427. CFErrorRef error = NULL;
  428. cc_key_pair->priv_key_ref = SecKeyCreateWithData(key_data, key_attributes, &error);
  429. if (error) {
  430. aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
  431. }
  432. if (pub_x.ptr) {
  433. cc_key_pair->pub_key_ref = SecKeyCopyPublicKey(cc_key_pair->priv_key_ref);
  434. }
  435. CFRelease(key_attributes);
  436. CFRelease(key_data);
  437. aws_der_decoder_destroy(decoder);
  438. return key_pair;
  439. error:
  440. if (decoder) {
  441. aws_der_decoder_destroy(decoder);
  442. }
  443. if (key_attributes) {
  444. CFRelease(key_attributes);
  445. }
  446. if (key_data) {
  447. CFRelease(key_data);
  448. }
  449. if (key_pair) {
  450. s_destroy_key(key_pair);
  451. }
  452. return NULL;
  453. }