kcapi_aes.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /* kcapi_aes.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <errno.h>
  25. #include <wolfssl/wolfcrypt/settings.h>
  26. #include <wolfssl/wolfcrypt/error-crypt.h>
  27. #if !defined(NO_AES) && defined(WOLFSSL_KCAPI_AES)
  28. #if defined(HAVE_FIPS) && \
  29. defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
  30. /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
  31. #define FIPS_NO_WRAPPERS
  32. #ifdef USE_WINDOWS_API
  33. #pragma code_seg(".fipsA$g")
  34. #pragma const_seg(".fipsB$g")
  35. #endif
  36. #endif
  37. #include <wolfssl/wolfcrypt/aes.h>
  38. #include <wolfssl/wolfcrypt/logging.h>
  39. #include <wolfssl/wolfcrypt/port/kcapi/wc_kcapi.h>
  40. #ifdef NO_INLINE
  41. #include <wolfssl/wolfcrypt/misc.h>
  42. #else
  43. #define WOLFSSL_MISC_INCLUDED
  44. #include <wolfcrypt/src/misc.c>
  45. #endif
  46. /* AES-CBC */
  47. #if defined(HAVE_AES_CBC) && defined(WOLFSSL_KCAPI_AES) && \
  48. !defined(WOLFSSL_NO_KCAPI_AES_CBC)
  49. static const char WC_NAME_AESCBC[] = "cbc(aes)";
  50. int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  51. {
  52. int ret = 0;
  53. struct iovec iov;
  54. if (aes == NULL || out == NULL || in == NULL) {
  55. ret = BAD_FUNC_ARG;
  56. }
  57. if (ret == 0 && aes->handle == NULL) {
  58. ret = kcapi_cipher_init(&aes->handle, WC_NAME_AESCBC, 0);
  59. if (ret != 0) {
  60. WOLFSSL_MSG("Error with first time setup of kcapi");
  61. }
  62. }
  63. if (ret == 0 && aes->init == 0) {
  64. ret = kcapi_cipher_setkey(aes->handle, (byte*)aes->devKey,
  65. aes->keylen);
  66. if (ret != 0) {
  67. WOLFSSL_MSG("Error setting key through KCAPI");
  68. }
  69. }
  70. if (ret == 0 && aes->init == 0) {
  71. ret = (int)kcapi_cipher_stream_init_enc(aes->handle, (byte*)aes->reg,
  72. NULL, 0);
  73. if (ret != 0) {
  74. WOLFSSL_MSG("Error initializing IV through KCAPI");
  75. }
  76. }
  77. if (ret == 0) {
  78. aes->init = 1;
  79. iov.iov_base = (byte*)in;
  80. iov.iov_len = sz;
  81. ret = (int)kcapi_cipher_stream_update(aes->handle, &iov, 1);
  82. if (ret < 0) {
  83. WOLFSSL_MSG("CbcEncrypt error updating through KCAPI");
  84. }
  85. }
  86. if (ret >= 0) {
  87. iov.iov_base = out;
  88. iov.iov_len = sz;
  89. ret = (int)kcapi_cipher_stream_op(aes->handle, &iov, 1);
  90. if (ret < 0) {
  91. WOLFSSL_MSG("CbcEncrypt error with op in KCAPI");
  92. }
  93. }
  94. if (ret > 0) {
  95. ret = 0;
  96. }
  97. return ret;
  98. }
  99. #ifdef HAVE_AES_DECRYPT
  100. int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  101. {
  102. int ret = 0;
  103. struct iovec iov;
  104. if (aes == NULL || out == NULL || in == NULL || \
  105. sz % AES_BLOCK_SIZE != 0) {
  106. ret = BAD_FUNC_ARG;
  107. }
  108. if (ret == 0 && aes->handle == NULL) {
  109. ret = kcapi_cipher_init(&aes->handle, WC_NAME_AESCBC, 0);
  110. if (ret != 0) {
  111. WOLFSSL_MSG("Error with first time setup of kcapi");
  112. }
  113. }
  114. if (ret == 0 && aes->init == 0) {
  115. ret = kcapi_cipher_setkey(aes->handle, (byte*)aes->devKey,
  116. aes->keylen);
  117. if (ret != 0) {
  118. WOLFSSL_MSG("Error setting key through KCAPI");
  119. }
  120. }
  121. if (ret == 0 && aes->init == 0) {
  122. ret = (int)kcapi_cipher_stream_init_dec(aes->handle, (byte*)aes->reg,
  123. NULL, 0);
  124. if (ret != 0) {
  125. WOLFSSL_MSG("Error initializing IV through KCAPI");
  126. }
  127. }
  128. if (ret == 0) {
  129. aes->init = 1;
  130. iov.iov_base = (byte*)in;
  131. iov.iov_len = sz;
  132. ret = (int)kcapi_cipher_stream_update(aes->handle, &iov, 1);
  133. if (ret < 0) {
  134. WOLFSSL_MSG("CbcDecrypt error updating through KCAPI");
  135. }
  136. }
  137. if (ret >= 0) {
  138. iov.iov_base = out;
  139. iov.iov_len = sz;
  140. ret = (int)kcapi_cipher_stream_op(aes->handle, &iov, 1);
  141. if (ret < 0) {
  142. WOLFSSL_MSG("CbcDecrypt error with op in KCAPI");
  143. }
  144. }
  145. if (ret > 0) {
  146. ret = 0;
  147. }
  148. return ret;
  149. }
  150. #endif
  151. #endif /* HAVE_AES_CBC */
  152. #ifdef HAVE_AESGCM
  153. static const char WC_NAME_AESGCM[] = "gcm(aes)";
  154. #ifndef WC_SYSTEM_AESGCM_IV
  155. /* size of IV allowed on system for AES-GCM */
  156. #define WC_SYSTEM_AESGCM_IV 12
  157. #endif
  158. #ifndef WOLFSSL_MAX_AUTH_TAG_SZ
  159. /* size of tag is restricted by system for AES-GCM
  160. * check 'cat /proc/crypto' to see restricted size */
  161. #define WOLFSSL_MAX_AUTH_TAG_SZ 16
  162. #endif
  163. int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
  164. {
  165. #if defined(AES_MAX_KEY_SIZE)
  166. const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
  167. #endif
  168. int ret = 0;
  169. if (aes == NULL || !((len == 16) || (len == 24) || (len == 32))) {
  170. ret = BAD_FUNC_ARG;
  171. }
  172. #if defined(AES_MAX_KEY_SIZE)
  173. /* Check key length */
  174. if ((ret == 0) && (len > max_key_len)) {
  175. ret = BAD_FUNC_ARG;
  176. }
  177. #endif
  178. if (ret == 0) {
  179. aes->keylen = len;
  180. aes->rounds = len/4 + 6;
  181. /* save key until type is known i.e. CBC, ECB, ... */
  182. XMEMCPY((byte*)(aes->devKey), key, len);
  183. }
  184. return ret;
  185. }
  186. /* Performs AES-GCM encryption and returns 0 on success
  187. */
  188. int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
  189. const byte* iv, word32 ivSz,
  190. byte* authTag, word32 authTagSz,
  191. const byte* authIn, word32 authInSz)
  192. {
  193. int ret = 0;
  194. byte* data = NULL;
  195. word32 dataSz;
  196. int inbuflen = 0, outbuflen = 0;
  197. #ifndef KCAPI_USE_XMALLOC
  198. size_t pageSz = (size_t)sysconf(_SC_PAGESIZE);
  199. #endif
  200. /* argument checks */
  201. if ((aes == NULL) || ((sz != 0 && (in == NULL || out == NULL))) ||
  202. (iv == NULL) || ((authTag == NULL) && (authTagSz > 0)) ||
  203. (authTagSz > AES_BLOCK_SIZE) || ((authIn == NULL) && (authInSz > 0))) {
  204. ret = BAD_FUNC_ARG;
  205. }
  206. if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) ||
  207. (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ))) {
  208. WOLFSSL_MSG("IV/AAD size not supported on system");
  209. ret = BAD_FUNC_ARG;
  210. }
  211. if ((ret == 0) && (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ)) {
  212. WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
  213. ret = BAD_FUNC_ARG;
  214. }
  215. if (ret == 0) {
  216. ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0);
  217. if (ret != 0) {
  218. WOLFSSL_MSG("Error with first time setup of kcapi");
  219. }
  220. }
  221. if (ret == 0) {
  222. inbuflen = (int)kcapi_aead_inbuflen_enc( aes->handle, sz, authInSz,
  223. authTagSz);
  224. outbuflen = (int)kcapi_aead_outbuflen_enc(aes->handle, sz, authInSz,
  225. authTagSz);
  226. dataSz = (inbuflen > outbuflen) ? inbuflen : outbuflen;
  227. #ifdef KCAPI_USE_XMALLOC
  228. data = (byte *)XMALLOC(dataSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
  229. if (data == NULL) {
  230. ret = MEMORY_E;
  231. }
  232. #else
  233. ret = posix_memalign((void*)&data, pageSz, dataSz);
  234. if (ret < 0) {
  235. ret = MEMORY_E;
  236. }
  237. #endif
  238. }
  239. if (ret >= 0) {
  240. ret = kcapi_aead_setkey(aes->handle, (byte*)aes->devKey, aes->keylen);
  241. if (ret != 0) {
  242. WOLFSSL_MSG("GcmEncrypt set key failed");
  243. }
  244. }
  245. if (ret == 0) {
  246. ret = kcapi_aead_settaglen(aes->handle, authTagSz);
  247. if (ret != 0) {
  248. WOLFSSL_MSG("GcmEncrypt set tag len failed");
  249. }
  250. }
  251. if (ret == 0) {
  252. kcapi_aead_setassoclen(aes->handle, authInSz);
  253. XMEMCPY(data, authIn, authInSz);
  254. XMEMCPY(data + authInSz, in, sz);
  255. ret = (int)kcapi_aead_encrypt(aes->handle, data, inbuflen, iv, data,
  256. outbuflen, KCAPI_ACCESS_HEURISTIC);
  257. if (ret < 0) {
  258. WOLFSSL_MSG("GcmEncrypt failed");
  259. }
  260. else if (ret != outbuflen) {
  261. WOLFSSL_MSG("GcmEncrypt produced wrong output length");
  262. ret = BAD_FUNC_ARG;
  263. }
  264. else {
  265. ret = 0; /* success */
  266. }
  267. }
  268. if (ret == 0) {
  269. XMEMCPY(out, data + authInSz, sz);
  270. XMEMCPY(authTag, data + authInSz + sz, authTagSz);
  271. }
  272. if (data != NULL) {
  273. #ifdef KCAPI_USE_XMALLOC
  274. XFREE(data, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
  275. #else
  276. free(data);
  277. #endif
  278. }
  279. if (aes != NULL && aes->handle != NULL) {
  280. kcapi_aead_destroy(aes->handle);
  281. aes->handle = NULL;
  282. }
  283. return ret;
  284. }
  285. #if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
  286. /* Performs AES-GCM decryption and returns 0 on success
  287. */
  288. int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
  289. const byte* iv, word32 ivSz,
  290. const byte* authTag, word32 authTagSz,
  291. const byte* authIn, word32 authInSz)
  292. {
  293. int ret = 0;
  294. byte* data = NULL;
  295. word32 dataSz;
  296. int inbuflen = 0, outbuflen = 0;
  297. #ifndef KCAPI_USE_XMALLOC
  298. size_t pageSz = (size_t)sysconf(_SC_PAGESIZE);
  299. #endif
  300. /* argument checks */
  301. if ((aes == NULL) || ((sz != 0 && (in == NULL || out == NULL))) ||
  302. (iv == NULL) || ((authTag == NULL) && (authTagSz > 0)) ||
  303. (authTagSz > AES_BLOCK_SIZE) || ((authIn == NULL) && (authInSz > 0))) {
  304. ret = BAD_FUNC_ARG;
  305. }
  306. if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) ||
  307. (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ))) {
  308. WOLFSSL_MSG("IV/AAD size not supported on system");
  309. ret = BAD_FUNC_ARG;
  310. }
  311. if ((ret == 0) && (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ)) {
  312. WOLFSSL_MSG("GcmDecrypt authTagSz too small error");
  313. ret = BAD_FUNC_ARG;
  314. }
  315. if (ret == 0) {
  316. ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0);
  317. if (ret != 0) {
  318. WOLFSSL_MSG("Error with first time setup of kcapi");
  319. }
  320. }
  321. if (ret == 0) {
  322. inbuflen = (int)kcapi_aead_inbuflen_dec( aes->handle, sz, authInSz,
  323. authTagSz);
  324. outbuflen = (int)kcapi_aead_outbuflen_dec(aes->handle, sz, authInSz,
  325. authTagSz);
  326. dataSz = (inbuflen > outbuflen) ? inbuflen : outbuflen;
  327. #ifdef KCAPI_USE_XMALLOC
  328. data = (byte*)XMALLOC(dataSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
  329. if (data == NULL) {
  330. ret = MEMORY_E;
  331. }
  332. #else
  333. ret = posix_memalign((void*)&data, pageSz, dataSz);
  334. if (ret < 0) {
  335. ret = MEMORY_E;
  336. }
  337. #endif
  338. }
  339. if (ret >= 0) {
  340. ret = kcapi_aead_setkey(aes->handle, (byte*)aes->devKey, aes->keylen);
  341. if (ret != 0) {
  342. WOLFSSL_MSG("GcmDecrypt set key failed");
  343. }
  344. }
  345. if (ret == 0) {
  346. ret = kcapi_aead_settaglen(aes->handle, authTagSz);
  347. }
  348. if (ret == 0) {
  349. kcapi_aead_setassoclen(aes->handle, authInSz);
  350. XMEMCPY(data, authIn, authInSz);
  351. XMEMCPY(data + authInSz, in, sz);
  352. XMEMCPY(data + authInSz + sz, authTag, authTagSz);
  353. ret = (int)kcapi_aead_decrypt(aes->handle, data, inbuflen, iv, data,
  354. outbuflen, KCAPI_ACCESS_HEURISTIC);
  355. if (ret < 0) {
  356. WOLFSSL_MSG("GcmDecrypt failed");
  357. if (ret == -EBADMSG)
  358. ret = AES_GCM_AUTH_E;
  359. }
  360. else if (ret != outbuflen) {
  361. WOLFSSL_MSG("GcmDecrypt produced wrong output length");
  362. ret = BAD_FUNC_ARG;
  363. }
  364. else {
  365. ret = 0; /* success */
  366. }
  367. }
  368. if (ret == 0) {
  369. XMEMCPY(out, data + authInSz, sz);
  370. }
  371. if (data != NULL) {
  372. #ifdef KCAPI_USE_XMALLOC
  373. XFREE(data, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
  374. #else
  375. free(data);
  376. #endif
  377. }
  378. if (aes != NULL && aes->handle != NULL) {
  379. kcapi_aead_destroy(aes->handle);
  380. aes->handle = NULL;
  381. }
  382. return ret;
  383. }
  384. #endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
  385. #endif /* HAVE_AESGCM */
  386. #endif /* !NO_AES && WOLFSSL_KCAPI_AES */