psa_crypto_aead.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * PSA AEAD entry points
  3. */
  4. /*
  5. * Copyright The Mbed TLS Contributors
  6. * SPDX-License-Identifier: Apache-2.0
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  9. * not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  16. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. #include "common.h"
  21. #if defined(MBEDTLS_PSA_CRYPTO_C)
  22. #include "psa_crypto_aead.h"
  23. #include "psa_crypto_core.h"
  24. #include "mbedtls/ccm.h"
  25. #include "mbedtls/chachapoly.h"
  26. #include "mbedtls/cipher.h"
  27. #include "mbedtls/gcm.h"
  28. typedef struct
  29. {
  30. union
  31. {
  32. unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
  33. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
  34. mbedtls_ccm_context ccm;
  35. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
  36. #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
  37. mbedtls_gcm_context gcm;
  38. #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
  39. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
  40. mbedtls_chachapoly_context chachapoly;
  41. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
  42. } ctx;
  43. psa_algorithm_t core_alg;
  44. uint8_t tag_length;
  45. } aead_operation_t;
  46. #define AEAD_OPERATION_INIT {{0}, 0, 0}
  47. static void psa_aead_abort_internal( aead_operation_t *operation )
  48. {
  49. switch( operation->core_alg )
  50. {
  51. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
  52. case PSA_ALG_CCM:
  53. mbedtls_ccm_free( &operation->ctx.ccm );
  54. break;
  55. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
  56. #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
  57. case PSA_ALG_GCM:
  58. mbedtls_gcm_free( &operation->ctx.gcm );
  59. break;
  60. #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
  61. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
  62. case PSA_ALG_CHACHA20_POLY1305:
  63. mbedtls_chachapoly_free( &operation->ctx.chachapoly );
  64. break;
  65. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
  66. }
  67. }
  68. static psa_status_t psa_aead_setup(
  69. aead_operation_t *operation,
  70. const psa_key_attributes_t *attributes,
  71. const uint8_t *key_buffer,
  72. psa_algorithm_t alg )
  73. {
  74. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  75. size_t key_bits;
  76. const mbedtls_cipher_info_t *cipher_info;
  77. mbedtls_cipher_id_t cipher_id;
  78. size_t full_tag_length = 0;
  79. key_bits = attributes->core.bits;
  80. cipher_info = mbedtls_cipher_info_from_psa( alg,
  81. attributes->core.type, key_bits,
  82. &cipher_id );
  83. if( cipher_info == NULL )
  84. return( PSA_ERROR_NOT_SUPPORTED );
  85. switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) )
  86. {
  87. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
  88. case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
  89. operation->core_alg = PSA_ALG_CCM;
  90. full_tag_length = 16;
  91. /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
  92. * The call to mbedtls_ccm_encrypt_and_tag or
  93. * mbedtls_ccm_auth_decrypt will validate the tag length. */
  94. if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
  95. return( PSA_ERROR_INVALID_ARGUMENT );
  96. mbedtls_ccm_init( &operation->ctx.ccm );
  97. status = mbedtls_to_psa_error(
  98. mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
  99. key_buffer, (unsigned int) key_bits ) );
  100. if( status != PSA_SUCCESS )
  101. return( status );
  102. break;
  103. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
  104. #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
  105. case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
  106. operation->core_alg = PSA_ALG_GCM;
  107. full_tag_length = 16;
  108. /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
  109. * The call to mbedtls_gcm_crypt_and_tag or
  110. * mbedtls_gcm_auth_decrypt will validate the tag length. */
  111. if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
  112. return( PSA_ERROR_INVALID_ARGUMENT );
  113. mbedtls_gcm_init( &operation->ctx.gcm );
  114. status = mbedtls_to_psa_error(
  115. mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
  116. key_buffer, (unsigned int) key_bits ) );
  117. if( status != PSA_SUCCESS )
  118. return( status );
  119. break;
  120. #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
  121. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
  122. case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
  123. operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
  124. full_tag_length = 16;
  125. /* We only support the default tag length. */
  126. if( alg != PSA_ALG_CHACHA20_POLY1305 )
  127. return( PSA_ERROR_NOT_SUPPORTED );
  128. mbedtls_chachapoly_init( &operation->ctx.chachapoly );
  129. status = mbedtls_to_psa_error(
  130. mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
  131. key_buffer ) );
  132. if( status != PSA_SUCCESS )
  133. return( status );
  134. break;
  135. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
  136. default:
  137. return( PSA_ERROR_NOT_SUPPORTED );
  138. }
  139. if( PSA_AEAD_TAG_LENGTH( attributes->core.type,
  140. key_bits, alg )
  141. > full_tag_length )
  142. return( PSA_ERROR_INVALID_ARGUMENT );
  143. operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
  144. key_bits,
  145. alg );
  146. return( PSA_SUCCESS );
  147. }
  148. psa_status_t mbedtls_psa_aead_encrypt(
  149. const psa_key_attributes_t *attributes,
  150. const uint8_t *key_buffer, size_t key_buffer_size,
  151. psa_algorithm_t alg,
  152. const uint8_t *nonce, size_t nonce_length,
  153. const uint8_t *additional_data, size_t additional_data_length,
  154. const uint8_t *plaintext, size_t plaintext_length,
  155. uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
  156. {
  157. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  158. aead_operation_t operation = AEAD_OPERATION_INIT;
  159. uint8_t *tag;
  160. (void) key_buffer_size;
  161. status = psa_aead_setup( &operation, attributes, key_buffer, alg );
  162. if( status != PSA_SUCCESS )
  163. goto exit;
  164. /* For all currently supported modes, the tag is at the end of the
  165. * ciphertext. */
  166. if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
  167. {
  168. status = PSA_ERROR_BUFFER_TOO_SMALL;
  169. goto exit;
  170. }
  171. tag = ciphertext + plaintext_length;
  172. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
  173. if( operation.core_alg == PSA_ALG_CCM )
  174. {
  175. status = mbedtls_to_psa_error(
  176. mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
  177. plaintext_length,
  178. nonce, nonce_length,
  179. additional_data,
  180. additional_data_length,
  181. plaintext, ciphertext,
  182. tag, operation.tag_length ) );
  183. }
  184. else
  185. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
  186. #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
  187. if( operation.core_alg == PSA_ALG_GCM )
  188. {
  189. status = mbedtls_to_psa_error(
  190. mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
  191. MBEDTLS_GCM_ENCRYPT,
  192. plaintext_length,
  193. nonce, nonce_length,
  194. additional_data, additional_data_length,
  195. plaintext, ciphertext,
  196. operation.tag_length, tag ) );
  197. }
  198. else
  199. #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
  200. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
  201. if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
  202. {
  203. if( nonce_length != 12 || operation.tag_length != 16 )
  204. {
  205. status = PSA_ERROR_NOT_SUPPORTED;
  206. goto exit;
  207. }
  208. status = mbedtls_to_psa_error(
  209. mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
  210. plaintext_length,
  211. nonce,
  212. additional_data,
  213. additional_data_length,
  214. plaintext,
  215. ciphertext,
  216. tag ) );
  217. }
  218. else
  219. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
  220. {
  221. (void) tag;
  222. return( PSA_ERROR_NOT_SUPPORTED );
  223. }
  224. if( status == PSA_SUCCESS )
  225. *ciphertext_length = plaintext_length + operation.tag_length;
  226. exit:
  227. psa_aead_abort_internal( &operation );
  228. return( status );
  229. }
  230. /* Locate the tag in a ciphertext buffer containing the encrypted data
  231. * followed by the tag. Return the length of the part preceding the tag in
  232. * *plaintext_length. This is the size of the plaintext in modes where
  233. * the encrypted data has the same size as the plaintext, such as
  234. * CCM and GCM. */
  235. static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
  236. const uint8_t *ciphertext,
  237. size_t ciphertext_length,
  238. size_t plaintext_size,
  239. const uint8_t **p_tag )
  240. {
  241. size_t payload_length;
  242. if( tag_length > ciphertext_length )
  243. return( PSA_ERROR_INVALID_ARGUMENT );
  244. payload_length = ciphertext_length - tag_length;
  245. if( payload_length > plaintext_size )
  246. return( PSA_ERROR_BUFFER_TOO_SMALL );
  247. *p_tag = ciphertext + payload_length;
  248. return( PSA_SUCCESS );
  249. }
  250. psa_status_t mbedtls_psa_aead_decrypt(
  251. const psa_key_attributes_t *attributes,
  252. const uint8_t *key_buffer, size_t key_buffer_size,
  253. psa_algorithm_t alg,
  254. const uint8_t *nonce, size_t nonce_length,
  255. const uint8_t *additional_data, size_t additional_data_length,
  256. const uint8_t *ciphertext, size_t ciphertext_length,
  257. uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
  258. {
  259. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  260. aead_operation_t operation = AEAD_OPERATION_INIT;
  261. const uint8_t *tag = NULL;
  262. (void) key_buffer_size;
  263. status = psa_aead_setup( &operation, attributes, key_buffer, alg );
  264. if( status != PSA_SUCCESS )
  265. goto exit;
  266. status = psa_aead_unpadded_locate_tag( operation.tag_length,
  267. ciphertext, ciphertext_length,
  268. plaintext_size, &tag );
  269. if( status != PSA_SUCCESS )
  270. goto exit;
  271. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
  272. if( operation.core_alg == PSA_ALG_CCM )
  273. {
  274. status = mbedtls_to_psa_error(
  275. mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
  276. ciphertext_length - operation.tag_length,
  277. nonce, nonce_length,
  278. additional_data,
  279. additional_data_length,
  280. ciphertext, plaintext,
  281. tag, operation.tag_length ) );
  282. }
  283. else
  284. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
  285. #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
  286. if( operation.core_alg == PSA_ALG_GCM )
  287. {
  288. status = mbedtls_to_psa_error(
  289. mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
  290. ciphertext_length - operation.tag_length,
  291. nonce, nonce_length,
  292. additional_data,
  293. additional_data_length,
  294. tag, operation.tag_length,
  295. ciphertext, plaintext ) );
  296. }
  297. else
  298. #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
  299. #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
  300. if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
  301. {
  302. if( nonce_length != 12 || operation.tag_length != 16 )
  303. {
  304. status = PSA_ERROR_NOT_SUPPORTED;
  305. goto exit;
  306. }
  307. status = mbedtls_to_psa_error(
  308. mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
  309. ciphertext_length - operation.tag_length,
  310. nonce,
  311. additional_data,
  312. additional_data_length,
  313. tag,
  314. ciphertext,
  315. plaintext ) );
  316. }
  317. else
  318. #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
  319. {
  320. return( PSA_ERROR_NOT_SUPPORTED );
  321. }
  322. if( status == PSA_SUCCESS )
  323. *plaintext_length = ciphertext_length - operation.tag_length;
  324. exit:
  325. psa_aead_abort_internal( &operation );
  326. if( status == PSA_SUCCESS )
  327. *plaintext_length = ciphertext_length - operation.tag_length;
  328. return( status );
  329. }
  330. #endif /* MBEDTLS_PSA_CRYPTO_C */