commoncrypto_aes.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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/symmetric_cipher_priv.h>
  6. #include <CommonCrypto/CommonCryptor.h>
  7. #include <CommonCrypto/CommonHMAC.h>
  8. #include <CommonCrypto/CommonSymmetricKeywrap.h>
  9. #include "common_cryptor_spi.h"
  10. #if (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 /* macOS 10.13 */)) || \
  11. (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* iOS v11 */))
  12. # define USE_LATEST_CRYPTO_API 1
  13. #endif
  14. struct cc_aes_cipher {
  15. struct aws_symmetric_cipher cipher_base;
  16. struct _CCCryptor *encryptor_handle;
  17. struct _CCCryptor *decryptor_handle;
  18. struct aws_byte_buf working_buffer;
  19. };
  20. static int s_encrypt(struct aws_symmetric_cipher *cipher, struct aws_byte_cursor input, struct aws_byte_buf *out) {
  21. /* allow for a padded block by making sure we have at least a block of padding reserved. */
  22. size_t required_buffer_space = input.len + cipher->block_size - 1;
  23. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, required_buffer_space)) {
  24. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  25. }
  26. size_t available_write_space = out->capacity - out->len;
  27. struct cc_aes_cipher *cc_cipher = cipher->impl;
  28. size_t len_written = 0;
  29. CCStatus status = CCCryptorUpdate(
  30. cc_cipher->encryptor_handle, input.ptr, input.len, out->buffer + out->len, available_write_space, &len_written);
  31. if (status != kCCSuccess) {
  32. cipher->good = false;
  33. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  34. }
  35. out->len += len_written;
  36. return AWS_OP_SUCCESS;
  37. }
  38. static int s_decrypt(struct aws_symmetric_cipher *cipher, struct aws_byte_cursor input, struct aws_byte_buf *out) {
  39. /* allow for a padded block by making sure we have at least a block of padding reserved. */
  40. size_t required_buffer_space = input.len + cipher->block_size - 1;
  41. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, required_buffer_space)) {
  42. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  43. }
  44. size_t available_write_space = out->capacity - out->len;
  45. struct cc_aes_cipher *cc_cipher = cipher->impl;
  46. size_t len_written = 0;
  47. CCStatus status = CCCryptorUpdate(
  48. cc_cipher->decryptor_handle, input.ptr, input.len, out->buffer + out->len, available_write_space, &len_written);
  49. if (status != kCCSuccess) {
  50. cipher->good = false;
  51. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  52. }
  53. out->len += len_written;
  54. return AWS_OP_SUCCESS;
  55. }
  56. static int s_finalize_encryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  57. /* in CBC mode, this will pad the final block from the previous encrypt call, or do nothing
  58. * if we were already on a block boundary. In CTR mode this will do nothing. */
  59. size_t required_buffer_space = cipher->block_size;
  60. size_t len_written = 0;
  61. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, required_buffer_space)) {
  62. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  63. }
  64. size_t available_write_space = out->capacity - out->len;
  65. struct cc_aes_cipher *cc_cipher = cipher->impl;
  66. CCStatus status =
  67. CCCryptorFinal(cc_cipher->encryptor_handle, out->buffer + out->len, available_write_space, &len_written);
  68. if (status != kCCSuccess) {
  69. cipher->good = false;
  70. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  71. }
  72. out->len += len_written;
  73. return AWS_OP_SUCCESS;
  74. }
  75. static int s_finalize_decryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  76. /* in CBC mode, this will pad the final block from the previous encrypt call, or do nothing
  77. * if we were already on a block boundary. In CTR mode this will do nothing. */
  78. size_t required_buffer_space = cipher->block_size;
  79. size_t len_written = 0;
  80. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, required_buffer_space)) {
  81. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  82. }
  83. size_t available_write_space = out->capacity - out->len;
  84. struct cc_aes_cipher *cc_cipher = cipher->impl;
  85. CCStatus status =
  86. CCCryptorFinal(cc_cipher->decryptor_handle, out->buffer + out->len, available_write_space, &len_written);
  87. if (status != kCCSuccess) {
  88. cipher->good = false;
  89. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  90. }
  91. out->len += len_written;
  92. return AWS_OP_SUCCESS;
  93. }
  94. static int s_initialize_cbc_cipher_materials(
  95. struct cc_aes_cipher *cc_cipher,
  96. const struct aws_byte_cursor *key,
  97. const struct aws_byte_cursor *iv) {
  98. if (!cc_cipher->cipher_base.key.len) {
  99. if (key) {
  100. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, *key);
  101. } else {
  102. aws_byte_buf_init(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, AWS_AES_256_KEY_BYTE_LEN);
  103. aws_symmetric_cipher_generate_key(AWS_AES_256_KEY_BYTE_LEN, &cc_cipher->cipher_base.key);
  104. }
  105. }
  106. if (!cc_cipher->cipher_base.iv.len) {
  107. if (iv) {
  108. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, *iv);
  109. } else {
  110. aws_byte_buf_init(
  111. &cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, AWS_AES_256_CIPHER_BLOCK_SIZE);
  112. aws_symmetric_cipher_generate_initialization_vector(
  113. AWS_AES_256_CIPHER_BLOCK_SIZE, false, &cc_cipher->cipher_base.iv);
  114. }
  115. }
  116. CCCryptorStatus status = CCCryptorCreateWithMode(
  117. kCCEncrypt,
  118. kCCModeCBC,
  119. kCCAlgorithmAES,
  120. ccPKCS7Padding,
  121. cc_cipher->cipher_base.iv.buffer,
  122. cc_cipher->cipher_base.key.buffer,
  123. cc_cipher->cipher_base.key.len,
  124. NULL,
  125. 0,
  126. 0,
  127. 0,
  128. &cc_cipher->encryptor_handle);
  129. status |= CCCryptorCreateWithMode(
  130. kCCDecrypt,
  131. kCCModeCBC,
  132. kCCAlgorithmAES,
  133. ccPKCS7Padding,
  134. cc_cipher->cipher_base.iv.buffer,
  135. cc_cipher->cipher_base.key.buffer,
  136. cc_cipher->cipher_base.key.len,
  137. NULL,
  138. 0,
  139. 0,
  140. 0,
  141. &cc_cipher->decryptor_handle);
  142. return status == kCCSuccess ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  143. }
  144. static int s_reset(struct aws_symmetric_cipher *cipher) {
  145. struct cc_aes_cipher *cc_cipher = cipher->impl;
  146. if (cc_cipher->encryptor_handle) {
  147. CCCryptorRelease(cc_cipher->encryptor_handle);
  148. cc_cipher->encryptor_handle = NULL;
  149. }
  150. if (cc_cipher->decryptor_handle) {
  151. CCCryptorRelease(cc_cipher->decryptor_handle);
  152. cc_cipher->decryptor_handle = NULL;
  153. }
  154. aws_byte_buf_secure_zero(&cc_cipher->working_buffer);
  155. return AWS_OP_SUCCESS;
  156. }
  157. static void s_destroy(struct aws_symmetric_cipher *cipher) {
  158. aws_byte_buf_clean_up_secure(&cipher->key);
  159. aws_byte_buf_clean_up_secure(&cipher->iv);
  160. aws_byte_buf_clean_up_secure(&cipher->tag);
  161. aws_byte_buf_clean_up_secure(&cipher->aad);
  162. s_reset(cipher);
  163. struct cc_aes_cipher *cc_cipher = cipher->impl;
  164. aws_byte_buf_clean_up_secure(&cc_cipher->working_buffer);
  165. aws_mem_release(cipher->allocator, cc_cipher);
  166. }
  167. static int s_cbc_reset(struct aws_symmetric_cipher *cipher) {
  168. struct cc_aes_cipher *cc_cipher = cipher->impl;
  169. int ret_val = s_reset(cipher);
  170. if (ret_val == AWS_OP_SUCCESS) {
  171. ret_val = s_initialize_cbc_cipher_materials(cc_cipher, NULL, NULL);
  172. }
  173. return ret_val;
  174. }
  175. static struct aws_symmetric_cipher_vtable s_aes_cbc_vtable = {
  176. .finalize_decryption = s_finalize_decryption,
  177. .finalize_encryption = s_finalize_encryption,
  178. .decrypt = s_decrypt,
  179. .encrypt = s_encrypt,
  180. .provider = "CommonCrypto",
  181. .alg_name = "AES-CBC 256",
  182. .destroy = s_destroy,
  183. .reset = s_cbc_reset,
  184. };
  185. struct aws_symmetric_cipher *aws_aes_cbc_256_new_impl(
  186. struct aws_allocator *allocator,
  187. const struct aws_byte_cursor *key,
  188. const struct aws_byte_cursor *iv) {
  189. struct cc_aes_cipher *cc_cipher = aws_mem_calloc(allocator, 1, sizeof(struct cc_aes_cipher));
  190. cc_cipher->cipher_base.allocator = allocator;
  191. cc_cipher->cipher_base.block_size = AWS_AES_256_CIPHER_BLOCK_SIZE;
  192. cc_cipher->cipher_base.key_length_bits = AWS_AES_256_KEY_BIT_LEN;
  193. cc_cipher->cipher_base.impl = cc_cipher;
  194. cc_cipher->cipher_base.vtable = &s_aes_cbc_vtable;
  195. if (s_initialize_cbc_cipher_materials(cc_cipher, key, iv) != AWS_OP_SUCCESS) {
  196. s_destroy(&cc_cipher->cipher_base);
  197. return NULL;
  198. }
  199. cc_cipher->cipher_base.good = true;
  200. cc_cipher->cipher_base.key_length_bits = AWS_AES_256_KEY_BIT_LEN;
  201. return &cc_cipher->cipher_base;
  202. }
  203. static int s_initialize_ctr_cipher_materials(
  204. struct cc_aes_cipher *cc_cipher,
  205. const struct aws_byte_cursor *key,
  206. const struct aws_byte_cursor *iv) {
  207. if (!cc_cipher->cipher_base.key.len) {
  208. if (key) {
  209. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, *key);
  210. } else {
  211. aws_byte_buf_init(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, AWS_AES_256_KEY_BYTE_LEN);
  212. aws_symmetric_cipher_generate_key(AWS_AES_256_KEY_BYTE_LEN, &cc_cipher->cipher_base.key);
  213. }
  214. }
  215. if (!cc_cipher->cipher_base.iv.len) {
  216. if (iv) {
  217. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, *iv);
  218. } else {
  219. aws_byte_buf_init(
  220. &cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, AWS_AES_256_CIPHER_BLOCK_SIZE);
  221. aws_symmetric_cipher_generate_initialization_vector(
  222. AWS_AES_256_CIPHER_BLOCK_SIZE, true, &cc_cipher->cipher_base.iv);
  223. }
  224. }
  225. CCCryptorStatus status = CCCryptorCreateWithMode(
  226. kCCEncrypt,
  227. kCCModeCTR,
  228. kCCAlgorithmAES,
  229. ccNoPadding,
  230. cc_cipher->cipher_base.iv.buffer,
  231. cc_cipher->cipher_base.key.buffer,
  232. cc_cipher->cipher_base.key.len,
  233. NULL,
  234. 0,
  235. 0,
  236. kCCModeOptionCTR_BE,
  237. &cc_cipher->encryptor_handle);
  238. status |= CCCryptorCreateWithMode(
  239. kCCDecrypt,
  240. kCCModeCTR,
  241. kCCAlgorithmAES,
  242. ccNoPadding,
  243. cc_cipher->cipher_base.iv.buffer,
  244. cc_cipher->cipher_base.key.buffer,
  245. cc_cipher->cipher_base.key.len,
  246. NULL,
  247. 0,
  248. 0,
  249. kCCModeOptionCTR_BE,
  250. &cc_cipher->decryptor_handle);
  251. return status == kCCSuccess ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  252. }
  253. static int s_ctr_reset(struct aws_symmetric_cipher *cipher) {
  254. struct cc_aes_cipher *cc_cipher = cipher->impl;
  255. int ret_val = s_reset(cipher);
  256. if (ret_val == AWS_OP_SUCCESS) {
  257. ret_val = s_initialize_ctr_cipher_materials(cc_cipher, NULL, NULL);
  258. }
  259. return ret_val;
  260. }
  261. static struct aws_symmetric_cipher_vtable s_aes_ctr_vtable = {
  262. .finalize_decryption = s_finalize_decryption,
  263. .finalize_encryption = s_finalize_encryption,
  264. .decrypt = s_decrypt,
  265. .encrypt = s_encrypt,
  266. .provider = "CommonCrypto",
  267. .alg_name = "AES-CTR 256",
  268. .destroy = s_destroy,
  269. .reset = s_ctr_reset,
  270. };
  271. struct aws_symmetric_cipher *aws_aes_ctr_256_new_impl(
  272. struct aws_allocator *allocator,
  273. const struct aws_byte_cursor *key,
  274. const struct aws_byte_cursor *iv) {
  275. struct cc_aes_cipher *cc_cipher = aws_mem_calloc(allocator, 1, sizeof(struct cc_aes_cipher));
  276. cc_cipher->cipher_base.allocator = allocator;
  277. cc_cipher->cipher_base.block_size = AWS_AES_256_CIPHER_BLOCK_SIZE;
  278. cc_cipher->cipher_base.impl = cc_cipher;
  279. cc_cipher->cipher_base.vtable = &s_aes_ctr_vtable;
  280. if (s_initialize_ctr_cipher_materials(cc_cipher, key, iv) != AWS_OP_SUCCESS) {
  281. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  282. s_destroy(&cc_cipher->cipher_base);
  283. return NULL;
  284. }
  285. cc_cipher->cipher_base.good = true;
  286. cc_cipher->cipher_base.key_length_bits = AWS_AES_256_KEY_BIT_LEN;
  287. return &cc_cipher->cipher_base;
  288. }
  289. /*
  290. * Note that CCCryptorGCMFinal is deprecated in Mac 10.13. It also doesn't compare the tag with expected tag
  291. * https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60118.1.1/include/CommonCryptorSPI.h.auto.html
  292. */
  293. static CCStatus s_cc_crypto_gcm_finalize(struct _CCCryptor *encryptor_handle, uint8_t *buffer, size_t tag_length) {
  294. #ifdef USE_LATEST_CRYPTO_API
  295. if (__builtin_available(macOS 10.13, iOS 11.0, *)) {
  296. return CCCryptorGCMFinalize(encryptor_handle, buffer, tag_length);
  297. } else {
  298. /* We would never hit this branch for newer macOS and iOS versions because of the __builtin_available check, so we can
  299. * suppress the compiler warning. */
  300. # pragma clang diagnostic push
  301. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  302. return CCCryptorGCMFinal(encryptor_handle, buffer, &tag_length);
  303. # pragma clang diagnostic pop
  304. }
  305. #else
  306. return CCCryptorGCMFinal(encryptor_handle, buffer, &tag_length);
  307. #endif
  308. }
  309. static CCCryptorStatus s_cc_cryptor_gcm_set_iv(struct _CCCryptor *encryptor_handle, uint8_t *buffer, size_t length) {
  310. #ifdef USE_LATEST_CRYPTO_API
  311. if (__builtin_available(macOS 10.13, iOS 11.0, *)) {
  312. return CCCryptorGCMSetIV(encryptor_handle, buffer, length);
  313. } else {
  314. /* We would never hit this branch for newer macOS and iOS versions because of the __builtin_available check, so we can
  315. * suppress the compiler warning. */
  316. # pragma clang diagnostic push
  317. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  318. return CCCryptorGCMAddIV(encryptor_handle, buffer, length);
  319. # pragma clang diagnostic pop
  320. }
  321. #else
  322. return CCCryptorGCMAddIV(encryptor_handle, buffer, length);
  323. #endif
  324. }
  325. static int s_finalize_gcm_encryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  326. (void)out;
  327. /* user specification takes precedence. If its wrong its wrong */
  328. if (!cipher->tag.len) {
  329. aws_byte_buf_init(&cipher->tag, cipher->allocator, AWS_AES_256_CIPHER_BLOCK_SIZE);
  330. }
  331. struct cc_aes_cipher *cc_cipher = cipher->impl;
  332. size_t tag_length = AWS_AES_256_CIPHER_BLOCK_SIZE;
  333. CCStatus status = s_cc_crypto_gcm_finalize(cc_cipher->encryptor_handle, cipher->tag.buffer, tag_length);
  334. if (status != kCCSuccess) {
  335. cipher->good = false;
  336. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  337. }
  338. cipher->tag.len = tag_length;
  339. return AWS_OP_SUCCESS;
  340. }
  341. static int s_finalize_gcm_decryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  342. (void)out;
  343. struct cc_aes_cipher *cc_cipher = cipher->impl;
  344. size_t tag_length = AWS_AES_256_CIPHER_BLOCK_SIZE;
  345. CCStatus status = s_cc_crypto_gcm_finalize(cc_cipher->encryptor_handle, cipher->tag.buffer, tag_length);
  346. if (status != kCCSuccess) {
  347. cipher->good = false;
  348. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  349. }
  350. return AWS_OP_SUCCESS;
  351. }
  352. static int s_initialize_gcm_cipher_materials(
  353. struct cc_aes_cipher *cc_cipher,
  354. const struct aws_byte_cursor *key,
  355. const struct aws_byte_cursor *iv,
  356. const struct aws_byte_cursor *aad,
  357. const struct aws_byte_cursor *tag) {
  358. if (!cc_cipher->cipher_base.key.len) {
  359. if (key) {
  360. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, *key);
  361. } else {
  362. aws_byte_buf_init(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, AWS_AES_256_KEY_BYTE_LEN);
  363. aws_symmetric_cipher_generate_key(AWS_AES_256_KEY_BYTE_LEN, &cc_cipher->cipher_base.key);
  364. }
  365. }
  366. if (!cc_cipher->cipher_base.iv.len) {
  367. if (iv) {
  368. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, *iv);
  369. } else {
  370. /* GCM IVs are kind of a hidden implementation detail. 4 are reserved by the system for long running stream
  371. * blocks. */
  372. /* This is because there's a GMAC attached to the cipher (that's what tag is for). For that to work, it has
  373. * to control the actual counter */
  374. aws_byte_buf_init(
  375. &cc_cipher->cipher_base.iv, cc_cipher->cipher_base.allocator, AWS_AES_256_CIPHER_BLOCK_SIZE - 4);
  376. aws_symmetric_cipher_generate_initialization_vector(
  377. AWS_AES_256_CIPHER_BLOCK_SIZE - 4, false, &cc_cipher->cipher_base.iv);
  378. }
  379. }
  380. if (aad && aad->len) {
  381. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.aad, cc_cipher->cipher_base.allocator, *aad);
  382. }
  383. if (tag && tag->len) {
  384. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.tag, cc_cipher->cipher_base.allocator, *tag);
  385. }
  386. CCCryptorStatus status = CCCryptorCreateWithMode(
  387. kCCEncrypt,
  388. kCCModeGCM,
  389. kCCAlgorithmAES,
  390. ccNoPadding,
  391. NULL,
  392. cc_cipher->cipher_base.key.buffer,
  393. cc_cipher->cipher_base.key.len,
  394. NULL,
  395. 0,
  396. 0,
  397. kCCModeOptionCTR_BE,
  398. &cc_cipher->encryptor_handle);
  399. if (status != kCCSuccess) {
  400. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  401. }
  402. status = s_cc_cryptor_gcm_set_iv(
  403. cc_cipher->encryptor_handle, cc_cipher->cipher_base.iv.buffer, cc_cipher->cipher_base.iv.len);
  404. if (status != kCCSuccess) {
  405. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  406. }
  407. if (cc_cipher->cipher_base.aad.len) {
  408. status = CCCryptorGCMAddAAD(
  409. cc_cipher->encryptor_handle, cc_cipher->cipher_base.aad.buffer, cc_cipher->cipher_base.aad.len);
  410. if (status != kCCSuccess) {
  411. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  412. }
  413. }
  414. status = CCCryptorCreateWithMode(
  415. kCCDecrypt,
  416. kCCModeGCM,
  417. kCCAlgorithmAES,
  418. ccNoPadding,
  419. NULL,
  420. cc_cipher->cipher_base.key.buffer,
  421. cc_cipher->cipher_base.key.len,
  422. NULL,
  423. 0,
  424. 0,
  425. kCCModeOptionCTR_BE,
  426. &cc_cipher->decryptor_handle);
  427. if (status != kCCSuccess) {
  428. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  429. }
  430. status = s_cc_cryptor_gcm_set_iv(
  431. cc_cipher->decryptor_handle, cc_cipher->cipher_base.iv.buffer, cc_cipher->cipher_base.iv.len);
  432. if (status != kCCSuccess) {
  433. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  434. }
  435. if (cc_cipher->cipher_base.aad.len) {
  436. status = CCCryptorGCMAddAAD(
  437. cc_cipher->decryptor_handle, cc_cipher->cipher_base.aad.buffer, cc_cipher->cipher_base.aad.len);
  438. }
  439. if (status != kCCSuccess) {
  440. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  441. }
  442. return AWS_OP_SUCCESS;
  443. }
  444. static int s_gcm_reset(struct aws_symmetric_cipher *cipher) {
  445. struct cc_aes_cipher *cc_cipher = cipher->impl;
  446. int ret_val = s_reset(cipher);
  447. if (ret_val == AWS_OP_SUCCESS) {
  448. ret_val = s_initialize_gcm_cipher_materials(cc_cipher, NULL, NULL, NULL, NULL);
  449. }
  450. return ret_val;
  451. }
  452. static struct aws_symmetric_cipher_vtable s_aes_gcm_vtable = {
  453. .finalize_decryption = s_finalize_gcm_decryption,
  454. .finalize_encryption = s_finalize_gcm_encryption,
  455. .decrypt = s_decrypt,
  456. .encrypt = s_encrypt,
  457. .provider = "CommonCrypto",
  458. .alg_name = "AES-GCM 256",
  459. .destroy = s_destroy,
  460. .reset = s_gcm_reset,
  461. };
  462. struct aws_symmetric_cipher *aws_aes_gcm_256_new_impl(
  463. struct aws_allocator *allocator,
  464. const struct aws_byte_cursor *key,
  465. const struct aws_byte_cursor *iv,
  466. const struct aws_byte_cursor *aad,
  467. const struct aws_byte_cursor *tag) {
  468. struct cc_aes_cipher *cc_cipher = aws_mem_calloc(allocator, 1, sizeof(struct cc_aes_cipher));
  469. cc_cipher->cipher_base.allocator = allocator;
  470. cc_cipher->cipher_base.block_size = AWS_AES_256_CIPHER_BLOCK_SIZE;
  471. cc_cipher->cipher_base.impl = cc_cipher;
  472. cc_cipher->cipher_base.vtable = &s_aes_gcm_vtable;
  473. if (s_initialize_gcm_cipher_materials(cc_cipher, key, iv, aad, tag) != AWS_OP_SUCCESS) {
  474. s_destroy(&cc_cipher->cipher_base);
  475. return NULL;
  476. }
  477. cc_cipher->cipher_base.good = true;
  478. cc_cipher->cipher_base.key_length_bits = AWS_AES_256_KEY_BIT_LEN;
  479. return &cc_cipher->cipher_base;
  480. }
  481. static int s_keywrap_encrypt_decrypt(
  482. struct aws_symmetric_cipher *cipher,
  483. struct aws_byte_cursor input,
  484. struct aws_byte_buf *out) {
  485. struct cc_aes_cipher *cc_cipher = cipher->impl;
  486. return aws_byte_buf_append_dynamic(&cc_cipher->working_buffer, &input);
  487. }
  488. static int s_finalize_keywrap_encryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  489. struct cc_aes_cipher *cc_cipher = cipher->impl;
  490. if (cc_cipher->working_buffer.len == 0) {
  491. cipher->good = false;
  492. return aws_raise_error(AWS_ERROR_INVALID_STATE);
  493. }
  494. size_t output_buffer_len = cipher->block_size + cc_cipher->working_buffer.len;
  495. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, output_buffer_len)) {
  496. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  497. }
  498. CCCryptorStatus status = CCSymmetricKeyWrap(
  499. kCCWRAPAES,
  500. CCrfc3394_iv,
  501. CCrfc3394_ivLen,
  502. cipher->key.buffer,
  503. cipher->key.len,
  504. cc_cipher->working_buffer.buffer,
  505. cc_cipher->working_buffer.len,
  506. out->buffer,
  507. &output_buffer_len);
  508. if (status != kCCSuccess) {
  509. cipher->good = false;
  510. return aws_raise_error(AWS_ERROR_INVALID_STATE);
  511. }
  512. out->len += output_buffer_len;
  513. return AWS_OP_SUCCESS;
  514. }
  515. static int s_finalize_keywrap_decryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
  516. struct cc_aes_cipher *cc_cipher = cipher->impl;
  517. if (cc_cipher->working_buffer.len == 0) {
  518. cipher->good = false;
  519. return aws_raise_error(AWS_ERROR_INVALID_STATE);
  520. }
  521. size_t output_buffer_len = cipher->block_size + cc_cipher->working_buffer.len;
  522. if (aws_symmetric_cipher_try_ensure_sufficient_buffer_space(out, output_buffer_len)) {
  523. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  524. }
  525. CCCryptorStatus status = CCSymmetricKeyUnwrap(
  526. kCCWRAPAES,
  527. CCrfc3394_iv,
  528. CCrfc3394_ivLen,
  529. cipher->key.buffer,
  530. cipher->key.len,
  531. cc_cipher->working_buffer.buffer,
  532. cc_cipher->working_buffer.len,
  533. out->buffer,
  534. &output_buffer_len);
  535. if (status != kCCSuccess) {
  536. cipher->good = false;
  537. return aws_raise_error(AWS_ERROR_INVALID_STATE);
  538. }
  539. out->len += output_buffer_len;
  540. return AWS_OP_SUCCESS;
  541. }
  542. static struct aws_symmetric_cipher_vtable s_aes_keywrap_vtable = {
  543. .finalize_decryption = s_finalize_keywrap_decryption,
  544. .finalize_encryption = s_finalize_keywrap_encryption,
  545. .decrypt = s_keywrap_encrypt_decrypt,
  546. .encrypt = s_keywrap_encrypt_decrypt,
  547. .provider = "CommonCrypto",
  548. .alg_name = "AES-KEYWRAP 256",
  549. .destroy = s_destroy,
  550. .reset = s_reset,
  551. };
  552. struct aws_symmetric_cipher *aws_aes_keywrap_256_new_impl(
  553. struct aws_allocator *allocator,
  554. const struct aws_byte_cursor *key) {
  555. struct cc_aes_cipher *cc_cipher = aws_mem_calloc(allocator, 1, sizeof(struct cc_aes_cipher));
  556. cc_cipher->cipher_base.allocator = allocator;
  557. cc_cipher->cipher_base.block_size = AWS_AES_256_CIPHER_BLOCK_SIZE / 2;
  558. cc_cipher->cipher_base.impl = cc_cipher;
  559. cc_cipher->cipher_base.vtable = &s_aes_keywrap_vtable;
  560. if (key) {
  561. aws_byte_buf_init_copy_from_cursor(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, *key);
  562. } else {
  563. aws_byte_buf_init(&cc_cipher->cipher_base.key, cc_cipher->cipher_base.allocator, AWS_AES_256_KEY_BYTE_LEN);
  564. aws_symmetric_cipher_generate_key(AWS_AES_256_KEY_BYTE_LEN, &cc_cipher->cipher_base.key);
  565. }
  566. aws_byte_buf_init(&cc_cipher->working_buffer, allocator, (AWS_AES_256_CIPHER_BLOCK_SIZE * 2) + 8);
  567. cc_cipher->cipher_base.good = true;
  568. cc_cipher->cipher_base.key_length_bits = AWS_AES_256_KEY_BIT_LEN;
  569. return &cc_cipher->cipher_base;
  570. }