cipher_aes_wrp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. /*
  10. * This file uses the low level AES functions (which are deprecated for
  11. * non-internal use) in order to implement provider AES ciphers.
  12. */
  13. #include "internal/deprecated.h"
  14. #include <openssl/proverr.h>
  15. #include "cipher_aes.h"
  16. #include "prov/providercommon.h"
  17. #include "prov/implementations.h"
  18. /* AES wrap with padding has IV length of 4, without padding 8 */
  19. #define AES_WRAP_PAD_IVLEN 4
  20. #define AES_WRAP_NOPAD_IVLEN 8
  21. #define WRAP_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
  22. #define WRAP_FLAGS_INV (WRAP_FLAGS | PROV_CIPHER_FLAG_INVERSE_CIPHER)
  23. typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
  24. unsigned char *out, const unsigned char *in,
  25. size_t inlen, block128_f block);
  26. static OSSL_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
  27. static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
  28. static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
  29. static OSSL_FUNC_cipher_final_fn aes_wrap_final;
  30. static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
  31. static OSSL_FUNC_cipher_set_ctx_params_fn aes_wrap_set_ctx_params;
  32. typedef struct prov_aes_wrap_ctx_st {
  33. PROV_CIPHER_CTX base;
  34. union {
  35. OSSL_UNION_ALIGN;
  36. AES_KEY ks;
  37. } ks;
  38. aeswrap_fn wrapfn;
  39. } PROV_AES_WRAP_CTX;
  40. static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
  41. size_t ivbits, unsigned int mode, uint64_t flags)
  42. {
  43. PROV_AES_WRAP_CTX *wctx;
  44. PROV_CIPHER_CTX *ctx;
  45. if (!ossl_prov_is_running())
  46. return NULL;
  47. wctx = OPENSSL_zalloc(sizeof(*wctx));
  48. ctx = (PROV_CIPHER_CTX *)wctx;
  49. if (ctx != NULL) {
  50. ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
  51. NULL, NULL);
  52. ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
  53. }
  54. return wctx;
  55. }
  56. static void *aes_wrap_dupctx(void *wctx)
  57. {
  58. PROV_AES_WRAP_CTX *ctx = wctx;
  59. PROV_AES_WRAP_CTX *dctx = wctx;
  60. if (ctx == NULL)
  61. return NULL;
  62. dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
  63. if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) {
  64. dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac,
  65. dctx->base.tlsmacsize);
  66. if (dctx->base.tlsmac == NULL) {
  67. OPENSSL_free(dctx);
  68. dctx = NULL;
  69. }
  70. }
  71. return dctx;
  72. }
  73. static void aes_wrap_freectx(void *vctx)
  74. {
  75. PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
  76. ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
  77. OPENSSL_clear_free(wctx, sizeof(*wctx));
  78. }
  79. static int aes_wrap_init(void *vctx, const unsigned char *key,
  80. size_t keylen, const unsigned char *iv,
  81. size_t ivlen, const OSSL_PARAM params[], int enc)
  82. {
  83. PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
  84. PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
  85. if (!ossl_prov_is_running())
  86. return 0;
  87. ctx->enc = enc;
  88. if (ctx->pad)
  89. wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
  90. else
  91. wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
  92. if (iv != NULL) {
  93. if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
  94. return 0;
  95. }
  96. if (key != NULL) {
  97. int use_forward_transform;
  98. if (keylen != ctx->keylen) {
  99. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
  100. return 0;
  101. }
  102. /*
  103. * See SP800-38F : Section 5.1
  104. * The forward and inverse transformations for the AES block
  105. * cipher—called “cipher” and “inverse cipher” are informally known as
  106. * the AES encryption and AES decryption functions, respectively.
  107. * If the designated cipher function for a key-wrap algorithm is chosen
  108. * to be the AES decryption function, then CIPH-1K will be the AES
  109. * encryption function.
  110. */
  111. if (ctx->inverse_cipher == 0)
  112. use_forward_transform = ctx->enc;
  113. else
  114. use_forward_transform = !ctx->enc;
  115. if (use_forward_transform) {
  116. AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
  117. ctx->block = (block128_f)AES_encrypt;
  118. } else {
  119. AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
  120. ctx->block = (block128_f)AES_decrypt;
  121. }
  122. }
  123. return aes_wrap_set_ctx_params(ctx, params);
  124. }
  125. static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
  126. const unsigned char *iv, size_t ivlen,
  127. const OSSL_PARAM params[])
  128. {
  129. return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 1);
  130. }
  131. static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
  132. const unsigned char *iv, size_t ivlen,
  133. const OSSL_PARAM params[])
  134. {
  135. return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 0);
  136. }
  137. static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
  138. const unsigned char *in, size_t inlen)
  139. {
  140. PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
  141. PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
  142. size_t rv;
  143. int pad = ctx->pad;
  144. /* No final operation so always return zero length */
  145. if (in == NULL)
  146. return 0;
  147. /* Input length must always be non-zero */
  148. if (inlen == 0) {
  149. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
  150. return -1;
  151. }
  152. /* If decrypting need at least 16 bytes and multiple of 8 */
  153. if (!ctx->enc && (inlen < 16 || inlen & 0x7)) {
  154. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
  155. return -1;
  156. }
  157. /* If not padding input must be multiple of 8 */
  158. if (!pad && inlen & 0x7) {
  159. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
  160. return -1;
  161. }
  162. if (out == NULL) {
  163. if (ctx->enc) {
  164. /* If padding round up to multiple of 8 */
  165. if (pad)
  166. inlen = (inlen + 7) / 8 * 8;
  167. /* 8 byte prefix */
  168. return inlen + 8;
  169. } else {
  170. /*
  171. * If not padding output will be exactly 8 bytes smaller than
  172. * input. If padding it will be at least 8 bytes smaller but we
  173. * don't know how much.
  174. */
  175. return inlen - 8;
  176. }
  177. }
  178. rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in,
  179. inlen, ctx->block);
  180. if (!rv) {
  181. ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
  182. return -1;
  183. }
  184. if (rv > INT_MAX) {
  185. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
  186. return -1;
  187. }
  188. return (int)rv;
  189. }
  190. static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
  191. size_t outsize)
  192. {
  193. if (!ossl_prov_is_running())
  194. return 0;
  195. *outl = 0;
  196. return 1;
  197. }
  198. static int aes_wrap_cipher(void *vctx,
  199. unsigned char *out, size_t *outl, size_t outsize,
  200. const unsigned char *in, size_t inl)
  201. {
  202. PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
  203. size_t len;
  204. if (!ossl_prov_is_running())
  205. return 0;
  206. if (inl == 0) {
  207. *outl = 0;
  208. return 1;
  209. }
  210. if (outsize < inl) {
  211. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  212. return 0;
  213. }
  214. len = aes_wrap_cipher_internal(ctx, out, in, inl);
  215. if (len <= 0)
  216. return 0;
  217. *outl = len;
  218. return 1;
  219. }
  220. static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
  221. {
  222. PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
  223. const OSSL_PARAM *p;
  224. size_t keylen = 0;
  225. if (params == NULL)
  226. return 1;
  227. p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
  228. if (p != NULL) {
  229. if (!OSSL_PARAM_get_size_t(p, &keylen)) {
  230. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
  231. return 0;
  232. }
  233. if (ctx->keylen != keylen) {
  234. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
  235. return 0;
  236. }
  237. }
  238. return 1;
  239. }
  240. #define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits) \
  241. static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \
  242. static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \
  243. { \
  244. return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
  245. flags, kbits, blkbits, ivbits); \
  246. } \
  247. static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx; \
  248. static void *aes_##kbits##fname##_newctx(void *provctx) \
  249. { \
  250. return aes_##mode##_newctx(kbits, blkbits, ivbits, \
  251. EVP_CIPH_##UCMODE##_MODE, flags); \
  252. } \
  253. const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = { \
  254. { OSSL_FUNC_CIPHER_NEWCTX, \
  255. (void (*)(void))aes_##kbits##fname##_newctx }, \
  256. { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
  257. { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
  258. { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \
  259. { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \
  260. { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
  261. { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
  262. { OSSL_FUNC_CIPHER_GET_PARAMS, \
  263. (void (*)(void))aes_##kbits##_##fname##_get_params }, \
  264. { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
  265. (void (*)(void))ossl_cipher_generic_gettable_params }, \
  266. { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
  267. (void (*)(void))ossl_cipher_generic_get_ctx_params }, \
  268. { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
  269. (void (*)(void))aes_wrap_set_ctx_params }, \
  270. { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
  271. (void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
  272. { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
  273. (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
  274. OSSL_DISPATCH_END \
  275. }
  276. IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
  277. IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
  278. IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
  279. IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
  280. IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
  281. IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
  282. IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
  283. IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
  284. IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
  285. IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
  286. IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
  287. IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);