You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

keypair.c 24KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "libcryptobox/keypair.h"
  18. #include "libcryptobox/keypair_private.h"
  19. #include "libutil/str_util.h"
  20. #include "libutil/printf.h"
  21. #include "contrib/libottery/ottery.h"
  22. const guchar encrypted_magic[7] = {'r', 'u', 'c', 'l', 'e', 'v', '1'};
  23. static GQuark
  24. rspamd_keypair_quark (void)
  25. {
  26. return g_quark_from_static_string ("rspamd-cryptobox-keypair");
  27. }
  28. /**
  29. * Returns specific private key for different keypair types
  30. */
  31. static void *
  32. rspamd_cryptobox_keypair_sk (struct rspamd_cryptobox_keypair *kp,
  33. guint *len)
  34. {
  35. g_assert (kp != NULL);
  36. if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  37. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  38. *len = 32;
  39. return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->sk;
  40. }
  41. else {
  42. *len = 64;
  43. return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->sk;
  44. }
  45. }
  46. else {
  47. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  48. *len = 32;
  49. return RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp)->sk;
  50. }
  51. else {
  52. *len = 32;
  53. return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_NIST(kp)->sk;
  54. }
  55. }
  56. /* Not reached */
  57. return NULL;
  58. }
  59. static void *
  60. rspamd_cryptobox_keypair_pk (struct rspamd_cryptobox_keypair *kp,
  61. guint *len)
  62. {
  63. g_assert (kp != NULL);
  64. if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  65. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  66. *len = 32;
  67. return RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp)->pk;
  68. }
  69. else {
  70. *len = 32;
  71. return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_25519(kp)->pk;
  72. }
  73. }
  74. else {
  75. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  76. *len = 65;
  77. return RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp)->pk;
  78. }
  79. else {
  80. *len = 65;
  81. return RSPAMD_CRYPTOBOX_KEYPAIR_SIG_NIST(kp)->pk;
  82. }
  83. }
  84. /* Not reached */
  85. return NULL;
  86. }
  87. static void *
  88. rspamd_cryptobox_pubkey_pk (const struct rspamd_cryptobox_pubkey *kp,
  89. guint *len)
  90. {
  91. g_assert (kp != NULL);
  92. if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  93. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  94. *len = 32;
  95. return RSPAMD_CRYPTOBOX_PUBKEY_25519(kp)->pk;
  96. }
  97. else {
  98. *len = 32;
  99. return RSPAMD_CRYPTOBOX_PUBKEY_SIG_25519(kp)->pk;
  100. }
  101. }
  102. else {
  103. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  104. *len = 65;
  105. return RSPAMD_CRYPTOBOX_PUBKEY_NIST(kp)->pk;
  106. }
  107. else {
  108. *len = 65;
  109. return RSPAMD_CRYPTOBOX_PUBKEY_SIG_NIST(kp)->pk;
  110. }
  111. }
  112. /* Not reached */
  113. return NULL;
  114. }
  115. static struct rspamd_cryptobox_keypair *
  116. rspamd_cryptobox_keypair_alloc (enum rspamd_cryptobox_keypair_type type,
  117. enum rspamd_cryptobox_mode alg)
  118. {
  119. struct rspamd_cryptobox_keypair *kp;
  120. guint size = 0;
  121. if (alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  122. if (type == RSPAMD_KEYPAIR_KEX) {
  123. size = sizeof (struct rspamd_cryptobox_keypair_25519);
  124. }
  125. else {
  126. size = sizeof (struct rspamd_cryptobox_keypair_sig_25519);
  127. }
  128. }
  129. else {
  130. if (type == RSPAMD_KEYPAIR_KEX) {
  131. size = sizeof (struct rspamd_cryptobox_keypair_nist);
  132. }
  133. else {
  134. size = sizeof (struct rspamd_cryptobox_keypair_sig_nist);
  135. }
  136. }
  137. g_assert (size >= sizeof (*kp));
  138. if (posix_memalign ((void **)&kp, 32, size) != 0) {
  139. abort ();
  140. }
  141. memset (kp, 0, size);
  142. return kp;
  143. }
  144. static struct rspamd_cryptobox_pubkey *
  145. rspamd_cryptobox_pubkey_alloc (enum rspamd_cryptobox_keypair_type type,
  146. enum rspamd_cryptobox_mode alg)
  147. {
  148. struct rspamd_cryptobox_pubkey *pk;
  149. guint size = 0;
  150. if (alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  151. if (type == RSPAMD_KEYPAIR_KEX) {
  152. size = sizeof (struct rspamd_cryptobox_pubkey_25519);
  153. }
  154. else {
  155. size = sizeof (struct rspamd_cryptobox_pubkey_sig_25519);
  156. }
  157. }
  158. else {
  159. if (type == RSPAMD_KEYPAIR_KEX) {
  160. size = sizeof (struct rspamd_cryptobox_pubkey_nist);
  161. }
  162. else {
  163. size = sizeof (struct rspamd_cryptobox_pubkey_sig_nist);
  164. }
  165. }
  166. g_assert (size >= sizeof (*pk));
  167. if (posix_memalign ((void **)&pk, 32, size) != 0) {
  168. abort ();
  169. }
  170. memset (pk, 0, size);
  171. return pk;
  172. }
  173. void
  174. rspamd_cryptobox_nm_dtor (struct rspamd_cryptobox_nm *nm)
  175. {
  176. rspamd_explicit_memzero (nm->nm, sizeof (nm->nm));
  177. free (nm);
  178. }
  179. void
  180. rspamd_cryptobox_keypair_dtor (struct rspamd_cryptobox_keypair *kp)
  181. {
  182. void *sk;
  183. guint len = 0;
  184. sk = rspamd_cryptobox_keypair_sk (kp, &len);
  185. g_assert (sk != NULL && len > 0);
  186. rspamd_explicit_memzero (sk, len);
  187. /* Not g_free as kp is aligned using posix_memalign */
  188. free (kp);
  189. }
  190. void
  191. rspamd_cryptobox_pubkey_dtor (struct rspamd_cryptobox_pubkey *p)
  192. {
  193. if (p->nm) {
  194. REF_RELEASE (p->nm);
  195. }
  196. /* Not g_free as p is aligned using posix_memalign */
  197. free (p);
  198. }
  199. struct rspamd_cryptobox_keypair*
  200. rspamd_keypair_new (enum rspamd_cryptobox_keypair_type type,
  201. enum rspamd_cryptobox_mode alg)
  202. {
  203. struct rspamd_cryptobox_keypair *kp;
  204. void *pk, *sk;
  205. guint size;
  206. kp = rspamd_cryptobox_keypair_alloc (type, alg);
  207. kp->alg = alg;
  208. kp->type = type;
  209. sk = rspamd_cryptobox_keypair_sk (kp, &size);
  210. pk = rspamd_cryptobox_keypair_pk (kp, &size);
  211. if (type == RSPAMD_KEYPAIR_KEX) {
  212. rspamd_cryptobox_keypair (pk, sk, alg);
  213. }
  214. else {
  215. rspamd_cryptobox_keypair_sig (pk, sk, alg);
  216. }
  217. rspamd_cryptobox_hash (kp->id, pk, size, NULL, 0);
  218. REF_INIT_RETAIN (kp, rspamd_cryptobox_keypair_dtor);
  219. return kp;
  220. }
  221. struct rspamd_cryptobox_keypair*
  222. rspamd_keypair_ref (struct rspamd_cryptobox_keypair *kp)
  223. {
  224. REF_RETAIN (kp);
  225. return kp;
  226. }
  227. void
  228. rspamd_keypair_unref (struct rspamd_cryptobox_keypair *kp)
  229. {
  230. REF_RELEASE (kp);
  231. }
  232. struct rspamd_cryptobox_pubkey*
  233. rspamd_pubkey_ref (struct rspamd_cryptobox_pubkey *kp)
  234. {
  235. REF_RETAIN (kp);
  236. return kp;
  237. }
  238. void
  239. rspamd_pubkey_unref (struct rspamd_cryptobox_pubkey *kp)
  240. {
  241. REF_RELEASE (kp);
  242. }
  243. enum rspamd_cryptobox_keypair_type
  244. rspamd_keypair_type (struct rspamd_cryptobox_keypair *kp)
  245. {
  246. g_assert (kp != NULL);
  247. return kp->type;
  248. }
  249. enum rspamd_cryptobox_keypair_type
  250. rspamd_pubkey_type (struct rspamd_cryptobox_pubkey *p)
  251. {
  252. g_assert (p != NULL);
  253. return p->type;
  254. }
  255. enum rspamd_cryptobox_mode
  256. rspamd_keypair_alg (struct rspamd_cryptobox_keypair *kp)
  257. {
  258. g_assert (kp != NULL);
  259. return kp->alg;
  260. }
  261. enum rspamd_cryptobox_mode
  262. rspamd_pubkey_alg (struct rspamd_cryptobox_pubkey *p)
  263. {
  264. g_assert (p != NULL);
  265. return p->alg;
  266. }
  267. struct rspamd_cryptobox_pubkey*
  268. rspamd_pubkey_from_base32 (const gchar *b32,
  269. gsize len,
  270. enum rspamd_cryptobox_keypair_type type,
  271. enum rspamd_cryptobox_mode alg)
  272. {
  273. guchar *decoded;
  274. gsize dlen, expected_len;
  275. guint pklen;
  276. struct rspamd_cryptobox_pubkey *pk;
  277. guchar *pk_data;
  278. g_assert (b32 != NULL);
  279. if (len == 0) {
  280. len = strlen (b32);
  281. }
  282. decoded = rspamd_decode_base32 (b32, len, &dlen, RSPAMD_BASE32_DEFAULT);
  283. if (decoded == NULL) {
  284. return NULL;
  285. }
  286. expected_len = (type == RSPAMD_KEYPAIR_KEX) ?
  287. rspamd_cryptobox_pk_bytes (alg) : rspamd_cryptobox_pk_sig_bytes (alg);
  288. if (dlen != expected_len) {
  289. g_free (decoded);
  290. return NULL;
  291. }
  292. pk = rspamd_cryptobox_pubkey_alloc (type, alg);
  293. REF_INIT_RETAIN (pk, rspamd_cryptobox_pubkey_dtor);
  294. pk->alg = alg;
  295. pk->type = type;
  296. pk_data = rspamd_cryptobox_pubkey_pk (pk, &pklen);
  297. memcpy (pk_data, decoded, pklen);
  298. g_free (decoded);
  299. rspamd_cryptobox_hash (pk->id, pk_data, pklen, NULL, 0);
  300. return pk;
  301. }
  302. struct rspamd_cryptobox_pubkey*
  303. rspamd_pubkey_from_hex (const gchar *hex,
  304. gsize len,
  305. enum rspamd_cryptobox_keypair_type type,
  306. enum rspamd_cryptobox_mode alg)
  307. {
  308. guchar *decoded;
  309. gsize dlen, expected_len;
  310. guint pklen;
  311. struct rspamd_cryptobox_pubkey *pk;
  312. guchar *pk_data;
  313. g_assert (hex != NULL);
  314. if (len == 0) {
  315. len = strlen (hex);
  316. }
  317. dlen = len / 2;
  318. decoded = rspamd_decode_hex (hex, len);
  319. if (decoded == NULL) {
  320. return NULL;
  321. }
  322. expected_len = (type == RSPAMD_KEYPAIR_KEX) ?
  323. rspamd_cryptobox_pk_bytes (alg) : rspamd_cryptobox_pk_sig_bytes (alg);
  324. if (dlen != expected_len) {
  325. g_free (decoded);
  326. return NULL;
  327. }
  328. pk = rspamd_cryptobox_pubkey_alloc (type, alg);
  329. REF_INIT_RETAIN (pk, rspamd_cryptobox_pubkey_dtor);
  330. pk->alg = alg;
  331. pk->type = type;
  332. pk_data = rspamd_cryptobox_pubkey_pk (pk, &pklen);
  333. memcpy (pk_data, decoded, pklen);
  334. g_free (decoded);
  335. rspamd_cryptobox_hash (pk->id, pk_data, pklen, NULL, 0);
  336. return pk;
  337. }
  338. struct rspamd_cryptobox_pubkey*
  339. rspamd_pubkey_from_bin (const guchar *raw,
  340. gsize len,
  341. enum rspamd_cryptobox_keypair_type type,
  342. enum rspamd_cryptobox_mode alg)
  343. {
  344. gsize expected_len;
  345. guint pklen;
  346. struct rspamd_cryptobox_pubkey *pk;
  347. guchar *pk_data;
  348. g_assert (raw != NULL && len > 0);
  349. expected_len = (type == RSPAMD_KEYPAIR_KEX) ?
  350. rspamd_cryptobox_pk_bytes (alg) : rspamd_cryptobox_pk_sig_bytes (alg);
  351. if (len != expected_len) {
  352. return NULL;
  353. }
  354. pk = rspamd_cryptobox_pubkey_alloc (type, alg);
  355. REF_INIT_RETAIN (pk, rspamd_cryptobox_pubkey_dtor);
  356. pk->alg = alg;
  357. pk->type = type;
  358. pk_data = rspamd_cryptobox_pubkey_pk (pk, &pklen);
  359. memcpy (pk_data, raw, pklen);
  360. rspamd_cryptobox_hash (pk->id, pk_data, pklen, NULL, 0);
  361. return pk;
  362. }
  363. const guchar *
  364. rspamd_pubkey_get_nm (struct rspamd_cryptobox_pubkey *p,
  365. struct rspamd_cryptobox_keypair *kp)
  366. {
  367. g_assert (p != NULL);
  368. if (p->nm) {
  369. if (memcmp (kp->id, (const guchar *)&p->nm->sk_id, sizeof (guint64)) == 0) {
  370. return p->nm->nm;
  371. }
  372. /* Wrong ID, need to recalculate */
  373. REF_RELEASE (p->nm);
  374. p->nm = NULL;
  375. }
  376. return NULL;
  377. }
  378. const guchar *
  379. rspamd_pubkey_calculate_nm (struct rspamd_cryptobox_pubkey *p,
  380. struct rspamd_cryptobox_keypair *kp)
  381. {
  382. g_assert (kp->alg == p->alg);
  383. g_assert (kp->type == p->type);
  384. g_assert (p->type == RSPAMD_KEYPAIR_KEX);
  385. if (p->nm == NULL) {
  386. if (posix_memalign ((void **)&p->nm, 32, sizeof (*p->nm)) != 0) {
  387. abort ();
  388. }
  389. memcpy (&p->nm->sk_id, kp->id, sizeof (guint64));
  390. REF_INIT_RETAIN (p->nm, rspamd_cryptobox_nm_dtor);
  391. }
  392. if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  393. struct rspamd_cryptobox_pubkey_25519 *rk_25519 =
  394. RSPAMD_CRYPTOBOX_PUBKEY_25519(p);
  395. struct rspamd_cryptobox_keypair_25519 *sk_25519 =
  396. RSPAMD_CRYPTOBOX_KEYPAIR_25519(kp);
  397. rspamd_cryptobox_nm (p->nm->nm, rk_25519->pk, sk_25519->sk, p->alg);
  398. }
  399. else {
  400. struct rspamd_cryptobox_pubkey_nist *rk_nist =
  401. RSPAMD_CRYPTOBOX_PUBKEY_NIST(p);
  402. struct rspamd_cryptobox_keypair_nist *sk_nist =
  403. RSPAMD_CRYPTOBOX_KEYPAIR_NIST(kp);
  404. rspamd_cryptobox_nm (p->nm->nm, rk_nist->pk, sk_nist->sk, p->alg);
  405. }
  406. return p->nm->nm;
  407. }
  408. const guchar *
  409. rspamd_keypair_get_id (struct rspamd_cryptobox_keypair *kp)
  410. {
  411. g_assert (kp != NULL);
  412. return kp->id;
  413. }
  414. const guchar *
  415. rspamd_pubkey_get_id (struct rspamd_cryptobox_pubkey *pk)
  416. {
  417. g_assert (pk != NULL);
  418. return pk->id;
  419. }
  420. const guchar *
  421. rspamd_pubkey_get_pk (struct rspamd_cryptobox_pubkey *pk,
  422. guint *len)
  423. {
  424. guchar *ret = NULL;
  425. guint rlen;
  426. ret = rspamd_cryptobox_pubkey_pk (pk, &rlen);
  427. if (len) {
  428. *len = rlen;
  429. }
  430. return ret;
  431. }
  432. static void
  433. rspamd_keypair_print_component (guchar *data, gsize datalen,
  434. GString *res, guint how, const gchar *description)
  435. {
  436. gint olen, b32_len;
  437. if (how & RSPAMD_KEYPAIR_HUMAN) {
  438. rspamd_printf_gstring (res, "%s: ", description);
  439. }
  440. if (how & RSPAMD_KEYPAIR_BASE32) {
  441. b32_len = (datalen * 8 / 5) + 2;
  442. g_string_set_size (res, res->len + b32_len);
  443. res->len -= b32_len;
  444. olen = rspamd_encode_base32_buf (data, datalen, res->str + res->len,
  445. res->len + b32_len - 1, RSPAMD_BASE32_DEFAULT);
  446. if (olen > 0) {
  447. res->len += olen;
  448. res->str[res->len] = '\0';
  449. }
  450. }
  451. else if (how & RSPAMD_KEYPAIR_HEX) {
  452. rspamd_printf_gstring (res, "%*xs", (gint)datalen, data);
  453. }
  454. else {
  455. g_string_append_len (res, data, datalen);
  456. }
  457. if (how & RSPAMD_KEYPAIR_HUMAN) {
  458. g_string_append_c (res, '\n');
  459. }
  460. }
  461. GString *
  462. rspamd_keypair_print (struct rspamd_cryptobox_keypair *kp, guint how)
  463. {
  464. GString *res;
  465. guint len;
  466. gpointer p;
  467. g_assert (kp != NULL);
  468. res = g_string_sized_new (63);
  469. if ((how & RSPAMD_KEYPAIR_PUBKEY)) {
  470. p = rspamd_cryptobox_keypair_pk (kp, &len);
  471. rspamd_keypair_print_component (p, len, res, how, "Public key");
  472. }
  473. if ((how & RSPAMD_KEYPAIR_PRIVKEY)) {
  474. p = rspamd_cryptobox_keypair_sk (kp, &len);
  475. rspamd_keypair_print_component (p, len, res, how, "Private key");
  476. }
  477. if ((how & RSPAMD_KEYPAIR_ID_SHORT)) {
  478. rspamd_keypair_print_component (kp->id, RSPAMD_KEYPAIR_SHORT_ID_LEN,
  479. res, how, "Short key ID");
  480. }
  481. if ((how & RSPAMD_KEYPAIR_ID)) {
  482. rspamd_keypair_print_component (kp->id, sizeof (kp->id), res, how, "Key ID");
  483. }
  484. return res;
  485. }
  486. GString *
  487. rspamd_pubkey_print (struct rspamd_cryptobox_pubkey *pk, guint how)
  488. {
  489. GString *res;
  490. guint len;
  491. gpointer p;
  492. g_assert (pk != NULL);
  493. res = g_string_sized_new (63);
  494. if ((how & RSPAMD_KEYPAIR_PUBKEY)) {
  495. p = rspamd_cryptobox_pubkey_pk (pk, &len);
  496. rspamd_keypair_print_component (p, len, res, how, "Public key");
  497. }
  498. if ((how & RSPAMD_KEYPAIR_ID_SHORT)) {
  499. rspamd_keypair_print_component (pk->id, RSPAMD_KEYPAIR_SHORT_ID_LEN,
  500. res, how, "Short key ID");
  501. }
  502. if ((how & RSPAMD_KEYPAIR_ID)) {
  503. rspamd_keypair_print_component (pk->id, sizeof (pk->id), res, how,
  504. "Key ID");
  505. }
  506. return res;
  507. }
  508. const guchar *
  509. rspamd_keypair_component (struct rspamd_cryptobox_keypair *kp,
  510. guint ncomp, guint *len)
  511. {
  512. guint rlen = 0;
  513. const guchar *ret = NULL;
  514. g_assert (kp != NULL);
  515. switch (ncomp) {
  516. case RSPAMD_KEYPAIR_COMPONENT_ID:
  517. rlen = sizeof (kp->id);
  518. ret = kp->id;
  519. break;
  520. case RSPAMD_KEYPAIR_COMPONENT_PK:
  521. ret = rspamd_cryptobox_keypair_pk (kp, &rlen);
  522. break;
  523. case RSPAMD_KEYPAIR_COMPONENT_SK:
  524. ret = rspamd_cryptobox_keypair_sk (kp, &rlen);
  525. break;
  526. }
  527. if (len) {
  528. *len = rlen;
  529. }
  530. return ret;
  531. }
  532. struct rspamd_cryptobox_keypair *
  533. rspamd_keypair_from_ucl (const ucl_object_t *obj)
  534. {
  535. const ucl_object_t *privkey, *pubkey, *elt;
  536. const gchar *str;
  537. enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
  538. enum rspamd_cryptobox_mode mode = RSPAMD_CRYPTOBOX_MODE_25519;
  539. gboolean is_hex = FALSE;
  540. struct rspamd_cryptobox_keypair *kp;
  541. guint len;
  542. gsize ucl_len;
  543. gint dec_len;
  544. gpointer target;
  545. if (ucl_object_type (obj) != UCL_OBJECT) {
  546. return NULL;
  547. }
  548. elt = ucl_object_lookup (obj, "keypair");
  549. if (elt != NULL) {
  550. obj = elt;
  551. }
  552. pubkey = ucl_object_lookup_any (obj, "pubkey", "public", "public_key",
  553. NULL);
  554. if (pubkey == NULL || ucl_object_type (pubkey) != UCL_STRING) {
  555. return NULL;
  556. }
  557. privkey = ucl_object_lookup_any (obj, "privkey", "private", "private_key",
  558. "secret", "secret_key", NULL);
  559. if (privkey == NULL || ucl_object_type (privkey) != UCL_STRING) {
  560. return NULL;
  561. }
  562. /* Optional fields */
  563. elt = ucl_object_lookup (obj, "type");
  564. if (elt && ucl_object_type (elt) == UCL_STRING) {
  565. str = ucl_object_tostring (elt);
  566. if (g_ascii_strcasecmp (str, "kex") == 0) {
  567. type = RSPAMD_KEYPAIR_KEX;
  568. }
  569. else if (g_ascii_strcasecmp (str, "sign") == 0) {
  570. type = RSPAMD_KEYPAIR_SIGN;
  571. }
  572. /* TODO: handle errors */
  573. }
  574. elt = ucl_object_lookup (obj, "algorithm");
  575. if (elt && ucl_object_type (elt) == UCL_STRING) {
  576. str = ucl_object_tostring (elt);
  577. if (g_ascii_strcasecmp (str, "curve25519") == 0) {
  578. mode = RSPAMD_CRYPTOBOX_MODE_25519;
  579. }
  580. else if (g_ascii_strcasecmp (str, "nistp256") == 0) {
  581. mode = RSPAMD_CRYPTOBOX_MODE_NIST;
  582. }
  583. /* TODO: handle errors */
  584. }
  585. elt = ucl_object_lookup (obj, "encoding");
  586. if (elt && ucl_object_type (elt) == UCL_STRING) {
  587. str = ucl_object_tostring (elt);
  588. if (g_ascii_strcasecmp (str, "hex") == 0) {
  589. is_hex = TRUE;
  590. }
  591. /* TODO: handle errors */
  592. }
  593. kp = rspamd_cryptobox_keypair_alloc (type, mode);
  594. kp->type = type;
  595. kp->alg = mode;
  596. REF_INIT_RETAIN (kp, rspamd_cryptobox_keypair_dtor);
  597. g_assert (kp != NULL);
  598. target = rspamd_cryptobox_keypair_sk (kp, &len);
  599. str = ucl_object_tolstring (privkey, &ucl_len);
  600. if (is_hex) {
  601. dec_len = rspamd_decode_hex_buf (str, ucl_len, target, len);
  602. }
  603. else {
  604. dec_len = rspamd_decode_base32_buf (str, ucl_len, target, len, RSPAMD_BASE32_DEFAULT);
  605. }
  606. if (dec_len != (gint)len) {
  607. rspamd_keypair_unref (kp);
  608. return NULL;
  609. }
  610. target = rspamd_cryptobox_keypair_pk (kp, &len);
  611. str = ucl_object_tolstring (pubkey, &ucl_len);
  612. if (is_hex) {
  613. dec_len = rspamd_decode_hex_buf (str, ucl_len, target, len);
  614. }
  615. else {
  616. dec_len = rspamd_decode_base32_buf (str, ucl_len, target, len, RSPAMD_BASE32_DEFAULT);
  617. }
  618. if (dec_len != (gint)len) {
  619. rspamd_keypair_unref (kp);
  620. return NULL;
  621. }
  622. rspamd_cryptobox_hash (kp->id, target, len, NULL, 0);
  623. return kp;
  624. }
  625. ucl_object_t *
  626. rspamd_keypair_to_ucl (struct rspamd_cryptobox_keypair *kp,
  627. gboolean is_hex)
  628. {
  629. ucl_object_t *ucl_out, *elt;
  630. gint how = 0;
  631. GString *keypair_out;
  632. const gchar *encoding;
  633. g_assert (kp != NULL);
  634. if (is_hex) {
  635. how |= RSPAMD_KEYPAIR_HEX;
  636. encoding = "hex";
  637. }
  638. else {
  639. how |= RSPAMD_KEYPAIR_BASE32;
  640. encoding = "base32";
  641. }
  642. ucl_out = ucl_object_typed_new (UCL_OBJECT);
  643. elt = ucl_object_typed_new (UCL_OBJECT);
  644. ucl_object_insert_key (ucl_out, elt, "keypair", 0, false);
  645. /* pubkey part */
  646. keypair_out = rspamd_keypair_print (kp,
  647. RSPAMD_KEYPAIR_PUBKEY|how);
  648. ucl_object_insert_key (elt,
  649. ucl_object_fromlstring (keypair_out->str, keypair_out->len),
  650. "pubkey", 0, false);
  651. g_string_free (keypair_out, TRUE);
  652. /* privkey part */
  653. keypair_out = rspamd_keypair_print (kp,
  654. RSPAMD_KEYPAIR_PRIVKEY|how);
  655. ucl_object_insert_key (elt,
  656. ucl_object_fromlstring (keypair_out->str, keypair_out->len),
  657. "privkey", 0, false);
  658. g_string_free (keypair_out, TRUE);
  659. keypair_out = rspamd_keypair_print (kp,
  660. RSPAMD_KEYPAIR_ID|how);
  661. ucl_object_insert_key (elt,
  662. ucl_object_fromlstring (keypair_out->str, keypair_out->len),
  663. "id", 0, false);
  664. g_string_free (keypair_out, TRUE);
  665. ucl_object_insert_key (elt,
  666. ucl_object_fromstring (encoding),
  667. "encoding", 0, false);
  668. ucl_object_insert_key (elt,
  669. ucl_object_fromstring (
  670. kp->alg == RSPAMD_CRYPTOBOX_MODE_NIST ?
  671. "nistp256" : "curve25519"),
  672. "algorithm", 0, false);
  673. ucl_object_insert_key (elt,
  674. ucl_object_fromstring (
  675. kp->type == RSPAMD_KEYPAIR_KEX ?
  676. "kex" : "sign"),
  677. "type", 0, false);
  678. return ucl_out;
  679. }
  680. gboolean
  681. rspamd_keypair_sign (struct rspamd_cryptobox_keypair *kp,
  682. const void *data, gsize len, guchar **sig, gsize *outlen,
  683. GError **err)
  684. {
  685. unsigned long long siglen;
  686. guint sklen;
  687. g_assert (kp != NULL);
  688. g_assert (data != NULL);
  689. g_assert (sig != NULL);
  690. if (kp->type != RSPAMD_KEYPAIR_SIGN) {
  691. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  692. "invalid keypair: expected signature pair");
  693. return FALSE;
  694. }
  695. siglen = rspamd_cryptobox_signature_bytes (kp->alg);
  696. *sig = g_malloc (siglen);
  697. rspamd_cryptobox_sign (*sig, &siglen, data, len,
  698. rspamd_cryptobox_keypair_sk (kp, &sklen), kp->alg);
  699. if (outlen != NULL) {
  700. *outlen = siglen;
  701. }
  702. return TRUE;
  703. }
  704. gboolean
  705. rspamd_keypair_verify (struct rspamd_cryptobox_pubkey *pk,
  706. const void *data, gsize len, const guchar *sig, gsize siglen,
  707. GError **err)
  708. {
  709. guint pklen;
  710. g_assert (pk != NULL);
  711. g_assert (data != NULL);
  712. g_assert (sig != NULL);
  713. if (pk->type != RSPAMD_KEYPAIR_SIGN) {
  714. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  715. "invalid keypair: expected signature pair");
  716. return FALSE;
  717. }
  718. if (siglen != rspamd_cryptobox_signature_bytes (pk->alg)) {
  719. g_set_error (err, rspamd_keypair_quark (), E2BIG,
  720. "invalid signature length: %d; expected %d",
  721. (int)siglen, (int) rspamd_cryptobox_signature_bytes (pk->alg));
  722. return FALSE;
  723. }
  724. if (!rspamd_cryptobox_verify (sig, siglen, data, len,
  725. rspamd_cryptobox_pubkey_pk (pk, &pklen), pk->alg)) {
  726. g_set_error (err, rspamd_keypair_quark (), EPERM,
  727. "signature verification failed");
  728. return FALSE;
  729. }
  730. return TRUE;
  731. }
  732. gboolean
  733. rspamd_pubkey_equal (const struct rspamd_cryptobox_pubkey *k1,
  734. const struct rspamd_cryptobox_pubkey *k2)
  735. {
  736. guchar *p1 = NULL, *p2 = NULL;
  737. guint len1, len2;
  738. if (k1->alg == k2->alg && k1->type == k2->type) {
  739. p1 = rspamd_cryptobox_pubkey_pk (k1, &len1);
  740. p2 = rspamd_cryptobox_pubkey_pk (k2, &len2);
  741. if (len1 == len2) {
  742. return (memcmp (p1, p2, len1) == 0);
  743. }
  744. }
  745. return FALSE;
  746. }
  747. gboolean
  748. rspamd_keypair_decrypt (struct rspamd_cryptobox_keypair *kp,
  749. const guchar *in, gsize inlen,
  750. guchar **out, gsize *outlen,
  751. GError **err)
  752. {
  753. const guchar *nonce, *mac, *data, *pubkey;
  754. g_assert (kp != NULL);
  755. g_assert (in != NULL);
  756. if (kp->type != RSPAMD_KEYPAIR_KEX) {
  757. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  758. "invalid keypair type");
  759. return FALSE;
  760. }
  761. if (inlen < sizeof (encrypted_magic) + rspamd_cryptobox_pk_bytes (kp->alg) +
  762. rspamd_cryptobox_mac_bytes (kp->alg) +
  763. rspamd_cryptobox_nonce_bytes (kp->alg)) {
  764. g_set_error (err, rspamd_keypair_quark (), E2BIG, "invalid size: too small");
  765. return FALSE;
  766. }
  767. if (memcmp (in, encrypted_magic, sizeof (encrypted_magic)) != 0) {
  768. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  769. "invalid magic");
  770. return FALSE;
  771. }
  772. /* Set pointers */
  773. pubkey = in + sizeof (encrypted_magic);
  774. mac = pubkey + rspamd_cryptobox_pk_bytes (kp->alg);
  775. nonce = mac + rspamd_cryptobox_mac_bytes (kp->alg);
  776. data = nonce + rspamd_cryptobox_nonce_bytes (kp->alg);
  777. if (data - in >= inlen) {
  778. g_set_error (err, rspamd_keypair_quark (), E2BIG, "invalid size: too small");
  779. return FALSE;
  780. }
  781. inlen -= data - in;
  782. /* Allocate memory for output */
  783. *out = g_malloc (inlen);
  784. memcpy (*out, data, inlen);
  785. if (!rspamd_cryptobox_decrypt_inplace (*out, inlen, nonce, pubkey,
  786. rspamd_keypair_component (kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
  787. mac, kp->alg)) {
  788. g_set_error (err, rspamd_keypair_quark (), EPERM, "verification failed");
  789. g_free (*out);
  790. return FALSE;
  791. }
  792. if (outlen) {
  793. *outlen = inlen;
  794. }
  795. return TRUE;
  796. }
  797. gboolean
  798. rspamd_keypair_encrypt (struct rspamd_cryptobox_keypair *kp,
  799. const guchar *in, gsize inlen,
  800. guchar **out, gsize *outlen,
  801. GError **err)
  802. {
  803. guchar *nonce, *mac, *data, *pubkey;
  804. struct rspamd_cryptobox_keypair *local;
  805. gsize olen;
  806. g_assert (kp != NULL);
  807. g_assert (in != NULL);
  808. if (kp->type != RSPAMD_KEYPAIR_KEX) {
  809. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  810. "invalid keypair type");
  811. return FALSE;
  812. }
  813. local = rspamd_keypair_new (kp->type, kp->alg);
  814. olen = inlen + sizeof (encrypted_magic) +
  815. rspamd_cryptobox_pk_bytes (kp->alg) +
  816. rspamd_cryptobox_mac_bytes (kp->alg) +
  817. rspamd_cryptobox_nonce_bytes (kp->alg);
  818. *out = g_malloc (olen);
  819. memcpy (*out, encrypted_magic, sizeof (encrypted_magic));
  820. pubkey = *out + sizeof (encrypted_magic);
  821. mac = pubkey + rspamd_cryptobox_pk_bytes (kp->alg);
  822. nonce = mac + rspamd_cryptobox_mac_bytes (kp->alg);
  823. data = nonce + rspamd_cryptobox_nonce_bytes (kp->alg);
  824. ottery_rand_bytes (nonce, rspamd_cryptobox_nonce_bytes (kp->alg));
  825. memcpy (data, in, inlen);
  826. memcpy (pubkey, rspamd_keypair_component (kp,
  827. RSPAMD_KEYPAIR_COMPONENT_PK, NULL),
  828. rspamd_cryptobox_pk_bytes (kp->alg));
  829. rspamd_cryptobox_encrypt_inplace (data, inlen, nonce, pubkey,
  830. rspamd_keypair_component (local, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
  831. mac, kp->alg);
  832. rspamd_keypair_unref (local);
  833. if (outlen) {
  834. *outlen = olen;
  835. }
  836. return TRUE;
  837. }
  838. gboolean
  839. rspamd_pubkey_encrypt (struct rspamd_cryptobox_pubkey *pk,
  840. const guchar *in, gsize inlen,
  841. guchar **out, gsize *outlen,
  842. GError **err)
  843. {
  844. guchar *nonce, *mac, *data, *pubkey;
  845. struct rspamd_cryptobox_keypair *local;
  846. gsize olen;
  847. g_assert (pk != NULL);
  848. g_assert (in != NULL);
  849. if (pk->type != RSPAMD_KEYPAIR_KEX) {
  850. g_set_error (err, rspamd_keypair_quark (), EINVAL,
  851. "invalid pubkey type");
  852. return FALSE;
  853. }
  854. local = rspamd_keypair_new (pk->type, pk->alg);
  855. olen = inlen + sizeof (encrypted_magic) +
  856. rspamd_cryptobox_pk_bytes (pk->alg) +
  857. rspamd_cryptobox_mac_bytes (pk->alg) +
  858. rspamd_cryptobox_nonce_bytes (pk->alg);
  859. *out = g_malloc (olen);
  860. memcpy (*out, encrypted_magic, sizeof (encrypted_magic));
  861. pubkey = *out + sizeof (encrypted_magic);
  862. mac = pubkey + rspamd_cryptobox_pk_bytes (pk->alg);
  863. nonce = mac + rspamd_cryptobox_mac_bytes (pk->alg);
  864. data = nonce + rspamd_cryptobox_nonce_bytes (pk->alg);
  865. ottery_rand_bytes (nonce, rspamd_cryptobox_nonce_bytes (pk->alg));
  866. memcpy (data, in, inlen);
  867. memcpy (pubkey, rspamd_pubkey_get_pk (pk, NULL),
  868. rspamd_cryptobox_pk_bytes (pk->alg));
  869. rspamd_cryptobox_encrypt_inplace (data, inlen, nonce, pubkey,
  870. rspamd_keypair_component (local, RSPAMD_KEYPAIR_COMPONENT_SK, NULL),
  871. mac, pk->alg);
  872. rspamd_keypair_unref (local);
  873. if (outlen) {
  874. *outlen = olen;
  875. }
  876. return TRUE;
  877. }