jwe.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
  2. /*
  3. * Copyright 2016 Red Hat, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #define _GNU_SOURCE
  18. #include "misc.h"
  19. #include <jose/b64.h>
  20. #include <jose/jwk.h>
  21. #include <jose/jwe.h>
  22. #include "hooks.h"
  23. #include <errno.h>
  24. #include <string.h>
  25. #include <unistd.h>
  26. static bool
  27. jwe_hdr_set_new(json_t *jwe, const char *name, json_t *value)
  28. {
  29. json_auto_t *v = value;
  30. json_t *p = NULL;
  31. json_t *u = NULL;
  32. p = json_object_get(jwe, "protected");
  33. if (p && !json_is_object(p) && !json_is_string(p))
  34. return false;
  35. u = json_object_get(jwe, "unprotected");
  36. if (u && !json_is_object(u))
  37. return false;
  38. if (!u && json_is_string(p) &&
  39. json_object_set_new(jwe, "unprotected", u = json_object()) < 0)
  40. return false;
  41. if (!u && !p &&
  42. json_object_set_new(jwe, "protected", p = json_object()) < 0)
  43. return false;
  44. if (json_object_set(json_is_object(p) ? p : u, name, v) < 0)
  45. return false;
  46. return true;
  47. }
  48. json_t *
  49. jose_jwe_hdr(const json_t *jwe, const json_t *rcp)
  50. {
  51. json_auto_t *p = NULL;
  52. json_t *s = NULL;
  53. json_t *h = NULL;
  54. p = json_incref(json_object_get(jwe, "protected"));
  55. if (!p) {
  56. p = json_object();
  57. } else if (json_is_object(p)) {
  58. json_decref(p);
  59. p = json_deep_copy(p);
  60. } else if (json_is_string(p)) {
  61. json_decref(p);
  62. p = jose_b64_dec_load(p);
  63. }
  64. if (!json_is_object(p))
  65. return NULL;
  66. s = json_object_get(jwe, "unprotected");
  67. if (s) {
  68. if (json_object_update_missing(p, s) == -1)
  69. return NULL;
  70. }
  71. h = json_object_get(rcp, "header");
  72. if (h) {
  73. if (json_object_update_missing(p, h) == -1)
  74. return NULL;
  75. }
  76. return json_incref(p);
  77. }
  78. bool
  79. jose_jwe_enc(jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *jwk,
  80. const void *pt, size_t ptl)
  81. {
  82. json_auto_t *cek = NULL;
  83. cek = json_object();
  84. if (!cek)
  85. return NULL;
  86. if (!jose_jwe_enc_jwk(cfg, jwe, rcp, jwk, cek))
  87. return NULL;
  88. return jose_jwe_enc_cek(cfg, jwe, cek, pt, ptl);
  89. }
  90. jose_io_t *
  91. jose_jwe_enc_io(jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *jwk,
  92. jose_io_t *next)
  93. {
  94. json_auto_t *cek = NULL;
  95. cek = json_object();
  96. if (!cek)
  97. return NULL;
  98. if (!jose_jwe_enc_jwk(cfg, jwe, rcp, jwk, cek))
  99. return NULL;
  100. return jose_jwe_enc_cek_io(cfg, jwe, cek, next);
  101. }
  102. static const jose_hook_alg_t *
  103. find_alg(jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *hdr,
  104. const json_t *jwk)
  105. {
  106. const jose_hook_alg_t *alg = NULL;
  107. const char *name = NULL;
  108. json_t *h = NULL;
  109. if (json_unpack((json_t *) hdr, "{s:s}", "alg", &name) >= 0)
  110. return jose_hook_alg_find(JOSE_HOOK_ALG_KIND_WRAP, name);
  111. for (alg = jose_hook_alg_list(); alg && !name; alg = alg->next) {
  112. if (alg->kind != JOSE_HOOK_ALG_KIND_WRAP)
  113. continue;
  114. name = alg->wrap.alg(alg, cfg, jwk);
  115. }
  116. if (!name)
  117. return NULL;
  118. alg = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_WRAP, name);
  119. if (alg) {
  120. h = json_object_get(rcp, "header");
  121. if (!h && json_object_set_new(rcp, "header", h = json_object()) < 0)
  122. return NULL;
  123. if (json_object_set_new(h, "alg", json_string(alg->name)) < 0)
  124. return NULL;
  125. }
  126. return alg;
  127. }
  128. static bool
  129. ensure_enc(const jose_hook_alg_t *alg, jose_cfg_t *cfg, json_t *jwe,
  130. const json_t *hdr, const json_t *jwk, json_t *cek)
  131. {
  132. const char *enc = NULL;
  133. enc = json_string_value(json_object_get(cek, "alg"));
  134. if (enc)
  135. return true;
  136. if (json_unpack((json_t *) hdr, "{s?s}", "enc", &enc) < 0)
  137. return false;
  138. /* See if we can infer an enc from the CEK. */
  139. for (const jose_hook_alg_t *a = jose_hook_alg_list();
  140. a && !enc; a = a->next) {
  141. if (a->kind != JOSE_HOOK_ALG_KIND_ENCR)
  142. continue;
  143. enc = a->encr.sug(a, cfg, cek);
  144. }
  145. /* See if we can infer an enc from the JWK. */
  146. if (!enc)
  147. enc = alg->wrap.enc(alg, cfg, jwk);
  148. /* Just pick an enc. */
  149. for (const jose_hook_alg_t *a = jose_hook_alg_list();
  150. a && !enc; a = a->next) {
  151. if (a->kind == JOSE_HOOK_ALG_KIND_ENCR)
  152. enc = a->name;
  153. }
  154. return json_object_set_new(cek, "alg", json_string(enc)) >= 0;
  155. }
  156. bool
  157. jose_jwe_enc_jwk(jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *jwk,
  158. json_t *cek)
  159. {
  160. const jose_hook_alg_t *alg = NULL;
  161. json_auto_t *hdr = NULL;
  162. json_auto_t *r = NULL;
  163. if (!cek)
  164. return false;
  165. if (json_is_array(jwk) || json_is_array(json_object_get(jwk, "keys"))) {
  166. if (!json_is_array(jwk))
  167. jwk = json_object_get(jwk, "keys");
  168. if (json_is_array(rcp) && json_array_size(rcp) != json_array_size(jwk))
  169. return NULL;
  170. for (size_t i = 0; i < json_array_size(jwk); i++) {
  171. json_auto_t *tmp = NULL;
  172. if (json_is_array(rcp))
  173. tmp = json_incref(json_array_get(rcp, i));
  174. else
  175. tmp = json_deep_copy(rcp);
  176. if (!jose_jwe_enc_jwk(cfg, jwe, tmp, json_array_get(jwk, i), cek))
  177. return false;
  178. }
  179. return json_array_size(jwk) > 0;
  180. }
  181. if (!rcp)
  182. r = json_object();
  183. else if (!json_is_object(rcp))
  184. return false;
  185. else
  186. r = json_incref(rcp);
  187. hdr = jose_jwe_hdr(jwe, r);
  188. if (!hdr)
  189. return false;
  190. alg = find_alg(cfg, jwe, r, hdr, jwk);
  191. if (!alg)
  192. return false;
  193. if (!ensure_enc(alg, cfg, jwe, hdr, jwk, cek))
  194. return false;
  195. if (!jose_jwk_prm(cfg, jwk, false, alg->wrap.eprm))
  196. return false;
  197. return alg->wrap.wrp(alg, cfg, jwe, r, jwk, cek);
  198. }
  199. bool
  200. jose_jwe_enc_cek(jose_cfg_t *cfg, json_t *jwe, const json_t *cek,
  201. const void *pt, size_t ptl)
  202. {
  203. jose_io_auto_t *i = NULL;
  204. jose_io_auto_t *o = NULL;
  205. void *ct = NULL;
  206. size_t ctl = 0;
  207. o = jose_io_malloc(cfg, &ct, &ctl);
  208. i = jose_jwe_enc_cek_io(cfg, jwe, cek, o);
  209. if (!o || !i || !i->feed(i, pt, ptl) || !i->done(i))
  210. return false;
  211. if (json_object_set_new(jwe, "ciphertext", jose_b64_enc(ct, ctl)) < 0)
  212. return false;
  213. return true;
  214. }
  215. jose_io_t *
  216. jose_jwe_enc_cek_io(jose_cfg_t *cfg, json_t *jwe, const json_t *cek,
  217. jose_io_t *next)
  218. {
  219. const jose_hook_alg_t *alg = NULL;
  220. jose_io_auto_t *zip = NULL;
  221. json_auto_t *prt = NULL;
  222. const char *h = NULL;
  223. const char *k = NULL;
  224. const char *z = NULL;
  225. prt = jose_b64_dec_load(json_object_get(jwe, "protected"));
  226. (void) json_unpack(prt, "{s:s}", "zip", &z);
  227. if (json_unpack(jwe, "{s?{s?s}}", "unprotected", "enc", &h) < 0)
  228. return NULL;
  229. if (json_unpack(jwe, "{s?{s?s}}", "protected", "enc", &h) < 0)
  230. return NULL;
  231. if (json_unpack((json_t *) cek, "{s?s}", "alg", &k) < 0)
  232. return NULL;
  233. if (!h) {
  234. h = k;
  235. for (alg = jose_hook_alg_list(); alg && !h; alg = alg->next) {
  236. if (alg->kind != JOSE_HOOK_ALG_KIND_ENCR)
  237. continue;
  238. h = alg->encr.sug(alg, cfg, cek);
  239. }
  240. if (!h) {
  241. jose_cfg_err(cfg, JOSE_CFG_ERR_ALG_NOINFER,
  242. "Unable to infer encryption algorithm");
  243. return NULL;
  244. }
  245. alg = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_ENCR, h);
  246. if (alg && !jwe_hdr_set_new(jwe, "enc", json_string(alg->name)))
  247. return NULL;
  248. } else {
  249. if (k && strcmp(h, k) != 0) {
  250. jose_cfg_err(cfg, JOSE_CFG_ERR_JWK_MISMATCH,
  251. "Algorithm mismatch (%s != %s)", h, k);
  252. return NULL;
  253. }
  254. alg = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_ENCR, h);
  255. }
  256. if (!alg) {
  257. jose_cfg_err(cfg, JOSE_CFG_ERR_ALG_NOTSUP,
  258. "Unsupported encryption algorithm (%s)", h);
  259. return NULL;
  260. }
  261. if (!jose_jwk_prm(cfg, cek, false, alg->encr.eprm)) {
  262. jose_cfg_err(cfg, JOSE_CFG_ERR_JWK_DENIED,
  263. "CEK is not allowed to encrypt");
  264. return NULL;
  265. }
  266. if (!encode_protected(jwe))
  267. return NULL;
  268. if (z) {
  269. const jose_hook_alg_t *a = NULL;
  270. a = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_COMP, z);
  271. if (!a)
  272. return NULL;
  273. zip = a->comp.def(a, cfg, next);
  274. if (!zip)
  275. return NULL;
  276. }
  277. return alg->encr.enc(alg, cfg, jwe, cek, zip ? zip : next);
  278. }
  279. void *
  280. jose_jwe_dec(jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp,
  281. const json_t *jwk, size_t *ptl)
  282. {
  283. json_auto_t *cek = NULL;
  284. cek = jose_jwe_dec_jwk(cfg, jwe, rcp, jwk);
  285. if (!cek)
  286. return NULL;
  287. return jose_jwe_dec_cek(cfg, jwe, cek, ptl);
  288. }
  289. jose_io_t *
  290. jose_jwe_dec_io(jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp,
  291. const json_t *jwk, jose_io_t *next)
  292. {
  293. json_auto_t *cek = NULL;
  294. cek = jose_jwe_dec_jwk(cfg, jwe, rcp, jwk);
  295. if (!cek)
  296. return NULL;
  297. return jose_jwe_dec_cek_io(cfg, jwe, cek, next);
  298. }
  299. json_t *
  300. jose_jwe_dec_jwk(jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp,
  301. const json_t *jwk)
  302. {
  303. const jose_hook_alg_t *alg = NULL;
  304. const char *halg = NULL;
  305. const char *henc = NULL;
  306. const char *kalg = NULL;
  307. json_auto_t *cek = NULL;
  308. json_auto_t *hdr = NULL;
  309. if (json_is_array(jwk) || json_is_array(json_object_get(jwk, "keys"))) {
  310. if (!json_is_array(jwk))
  311. jwk = json_object_get(jwk, "keys");
  312. for (size_t i = 0; i < json_array_size(jwk) && !cek; i++)
  313. cek = jose_jwe_dec_jwk(cfg, jwe, rcp, json_array_get(jwk, i));
  314. return json_incref(cek);
  315. }
  316. if (!rcp) {
  317. const json_t *rcps = NULL;
  318. rcps = json_object_get(jwe, "recipients");
  319. if (json_is_array(rcps)) {
  320. for (size_t i = 0; i < json_array_size(rcps) && !cek; i++)
  321. cek = jose_jwe_dec_jwk(cfg, jwe, json_array_get(rcps, i), jwk);
  322. } else if (!rcps) {
  323. cek = jose_jwe_dec_jwk(cfg, jwe, jwe, jwk);
  324. }
  325. return json_incref(cek);
  326. }
  327. hdr = jose_jwe_hdr(jwe, rcp);
  328. if (!hdr)
  329. return NULL;
  330. if (json_unpack(hdr, "{s?s,s?s}", "alg", &halg, "enc", &henc) == -1)
  331. return NULL;
  332. kalg = json_string_value(json_object_get(jwk, "alg"));
  333. if (!halg)
  334. halg = kalg;
  335. else if (kalg && strcmp(halg, kalg) != 0 &&
  336. (!henc || strcmp(henc, kalg) != 0))
  337. return NULL;
  338. alg = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_WRAP, halg);
  339. if (!alg)
  340. return NULL;
  341. if (!jose_jwk_prm(cfg, jwk, false, alg->wrap.dprm))
  342. return NULL;
  343. cek = json_pack("{s:s,s:s,s:O,s:[ss]}",
  344. "kty", "oct", "use", "enc",
  345. "enc", json_object_get(hdr, "enc"),
  346. "key_ops", "encrypt", "decrypt");
  347. if (!cek)
  348. return NULL;
  349. if (!alg->wrap.unw(alg, cfg, jwe, rcp, jwk, cek))
  350. return NULL;
  351. return json_incref(cek);
  352. }
  353. void *
  354. jose_jwe_dec_cek(jose_cfg_t *cfg, const json_t *jwe, const json_t *cek,
  355. size_t *ptl)
  356. {
  357. jose_io_auto_t *d = NULL;
  358. jose_io_auto_t *i = NULL;
  359. jose_io_auto_t *o = NULL;
  360. const char *ct = NULL;
  361. void *pt = NULL;
  362. size_t ctl = 0;
  363. if (json_unpack((json_t *) jwe, "{s:s%}", "ciphertext", &ct, &ctl) < 0)
  364. return NULL;
  365. o = jose_io_malloc(cfg, &pt, ptl);
  366. d = jose_jwe_dec_cek_io(cfg, jwe, cek, o);
  367. i = jose_b64_dec_io(d);
  368. if (!o || !d || !i || !i->feed(i, ct, ctl) || !i->done(i))
  369. return NULL;
  370. return jose_io_malloc_steal(&pt);
  371. }
  372. jose_io_t *
  373. jose_jwe_dec_cek_io(jose_cfg_t *cfg, const json_t *jwe, const json_t *cek,
  374. jose_io_t *next)
  375. {
  376. const jose_hook_alg_t *alg = NULL;
  377. jose_io_auto_t *zip = NULL;
  378. json_auto_t *hdr = NULL;
  379. json_auto_t *prt = NULL;
  380. const char *kalg = NULL;
  381. const char *halg = NULL;
  382. const char *hzip = NULL;
  383. prt = jose_b64_dec_load(json_object_get(jwe, "protected"));
  384. (void) json_unpack(prt, "{s:s}", "zip", &hzip);
  385. hdr = jose_jwe_hdr(jwe, NULL);
  386. if (!hdr)
  387. return NULL;
  388. if (json_unpack(hdr, "{s?s}", "enc", &halg) < 0)
  389. return NULL;
  390. if (json_unpack((json_t *) cek, "{s?s}", "alg", &kalg) < 0)
  391. return NULL;
  392. if (!halg && !kalg) {
  393. jose_cfg_err(cfg, JOSE_CFG_ERR_ALG_NOINFER,
  394. "Decryption algorithm cannot be inferred");
  395. return NULL;
  396. } else if (halg && kalg && strcmp(halg, kalg) != 0) {
  397. jose_cfg_err(cfg, JOSE_CFG_ERR_JWK_MISMATCH,
  398. "Algorithm mismatch (%s != %s)", halg, kalg);
  399. return NULL;
  400. }
  401. alg = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_ENCR, halg ? halg : kalg);
  402. if (!alg)
  403. return NULL;
  404. if (!jose_jwk_prm(cfg, cek, false, alg->encr.dprm))
  405. return NULL;
  406. if (hzip) {
  407. const jose_hook_alg_t *a = NULL;
  408. a = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_COMP, hzip);
  409. if (!a)
  410. return NULL;
  411. zip = a->comp.inf(a, cfg, next);
  412. if (!zip)
  413. return NULL;
  414. }
  415. return alg->encr.dec(alg, cfg, jwe, cek, zip ? zip : next);
  416. }