jwe-rsa-aesgcm.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #define LWS_AESGCM_IV 12
  27. int
  28. lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe, char *temp, int *temp_len)
  29. {
  30. int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8;
  31. struct lws_genrsa_ctx rsactx;
  32. int n, ret = -1, ot = *temp_len;
  33. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
  34. lwsl_err("%s: wrong kty %d\n", __func__, jwe->jws.jwk->kty);
  35. return -1;
  36. }
  37. /* create the IV + CEK */
  38. if (lws_jws_randomize_element(jwe->jws.context, &jwe->jws.map, LJWE_IV,
  39. temp, temp_len,
  40. LWS_AESGCM_IV, 0))
  41. return -1;
  42. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
  43. temp + (ot - *temp_len),
  44. temp_len, LWS_AESGCM_TAG, 0))
  45. return -1;
  46. /* create a b64 version of the JOSE header, needed as aad */
  47. if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
  48. temp + (ot - *temp_len), temp_len,
  49. jwe->jws.map.buf[LJWE_JOSE],
  50. jwe->jws.map.len[LJWE_JOSE]))
  51. return -1;
  52. /*
  53. * If none already, create a new, random CEK in the JWE (so it can be
  54. * reused for other recipients on same payload). If it already exists,
  55. * just reuse it. It will be cleansed in the JWE destroy.
  56. */
  57. if (!jwe->cek_valid) {
  58. if (lws_get_random(jwe->jws.context, jwe->cek, ekbytes) !=
  59. (size_t)ekbytes) {
  60. lwsl_err("%s: Problem getting random\n", __func__);
  61. return -1;
  62. }
  63. jwe->cek_valid = 1;
  64. }
  65. if (lws_jws_dup_element(&jwe->jws.map, LJWE_EKEY,
  66. temp + (ot - *temp_len), temp_len,
  67. jwe->cek, ekbytes, 0))
  68. return -1;
  69. /* encrypt the payload */
  70. n = lws_jwe_encrypt_gcm(jwe, (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
  71. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  72. jwe->jws.map_b64.len[LJWE_JOSE]);
  73. if (n < 0) {
  74. lwsl_err("%s: lws_jwe_encrypt_gcm failed\n",
  75. __func__);
  76. goto bail;
  77. }
  78. /* Encrypt the CEK into EKEY to make the JWE Encrypted Key */
  79. if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
  80. !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
  81. LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
  82. LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
  83. lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
  84. __func__);
  85. goto bail;
  86. }
  87. n = lws_genrsa_public_encrypt(&rsactx, jwe->cek, ekbytes,
  88. (uint8_t *)jwe->jws.map.buf[LJWE_EKEY]);
  89. lws_genrsa_destroy(&rsactx);
  90. if (n < 0) {
  91. lwsl_err("%s: encrypt cek fail: \n", __func__);
  92. goto bail;
  93. }
  94. /* set the EKEY length to the actual enciphered length */
  95. jwe->jws.map.len[LJWE_EKEY] = n;
  96. ret = jwe->jws.map.len[LJWE_CTXT];
  97. bail:
  98. return ret;
  99. }
  100. int
  101. lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe)
  102. {
  103. int n;
  104. struct lws_genrsa_ctx rsactx;
  105. uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
  106. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
  107. lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
  108. return -1;
  109. }
  110. if (jwe->jws.map.len[LJWE_EKEY] < 32) {
  111. lwsl_err("%s: EKEY length too short %d\n", __func__,
  112. jwe->jws.map.len[LJWE_EKEY]);
  113. return -1;
  114. }
  115. /* Decrypt the JWE Encrypted Key to get the direct CEK */
  116. if (lws_genrsa_create(&rsactx, jwe->jws.jwk->e, jwe->jws.context,
  117. !strcmp(jwe->jose.alg->alg, "RSA-OAEP") ?
  118. LGRSAM_PKCS1_OAEP_PSS : LGRSAM_PKCS1_1_5,
  119. LWS_GENHASH_TYPE_SHA1 /* !!! */)) {
  120. lwsl_notice("%s: lws_genrsa_public_decrypt_create\n",
  121. __func__);
  122. return -1;
  123. }
  124. n = lws_genrsa_private_decrypt(&rsactx,
  125. (uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
  126. jwe->jws.map.len[LJWE_EKEY], enc_cek,
  127. sizeof(enc_cek));
  128. lws_genrsa_destroy(&rsactx);
  129. if (n < 0) {
  130. lwsl_err("%s: decrypt cek fail: \n", __func__);
  131. return -1;
  132. }
  133. n = lws_jwe_auth_and_decrypt_gcm(jwe, enc_cek,
  134. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  135. jwe->jws.map_b64.len[LJWE_JOSE]);
  136. if (n < 0) {
  137. lwsl_err("%s: lws_jwe_auth_and_decrypt_gcm_hs failed\n",
  138. __func__);
  139. return -1;
  140. }
  141. #if defined(LWS_WITH_MBEDTLS) && defined(LWS_PLAT_OPTEE)
  142. /* strip padding */
  143. n = jwe->jws.map.buf[LJWE_CTXT][jwe->jws.map.len[LJWE_CTXT] - 1];
  144. if (n > 16)
  145. return -1;
  146. jwe->jws.map.len[LJWE_CTXT] -= n;
  147. #endif
  148. return jwe->jws.map.len[LJWE_CTXT];
  149. }