jwe-rsa-aescbc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #include "private-lib-jose-jwe.h"
  26. /*
  27. * Requirements on entry:
  28. *
  29. * - jwe->jws.map LJWE_JOSE contains the ASCII JOSE header
  30. * - jwe->jws.map LJWE_EKEY contains cek of enc_alg hmac length
  31. * - jwe->jws.map LJWE_CTXT contains the plaintext
  32. *
  33. * On successful exit:
  34. *
  35. * - jwe->jws.map LJWE_ATAG contains the tag
  36. * - jwe->jws.map LJWE_IV contains the new random IV that was used
  37. * - jwe->jws.map LJWE_EKEY contains the encrypted CEK
  38. * - jwe->jws.map LJWE_CTXT contains the ciphertext
  39. *
  40. * Return the amount of temp used, or -1
  41. */
  42. int
  43. lws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe,
  44. char *temp, int *temp_len)
  45. {
  46. int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type),
  47. ot = *temp_len;
  48. char ekey[LWS_GENHASH_LARGEST];
  49. struct lws_genrsa_ctx rsactx;
  50. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
  51. lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
  52. return -1;
  53. }
  54. /*
  55. * Notice that the unencrypted EKEY coming in is smaller than the
  56. * RSA-encrypted EKEY going out, which is going to be the RSA key size
  57. *
  58. * Create a b64 version of the JOSE header, needed as aad
  59. */
  60. if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
  61. temp, temp_len,
  62. jwe->jws.map.buf[LJWE_JOSE],
  63. jwe->jws.map.len[LJWE_JOSE]))
  64. return -1;
  65. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG, temp + (ot - *temp_len),
  66. temp_len, hlen / 2, 0))
  67. return -1;
  68. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV, temp + (ot - *temp_len),
  69. temp_len, LWS_JWE_AES_IV_BYTES, 0))
  70. return -1;
  71. /*
  72. * Without changing the unencrypted CEK in EKEY, reallocate enough
  73. * space to write the RSA-encrypted version in-situ.
  74. */
  75. if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY, temp + (ot - *temp_len),
  76. temp_len, jwe->jws.map.buf[LJWE_EKEY],
  77. jwe->jws.map.len[LJWE_EKEY],
  78. jwe->jws.jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len))
  79. return -1;
  80. /* Encrypt using the raw CEK (treated as MAC KEY | ENC KEY) */
  81. n = lws_jwe_encrypt_cbc_hs(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
  82. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  83. jwe->jws.map_b64.len[LJWE_JOSE]);
  84. if (n < 0) {
  85. lwsl_err("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__);
  86. return -1;
  87. }
  88. if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
  89. !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
  90. LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
  91. LWS_GENHASH_TYPE_UNKNOWN)) {
  92. lwsl_notice("%s: lws_genrsa_create\n",
  93. __func__);
  94. return -1;
  95. }
  96. /* encrypt the CEK using RSA, mbedtls can't handle both in and out are
  97. * the EKEY, so copy the unencrypted ekey out temporarily */
  98. memcpy(ekey, jwe->jws.map.buf[LJWE_EKEY], hlen);
  99. n = lws_genrsa_public_encrypt(&rsactx, (uint8_t *)ekey, hlen,
  100. (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
  101. lws_genrsa_destroy(&rsactx);
  102. lws_explicit_bzero(ekey, hlen); /* cleanse the temp CEK copy */
  103. if (n < 0) {
  104. lwsl_err("%s: encrypt cek fail\n", __func__);
  105. return -1;
  106. }
  107. jwe->jws.map.len[LJWE_EKEY] = n; /* update to encrypted EKEY size */
  108. /*
  109. * We end up with IV, ATAG, set, EKEY encrypted and CTXT is ciphertext,
  110. * and b64u version of ATAG in map_b64.
  111. */
  112. return 0;
  113. }
  114. int
  115. lws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe)
  116. {
  117. int n;
  118. struct lws_genrsa_ctx rsactx;
  119. uint8_t enc_cek[512];
  120. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
  121. lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
  122. return -1;
  123. }
  124. if (jwe->jws.map.len[LJWE_EKEY] < 40) {
  125. lwsl_err("%s: EKEY length too short %d\n", __func__,
  126. jwe->jws.map.len[LJWE_EKEY]);
  127. return -1;
  128. }
  129. /* Decrypt the JWE Encrypted Key to get the raw MAC || CEK */
  130. if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
  131. !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
  132. LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
  133. LWS_GENHASH_TYPE_UNKNOWN)) {
  134. lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
  135. __func__);
  136. return -1;
  137. }
  138. n = lws_genrsa_private_decrypt(&rsactx,
  139. (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
  140. jwe->jws.map.len[LJWE_EKEY], enc_cek,
  141. sizeof(enc_cek));
  142. lws_genrsa_destroy(&rsactx);
  143. if (n < 0) {
  144. lwsl_err("%s: decrypt cek fail: \n", __func__);
  145. return -1;
  146. }
  147. n = lws_jwe_auth_and_decrypt_cbc_hs(jwe, enc_cek,
  148. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  149. jwe->jws.map_b64.len[LJWE_JOSE]);
  150. if (n < 0) {
  151. lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs failed\n",
  152. __func__);
  153. return -1;
  154. }
  155. #if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
  156. /* strip padding */
  157. n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
  158. if (n > 16) {
  159. lwsl_err("%s: n == %d, plen %d\n", __func__, n,
  160. (int)jwe->jws.map.len[LJWE_CTXT]);
  161. return -1;
  162. }
  163. jwe->jws.map.len[LJWE_CTXT] -= n;
  164. #endif
  165. return jwe->jws.map.len[LJWE_CTXT];
  166. }