cipher_aes_gcm_siv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /* Dispatch functions for AES SIV mode */
  10. /*
  11. * This file uses the low level AES functions (which are deprecated for
  12. * non-internal use) in order to implement provider AES ciphers.
  13. */
  14. #include "internal/deprecated.h"
  15. #include <openssl/proverr.h>
  16. #include "prov/implementations.h"
  17. #include "prov/providercommon.h"
  18. #include "prov/ciphercommon_aead.h"
  19. #include "prov/provider_ctx.h"
  20. #include "cipher_aes_gcm_siv.h"
  21. static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
  22. static void *ossl_aes_gcm_siv_newctx(void *provctx, size_t keybits)
  23. {
  24. PROV_AES_GCM_SIV_CTX *ctx;
  25. if (!ossl_prov_is_running())
  26. return NULL;
  27. ctx = OPENSSL_zalloc(sizeof(*ctx));
  28. if (ctx != NULL) {
  29. ctx->key_len = keybits / 8;
  30. ctx->hw = ossl_prov_cipher_hw_aes_gcm_siv(keybits);
  31. ctx->libctx = PROV_LIBCTX_OF(provctx);
  32. ctx->provctx = provctx;
  33. }
  34. return ctx;
  35. }
  36. static void ossl_aes_gcm_siv_freectx(void *vctx)
  37. {
  38. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  39. if (ctx == NULL)
  40. return;
  41. OPENSSL_clear_free(ctx->aad, ctx->aad_len);
  42. ctx->hw->clean_ctx(ctx);
  43. OPENSSL_clear_free(ctx, sizeof(*ctx));
  44. }
  45. static void *ossl_aes_gcm_siv_dupctx(void *vctx)
  46. {
  47. PROV_AES_GCM_SIV_CTX *in = (PROV_AES_GCM_SIV_CTX *)vctx;
  48. PROV_AES_GCM_SIV_CTX *ret;
  49. if (!ossl_prov_is_running())
  50. return NULL;
  51. if (in->hw == NULL)
  52. return NULL;
  53. ret = OPENSSL_memdup(in, sizeof(*in));
  54. if (ret == NULL)
  55. return NULL;
  56. /* NULL-out these things we create later */
  57. ret->aad = NULL;
  58. ret->ecb_ctx = NULL;
  59. if (in->aad != NULL) {
  60. if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL)
  61. goto err;
  62. }
  63. if (!in->hw->dup_ctx(ret, in))
  64. goto err;
  65. return ret;
  66. err:
  67. if (ret != NULL) {
  68. OPENSSL_clear_free(ret->aad, ret->aad_len);
  69. OPENSSL_free(ret);
  70. }
  71. return NULL;
  72. }
  73. static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t keylen,
  74. const unsigned char *iv, size_t ivlen,
  75. const OSSL_PARAM params[], int enc)
  76. {
  77. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  78. if (!ossl_prov_is_running())
  79. return 0;
  80. ctx->enc = enc;
  81. if (key != NULL) {
  82. if (keylen != ctx->key_len) {
  83. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
  84. return 0;
  85. }
  86. memcpy(ctx->key_gen_key, key, ctx->key_len);
  87. }
  88. if (iv != NULL) {
  89. if (ivlen != sizeof(ctx->nonce)) {
  90. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
  91. return 0;
  92. }
  93. memcpy(ctx->nonce, iv, sizeof(ctx->nonce));
  94. }
  95. if (!ctx->hw->initkey(ctx))
  96. return 0;
  97. return ossl_aes_gcm_siv_set_ctx_params(ctx, params);
  98. }
  99. static int ossl_aes_gcm_siv_einit(void *vctx, const unsigned char *key, size_t keylen,
  100. const unsigned char *iv, size_t ivlen,
  101. const OSSL_PARAM params[])
  102. {
  103. return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 1);
  104. }
  105. static int ossl_aes_gcm_siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
  106. const unsigned char *iv, size_t ivlen,
  107. const OSSL_PARAM params[])
  108. {
  109. return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 0);
  110. }
  111. #define ossl_aes_gcm_siv_stream_update ossl_aes_gcm_siv_cipher
  112. static int ossl_aes_gcm_siv_cipher(void *vctx, unsigned char *out, size_t *outl,
  113. size_t outsize, const unsigned char *in, size_t inl)
  114. {
  115. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  116. int error = 0;
  117. if (!ossl_prov_is_running())
  118. return 0;
  119. /* The RFC has a test case for this, but we don't try to do anything */
  120. if (inl == 0) {
  121. if (outl != NULL)
  122. *outl = 0;
  123. return 1;
  124. }
  125. if (outsize < inl) {
  126. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  127. return 0;
  128. }
  129. error |= !ctx->hw->cipher(ctx, out, in, inl);
  130. if (outl != NULL && !error)
  131. *outl = inl;
  132. return !error;
  133. }
  134. static int ossl_aes_gcm_siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
  135. size_t outsize)
  136. {
  137. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  138. int error = 0;
  139. if (!ossl_prov_is_running())
  140. return 0;
  141. error |= !ctx->hw->cipher(vctx, out, NULL, 0);
  142. if (outl != NULL && !error)
  143. *outl = 0;
  144. return !error;
  145. }
  146. static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
  147. {
  148. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  149. OSSL_PARAM *p;
  150. p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
  151. if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
  152. if (!ctx->enc || !ctx->generated_tag
  153. || p->data_size != sizeof(ctx->tag)
  154. || !OSSL_PARAM_set_octet_string(p, ctx->tag, sizeof(ctx->tag))) {
  155. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
  156. return 0;
  157. }
  158. }
  159. p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
  160. if (p != NULL && !OSSL_PARAM_set_size_t(p, sizeof(ctx->tag))) {
  161. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
  162. return 0;
  163. }
  164. p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
  165. if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_len)) {
  166. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
  167. return 0;
  168. }
  169. return 1;
  170. }
  171. static const OSSL_PARAM aes_gcm_siv_known_gettable_ctx_params[] = {
  172. OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
  173. OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
  174. OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
  175. OSSL_PARAM_END
  176. };
  177. static const OSSL_PARAM *ossl_aes_gcm_siv_gettable_ctx_params(ossl_unused void *cctx,
  178. ossl_unused void *provctx)
  179. {
  180. return aes_gcm_siv_known_gettable_ctx_params;
  181. }
  182. static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
  183. {
  184. PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
  185. const OSSL_PARAM *p;
  186. unsigned int speed = 0;
  187. if (params == NULL)
  188. return 1;
  189. p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
  190. if (p != NULL) {
  191. if (p->data_type != OSSL_PARAM_OCTET_STRING
  192. || p->data_size != sizeof(ctx->user_tag)) {
  193. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
  194. return 0;
  195. }
  196. if (!ctx->enc) {
  197. memcpy(ctx->user_tag, p->data, sizeof(ctx->tag));
  198. ctx->have_user_tag = 1;
  199. }
  200. }
  201. p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
  202. if (p != NULL) {
  203. if (!OSSL_PARAM_get_uint(p, &speed)) {
  204. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
  205. return 0;
  206. }
  207. ctx->speed = !!speed;
  208. }
  209. p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
  210. if (p != NULL) {
  211. size_t key_len;
  212. if (!OSSL_PARAM_get_size_t(p, &key_len)) {
  213. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
  214. return 0;
  215. }
  216. /* The key length can not be modified */
  217. if (key_len != ctx->key_len) {
  218. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
  219. return 0;
  220. }
  221. }
  222. return 1;
  223. }
  224. static const OSSL_PARAM aes_gcm_siv_known_settable_ctx_params[] = {
  225. OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
  226. OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
  227. OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
  228. OSSL_PARAM_END
  229. };
  230. static const OSSL_PARAM *ossl_aes_gcm_siv_settable_ctx_params(ossl_unused void *cctx,
  231. ossl_unused void *provctx)
  232. {
  233. return aes_gcm_siv_known_settable_ctx_params;
  234. }
  235. #define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
  236. static OSSL_FUNC_cipher_newctx_fn ossl_##alg##kbits##_##lc##_newctx; \
  237. static OSSL_FUNC_cipher_freectx_fn ossl_##alg##_##lc##_freectx; \
  238. static OSSL_FUNC_cipher_dupctx_fn ossl_##alg##_##lc##_dupctx; \
  239. static OSSL_FUNC_cipher_encrypt_init_fn ossl_##alg##_##lc##_einit; \
  240. static OSSL_FUNC_cipher_decrypt_init_fn ossl_##alg##_##lc##_dinit; \
  241. static OSSL_FUNC_cipher_update_fn ossl_##alg##_##lc##_stream_update; \
  242. static OSSL_FUNC_cipher_final_fn ossl_##alg##_##lc##_stream_final; \
  243. static OSSL_FUNC_cipher_cipher_fn ossl_##alg##_##lc##_cipher; \
  244. static OSSL_FUNC_cipher_get_params_fn ossl_##alg##_##kbits##_##lc##_get_params; \
  245. static OSSL_FUNC_cipher_get_ctx_params_fn ossl_##alg##_##lc##_get_ctx_params; \
  246. static OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_##alg##_##lc##_gettable_ctx_params; \
  247. static OSSL_FUNC_cipher_set_ctx_params_fn ossl_##alg##_##lc##_set_ctx_params; \
  248. static OSSL_FUNC_cipher_settable_ctx_params_fn ossl_##alg##_##lc##_settable_ctx_params; \
  249. static int ossl_##alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
  250. { \
  251. return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
  252. flags, kbits, blkbits, ivbits); \
  253. } \
  254. static void *ossl_##alg##kbits##_##lc##_newctx(void *provctx) \
  255. { \
  256. return ossl_##alg##_##lc##_newctx(provctx, kbits); \
  257. } \
  258. const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
  259. { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))ossl_##alg##kbits##_##lc##_newctx }, \
  260. { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_##alg##_##lc##_freectx }, \
  261. { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_##alg##_##lc##_dupctx }, \
  262. { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_einit }, \
  263. { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_dinit }, \
  264. { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##alg##_##lc##_stream_update }, \
  265. { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##alg##_##lc##_stream_final }, \
  266. { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##alg##_##lc##_cipher }, \
  267. { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))ossl_##alg##_##kbits##_##lc##_get_params }, \
  268. { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))ossl_cipher_generic_gettable_params }, \
  269. { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_get_ctx_params }, \
  270. { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_gettable_ctx_params }, \
  271. { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_set_ctx_params }, \
  272. { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_settable_ctx_params }, \
  273. OSSL_DISPATCH_END \
  274. }
  275. IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 128, 8, 96);
  276. IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 192, 8, 96);
  277. IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 256, 8, 96);