1 /*-
2 * Copyright (c) 2017-2021, Ribose Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
18 * CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "crypto.h"
29 #include "crypto/common.h"
30 #include "pgp-key.h"
31 #include "defaults.h"
32 #include <assert.h>
33 #include <json_object.h>
34 #include <json.h>
35 #include <librekey/key_store_pgp.h>
36 #include <librepgp/stream-ctx.h>
37 #include <librepgp/stream-common.h>
38 #include <librepgp/stream-armor.h>
39 #include <librepgp/stream-parse.h>
40 #include <librepgp/stream-write.h>
41 #include <librepgp/stream-sig.h>
42 #include <librepgp/stream-packet.h>
43 #include <librepgp/stream-key.h>
44 #include <librepgp/stream-dump.h>
45 #include <rnp/rnp.h>
46 #include <stdarg.h>
47 #include <stdlib.h>
48 #ifdef _MSC_VER
49 #include "uniwin.h"
50 #include <inttypes.h>
51 #else
52 #include <unistd.h>
53 #endif
54 #include <string.h>
55 #include <sys/stat.h>
56 #include <stdexcept>
57 #include "utils.h"
58 #include "str-utils.h"
59 #include "json-utils.h"
60 #include "version.h"
61 #include "ffi-priv-types.h"
62 #include "file-utils.h"
63
64 #define FFI_LOG(ffi, ...) \
65 do { \
66 FILE *fp = stderr; \
67 if (ffi && ffi->errs) { \
68 fp = ffi->errs; \
69 } \
70 RNP_LOG_FD(fp, __VA_ARGS__); \
71 } while (0)
72
73 static pgp_key_t *get_key_require_public(rnp_key_handle_t handle);
74 static pgp_key_t *get_key_prefer_public(rnp_key_handle_t handle);
75 static pgp_key_t *get_key_require_secret(rnp_key_handle_t handle);
76
77 static bool locator_to_str(const pgp_key_search_t *locator,
78 const char ** identifier_type,
79 char * identifier,
80 size_t identifier_size);
81
82 static bool rnp_password_cb_bounce(const pgp_password_ctx_t *ctx,
83 char * password,
84 size_t password_size,
85 void * userdata_void);
86
87 static rnp_result_t rnp_dump_src_to_json(pgp_source_t *src, uint32_t flags, char **result);
88
89 static pgp_key_t *
find_key(rnp_ffi_t ffi,const pgp_key_search_t * search,key_type_t key_type,bool try_key_provider)90 find_key(rnp_ffi_t ffi,
91 const pgp_key_search_t *search,
92 key_type_t key_type,
93 bool try_key_provider)
94 {
95 pgp_key_t *key = NULL;
96
97 switch (key_type) {
98 case KEY_TYPE_PUBLIC:
99 key = rnp_key_store_search(ffi->pubring, search, NULL);
100 break;
101 case KEY_TYPE_SECRET:
102 key = rnp_key_store_search(ffi->secring, search, NULL);
103 break;
104 default:
105 assert(false);
106 break;
107 }
108 if (!key && ffi->getkeycb && try_key_provider) {
109 char identifier[RNP_LOCATOR_MAX_SIZE];
110 const char *identifier_type = NULL;
111
112 if (locator_to_str(search, &identifier_type, identifier, sizeof(identifier))) {
113 ffi->getkeycb(ffi,
114 ffi->getkeycb_ctx,
115 identifier_type,
116 identifier,
117 key_type == KEY_TYPE_SECRET);
118 // recurse and try the store search above once more
119 return find_key(ffi, search, key_type, false);
120 }
121 }
122 return key;
123 }
124
125 static pgp_key_t *
ffi_key_provider(const pgp_key_request_ctx_t * ctx,void * userdata)126 ffi_key_provider(const pgp_key_request_ctx_t *ctx, void *userdata)
127 {
128 rnp_ffi_t ffi = (rnp_ffi_t) userdata;
129 return find_key(ffi, &ctx->search, ctx->secret ? KEY_TYPE_SECRET : KEY_TYPE_PUBLIC, true);
130 }
131
132 static void
rnp_ctx_init_ffi(rnp_ctx_t & ctx,rnp_ffi_t ffi)133 rnp_ctx_init_ffi(rnp_ctx_t &ctx, rnp_ffi_t ffi)
134 {
135 ctx.ctx = &ffi->context;
136 ctx.ealg = DEFAULT_PGP_SYMM_ALG;
137 }
138
139 static const id_str_pair sig_type_map[] = {{PGP_SIG_BINARY, "binary"},
140 {PGP_SIG_TEXT, "text"},
141 {PGP_SIG_STANDALONE, "standalone"},
142 {PGP_CERT_GENERIC, "certification (generic)"},
143 {PGP_CERT_PERSONA, "certification (persona)"},
144 {PGP_CERT_CASUAL, "certification (casual)"},
145 {PGP_CERT_POSITIVE, "certification (positive)"},
146 {PGP_SIG_SUBKEY, "subkey binding"},
147 {PGP_SIG_PRIMARY, "primary key binding"},
148 {PGP_SIG_DIRECT, "direct"},
149 {PGP_SIG_REV_KEY, "key revocation"},
150 {PGP_SIG_REV_SUBKEY, "subkey revocation"},
151 {PGP_SIG_REV_CERT, "certification revocation"},
152 {PGP_SIG_TIMESTAMP, "timestamp"},
153 {PGP_SIG_3RD_PARTY, "third-party"},
154 {0, NULL}};
155
156 static const id_str_pair pubkey_alg_map[] = {
157 {PGP_PKA_RSA, RNP_ALGNAME_RSA},
158 {PGP_PKA_RSA_ENCRYPT_ONLY, RNP_ALGNAME_RSA},
159 {PGP_PKA_RSA_SIGN_ONLY, RNP_ALGNAME_RSA},
160 {PGP_PKA_ELGAMAL, RNP_ALGNAME_ELGAMAL},
161 {PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN, RNP_ALGNAME_ELGAMAL},
162 {PGP_PKA_DSA, RNP_ALGNAME_DSA},
163 {PGP_PKA_ECDH, RNP_ALGNAME_ECDH},
164 {PGP_PKA_ECDSA, RNP_ALGNAME_ECDSA},
165 {PGP_PKA_EDDSA, RNP_ALGNAME_EDDSA},
166 {PGP_PKA_SM2, RNP_ALGNAME_SM2},
167 {0, NULL}};
168
169 static const id_str_pair symm_alg_map[] = {{PGP_SA_IDEA, RNP_ALGNAME_IDEA},
170 {PGP_SA_TRIPLEDES, RNP_ALGNAME_TRIPLEDES},
171 {PGP_SA_CAST5, RNP_ALGNAME_CAST5},
172 {PGP_SA_BLOWFISH, RNP_ALGNAME_BLOWFISH},
173 {PGP_SA_AES_128, RNP_ALGNAME_AES_128},
174 {PGP_SA_AES_192, RNP_ALGNAME_AES_192},
175 {PGP_SA_AES_256, RNP_ALGNAME_AES_256},
176 {PGP_SA_TWOFISH, RNP_ALGNAME_TWOFISH},
177 {PGP_SA_CAMELLIA_128, RNP_ALGNAME_CAMELLIA_128},
178 {PGP_SA_CAMELLIA_192, RNP_ALGNAME_CAMELLIA_192},
179 {PGP_SA_CAMELLIA_256, RNP_ALGNAME_CAMELLIA_256},
180 {PGP_SA_SM4, RNP_ALGNAME_SM4},
181 {0, NULL}};
182
183 static const id_str_pair aead_alg_map[] = {
184 {PGP_AEAD_NONE, "None"}, {PGP_AEAD_EAX, "EAX"}, {PGP_AEAD_OCB, "OCB"}, {0, NULL}};
185
186 static const id_str_pair cipher_mode_map[] = {{PGP_CIPHER_MODE_CFB, "CFB"},
187 {PGP_CIPHER_MODE_CBC, "CBC"},
188 {PGP_CIPHER_MODE_OCB, "OCB"},
189 {0, NULL}};
190
191 static const id_str_pair compress_alg_map[] = {{PGP_C_NONE, "Uncompressed"},
192 {PGP_C_ZIP, "ZIP"},
193 {PGP_C_ZLIB, "ZLIB"},
194 {PGP_C_BZIP2, "BZip2"},
195 {0, NULL}};
196
197 static const id_str_pair hash_alg_map[] = {{PGP_HASH_MD5, RNP_ALGNAME_MD5},
198 {PGP_HASH_SHA1, RNP_ALGNAME_SHA1},
199 {PGP_HASH_RIPEMD, RNP_ALGNAME_RIPEMD160},
200 {PGP_HASH_SHA256, RNP_ALGNAME_SHA256},
201 {PGP_HASH_SHA384, RNP_ALGNAME_SHA384},
202 {PGP_HASH_SHA512, RNP_ALGNAME_SHA512},
203 {PGP_HASH_SHA224, RNP_ALGNAME_SHA224},
204 {PGP_HASH_SHA3_256, RNP_ALGNAME_SHA3_256},
205 {PGP_HASH_SHA3_512, RNP_ALGNAME_SHA3_512},
206 {PGP_HASH_SM3, RNP_ALGNAME_SM3},
207 {0, NULL}};
208
209 static const id_str_pair s2k_type_map[] = {
210 {PGP_S2KS_SIMPLE, "Simple"},
211 {PGP_S2KS_SALTED, "Salted"},
212 {PGP_S2KS_ITERATED_AND_SALTED, "Iterated and salted"},
213 {0, NULL}};
214
215 static const id_str_pair key_usage_map[] = {
216 {PGP_KF_SIGN, "sign"},
217 {PGP_KF_CERTIFY, "certify"},
218 {PGP_KF_ENCRYPT, "encrypt"},
219 {PGP_KF_AUTH, "authenticate"},
220 {0, NULL},
221 };
222
223 static const id_str_pair key_flags_map[] = {
224 {PGP_KF_SPLIT, "split"},
225 {PGP_KF_SHARED, "shared"},
226 {0, NULL},
227 };
228
229 static const id_str_pair identifier_type_map[] = {{PGP_KEY_SEARCH_USERID, "userid"},
230 {PGP_KEY_SEARCH_KEYID, "keyid"},
231 {PGP_KEY_SEARCH_FINGERPRINT, "fingerprint"},
232 {PGP_KEY_SEARCH_GRIP, "grip"},
233 {0, NULL}};
234
235 static const id_str_pair key_server_prefs_map[] = {{PGP_KEY_SERVER_NO_MODIFY, "no-modify"},
236 {0, NULL}};
237
238 static const id_str_pair armor_type_map[] = {{PGP_ARMORED_MESSAGE, "message"},
239 {PGP_ARMORED_PUBLIC_KEY, "public key"},
240 {PGP_ARMORED_SECRET_KEY, "secret key"},
241 {PGP_ARMORED_SIGNATURE, "signature"},
242 {PGP_ARMORED_CLEARTEXT, "cleartext"},
243 {0, NULL}};
244
245 static const id_str_pair key_import_status_map[] = {
246 {PGP_KEY_IMPORT_STATUS_UNKNOWN, "unknown"},
247 {PGP_KEY_IMPORT_STATUS_UNCHANGED, "unchanged"},
248 {PGP_KEY_IMPORT_STATUS_UPDATED, "updated"},
249 {PGP_KEY_IMPORT_STATUS_NEW, "new"},
250 {0, NULL}};
251
252 static const id_str_pair sig_import_status_map[] = {
253 {PGP_SIG_IMPORT_STATUS_UNKNOWN, "unknown"},
254 {PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY, "unknown key"},
255 {PGP_SIG_IMPORT_STATUS_UNCHANGED, "unchanged"},
256 {PGP_SIG_IMPORT_STATUS_NEW, "new"},
257 {0, NULL}};
258
259 static const id_str_pair revocation_code_map[] = {
260 {PGP_REVOCATION_NO_REASON, "no"},
261 {PGP_REVOCATION_SUPERSEDED, "superseded"},
262 {PGP_REVOCATION_COMPROMISED, "compromised"},
263 {PGP_REVOCATION_RETIRED, "retired"},
264 {PGP_REVOCATION_NO_LONGER_VALID, "no longer valid"},
265 {0, NULL}};
266
267 static bool
curve_str_to_type(const char * str,pgp_curve_t * value)268 curve_str_to_type(const char *str, pgp_curve_t *value)
269 {
270 *value = find_curve_by_name(str);
271 return curve_supported(*value);
272 }
273
274 static bool
curve_type_to_str(pgp_curve_t type,const char ** str)275 curve_type_to_str(pgp_curve_t type, const char **str)
276 {
277 const ec_curve_desc_t *desc = get_curve_desc(type);
278 if (!desc) {
279 return false;
280 }
281 *str = desc->pgp_name;
282 return true;
283 }
284
285 static bool
str_to_cipher(const char * str,pgp_symm_alg_t * cipher)286 str_to_cipher(const char *str, pgp_symm_alg_t *cipher)
287 {
288 auto alg =
289 static_cast<pgp_symm_alg_t>(id_str_pair::lookup(symm_alg_map, str, PGP_SA_UNKNOWN));
290 if (alg == PGP_SA_UNKNOWN) {
291 return false;
292 }
293 #if !defined(ENABLE_SM2)
294 if (alg == PGP_SA_SM4) {
295 return false;
296 }
297 #endif
298 #if !defined(ENABLE_TWOFISH)
299 if (alg == PGP_SA_TWOFISH) {
300 return false;
301 }
302 #endif
303 *cipher = alg;
304 return true;
305 }
306
307 static bool
str_to_hash_alg(const char * str,pgp_hash_alg_t * hash_alg)308 str_to_hash_alg(const char *str, pgp_hash_alg_t *hash_alg)
309 {
310 auto alg =
311 static_cast<pgp_hash_alg_t>(id_str_pair::lookup(hash_alg_map, str, PGP_HASH_UNKNOWN));
312 if (alg == PGP_HASH_UNKNOWN) {
313 return false;
314 }
315 #if !defined(ENABLE_SM2)
316 if (alg == PGP_HASH_SM3) {
317 return false;
318 }
319 #endif
320 *hash_alg = alg;
321 return true;
322 }
323
324 static bool
str_to_aead_alg(const char * str,pgp_aead_alg_t * aead_alg)325 str_to_aead_alg(const char *str, pgp_aead_alg_t *aead_alg)
326 {
327 pgp_aead_alg_t alg =
328 static_cast<pgp_aead_alg_t>(id_str_pair::lookup(aead_alg_map, str, PGP_AEAD_UNKNOWN));
329 if (alg == PGP_AEAD_UNKNOWN) {
330 return false;
331 }
332 #if !defined(ENABLE_AEAD)
333 if (alg != PGP_AEAD_NONE) {
334 return false;
335 }
336 #endif
337 *aead_alg = alg;
338 return true;
339 }
340
341 static bool
str_to_compression_alg(const char * str,pgp_compression_type_t * zalg)342 str_to_compression_alg(const char *str, pgp_compression_type_t *zalg)
343 {
344 pgp_compression_type_t alg = static_cast<pgp_compression_type_t>(
345 id_str_pair::lookup(compress_alg_map, str, PGP_C_UNKNOWN));
346 if (alg == PGP_C_UNKNOWN) {
347 return false;
348 }
349 *zalg = alg;
350 return true;
351 }
352
353 static bool
str_to_revocation_type(const char * str,pgp_revocation_type_t * code)354 str_to_revocation_type(const char *str, pgp_revocation_type_t *code)
355 {
356 pgp_revocation_type_t rev = static_cast<pgp_revocation_type_t>(
357 id_str_pair::lookup(revocation_code_map, str, PGP_REVOCATION_NO_REASON));
358 if ((rev == PGP_REVOCATION_NO_REASON) && !rnp::str_case_eq(str, "no")) {
359 return false;
360 }
361 *code = rev;
362 return true;
363 }
364
365 static bool
str_to_cipher_mode(const char * str,pgp_cipher_mode_t * mode)366 str_to_cipher_mode(const char *str, pgp_cipher_mode_t *mode)
367 {
368 pgp_cipher_mode_t c_mode = static_cast<pgp_cipher_mode_t>(
369 id_str_pair::lookup(cipher_mode_map, str, PGP_CIPHER_MODE_NONE));
370 if (c_mode == PGP_CIPHER_MODE_NONE) {
371 return false;
372 }
373
374 *mode = c_mode;
375 return true;
376 }
377
378 static bool
str_to_pubkey_alg(const char * str,pgp_pubkey_alg_t * pub_alg)379 str_to_pubkey_alg(const char *str, pgp_pubkey_alg_t *pub_alg)
380 {
381 pgp_pubkey_alg_t alg =
382 static_cast<pgp_pubkey_alg_t>(id_str_pair::lookup(pubkey_alg_map, str, PGP_PKA_NOTHING));
383 if (alg == PGP_PKA_NOTHING) {
384 return false;
385 }
386 #if !defined(ENABLE_SM2)
387 if (alg == PGP_PKA_SM2) {
388 return false;
389 }
390 #endif
391 *pub_alg = alg;
392 return true;
393 }
394
395 static bool
str_to_key_flag(const char * str,uint8_t * flag)396 str_to_key_flag(const char *str, uint8_t *flag)
397 {
398 uint8_t _flag = id_str_pair::lookup(key_usage_map, str);
399 if (!_flag) {
400 return false;
401 }
402 *flag = _flag;
403 return true;
404 }
405
406 static bool
parse_ks_format(pgp_key_store_format_t * key_store_format,const char * format)407 parse_ks_format(pgp_key_store_format_t *key_store_format, const char *format)
408 {
409 if (!strcmp(format, RNP_KEYSTORE_GPG)) {
410 *key_store_format = PGP_KEY_STORE_GPG;
411 } else if (!strcmp(format, RNP_KEYSTORE_KBX)) {
412 *key_store_format = PGP_KEY_STORE_KBX;
413 } else if (!strcmp(format, RNP_KEYSTORE_G10)) {
414 *key_store_format = PGP_KEY_STORE_G10;
415 } else {
416 return false;
417 }
418 return true;
419 }
420
421 static rnp_result_t
hex_encode_value(const uint8_t * value,size_t len,char ** res,rnp::hex_format_t format=rnp::HEX_UPPERCASE)422 hex_encode_value(const uint8_t * value,
423 size_t len,
424 char ** res,
425 rnp::hex_format_t format = rnp::HEX_UPPERCASE)
426 {
427 size_t hex_len = len * 2 + 1;
428 *res = (char *) malloc(hex_len);
429 if (!*res) {
430 return RNP_ERROR_OUT_OF_MEMORY;
431 }
432 if (!rnp::hex_encode(value, len, *res, hex_len, format)) {
433 free(*res);
434 *res = NULL;
435 return RNP_ERROR_GENERIC;
436 }
437 return RNP_SUCCESS;
438 }
439
440 static rnp_result_t
get_map_value(const id_str_pair * map,int val,char ** res)441 get_map_value(const id_str_pair *map, int val, char **res)
442 {
443 const char *str = id_str_pair::lookup(map, val, NULL);
444 if (!str) {
445 return RNP_ERROR_BAD_PARAMETERS;
446 }
447 char *strcp = strdup(str);
448 if (!strcp) {
449 return RNP_ERROR_OUT_OF_MEMORY;
450 }
451 *res = strcp;
452 return RNP_SUCCESS;
453 }
454
455 static rnp_result_t
ret_str_value(const char * str,char ** res)456 ret_str_value(const char *str, char **res)
457 {
458 if (!str) {
459 return RNP_ERROR_BAD_PARAMETERS;
460 }
461 char *strcp = strdup(str);
462 if (!strcp) {
463 return RNP_ERROR_OUT_OF_MEMORY;
464 }
465 *res = strcp;
466 return RNP_SUCCESS;
467 }
468
469 static uint32_t
ffi_exception(FILE * fp,const char * func,const char * msg,uint32_t ret=RNP_ERROR_GENERIC)470 ffi_exception(FILE *fp, const char *func, const char *msg, uint32_t ret = RNP_ERROR_GENERIC)
471 {
472 if (rnp_log_switch()) {
473 fprintf(
474 fp, "[%s()] Error 0x%08X (%s): %s\n", func, ret, rnp_result_to_string(ret), msg);
475 }
476 return ret;
477 }
478
479 #define FFI_GUARD_FP(fp) \
480 catch (rnp::rnp_exception & e) \
481 { \
482 return ffi_exception((fp), __func__, e.what(), e.code()); \
483 } \
484 catch (std::bad_alloc &) \
485 { \
486 return ffi_exception((fp), __func__, "bad_alloc", RNP_ERROR_OUT_OF_MEMORY); \
487 } \
488 catch (std::exception & e) \
489 { \
490 return ffi_exception((fp), __func__, e.what()); \
491 } \
492 catch (...) \
493 { \
494 return ffi_exception((fp), __func__, "unknown exception"); \
495 }
496
497 #define FFI_GUARD FFI_GUARD_FP((stderr))
498
rnp_ffi_st(pgp_key_store_format_t pub_fmt,pgp_key_store_format_t sec_fmt)499 rnp_ffi_st::rnp_ffi_st(pgp_key_store_format_t pub_fmt, pgp_key_store_format_t sec_fmt)
500 {
501 errs = stderr;
502 pubring = new rnp_key_store_t(pub_fmt, "", context);
503 secring = new rnp_key_store_t(sec_fmt, "", context);
504 getkeycb = NULL;
505 getkeycb_ctx = NULL;
506 getpasscb = NULL;
507 getpasscb_ctx = NULL;
508 key_provider.callback = ffi_key_provider;
509 key_provider.userdata = this;
510 pass_provider.callback = rnp_password_cb_bounce;
511 pass_provider.userdata = this;
512 }
513
514 rnp::RNG &
rng()515 rnp_ffi_st::rng() noexcept
516 {
517 return context.rng;
518 }
519
520 rnp::SecurityProfile &
profile()521 rnp_ffi_st::profile() noexcept
522 {
523 return context.profile;
524 }
525
526 rnp_result_t
rnp_ffi_create(rnp_ffi_t * ffi,const char * pub_format,const char * sec_format)527 rnp_ffi_create(rnp_ffi_t *ffi, const char *pub_format, const char *sec_format)
528 try {
529 // checks
530 if (!ffi || !pub_format || !sec_format) {
531 return RNP_ERROR_NULL_POINTER;
532 }
533
534 pgp_key_store_format_t pub_ks_format = PGP_KEY_STORE_UNKNOWN;
535 pgp_key_store_format_t sec_ks_format = PGP_KEY_STORE_UNKNOWN;
536 if (!parse_ks_format(&pub_ks_format, pub_format) ||
537 !parse_ks_format(&sec_ks_format, sec_format)) {
538 return RNP_ERROR_BAD_PARAMETERS;
539 }
540
541 struct rnp_ffi_st *ob = new rnp_ffi_st(pub_ks_format, sec_ks_format);
542 *ffi = ob;
543 return RNP_SUCCESS;
544 }
545 FFI_GUARD
546
547 static bool
is_std_file(FILE * fp)548 is_std_file(FILE *fp)
549 {
550 return fp == stdout || fp == stderr;
551 }
552
553 static void
close_io_file(FILE ** fp)554 close_io_file(FILE **fp)
555 {
556 if (*fp && !is_std_file(*fp)) {
557 fclose(*fp);
558 }
559 *fp = NULL;
560 }
561
~rnp_ffi_st()562 rnp_ffi_st::~rnp_ffi_st()
563 {
564 close_io_file(&errs);
565 delete pubring;
566 delete secring;
567 }
568
569 rnp_result_t
rnp_ffi_destroy(rnp_ffi_t ffi)570 rnp_ffi_destroy(rnp_ffi_t ffi)
571 try {
572 if (ffi) {
573 delete ffi;
574 }
575 return RNP_SUCCESS;
576 }
577 FFI_GUARD
578
579 rnp_result_t
rnp_ffi_set_log_fd(rnp_ffi_t ffi,int fd)580 rnp_ffi_set_log_fd(rnp_ffi_t ffi, int fd)
581 try {
582 // checks
583 if (!ffi) {
584 return RNP_ERROR_NULL_POINTER;
585 }
586
587 // open
588 FILE *errs = fdopen(fd, "a");
589 if (!errs) {
590 return RNP_ERROR_ACCESS;
591 }
592 // close previous streams and replace them
593 close_io_file(&ffi->errs);
594 ffi->errs = errs;
595 return RNP_SUCCESS;
596 }
597 FFI_GUARD
598
599 rnp_result_t
rnp_ffi_set_key_provider(rnp_ffi_t ffi,rnp_get_key_cb getkeycb,void * getkeycb_ctx)600 rnp_ffi_set_key_provider(rnp_ffi_t ffi, rnp_get_key_cb getkeycb, void *getkeycb_ctx)
601 try {
602 if (!ffi) {
603 return RNP_ERROR_NULL_POINTER;
604 }
605 ffi->getkeycb = getkeycb;
606 ffi->getkeycb_ctx = getkeycb_ctx;
607 return RNP_SUCCESS;
608 }
609 FFI_GUARD
610
611 rnp_result_t
rnp_ffi_set_pass_provider(rnp_ffi_t ffi,rnp_password_cb getpasscb,void * getpasscb_ctx)612 rnp_ffi_set_pass_provider(rnp_ffi_t ffi, rnp_password_cb getpasscb, void *getpasscb_ctx)
613 try {
614 if (!ffi) {
615 return RNP_ERROR_NULL_POINTER;
616 }
617 ffi->getpasscb = getpasscb;
618 ffi->getpasscb_ctx = getpasscb_ctx;
619 return RNP_SUCCESS;
620 }
621 FFI_GUARD
622
623 static const char *
operation_description(uint8_t op)624 operation_description(uint8_t op)
625 {
626 switch (op) {
627 case PGP_OP_ADD_SUBKEY:
628 return "add subkey";
629 case PGP_OP_ADD_USERID:
630 return "add userid";
631 case PGP_OP_SIGN:
632 return "sign";
633 case PGP_OP_DECRYPT:
634 return "decrypt";
635 case PGP_OP_UNLOCK:
636 return "unlock";
637 case PGP_OP_PROTECT:
638 return "protect";
639 case PGP_OP_UNPROTECT:
640 return "unprotect";
641 case PGP_OP_DECRYPT_SYM:
642 return "decrypt (symmetric)";
643 case PGP_OP_ENCRYPT_SYM:
644 return "encrypt (symmetric)";
645 default:
646 return "unknown";
647 }
648 }
649
650 static bool
rnp_password_cb_bounce(const pgp_password_ctx_t * ctx,char * password,size_t password_size,void * userdata_void)651 rnp_password_cb_bounce(const pgp_password_ctx_t *ctx,
652 char * password,
653 size_t password_size,
654 void * userdata_void)
655 {
656 rnp_ffi_t ffi = (rnp_ffi_t) userdata_void;
657
658 if (!ffi || !ffi->getpasscb) {
659 return false;
660 }
661
662 struct rnp_key_handle_st key = {};
663 key.ffi = ffi;
664 key.sec = (pgp_key_t *) ctx->key;
665 return ffi->getpasscb(ffi,
666 ffi->getpasscb_ctx,
667 ctx->key ? &key : NULL,
668 operation_description(ctx->op),
669 password,
670 password_size);
671 }
672
673 const char *
rnp_result_to_string(rnp_result_t result)674 rnp_result_to_string(rnp_result_t result)
675 {
676 switch (result) {
677 case RNP_SUCCESS:
678 return "Success";
679
680 case RNP_ERROR_GENERIC:
681 return "Unknown error";
682 case RNP_ERROR_BAD_FORMAT:
683 return "Bad format";
684 case RNP_ERROR_BAD_PARAMETERS:
685 return "Bad parameters";
686 case RNP_ERROR_NOT_IMPLEMENTED:
687 return "Not implemented";
688 case RNP_ERROR_NOT_SUPPORTED:
689 return "Not supported";
690 case RNP_ERROR_OUT_OF_MEMORY:
691 return "Out of memory";
692 case RNP_ERROR_SHORT_BUFFER:
693 return "Buffer too short";
694 case RNP_ERROR_NULL_POINTER:
695 return "Null pointer";
696
697 case RNP_ERROR_ACCESS:
698 return "Error accessing file";
699 case RNP_ERROR_READ:
700 return "Error reading file";
701 case RNP_ERROR_WRITE:
702 return "Error writing file";
703
704 case RNP_ERROR_BAD_STATE:
705 return "Bad state";
706 case RNP_ERROR_MAC_INVALID:
707 return "Invalid MAC";
708 case RNP_ERROR_SIGNATURE_INVALID:
709 return "Invalid signature";
710 case RNP_ERROR_KEY_GENERATION:
711 return "Error during key generation";
712 case RNP_ERROR_BAD_PASSWORD:
713 return "Bad password";
714 case RNP_ERROR_KEY_NOT_FOUND:
715 return "Key not found";
716 case RNP_ERROR_NO_SUITABLE_KEY:
717 return "No suitable key";
718 case RNP_ERROR_DECRYPT_FAILED:
719 return "Decryption failed";
720 case RNP_ERROR_NO_SIGNATURES_FOUND:
721 return "No signatures found cannot verify";
722
723 case RNP_ERROR_NOT_ENOUGH_DATA:
724 return "Not enough data";
725 case RNP_ERROR_UNKNOWN_TAG:
726 return "Unknown tag";
727 case RNP_ERROR_PACKET_NOT_CONSUMED:
728 return "Packet not consumed";
729 case RNP_ERROR_NO_USERID:
730 return "No userid";
731 case RNP_ERROR_EOF:
732 return "EOF detected";
733 }
734
735 return "Unknown error";
736 }
737
738 const char *
rnp_version_string()739 rnp_version_string()
740 {
741 return RNP_VERSION_STRING;
742 }
743
744 const char *
rnp_version_string_full()745 rnp_version_string_full()
746 {
747 return RNP_VERSION_STRING_FULL;
748 }
749
750 uint32_t
rnp_version()751 rnp_version()
752 {
753 return RNP_VERSION_CODE;
754 }
755
756 uint32_t
rnp_version_for(uint32_t major,uint32_t minor,uint32_t patch)757 rnp_version_for(uint32_t major, uint32_t minor, uint32_t patch)
758 {
759 if (major > RNP_VERSION_COMPONENT_MASK || minor > RNP_VERSION_COMPONENT_MASK ||
760 patch > RNP_VERSION_COMPONENT_MASK) {
761 RNP_LOG("invalid version, out of range: %d.%d.%d", major, minor, patch);
762 return 0;
763 }
764 return RNP_VERSION_CODE_FOR(major, minor, patch);
765 }
766
767 uint32_t
rnp_version_major(uint32_t version)768 rnp_version_major(uint32_t version)
769 {
770 return (version >> RNP_VERSION_MAJOR_SHIFT) & RNP_VERSION_COMPONENT_MASK;
771 }
772
773 uint32_t
rnp_version_minor(uint32_t version)774 rnp_version_minor(uint32_t version)
775 {
776 return (version >> RNP_VERSION_MINOR_SHIFT) & RNP_VERSION_COMPONENT_MASK;
777 }
778
779 uint32_t
rnp_version_patch(uint32_t version)780 rnp_version_patch(uint32_t version)
781 {
782 return (version >> RNP_VERSION_PATCH_SHIFT) & RNP_VERSION_COMPONENT_MASK;
783 }
784
785 uint64_t
rnp_version_commit_timestamp()786 rnp_version_commit_timestamp()
787 {
788 return RNP_VERSION_COMMIT_TIMESTAMP;
789 }
790
791 #ifndef RNP_NO_DEPRECATED
792 rnp_result_t
rnp_enable_debug(const char * file)793 rnp_enable_debug(const char *file)
794 try {
795 return RNP_SUCCESS;
796 }
797 FFI_GUARD
798 #endif
799
800 #ifndef RNP_NO_DEPRECATED
801 rnp_result_t
rnp_disable_debug()802 rnp_disable_debug()
803 try {
804 return RNP_SUCCESS;
805 }
806 FFI_GUARD
807 #endif
808
809 rnp_result_t
rnp_get_default_homedir(char ** homedir)810 rnp_get_default_homedir(char **homedir)
811 try {
812 // checks
813 if (!homedir) {
814 return RNP_ERROR_NULL_POINTER;
815 }
816
817 // get the users home dir
818 char *home = getenv("HOME");
819 if (!home) {
820 return RNP_ERROR_NOT_SUPPORTED;
821 }
822 if (!rnp_compose_path_ex(homedir, NULL, home, ".rnp", NULL)) {
823 return RNP_ERROR_OUT_OF_MEMORY;
824 }
825 return RNP_SUCCESS;
826 }
827 FFI_GUARD
828
829 rnp_result_t
rnp_detect_homedir_info(const char * homedir,char ** pub_format,char ** pub_path,char ** sec_format,char ** sec_path)830 rnp_detect_homedir_info(
831 const char *homedir, char **pub_format, char **pub_path, char **sec_format, char **sec_path)
832 try {
833 rnp_result_t ret = RNP_ERROR_GENERIC;
834 char * path = NULL;
835 size_t path_size = 0;
836
837 // checks
838 if (!homedir || !pub_format || !pub_path || !sec_format || !sec_path) {
839 return RNP_ERROR_NULL_POINTER;
840 }
841
842 // we only support the common cases of GPG+GPG or GPG+G10, we don't
843 // support unused combinations like KBX+KBX
844
845 *pub_format = NULL;
846 *pub_path = NULL;
847 *sec_format = NULL;
848 *sec_path = NULL;
849
850 const char *pub_format_guess = NULL;
851 const char *pub_path_guess = NULL;
852 const char *sec_format_guess = NULL;
853 const char *sec_path_guess = NULL;
854 // check for pubring.kbx file
855 if (!rnp_compose_path_ex(&path, &path_size, homedir, "pubring.kbx", NULL)) {
856 goto done;
857 }
858 if (rnp_file_exists(path)) {
859 // we have a pubring.kbx, now check for private-keys-v1.d dir
860 if (!rnp_compose_path_ex(&path, &path_size, homedir, "private-keys-v1.d", NULL)) {
861 goto done;
862 }
863 if (rnp_dir_exists(path)) {
864 pub_format_guess = "KBX";
865 pub_path_guess = "pubring.kbx";
866 sec_format_guess = "G10";
867 sec_path_guess = "private-keys-v1.d";
868 }
869 } else {
870 // check for pubring.gpg
871 if (!rnp_compose_path_ex(&path, &path_size, homedir, "pubring.gpg", NULL)) {
872 goto done;
873 }
874 if (rnp_file_exists(path)) {
875 // we have a pubring.gpg, now check for secring.gpg
876 if (!rnp_compose_path_ex(&path, &path_size, homedir, "secring.gpg", NULL)) {
877 goto done;
878 }
879 if (rnp_file_exists(path)) {
880 pub_format_guess = "GPG";
881 pub_path_guess = "pubring.gpg";
882 sec_format_guess = "GPG";
883 sec_path_guess = "secring.gpg";
884 }
885 }
886 }
887
888 // set our results
889 if (pub_format_guess) {
890 *pub_format = strdup(pub_format_guess);
891 *pub_path = rnp_compose_path(homedir, pub_path_guess, NULL);
892 if (!*pub_format || !*pub_path) {
893 ret = RNP_ERROR_OUT_OF_MEMORY;
894 goto done;
895 }
896 }
897 if (sec_format_guess) {
898 *sec_format = strdup(sec_format_guess);
899 *sec_path = rnp_compose_path(homedir, sec_path_guess, NULL);
900 if (!*sec_format || !*sec_path) {
901 ret = RNP_ERROR_OUT_OF_MEMORY;
902 goto done;
903 }
904 }
905 // we leave the *formats as NULL if we were not able to determine the format
906 // (but no error occurred)
907
908 ret = RNP_SUCCESS;
909 done:
910 if (ret) {
911 free(*pub_format);
912 *pub_format = NULL;
913 free(*pub_path);
914 *pub_path = NULL;
915
916 free(*sec_format);
917 *sec_format = NULL;
918 free(*sec_path);
919 *sec_path = NULL;
920 }
921 free(path);
922 return ret;
923 }
924 FFI_GUARD
925
926 rnp_result_t
rnp_detect_key_format(const uint8_t buf[],size_t buf_len,char ** format)927 rnp_detect_key_format(const uint8_t buf[], size_t buf_len, char **format)
928 try {
929 rnp_result_t ret = RNP_ERROR_GENERIC;
930
931 // checks
932 if (!buf || !format) {
933 return RNP_ERROR_NULL_POINTER;
934 }
935 if (!buf_len) {
936 return RNP_ERROR_SHORT_BUFFER;
937 }
938
939 *format = NULL;
940 // ordered from most reliable detection to least
941 const char *guess = NULL;
942 if (buf_len >= 12 && memcmp(buf + 8, "KBXf", 4) == 0) {
943 // KBX has a magic KBXf marker
944 guess = "KBX";
945 } else if (buf_len >= 5 && memcmp(buf, "-----", 5) == 0) {
946 // likely armored GPG
947 guess = "GPG";
948 } else if (buf[0] == '(') {
949 // G10 is s-exprs and should start end end with parentheses
950 guess = "G10";
951 } else if (buf[0] & PGP_PTAG_ALWAYS_SET) {
952 // this is harder to reliably determine, but could likely be improved
953 guess = "GPG";
954 }
955 if (guess) {
956 *format = strdup(guess);
957 if (!*format) {
958 ret = RNP_ERROR_OUT_OF_MEMORY;
959 goto done;
960 }
961 }
962
963 // success
964 ret = RNP_SUCCESS;
965 done:
966 return ret;
967 }
968 FFI_GUARD
969
970 rnp_result_t
rnp_calculate_iterations(const char * hash,size_t msec,size_t * iterations)971 rnp_calculate_iterations(const char *hash, size_t msec, size_t *iterations)
972 try {
973 if (!hash || !iterations) {
974 return RNP_ERROR_NULL_POINTER;
975 }
976 pgp_hash_alg_t halg = PGP_HASH_UNKNOWN;
977 if (!str_to_hash_alg(hash, &halg)) {
978 return RNP_ERROR_BAD_PARAMETERS;
979 }
980
981 *iterations = pgp_s2k_compute_iters(halg, msec, 0);
982 return RNP_SUCCESS;
983 }
984 FFI_GUARD
985
986 rnp_result_t
rnp_supports_feature(const char * type,const char * name,bool * supported)987 rnp_supports_feature(const char *type, const char *name, bool *supported)
988 try {
989 if (!type || !name || !supported) {
990 return RNP_ERROR_NULL_POINTER;
991 }
992 if (rnp::str_case_eq(type, RNP_FEATURE_SYMM_ALG)) {
993 pgp_symm_alg_t alg = PGP_SA_UNKNOWN;
994 *supported = str_to_cipher(name, &alg);
995 } else if (rnp::str_case_eq(type, RNP_FEATURE_AEAD_ALG)) {
996 pgp_aead_alg_t alg = PGP_AEAD_UNKNOWN;
997 *supported = str_to_aead_alg(name, &alg);
998 } else if (rnp::str_case_eq(type, RNP_FEATURE_PROT_MODE)) {
999 // for now we support only CFB for key encryption
1000 *supported = rnp::str_case_eq(name, "CFB");
1001 } else if (rnp::str_case_eq(type, RNP_FEATURE_PK_ALG)) {
1002 pgp_pubkey_alg_t alg = PGP_PKA_NOTHING;
1003 *supported = str_to_pubkey_alg(name, &alg);
1004 } else if (rnp::str_case_eq(type, RNP_FEATURE_HASH_ALG)) {
1005 pgp_hash_alg_t alg = PGP_HASH_UNKNOWN;
1006 *supported = str_to_hash_alg(name, &alg);
1007 } else if (rnp::str_case_eq(type, RNP_FEATURE_COMP_ALG)) {
1008 pgp_compression_type_t alg = PGP_C_UNKNOWN;
1009 *supported = str_to_compression_alg(name, &alg);
1010 } else if (rnp::str_case_eq(type, RNP_FEATURE_CURVE)) {
1011 pgp_curve_t curve = PGP_CURVE_UNKNOWN;
1012 *supported = curve_str_to_type(name, &curve);
1013 } else {
1014 return RNP_ERROR_BAD_PARAMETERS;
1015 }
1016 return RNP_SUCCESS;
1017 }
1018 FFI_GUARD
1019
1020 static rnp_result_t
json_array_add_id_str(json_object * arr,const id_str_pair * map,int from,int to)1021 json_array_add_id_str(json_object *arr, const id_str_pair *map, int from, int to)
1022 {
1023 while (map->str && (map->id < from)) {
1024 map++;
1025 }
1026 while (map->str && (map->id <= to)) {
1027 if (!array_add_element_json(arr, json_object_new_string(map->str))) {
1028 return RNP_ERROR_OUT_OF_MEMORY;
1029 }
1030 map++;
1031 }
1032 return RNP_SUCCESS;
1033 }
1034
1035 rnp_result_t
rnp_supported_features(const char * type,char ** result)1036 rnp_supported_features(const char *type, char **result)
1037 try {
1038 if (!type || !result) {
1039 return RNP_ERROR_NULL_POINTER;
1040 }
1041
1042 json_object *features = json_object_new_array();
1043 if (!features) {
1044 return RNP_ERROR_OUT_OF_MEMORY;
1045 }
1046
1047 rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS;
1048
1049 if (rnp::str_case_eq(type, RNP_FEATURE_SYMM_ALG)) {
1050 ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_IDEA, PGP_SA_AES_256);
1051 #if defined(ENABLE_TWOFISH)
1052 ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_TWOFISH, PGP_SA_TWOFISH);
1053 #endif
1054 ret = json_array_add_id_str(
1055 features, symm_alg_map, PGP_SA_CAMELLIA_128, PGP_SA_CAMELLIA_256);
1056 #if defined(ENABLE_SM2)
1057 ret = json_array_add_id_str(features, symm_alg_map, PGP_SA_SM4, PGP_SA_SM4);
1058 #endif
1059 } else if (rnp::str_case_eq(type, RNP_FEATURE_AEAD_ALG)) {
1060 #if defined(ENABLE_AEAD)
1061 ret = json_array_add_id_str(features, aead_alg_map, PGP_AEAD_NONE, PGP_AEAD_OCB);
1062 #else
1063 ret = json_array_add_id_str(features, aead_alg_map, PGP_AEAD_NONE, PGP_AEAD_NONE);
1064 #endif
1065 } else if (rnp::str_case_eq(type, RNP_FEATURE_PROT_MODE)) {
1066 ret = json_array_add_id_str(
1067 features, cipher_mode_map, PGP_CIPHER_MODE_CFB, PGP_CIPHER_MODE_CFB);
1068 } else if (rnp::str_case_eq(type, RNP_FEATURE_PK_ALG)) {
1069 // workaround to avoid duplicates, maybe there is a better solution
1070 (void) json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_RSA, PGP_PKA_RSA);
1071 ret = json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_DSA, PGP_PKA_EDDSA);
1072 #if defined(ENABLE_SM2)
1073 ret = json_array_add_id_str(features, pubkey_alg_map, PGP_PKA_SM2, PGP_PKA_SM2);
1074 #endif
1075 } else if (rnp::str_case_eq(type, RNP_FEATURE_HASH_ALG)) {
1076 ret = json_array_add_id_str(features, hash_alg_map, PGP_HASH_MD5, PGP_HASH_SHA3_512);
1077 #if defined(ENABLE_SM2)
1078 ret = json_array_add_id_str(features, hash_alg_map, PGP_HASH_SM3, PGP_HASH_SM3);
1079 #endif
1080 } else if (rnp::str_case_eq(type, RNP_FEATURE_COMP_ALG)) {
1081 ret = json_array_add_id_str(features, compress_alg_map, PGP_C_NONE, PGP_C_BZIP2);
1082 } else if (rnp::str_case_eq(type, RNP_FEATURE_CURVE)) {
1083 for (pgp_curve_t curve = PGP_CURVE_NIST_P_256; curve < PGP_CURVE_MAX;
1084 curve = (pgp_curve_t)(curve + 1)) {
1085 const ec_curve_desc_t *desc = get_curve_desc(curve);
1086 if (!desc) {
1087 ret = RNP_ERROR_BAD_STATE;
1088 goto done;
1089 }
1090 if (!desc->supported) {
1091 continue;
1092 }
1093 if (!array_add_element_json(features, json_object_new_string(desc->pgp_name))) {
1094 ret = RNP_ERROR_OUT_OF_MEMORY;
1095 goto done;
1096 }
1097 }
1098 ret = RNP_SUCCESS;
1099 }
1100
1101 if (ret) {
1102 goto done;
1103 }
1104
1105 *result = (char *) json_object_to_json_string_ext(features, JSON_C_TO_STRING_PRETTY);
1106 if (!*result) {
1107 ret = RNP_ERROR_BAD_STATE;
1108 goto done;
1109 }
1110 *result = strdup(*result);
1111 if (!*result) {
1112 ret = RNP_ERROR_OUT_OF_MEMORY;
1113 }
1114 done:
1115 json_object_put(features);
1116 return ret;
1117 }
1118 FFI_GUARD
1119
1120 static bool
get_feature_sec_value(rnp_ffi_t ffi,const char * stype,const char * sname,rnp::FeatureType & type,int & value)1121 get_feature_sec_value(
1122 rnp_ffi_t ffi, const char *stype, const char *sname, rnp::FeatureType &type, int &value)
1123 {
1124 /* check type */
1125 if (!rnp::str_case_eq(stype, RNP_FEATURE_HASH_ALG)) {
1126 FFI_LOG(ffi, "Unsupported feature type: %s", stype);
1127 return false;
1128 }
1129 type = rnp::FeatureType::Hash;
1130 /* check feature name */
1131 pgp_hash_alg_t alg = PGP_HASH_UNKNOWN;
1132 if (sname && !str_to_hash_alg(sname, &alg)) {
1133 FFI_LOG(ffi, "Unknown hash algorithm: %s", sname);
1134 return false;
1135 }
1136 value = alg;
1137 return true;
1138 }
1139
1140 static bool
get_feature_sec_level(rnp_ffi_t ffi,uint32_t flevel,rnp::SecurityLevel & level)1141 get_feature_sec_level(rnp_ffi_t ffi, uint32_t flevel, rnp::SecurityLevel &level)
1142 {
1143 switch (flevel) {
1144 case RNP_SECURITY_PROHIBITED:
1145 level = rnp::SecurityLevel::Disabled;
1146 break;
1147 case RNP_SECURITY_INSECURE:
1148 level = rnp::SecurityLevel::Insecure;
1149 break;
1150 case RNP_SECURITY_DEFAULT:
1151 level = rnp::SecurityLevel::Default;
1152 break;
1153 default:
1154 FFI_LOG(ffi, "Invalid security level : %" PRIu32, flevel);
1155 return false;
1156 }
1157 return true;
1158 }
1159
1160 rnp_result_t
rnp_add_security_rule(rnp_ffi_t ffi,const char * type,const char * name,uint32_t flags,uint64_t from,uint32_t level)1161 rnp_add_security_rule(rnp_ffi_t ffi,
1162 const char *type,
1163 const char *name,
1164 uint32_t flags,
1165 uint64_t from,
1166 uint32_t level)
1167 try {
1168 if (!ffi || !type || !name) {
1169 return RNP_ERROR_NULL_POINTER;
1170 }
1171 /* convert values */
1172 rnp::FeatureType ftype;
1173 int fvalue;
1174 rnp::SecurityLevel sec_level;
1175 if (!get_feature_sec_value(ffi, type, name, ftype, fvalue) ||
1176 !get_feature_sec_level(ffi, level, sec_level)) {
1177 return RNP_ERROR_BAD_PARAMETERS;
1178 }
1179 /* check flags */
1180 bool rule_override = flags & RNP_SECURITY_OVERRIDE;
1181 flags &= ~RNP_SECURITY_OVERRIDE;
1182 if (flags) {
1183 FFI_LOG(ffi, "Unknown flags: %" PRIu32, flags);
1184 return RNP_ERROR_BAD_PARAMETERS;
1185 }
1186 /* add rule */
1187 rnp::SecurityRule newrule(ftype, fvalue, sec_level, from);
1188 newrule.override = rule_override;
1189 ffi->profile().add_rule(newrule);
1190 return RNP_SUCCESS;
1191 }
1192 FFI_GUARD
1193
1194 rnp_result_t
rnp_get_security_rule(rnp_ffi_t ffi,const char * type,const char * name,uint64_t time,uint32_t * flags,uint64_t * from,uint32_t * level)1195 rnp_get_security_rule(rnp_ffi_t ffi,
1196 const char *type,
1197 const char *name,
1198 uint64_t time,
1199 uint32_t * flags,
1200 uint64_t * from,
1201 uint32_t * level)
1202 try {
1203 if (!ffi || !type || !name || !level) {
1204 return RNP_ERROR_NULL_POINTER;
1205 }
1206 /* convert values */
1207 rnp::FeatureType ftype;
1208 int fvalue;
1209 if (!get_feature_sec_value(ffi, type, name, ftype, fvalue)) {
1210 return RNP_ERROR_BAD_PARAMETERS;
1211 }
1212 /* init default rule */
1213 rnp::SecurityRule rule(ftype, fvalue, ffi->profile().def_level());
1214 /* check whether rule exists */
1215 if (ffi->profile().has_rule(ftype, fvalue, time)) {
1216 rule = ffi->profile().get_rule(ftype, fvalue, time);
1217 }
1218 /* fill the results */
1219 if (flags) {
1220 *flags = rule.override ? RNP_SECURITY_OVERRIDE : 0;
1221 }
1222 if (from) {
1223 *from = rule.from;
1224 }
1225 switch (rule.level) {
1226 case rnp::SecurityLevel::Disabled:
1227 *level = RNP_SECURITY_PROHIBITED;
1228 break;
1229 case rnp::SecurityLevel::Insecure:
1230 *level = RNP_SECURITY_INSECURE;
1231 break;
1232 case rnp::SecurityLevel::Default:
1233 *level = RNP_SECURITY_DEFAULT;
1234 break;
1235 default:
1236 FFI_LOG(ffi, "Invalid security level.");
1237 return RNP_ERROR_BAD_STATE;
1238 }
1239 return RNP_SUCCESS;
1240 }
1241 FFI_GUARD
1242
1243 rnp_result_t
rnp_remove_security_rule(rnp_ffi_t ffi,const char * type,const char * name,uint32_t level,uint32_t flags,uint64_t from,size_t * removed)1244 rnp_remove_security_rule(rnp_ffi_t ffi,
1245 const char *type,
1246 const char *name,
1247 uint32_t level,
1248 uint32_t flags,
1249 uint64_t from,
1250 size_t * removed)
1251 try {
1252 if (!ffi) {
1253 return RNP_ERROR_NULL_POINTER;
1254 }
1255 /* check flags */
1256 bool remove_all = flags & RNP_SECURITY_REMOVE_ALL;
1257 flags &= ~RNP_SECURITY_REMOVE_ALL;
1258 bool rule_override = flags & RNP_SECURITY_OVERRIDE;
1259 flags &= ~RNP_SECURITY_OVERRIDE;
1260 if (flags) {
1261 FFI_LOG(ffi, "Unknown flags: %" PRIu32, flags);
1262 return RNP_ERROR_BAD_PARAMETERS;
1263 }
1264 /* remove all rules */
1265 size_t rules = ffi->profile().size();
1266 if (!type) {
1267 ffi->profile().clear_rules();
1268 goto success;
1269 }
1270 rnp::FeatureType ftype;
1271 int fvalue;
1272 rnp::SecurityLevel flevel;
1273 if (!get_feature_sec_value(ffi, type, name, ftype, fvalue) ||
1274 !get_feature_sec_level(ffi, level, flevel)) {
1275 return RNP_ERROR_BAD_PARAMETERS;
1276 }
1277 /* remove all rules for the specified type */
1278 if (!name) {
1279 ffi->profile().clear_rules(ftype);
1280 goto success;
1281 }
1282 if (remove_all) {
1283 /* remove all rules for the specified type and name */
1284 ffi->profile().clear_rules(ftype, fvalue);
1285 } else {
1286 /* remove specific rule */
1287 rnp::SecurityRule rule(ftype, fvalue, flevel, from);
1288 rule.override = rule_override;
1289 ffi->profile().del_rule(rule);
1290 }
1291 success:
1292 if (removed) {
1293 *removed = rules - ffi->profile().size();
1294 }
1295 return RNP_SUCCESS;
1296 }
1297 FFI_GUARD
1298
1299 rnp_result_t
rnp_request_password(rnp_ffi_t ffi,rnp_key_handle_t key,const char * context,char ** password)1300 rnp_request_password(rnp_ffi_t ffi, rnp_key_handle_t key, const char *context, char **password)
1301 {
1302 if (!ffi || !password || !ffi->getpasscb) {
1303 return RNP_ERROR_NULL_POINTER;
1304 }
1305
1306 rnp::secure_vector<char> pass(MAX_PASSWORD_LENGTH, '\0');
1307 bool req_res =
1308 ffi->getpasscb(ffi, ffi->getpasscb_ctx, key, context, pass.data(), pass.size());
1309 if (!req_res) {
1310 return RNP_ERROR_GENERIC;
1311 }
1312 size_t pass_len = strlen(pass.data()) + 1;
1313 *password = (char *) malloc(pass_len);
1314 if (!*password) {
1315 return RNP_ERROR_OUT_OF_MEMORY;
1316 }
1317 memcpy(*password, pass.data(), pass_len);
1318 return RNP_SUCCESS;
1319 }
1320
1321 static rnp_result_t
load_keys_from_input(rnp_ffi_t ffi,rnp_input_t input,rnp_key_store_t * store)1322 load_keys_from_input(rnp_ffi_t ffi, rnp_input_t input, rnp_key_store_t *store)
1323 {
1324 rnp_result_t ret = RNP_ERROR_GENERIC;
1325
1326 pgp_key_provider_t chained;
1327 chained.callback = rnp_key_provider_store;
1328 chained.userdata = store;
1329
1330 const pgp_key_provider_t *key_providers[] = {&chained, &ffi->key_provider, NULL};
1331
1332 const pgp_key_provider_t key_provider = {.callback = rnp_key_provider_chained,
1333 .userdata = key_providers};
1334
1335 if (input->src_directory) {
1336 // load the keys
1337 try {
1338 store->path = input->src_directory;
1339 } catch (const std::exception &e) {
1340 FFI_LOG(ffi, "%s", e.what());
1341 ret = RNP_ERROR_OUT_OF_MEMORY;
1342 goto done;
1343 }
1344 if (!rnp_key_store_load_from_path(store, &key_provider)) {
1345 ret = RNP_ERROR_BAD_FORMAT;
1346 goto done;
1347 }
1348 } else {
1349 // load the keys
1350 if (!rnp_key_store_load_from_src(store, &input->src, &key_provider)) {
1351 ret = RNP_ERROR_BAD_FORMAT;
1352 goto done;
1353 }
1354 }
1355
1356 ret = RNP_SUCCESS;
1357 done:
1358 return ret;
1359 }
1360
1361 static bool
key_needs_conversion(const pgp_key_t * key,const rnp_key_store_t * store)1362 key_needs_conversion(const pgp_key_t *key, const rnp_key_store_t *store)
1363 {
1364 pgp_key_store_format_t key_format = key->format;
1365 pgp_key_store_format_t store_format = store->format;
1366 /* pgp_key_t->format is only ever GPG or G10.
1367 *
1368 * The key store, however, could have a format of KBX, GPG, or G10.
1369 * A KBX (and GPG) key store can only handle a pgp_key_t with a format of GPG.
1370 * A G10 key store can only handle a pgp_key_t with a format of G10.
1371 */
1372 // should never be the case
1373 assert(key_format != PGP_KEY_STORE_KBX);
1374 // normalize the store format
1375 if (store_format == PGP_KEY_STORE_KBX) {
1376 store_format = PGP_KEY_STORE_GPG;
1377 }
1378 // from here, both the key and store formats can only be GPG or G10
1379 return key_format != store_format;
1380 }
1381
1382 static rnp_result_t
do_load_keys(rnp_ffi_t ffi,rnp_input_t input,pgp_key_store_format_t format,key_type_t key_type)1383 do_load_keys(rnp_ffi_t ffi,
1384 rnp_input_t input,
1385 pgp_key_store_format_t format,
1386 key_type_t key_type)
1387 {
1388 rnp_result_t ret = RNP_ERROR_GENERIC;
1389 rnp_key_store_t *tmp_store = NULL;
1390 pgp_key_t keycp;
1391 rnp_result_t tmpret;
1392
1393 // create a temporary key store to hold the keys
1394 try {
1395 tmp_store = new rnp_key_store_t(format, "", ffi->context);
1396 } catch (const std::invalid_argument &e) {
1397 FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format);
1398 return RNP_ERROR_BAD_PARAMETERS;
1399 } catch (const std::exception &e) {
1400 FFI_LOG(ffi, "%s", e.what());
1401 return RNP_ERROR_OUT_OF_MEMORY;
1402 }
1403
1404 // load keys into our temporary store
1405 tmpret = load_keys_from_input(ffi, input, tmp_store);
1406 if (tmpret) {
1407 ret = tmpret;
1408 goto done;
1409 }
1410 // go through all the loaded keys
1411 for (auto &key : tmp_store->keys) {
1412 // check that the key is the correct type and has not already been loaded
1413 // add secret key part if it is and we need it
1414 if (key.is_secret() && ((key_type == KEY_TYPE_SECRET) || (key_type == KEY_TYPE_ANY))) {
1415 if (key_needs_conversion(&key, ffi->secring)) {
1416 FFI_LOG(ffi, "This key format conversion is not yet supported");
1417 ret = RNP_ERROR_NOT_IMPLEMENTED;
1418 goto done;
1419 }
1420
1421 if (!rnp_key_store_add_key(ffi->secring, &key)) {
1422 FFI_LOG(ffi, "Failed to add secret key");
1423 ret = RNP_ERROR_GENERIC;
1424 goto done;
1425 }
1426 }
1427
1428 // add public key part if needed
1429 if ((key.format == PGP_KEY_STORE_G10) ||
1430 ((key_type != KEY_TYPE_ANY) && (key_type != KEY_TYPE_PUBLIC))) {
1431 continue;
1432 }
1433
1434 try {
1435 keycp = pgp_key_t(key, true);
1436 } catch (const std::exception &e) {
1437 RNP_LOG("Failed to copy public key part: %s", e.what());
1438 ret = RNP_ERROR_GENERIC;
1439 goto done;
1440 }
1441
1442 /* TODO: We could do this a few different ways. There isn't an obvious reason
1443 * to restrict what formats we load, so we don't necessarily need to require a
1444 * conversion just to load and use a G10 key when using GPG keyrings, for
1445 * example. We could just convert when saving.
1446 */
1447
1448 if (key_needs_conversion(&key, ffi->pubring)) {
1449 FFI_LOG(ffi, "This key format conversion is not yet supported");
1450 ret = RNP_ERROR_NOT_IMPLEMENTED;
1451 goto done;
1452 }
1453
1454 if (!rnp_key_store_add_key(ffi->pubring, &keycp)) {
1455 FFI_LOG(ffi, "Failed to add public key");
1456 ret = RNP_ERROR_GENERIC;
1457 goto done;
1458 }
1459 }
1460
1461 // success, even if we didn't actually load any
1462 ret = RNP_SUCCESS;
1463 done:
1464 delete tmp_store;
1465 return ret;
1466 }
1467
1468 static key_type_t
flags_to_key_type(uint32_t * flags)1469 flags_to_key_type(uint32_t *flags)
1470 {
1471 key_type_t type = KEY_TYPE_NONE;
1472 // figure out what type of keys to operate on, based on flags
1473 if ((*flags & RNP_LOAD_SAVE_PUBLIC_KEYS) && (*flags & RNP_LOAD_SAVE_SECRET_KEYS)) {
1474 type = KEY_TYPE_ANY;
1475 *flags &= ~(RNP_LOAD_SAVE_PUBLIC_KEYS | RNP_LOAD_SAVE_SECRET_KEYS);
1476 } else if (*flags & RNP_LOAD_SAVE_PUBLIC_KEYS) {
1477 type = KEY_TYPE_PUBLIC;
1478 *flags &= ~RNP_LOAD_SAVE_PUBLIC_KEYS;
1479 } else if (*flags & RNP_LOAD_SAVE_SECRET_KEYS) {
1480 type = KEY_TYPE_SECRET;
1481 *flags &= ~RNP_LOAD_SAVE_SECRET_KEYS;
1482 }
1483 return type;
1484 }
1485
1486 rnp_result_t
rnp_load_keys(rnp_ffi_t ffi,const char * format,rnp_input_t input,uint32_t flags)1487 rnp_load_keys(rnp_ffi_t ffi, const char *format, rnp_input_t input, uint32_t flags)
1488 try {
1489 // checks
1490 if (!ffi || !format || !input) {
1491 return RNP_ERROR_NULL_POINTER;
1492 }
1493 key_type_t type = flags_to_key_type(&flags);
1494 if (!type) {
1495 FFI_LOG(ffi, "invalid flags - must have public and/or secret keys");
1496 return RNP_ERROR_BAD_PARAMETERS;
1497 }
1498 pgp_key_store_format_t ks_format = PGP_KEY_STORE_UNKNOWN;
1499 if (!parse_ks_format(&ks_format, format)) {
1500 FFI_LOG(ffi, "invalid key store format: %s", format);
1501 return RNP_ERROR_BAD_PARAMETERS;
1502 }
1503
1504 // check for any unrecognized flags (not forward-compat, but maybe still a good idea)
1505 if (flags) {
1506 FFI_LOG(ffi, "unexpected flags remaining: 0x%X", flags);
1507 return RNP_ERROR_BAD_PARAMETERS;
1508 }
1509 return do_load_keys(ffi, input, ks_format, type);
1510 }
1511 FFI_GUARD
1512
1513 rnp_result_t
rnp_unload_keys(rnp_ffi_t ffi,uint32_t flags)1514 rnp_unload_keys(rnp_ffi_t ffi, uint32_t flags)
1515 try {
1516 if (!ffi) {
1517 return RNP_ERROR_NULL_POINTER;
1518 }
1519
1520 if (flags & ~(RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)) {
1521 return RNP_ERROR_BAD_PARAMETERS;
1522 }
1523
1524 if (flags & RNP_KEY_UNLOAD_PUBLIC) {
1525 rnp_key_store_clear(ffi->pubring);
1526 }
1527 if (flags & RNP_KEY_UNLOAD_SECRET) {
1528 rnp_key_store_clear(ffi->secring);
1529 }
1530
1531 return RNP_SUCCESS;
1532 }
1533 FFI_GUARD
1534
1535 static rnp_result_t
rnp_input_dearmor_if_needed(rnp_input_t input)1536 rnp_input_dearmor_if_needed(rnp_input_t input)
1537 {
1538 if (!input) {
1539 return RNP_ERROR_NULL_POINTER;
1540 }
1541 if (input->src_directory) {
1542 return RNP_ERROR_BAD_PARAMETERS;
1543 }
1544 bool require_armor = false;
1545 /* check whether we already have armored stream */
1546 if (input->src.type == PGP_STREAM_ARMORED) {
1547 if (!src_eof(&input->src)) {
1548 return RNP_SUCCESS;
1549 }
1550 /* eof - probably next we have another armored message */
1551 src_close(&input->src);
1552 void *app_ctx = input->app_ctx;
1553 *input = *(rnp_input_t) app_ctx;
1554 free(app_ctx);
1555 /* we should not mix armored data with binary */
1556 require_armor = true;
1557 }
1558 if (src_eof(&input->src)) {
1559 return RNP_ERROR_EOF;
1560 }
1561 if (!is_armored_source(&input->src)) {
1562 return require_armor ? RNP_ERROR_BAD_FORMAT : RNP_SUCCESS;
1563 }
1564
1565 rnp_input_t app_ctx = (rnp_input_t) calloc(1, sizeof(*input));
1566 if (!app_ctx) {
1567 return RNP_ERROR_OUT_OF_MEMORY;
1568 }
1569 *app_ctx = *input;
1570
1571 pgp_source_t armored;
1572 rnp_result_t ret = init_armored_src(&armored, &app_ctx->src);
1573 if (ret) {
1574 /* original src may be changed during init_armored_src call, so copy it back */
1575 input->src = app_ctx->src;
1576 free(app_ctx);
1577 return ret;
1578 }
1579
1580 input->src = armored;
1581 input->app_ctx = app_ctx;
1582 return RNP_SUCCESS;
1583 }
1584
1585 static const char *
key_status_to_str(pgp_key_import_status_t status)1586 key_status_to_str(pgp_key_import_status_t status)
1587 {
1588 if (status == PGP_KEY_IMPORT_STATUS_UNKNOWN) {
1589 return "none";
1590 }
1591 return id_str_pair::lookup(key_import_status_map, status, "none");
1592 }
1593
1594 static rnp_result_t
add_key_status(json_object * keys,const pgp_key_t * key,pgp_key_import_status_t pub,pgp_key_import_status_t sec)1595 add_key_status(json_object * keys,
1596 const pgp_key_t * key,
1597 pgp_key_import_status_t pub,
1598 pgp_key_import_status_t sec)
1599 {
1600 json_object *jsokey = json_object_new_object();
1601 if (!jsokey) {
1602 return RNP_ERROR_OUT_OF_MEMORY;
1603 }
1604
1605 if (!obj_add_field_json(
1606 jsokey, "public", json_object_new_string(key_status_to_str(pub))) ||
1607 !obj_add_field_json(
1608 jsokey, "secret", json_object_new_string(key_status_to_str(sec))) ||
1609 !obj_add_hex_json(jsokey, "fingerprint", key->fp().fingerprint, key->fp().length) ||
1610 !array_add_element_json(keys, jsokey)) {
1611 json_object_put(jsokey);
1612 return RNP_ERROR_OUT_OF_MEMORY;
1613 }
1614
1615 return RNP_SUCCESS;
1616 }
1617
1618 rnp_result_t
rnp_import_keys(rnp_ffi_t ffi,rnp_input_t input,uint32_t flags,char ** results)1619 rnp_import_keys(rnp_ffi_t ffi, rnp_input_t input, uint32_t flags, char **results)
1620 try {
1621 if (!ffi || !input) {
1622 return RNP_ERROR_NULL_POINTER;
1623 }
1624 bool sec = false;
1625 bool pub = false;
1626 if (flags & RNP_LOAD_SAVE_SECRET_KEYS) {
1627 sec = true;
1628 flags &= ~RNP_LOAD_SAVE_SECRET_KEYS;
1629 }
1630 if (flags & RNP_LOAD_SAVE_PUBLIC_KEYS) {
1631 pub = true;
1632 flags &= ~RNP_LOAD_SAVE_PUBLIC_KEYS;
1633 }
1634 if (!pub && !sec) {
1635 FFI_LOG(ffi, "bad flags: need to specify public and/or secret keys");
1636 return RNP_ERROR_BAD_PARAMETERS;
1637 }
1638 bool skipbad = false;
1639 if (flags & RNP_LOAD_SAVE_PERMISSIVE) {
1640 skipbad = true;
1641 flags &= ~RNP_LOAD_SAVE_PERMISSIVE;
1642 }
1643 bool single = false;
1644 if (flags & RNP_LOAD_SAVE_SINGLE) {
1645 single = true;
1646 flags &= ~RNP_LOAD_SAVE_SINGLE;
1647 }
1648 if (flags) {
1649 FFI_LOG(ffi, "unexpected flags remaining: 0x%X", flags);
1650 return RNP_ERROR_BAD_PARAMETERS;
1651 }
1652
1653 rnp_result_t ret = RNP_ERROR_GENERIC;
1654 rnp_key_store_t *tmp_store = NULL;
1655 rnp_result_t tmpret;
1656 json_object * jsores = NULL;
1657 json_object * jsokeys = NULL;
1658
1659 // load keys to temporary keystore.
1660 try {
1661 tmp_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", ffi->context);
1662 } catch (const std::exception &e) {
1663 FFI_LOG(ffi, "Failed to create key store: %s.", e.what());
1664 return RNP_ERROR_OUT_OF_MEMORY;
1665 }
1666
1667 if (single) {
1668 /* we need to init and handle dearmor on this layer since it may be used for the next
1669 * keys import */
1670 ret = rnp_input_dearmor_if_needed(input);
1671 if (ret == RNP_ERROR_EOF) {
1672 goto done;
1673 }
1674 if (ret) {
1675 FFI_LOG(ffi, "Failed to init/check dearmor.");
1676 goto done;
1677 }
1678 ret = rnp_key_store_pgp_read_key_from_src(*tmp_store, input->src, skipbad);
1679 if (ret) {
1680 goto done;
1681 }
1682 } else {
1683 ret = rnp_key_store_pgp_read_from_src(tmp_store, &input->src, skipbad);
1684 if (ret) {
1685 goto done;
1686 }
1687 }
1688 jsores = json_object_new_object();
1689 if (!jsores) {
1690 ret = RNP_ERROR_OUT_OF_MEMORY;
1691 goto done;
1692 }
1693 jsokeys = json_object_new_array();
1694 if (!obj_add_field_json(jsores, "keys", jsokeys)) {
1695 ret = RNP_ERROR_OUT_OF_MEMORY;
1696 goto done;
1697 }
1698
1699 // import keys to the main keystore.
1700 for (auto &key : tmp_store->keys) {
1701 pgp_key_import_status_t pub_status = PGP_KEY_IMPORT_STATUS_UNKNOWN;
1702 pgp_key_import_status_t sec_status = PGP_KEY_IMPORT_STATUS_UNKNOWN;
1703 if (!pub && key.is_public()) {
1704 continue;
1705 }
1706 // if we got here then we add public key itself or public part of the secret key
1707 if (!rnp_key_store_import_key(ffi->pubring, &key, true, &pub_status)) {
1708 ret = RNP_ERROR_BAD_PARAMETERS;
1709 goto done;
1710 }
1711 // import secret key part if available and requested
1712 if (sec && key.is_secret()) {
1713 if (!rnp_key_store_import_key(ffi->secring, &key, false, &sec_status)) {
1714 ret = RNP_ERROR_BAD_PARAMETERS;
1715 goto done;
1716 }
1717 // add uids, certifications and other stuff from the public key if any
1718 pgp_key_t *expub = rnp_key_store_get_key_by_fpr(ffi->pubring, key.fp());
1719 if (expub && !rnp_key_store_import_key(ffi->secring, expub, true, NULL)) {
1720 ret = RNP_ERROR_BAD_PARAMETERS;
1721 goto done;
1722 }
1723 }
1724 // now add key fingerprint to json based on statuses
1725 if ((tmpret = add_key_status(jsokeys, &key, pub_status, sec_status))) {
1726 ret = tmpret;
1727 goto done;
1728 }
1729 }
1730
1731 if (results) {
1732 *results = (char *) json_object_to_json_string_ext(jsores, JSON_C_TO_STRING_PRETTY);
1733 if (!*results) {
1734 goto done;
1735 }
1736 *results = strdup(*results);
1737 if (!*results) {
1738 ret = RNP_ERROR_OUT_OF_MEMORY;
1739 goto done;
1740 }
1741 }
1742
1743 ret = RNP_SUCCESS;
1744 done:
1745 delete tmp_store;
1746 json_object_put(jsores);
1747 return ret;
1748 }
1749 FFI_GUARD
1750
1751 static const char *
sig_status_to_str(pgp_sig_import_status_t status)1752 sig_status_to_str(pgp_sig_import_status_t status)
1753 {
1754 if (status == PGP_SIG_IMPORT_STATUS_UNKNOWN) {
1755 return "none";
1756 }
1757 return id_str_pair::lookup(sig_import_status_map, status, "none");
1758 }
1759
1760 static rnp_result_t
add_sig_status(json_object * sigs,const pgp_key_t * signer,pgp_sig_import_status_t pub,pgp_sig_import_status_t sec)1761 add_sig_status(json_object * sigs,
1762 const pgp_key_t * signer,
1763 pgp_sig_import_status_t pub,
1764 pgp_sig_import_status_t sec)
1765 {
1766 json_object *jsosig = json_object_new_object();
1767 if (!jsosig) {
1768 return RNP_ERROR_OUT_OF_MEMORY;
1769 }
1770
1771 if (!obj_add_field_json(
1772 jsosig, "public", json_object_new_string(sig_status_to_str(pub))) ||
1773 !obj_add_field_json(
1774 jsosig, "secret", json_object_new_string(sig_status_to_str(sec)))) {
1775 json_object_put(jsosig);
1776 return RNP_ERROR_OUT_OF_MEMORY;
1777 }
1778
1779 if (signer) {
1780 const pgp_fingerprint_t &fp = signer->fp();
1781 if (!obj_add_hex_json(jsosig, "signer fingerprint", fp.fingerprint, fp.length)) {
1782 json_object_put(jsosig);
1783 return RNP_ERROR_OUT_OF_MEMORY;
1784 }
1785 }
1786
1787 if (!array_add_element_json(sigs, jsosig)) {
1788 json_object_put(jsosig);
1789 return RNP_ERROR_OUT_OF_MEMORY;
1790 }
1791
1792 return RNP_SUCCESS;
1793 }
1794
1795 rnp_result_t
rnp_import_signatures(rnp_ffi_t ffi,rnp_input_t input,uint32_t flags,char ** results)1796 rnp_import_signatures(rnp_ffi_t ffi, rnp_input_t input, uint32_t flags, char **results)
1797 try {
1798 if (!ffi || !input) {
1799 return RNP_ERROR_NULL_POINTER;
1800 }
1801 if (flags) {
1802 FFI_LOG(ffi, "wrong flags: %d", (int) flags);
1803 return RNP_ERROR_BAD_PARAMETERS;
1804 }
1805
1806 rnp_result_t ret = RNP_ERROR_GENERIC;
1807 json_object * jsores = NULL;
1808 json_object * jsosigs = NULL;
1809 pgp_signature_list_t sigs;
1810 rnp_result_t sigret = process_pgp_signatures(&input->src, sigs);
1811 if (sigret) {
1812 ret = sigret;
1813 FFI_LOG(ffi, "failed to parse signature(s)");
1814 goto done;
1815 }
1816
1817 jsores = json_object_new_object();
1818 if (!jsores) {
1819 ret = RNP_ERROR_OUT_OF_MEMORY;
1820 goto done;
1821 }
1822 jsosigs = json_object_new_array();
1823 if (!obj_add_field_json(jsores, "sigs", jsosigs)) {
1824 ret = RNP_ERROR_OUT_OF_MEMORY;
1825 goto done;
1826 }
1827
1828 for (auto &sig : sigs) {
1829 pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN;
1830 pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN;
1831 pgp_key_t *pkey = rnp_key_store_import_signature(ffi->pubring, &sig, &pub_status);
1832 pgp_key_t *skey = rnp_key_store_import_signature(ffi->secring, &sig, &sec_status);
1833 sigret = add_sig_status(jsosigs, pkey ? pkey : skey, pub_status, sec_status);
1834 if (sigret) {
1835 ret = sigret;
1836 goto done;
1837 }
1838 }
1839
1840 if (results) {
1841 *results = (char *) json_object_to_json_string_ext(jsores, JSON_C_TO_STRING_PRETTY);
1842 if (!*results) {
1843 ret = RNP_ERROR_OUT_OF_MEMORY;
1844 goto done;
1845 }
1846 *results = strdup(*results);
1847 if (!*results) {
1848 ret = RNP_ERROR_OUT_OF_MEMORY;
1849 goto done;
1850 }
1851 }
1852 ret = RNP_SUCCESS;
1853 done:
1854 json_object_put(jsores);
1855 return ret;
1856 }
1857 FFI_GUARD
1858
1859 static bool
copy_store_keys(rnp_ffi_t ffi,rnp_key_store_t * dest,rnp_key_store_t * src)1860 copy_store_keys(rnp_ffi_t ffi, rnp_key_store_t *dest, rnp_key_store_t *src)
1861 {
1862 for (auto &key : src->keys) {
1863 if (!rnp_key_store_add_key(dest, &key)) {
1864 FFI_LOG(ffi, "failed to add key to the store");
1865 return false;
1866 }
1867 }
1868 return true;
1869 }
1870
1871 static rnp_result_t
do_save_keys(rnp_ffi_t ffi,rnp_output_t output,pgp_key_store_format_t format,key_type_t key_type)1872 do_save_keys(rnp_ffi_t ffi,
1873 rnp_output_t output,
1874 pgp_key_store_format_t format,
1875 key_type_t key_type)
1876 {
1877 rnp_result_t ret = RNP_ERROR_GENERIC;
1878
1879 // create a temporary key store to hold the keys
1880 rnp_key_store_t *tmp_store = NULL;
1881 try {
1882 tmp_store = new rnp_key_store_t(format, "", ffi->context);
1883 } catch (const std::invalid_argument &e) {
1884 FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format);
1885 return RNP_ERROR_BAD_PARAMETERS;
1886 } catch (const std::exception &e) {
1887 FFI_LOG(ffi, "%s", e.what());
1888 return RNP_ERROR_OUT_OF_MEMORY;
1889 }
1890 // include the public keys, if desired
1891 if (key_type == KEY_TYPE_PUBLIC || key_type == KEY_TYPE_ANY) {
1892 if (!copy_store_keys(ffi, tmp_store, ffi->pubring)) {
1893 ret = RNP_ERROR_OUT_OF_MEMORY;
1894 goto done;
1895 }
1896 }
1897 // include the secret keys, if desired
1898 if (key_type == KEY_TYPE_SECRET || key_type == KEY_TYPE_ANY) {
1899 if (!copy_store_keys(ffi, tmp_store, ffi->secring)) {
1900 ret = RNP_ERROR_OUT_OF_MEMORY;
1901 goto done;
1902 }
1903 }
1904 // preliminary check on the format
1905 for (auto &key : tmp_store->keys) {
1906 if (key_needs_conversion(&key, tmp_store)) {
1907 FFI_LOG(ffi, "This key format conversion is not yet supported");
1908 ret = RNP_ERROR_NOT_IMPLEMENTED;
1909 goto done;
1910 }
1911 }
1912 // write
1913 if (output->dst_directory) {
1914 try {
1915 tmp_store->path = output->dst_directory;
1916 } catch (const std::exception &e) {
1917 FFI_LOG(ffi, "%s", e.what());
1918 ret = RNP_ERROR_OUT_OF_MEMORY;
1919 goto done;
1920 }
1921 if (!rnp_key_store_write_to_path(tmp_store)) {
1922 ret = RNP_ERROR_WRITE;
1923 goto done;
1924 }
1925 ret = RNP_SUCCESS;
1926 } else {
1927 if (!rnp_key_store_write_to_dst(tmp_store, &output->dst)) {
1928 ret = RNP_ERROR_WRITE;
1929 goto done;
1930 }
1931 dst_flush(&output->dst);
1932 output->keep = (output->dst.werr == RNP_SUCCESS);
1933 ret = output->dst.werr;
1934 }
1935
1936 done:
1937 delete tmp_store;
1938 return ret;
1939 }
1940
1941 rnp_result_t
rnp_save_keys(rnp_ffi_t ffi,const char * format,rnp_output_t output,uint32_t flags)1942 rnp_save_keys(rnp_ffi_t ffi, const char *format, rnp_output_t output, uint32_t flags)
1943 try {
1944 // checks
1945 if (!ffi || !format || !output) {
1946 return RNP_ERROR_NULL_POINTER;
1947 }
1948 key_type_t type = flags_to_key_type(&flags);
1949 if (!type) {
1950 FFI_LOG(ffi, "invalid flags - must have public and/or secret keys");
1951 return RNP_ERROR_BAD_PARAMETERS;
1952 }
1953 // check for any unrecognized flags (not forward-compat, but maybe still a good idea)
1954 if (flags) {
1955 FFI_LOG(ffi, "unexpected flags remaining: 0x%X", flags);
1956 return RNP_ERROR_BAD_PARAMETERS;
1957 }
1958 pgp_key_store_format_t ks_format = PGP_KEY_STORE_UNKNOWN;
1959 if (!parse_ks_format(&ks_format, format)) {
1960 FFI_LOG(ffi, "unknown key store format: %s", format);
1961 return RNP_ERROR_BAD_PARAMETERS;
1962 }
1963 return do_save_keys(ffi, output, ks_format, type);
1964 }
1965 FFI_GUARD
1966
1967 rnp_result_t
rnp_get_public_key_count(rnp_ffi_t ffi,size_t * count)1968 rnp_get_public_key_count(rnp_ffi_t ffi, size_t *count)
1969 try {
1970 if (!ffi || !count) {
1971 return RNP_ERROR_NULL_POINTER;
1972 }
1973 *count = rnp_key_store_get_key_count(ffi->pubring);
1974 return RNP_SUCCESS;
1975 }
1976 FFI_GUARD
1977
1978 rnp_result_t
rnp_get_secret_key_count(rnp_ffi_t ffi,size_t * count)1979 rnp_get_secret_key_count(rnp_ffi_t ffi, size_t *count)
1980 try {
1981 if (!ffi || !count) {
1982 return RNP_ERROR_NULL_POINTER;
1983 }
1984 *count = rnp_key_store_get_key_count(ffi->secring);
1985 return RNP_SUCCESS;
1986 }
1987 FFI_GUARD
1988
1989 rnp_result_t
rnp_input_from_path(rnp_input_t * input,const char * path)1990 rnp_input_from_path(rnp_input_t *input, const char *path)
1991 try {
1992 struct rnp_input_st *ob = NULL;
1993 struct stat st = {0};
1994
1995 if (!input || !path) {
1996 return RNP_ERROR_NULL_POINTER;
1997 }
1998 ob = (rnp_input_st *) calloc(1, sizeof(*ob));
1999 if (!ob) {
2000 return RNP_ERROR_OUT_OF_MEMORY;
2001 }
2002 if (rnp_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
2003 // a bit hacky, just save the directory path
2004 ob->src_directory = strdup(path);
2005 if (!ob->src_directory) {
2006 free(ob);
2007 return RNP_ERROR_OUT_OF_MEMORY;
2008 }
2009 // return error on attempt to read from this source
2010 (void) init_null_src(&ob->src);
2011 } else {
2012 // simple input from a file
2013 rnp_result_t ret = init_file_src(&ob->src, path);
2014 if (ret) {
2015 free(ob);
2016 return ret;
2017 }
2018 }
2019 *input = ob;
2020 return RNP_SUCCESS;
2021 }
2022 FFI_GUARD
2023
2024 rnp_result_t
rnp_input_from_memory(rnp_input_t * input,const uint8_t buf[],size_t buf_len,bool do_copy)2025 rnp_input_from_memory(rnp_input_t *input, const uint8_t buf[], size_t buf_len, bool do_copy)
2026 try {
2027 if (!input || !buf) {
2028 return RNP_ERROR_NULL_POINTER;
2029 }
2030 if (!buf_len) {
2031 return RNP_ERROR_SHORT_BUFFER;
2032 }
2033 *input = (rnp_input_t) calloc(1, sizeof(**input));
2034 if (!*input) {
2035 return RNP_ERROR_OUT_OF_MEMORY;
2036 }
2037 uint8_t *data = (uint8_t *) buf;
2038 if (do_copy) {
2039 data = (uint8_t *) malloc(buf_len);
2040 if (!data) {
2041 free(*input);
2042 *input = NULL;
2043 return RNP_ERROR_OUT_OF_MEMORY;
2044 }
2045 memcpy(data, buf, buf_len);
2046 }
2047 rnp_result_t ret = init_mem_src(&(*input)->src, data, buf_len, do_copy);
2048 if (ret) {
2049 if (do_copy) {
2050 free(data);
2051 }
2052 free(*input);
2053 *input = NULL;
2054 return ret;
2055 }
2056 return RNP_SUCCESS;
2057 }
2058 FFI_GUARD
2059
2060 static bool
input_reader_bounce(pgp_source_t * src,void * buf,size_t len,size_t * read)2061 input_reader_bounce(pgp_source_t *src, void *buf, size_t len, size_t *read)
2062 {
2063 rnp_input_t input = (rnp_input_t) src->param;
2064 if (!input->reader) {
2065 return false;
2066 }
2067 return input->reader(input->app_ctx, buf, len, read);
2068 }
2069
2070 static void
input_closer_bounce(pgp_source_t * src)2071 input_closer_bounce(pgp_source_t *src)
2072 {
2073 rnp_input_t input = (rnp_input_t) src->param;
2074 if (input->closer) {
2075 input->closer(input->app_ctx);
2076 }
2077 }
2078
2079 rnp_result_t
rnp_input_from_callback(rnp_input_t * input,rnp_input_reader_t * reader,rnp_input_closer_t * closer,void * app_ctx)2080 rnp_input_from_callback(rnp_input_t * input,
2081 rnp_input_reader_t *reader,
2082 rnp_input_closer_t *closer,
2083 void * app_ctx)
2084 try {
2085 struct rnp_input_st *obj = NULL;
2086
2087 // checks
2088 if (!input || !reader) {
2089 return RNP_ERROR_NULL_POINTER;
2090 }
2091 obj = (rnp_input_st *) calloc(1, sizeof(*obj));
2092 if (!obj) {
2093 return RNP_ERROR_OUT_OF_MEMORY;
2094 }
2095 pgp_source_t *src = &obj->src;
2096 obj->reader = reader;
2097 obj->closer = closer;
2098 obj->app_ctx = app_ctx;
2099 if (!init_src_common(src, 0)) {
2100 free(obj);
2101 return RNP_ERROR_OUT_OF_MEMORY;
2102 }
2103 src->param = obj;
2104 src->read = input_reader_bounce;
2105 src->close = input_closer_bounce;
2106 src->type = PGP_STREAM_MEMORY;
2107 *input = obj;
2108 return RNP_SUCCESS;
2109 }
2110 FFI_GUARD
2111
2112 rnp_result_t
rnp_input_destroy(rnp_input_t input)2113 rnp_input_destroy(rnp_input_t input)
2114 try {
2115 if (input) {
2116 bool armored = input->src.type == PGP_STREAM_ARMORED;
2117 src_close(&input->src);
2118 if (armored) {
2119 rnp_input_destroy((rnp_input_t) input->app_ctx);
2120 }
2121 free(input->src_directory);
2122 free(input);
2123 }
2124 return RNP_SUCCESS;
2125 }
2126 FFI_GUARD
2127
2128 rnp_result_t
rnp_output_to_path(rnp_output_t * output,const char * path)2129 rnp_output_to_path(rnp_output_t *output, const char *path)
2130 try {
2131 struct rnp_output_st *ob = NULL;
2132 struct stat st = {0};
2133
2134 if (!output || !path) {
2135 return RNP_ERROR_NULL_POINTER;
2136 }
2137 ob = (rnp_output_st *) calloc(1, sizeof(*ob));
2138 if (!ob) {
2139 return RNP_ERROR_OUT_OF_MEMORY;
2140 }
2141 if (rnp_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
2142 // a bit hacky, just save the directory path
2143 ob->dst_directory = strdup(path);
2144 if (!ob->dst_directory) {
2145 free(ob);
2146 return RNP_ERROR_OUT_OF_MEMORY;
2147 }
2148 } else {
2149 // simple output to a file
2150 rnp_result_t ret = init_file_dest(&ob->dst, path, true);
2151 if (ret) {
2152 free(ob);
2153 return ret;
2154 }
2155 }
2156 *output = ob;
2157 return RNP_SUCCESS;
2158 }
2159 FFI_GUARD
2160
2161 rnp_result_t
rnp_output_to_file(rnp_output_t * output,const char * path,uint32_t flags)2162 rnp_output_to_file(rnp_output_t *output, const char *path, uint32_t flags)
2163 try {
2164 if (!output || !path) {
2165 return RNP_ERROR_NULL_POINTER;
2166 }
2167 bool overwrite = false;
2168 bool random = false;
2169 if (flags & RNP_OUTPUT_FILE_OVERWRITE) {
2170 overwrite = true;
2171 flags &= ~RNP_OUTPUT_FILE_OVERWRITE;
2172 }
2173 if (flags & RNP_OUTPUT_FILE_RANDOM) {
2174 random = true;
2175 flags &= ~RNP_OUTPUT_FILE_RANDOM;
2176 }
2177 if (flags) {
2178 return RNP_ERROR_BAD_PARAMETERS;
2179 }
2180 rnp_output_t res = (rnp_output_t) calloc(1, sizeof(*res));
2181 if (!res) {
2182 return RNP_ERROR_OUT_OF_MEMORY;
2183 }
2184 rnp_result_t ret = RNP_ERROR_GENERIC;
2185 if (random) {
2186 ret = init_tmpfile_dest(&res->dst, path, overwrite);
2187 } else {
2188 ret = init_file_dest(&res->dst, path, overwrite);
2189 }
2190 if (ret) {
2191 free(res);
2192 return ret;
2193 }
2194 *output = res;
2195 return RNP_SUCCESS;
2196 }
2197 FFI_GUARD
2198
2199 rnp_result_t
rnp_output_to_memory(rnp_output_t * output,size_t max_alloc)2200 rnp_output_to_memory(rnp_output_t *output, size_t max_alloc)
2201 try {
2202 // checks
2203 if (!output) {
2204 return RNP_ERROR_NULL_POINTER;
2205 }
2206
2207 *output = (rnp_output_t) calloc(1, sizeof(**output));
2208 if (!*output) {
2209 return RNP_ERROR_OUT_OF_MEMORY;
2210 }
2211 rnp_result_t ret = init_mem_dest(&(*output)->dst, NULL, max_alloc);
2212 if (ret) {
2213 free(*output);
2214 *output = NULL;
2215 return ret;
2216 }
2217 return RNP_SUCCESS;
2218 }
2219 FFI_GUARD
2220
2221 rnp_result_t
rnp_output_to_armor(rnp_output_t base,rnp_output_t * output,const char * type)2222 rnp_output_to_armor(rnp_output_t base, rnp_output_t *output, const char *type)
2223 try {
2224 if (!base || !output) {
2225 return RNP_ERROR_NULL_POINTER;
2226 }
2227 pgp_armored_msg_t msgtype = PGP_ARMORED_MESSAGE;
2228 if (type) {
2229 msgtype = static_cast<pgp_armored_msg_t>(
2230 id_str_pair::lookup(armor_type_map, type, PGP_ARMORED_UNKNOWN));
2231 if (msgtype == PGP_ARMORED_UNKNOWN) {
2232 RNP_LOG("Unsupported armor type: %s", type);
2233 return RNP_ERROR_BAD_PARAMETERS;
2234 }
2235 }
2236 *output = (rnp_output_t) calloc(1, sizeof(**output));
2237 if (!*output) {
2238 return RNP_ERROR_OUT_OF_MEMORY;
2239 }
2240 rnp_result_t ret = init_armored_dst(&(*output)->dst, &base->dst, msgtype);
2241 if (ret) {
2242 free(*output);
2243 *output = NULL;
2244 return ret;
2245 }
2246 (*output)->app_ctx = base;
2247 return RNP_SUCCESS;
2248 }
2249 FFI_GUARD
2250
2251 rnp_result_t
rnp_output_memory_get_buf(rnp_output_t output,uint8_t ** buf,size_t * len,bool do_copy)2252 rnp_output_memory_get_buf(rnp_output_t output, uint8_t **buf, size_t *len, bool do_copy)
2253 try {
2254 if (!output || !buf || !len) {
2255 return RNP_ERROR_NULL_POINTER;
2256 }
2257
2258 *len = output->dst.writeb;
2259 *buf = (uint8_t *) mem_dest_get_memory(&output->dst);
2260 if (!*buf) {
2261 return RNP_ERROR_BAD_PARAMETERS;
2262 }
2263 if (do_copy) {
2264 uint8_t *tmp_buf = *buf;
2265 *buf = (uint8_t *) malloc(*len);
2266 if (!*buf) {
2267 return RNP_ERROR_OUT_OF_MEMORY;
2268 }
2269 memcpy(*buf, tmp_buf, *len);
2270 }
2271 return RNP_SUCCESS;
2272 }
2273 FFI_GUARD
2274
2275 static rnp_result_t
output_writer_bounce(pgp_dest_t * dst,const void * buf,size_t len)2276 output_writer_bounce(pgp_dest_t *dst, const void *buf, size_t len)
2277 {
2278 rnp_output_t output = (rnp_output_t) dst->param;
2279 if (!output->writer) {
2280 return RNP_ERROR_NULL_POINTER;
2281 }
2282 if (!output->writer(output->app_ctx, buf, len)) {
2283 return RNP_ERROR_WRITE;
2284 }
2285 return RNP_SUCCESS;
2286 }
2287
2288 static void
output_closer_bounce(pgp_dest_t * dst,bool discard)2289 output_closer_bounce(pgp_dest_t *dst, bool discard)
2290 {
2291 rnp_output_t output = (rnp_output_t) dst->param;
2292 if (output->closer) {
2293 output->closer(output->app_ctx, discard);
2294 }
2295 }
2296
2297 rnp_result_t
rnp_output_to_null(rnp_output_t * output)2298 rnp_output_to_null(rnp_output_t *output)
2299 try {
2300 // checks
2301 if (!output) {
2302 return RNP_ERROR_NULL_POINTER;
2303 }
2304
2305 *output = (rnp_output_t) calloc(1, sizeof(**output));
2306 if (!*output) {
2307 return RNP_ERROR_OUT_OF_MEMORY;
2308 }
2309 rnp_result_t ret = init_null_dest(&(*output)->dst);
2310 if (ret) {
2311 free(*output);
2312 *output = NULL;
2313 return ret;
2314 }
2315 return RNP_SUCCESS;
2316 }
2317 FFI_GUARD
2318
2319 rnp_result_t
rnp_output_write(rnp_output_t output,const void * data,size_t size,size_t * written)2320 rnp_output_write(rnp_output_t output, const void *data, size_t size, size_t *written)
2321 try {
2322 if (!output || (!data && size)) {
2323 return RNP_ERROR_NULL_POINTER;
2324 }
2325 if (!data && !size) {
2326 if (written) {
2327 *written = 0;
2328 }
2329 return RNP_SUCCESS;
2330 }
2331 size_t old = output->dst.writeb + output->dst.clen;
2332 dst_write(&output->dst, data, size);
2333 if (!output->dst.werr && written) {
2334 *written = output->dst.writeb + output->dst.clen - old;
2335 }
2336 output->keep = !output->dst.werr;
2337 return output->dst.werr;
2338 }
2339 FFI_GUARD
2340
2341 rnp_result_t
rnp_output_to_callback(rnp_output_t * output,rnp_output_writer_t * writer,rnp_output_closer_t * closer,void * app_ctx)2342 rnp_output_to_callback(rnp_output_t * output,
2343 rnp_output_writer_t *writer,
2344 rnp_output_closer_t *closer,
2345 void * app_ctx)
2346 try {
2347 // checks
2348 if (!output || !writer) {
2349 return RNP_ERROR_NULL_POINTER;
2350 }
2351
2352 *output = (rnp_output_t) calloc(1, sizeof(**output));
2353 if (!*output) {
2354 return RNP_ERROR_OUT_OF_MEMORY;
2355 }
2356 (*output)->writer = writer;
2357 (*output)->closer = closer;
2358 (*output)->app_ctx = app_ctx;
2359
2360 pgp_dest_t *dst = &(*output)->dst;
2361 dst->write = output_writer_bounce;
2362 dst->close = output_closer_bounce;
2363 dst->param = *output;
2364 dst->type = PGP_STREAM_MEMORY;
2365 dst->writeb = 0;
2366 dst->werr = RNP_SUCCESS;
2367 return RNP_SUCCESS;
2368 }
2369 FFI_GUARD
2370
2371 rnp_result_t
rnp_output_finish(rnp_output_t output)2372 rnp_output_finish(rnp_output_t output)
2373 try {
2374 if (!output) {
2375 return RNP_ERROR_NULL_POINTER;
2376 }
2377 return dst_finish(&output->dst);
2378 }
2379 FFI_GUARD
2380
2381 rnp_result_t
rnp_output_destroy(rnp_output_t output)2382 rnp_output_destroy(rnp_output_t output)
2383 try {
2384 if (output) {
2385 if (output->dst.type == PGP_STREAM_ARMORED) {
2386 ((rnp_output_t) output->app_ctx)->keep = output->keep;
2387 }
2388 dst_close(&output->dst, !output->keep);
2389 free(output->dst_directory);
2390 free(output);
2391 }
2392 return RNP_SUCCESS;
2393 }
2394 FFI_GUARD
2395
2396 static rnp_result_t
rnp_op_add_signature(rnp_ffi_t ffi,rnp_op_sign_signatures_t & signatures,rnp_key_handle_t key,rnp_ctx_t & ctx,rnp_op_sign_signature_t * sig)2397 rnp_op_add_signature(rnp_ffi_t ffi,
2398 rnp_op_sign_signatures_t &signatures,
2399 rnp_key_handle_t key,
2400 rnp_ctx_t & ctx,
2401 rnp_op_sign_signature_t * sig)
2402 {
2403 if (!key) {
2404 return RNP_ERROR_NULL_POINTER;
2405 }
2406
2407 pgp_key_t *signkey = find_suitable_key(
2408 PGP_OP_SIGN, get_key_prefer_public(key), &key->ffi->key_provider, PGP_KF_SIGN);
2409 if (signkey && !signkey->is_secret()) {
2410 pgp_key_request_ctx_t keyctx = {.op = PGP_OP_SIGN, .secret = true};
2411 keyctx.search.type = PGP_KEY_SEARCH_GRIP;
2412 keyctx.search.by.grip = signkey->grip();
2413 signkey = pgp_request_key(&key->ffi->key_provider, &keyctx);
2414 }
2415 if (!signkey) {
2416 return RNP_ERROR_NO_SUITABLE_KEY;
2417 }
2418
2419 try {
2420 signatures.emplace_back();
2421 } catch (const std::exception &e) {
2422 FFI_LOG(ffi, "%s", e.what());
2423 return RNP_ERROR_BAD_PARAMETERS;
2424 }
2425 rnp_op_sign_signature_t newsig = &signatures.back();
2426 newsig->signer.key = signkey;
2427 /* set default create/expire times */
2428 newsig->signer.sigcreate = ctx.sigcreate;
2429 newsig->signer.sigexpire = ctx.sigexpire;
2430 newsig->ffi = ffi;
2431
2432 if (sig) {
2433 *sig = newsig;
2434 }
2435 return RNP_SUCCESS;
2436 }
2437
2438 static rnp_result_t
rnp_op_set_armor(rnp_ctx_t & ctx,bool armored)2439 rnp_op_set_armor(rnp_ctx_t &ctx, bool armored)
2440 {
2441 ctx.armor = armored;
2442 return RNP_SUCCESS;
2443 }
2444
2445 static rnp_result_t
rnp_op_set_compression(rnp_ffi_t ffi,rnp_ctx_t & ctx,const char * compression,int level)2446 rnp_op_set_compression(rnp_ffi_t ffi, rnp_ctx_t &ctx, const char *compression, int level)
2447 {
2448 if (!compression) {
2449 return RNP_ERROR_NULL_POINTER;
2450 }
2451
2452 pgp_compression_type_t zalg = PGP_C_UNKNOWN;
2453 if (!str_to_compression_alg(compression, &zalg)) {
2454 FFI_LOG(ffi, "Invalid compression: %s", compression);
2455 return RNP_ERROR_BAD_PARAMETERS;
2456 }
2457 ctx.zalg = (int) zalg;
2458 ctx.zlevel = level;
2459 return RNP_SUCCESS;
2460 }
2461
2462 static rnp_result_t
rnp_op_set_hash(rnp_ffi_t ffi,rnp_ctx_t & ctx,const char * hash)2463 rnp_op_set_hash(rnp_ffi_t ffi, rnp_ctx_t &ctx, const char *hash)
2464 {
2465 if (!hash) {
2466 return RNP_ERROR_NULL_POINTER;
2467 }
2468
2469 if (!str_to_hash_alg(hash, &ctx.halg)) {
2470 FFI_LOG(ffi, "Invalid hash: %s", hash);
2471 return RNP_ERROR_BAD_PARAMETERS;
2472 }
2473 return RNP_SUCCESS;
2474 }
2475
2476 static rnp_result_t
rnp_op_set_creation_time(rnp_ctx_t & ctx,uint32_t create)2477 rnp_op_set_creation_time(rnp_ctx_t &ctx, uint32_t create)
2478 {
2479 ctx.sigcreate = create;
2480 return RNP_SUCCESS;
2481 }
2482
2483 static rnp_result_t
rnp_op_set_expiration_time(rnp_ctx_t & ctx,uint32_t expire)2484 rnp_op_set_expiration_time(rnp_ctx_t &ctx, uint32_t expire)
2485 {
2486 ctx.sigexpire = expire;
2487 return RNP_SUCCESS;
2488 }
2489
2490 static rnp_result_t
rnp_op_set_file_name(rnp_ctx_t & ctx,const char * filename)2491 rnp_op_set_file_name(rnp_ctx_t &ctx, const char *filename)
2492 {
2493 ctx.filename = filename ? filename : "";
2494 return RNP_SUCCESS;
2495 }
2496
2497 static rnp_result_t
rnp_op_set_file_mtime(rnp_ctx_t & ctx,uint32_t mtime)2498 rnp_op_set_file_mtime(rnp_ctx_t &ctx, uint32_t mtime)
2499 {
2500 ctx.filemtime = mtime;
2501 return RNP_SUCCESS;
2502 }
2503
2504 rnp_result_t
rnp_op_encrypt_create(rnp_op_encrypt_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_output_t output)2505 rnp_op_encrypt_create(rnp_op_encrypt_t *op,
2506 rnp_ffi_t ffi,
2507 rnp_input_t input,
2508 rnp_output_t output)
2509 try {
2510 // checks
2511 if (!op || !ffi || !input || !output) {
2512 return RNP_ERROR_NULL_POINTER;
2513 }
2514
2515 *op = new rnp_op_encrypt_st();
2516 rnp_ctx_init_ffi((*op)->rnpctx, ffi);
2517 (*op)->ffi = ffi;
2518 (*op)->input = input;
2519 (*op)->output = output;
2520 return RNP_SUCCESS;
2521 }
2522 FFI_GUARD
2523
2524 rnp_result_t
rnp_op_encrypt_add_recipient(rnp_op_encrypt_t op,rnp_key_handle_t handle)2525 rnp_op_encrypt_add_recipient(rnp_op_encrypt_t op, rnp_key_handle_t handle)
2526 try {
2527 // checks
2528 if (!op || !handle) {
2529 return RNP_ERROR_NULL_POINTER;
2530 }
2531
2532 pgp_key_t *key = find_suitable_key(PGP_OP_ENCRYPT,
2533 get_key_prefer_public(handle),
2534 &handle->ffi->key_provider,
2535 PGP_KF_ENCRYPT);
2536 if (!key) {
2537 key = get_key_prefer_public(handle);
2538 }
2539 op->rnpctx.recipients.push_back(key);
2540 return RNP_SUCCESS;
2541 }
2542 FFI_GUARD
2543
2544 rnp_result_t
rnp_op_encrypt_add_signature(rnp_op_encrypt_t op,rnp_key_handle_t key,rnp_op_sign_signature_t * sig)2545 rnp_op_encrypt_add_signature(rnp_op_encrypt_t op,
2546 rnp_key_handle_t key,
2547 rnp_op_sign_signature_t *sig)
2548 try {
2549 if (!op) {
2550 return RNP_ERROR_NULL_POINTER;
2551 }
2552 return rnp_op_add_signature(op->ffi, op->signatures, key, op->rnpctx, sig);
2553 }
2554 FFI_GUARD
2555
2556 rnp_result_t
rnp_op_encrypt_set_hash(rnp_op_encrypt_t op,const char * hash)2557 rnp_op_encrypt_set_hash(rnp_op_encrypt_t op, const char *hash)
2558 try {
2559 if (!op) {
2560 return RNP_ERROR_NULL_POINTER;
2561 }
2562 return rnp_op_set_hash(op->ffi, op->rnpctx, hash);
2563 }
2564 FFI_GUARD
2565
2566 rnp_result_t
rnp_op_encrypt_set_creation_time(rnp_op_encrypt_t op,uint32_t create)2567 rnp_op_encrypt_set_creation_time(rnp_op_encrypt_t op, uint32_t create)
2568 try {
2569 if (!op) {
2570 return RNP_ERROR_NULL_POINTER;
2571 }
2572 return rnp_op_set_creation_time(op->rnpctx, create);
2573 }
2574 FFI_GUARD
2575
2576 rnp_result_t
rnp_op_encrypt_set_expiration_time(rnp_op_encrypt_t op,uint32_t expire)2577 rnp_op_encrypt_set_expiration_time(rnp_op_encrypt_t op, uint32_t expire)
2578 try {
2579 if (!op) {
2580 return RNP_ERROR_NULL_POINTER;
2581 }
2582 return rnp_op_set_expiration_time(op->rnpctx, expire);
2583 }
2584 FFI_GUARD
2585
2586 rnp_result_t
rnp_op_encrypt_add_password(rnp_op_encrypt_t op,const char * password,const char * s2k_hash,size_t iterations,const char * s2k_cipher)2587 rnp_op_encrypt_add_password(rnp_op_encrypt_t op,
2588 const char * password,
2589 const char * s2k_hash,
2590 size_t iterations,
2591 const char * s2k_cipher)
2592 try {
2593 // checks
2594 if (!op) {
2595 return RNP_ERROR_NULL_POINTER;
2596 }
2597 if (password && !*password) {
2598 // no blank passwords
2599 FFI_LOG(op->ffi, "Blank password");
2600 return RNP_ERROR_BAD_PARAMETERS;
2601 }
2602
2603 // set some defaults
2604 if (!s2k_hash) {
2605 s2k_hash = DEFAULT_HASH_ALG;
2606 }
2607 if (!s2k_cipher) {
2608 s2k_cipher = DEFAULT_SYMM_ALG;
2609 }
2610 // parse
2611 pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN;
2612 if (!str_to_hash_alg(s2k_hash, &hash_alg)) {
2613 FFI_LOG(op->ffi, "Invalid hash: %s", s2k_hash);
2614 return RNP_ERROR_BAD_PARAMETERS;
2615 }
2616 pgp_symm_alg_t symm_alg = PGP_SA_UNKNOWN;
2617 if (!str_to_cipher(s2k_cipher, &symm_alg)) {
2618 FFI_LOG(op->ffi, "Invalid cipher: %s", s2k_cipher);
2619 return RNP_ERROR_BAD_PARAMETERS;
2620 }
2621 try {
2622 rnp::secure_vector<char> ask_pass(MAX_PASSWORD_LENGTH, '\0');
2623 if (!password) {
2624 pgp_password_ctx_t pswdctx = {.op = PGP_OP_ENCRYPT_SYM, .key = NULL};
2625 if (!pgp_request_password(
2626 &op->ffi->pass_provider, &pswdctx, ask_pass.data(), ask_pass.size())) {
2627 return RNP_ERROR_BAD_PASSWORD;
2628 }
2629 password = ask_pass.data();
2630 }
2631 return rnp_ctx_add_encryption_password(
2632 op->rnpctx, password, hash_alg, symm_alg, iterations);
2633 } catch (const std::exception &e) {
2634 FFI_LOG(op->ffi, "%s", e.what());
2635 return RNP_ERROR_OUT_OF_MEMORY;
2636 }
2637 }
2638 FFI_GUARD
2639
2640 rnp_result_t
rnp_op_encrypt_set_armor(rnp_op_encrypt_t op,bool armored)2641 rnp_op_encrypt_set_armor(rnp_op_encrypt_t op, bool armored)
2642 try {
2643 // checks
2644 if (!op) {
2645 return RNP_ERROR_NULL_POINTER;
2646 }
2647 return rnp_op_set_armor(op->rnpctx, armored);
2648 }
2649 FFI_GUARD
2650
2651 rnp_result_t
rnp_op_encrypt_set_cipher(rnp_op_encrypt_t op,const char * cipher)2652 rnp_op_encrypt_set_cipher(rnp_op_encrypt_t op, const char *cipher)
2653 try {
2654 // checks
2655 if (!op || !cipher) {
2656 return RNP_ERROR_NULL_POINTER;
2657 }
2658 if (!str_to_cipher(cipher, &op->rnpctx.ealg)) {
2659 FFI_LOG(op->ffi, "Invalid cipher: %s", cipher);
2660 return RNP_ERROR_BAD_PARAMETERS;
2661 }
2662 return RNP_SUCCESS;
2663 }
2664 FFI_GUARD
2665
2666 rnp_result_t
rnp_op_encrypt_set_aead(rnp_op_encrypt_t op,const char * alg)2667 rnp_op_encrypt_set_aead(rnp_op_encrypt_t op, const char *alg)
2668 try {
2669 // checks
2670 if (!op || !alg) {
2671 return RNP_ERROR_NULL_POINTER;
2672 }
2673 if (!str_to_aead_alg(alg, &op->rnpctx.aalg)) {
2674 FFI_LOG(op->ffi, "Invalid AEAD algorithm: %s", alg);
2675 return RNP_ERROR_BAD_PARAMETERS;
2676 }
2677 return RNP_SUCCESS;
2678 }
2679 FFI_GUARD
2680
2681 rnp_result_t
rnp_op_encrypt_set_aead_bits(rnp_op_encrypt_t op,int bits)2682 rnp_op_encrypt_set_aead_bits(rnp_op_encrypt_t op, int bits)
2683 try {
2684 if (!op) {
2685 return RNP_ERROR_NULL_POINTER;
2686 }
2687 if ((bits < 0) || (bits > 56)) {
2688 return RNP_ERROR_BAD_PARAMETERS;
2689 }
2690 op->rnpctx.abits = bits;
2691 return RNP_SUCCESS;
2692 }
2693 FFI_GUARD
2694
2695 rnp_result_t
rnp_op_encrypt_set_compression(rnp_op_encrypt_t op,const char * compression,int level)2696 rnp_op_encrypt_set_compression(rnp_op_encrypt_t op, const char *compression, int level)
2697 try {
2698 // checks
2699 if (!op) {
2700 return RNP_ERROR_NULL_POINTER;
2701 }
2702 return rnp_op_set_compression(op->ffi, op->rnpctx, compression, level);
2703 }
2704 FFI_GUARD
2705
2706 rnp_result_t
rnp_op_encrypt_set_file_name(rnp_op_encrypt_t op,const char * filename)2707 rnp_op_encrypt_set_file_name(rnp_op_encrypt_t op, const char *filename)
2708 try {
2709 if (!op) {
2710 return RNP_ERROR_NULL_POINTER;
2711 }
2712 return rnp_op_set_file_name(op->rnpctx, filename);
2713 }
2714 FFI_GUARD
2715
2716 rnp_result_t
rnp_op_encrypt_set_file_mtime(rnp_op_encrypt_t op,uint32_t mtime)2717 rnp_op_encrypt_set_file_mtime(rnp_op_encrypt_t op, uint32_t mtime)
2718 try {
2719 if (!op) {
2720 return RNP_ERROR_NULL_POINTER;
2721 }
2722 return rnp_op_set_file_mtime(op->rnpctx, mtime);
2723 }
2724 FFI_GUARD
2725
2726 static pgp_write_handler_t
pgp_write_handler(pgp_password_provider_t * pass_provider,rnp_ctx_t * rnpctx,void * param,pgp_key_provider_t * key_provider)2727 pgp_write_handler(pgp_password_provider_t *pass_provider,
2728 rnp_ctx_t * rnpctx,
2729 void * param,
2730 pgp_key_provider_t * key_provider)
2731 {
2732 pgp_write_handler_t handler;
2733 memset(&handler, 0, sizeof(handler));
2734 handler.password_provider = pass_provider;
2735 handler.ctx = rnpctx;
2736 handler.param = param;
2737 handler.key_provider = key_provider;
2738 return handler;
2739 }
2740
2741 static rnp_result_t
rnp_op_add_signatures(rnp_op_sign_signatures_t & opsigs,rnp_ctx_t & ctx)2742 rnp_op_add_signatures(rnp_op_sign_signatures_t &opsigs, rnp_ctx_t &ctx)
2743 {
2744 for (auto &sig : opsigs) {
2745 if (!sig.signer.key) {
2746 return RNP_ERROR_NO_SUITABLE_KEY;
2747 }
2748
2749 rnp_signer_info_t sinfo = sig.signer;
2750 if (!sig.hash_set) {
2751 sinfo.halg = ctx.halg;
2752 }
2753 if (!sig.expiry_set) {
2754 sinfo.sigexpire = ctx.sigexpire;
2755 }
2756 if (!sig.create_set) {
2757 sinfo.sigcreate = ctx.sigcreate;
2758 }
2759 ctx.signers.push_back(sinfo);
2760 }
2761 return RNP_SUCCESS;
2762 }
2763
2764 rnp_result_t
rnp_op_encrypt_execute(rnp_op_encrypt_t op)2765 rnp_op_encrypt_execute(rnp_op_encrypt_t op)
2766 try {
2767 // checks
2768 if (!op || !op->input || !op->output) {
2769 return RNP_ERROR_NULL_POINTER;
2770 }
2771
2772 // set the default hash alg if none was specified
2773 if (!op->rnpctx.halg) {
2774 op->rnpctx.halg = DEFAULT_PGP_HASH_ALG;
2775 }
2776 pgp_write_handler_t handler =
2777 pgp_write_handler(&op->ffi->pass_provider, &op->rnpctx, NULL, &op->ffi->key_provider);
2778
2779 rnp_result_t ret;
2780 if (!op->signatures.empty()) {
2781 if ((ret = rnp_op_add_signatures(op->signatures, op->rnpctx))) {
2782 return ret;
2783 }
2784 ret = rnp_encrypt_sign_src(&handler, &op->input->src, &op->output->dst);
2785 } else {
2786 ret = rnp_encrypt_src(&handler, &op->input->src, &op->output->dst);
2787 }
2788
2789 dst_flush(&op->output->dst);
2790 op->output->keep = ret == RNP_SUCCESS;
2791 op->input = NULL;
2792 op->output = NULL;
2793 return ret;
2794 }
2795 FFI_GUARD
2796
2797 rnp_result_t
rnp_op_encrypt_destroy(rnp_op_encrypt_t op)2798 rnp_op_encrypt_destroy(rnp_op_encrypt_t op)
2799 try {
2800 delete op;
2801 return RNP_SUCCESS;
2802 }
2803 FFI_GUARD
2804
2805 rnp_result_t
rnp_op_sign_create(rnp_op_sign_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_output_t output)2806 rnp_op_sign_create(rnp_op_sign_t *op, rnp_ffi_t ffi, rnp_input_t input, rnp_output_t output)
2807 try {
2808 // checks
2809 if (!op || !ffi || !input || !output) {
2810 return RNP_ERROR_NULL_POINTER;
2811 }
2812
2813 *op = new rnp_op_sign_st();
2814 rnp_ctx_init_ffi((*op)->rnpctx, ffi);
2815 (*op)->ffi = ffi;
2816 (*op)->input = input;
2817 (*op)->output = output;
2818 return RNP_SUCCESS;
2819 }
2820 FFI_GUARD
2821
2822 rnp_result_t
rnp_op_sign_cleartext_create(rnp_op_sign_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_output_t output)2823 rnp_op_sign_cleartext_create(rnp_op_sign_t *op,
2824 rnp_ffi_t ffi,
2825 rnp_input_t input,
2826 rnp_output_t output)
2827 try {
2828 rnp_result_t res = rnp_op_sign_create(op, ffi, input, output);
2829 if (!res) {
2830 (*op)->rnpctx.clearsign = true;
2831 }
2832 return res;
2833 }
2834 FFI_GUARD
2835
2836 rnp_result_t
rnp_op_sign_detached_create(rnp_op_sign_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_output_t signature)2837 rnp_op_sign_detached_create(rnp_op_sign_t *op,
2838 rnp_ffi_t ffi,
2839 rnp_input_t input,
2840 rnp_output_t signature)
2841 try {
2842 rnp_result_t res = rnp_op_sign_create(op, ffi, input, signature);
2843 if (!res) {
2844 (*op)->rnpctx.detached = true;
2845 }
2846 return res;
2847 }
2848 FFI_GUARD
2849
2850 rnp_result_t
rnp_op_sign_add_signature(rnp_op_sign_t op,rnp_key_handle_t key,rnp_op_sign_signature_t * sig)2851 rnp_op_sign_add_signature(rnp_op_sign_t op, rnp_key_handle_t key, rnp_op_sign_signature_t *sig)
2852 try {
2853 if (!op) {
2854 return RNP_ERROR_NULL_POINTER;
2855 }
2856 return rnp_op_add_signature(op->ffi, op->signatures, key, op->rnpctx, sig);
2857 }
2858 FFI_GUARD
2859
2860 rnp_result_t
rnp_op_sign_signature_set_hash(rnp_op_sign_signature_t sig,const char * hash)2861 rnp_op_sign_signature_set_hash(rnp_op_sign_signature_t sig, const char *hash)
2862 try {
2863 if (!sig) {
2864 return RNP_ERROR_NULL_POINTER;
2865 }
2866 if (!str_to_hash_alg(hash, &sig->signer.halg)) {
2867 FFI_LOG(sig->ffi, "Invalid hash: %s", hash);
2868 return RNP_ERROR_BAD_PARAMETERS;
2869 }
2870 sig->hash_set = true;
2871 return RNP_SUCCESS;
2872 }
2873 FFI_GUARD
2874
2875 rnp_result_t
rnp_op_sign_signature_set_creation_time(rnp_op_sign_signature_t sig,uint32_t create)2876 rnp_op_sign_signature_set_creation_time(rnp_op_sign_signature_t sig, uint32_t create)
2877 try {
2878 if (!sig) {
2879 return RNP_ERROR_NULL_POINTER;
2880 }
2881 sig->signer.sigcreate = create;
2882 sig->create_set = true;
2883 return RNP_SUCCESS;
2884 }
2885 FFI_GUARD
2886
2887 rnp_result_t
rnp_op_sign_signature_set_expiration_time(rnp_op_sign_signature_t sig,uint32_t expires)2888 rnp_op_sign_signature_set_expiration_time(rnp_op_sign_signature_t sig, uint32_t expires)
2889 try {
2890 if (!sig) {
2891 return RNP_ERROR_NULL_POINTER;
2892 }
2893 sig->signer.sigexpire = expires;
2894 sig->expiry_set = true;
2895 return RNP_SUCCESS;
2896 }
2897 FFI_GUARD
2898
2899 rnp_result_t
rnp_op_sign_set_armor(rnp_op_sign_t op,bool armored)2900 rnp_op_sign_set_armor(rnp_op_sign_t op, bool armored)
2901 try {
2902 if (!op) {
2903 return RNP_ERROR_NULL_POINTER;
2904 }
2905 return rnp_op_set_armor(op->rnpctx, armored);
2906 }
2907 FFI_GUARD
2908
2909 rnp_result_t
rnp_op_sign_set_compression(rnp_op_sign_t op,const char * compression,int level)2910 rnp_op_sign_set_compression(rnp_op_sign_t op, const char *compression, int level)
2911 try {
2912 if (!op) {
2913 return RNP_ERROR_NULL_POINTER;
2914 }
2915 return rnp_op_set_compression(op->ffi, op->rnpctx, compression, level);
2916 }
2917 FFI_GUARD
2918
2919 rnp_result_t
rnp_op_sign_set_hash(rnp_op_sign_t op,const char * hash)2920 rnp_op_sign_set_hash(rnp_op_sign_t op, const char *hash)
2921 try {
2922 if (!op) {
2923 return RNP_ERROR_NULL_POINTER;
2924 }
2925 return rnp_op_set_hash(op->ffi, op->rnpctx, hash);
2926 }
2927 FFI_GUARD
2928
2929 rnp_result_t
rnp_op_sign_set_creation_time(rnp_op_sign_t op,uint32_t create)2930 rnp_op_sign_set_creation_time(rnp_op_sign_t op, uint32_t create)
2931 try {
2932 if (!op) {
2933 return RNP_ERROR_NULL_POINTER;
2934 }
2935 return rnp_op_set_creation_time(op->rnpctx, create);
2936 }
2937 FFI_GUARD
2938
2939 rnp_result_t
rnp_op_sign_set_expiration_time(rnp_op_sign_t op,uint32_t expire)2940 rnp_op_sign_set_expiration_time(rnp_op_sign_t op, uint32_t expire)
2941 try {
2942 if (!op) {
2943 return RNP_ERROR_NULL_POINTER;
2944 }
2945 return rnp_op_set_expiration_time(op->rnpctx, expire);
2946 }
2947 FFI_GUARD
2948
2949 rnp_result_t
rnp_op_sign_set_file_name(rnp_op_sign_t op,const char * filename)2950 rnp_op_sign_set_file_name(rnp_op_sign_t op, const char *filename)
2951 try {
2952 if (!op) {
2953 return RNP_ERROR_NULL_POINTER;
2954 }
2955 return rnp_op_set_file_name(op->rnpctx, filename);
2956 }
2957 FFI_GUARD
2958
2959 rnp_result_t
rnp_op_sign_set_file_mtime(rnp_op_sign_t op,uint32_t mtime)2960 rnp_op_sign_set_file_mtime(rnp_op_sign_t op, uint32_t mtime)
2961 try {
2962 if (!op) {
2963 return RNP_ERROR_NULL_POINTER;
2964 }
2965 return rnp_op_set_file_mtime(op->rnpctx, mtime);
2966 }
2967 FFI_GUARD
2968
2969 rnp_result_t
rnp_op_sign_execute(rnp_op_sign_t op)2970 rnp_op_sign_execute(rnp_op_sign_t op)
2971 try {
2972 // checks
2973 if (!op || !op->input || !op->output) {
2974 return RNP_ERROR_NULL_POINTER;
2975 }
2976
2977 // set the default hash alg if none was specified
2978 if (!op->rnpctx.halg) {
2979 op->rnpctx.halg = DEFAULT_PGP_HASH_ALG;
2980 }
2981 pgp_write_handler_t handler =
2982 pgp_write_handler(&op->ffi->pass_provider, &op->rnpctx, NULL, &op->ffi->key_provider);
2983
2984 rnp_result_t ret;
2985 if ((ret = rnp_op_add_signatures(op->signatures, op->rnpctx))) {
2986 return ret;
2987 }
2988 ret = rnp_sign_src(&handler, &op->input->src, &op->output->dst);
2989
2990 dst_flush(&op->output->dst);
2991 op->output->keep = ret == RNP_SUCCESS;
2992 op->input = NULL;
2993 op->output = NULL;
2994 return ret;
2995 }
2996 FFI_GUARD
2997
2998 rnp_result_t
rnp_op_sign_destroy(rnp_op_sign_t op)2999 rnp_op_sign_destroy(rnp_op_sign_t op)
3000 try {
3001 delete op;
3002 return RNP_SUCCESS;
3003 }
3004 FFI_GUARD
3005
3006 static void
rnp_op_verify_on_signatures(const std::vector<pgp_signature_info_t> & sigs,void * param)3007 rnp_op_verify_on_signatures(const std::vector<pgp_signature_info_t> &sigs, void *param)
3008 {
3009 rnp_op_verify_t op = (rnp_op_verify_t) param;
3010
3011 try {
3012 /* in case we have multiple signed layers */
3013 delete[] op->signatures;
3014 op->signatures = new rnp_op_verify_signature_st[sigs.size()];
3015 } catch (const std::exception &e) {
3016 FFI_LOG(op->ffi, "%s", e.what());
3017 return;
3018 }
3019 op->signature_count = sigs.size();
3020
3021 size_t i = 0;
3022 for (const auto &sinfo : sigs) {
3023 rnp_op_verify_signature_t res = &op->signatures[i++];
3024 /* sinfo.sig may be NULL */
3025 if (sinfo.sig) {
3026 try {
3027 res->sig_pkt = *sinfo.sig;
3028 } catch (const std::exception &e) {
3029 FFI_LOG(op->ffi, "%s", e.what());
3030 }
3031 }
3032
3033 if (sinfo.unknown) {
3034 res->verify_status = RNP_ERROR_SIGNATURE_INVALID;
3035 } else if (sinfo.valid) {
3036 res->verify_status = sinfo.expired ? RNP_ERROR_SIGNATURE_EXPIRED : RNP_SUCCESS;
3037 } else {
3038 res->verify_status =
3039 sinfo.no_signer ? RNP_ERROR_KEY_NOT_FOUND : RNP_ERROR_SIGNATURE_INVALID;
3040 }
3041 res->ffi = op->ffi;
3042 }
3043 }
3044
3045 static bool
rnp_verify_src_provider(pgp_parse_handler_t * handler,pgp_source_t * src)3046 rnp_verify_src_provider(pgp_parse_handler_t *handler, pgp_source_t *src)
3047 {
3048 /* this one is called only when input for detached signature is needed */
3049 rnp_op_verify_t op = (rnp_op_verify_t) handler->param;
3050 if (!op->detached_input) {
3051 return false;
3052 }
3053 *src = op->detached_input->src;
3054 /* we should give ownership on src to caller */
3055 memset(&op->detached_input->src, 0, sizeof(op->detached_input->src));
3056 return true;
3057 };
3058
3059 static bool
rnp_verify_dest_provider(pgp_parse_handler_t * handler,pgp_dest_t ** dst,bool * closedst,const char * filename,uint32_t mtime)3060 rnp_verify_dest_provider(pgp_parse_handler_t *handler,
3061 pgp_dest_t ** dst,
3062 bool * closedst,
3063 const char * filename,
3064 uint32_t mtime)
3065 {
3066 rnp_op_verify_t op = (rnp_op_verify_t) handler->param;
3067 if (!op->output) {
3068 return false;
3069 }
3070 *dst = &(op->output->dst);
3071 *closedst = false;
3072 op->filename = filename ? strdup(filename) : NULL;
3073 op->file_mtime = mtime;
3074 return true;
3075 }
3076
3077 static void
recipient_handle_from_pk_sesskey(rnp_recipient_handle_t handle,const pgp_pk_sesskey_t & sesskey)3078 recipient_handle_from_pk_sesskey(rnp_recipient_handle_t handle,
3079 const pgp_pk_sesskey_t &sesskey)
3080 {
3081 static_assert(sizeof(handle->keyid) == PGP_KEY_ID_SIZE, "Keyid size mismatch");
3082 memcpy(handle->keyid, sesskey.key_id.data(), PGP_KEY_ID_SIZE);
3083 handle->palg = sesskey.alg;
3084 }
3085
3086 static void
symenc_handle_from_sk_sesskey(rnp_symenc_handle_t handle,const pgp_sk_sesskey_t & sesskey)3087 symenc_handle_from_sk_sesskey(rnp_symenc_handle_t handle, const pgp_sk_sesskey_t &sesskey)
3088 {
3089 handle->alg = sesskey.alg;
3090 handle->halg = sesskey.s2k.hash_alg;
3091 handle->s2k_type = sesskey.s2k.specifier;
3092 if (sesskey.s2k.specifier == PGP_S2KS_ITERATED_AND_SALTED) {
3093 handle->iterations = pgp_s2k_decode_iterations(sesskey.s2k.iterations);
3094 } else {
3095 handle->iterations = 1;
3096 }
3097 handle->aalg = sesskey.aalg;
3098 }
3099
3100 static void
rnp_verify_on_recipients(const std::vector<pgp_pk_sesskey_t> & recipients,const std::vector<pgp_sk_sesskey_t> & passwords,void * param)3101 rnp_verify_on_recipients(const std::vector<pgp_pk_sesskey_t> &recipients,
3102 const std::vector<pgp_sk_sesskey_t> &passwords,
3103 void * param)
3104 {
3105 rnp_op_verify_t op = (rnp_op_verify_t) param;
3106 /* store only top-level encrypted stream recipients info for now */
3107 if (op->encrypted_layers++) {
3108 return;
3109 }
3110 if (!recipients.empty()) {
3111 op->recipients =
3112 (rnp_recipient_handle_t) calloc(recipients.size(), sizeof(*op->recipients));
3113 if (!op->recipients) {
3114 FFI_LOG(op->ffi, "allocation failed");
3115 return;
3116 }
3117 for (size_t i = 0; i < recipients.size(); i++) {
3118 recipient_handle_from_pk_sesskey(&op->recipients[i], recipients[i]);
3119 }
3120 }
3121 op->recipient_count = recipients.size();
3122 if (!passwords.empty()) {
3123 op->symencs = (rnp_symenc_handle_t) calloc(passwords.size(), sizeof(*op->symencs));
3124 if (!op->symencs) {
3125 FFI_LOG(op->ffi, "allocation failed");
3126 return;
3127 }
3128 for (size_t i = 0; i < passwords.size(); i++) {
3129 symenc_handle_from_sk_sesskey(&op->symencs[i], passwords[i]);
3130 }
3131 }
3132 op->symenc_count = passwords.size();
3133 }
3134
3135 static void
rnp_verify_on_decryption_start(pgp_pk_sesskey_t * pubenc,pgp_sk_sesskey_t * symenc,void * param)3136 rnp_verify_on_decryption_start(pgp_pk_sesskey_t *pubenc, pgp_sk_sesskey_t *symenc, void *param)
3137 {
3138 rnp_op_verify_t op = (rnp_op_verify_t) param;
3139 /* store only top-level encrypted stream info */
3140 if (op->encrypted_layers > 1) {
3141 return;
3142 }
3143 if (pubenc) {
3144 op->used_recipient = (rnp_recipient_handle_t) calloc(1, sizeof(*op->used_recipient));
3145 if (!op->used_recipient) {
3146 FFI_LOG(op->ffi, "allocation failed");
3147 return;
3148 }
3149 recipient_handle_from_pk_sesskey(op->used_recipient, *pubenc);
3150 return;
3151 }
3152 if (symenc) {
3153 op->used_symenc = (rnp_symenc_handle_t) calloc(1, sizeof(*op->used_symenc));
3154 if (!op->used_symenc) {
3155 FFI_LOG(op->ffi, "allocation failed");
3156 return;
3157 }
3158 symenc_handle_from_sk_sesskey(op->used_symenc, *symenc);
3159 return;
3160 }
3161 FFI_LOG(op->ffi, "Warning! Both pubenc and symenc are NULL.");
3162 }
3163
3164 static void
rnp_verify_on_decryption_info(bool mdc,pgp_aead_alg_t aead,pgp_symm_alg_t salg,void * param)3165 rnp_verify_on_decryption_info(bool mdc, pgp_aead_alg_t aead, pgp_symm_alg_t salg, void *param)
3166 {
3167 rnp_op_verify_t op = (rnp_op_verify_t) param;
3168 /* store only top-level encrypted stream info for now */
3169 if (op->encrypted_layers > 1) {
3170 return;
3171 }
3172 op->mdc = mdc;
3173 op->aead = aead;
3174 op->salg = salg;
3175 op->encrypted = true;
3176 }
3177
3178 static void
rnp_verify_on_decryption_done(bool validated,void * param)3179 rnp_verify_on_decryption_done(bool validated, void *param)
3180 {
3181 rnp_op_verify_t op = (rnp_op_verify_t) param;
3182 if (op->encrypted_layers > 1) {
3183 return;
3184 }
3185 op->validated = validated;
3186 }
3187
3188 rnp_result_t
rnp_op_verify_create(rnp_op_verify_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_output_t output)3189 rnp_op_verify_create(rnp_op_verify_t *op,
3190 rnp_ffi_t ffi,
3191 rnp_input_t input,
3192 rnp_output_t output)
3193 try {
3194 if (!op || !ffi || !input || !output) {
3195 return RNP_ERROR_NULL_POINTER;
3196 }
3197
3198 *op = new rnp_op_verify_st();
3199 rnp_ctx_init_ffi((*op)->rnpctx, ffi);
3200 (*op)->ffi = ffi;
3201 (*op)->input = input;
3202 (*op)->output = output;
3203
3204 return RNP_SUCCESS;
3205 }
3206 FFI_GUARD
3207
3208 rnp_result_t
rnp_op_verify_detached_create(rnp_op_verify_t * op,rnp_ffi_t ffi,rnp_input_t input,rnp_input_t signature)3209 rnp_op_verify_detached_create(rnp_op_verify_t *op,
3210 rnp_ffi_t ffi,
3211 rnp_input_t input,
3212 rnp_input_t signature)
3213 try {
3214 if (!op || !ffi || !input || !signature) {
3215 return RNP_ERROR_NULL_POINTER;
3216 }
3217
3218 *op = new rnp_op_verify_st();
3219 rnp_ctx_init_ffi((*op)->rnpctx, ffi);
3220 (*op)->rnpctx.detached = true;
3221 (*op)->ffi = ffi;
3222 (*op)->input = signature;
3223 (*op)->detached_input = input;
3224
3225 return RNP_SUCCESS;
3226 }
3227 FFI_GUARD
3228
3229 rnp_result_t
rnp_op_verify_execute(rnp_op_verify_t op)3230 rnp_op_verify_execute(rnp_op_verify_t op)
3231 try {
3232 if (!op) {
3233 return RNP_ERROR_NULL_POINTER;
3234 }
3235
3236 pgp_parse_handler_t handler;
3237
3238 handler.password_provider = &op->ffi->pass_provider;
3239 handler.key_provider = &op->ffi->key_provider;
3240 handler.on_signatures = rnp_op_verify_on_signatures;
3241 handler.src_provider = rnp_verify_src_provider;
3242 handler.dest_provider = rnp_verify_dest_provider;
3243 handler.on_recipients = rnp_verify_on_recipients;
3244 handler.on_decryption_start = rnp_verify_on_decryption_start;
3245 handler.on_decryption_info = rnp_verify_on_decryption_info;
3246 handler.on_decryption_done = rnp_verify_on_decryption_done;
3247 handler.param = op;
3248 handler.ctx = &op->rnpctx;
3249
3250 rnp_result_t ret = process_pgp_source(&handler, op->input->src);
3251 if (op->output) {
3252 dst_flush(&op->output->dst);
3253 op->output->keep = ret == RNP_SUCCESS;
3254 }
3255 return ret;
3256 }
3257 FFI_GUARD
3258
3259 rnp_result_t
rnp_op_verify_get_signature_count(rnp_op_verify_t op,size_t * count)3260 rnp_op_verify_get_signature_count(rnp_op_verify_t op, size_t *count)
3261 try {
3262 if (!op || !count) {
3263 return RNP_ERROR_NULL_POINTER;
3264 }
3265
3266 *count = op->signature_count;
3267 return RNP_SUCCESS;
3268 }
3269 FFI_GUARD
3270
3271 rnp_result_t
rnp_op_verify_get_signature_at(rnp_op_verify_t op,size_t idx,rnp_op_verify_signature_t * sig)3272 rnp_op_verify_get_signature_at(rnp_op_verify_t op, size_t idx, rnp_op_verify_signature_t *sig)
3273 try {
3274 if (!op || !sig) {
3275 return RNP_ERROR_NULL_POINTER;
3276 }
3277 if (idx >= op->signature_count) {
3278 FFI_LOG(op->ffi, "Invalid signature index: %zu", idx);
3279 return RNP_ERROR_BAD_PARAMETERS;
3280 }
3281 *sig = &op->signatures[idx];
3282 return RNP_SUCCESS;
3283 }
3284 FFI_GUARD
3285
3286 rnp_result_t
rnp_op_verify_get_file_info(rnp_op_verify_t op,char ** filename,uint32_t * mtime)3287 rnp_op_verify_get_file_info(rnp_op_verify_t op, char **filename, uint32_t *mtime)
3288 try {
3289 if (!op) {
3290 return RNP_ERROR_NULL_POINTER;
3291 }
3292 if (mtime) {
3293 *mtime = op->file_mtime;
3294 }
3295 if (filename) {
3296 if (op->filename) {
3297 *filename = strdup(op->filename);
3298 } else {
3299 *filename = NULL;
3300 }
3301 }
3302 return RNP_SUCCESS;
3303 }
3304 FFI_GUARD
3305
3306 static const char *
get_protection_mode(rnp_op_verify_t op)3307 get_protection_mode(rnp_op_verify_t op)
3308 {
3309 if (!op->encrypted) {
3310 return "none";
3311 }
3312 if (op->mdc) {
3313 return "cfb-mdc";
3314 }
3315 if (op->aead == PGP_AEAD_NONE) {
3316 return "cfb";
3317 }
3318 switch (op->aead) {
3319 case PGP_AEAD_EAX:
3320 return "aead-eax";
3321 case PGP_AEAD_OCB:
3322 return "aead-ocb";
3323 default:
3324 return "aead-unknown";
3325 }
3326 }
3327
3328 static const char *
get_protection_cipher(rnp_op_verify_t op)3329 get_protection_cipher(rnp_op_verify_t op)
3330 {
3331 if (!op->encrypted) {
3332 return "none";
3333 }
3334 return id_str_pair::lookup(symm_alg_map, op->salg);
3335 }
3336
3337 rnp_result_t
rnp_op_verify_get_protection_info(rnp_op_verify_t op,char ** mode,char ** cipher,bool * valid)3338 rnp_op_verify_get_protection_info(rnp_op_verify_t op, char **mode, char **cipher, bool *valid)
3339 try {
3340 if (!op || (!mode && !cipher && !valid)) {
3341 return RNP_ERROR_NULL_POINTER;
3342 }
3343
3344 if (mode) {
3345 *mode = strdup(get_protection_mode(op));
3346 if (!*mode) {
3347 return RNP_ERROR_OUT_OF_MEMORY;
3348 }
3349 }
3350 if (cipher) {
3351 *cipher = strdup(get_protection_cipher(op));
3352 if (!*cipher) {
3353 return RNP_ERROR_OUT_OF_MEMORY;
3354 }
3355 }
3356 if (valid) {
3357 *valid = op->validated;
3358 }
3359 return RNP_SUCCESS;
3360 }
3361 FFI_GUARD
3362
3363 rnp_result_t
rnp_op_verify_get_recipient_count(rnp_op_verify_t op,size_t * count)3364 rnp_op_verify_get_recipient_count(rnp_op_verify_t op, size_t *count)
3365 try {
3366 if (!op || !count) {
3367 return RNP_ERROR_NULL_POINTER;
3368 }
3369 *count = op->recipient_count;
3370 return RNP_SUCCESS;
3371 }
3372 FFI_GUARD
3373
3374 rnp_result_t
rnp_op_verify_get_used_recipient(rnp_op_verify_t op,rnp_recipient_handle_t * recipient)3375 rnp_op_verify_get_used_recipient(rnp_op_verify_t op, rnp_recipient_handle_t *recipient)
3376 try {
3377 if (!op || !recipient) {
3378 return RNP_ERROR_NULL_POINTER;
3379 }
3380 *recipient = op->used_recipient;
3381 return RNP_SUCCESS;
3382 }
3383 FFI_GUARD
3384
3385 rnp_result_t
rnp_op_verify_get_recipient_at(rnp_op_verify_t op,size_t idx,rnp_recipient_handle_t * recipient)3386 rnp_op_verify_get_recipient_at(rnp_op_verify_t op,
3387 size_t idx,
3388 rnp_recipient_handle_t *recipient)
3389 try {
3390 if (!op || !recipient) {
3391 return RNP_ERROR_NULL_POINTER;
3392 }
3393 if (idx >= op->recipient_count) {
3394 return RNP_ERROR_BAD_PARAMETERS;
3395 }
3396 *recipient = &op->recipients[idx];
3397 return RNP_SUCCESS;
3398 }
3399 FFI_GUARD
3400
3401 rnp_result_t
rnp_recipient_get_keyid(rnp_recipient_handle_t recipient,char ** keyid)3402 rnp_recipient_get_keyid(rnp_recipient_handle_t recipient, char **keyid)
3403 try {
3404 if (!recipient || !keyid) {
3405 return RNP_ERROR_NULL_POINTER;
3406 }
3407 static_assert(sizeof(recipient->keyid) == PGP_KEY_ID_SIZE,
3408 "rnp_recipient_handle_t.keyid size mismatch");
3409 return hex_encode_value(recipient->keyid, PGP_KEY_ID_SIZE, keyid);
3410 }
3411 FFI_GUARD
3412
3413 rnp_result_t
rnp_recipient_get_alg(rnp_recipient_handle_t recipient,char ** alg)3414 rnp_recipient_get_alg(rnp_recipient_handle_t recipient, char **alg)
3415 try {
3416 if (!recipient || !alg) {
3417 return RNP_ERROR_NULL_POINTER;
3418 }
3419 return get_map_value(pubkey_alg_map, recipient->palg, alg);
3420 }
3421 FFI_GUARD
3422
3423 rnp_result_t
rnp_op_verify_get_symenc_count(rnp_op_verify_t op,size_t * count)3424 rnp_op_verify_get_symenc_count(rnp_op_verify_t op, size_t *count)
3425 try {
3426 if (!op || !count) {
3427 return RNP_ERROR_NULL_POINTER;
3428 }
3429 *count = op->symenc_count;
3430 return RNP_SUCCESS;
3431 }
3432 FFI_GUARD
3433
3434 rnp_result_t
rnp_op_verify_get_used_symenc(rnp_op_verify_t op,rnp_symenc_handle_t * symenc)3435 rnp_op_verify_get_used_symenc(rnp_op_verify_t op, rnp_symenc_handle_t *symenc)
3436 try {
3437 if (!op || !symenc) {
3438 return RNP_ERROR_NULL_POINTER;
3439 }
3440 *symenc = op->used_symenc;
3441 return RNP_SUCCESS;
3442 }
3443 FFI_GUARD
3444
3445 rnp_result_t
rnp_op_verify_get_symenc_at(rnp_op_verify_t op,size_t idx,rnp_symenc_handle_t * symenc)3446 rnp_op_verify_get_symenc_at(rnp_op_verify_t op, size_t idx, rnp_symenc_handle_t *symenc)
3447 try {
3448 if (!op || !symenc) {
3449 return RNP_ERROR_NULL_POINTER;
3450 }
3451 if (idx >= op->symenc_count) {
3452 return RNP_ERROR_BAD_PARAMETERS;
3453 }
3454 *symenc = &op->symencs[idx];
3455 return RNP_SUCCESS;
3456 }
3457 FFI_GUARD
3458
3459 rnp_result_t
rnp_symenc_get_cipher(rnp_symenc_handle_t symenc,char ** cipher)3460 rnp_symenc_get_cipher(rnp_symenc_handle_t symenc, char **cipher)
3461 try {
3462 if (!symenc || !cipher) {
3463 return RNP_ERROR_NULL_POINTER;
3464 }
3465 return get_map_value(symm_alg_map, symenc->alg, cipher);
3466 }
3467 FFI_GUARD
3468
3469 rnp_result_t
rnp_symenc_get_aead_alg(rnp_symenc_handle_t symenc,char ** alg)3470 rnp_symenc_get_aead_alg(rnp_symenc_handle_t symenc, char **alg)
3471 try {
3472 if (!symenc || !alg) {
3473 return RNP_ERROR_NULL_POINTER;
3474 }
3475 return get_map_value(aead_alg_map, symenc->aalg, alg);
3476 }
3477 FFI_GUARD
3478
3479 rnp_result_t
rnp_symenc_get_hash_alg(rnp_symenc_handle_t symenc,char ** alg)3480 rnp_symenc_get_hash_alg(rnp_symenc_handle_t symenc, char **alg)
3481 try {
3482 if (!symenc || !alg) {
3483 return RNP_ERROR_NULL_POINTER;
3484 }
3485 return get_map_value(hash_alg_map, symenc->halg, alg);
3486 }
3487 FFI_GUARD
3488
3489 rnp_result_t
rnp_symenc_get_s2k_type(rnp_symenc_handle_t symenc,char ** type)3490 rnp_symenc_get_s2k_type(rnp_symenc_handle_t symenc, char **type)
3491 try {
3492 if (!symenc || !type) {
3493 return RNP_ERROR_NULL_POINTER;
3494 }
3495 return get_map_value(s2k_type_map, symenc->s2k_type, type);
3496 }
3497 FFI_GUARD
3498
3499 rnp_result_t
rnp_symenc_get_s2k_iterations(rnp_symenc_handle_t symenc,uint32_t * iterations)3500 rnp_symenc_get_s2k_iterations(rnp_symenc_handle_t symenc, uint32_t *iterations)
3501 try {
3502 if (!symenc || !iterations) {
3503 return RNP_ERROR_NULL_POINTER;
3504 }
3505 *iterations = symenc->iterations;
3506 return RNP_SUCCESS;
3507 }
3508 FFI_GUARD
3509
3510 rnp_result_t
rnp_op_verify_destroy(rnp_op_verify_t op)3511 rnp_op_verify_destroy(rnp_op_verify_t op)
3512 try {
3513 delete op;
3514 return RNP_SUCCESS;
3515 }
3516 FFI_GUARD
3517
~rnp_op_verify_st()3518 rnp_op_verify_st::~rnp_op_verify_st()
3519 {
3520 delete[] signatures;
3521 free(filename);
3522 free(recipients);
3523 free(used_recipient);
3524 free(symencs);
3525 free(used_symenc);
3526 }
3527
3528 rnp_result_t
rnp_op_verify_signature_get_status(rnp_op_verify_signature_t sig)3529 rnp_op_verify_signature_get_status(rnp_op_verify_signature_t sig)
3530 try {
3531 if (!sig) {
3532 return RNP_ERROR_NULL_POINTER;
3533 }
3534 return sig->verify_status;
3535 }
3536 FFI_GUARD
3537
3538 rnp_result_t
rnp_op_verify_signature_get_handle(rnp_op_verify_signature_t sig,rnp_signature_handle_t * handle)3539 rnp_op_verify_signature_get_handle(rnp_op_verify_signature_t sig,
3540 rnp_signature_handle_t * handle)
3541 try {
3542 if (!sig || !handle) {
3543 return RNP_ERROR_NULL_POINTER;
3544 }
3545
3546 *handle = (rnp_signature_handle_t) calloc(1, sizeof(**handle));
3547 if (!*handle) {
3548 return RNP_ERROR_OUT_OF_MEMORY;
3549 }
3550
3551 try {
3552 (*handle)->sig = new pgp_subsig_t(sig->sig_pkt);
3553 } catch (const std::exception &e) {
3554 FFI_LOG(sig->ffi, "%s", e.what());
3555 free(*handle);
3556 return RNP_ERROR_OUT_OF_MEMORY;
3557 }
3558 (*handle)->ffi = sig->ffi;
3559 (*handle)->key = NULL;
3560 (*handle)->own_sig = true;
3561 return RNP_SUCCESS;
3562 }
3563 FFI_GUARD
3564
3565 rnp_result_t
rnp_op_verify_signature_get_hash(rnp_op_verify_signature_t sig,char ** hash)3566 rnp_op_verify_signature_get_hash(rnp_op_verify_signature_t sig, char **hash)
3567 try {
3568 if (!sig || !hash) {
3569 return RNP_ERROR_NULL_POINTER;
3570 }
3571 return get_map_value(hash_alg_map, sig->sig_pkt.halg, hash);
3572 }
3573 FFI_GUARD
3574
3575 rnp_result_t
rnp_op_verify_signature_get_key(rnp_op_verify_signature_t sig,rnp_key_handle_t * key)3576 rnp_op_verify_signature_get_key(rnp_op_verify_signature_t sig, rnp_key_handle_t *key)
3577 try {
3578 rnp_ffi_t ffi = sig->ffi;
3579 pgp_key_search_t search = {};
3580
3581 if (!sig->sig_pkt.has_keyid()) {
3582 return RNP_ERROR_BAD_PARAMETERS;
3583 }
3584 search.by.keyid = sig->sig_pkt.keyid();
3585 // create a search (since we'll use this later anyways)
3586 search.type = PGP_KEY_SEARCH_KEYID;
3587
3588 // search the stores
3589 pgp_key_t *pub = rnp_key_store_search(ffi->pubring, &search, NULL);
3590 pgp_key_t *sec = rnp_key_store_search(ffi->secring, &search, NULL);
3591 if (!pub && !sec) {
3592 return RNP_ERROR_KEY_NOT_FOUND;
3593 }
3594
3595 struct rnp_key_handle_st *handle = (rnp_key_handle_st *) calloc(1, sizeof(*handle));
3596 if (!handle) {
3597 return RNP_ERROR_OUT_OF_MEMORY;
3598 }
3599 handle->ffi = ffi;
3600 handle->pub = pub;
3601 handle->sec = sec;
3602 handle->locator = search;
3603 *key = handle;
3604 return RNP_SUCCESS;
3605 }
3606 FFI_GUARD
3607
3608 rnp_result_t
rnp_op_verify_signature_get_times(rnp_op_verify_signature_t sig,uint32_t * create,uint32_t * expires)3609 rnp_op_verify_signature_get_times(rnp_op_verify_signature_t sig,
3610 uint32_t * create,
3611 uint32_t * expires)
3612 try {
3613 if (create) {
3614 *create = sig->sig_pkt.creation();
3615 }
3616 if (expires) {
3617 *expires = sig->sig_pkt.expiration();
3618 }
3619
3620 return RNP_SUCCESS;
3621 }
3622 FFI_GUARD
3623
3624 static bool
rnp_decrypt_dest_provider(pgp_parse_handler_t * handler,pgp_dest_t ** dst,bool * closedst,const char * filename,uint32_t mtime)3625 rnp_decrypt_dest_provider(pgp_parse_handler_t *handler,
3626 pgp_dest_t ** dst,
3627 bool * closedst,
3628 const char * filename,
3629 uint32_t mtime)
3630 {
3631 *dst = &((rnp_output_t) handler->param)->dst;
3632 *closedst = false;
3633 return true;
3634 }
3635
3636 rnp_result_t
rnp_decrypt(rnp_ffi_t ffi,rnp_input_t input,rnp_output_t output)3637 rnp_decrypt(rnp_ffi_t ffi, rnp_input_t input, rnp_output_t output)
3638 try {
3639 // checks
3640 if (!ffi || !input || !output) {
3641 return RNP_ERROR_NULL_POINTER;
3642 }
3643
3644 rnp_ctx_t rnpctx;
3645 rnp_ctx_init_ffi(rnpctx, ffi);
3646 pgp_parse_handler_t handler;
3647 memset(&handler, 0, sizeof(handler));
3648 handler.password_provider = &ffi->pass_provider;
3649 handler.key_provider = &ffi->key_provider;
3650 handler.dest_provider = rnp_decrypt_dest_provider;
3651 handler.param = output;
3652 handler.ctx = &rnpctx;
3653
3654 rnp_result_t ret = process_pgp_source(&handler, input->src);
3655 dst_flush(&output->dst);
3656 output->keep = (ret == RNP_SUCCESS);
3657 return ret;
3658 }
3659 FFI_GUARD
3660
3661 static rnp_result_t
str_to_locator(rnp_ffi_t ffi,pgp_key_search_t * locator,const char * identifier_type,const char * identifier)3662 str_to_locator(rnp_ffi_t ffi,
3663 pgp_key_search_t *locator,
3664 const char * identifier_type,
3665 const char * identifier)
3666 {
3667 // parse the identifier type
3668 locator->type = static_cast<pgp_key_search_type_t>(
3669 id_str_pair::lookup(identifier_type_map, identifier_type, PGP_KEY_SEARCH_UNKNOWN));
3670 if (locator->type == PGP_KEY_SEARCH_UNKNOWN) {
3671 FFI_LOG(ffi, "Invalid identifier type: %s", identifier_type);
3672 return RNP_ERROR_BAD_PARAMETERS;
3673 }
3674 // see what type we have
3675 switch (locator->type) {
3676 case PGP_KEY_SEARCH_USERID:
3677 if (snprintf(locator->by.userid, sizeof(locator->by.userid), "%s", identifier) >=
3678 (int) sizeof(locator->by.userid)) {
3679 FFI_LOG(ffi, "UserID too long");
3680 return RNP_ERROR_BAD_PARAMETERS;
3681 }
3682 break;
3683 case PGP_KEY_SEARCH_KEYID: {
3684 if (strlen(identifier) != (PGP_KEY_ID_SIZE * 2) ||
3685 !rnp::hex_decode(identifier, locator->by.keyid.data(), locator->by.keyid.size())) {
3686 FFI_LOG(ffi, "Invalid keyid: %s", identifier);
3687 return RNP_ERROR_BAD_PARAMETERS;
3688 }
3689 } break;
3690 case PGP_KEY_SEARCH_FINGERPRINT: {
3691 // TODO: support v5 fingerprints
3692 // Note: v2/v3 fingerprint are 16 bytes (32 chars) long.
3693 if ((strlen(identifier) != (PGP_FINGERPRINT_SIZE * 2)) && (strlen(identifier) != 32)) {
3694 FFI_LOG(ffi, "Invalid fingerprint: %s", identifier);
3695 return RNP_ERROR_BAD_PARAMETERS;
3696 }
3697 locator->by.fingerprint.length = rnp::hex_decode(
3698 identifier, locator->by.fingerprint.fingerprint, PGP_FINGERPRINT_SIZE);
3699 if (!locator->by.fingerprint.length) {
3700 FFI_LOG(ffi, "Invalid fingerprint: %s", identifier);
3701 return RNP_ERROR_BAD_PARAMETERS;
3702 }
3703 } break;
3704 case PGP_KEY_SEARCH_GRIP: {
3705 if (strlen(identifier) != (PGP_KEY_GRIP_SIZE * 2) ||
3706 !rnp::hex_decode(identifier, locator->by.grip.data(), locator->by.grip.size())) {
3707 FFI_LOG(ffi, "Invalid grip: %s", identifier);
3708 return RNP_ERROR_BAD_PARAMETERS;
3709 }
3710 } break;
3711 default:
3712 // should never happen
3713 assert(false);
3714 return RNP_ERROR_BAD_STATE;
3715 }
3716 return RNP_SUCCESS;
3717 }
3718
3719 static bool
locator_to_str(const pgp_key_search_t * locator,const char ** identifier_type,char * identifier,size_t identifier_size)3720 locator_to_str(const pgp_key_search_t *locator,
3721 const char ** identifier_type,
3722 char * identifier,
3723 size_t identifier_size)
3724 {
3725 // find the identifier type string with the map
3726 *identifier_type = id_str_pair::lookup(identifier_type_map, locator->type, NULL);
3727 if (!*identifier_type) {
3728 return false;
3729 }
3730 // fill in the actual identifier
3731 switch (locator->type) {
3732 case PGP_KEY_SEARCH_USERID:
3733 if (snprintf(identifier, identifier_size, "%s", locator->by.userid) >=
3734 (int) identifier_size) {
3735 return false;
3736 }
3737 break;
3738 case PGP_KEY_SEARCH_KEYID:
3739 if (!rnp::hex_encode(locator->by.keyid.data(),
3740 locator->by.keyid.size(),
3741 identifier,
3742 identifier_size)) {
3743 return false;
3744 }
3745 break;
3746 case PGP_KEY_SEARCH_FINGERPRINT:
3747 if (!rnp::hex_encode(locator->by.fingerprint.fingerprint,
3748 locator->by.fingerprint.length,
3749 identifier,
3750 identifier_size)) {
3751 return false;
3752 }
3753 break;
3754 case PGP_KEY_SEARCH_GRIP:
3755 if (!rnp::hex_encode(
3756 locator->by.grip.data(), locator->by.grip.size(), identifier, identifier_size)) {
3757 return false;
3758 }
3759 break;
3760 default:
3761 assert(false);
3762 return false;
3763 }
3764 return true;
3765 }
3766
3767 static rnp_result_t
rnp_locate_key_int(rnp_ffi_t ffi,const pgp_key_search_t & locator,rnp_key_handle_t * handle,bool require_secret=false)3768 rnp_locate_key_int(rnp_ffi_t ffi,
3769 const pgp_key_search_t &locator,
3770 rnp_key_handle_t * handle,
3771 bool require_secret = false)
3772 {
3773 // search pubring
3774 pgp_key_t *pub = rnp_key_store_search(ffi->pubring, &locator, NULL);
3775 // search secring
3776 pgp_key_t *sec = rnp_key_store_search(ffi->secring, &locator, NULL);
3777
3778 if (require_secret && !sec) {
3779 *handle = NULL;
3780 return RNP_SUCCESS;
3781 }
3782
3783 if (pub || sec) {
3784 *handle = (rnp_key_handle_t) malloc(sizeof(**handle));
3785 if (!*handle) {
3786 return RNP_ERROR_OUT_OF_MEMORY;
3787 }
3788 (*handle)->ffi = ffi;
3789 (*handle)->pub = pub;
3790 (*handle)->sec = sec;
3791 (*handle)->locator = locator;
3792 } else {
3793 *handle = NULL;
3794 }
3795 return RNP_SUCCESS;
3796 }
3797
3798 rnp_result_t
rnp_locate_key(rnp_ffi_t ffi,const char * identifier_type,const char * identifier,rnp_key_handle_t * handle)3799 rnp_locate_key(rnp_ffi_t ffi,
3800 const char * identifier_type,
3801 const char * identifier,
3802 rnp_key_handle_t *handle)
3803 try {
3804 // checks
3805 if (!ffi || !identifier_type || !identifier || !handle) {
3806 return RNP_ERROR_NULL_POINTER;
3807 }
3808
3809 // figure out the identifier type
3810 pgp_key_search_t locator = {(pgp_key_search_type_t) 0};
3811 rnp_result_t ret = str_to_locator(ffi, &locator, identifier_type, identifier);
3812 if (ret) {
3813 return ret;
3814 }
3815
3816 return rnp_locate_key_int(ffi, locator, handle);
3817 }
3818 FFI_GUARD
3819
3820 rnp_result_t
rnp_key_export(rnp_key_handle_t handle,rnp_output_t output,uint32_t flags)3821 rnp_key_export(rnp_key_handle_t handle, rnp_output_t output, uint32_t flags)
3822 try {
3823 pgp_dest_t * dst = NULL;
3824 pgp_dest_t armordst = {};
3825 pgp_key_t * key = NULL;
3826 rnp_key_store_t *store = NULL;
3827 bool export_subs = false;
3828 bool armored = false;
3829
3830 // checks
3831 if (!handle || !output) {
3832 return RNP_ERROR_NULL_POINTER;
3833 }
3834 dst = &output->dst;
3835 if ((flags & RNP_KEY_EXPORT_PUBLIC) && (flags & RNP_KEY_EXPORT_SECRET)) {
3836 FFI_LOG(handle->ffi, "Invalid export flags, select only public or secret, not both.");
3837 return RNP_ERROR_BAD_PARAMETERS;
3838 }
3839
3840 // handle flags
3841 if (flags & RNP_KEY_EXPORT_ARMORED) {
3842 flags &= ~RNP_KEY_EXPORT_ARMORED;
3843 armored = true;
3844 }
3845 if (flags & RNP_KEY_EXPORT_PUBLIC) {
3846 flags &= ~RNP_KEY_EXPORT_PUBLIC;
3847 key = get_key_require_public(handle);
3848 store = handle->ffi->pubring;
3849 } else if (flags & RNP_KEY_EXPORT_SECRET) {
3850 flags &= ~RNP_KEY_EXPORT_SECRET;
3851 key = get_key_require_secret(handle);
3852 store = handle->ffi->secring;
3853 } else {
3854 FFI_LOG(handle->ffi, "must specify public or secret key for export");
3855 return RNP_ERROR_BAD_PARAMETERS;
3856 }
3857 if (flags & RNP_KEY_EXPORT_SUBKEYS) {
3858 flags &= ~RNP_KEY_EXPORT_SUBKEYS;
3859 export_subs = true;
3860 }
3861 // check for any unrecognized flags
3862 if (flags) {
3863 FFI_LOG(handle->ffi, "unrecognized flags remaining: 0x%X", flags);
3864 return RNP_ERROR_BAD_PARAMETERS;
3865 }
3866 // make sure we found our key
3867 if (!key) {
3868 FFI_LOG(handle->ffi, "no suitable key found");
3869 return RNP_ERROR_NO_SUITABLE_KEY;
3870 }
3871 // only PGP packets supported for now
3872 if (key->format != PGP_KEY_STORE_GPG && key->format != PGP_KEY_STORE_KBX) {
3873 return RNP_ERROR_NOT_IMPLEMENTED;
3874 }
3875 if (armored) {
3876 auto msgtype = key->is_secret() ? PGP_ARMORED_SECRET_KEY : PGP_ARMORED_PUBLIC_KEY;
3877 rnp_result_t res = init_armored_dst(&armordst, &output->dst, msgtype);
3878 if (res) {
3879 return res;
3880 }
3881 dst = &armordst;
3882 }
3883 // write
3884 if (key->is_primary()) {
3885 // primary key, write just the primary or primary and all subkeys
3886 key->write_xfer(*dst, export_subs ? store : NULL);
3887 if (dst->werr) {
3888 return RNP_ERROR_WRITE;
3889 }
3890 } else {
3891 // subkeys flag is only valid for primary
3892 if (export_subs) {
3893 FFI_LOG(handle->ffi, "export with subkeys requested but key is not primary");
3894 return RNP_ERROR_BAD_PARAMETERS;
3895 }
3896 // subkey, write the primary + this subkey only
3897 pgp_key_t *primary = rnp_key_store_get_primary_key(store, key);
3898 if (!primary) {
3899 // shouldn't happen
3900 return RNP_ERROR_GENERIC;
3901 }
3902 primary->write_xfer(*dst);
3903 if (dst->werr) {
3904 return RNP_ERROR_WRITE;
3905 }
3906 key->write_xfer(*dst);
3907 if (dst->werr) {
3908 return RNP_ERROR_WRITE;
3909 }
3910 }
3911 if (armored) {
3912 dst_finish(&armordst);
3913 dst_close(&armordst, false);
3914 }
3915 output->keep = true;
3916 return RNP_SUCCESS;
3917 }
3918 FFI_GUARD
3919
3920 rnp_result_t
rnp_key_export_autocrypt(rnp_key_handle_t key,rnp_key_handle_t subkey,const char * uid,rnp_output_t output,uint32_t flags)3921 rnp_key_export_autocrypt(rnp_key_handle_t key,
3922 rnp_key_handle_t subkey,
3923 const char * uid,
3924 rnp_output_t output,
3925 uint32_t flags)
3926 try {
3927 if (!key || !output) {
3928 return RNP_ERROR_NULL_POINTER;
3929 }
3930 if (flags) {
3931 return RNP_ERROR_BAD_PARAMETERS;
3932 }
3933 /* Get the primary key */
3934 pgp_key_t *primary = get_key_prefer_public(key);
3935 if (!primary || !primary->is_primary() || !primary->valid() || !primary->can_sign()) {
3936 FFI_LOG(key->ffi, "No valid signing primary key");
3937 return RNP_ERROR_BAD_PARAMETERS;
3938 }
3939 /* Get encrypting subkey */
3940 pgp_key_t *sub = NULL;
3941 if (subkey) {
3942 sub = get_key_prefer_public(subkey);
3943 if (sub && (!sub->valid() || !sub->can_encrypt())) {
3944 FFI_LOG(key->ffi, "Invalid or non-encrypting subkey");
3945 return RNP_ERROR_BAD_PARAMETERS;
3946 }
3947 } else {
3948 sub = find_suitable_key(
3949 PGP_OP_ENCRYPT, primary, &key->ffi->key_provider, PGP_KF_ENCRYPT, true);
3950 }
3951 if (!sub || sub->is_primary()) {
3952 FFI_LOG(key->ffi, "No encrypting subkey");
3953 return RNP_ERROR_KEY_NOT_FOUND;
3954 }
3955 /* Get userid */
3956 size_t uididx = primary->uid_count();
3957 if (uid) {
3958 for (size_t idx = 0; idx < primary->uid_count(); idx++) {
3959 if (primary->get_uid(idx).str == uid) {
3960 uididx = idx;
3961 break;
3962 }
3963 }
3964 } else {
3965 if (primary->uid_count() > 1) {
3966 FFI_LOG(key->ffi, "Ambiguous userid");
3967 return RNP_ERROR_BAD_PARAMETERS;
3968 }
3969 uididx = 0;
3970 }
3971 if (uididx >= primary->uid_count()) {
3972 FFI_LOG(key->ffi, "Userid not found");
3973 return RNP_ERROR_BAD_PARAMETERS;
3974 }
3975
3976 if (!primary->write_autocrypt(output->dst, *sub, uididx)) {
3977 return RNP_ERROR_BAD_PARAMETERS;
3978 }
3979 return RNP_SUCCESS;
3980 }
3981 FFI_GUARD
3982
3983 static pgp_key_t *
rnp_key_get_revoker(rnp_key_handle_t key)3984 rnp_key_get_revoker(rnp_key_handle_t key)
3985 {
3986 pgp_key_t *exkey = get_key_prefer_public(key);
3987 if (!exkey) {
3988 return NULL;
3989 }
3990 if (exkey->is_subkey()) {
3991 return rnp_key_store_get_primary_key(key->ffi->secring, exkey);
3992 }
3993 // TODO: search through revocation key subpackets as well
3994 return get_key_require_secret(key);
3995 }
3996
3997 static rnp_result_t
rnp_key_get_revocation(rnp_ffi_t ffi,pgp_key_t * key,pgp_key_t * revoker,const char * hash,const char * code,const char * reason,pgp_signature_t & sig)3998 rnp_key_get_revocation(rnp_ffi_t ffi,
3999 pgp_key_t * key,
4000 pgp_key_t * revoker,
4001 const char * hash,
4002 const char * code,
4003 const char * reason,
4004 pgp_signature_t &sig)
4005 {
4006 if (!hash) {
4007 hash = DEFAULT_HASH_ALG;
4008 }
4009 pgp_hash_alg_t halg = PGP_HASH_UNKNOWN;
4010 if (!str_to_hash_alg(hash, &halg)) {
4011 FFI_LOG(ffi, "Unknown hash algorithm: %s", hash);
4012 return RNP_ERROR_BAD_PARAMETERS;
4013 }
4014 pgp_revoke_t revinfo = {};
4015 if (code && !str_to_revocation_type(code, &revinfo.code)) {
4016 FFI_LOG(ffi, "Wrong revocation code: %s", code);
4017 return RNP_ERROR_BAD_PARAMETERS;
4018 }
4019 if (revinfo.code > PGP_REVOCATION_RETIRED) {
4020 FFI_LOG(ffi, "Wrong key revocation code: %d", (int) revinfo.code);
4021 return RNP_ERROR_BAD_PARAMETERS;
4022 }
4023 if (reason) {
4024 try {
4025 revinfo.reason = reason;
4026 } catch (const std::exception &e) {
4027 FFI_LOG(ffi, "%s", e.what());
4028 return RNP_ERROR_OUT_OF_MEMORY;
4029 }
4030 }
4031 /* unlock the secret key if needed */
4032 rnp::KeyLocker revlock(*revoker);
4033 if (revoker->is_locked() && !revoker->unlock(ffi->pass_provider)) {
4034 FFI_LOG(ffi, "Failed to unlock secret key");
4035 return RNP_ERROR_BAD_PASSWORD;
4036 }
4037 try {
4038 revoker->gen_revocation(revinfo, halg, key->pkt(), sig, ffi->context);
4039 } catch (const std::exception &e) {
4040 FFI_LOG(ffi, "Failed to generate revocation signature: %s", e.what());
4041 return RNP_ERROR_BAD_STATE;
4042 }
4043 return RNP_SUCCESS;
4044 }
4045
4046 rnp_result_t
rnp_key_export_revocation(rnp_key_handle_t key,rnp_output_t output,uint32_t flags,const char * hash,const char * code,const char * reason)4047 rnp_key_export_revocation(rnp_key_handle_t key,
4048 rnp_output_t output,
4049 uint32_t flags,
4050 const char * hash,
4051 const char * code,
4052 const char * reason)
4053 try {
4054 if (!key || !key->ffi || !output) {
4055 return RNP_ERROR_NULL_POINTER;
4056 }
4057 if (flags) {
4058 return RNP_ERROR_BAD_PARAMETERS;
4059 }
4060
4061 pgp_key_t *exkey = get_key_prefer_public(key);
4062 if (!exkey || !exkey->is_primary()) {
4063 return RNP_ERROR_BAD_PARAMETERS;
4064 }
4065 pgp_key_t *revoker = rnp_key_get_revoker(key);
4066 if (!revoker) {
4067 FFI_LOG(key->ffi, "Revoker secret key not found");
4068 return RNP_ERROR_BAD_PARAMETERS;
4069 }
4070
4071 pgp_signature_t sig;
4072 rnp_result_t ret =
4073 rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, sig);
4074 if (ret) {
4075 return ret;
4076 }
4077
4078 sig.write(output->dst);
4079 ret = output->dst.werr;
4080 dst_flush(&output->dst);
4081 output->keep = !ret;
4082 return ret;
4083 }
4084 FFI_GUARD
4085
4086 rnp_result_t
rnp_key_revoke(rnp_key_handle_t key,uint32_t flags,const char * hash,const char * code,const char * reason)4087 rnp_key_revoke(
4088 rnp_key_handle_t key, uint32_t flags, const char *hash, const char *code, const char *reason)
4089 try {
4090 if (!key || !key->ffi) {
4091 return RNP_ERROR_NULL_POINTER;
4092 }
4093 if (flags) {
4094 return RNP_ERROR_BAD_PARAMETERS;
4095 }
4096
4097 pgp_key_t *exkey = get_key_prefer_public(key);
4098 if (!exkey) {
4099 return RNP_ERROR_BAD_PARAMETERS;
4100 }
4101 pgp_key_t *revoker = rnp_key_get_revoker(key);
4102 if (!revoker) {
4103 FFI_LOG(key->ffi, "Revoker secret key not found");
4104 return RNP_ERROR_BAD_PARAMETERS;
4105 }
4106
4107 pgp_signature_t sig;
4108 rnp_result_t ret =
4109 rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, sig);
4110 if (ret) {
4111 return ret;
4112 }
4113 pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
4114 pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
4115 if (key->pub) {
4116 pub_status = rnp_key_store_import_key_signature(key->ffi->pubring, key->pub, &sig);
4117 }
4118 if (key->sec) {
4119 sec_status = rnp_key_store_import_key_signature(key->ffi->secring, key->sec, &sig);
4120 }
4121
4122 if ((pub_status == PGP_SIG_IMPORT_STATUS_UNKNOWN) ||
4123 (sec_status == PGP_SIG_IMPORT_STATUS_UNKNOWN)) {
4124 return RNP_ERROR_GENERIC;
4125 }
4126 return RNP_SUCCESS;
4127 }
4128 FFI_GUARD
4129
4130 rnp_result_t
rnp_key_25519_bits_tweaked(rnp_key_handle_t key,bool * result)4131 rnp_key_25519_bits_tweaked(rnp_key_handle_t key, bool *result)
4132 try {
4133 if (!key || !result) {
4134 return RNP_ERROR_NULL_POINTER;
4135 }
4136 pgp_key_t *seckey = get_key_require_secret(key);
4137 if (!seckey || seckey->is_locked() || (seckey->alg() != PGP_PKA_ECDH) ||
4138 (seckey->curve() != PGP_CURVE_25519)) {
4139 return RNP_ERROR_BAD_PARAMETERS;
4140 }
4141 *result = x25519_bits_tweaked(seckey->material().ec);
4142 return RNP_SUCCESS;
4143 }
4144 FFI_GUARD
4145
4146 rnp_result_t
rnp_key_25519_bits_tweak(rnp_key_handle_t key)4147 rnp_key_25519_bits_tweak(rnp_key_handle_t key)
4148 try {
4149 if (!key) {
4150 return RNP_ERROR_NULL_POINTER;
4151 }
4152 pgp_key_t *seckey = get_key_require_secret(key);
4153 if (!seckey || seckey->is_protected() || (seckey->alg() != PGP_PKA_ECDH) ||
4154 (seckey->curve() != PGP_CURVE_25519)) {
4155 return RNP_ERROR_BAD_PARAMETERS;
4156 }
4157 if (!x25519_tweak_bits(seckey->pkt().material.ec)) {
4158 FFI_LOG(key->ffi, "Failed to tweak 25519 key bits.");
4159 return RNP_ERROR_BAD_STATE;
4160 }
4161 if (!seckey->write_sec_rawpkt(seckey->pkt(), "", key->ffi->rng())) {
4162 FFI_LOG(key->ffi, "Failed to update rawpkt.");
4163 return RNP_ERROR_BAD_STATE;
4164 }
4165 return RNP_SUCCESS;
4166 }
4167 FFI_GUARD
4168
4169 rnp_result_t
rnp_key_remove(rnp_key_handle_t key,uint32_t flags)4170 rnp_key_remove(rnp_key_handle_t key, uint32_t flags)
4171 try {
4172 if (!key || !key->ffi) {
4173 return RNP_ERROR_NULL_POINTER;
4174 }
4175 bool pub = false;
4176 if (flags & RNP_KEY_REMOVE_PUBLIC) {
4177 pub = true;
4178 flags &= ~RNP_KEY_REMOVE_PUBLIC;
4179 }
4180 bool sec = false;
4181 if (flags & RNP_KEY_REMOVE_SECRET) {
4182 sec = true;
4183 flags &= ~RNP_KEY_REMOVE_SECRET;
4184 }
4185 bool sub = false;
4186 if (flags & RNP_KEY_REMOVE_SUBKEYS) {
4187 sub = true;
4188 flags &= ~RNP_KEY_REMOVE_SUBKEYS;
4189 }
4190 if (flags) {
4191 FFI_LOG(key->ffi, "Unknown flags: %" PRIu32, flags);
4192 return RNP_ERROR_BAD_PARAMETERS;
4193 }
4194 if (!pub && !sec) {
4195 return RNP_ERROR_BAD_PARAMETERS;
4196 }
4197 if (sub && get_key_prefer_public(key)->is_subkey()) {
4198 return RNP_ERROR_BAD_PARAMETERS;
4199 }
4200
4201 if (pub) {
4202 if (!key->ffi->pubring || !key->pub) {
4203 return RNP_ERROR_BAD_PARAMETERS;
4204 }
4205 if (!rnp_key_store_remove_key(key->ffi->pubring, key->pub, sub)) {
4206 return RNP_ERROR_KEY_NOT_FOUND;
4207 }
4208 key->pub = NULL;
4209 }
4210 if (sec) {
4211 if (!key->ffi->secring || !key->sec) {
4212 return RNP_ERROR_BAD_PARAMETERS;
4213 }
4214 if (!rnp_key_store_remove_key(key->ffi->secring, key->sec, sub)) {
4215 return RNP_ERROR_KEY_NOT_FOUND;
4216 }
4217 key->sec = NULL;
4218 }
4219 return RNP_SUCCESS;
4220 }
4221 FFI_GUARD
4222
4223 static void
report_signature_removal(rnp_ffi_t ffi,const pgp_key_t & key,rnp_key_signatures_cb sigcb,void * app_ctx,pgp_subsig_t & keysig,bool & remove)4224 report_signature_removal(rnp_ffi_t ffi,
4225 const pgp_key_t & key,
4226 rnp_key_signatures_cb sigcb,
4227 void * app_ctx,
4228 pgp_subsig_t & keysig,
4229 bool & remove)
4230 {
4231 if (!sigcb) {
4232 return;
4233 }
4234 rnp_signature_handle_t sig = (rnp_signature_handle_t) calloc(1, sizeof(*sig));
4235 if (!sig) {
4236 FFI_LOG(ffi, "Signature handle allocation failed.");
4237 return;
4238 }
4239 sig->ffi = ffi;
4240 sig->key = &key;
4241 sig->sig = &keysig;
4242 sig->own_sig = false;
4243 uint32_t action = remove ? RNP_KEY_SIGNATURE_REMOVE : RNP_KEY_SIGNATURE_KEEP;
4244 sigcb(ffi, app_ctx, sig, &action);
4245 switch (action) {
4246 case RNP_KEY_SIGNATURE_REMOVE:
4247 remove = true;
4248 break;
4249 case RNP_KEY_SIGNATURE_KEEP:
4250 remove = false;
4251 break;
4252 default:
4253 FFI_LOG(ffi, "Invalid signature removal action: %" PRIu32, action);
4254 break;
4255 }
4256 rnp_signature_handle_destroy(sig);
4257 }
4258
4259 static bool
signature_needs_removal(rnp_ffi_t ffi,const pgp_key_t & key,pgp_subsig_t & sig,uint32_t flags)4260 signature_needs_removal(rnp_ffi_t ffi, const pgp_key_t &key, pgp_subsig_t &sig, uint32_t flags)
4261 {
4262 /* quick check for non-self signatures */
4263 bool nonself = flags & RNP_KEY_SIGNATURE_NON_SELF_SIG;
4264 if (nonself && key.is_primary() && !key.is_signer(sig)) {
4265 return true;
4266 }
4267 if (nonself && key.is_subkey()) {
4268 pgp_key_t *primary = rnp_key_store_get_primary_key(ffi->pubring, &key);
4269 if (primary && !primary->is_signer(sig)) {
4270 return true;
4271 }
4272 }
4273 /* unknown signer */
4274 pgp_key_t *signer = pgp_sig_get_signer(sig, ffi->pubring, &ffi->key_provider);
4275 if (!signer && (flags & RNP_KEY_SIGNATURE_UNKNOWN_KEY)) {
4276 return true;
4277 }
4278 /* validate signature if didn't */
4279 if (signer && !sig.validated()) {
4280 signer->validate_sig(key, sig, ffi->context);
4281 }
4282 /* we cannot check for invalid/expired if sig was not validated */
4283 if (!sig.validated()) {
4284 return false;
4285 }
4286 if ((flags & RNP_KEY_SIGNATURE_INVALID) && !sig.validity.valid) {
4287 return true;
4288 }
4289 return false;
4290 }
4291
4292 static void
remove_key_signatures(rnp_ffi_t ffi,pgp_key_t & pub,pgp_key_t * sec,uint32_t flags,rnp_key_signatures_cb sigcb,void * app_ctx)4293 remove_key_signatures(rnp_ffi_t ffi,
4294 pgp_key_t & pub,
4295 pgp_key_t * sec,
4296 uint32_t flags,
4297 rnp_key_signatures_cb sigcb,
4298 void * app_ctx)
4299 {
4300 std::vector<pgp_sig_id_t> sigs;
4301
4302 for (size_t idx = 0; idx < pub.sig_count(); idx++) {
4303 pgp_subsig_t &sig = pub.get_sig(idx);
4304 bool remove = signature_needs_removal(ffi, pub, sig, flags);
4305 report_signature_removal(ffi, pub, sigcb, app_ctx, sig, remove);
4306 if (remove) {
4307 sigs.push_back(sig.sigid);
4308 }
4309 }
4310 size_t deleted = pub.del_sigs(sigs);
4311 if (deleted != sigs.size()) {
4312 FFI_LOG(ffi, "Invalid deleted sigs count: %zu instead of %zu.", deleted, sigs.size());
4313 }
4314 /* delete from the secret key if any */
4315 if (sec && (sec != &pub)) {
4316 sec->del_sigs(sigs);
4317 }
4318 }
4319
4320 rnp_result_t
rnp_key_remove_signatures(rnp_key_handle_t handle,uint32_t flags,rnp_key_signatures_cb sigcb,void * app_ctx)4321 rnp_key_remove_signatures(rnp_key_handle_t handle,
4322 uint32_t flags,
4323 rnp_key_signatures_cb sigcb,
4324 void * app_ctx)
4325 try {
4326 if (!handle) {
4327 return RNP_ERROR_NULL_POINTER;
4328 }
4329 if (!flags && !sigcb) {
4330 return RNP_ERROR_BAD_PARAMETERS;
4331 }
4332 uint32_t origflags = flags;
4333 if (flags & RNP_KEY_SIGNATURE_INVALID) {
4334 flags &= ~RNP_KEY_SIGNATURE_INVALID;
4335 }
4336 if (flags & RNP_KEY_SIGNATURE_NON_SELF_SIG) {
4337 flags &= ~RNP_KEY_SIGNATURE_NON_SELF_SIG;
4338 }
4339 if (flags & RNP_KEY_SIGNATURE_UNKNOWN_KEY) {
4340 flags &= ~RNP_KEY_SIGNATURE_UNKNOWN_KEY;
4341 }
4342 if (flags) {
4343 FFI_LOG(handle->ffi, "Invalid flags: %" PRIu32, flags);
4344 return RNP_ERROR_BAD_PARAMETERS;
4345 }
4346 flags = origflags;
4347
4348 pgp_key_t *key = get_key_prefer_public(handle);
4349 if (!key) {
4350 return RNP_ERROR_BAD_PARAMETERS;
4351 }
4352
4353 /* process key itself */
4354 pgp_key_t *sec = get_key_require_secret(handle);
4355 remove_key_signatures(handle->ffi, *key, sec, flags, sigcb, app_ctx);
4356
4357 /* process subkeys */
4358 for (size_t idx = 0; key->is_primary() && (idx < key->subkey_count()); idx++) {
4359 pgp_key_t *sub = pgp_key_get_subkey(key, handle->ffi->pubring, idx);
4360 if (!sub) {
4361 FFI_LOG(handle->ffi, "Failed to get subkey at idx %zu.", idx);
4362 continue;
4363 }
4364 pgp_key_t *subsec = rnp_key_store_get_key_by_fpr(handle->ffi->secring, sub->fp());
4365 remove_key_signatures(handle->ffi, *sub, subsec, flags, sigcb, app_ctx);
4366 }
4367 /* revalidate key/subkey */
4368 key->revalidate(*handle->ffi->pubring);
4369 if (sec) {
4370 sec->revalidate(*handle->ffi->secring);
4371 }
4372 return RNP_SUCCESS;
4373 }
4374 FFI_GUARD
4375
4376 static bool
pk_alg_allows_custom_curve(pgp_pubkey_alg_t pkalg)4377 pk_alg_allows_custom_curve(pgp_pubkey_alg_t pkalg)
4378 {
4379 switch (pkalg) {
4380 case PGP_PKA_ECDH:
4381 case PGP_PKA_ECDSA:
4382 case PGP_PKA_SM2:
4383 return true;
4384 default:
4385 return false;
4386 }
4387 }
4388
4389 static bool
parse_preferences(json_object * jso,pgp_user_prefs_t & prefs)4390 parse_preferences(json_object *jso, pgp_user_prefs_t &prefs)
4391 {
4392 static const struct {
4393 const char * key;
4394 enum json_type type;
4395 } properties[] = {{"hashes", json_type_array},
4396 {"ciphers", json_type_array},
4397 {"compression", json_type_array},
4398 {"key server", json_type_string}};
4399
4400 for (size_t iprop = 0; iprop < ARRAY_SIZE(properties); iprop++) {
4401 json_object *value = NULL;
4402 const char * key = properties[iprop].key;
4403
4404 if (!json_object_object_get_ex(jso, key, &value)) {
4405 continue;
4406 }
4407
4408 if (!json_object_is_type(value, properties[iprop].type)) {
4409 return false;
4410 }
4411 try {
4412 if (rnp::str_case_eq(key, "hashes")) {
4413 int length = json_object_array_length(value);
4414 for (int i = 0; i < length; i++) {
4415 json_object *item = json_object_array_get_idx(value, i);
4416 if (!json_object_is_type(item, json_type_string)) {
4417 return false;
4418 }
4419 pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN;
4420 if (!str_to_hash_alg(json_object_get_string(item), &hash_alg)) {
4421 return false;
4422 }
4423 prefs.add_hash_alg(hash_alg);
4424 }
4425 } else if (rnp::str_case_eq(key, "ciphers")) {
4426 int length = json_object_array_length(value);
4427 for (int i = 0; i < length; i++) {
4428 json_object *item = json_object_array_get_idx(value, i);
4429 if (!json_object_is_type(item, json_type_string)) {
4430 return false;
4431 }
4432 pgp_symm_alg_t symm_alg = PGP_SA_UNKNOWN;
4433 if (!str_to_cipher(json_object_get_string(item), &symm_alg)) {
4434 return false;
4435 }
4436 prefs.add_symm_alg(symm_alg);
4437 }
4438 } else if (rnp::str_case_eq(key, "compression")) {
4439 int length = json_object_array_length(value);
4440 for (int i = 0; i < length; i++) {
4441 json_object *item = json_object_array_get_idx(value, i);
4442 if (!json_object_is_type(item, json_type_string)) {
4443 return false;
4444 }
4445 pgp_compression_type_t z_alg = PGP_C_UNKNOWN;
4446 if (!str_to_compression_alg(json_object_get_string(item), &z_alg)) {
4447 return false;
4448 }
4449 prefs.add_z_alg(z_alg);
4450 }
4451 } else if (rnp::str_case_eq(key, "key server")) {
4452 prefs.key_server = json_object_get_string(value);
4453 }
4454 } catch (const std::exception &e) {
4455 RNP_LOG("%s", e.what());
4456 return false;
4457 }
4458 // delete this field since it has been handled
4459 json_object_object_del(jso, key);
4460 }
4461 return true;
4462 }
4463
4464 static bool
parse_keygen_crypto(json_object * jso,rnp_keygen_crypto_params_t * crypto)4465 parse_keygen_crypto(json_object *jso, rnp_keygen_crypto_params_t *crypto)
4466 {
4467 static const struct {
4468 const char * key;
4469 enum json_type type;
4470 } properties[] = {{"type", json_type_string},
4471 {"curve", json_type_string},
4472 {"length", json_type_int},
4473 {"hash", json_type_string}};
4474
4475 for (size_t i = 0; i < ARRAY_SIZE(properties); i++) {
4476 json_object *value = NULL;
4477 const char * key = properties[i].key;
4478
4479 if (!json_object_object_get_ex(jso, key, &value)) {
4480 continue;
4481 }
4482
4483 if (!json_object_is_type(value, properties[i].type)) {
4484 return false;
4485 }
4486 // TODO: make sure there are no duplicate keys in the JSON
4487 if (rnp::str_case_eq(key, "type")) {
4488 if (!str_to_pubkey_alg(json_object_get_string(value), &crypto->key_alg)) {
4489 return false;
4490 }
4491 } else if (rnp::str_case_eq(key, "length")) {
4492 int length = json_object_get_int(value);
4493 switch (crypto->key_alg) {
4494 case PGP_PKA_RSA:
4495 crypto->rsa.modulus_bit_len = length;
4496 break;
4497 case PGP_PKA_DSA:
4498 crypto->dsa.p_bitlen = length;
4499 break;
4500 case PGP_PKA_ELGAMAL:
4501 crypto->elgamal.key_bitlen = length;
4502 break;
4503 default:
4504 return false;
4505 }
4506 } else if (rnp::str_case_eq(key, "curve")) {
4507 if (!pk_alg_allows_custom_curve(crypto->key_alg)) {
4508 return false;
4509 }
4510 if (!curve_str_to_type(json_object_get_string(value), &crypto->ecc.curve)) {
4511 return false;
4512 }
4513 } else if (rnp::str_case_eq(key, "hash")) {
4514 if (!str_to_hash_alg(json_object_get_string(value), &crypto->hash_alg)) {
4515 return false;
4516 }
4517 } else {
4518 // shouldn't happen
4519 return false;
4520 }
4521 // delete this field since it has been handled
4522 json_object_object_del(jso, key);
4523 }
4524 return true;
4525 }
4526
4527 static bool
parse_protection(json_object * jso,rnp_key_protection_params_t * protection)4528 parse_protection(json_object *jso, rnp_key_protection_params_t *protection)
4529 {
4530 static const struct {
4531 const char * key;
4532 enum json_type type;
4533 } properties[] = {{"cipher", json_type_string},
4534 {"mode", json_type_string},
4535 {"iterations", json_type_int},
4536 {"hash", json_type_string}};
4537
4538 for (size_t i = 0; i < ARRAY_SIZE(properties); i++) {
4539 json_object *value = NULL;
4540 const char * key = properties[i].key;
4541
4542 if (!json_object_object_get_ex(jso, key, &value)) {
4543 continue;
4544 }
4545
4546 if (!json_object_is_type(value, properties[i].type)) {
4547 return false;
4548 }
4549 // TODO: make sure there are no duplicate keys in the JSON
4550 if (rnp::str_case_eq(key, "cipher")) {
4551 if (!str_to_cipher(json_object_get_string(value), &protection->symm_alg)) {
4552 return false;
4553 }
4554 } else if (rnp::str_case_eq(key, "mode")) {
4555 if (!str_to_cipher_mode(json_object_get_string(value), &protection->cipher_mode)) {
4556 return false;
4557 }
4558 } else if (rnp::str_case_eq(key, "iterations")) {
4559 protection->iterations = json_object_get_int(value);
4560 } else if (rnp::str_case_eq(key, "hash")) {
4561 if (!str_to_hash_alg(json_object_get_string(value), &protection->hash_alg)) {
4562 return false;
4563 }
4564 } else {
4565 // shouldn't happen
4566 return false;
4567 }
4568 // delete this field since it has been handled
4569 json_object_object_del(jso, key);
4570 }
4571 return true;
4572 }
4573
4574 static bool
parse_keygen_primary(json_object * jso,rnp_action_keygen_t * desc)4575 parse_keygen_primary(json_object *jso, rnp_action_keygen_t *desc)
4576 {
4577 static const char *properties[] = {
4578 "userid", "usage", "expiration", "preferences", "protection"};
4579 rnp_selfsig_cert_info_t *cert = &desc->primary.keygen.cert;
4580
4581 if (!parse_keygen_crypto(jso, &desc->primary.keygen.crypto)) {
4582 return false;
4583 }
4584 for (size_t i = 0; i < ARRAY_SIZE(properties); i++) {
4585 json_object *value = NULL;
4586 const char * key = properties[i];
4587
4588 if (!json_object_object_get_ex(jso, key, &value)) {
4589 continue;
4590 }
4591 if (rnp::str_case_eq(key, "userid")) {
4592 if (!json_object_is_type(value, json_type_string)) {
4593 return false;
4594 }
4595 const char *userid = json_object_get_string(value);
4596 size_t userid_len = strlen(userid);
4597 if (userid_len >= sizeof(cert->userid)) {
4598 return false;
4599 }
4600 memcpy(cert->userid, userid, userid_len + 1);
4601 } else if (rnp::str_case_eq(key, "usage")) {
4602 switch (json_object_get_type(value)) {
4603 case json_type_array: {
4604 int length = json_object_array_length(value);
4605 for (int j = 0; j < length; j++) {
4606 json_object *item = json_object_array_get_idx(value, j);
4607 if (!json_object_is_type(item, json_type_string)) {
4608 return false;
4609 }
4610 uint8_t flag = 0;
4611 if (!str_to_key_flag(json_object_get_string(item), &flag)) {
4612 return false;
4613 }
4614 // check for duplicate
4615 if (cert->key_flags & flag) {
4616 return false;
4617 }
4618 cert->key_flags |= flag;
4619 }
4620 } break;
4621 case json_type_string: {
4622 if (!str_to_key_flag(json_object_get_string(value), &cert->key_flags)) {
4623 return false;
4624 }
4625 } break;
4626 default:
4627 return false;
4628 }
4629 } else if (rnp::str_case_eq(key, "expiration")) {
4630 if (!json_object_is_type(value, json_type_int)) {
4631 return false;
4632 }
4633 cert->key_expiration = json_object_get_int(value);
4634 } else if (rnp::str_case_eq(key, "preferences")) {
4635 if (!json_object_is_type(value, json_type_object)) {
4636 return false;
4637 }
4638 if (!parse_preferences(value, cert->prefs)) {
4639 return false;
4640 }
4641 if (json_object_object_length(value) != 0) {
4642 return false;
4643 }
4644 } else if (rnp::str_case_eq(key, "protection")) {
4645 if (!json_object_is_type(value, json_type_object)) {
4646 return false;
4647 }
4648 if (!parse_protection(value, &desc->primary.protection)) {
4649 return false;
4650 }
4651 if (json_object_object_length(value) != 0) {
4652 return false;
4653 }
4654 }
4655 // delete this field since it has been handled
4656 json_object_object_del(jso, key);
4657 }
4658 return json_object_object_length(jso) == 0;
4659 }
4660
4661 static bool
parse_keygen_sub(json_object * jso,rnp_action_keygen_t * desc)4662 parse_keygen_sub(json_object *jso, rnp_action_keygen_t *desc)
4663 {
4664 static const char * properties[] = {"usage", "expiration", "protection"};
4665 rnp_selfsig_binding_info_t *binding = &desc->subkey.keygen.binding;
4666
4667 if (!parse_keygen_crypto(jso, &desc->subkey.keygen.crypto)) {
4668 return false;
4669 }
4670 for (size_t i = 0; i < ARRAY_SIZE(properties); i++) {
4671 json_object *value = NULL;
4672 const char * key = properties[i];
4673
4674 if (!json_object_object_get_ex(jso, key, &value)) {
4675 continue;
4676 }
4677 if (rnp::str_case_eq(key, "usage")) {
4678 switch (json_object_get_type(value)) {
4679 case json_type_array: {
4680 int length = json_object_array_length(value);
4681 for (int j = 0; j < length; j++) {
4682 json_object *item = json_object_array_get_idx(value, j);
4683 if (!json_object_is_type(item, json_type_string)) {
4684 return false;
4685 }
4686 uint8_t flag = 0;
4687 if (!str_to_key_flag(json_object_get_string(item), &flag)) {
4688 return false;
4689 }
4690 if (binding->key_flags & flag) {
4691 return false;
4692 }
4693 binding->key_flags |= flag;
4694 }
4695 } break;
4696 case json_type_string: {
4697 if (!str_to_key_flag(json_object_get_string(value), &binding->key_flags)) {
4698 return false;
4699 }
4700 } break;
4701 default:
4702 return false;
4703 }
4704 } else if (rnp::str_case_eq(key, "expiration")) {
4705 if (!json_object_is_type(value, json_type_int)) {
4706 return false;
4707 }
4708 binding->key_expiration = json_object_get_int(value);
4709 } else if (rnp::str_case_eq(key, "protection")) {
4710 if (!json_object_is_type(value, json_type_object)) {
4711 return false;
4712 }
4713 if (!parse_protection(value, &desc->subkey.protection)) {
4714 return false;
4715 }
4716 if (json_object_object_length(value) != 0) {
4717 return false;
4718 }
4719 }
4720 // delete this field since it has been handled
4721 json_object_object_del(jso, key);
4722 }
4723 return json_object_object_length(jso) == 0;
4724 }
4725
4726 static bool
gen_json_grips(char ** result,const pgp_key_t * primary,const pgp_key_t * sub)4727 gen_json_grips(char **result, const pgp_key_t *primary, const pgp_key_t *sub)
4728 {
4729 bool ret = false;
4730 json_object *jso = NULL;
4731 char grip[PGP_KEY_GRIP_SIZE * 2 + 1];
4732
4733 if (!result) {
4734 return false;
4735 }
4736
4737 jso = json_object_new_object();
4738 if (!jso) {
4739 return false;
4740 }
4741
4742 if (primary) {
4743 json_object *jsoprimary = json_object_new_object();
4744 if (!jsoprimary) {
4745 goto done;
4746 }
4747 json_object_object_add(jso, "primary", jsoprimary);
4748 if (!rnp::hex_encode(
4749 primary->grip().data(), primary->grip().size(), grip, sizeof(grip))) {
4750 goto done;
4751 }
4752 json_object *jsogrip = json_object_new_string(grip);
4753 if (!jsogrip) {
4754 goto done;
4755 }
4756 json_object_object_add(jsoprimary, "grip", jsogrip);
4757 }
4758 if (sub) {
4759 json_object *jsosub = json_object_new_object();
4760 if (!jsosub) {
4761 goto done;
4762 }
4763 json_object_object_add(jso, "sub", jsosub);
4764 if (!rnp::hex_encode(sub->grip().data(), sub->grip().size(), grip, sizeof(grip))) {
4765 goto done;
4766 }
4767 json_object *jsogrip = json_object_new_string(grip);
4768 if (!jsogrip) {
4769 goto done;
4770 }
4771 json_object_object_add(jsosub, "grip", jsogrip);
4772 }
4773 *result = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
4774
4775 ret = true;
4776 done:
4777 json_object_put(jso);
4778 return ret;
4779 }
4780
4781 rnp_result_t
rnp_generate_key_json(rnp_ffi_t ffi,const char * json,char ** results)4782 rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
4783 try {
4784 rnp_result_t ret = RNP_ERROR_GENERIC;
4785 json_object * jso = NULL;
4786 rnp_action_keygen_t keygen_desc = {};
4787 char * identifier_type = NULL;
4788 char * identifier = NULL;
4789 pgp_key_t primary_pub;
4790 pgp_key_t primary_sec;
4791 pgp_key_t sub_pub;
4792 pgp_key_t sub_sec;
4793 json_object * jsoprimary = NULL;
4794 json_object * jsosub = NULL;
4795 json_tokener_error error;
4796
4797 // checks
4798 if (!ffi || !ffi->secring || !json) {
4799 return RNP_ERROR_NULL_POINTER;
4800 }
4801
4802 // parse the JSON
4803 jso = json_tokener_parse_verbose(json, &error);
4804 if (!jso) {
4805 // syntax error or some other issue
4806 FFI_LOG(ffi, "Invalid JSON: %s", json_tokener_error_desc(error));
4807 ret = RNP_ERROR_BAD_FORMAT;
4808 goto done;
4809 }
4810
4811 // locate the appropriate sections
4812 {
4813 json_object_object_foreach(jso, key, value)
4814 {
4815 json_object **dest = NULL;
4816
4817 if (rnp::str_case_eq(key, "primary")) {
4818 dest = &jsoprimary;
4819 } else if (rnp::str_case_eq(key, "sub")) {
4820 dest = &jsosub;
4821 } else {
4822 // unrecognized key in the object
4823 FFI_LOG(ffi, "Unexpected key in JSON: %s", key);
4824 ret = RNP_ERROR_BAD_PARAMETERS;
4825 goto done;
4826 }
4827
4828 // duplicate "primary"/"sub"
4829 if (*dest) {
4830 ret = RNP_ERROR_BAD_PARAMETERS;
4831 goto done;
4832 }
4833 *dest = value;
4834 }
4835 }
4836
4837 if (jsoprimary && jsosub) { // generating primary+sub
4838 if (!parse_keygen_primary(jsoprimary, &keygen_desc) ||
4839 !parse_keygen_sub(jsosub, &keygen_desc)) {
4840 ret = RNP_ERROR_BAD_PARAMETERS;
4841 goto done;
4842 }
4843 keygen_desc.primary.keygen.crypto.ctx = &ffi->context;
4844 keygen_desc.subkey.keygen.crypto.ctx = &ffi->context;
4845 if (!pgp_generate_keypair(keygen_desc.primary.keygen,
4846 keygen_desc.subkey.keygen,
4847 true,
4848 primary_sec,
4849 primary_pub,
4850 sub_sec,
4851 sub_pub,
4852 ffi->secring->format)) {
4853 goto done;
4854 }
4855 if (results && !gen_json_grips(results, &primary_pub, &sub_pub)) {
4856 ret = RNP_ERROR_OUT_OF_MEMORY;
4857 goto done;
4858 }
4859 if (ffi->pubring) {
4860 if (!rnp_key_store_add_key(ffi->pubring, &primary_pub)) {
4861 ret = RNP_ERROR_OUT_OF_MEMORY;
4862 goto done;
4863 }
4864 if (!rnp_key_store_add_key(ffi->pubring, &sub_pub)) {
4865 ret = RNP_ERROR_OUT_OF_MEMORY;
4866 goto done;
4867 }
4868 }
4869 /* add key/subkey protection */
4870 if (keygen_desc.primary.protection.symm_alg &&
4871 !primary_sec.protect(
4872 keygen_desc.primary.protection, ffi->pass_provider, ffi->rng())) {
4873 ret = RNP_ERROR_BAD_PARAMETERS;
4874 goto done;
4875 }
4876
4877 if (keygen_desc.subkey.protection.symm_alg &&
4878 !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider, ffi->rng())) {
4879 ret = RNP_ERROR_BAD_PARAMETERS;
4880 goto done;
4881 }
4882
4883 if (!rnp_key_store_add_key(ffi->secring, &primary_sec)) {
4884 ret = RNP_ERROR_OUT_OF_MEMORY;
4885 goto done;
4886 }
4887 if (!rnp_key_store_add_key(ffi->secring, &sub_sec)) {
4888 ret = RNP_ERROR_OUT_OF_MEMORY;
4889 goto done;
4890 }
4891 } else if (jsoprimary && !jsosub) { // generating primary only
4892 keygen_desc.primary.keygen.crypto.ctx = &ffi->context;
4893 if (!parse_keygen_primary(jsoprimary, &keygen_desc)) {
4894 ret = RNP_ERROR_BAD_PARAMETERS;
4895 goto done;
4896 }
4897 if (!pgp_generate_primary_key(keygen_desc.primary.keygen,
4898 true,
4899 primary_sec,
4900 primary_pub,
4901 ffi->secring->format)) {
4902 goto done;
4903 }
4904 if (results && !gen_json_grips(results, &primary_pub, NULL)) {
4905 ret = RNP_ERROR_OUT_OF_MEMORY;
4906 goto done;
4907 }
4908 if (ffi->pubring) {
4909 if (!rnp_key_store_add_key(ffi->pubring, &primary_pub)) {
4910 ret = RNP_ERROR_OUT_OF_MEMORY;
4911 goto done;
4912 }
4913 }
4914 /* encrypt secret key if specified */
4915 if (keygen_desc.primary.protection.symm_alg &&
4916 !primary_sec.protect(
4917 keygen_desc.primary.protection, ffi->pass_provider, ffi->rng())) {
4918 ret = RNP_ERROR_BAD_PARAMETERS;
4919 goto done;
4920 }
4921
4922 if (!rnp_key_store_add_key(ffi->secring, &primary_sec)) {
4923 ret = RNP_ERROR_OUT_OF_MEMORY;
4924 goto done;
4925 }
4926 } else if (jsosub) { // generating subkey only
4927 if (!ffi->pubring) {
4928 ret = RNP_ERROR_NULL_POINTER;
4929 goto done;
4930 }
4931 json_object *jsoparent = NULL;
4932 if (!json_object_object_get_ex(jsosub, "primary", &jsoparent) ||
4933 json_object_object_length(jsoparent) != 1) {
4934 ret = RNP_ERROR_BAD_PARAMETERS;
4935 goto done;
4936 }
4937 json_object_object_foreach(jsoparent, key, value)
4938 {
4939 if (!json_object_is_type(value, json_type_string)) {
4940 ret = RNP_ERROR_BAD_PARAMETERS;
4941 goto done;
4942 }
4943 identifier_type = strdup(key);
4944 identifier = strdup(json_object_get_string(value));
4945 }
4946 if (!identifier_type || !identifier) {
4947 ret = RNP_ERROR_OUT_OF_MEMORY;
4948 goto done;
4949 }
4950 json_object_object_del(jsosub, "primary");
4951
4952 pgp_key_search_t locator = {(pgp_key_search_type_t) 0};
4953 rnp_result_t tmpret = str_to_locator(ffi, &locator, identifier_type, identifier);
4954 if (tmpret) {
4955 ret = tmpret;
4956 goto done;
4957 }
4958
4959 pgp_key_t *primary_pub = rnp_key_store_search(ffi->pubring, &locator, NULL);
4960 pgp_key_t *primary_sec = rnp_key_store_search(ffi->secring, &locator, NULL);
4961 if (!primary_sec || !primary_pub) {
4962 ret = RNP_ERROR_KEY_NOT_FOUND;
4963 goto done;
4964 }
4965 if (!parse_keygen_sub(jsosub, &keygen_desc)) {
4966 ret = RNP_ERROR_BAD_PARAMETERS;
4967 goto done;
4968 }
4969 keygen_desc.subkey.keygen.crypto.ctx = &ffi->context;
4970 if (!pgp_generate_subkey(keygen_desc.subkey.keygen,
4971 true,
4972 *primary_sec,
4973 *primary_pub,
4974 sub_sec,
4975 sub_pub,
4976 ffi->pass_provider,
4977 ffi->secring->format)) {
4978 goto done;
4979 }
4980 if (results && !gen_json_grips(results, NULL, &sub_pub)) {
4981 ret = RNP_ERROR_OUT_OF_MEMORY;
4982 goto done;
4983 }
4984 if (ffi->pubring) {
4985 if (!rnp_key_store_add_key(ffi->pubring, &sub_pub)) {
4986 ret = RNP_ERROR_OUT_OF_MEMORY;
4987 goto done;
4988 }
4989 }
4990 /* encrypt subkey if specified */
4991 if (keygen_desc.subkey.protection.symm_alg &&
4992 !sub_sec.protect(keygen_desc.subkey.protection, ffi->pass_provider, ffi->rng())) {
4993 ret = RNP_ERROR_BAD_PARAMETERS;
4994 goto done;
4995 }
4996
4997 if (!rnp_key_store_add_key(ffi->secring, &sub_sec)) {
4998 ret = RNP_ERROR_OUT_OF_MEMORY;
4999 goto done;
5000 }
5001 } else {
5002 // nothing to generate...
5003 ret = RNP_ERROR_BAD_PARAMETERS;
5004 goto done;
5005 }
5006
5007 ret = RNP_SUCCESS;
5008 done:
5009 json_object_put(jso);
5010 free(identifier_type);
5011 free(identifier);
5012 return ret;
5013 }
5014 FFI_GUARD
5015
5016 rnp_result_t
rnp_generate_key_ex(rnp_ffi_t ffi,const char * key_alg,const char * sub_alg,uint32_t key_bits,uint32_t sub_bits,const char * key_curve,const char * sub_curve,const char * userid,const char * password,rnp_key_handle_t * key)5017 rnp_generate_key_ex(rnp_ffi_t ffi,
5018 const char * key_alg,
5019 const char * sub_alg,
5020 uint32_t key_bits,
5021 uint32_t sub_bits,
5022 const char * key_curve,
5023 const char * sub_curve,
5024 const char * userid,
5025 const char * password,
5026 rnp_key_handle_t *key)
5027 try {
5028 rnp_op_generate_t op = NULL;
5029 rnp_op_generate_t subop = NULL;
5030 rnp_key_handle_t primary = NULL;
5031 rnp_key_handle_t subkey = NULL;
5032 rnp_result_t ret = RNP_ERROR_KEY_GENERATION;
5033
5034 /* generate primary key */
5035 if ((ret = rnp_op_generate_create(&op, ffi, key_alg))) {
5036 return ret;
5037 }
5038 if (key_bits && (ret = rnp_op_generate_set_bits(op, key_bits))) {
5039 goto done;
5040 }
5041 if (key_curve && (ret = rnp_op_generate_set_curve(op, key_curve))) {
5042 goto done;
5043 }
5044 if ((ret = rnp_op_generate_set_userid(op, userid))) {
5045 goto done;
5046 }
5047 if ((ret = rnp_op_generate_add_usage(op, "sign"))) {
5048 goto done;
5049 }
5050 if ((ret = rnp_op_generate_add_usage(op, "certify"))) {
5051 goto done;
5052 }
5053 if ((ret = rnp_op_generate_execute(op))) {
5054 goto done;
5055 }
5056 if ((ret = rnp_op_generate_get_key(op, &primary))) {
5057 goto done;
5058 }
5059 /* generate subkey if requested */
5060 if (!sub_alg) {
5061 goto done;
5062 }
5063 if ((ret = rnp_op_generate_subkey_create(&subop, ffi, primary, sub_alg))) {
5064 goto done;
5065 }
5066 if (sub_bits && (ret = rnp_op_generate_set_bits(subop, sub_bits))) {
5067 goto done;
5068 }
5069 if (sub_curve && (ret = rnp_op_generate_set_curve(subop, sub_curve))) {
5070 goto done;
5071 }
5072 if (password && (ret = rnp_op_generate_set_protection_password(subop, password))) {
5073 goto done;
5074 }
5075 if ((ret = rnp_op_generate_add_usage(subop, "encrypt"))) {
5076 goto done;
5077 }
5078 if ((ret = rnp_op_generate_execute(subop))) {
5079 goto done;
5080 }
5081 if ((ret = rnp_op_generate_get_key(subop, &subkey))) {
5082 goto done;
5083 }
5084 done:
5085 /* only now will protect the primary key - to not spend time on unlocking to sign
5086 * subkey */
5087 if (!ret && password) {
5088 ret = rnp_key_protect(primary, password, NULL, NULL, NULL, 0);
5089 }
5090 if (ret && primary) {
5091 rnp_key_remove(primary, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SECRET);
5092 }
5093 if (ret && subkey) {
5094 rnp_key_remove(subkey, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SECRET);
5095 }
5096 if (!ret && key) {
5097 *key = primary;
5098 } else {
5099 rnp_key_handle_destroy(primary);
5100 }
5101 rnp_key_handle_destroy(subkey);
5102 rnp_op_generate_destroy(op);
5103 rnp_op_generate_destroy(subop);
5104 return ret;
5105 }
5106 FFI_GUARD
5107
5108 rnp_result_t
rnp_generate_key_rsa(rnp_ffi_t ffi,uint32_t bits,uint32_t subbits,const char * userid,const char * password,rnp_key_handle_t * key)5109 rnp_generate_key_rsa(rnp_ffi_t ffi,
5110 uint32_t bits,
5111 uint32_t subbits,
5112 const char * userid,
5113 const char * password,
5114 rnp_key_handle_t *key)
5115 try {
5116 return rnp_generate_key_ex(ffi,
5117 RNP_ALGNAME_RSA,
5118 subbits ? RNP_ALGNAME_RSA : NULL,
5119 bits,
5120 subbits,
5121 NULL,
5122 NULL,
5123 userid,
5124 password,
5125 key);
5126 }
5127 FFI_GUARD
5128
5129 rnp_result_t
rnp_generate_key_dsa_eg(rnp_ffi_t ffi,uint32_t bits,uint32_t subbits,const char * userid,const char * password,rnp_key_handle_t * key)5130 rnp_generate_key_dsa_eg(rnp_ffi_t ffi,
5131 uint32_t bits,
5132 uint32_t subbits,
5133 const char * userid,
5134 const char * password,
5135 rnp_key_handle_t *key)
5136 try {
5137 return rnp_generate_key_ex(ffi,
5138 RNP_ALGNAME_DSA,
5139 subbits ? RNP_ALGNAME_ELGAMAL : NULL,
5140 bits,
5141 subbits,
5142 NULL,
5143 NULL,
5144 userid,
5145 password,
5146 key);
5147 }
5148 FFI_GUARD
5149
5150 rnp_result_t
rnp_generate_key_ec(rnp_ffi_t ffi,const char * curve,const char * userid,const char * password,rnp_key_handle_t * key)5151 rnp_generate_key_ec(rnp_ffi_t ffi,
5152 const char * curve,
5153 const char * userid,
5154 const char * password,
5155 rnp_key_handle_t *key)
5156 try {
5157 return rnp_generate_key_ex(
5158 ffi, RNP_ALGNAME_ECDSA, RNP_ALGNAME_ECDH, 0, 0, curve, curve, userid, password, key);
5159 }
5160 FFI_GUARD
5161
5162 rnp_result_t
rnp_generate_key_25519(rnp_ffi_t ffi,const char * userid,const char * password,rnp_key_handle_t * key)5163 rnp_generate_key_25519(rnp_ffi_t ffi,
5164 const char * userid,
5165 const char * password,
5166 rnp_key_handle_t *key)
5167 try {
5168 return rnp_generate_key_ex(ffi,
5169 RNP_ALGNAME_EDDSA,
5170 RNP_ALGNAME_ECDH,
5171 0,
5172 0,
5173 NULL,
5174 "Curve25519",
5175 userid,
5176 password,
5177 key);
5178 }
5179 FFI_GUARD
5180
5181 rnp_result_t
rnp_generate_key_sm2(rnp_ffi_t ffi,const char * userid,const char * password,rnp_key_handle_t * key)5182 rnp_generate_key_sm2(rnp_ffi_t ffi,
5183 const char * userid,
5184 const char * password,
5185 rnp_key_handle_t *key)
5186 try {
5187 return rnp_generate_key_ex(
5188 ffi, RNP_ALGNAME_SM2, RNP_ALGNAME_SM2, 0, 0, NULL, NULL, userid, password, key);
5189 }
5190 FFI_GUARD
5191
5192 static pgp_key_flags_t
default_key_flags(pgp_pubkey_alg_t alg,bool subkey)5193 default_key_flags(pgp_pubkey_alg_t alg, bool subkey)
5194 {
5195 switch (alg) {
5196 case PGP_PKA_RSA:
5197 return subkey ? PGP_KF_ENCRYPT : pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY);
5198 case PGP_PKA_DSA:
5199 case PGP_PKA_ECDSA:
5200 case PGP_PKA_EDDSA:
5201 return subkey ? PGP_KF_SIGN : pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY);
5202 case PGP_PKA_SM2:
5203 return subkey ? PGP_KF_ENCRYPT : pgp_key_flags_t(PGP_KF_SIGN | PGP_KF_CERTIFY);
5204 case PGP_PKA_ECDH:
5205 case PGP_PKA_ELGAMAL:
5206 return PGP_KF_ENCRYPT;
5207 default:
5208 return PGP_KF_NONE;
5209 }
5210 }
5211
5212 rnp_result_t
rnp_op_generate_create(rnp_op_generate_t * op,rnp_ffi_t ffi,const char * alg)5213 rnp_op_generate_create(rnp_op_generate_t *op, rnp_ffi_t ffi, const char *alg)
5214 try {
5215 pgp_pubkey_alg_t key_alg = PGP_PKA_NOTHING;
5216
5217 if (!op || !ffi || !alg) {
5218 return RNP_ERROR_NULL_POINTER;
5219 }
5220
5221 if (!ffi->pubring || !ffi->secring) {
5222 return RNP_ERROR_BAD_PARAMETERS;
5223 }
5224
5225 if (!str_to_pubkey_alg(alg, &key_alg)) {
5226 return RNP_ERROR_BAD_PARAMETERS;
5227 }
5228
5229 if (!(pgp_pk_alg_capabilities(key_alg) & PGP_KF_SIGN)) {
5230 return RNP_ERROR_BAD_PARAMETERS;
5231 }
5232
5233 *op = new rnp_op_generate_st();
5234 (*op)->ffi = ffi;
5235 (*op)->primary = true;
5236 (*op)->crypto.key_alg = key_alg;
5237 (*op)->crypto.ctx = &ffi->context;
5238 (*op)->cert.key_flags = default_key_flags(key_alg, false);
5239
5240 return RNP_SUCCESS;
5241 }
5242 FFI_GUARD
5243
5244 rnp_result_t
rnp_op_generate_subkey_create(rnp_op_generate_t * op,rnp_ffi_t ffi,rnp_key_handle_t primary,const char * alg)5245 rnp_op_generate_subkey_create(rnp_op_generate_t *op,
5246 rnp_ffi_t ffi,
5247 rnp_key_handle_t primary,
5248 const char * alg)
5249 try {
5250 if (!op || !ffi || !alg || !primary) {
5251 return RNP_ERROR_NULL_POINTER;
5252 }
5253
5254 if (!ffi->pubring || !ffi->secring) {
5255 return RNP_ERROR_BAD_PARAMETERS;
5256 }
5257
5258 /* TODO: should we do these checks here or may leave it up till generate call? */
5259 bool flag = false;
5260 if (rnp_key_have_secret(primary, &flag) || !flag) {
5261 return RNP_ERROR_BAD_PARAMETERS;
5262 }
5263
5264 if (rnp_key_is_primary(primary, &flag) || !flag) {
5265 return RNP_ERROR_BAD_PARAMETERS;
5266 }
5267
5268 if (!primary->sec->can_sign()) {
5269 return RNP_ERROR_BAD_PARAMETERS;
5270 }
5271
5272 pgp_pubkey_alg_t key_alg = PGP_PKA_NOTHING;
5273 if (!str_to_pubkey_alg(alg, &key_alg)) {
5274 return RNP_ERROR_BAD_PARAMETERS;
5275 }
5276
5277 *op = new rnp_op_generate_st();
5278 (*op)->ffi = ffi;
5279 (*op)->primary = false;
5280 (*op)->crypto.key_alg = key_alg;
5281 (*op)->crypto.ctx = &ffi->context;
5282 (*op)->binding.key_flags = default_key_flags(key_alg, true);
5283 (*op)->primary_sec = primary->sec;
5284 (*op)->primary_pub = primary->pub;
5285
5286 return RNP_SUCCESS;
5287 }
5288 FFI_GUARD
5289
5290 rnp_result_t
rnp_op_generate_set_bits(rnp_op_generate_t op,uint32_t bits)5291 rnp_op_generate_set_bits(rnp_op_generate_t op, uint32_t bits)
5292 try {
5293 if (!op) {
5294 return RNP_ERROR_NULL_POINTER;
5295 }
5296
5297 switch (op->crypto.key_alg) {
5298 case PGP_PKA_RSA:
5299 case PGP_PKA_RSA_ENCRYPT_ONLY:
5300 case PGP_PKA_RSA_SIGN_ONLY:
5301 op->crypto.rsa.modulus_bit_len = bits;
5302 break;
5303 case PGP_PKA_ELGAMAL:
5304 op->crypto.elgamal.key_bitlen = bits;
5305 break;
5306 case PGP_PKA_DSA:
5307 op->crypto.dsa.p_bitlen = bits;
5308 break;
5309 default:
5310 return RNP_ERROR_BAD_PARAMETERS;
5311 }
5312
5313 return RNP_SUCCESS;
5314 }
5315 FFI_GUARD
5316
5317 rnp_result_t
rnp_op_generate_set_hash(rnp_op_generate_t op,const char * hash)5318 rnp_op_generate_set_hash(rnp_op_generate_t op, const char *hash)
5319 try {
5320 if (!op || !hash) {
5321 return RNP_ERROR_NULL_POINTER;
5322 }
5323 if (!str_to_hash_alg(hash, &op->crypto.hash_alg)) {
5324 FFI_LOG(op->ffi, "Invalid hash: %s", hash);
5325 return RNP_ERROR_BAD_PARAMETERS;
5326 }
5327 return RNP_SUCCESS;
5328 }
5329 FFI_GUARD
5330
5331 rnp_result_t
rnp_op_generate_set_dsa_qbits(rnp_op_generate_t op,uint32_t qbits)5332 rnp_op_generate_set_dsa_qbits(rnp_op_generate_t op, uint32_t qbits)
5333 try {
5334 if (!op) {
5335 return RNP_ERROR_NULL_POINTER;
5336 }
5337 if (op->crypto.key_alg != PGP_PKA_DSA) {
5338 return RNP_ERROR_BAD_PARAMETERS;
5339 }
5340 op->crypto.dsa.q_bitlen = qbits;
5341 return RNP_SUCCESS;
5342 }
5343 FFI_GUARD
5344
5345 rnp_result_t
rnp_op_generate_set_curve(rnp_op_generate_t op,const char * curve)5346 rnp_op_generate_set_curve(rnp_op_generate_t op, const char *curve)
5347 try {
5348 if (!op || !curve) {
5349 return RNP_ERROR_NULL_POINTER;
5350 }
5351 if (!pk_alg_allows_custom_curve(op->crypto.key_alg)) {
5352 return RNP_ERROR_BAD_PARAMETERS;
5353 }
5354 if (!curve_str_to_type(curve, &op->crypto.ecc.curve)) {
5355 return RNP_ERROR_BAD_PARAMETERS;
5356 }
5357 return RNP_SUCCESS;
5358 }
5359 FFI_GUARD
5360
5361 rnp_result_t
rnp_op_generate_set_protection_password(rnp_op_generate_t op,const char * password)5362 rnp_op_generate_set_protection_password(rnp_op_generate_t op, const char *password)
5363 try {
5364 if (!op || !password) {
5365 return RNP_ERROR_NULL_POINTER;
5366 }
5367 op->password.assign(password, password + strlen(password) + 1);
5368 return RNP_SUCCESS;
5369 }
5370 FFI_GUARD
5371
5372 rnp_result_t
rnp_op_generate_set_request_password(rnp_op_generate_t op,bool request)5373 rnp_op_generate_set_request_password(rnp_op_generate_t op, bool request)
5374 try {
5375 if (!op || !request) {
5376 return RNP_ERROR_NULL_POINTER;
5377 }
5378 op->request_password = request;
5379 return RNP_SUCCESS;
5380 }
5381 FFI_GUARD
5382
5383 rnp_result_t
rnp_op_generate_set_protection_cipher(rnp_op_generate_t op,const char * cipher)5384 rnp_op_generate_set_protection_cipher(rnp_op_generate_t op, const char *cipher)
5385 try {
5386 if (!op || !cipher) {
5387 return RNP_ERROR_NULL_POINTER;
5388 }
5389 if (!str_to_cipher(cipher, &op->protection.symm_alg)) {
5390 return RNP_ERROR_BAD_PARAMETERS;
5391 }
5392 return RNP_SUCCESS;
5393 }
5394 FFI_GUARD
5395
5396 rnp_result_t
rnp_op_generate_set_protection_hash(rnp_op_generate_t op,const char * hash)5397 rnp_op_generate_set_protection_hash(rnp_op_generate_t op, const char *hash)
5398 try {
5399 if (!op || !hash) {
5400 return RNP_ERROR_NULL_POINTER;
5401 }
5402 if (!str_to_hash_alg(hash, &op->protection.hash_alg)) {
5403 return RNP_ERROR_BAD_PARAMETERS;
5404 }
5405 return RNP_SUCCESS;
5406 }
5407 FFI_GUARD
5408
5409 rnp_result_t
rnp_op_generate_set_protection_mode(rnp_op_generate_t op,const char * mode)5410 rnp_op_generate_set_protection_mode(rnp_op_generate_t op, const char *mode)
5411 try {
5412 if (!op || !mode) {
5413 return RNP_ERROR_NULL_POINTER;
5414 }
5415 if (!str_to_cipher_mode(mode, &op->protection.cipher_mode)) {
5416 return RNP_ERROR_BAD_PARAMETERS;
5417 }
5418 return RNP_SUCCESS;
5419 }
5420 FFI_GUARD
5421
5422 rnp_result_t
rnp_op_generate_set_protection_iterations(rnp_op_generate_t op,uint32_t iterations)5423 rnp_op_generate_set_protection_iterations(rnp_op_generate_t op, uint32_t iterations)
5424 try {
5425 if (!op) {
5426 return RNP_ERROR_NULL_POINTER;
5427 }
5428 op->protection.iterations = iterations;
5429 return RNP_SUCCESS;
5430 }
5431 FFI_GUARD
5432
5433 rnp_result_t
rnp_op_generate_add_usage(rnp_op_generate_t op,const char * usage)5434 rnp_op_generate_add_usage(rnp_op_generate_t op, const char *usage)
5435 try {
5436 if (!op || !usage) {
5437 return RNP_ERROR_NULL_POINTER;
5438 }
5439 uint8_t flag = 0;
5440 if (!str_to_key_flag(usage, &flag)) {
5441 return RNP_ERROR_BAD_PARAMETERS;
5442 }
5443 if (!(pgp_pk_alg_capabilities(op->crypto.key_alg) & flag)) {
5444 return RNP_ERROR_NOT_SUPPORTED;
5445 }
5446 if (op->primary) {
5447 op->cert.key_flags |= flag;
5448 } else {
5449 op->binding.key_flags |= flag;
5450 }
5451 return RNP_SUCCESS;
5452 }
5453 FFI_GUARD
5454
5455 rnp_result_t
rnp_op_generate_clear_usage(rnp_op_generate_t op)5456 rnp_op_generate_clear_usage(rnp_op_generate_t op)
5457 try {
5458 if (!op) {
5459 return RNP_ERROR_NULL_POINTER;
5460 }
5461 if (op->primary) {
5462 op->cert.key_flags = 0;
5463 } else {
5464 op->binding.key_flags = 0;
5465 }
5466 return RNP_SUCCESS;
5467 }
5468 FFI_GUARD
5469
5470 rnp_result_t
rnp_op_generate_set_userid(rnp_op_generate_t op,const char * userid)5471 rnp_op_generate_set_userid(rnp_op_generate_t op, const char *userid)
5472 try {
5473 if (!op || !userid) {
5474 return RNP_ERROR_NULL_POINTER;
5475 }
5476 if (!op->primary) {
5477 return RNP_ERROR_BAD_PARAMETERS;
5478 }
5479 size_t userid_len = strlen(userid);
5480 if (userid_len >= sizeof(op->cert.userid)) {
5481 return RNP_ERROR_BAD_PARAMETERS;
5482 }
5483 memcpy(op->cert.userid, userid, userid_len + 1);
5484 return RNP_SUCCESS;
5485 }
5486 FFI_GUARD
5487
5488 rnp_result_t
rnp_op_generate_set_expiration(rnp_op_generate_t op,uint32_t expiration)5489 rnp_op_generate_set_expiration(rnp_op_generate_t op, uint32_t expiration)
5490 try {
5491 if (!op) {
5492 return RNP_ERROR_NULL_POINTER;
5493 }
5494 if (op->primary) {
5495 op->cert.key_expiration = expiration;
5496 } else {
5497 op->binding.key_expiration = expiration;
5498 }
5499 return RNP_SUCCESS;
5500 }
5501 FFI_GUARD
5502
5503 rnp_result_t
rnp_op_generate_clear_pref_hashes(rnp_op_generate_t op)5504 rnp_op_generate_clear_pref_hashes(rnp_op_generate_t op)
5505 try {
5506 if (!op) {
5507 return RNP_ERROR_NULL_POINTER;
5508 }
5509 if (!op->primary) {
5510 return RNP_ERROR_BAD_PARAMETERS;
5511 }
5512 op->cert.prefs.set_hash_algs({});
5513 return RNP_SUCCESS;
5514 }
5515 FFI_GUARD
5516
5517 rnp_result_t
rnp_op_generate_add_pref_hash(rnp_op_generate_t op,const char * hash)5518 rnp_op_generate_add_pref_hash(rnp_op_generate_t op, const char *hash)
5519 try {
5520 if (!op || !hash) {
5521 return RNP_ERROR_NULL_POINTER;
5522 }
5523 if (!op->primary) {
5524 return RNP_ERROR_BAD_PARAMETERS;
5525 }
5526 pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN;
5527 if (!str_to_hash_alg(hash, &hash_alg)) {
5528 return RNP_ERROR_BAD_PARAMETERS;
5529 }
5530 op->cert.prefs.add_hash_alg(hash_alg);
5531 return RNP_SUCCESS;
5532 }
5533 FFI_GUARD
5534
5535 rnp_result_t
rnp_op_generate_clear_pref_compression(rnp_op_generate_t op)5536 rnp_op_generate_clear_pref_compression(rnp_op_generate_t op)
5537 try {
5538 if (!op) {
5539 return RNP_ERROR_NULL_POINTER;
5540 }
5541 if (!op->primary) {
5542 return RNP_ERROR_BAD_PARAMETERS;
5543 }
5544 op->cert.prefs.set_z_algs({});
5545 return RNP_SUCCESS;
5546 }
5547 FFI_GUARD
5548
5549 rnp_result_t
rnp_op_generate_add_pref_compression(rnp_op_generate_t op,const char * compression)5550 rnp_op_generate_add_pref_compression(rnp_op_generate_t op, const char *compression)
5551 try {
5552 if (!op || !compression) {
5553 return RNP_ERROR_NULL_POINTER;
5554 }
5555 if (!op->primary) {
5556 return RNP_ERROR_BAD_PARAMETERS;
5557 }
5558 pgp_compression_type_t z_alg = PGP_C_UNKNOWN;
5559 if (!str_to_compression_alg(compression, &z_alg)) {
5560 return RNP_ERROR_BAD_PARAMETERS;
5561 }
5562 op->cert.prefs.add_z_alg(z_alg);
5563 return RNP_SUCCESS;
5564 }
5565 FFI_GUARD
5566
5567 rnp_result_t
rnp_op_generate_clear_pref_ciphers(rnp_op_generate_t op)5568 rnp_op_generate_clear_pref_ciphers(rnp_op_generate_t op)
5569 try {
5570 if (!op) {
5571 return RNP_ERROR_NULL_POINTER;
5572 }
5573 if (!op->primary) {
5574 return RNP_ERROR_BAD_PARAMETERS;
5575 }
5576 op->cert.prefs.set_symm_algs({});
5577 return RNP_SUCCESS;
5578 }
5579 FFI_GUARD
5580
5581 rnp_result_t
rnp_op_generate_add_pref_cipher(rnp_op_generate_t op,const char * cipher)5582 rnp_op_generate_add_pref_cipher(rnp_op_generate_t op, const char *cipher)
5583 try {
5584 if (!op || !cipher) {
5585 return RNP_ERROR_NULL_POINTER;
5586 }
5587 if (!op->primary) {
5588 return RNP_ERROR_BAD_PARAMETERS;
5589 }
5590 pgp_symm_alg_t symm_alg = PGP_SA_UNKNOWN;
5591 if (!str_to_cipher(cipher, &symm_alg)) {
5592 return RNP_ERROR_BAD_PARAMETERS;
5593 }
5594 op->cert.prefs.add_symm_alg(symm_alg);
5595 return RNP_SUCCESS;
5596 }
5597 FFI_GUARD
5598
5599 rnp_result_t
rnp_op_generate_set_pref_keyserver(rnp_op_generate_t op,const char * keyserver)5600 rnp_op_generate_set_pref_keyserver(rnp_op_generate_t op, const char *keyserver)
5601 try {
5602 if (!op) {
5603 return RNP_ERROR_NULL_POINTER;
5604 }
5605 if (!op->primary) {
5606 return RNP_ERROR_BAD_PARAMETERS;
5607 }
5608 op->cert.prefs.key_server = keyserver ? keyserver : "";
5609 return RNP_SUCCESS;
5610 }
5611 FFI_GUARD
5612
5613 rnp_result_t
rnp_op_generate_execute(rnp_op_generate_t op)5614 rnp_op_generate_execute(rnp_op_generate_t op)
5615 try {
5616 if (!op || !op->ffi) {
5617 return RNP_ERROR_NULL_POINTER;
5618 }
5619
5620 rnp_result_t ret = RNP_ERROR_GENERIC;
5621 pgp_key_t pub;
5622 pgp_key_t sec;
5623 pgp_password_provider_t prov = {.callback = NULL};
5624
5625 if (op->primary) {
5626 rnp_keygen_primary_desc_t keygen = {};
5627 keygen.crypto = op->crypto;
5628 keygen.cert = op->cert;
5629 op->cert.prefs = {}; /* generate call will free prefs */
5630
5631 if (!pgp_generate_primary_key(keygen, true, sec, pub, op->ffi->secring->format)) {
5632 return RNP_ERROR_KEY_GENERATION;
5633 }
5634 } else {
5635 /* subkey generation */
5636 rnp_keygen_subkey_desc_t keygen = {};
5637 keygen.crypto = op->crypto;
5638 keygen.binding = op->binding;
5639 if (!pgp_generate_subkey(keygen,
5640 true,
5641 *op->primary_sec,
5642 *op->primary_pub,
5643 sec,
5644 pub,
5645 op->ffi->pass_provider,
5646 op->ffi->secring->format)) {
5647 return RNP_ERROR_KEY_GENERATION;
5648 }
5649 }
5650
5651 /* add public key part to the keyring */
5652 if (!(op->gen_pub = rnp_key_store_add_key(op->ffi->pubring, &pub))) {
5653 ret = RNP_ERROR_OUT_OF_MEMORY;
5654 goto done;
5655 }
5656
5657 /* encrypt secret key if requested */
5658 if (!op->password.empty()) {
5659 prov = {.callback = rnp_password_provider_string,
5660 .userdata = (void *) op->password.data()};
5661 } else if (op->request_password) {
5662 prov = {.callback = rnp_password_cb_bounce, .userdata = op->ffi};
5663 }
5664 if (prov.callback && !sec.protect(op->protection, prov, op->ffi->rng())) {
5665 FFI_LOG(op->ffi, "failed to encrypt the key");
5666 ret = RNP_ERROR_BAD_PARAMETERS;
5667 goto done;
5668 }
5669
5670 /* add secret key to the keyring */
5671 if (!(op->gen_sec = rnp_key_store_add_key(op->ffi->secring, &sec))) {
5672 ret = RNP_ERROR_OUT_OF_MEMORY;
5673 goto done;
5674 }
5675 ret = RNP_SUCCESS;
5676 done:
5677 op->password.clear();
5678 if (ret && op->gen_pub) {
5679 rnp_key_store_remove_key(op->ffi->pubring, op->gen_pub, false);
5680 op->gen_pub = NULL;
5681 }
5682 if (ret && op->gen_sec) {
5683 rnp_key_store_remove_key(op->ffi->secring, op->gen_sec, false);
5684 op->gen_sec = NULL;
5685 }
5686 return ret;
5687 }
5688 FFI_GUARD
5689
5690 rnp_result_t
rnp_op_generate_get_key(rnp_op_generate_t op,rnp_key_handle_t * handle)5691 rnp_op_generate_get_key(rnp_op_generate_t op, rnp_key_handle_t *handle)
5692 try {
5693 if (!op || !handle) {
5694 return RNP_ERROR_NULL_POINTER;
5695 }
5696 if (!op->gen_sec || !op->gen_pub) {
5697 return RNP_ERROR_BAD_PARAMETERS;
5698 }
5699
5700 *handle = (rnp_key_handle_t) malloc(sizeof(**handle));
5701 if (!*handle) {
5702 return RNP_ERROR_OUT_OF_MEMORY;
5703 }
5704 (*handle)->ffi = op->ffi;
5705 (*handle)->pub = op->gen_pub;
5706 (*handle)->sec = op->gen_sec;
5707 return RNP_SUCCESS;
5708 }
5709 FFI_GUARD
5710
5711 rnp_result_t
rnp_op_generate_destroy(rnp_op_generate_t op)5712 rnp_op_generate_destroy(rnp_op_generate_t op)
5713 try {
5714 delete op;
5715 return RNP_SUCCESS;
5716 }
5717 FFI_GUARD
5718
5719 rnp_result_t
rnp_key_handle_destroy(rnp_key_handle_t key)5720 rnp_key_handle_destroy(rnp_key_handle_t key)
5721 try {
5722 // This does not free key->key which is owned by the keyring
5723 free(key);
5724 return RNP_SUCCESS;
5725 }
5726 FFI_GUARD
5727
5728 void
rnp_buffer_destroy(void * ptr)5729 rnp_buffer_destroy(void *ptr)
5730 {
5731 free(ptr);
5732 }
5733
5734 void
rnp_buffer_clear(void * ptr,size_t size)5735 rnp_buffer_clear(void *ptr, size_t size)
5736 {
5737 if (ptr) {
5738 secure_clear(ptr, size);
5739 }
5740 }
5741
5742 static pgp_key_t *
get_key_require_public(rnp_key_handle_t handle)5743 get_key_require_public(rnp_key_handle_t handle)
5744 {
5745 if (!handle->pub) {
5746 pgp_key_request_ctx_t request;
5747 request.secret = false;
5748
5749 // try fingerprint
5750 request.search.type = PGP_KEY_SEARCH_FINGERPRINT;
5751 request.search.by.fingerprint = handle->sec->fp();
5752 handle->pub = pgp_request_key(&handle->ffi->key_provider, &request);
5753 if (handle->pub) {
5754 return handle->pub;
5755 }
5756
5757 // try keyid
5758 request.search.type = PGP_KEY_SEARCH_KEYID;
5759 request.search.by.keyid = handle->sec->keyid();
5760 handle->pub = pgp_request_key(&handle->ffi->key_provider, &request);
5761 }
5762 return handle->pub;
5763 }
5764
5765 static pgp_key_t *
get_key_prefer_public(rnp_key_handle_t handle)5766 get_key_prefer_public(rnp_key_handle_t handle)
5767 {
5768 pgp_key_t *pub = get_key_require_public(handle);
5769 return pub ? pub : get_key_require_secret(handle);
5770 }
5771
5772 static pgp_key_t *
get_key_require_secret(rnp_key_handle_t handle)5773 get_key_require_secret(rnp_key_handle_t handle)
5774 {
5775 if (!handle->sec) {
5776 pgp_key_request_ctx_t request;
5777 request.secret = true;
5778
5779 // try fingerprint
5780 request.search.type = PGP_KEY_SEARCH_FINGERPRINT;
5781 request.search.by.fingerprint = handle->pub->fp();
5782 handle->sec = pgp_request_key(&handle->ffi->key_provider, &request);
5783 if (handle->sec) {
5784 return handle->sec;
5785 }
5786
5787 // try keyid
5788 request.search.type = PGP_KEY_SEARCH_KEYID;
5789 request.search.by.keyid = handle->pub->keyid();
5790 handle->sec = pgp_request_key(&handle->ffi->key_provider, &request);
5791 }
5792 return handle->sec;
5793 }
5794
5795 static rnp_result_t
key_get_uid_at(pgp_key_t * key,size_t idx,char ** uid)5796 key_get_uid_at(pgp_key_t *key, size_t idx, char **uid)
5797 {
5798 if (!key || !uid) {
5799 return RNP_ERROR_NULL_POINTER;
5800 }
5801 if (idx >= key->uid_count()) {
5802 return RNP_ERROR_BAD_PARAMETERS;
5803 }
5804 *uid = strdup(key->get_uid(idx).str.c_str());
5805 if (!*uid) {
5806 return RNP_ERROR_OUT_OF_MEMORY;
5807 }
5808 return RNP_SUCCESS;
5809 }
5810
5811 rnp_result_t
rnp_key_add_uid(rnp_key_handle_t handle,const char * uid,const char * hash,uint32_t expiration,uint8_t key_flags,bool primary)5812 rnp_key_add_uid(rnp_key_handle_t handle,
5813 const char * uid,
5814 const char * hash,
5815 uint32_t expiration,
5816 uint8_t key_flags,
5817 bool primary)
5818 try {
5819 if (!handle || !uid) {
5820 return RNP_ERROR_NULL_POINTER;
5821 }
5822 /* setup parameters */
5823 if (!hash) {
5824 hash = DEFAULT_HASH_ALG;
5825 }
5826 pgp_hash_alg_t hash_alg = PGP_HASH_UNKNOWN;
5827 if (!str_to_hash_alg(hash, &hash_alg)) {
5828 FFI_LOG(handle->ffi, "Invalid hash: %s", hash);
5829 return RNP_ERROR_BAD_PARAMETERS;
5830 }
5831
5832 rnp_selfsig_cert_info_t info = {};
5833 size_t uid_len = strlen(uid);
5834 if (uid_len >= sizeof(info.userid)) {
5835 FFI_LOG(handle->ffi, "UserID too long");
5836 return RNP_ERROR_BAD_PARAMETERS;
5837 }
5838 memcpy(info.userid, uid, uid_len + 1);
5839 info.key_flags = key_flags;
5840 info.key_expiration = expiration;
5841 info.primary = primary;
5842
5843 /* obtain and unlok secret key */
5844 pgp_key_t *secret_key = get_key_require_secret(handle);
5845 if (!secret_key) {
5846 return RNP_ERROR_NO_SUITABLE_KEY;
5847 }
5848 pgp_key_t *public_key = get_key_prefer_public(handle);
5849 if (!public_key && secret_key->format == PGP_KEY_STORE_G10) {
5850 return RNP_ERROR_NO_SUITABLE_KEY;
5851 }
5852 rnp::KeyLocker seclock(*secret_key);
5853 if (secret_key->is_locked() &&
5854 !secret_key->unlock(handle->ffi->pass_provider, PGP_OP_ADD_USERID)) {
5855 return RNP_ERROR_BAD_PASSWORD;
5856 }
5857 /* add and certify userid */
5858 secret_key->add_uid_cert(info, hash_alg, handle->ffi->context, public_key);
5859 return RNP_SUCCESS;
5860 }
5861 FFI_GUARD
5862
5863 rnp_result_t
rnp_key_get_primary_uid(rnp_key_handle_t handle,char ** uid)5864 rnp_key_get_primary_uid(rnp_key_handle_t handle, char **uid)
5865 try {
5866 if (!handle || !uid) {
5867 return RNP_ERROR_NULL_POINTER;
5868 }
5869
5870 pgp_key_t *key = get_key_prefer_public(handle);
5871 if (key->has_primary_uid()) {
5872 return key_get_uid_at(key, key->get_primary_uid(), uid);
5873 }
5874 for (size_t i = 0; i < key->uid_count(); i++) {
5875 if (!key->get_uid(i).valid) {
5876 continue;
5877 }
5878 return key_get_uid_at(key, i, uid);
5879 }
5880 return RNP_ERROR_BAD_PARAMETERS;
5881 }
5882 FFI_GUARD
5883
5884 rnp_result_t
rnp_key_get_uid_count(rnp_key_handle_t handle,size_t * count)5885 rnp_key_get_uid_count(rnp_key_handle_t handle, size_t *count)
5886 try {
5887 if (!handle || !count) {
5888 return RNP_ERROR_NULL_POINTER;
5889 }
5890
5891 *count = get_key_prefer_public(handle)->uid_count();
5892 return RNP_SUCCESS;
5893 }
5894 FFI_GUARD
5895
5896 rnp_result_t
rnp_key_get_uid_at(rnp_key_handle_t handle,size_t idx,char ** uid)5897 rnp_key_get_uid_at(rnp_key_handle_t handle, size_t idx, char **uid)
5898 try {
5899 if (handle == NULL || uid == NULL)
5900 return RNP_ERROR_NULL_POINTER;
5901
5902 pgp_key_t *key = get_key_prefer_public(handle);
5903 return key_get_uid_at(key, idx, uid);
5904 }
5905 FFI_GUARD
5906
5907 rnp_result_t
rnp_key_get_uid_handle_at(rnp_key_handle_t key,size_t idx,rnp_uid_handle_t * uid)5908 rnp_key_get_uid_handle_at(rnp_key_handle_t key, size_t idx, rnp_uid_handle_t *uid)
5909 try {
5910 if (!key || !uid) {
5911 return RNP_ERROR_NULL_POINTER;
5912 }
5913
5914 pgp_key_t *akey = get_key_prefer_public(key);
5915 if (!akey) {
5916 return RNP_ERROR_BAD_PARAMETERS;
5917 }
5918
5919 if (idx >= akey->uid_count()) {
5920 return RNP_ERROR_BAD_PARAMETERS;
5921 }
5922
5923 *uid = (rnp_uid_handle_t) malloc(sizeof(**uid));
5924 if (!*uid) {
5925 return RNP_ERROR_OUT_OF_MEMORY;
5926 }
5927
5928 (*uid)->ffi = key->ffi;
5929 (*uid)->key = akey;
5930 (*uid)->idx = idx;
5931 return RNP_SUCCESS;
5932 }
5933 FFI_GUARD
5934
5935 static pgp_userid_t *
rnp_uid_handle_get_uid(rnp_uid_handle_t uid)5936 rnp_uid_handle_get_uid(rnp_uid_handle_t uid)
5937 {
5938 if (!uid || !uid->key) {
5939 return NULL;
5940 }
5941 return &uid->key->get_uid(uid->idx);
5942 }
5943
5944 rnp_result_t
rnp_uid_get_type(rnp_uid_handle_t uid,uint32_t * type)5945 rnp_uid_get_type(rnp_uid_handle_t uid, uint32_t *type)
5946 try {
5947 if (!type) {
5948 return RNP_ERROR_NULL_POINTER;
5949 }
5950 pgp_userid_t *id = rnp_uid_handle_get_uid(uid);
5951 if (!id) {
5952 return RNP_ERROR_NULL_POINTER;
5953 }
5954 switch (id->pkt.tag) {
5955 case PGP_PKT_USER_ID:
5956 *type = RNP_USER_ID;
5957 return RNP_SUCCESS;
5958 case PGP_PKT_USER_ATTR:
5959 *type = RNP_USER_ATTR;
5960 return RNP_SUCCESS;
5961 default:
5962 return RNP_ERROR_BAD_STATE;
5963 }
5964 }
5965 FFI_GUARD
5966
5967 rnp_result_t
rnp_uid_get_data(rnp_uid_handle_t uid,void ** data,size_t * size)5968 rnp_uid_get_data(rnp_uid_handle_t uid, void **data, size_t *size)
5969 try {
5970 if (!data || !size) {
5971 return RNP_ERROR_NULL_POINTER;
5972 }
5973 pgp_userid_t *id = rnp_uid_handle_get_uid(uid);
5974 if (!id) {
5975 return RNP_ERROR_NULL_POINTER;
5976 }
5977 *data = malloc(id->pkt.uid_len);
5978 if (id->pkt.uid_len && !*data) {
5979 return RNP_ERROR_OUT_OF_MEMORY;
5980 }
5981 memcpy(*data, id->pkt.uid, id->pkt.uid_len);
5982 *size = id->pkt.uid_len;
5983 return RNP_SUCCESS;
5984 }
5985 FFI_GUARD
5986
5987 rnp_result_t
rnp_uid_is_primary(rnp_uid_handle_t uid,bool * primary)5988 rnp_uid_is_primary(rnp_uid_handle_t uid, bool *primary)
5989 try {
5990 if (!primary) {
5991 return RNP_ERROR_NULL_POINTER;
5992 }
5993 pgp_userid_t *id = rnp_uid_handle_get_uid(uid);
5994 if (!id) {
5995 return RNP_ERROR_NULL_POINTER;
5996 }
5997 *primary = uid->key->has_primary_uid() && (uid->key->get_primary_uid() == uid->idx);
5998 return RNP_SUCCESS;
5999 }
6000 FFI_GUARD
6001
6002 rnp_result_t
rnp_uid_is_valid(rnp_uid_handle_t uid,bool * valid)6003 rnp_uid_is_valid(rnp_uid_handle_t uid, bool *valid)
6004 try {
6005 if (!valid) {
6006 return RNP_ERROR_NULL_POINTER;
6007 }
6008 pgp_userid_t *id = rnp_uid_handle_get_uid(uid);
6009 if (!id) {
6010 return RNP_ERROR_NULL_POINTER;
6011 }
6012 *valid = id->valid;
6013 return RNP_SUCCESS;
6014 }
6015 FFI_GUARD
6016
6017 static rnp_result_t
rnp_key_return_signature(rnp_ffi_t ffi,pgp_key_t * key,pgp_subsig_t * subsig,rnp_signature_handle_t * sig)6018 rnp_key_return_signature(rnp_ffi_t ffi,
6019 pgp_key_t * key,
6020 pgp_subsig_t * subsig,
6021 rnp_signature_handle_t *sig)
6022 {
6023 *sig = (rnp_signature_handle_t) calloc(1, sizeof(**sig));
6024 if (!*sig) {
6025 return RNP_ERROR_OUT_OF_MEMORY;
6026 }
6027 (*sig)->ffi = ffi;
6028 (*sig)->key = key;
6029 (*sig)->sig = subsig;
6030 return RNP_SUCCESS;
6031 }
6032
6033 rnp_result_t
rnp_key_get_signature_count(rnp_key_handle_t handle,size_t * count)6034 rnp_key_get_signature_count(rnp_key_handle_t handle, size_t *count)
6035 try {
6036 if (!handle || !count) {
6037 return RNP_ERROR_NULL_POINTER;
6038 }
6039 pgp_key_t *key = get_key_prefer_public(handle);
6040 if (!key) {
6041 return RNP_ERROR_BAD_PARAMETERS;
6042 }
6043 *count = key->keysig_count();
6044 return RNP_SUCCESS;
6045 }
6046 FFI_GUARD
6047
6048 rnp_result_t
rnp_key_get_signature_at(rnp_key_handle_t handle,size_t idx,rnp_signature_handle_t * sig)6049 rnp_key_get_signature_at(rnp_key_handle_t handle, size_t idx, rnp_signature_handle_t *sig)
6050 try {
6051 if (!handle || !sig) {
6052 return RNP_ERROR_NULL_POINTER;
6053 }
6054
6055 pgp_key_t *key = get_key_prefer_public(handle);
6056 if (!key || (idx >= key->keysig_count())) {
6057 return RNP_ERROR_BAD_PARAMETERS;
6058 }
6059 return rnp_key_return_signature(handle->ffi, key, &key->get_keysig(idx), sig);
6060 }
6061 FFI_GUARD
6062
6063 rnp_result_t
rnp_key_get_revocation_signature(rnp_key_handle_t handle,rnp_signature_handle_t * sig)6064 rnp_key_get_revocation_signature(rnp_key_handle_t handle, rnp_signature_handle_t *sig)
6065 try {
6066 if (!handle || !sig) {
6067 return RNP_ERROR_NULL_POINTER;
6068 }
6069 pgp_key_t *key = get_key_prefer_public(handle);
6070 if (!key) {
6071 return RNP_ERROR_BAD_PARAMETERS;
6072 }
6073 if (!key->revoked()) {
6074 *sig = NULL;
6075 return RNP_SUCCESS;
6076 }
6077 if (!key->has_sig(key->revocation().sigid)) {
6078 return RNP_ERROR_BAD_STATE;
6079 }
6080 return rnp_key_return_signature(
6081 handle->ffi, key, &key->get_sig(key->revocation().sigid), sig);
6082 }
6083 FFI_GUARD
6084
6085 rnp_result_t
rnp_uid_get_signature_count(rnp_uid_handle_t handle,size_t * count)6086 rnp_uid_get_signature_count(rnp_uid_handle_t handle, size_t *count)
6087 try {
6088 if (!handle || !count) {
6089 return RNP_ERROR_NULL_POINTER;
6090 }
6091 if (!handle->key) {
6092 return RNP_ERROR_BAD_PARAMETERS;
6093 }
6094 *count = handle->key->get_uid(handle->idx).sig_count();
6095 return RNP_SUCCESS;
6096 }
6097 FFI_GUARD
6098
6099 rnp_result_t
rnp_uid_get_signature_at(rnp_uid_handle_t handle,size_t idx,rnp_signature_handle_t * sig)6100 rnp_uid_get_signature_at(rnp_uid_handle_t handle, size_t idx, rnp_signature_handle_t *sig)
6101 try {
6102 if (!handle || !sig) {
6103 return RNP_ERROR_NULL_POINTER;
6104 }
6105 if (!handle->key) {
6106 return RNP_ERROR_BAD_PARAMETERS;
6107 }
6108 pgp_userid_t &uid = handle->key->get_uid(handle->idx);
6109 if (idx >= uid.sig_count()) {
6110 return RNP_ERROR_BAD_PARAMETERS;
6111 }
6112 const pgp_sig_id_t &sigid = uid.get_sig(idx);
6113 if (!handle->key->has_sig(sigid)) {
6114 return RNP_ERROR_BAD_STATE;
6115 }
6116 return rnp_key_return_signature(
6117 handle->ffi, handle->key, &handle->key->get_sig(sigid), sig);
6118 }
6119 FFI_GUARD
6120
6121 rnp_result_t
rnp_signature_get_type(rnp_signature_handle_t handle,char ** type)6122 rnp_signature_get_type(rnp_signature_handle_t handle, char **type)
6123 try {
6124 if (!handle || !type) {
6125 return RNP_ERROR_NULL_POINTER;
6126 }
6127 if (!handle->sig) {
6128 return RNP_ERROR_BAD_PARAMETERS;
6129 }
6130 auto sigtype = id_str_pair::lookup(sig_type_map, handle->sig->sig.type());
6131 return ret_str_value(sigtype, type);
6132 }
6133 FFI_GUARD
6134
6135 rnp_result_t
rnp_signature_get_alg(rnp_signature_handle_t handle,char ** alg)6136 rnp_signature_get_alg(rnp_signature_handle_t handle, char **alg)
6137 try {
6138 if (!handle || !alg) {
6139 return RNP_ERROR_NULL_POINTER;
6140 }
6141 if (!handle->sig) {
6142 return RNP_ERROR_BAD_PARAMETERS;
6143 }
6144 return get_map_value(pubkey_alg_map, handle->sig->sig.palg, alg);
6145 }
6146 FFI_GUARD
6147
6148 rnp_result_t
rnp_signature_get_hash_alg(rnp_signature_handle_t handle,char ** alg)6149 rnp_signature_get_hash_alg(rnp_signature_handle_t handle, char **alg)
6150 try {
6151 if (!handle || !alg) {
6152 return RNP_ERROR_NULL_POINTER;
6153 }
6154 if (!handle->sig) {
6155 return RNP_ERROR_BAD_PARAMETERS;
6156 }
6157 return get_map_value(hash_alg_map, handle->sig->sig.halg, alg);
6158 }
6159 FFI_GUARD
6160
6161 rnp_result_t
rnp_signature_get_creation(rnp_signature_handle_t handle,uint32_t * create)6162 rnp_signature_get_creation(rnp_signature_handle_t handle, uint32_t *create)
6163 try {
6164 if (!handle || !create) {
6165 return RNP_ERROR_NULL_POINTER;
6166 }
6167 if (!handle->sig) {
6168 return RNP_ERROR_BAD_PARAMETERS;
6169 }
6170 *create = handle->sig->sig.creation();
6171 return RNP_SUCCESS;
6172 }
6173 FFI_GUARD
6174
6175 rnp_result_t
rnp_signature_get_expiration(rnp_signature_handle_t handle,uint32_t * expires)6176 rnp_signature_get_expiration(rnp_signature_handle_t handle, uint32_t *expires)
6177 try {
6178 if (!handle || !expires) {
6179 return RNP_ERROR_NULL_POINTER;
6180 }
6181 if (!handle->sig) {
6182 return RNP_ERROR_BAD_PARAMETERS;
6183 }
6184 *expires = handle->sig->sig.expiration();
6185 return RNP_SUCCESS;
6186 }
6187 FFI_GUARD
6188
6189 rnp_result_t
rnp_signature_get_keyid(rnp_signature_handle_t handle,char ** result)6190 rnp_signature_get_keyid(rnp_signature_handle_t handle, char **result)
6191 try {
6192 if (!handle || !result) {
6193 return RNP_ERROR_NULL_POINTER;
6194 }
6195 if (!handle->sig) {
6196 return RNP_ERROR_BAD_PARAMETERS;
6197 }
6198 if (!handle->sig->sig.has_keyid()) {
6199 *result = NULL;
6200 return RNP_SUCCESS;
6201 }
6202 pgp_key_id_t keyid = handle->sig->sig.keyid();
6203 return hex_encode_value(keyid.data(), keyid.size(), result);
6204 }
6205 FFI_GUARD
6206
6207 rnp_result_t
rnp_signature_get_signer(rnp_signature_handle_t sig,rnp_key_handle_t * key)6208 rnp_signature_get_signer(rnp_signature_handle_t sig, rnp_key_handle_t *key)
6209 try {
6210 if (!sig || !sig->sig) {
6211 return RNP_ERROR_BAD_PARAMETERS;
6212 }
6213 if (!sig->sig->sig.has_keyid()) {
6214 *key = NULL;
6215 return RNP_SUCCESS;
6216 }
6217 pgp_key_search_t locator = {};
6218 locator.type = PGP_KEY_SEARCH_KEYID;
6219 locator.by.keyid = sig->sig->sig.keyid();
6220 return rnp_locate_key_int(sig->ffi, locator, key);
6221 }
6222 FFI_GUARD
6223
6224 rnp_result_t
rnp_signature_is_valid(rnp_signature_handle_t sig,uint32_t flags)6225 rnp_signature_is_valid(rnp_signature_handle_t sig, uint32_t flags)
6226 try {
6227 if (!sig) {
6228 return RNP_ERROR_NULL_POINTER;
6229 }
6230 if (!sig->sig || sig->own_sig || flags) {
6231 return RNP_ERROR_BAD_PARAMETERS;
6232 }
6233
6234 if (!sig->sig->validity.validated) {
6235 pgp_key_t *signer =
6236 pgp_sig_get_signer(*sig->sig, sig->ffi->pubring, &sig->ffi->key_provider);
6237 if (!signer) {
6238 return RNP_ERROR_KEY_NOT_FOUND;
6239 }
6240 signer->validate_sig(*sig->key, *sig->sig, sig->ffi->context);
6241 }
6242
6243 if (!sig->sig->validity.validated) {
6244 return RNP_ERROR_VERIFICATION_FAILED;
6245 }
6246 if (sig->sig->validity.expired) {
6247 return RNP_ERROR_SIGNATURE_EXPIRED;
6248 }
6249 return sig->sig->valid() ? RNP_SUCCESS : RNP_ERROR_SIGNATURE_INVALID;
6250 }
6251 FFI_GUARD
6252
6253 rnp_result_t
rnp_signature_packet_to_json(rnp_signature_handle_t sig,uint32_t flags,char ** json)6254 rnp_signature_packet_to_json(rnp_signature_handle_t sig, uint32_t flags, char **json)
6255 try {
6256 if (!sig || !json) {
6257 return RNP_ERROR_NULL_POINTER;
6258 }
6259
6260 pgp_dest_t memdst = {};
6261 if (init_mem_dest(&memdst, NULL, 0)) {
6262 return RNP_ERROR_OUT_OF_MEMORY;
6263 }
6264 try {
6265 sig->sig->sig.write(memdst);
6266 } catch (const std::exception &e) {
6267 FFI_LOG(sig->ffi, "%s", e.what());
6268 dst_close(&memdst, true);
6269 return RNP_ERROR_BAD_PARAMETERS;
6270 }
6271
6272 pgp_source_t memsrc = {};
6273 rnp_result_t ret = RNP_ERROR_BAD_STATE;
6274 if (init_mem_src(&memsrc, mem_dest_get_memory(&memdst), memdst.writeb, false)) {
6275 goto done;
6276 }
6277
6278 ret = rnp_dump_src_to_json(&memsrc, flags, json);
6279 done:
6280 dst_close(&memdst, true);
6281 src_close(&memsrc);
6282 return ret;
6283 }
6284 FFI_GUARD
6285
6286 rnp_result_t
rnp_signature_remove(rnp_key_handle_t key,rnp_signature_handle_t sig)6287 rnp_signature_remove(rnp_key_handle_t key, rnp_signature_handle_t sig)
6288 try {
6289 if (!key || !sig) {
6290 return RNP_ERROR_NULL_POINTER;
6291 }
6292 if (sig->own_sig || !sig->sig) {
6293 return RNP_ERROR_BAD_PARAMETERS;
6294 }
6295 pgp_key_t *pkey = get_key_require_public(key);
6296 pgp_key_t *skey = get_key_require_secret(key);
6297 if (!pkey && !skey) {
6298 return RNP_ERROR_BAD_PARAMETERS;
6299 }
6300 const pgp_sig_id_t sigid = sig->sig->sigid;
6301 bool ok = false;
6302 if (pkey) {
6303 ok = pkey->del_sig(sigid);
6304 pkey->revalidate(*key->ffi->pubring);
6305 }
6306 if (skey) {
6307 /* secret key may not have signature, but we still need to delete it at least once to
6308 * succeed */
6309 ok = skey->del_sig(sigid) || ok;
6310 skey->revalidate(*key->ffi->secring);
6311 }
6312 return ok ? RNP_SUCCESS : RNP_ERROR_NO_SIGNATURES_FOUND;
6313 }
6314 FFI_GUARD
6315
6316 rnp_result_t
rnp_signature_handle_destroy(rnp_signature_handle_t sig)6317 rnp_signature_handle_destroy(rnp_signature_handle_t sig)
6318 try {
6319 if (sig && sig->own_sig) {
6320 delete sig->sig;
6321 }
6322 free(sig);
6323 return RNP_SUCCESS;
6324 }
6325 FFI_GUARD
6326
6327 rnp_result_t
rnp_uid_is_revoked(rnp_uid_handle_t uid,bool * result)6328 rnp_uid_is_revoked(rnp_uid_handle_t uid, bool *result)
6329 try {
6330 if (!uid || !result) {
6331 return RNP_ERROR_NULL_POINTER;
6332 }
6333
6334 if (!uid->key) {
6335 return RNP_ERROR_BAD_PARAMETERS;
6336 }
6337
6338 *result = uid->key->get_uid(uid->idx).revoked;
6339 return RNP_SUCCESS;
6340 }
6341 FFI_GUARD
6342
6343 rnp_result_t
rnp_uid_get_revocation_signature(rnp_uid_handle_t uid,rnp_signature_handle_t * sig)6344 rnp_uid_get_revocation_signature(rnp_uid_handle_t uid, rnp_signature_handle_t *sig)
6345 try {
6346 if (!uid || !sig) {
6347 return RNP_ERROR_NULL_POINTER;
6348 }
6349 if (!uid->key) {
6350 return RNP_ERROR_BAD_PARAMETERS;
6351 }
6352 if (uid->idx >= uid->key->uid_count()) {
6353 return RNP_ERROR_BAD_STATE;
6354 }
6355 const pgp_userid_t &userid = uid->key->get_uid(uid->idx);
6356 if (!userid.revoked) {
6357 *sig = NULL;
6358 return RNP_SUCCESS;
6359 }
6360 if (!uid->key->has_sig(userid.revocation.sigid)) {
6361 return RNP_ERROR_BAD_STATE;
6362 }
6363 return rnp_key_return_signature(
6364 uid->ffi, uid->key, &uid->key->get_sig(userid.revocation.sigid), sig);
6365 }
6366 FFI_GUARD
6367
6368 rnp_result_t
rnp_uid_remove(rnp_key_handle_t key,rnp_uid_handle_t uid)6369 rnp_uid_remove(rnp_key_handle_t key, rnp_uid_handle_t uid)
6370 try {
6371 if (!key || !uid) {
6372 return RNP_ERROR_NULL_POINTER;
6373 }
6374 pgp_key_t *pkey = get_key_require_public(key);
6375 pgp_key_t *skey = get_key_require_secret(key);
6376 if (!pkey && !skey) {
6377 return RNP_ERROR_BAD_PARAMETERS;
6378 }
6379 if ((uid->key != pkey) && (uid->key != skey)) {
6380 return RNP_ERROR_BAD_PARAMETERS;
6381 }
6382
6383 bool ok = false;
6384 if (pkey && (pkey->uid_count() > uid->idx)) {
6385 pkey->del_uid(uid->idx);
6386 pkey->revalidate(*key->ffi->pubring);
6387 ok = true;
6388 }
6389 if (skey && (skey->uid_count() > uid->idx)) {
6390 skey->del_uid(uid->idx);
6391 skey->revalidate(*key->ffi->secring);
6392 ok = true;
6393 }
6394 return ok ? RNP_SUCCESS : RNP_ERROR_BAD_PARAMETERS;
6395 }
6396 FFI_GUARD
6397
6398 rnp_result_t
rnp_uid_handle_destroy(rnp_uid_handle_t uid)6399 rnp_uid_handle_destroy(rnp_uid_handle_t uid)
6400 try {
6401 free(uid);
6402 return RNP_SUCCESS;
6403 }
6404 FFI_GUARD
6405
6406 rnp_result_t
rnp_key_get_subkey_count(rnp_key_handle_t handle,size_t * count)6407 rnp_key_get_subkey_count(rnp_key_handle_t handle, size_t *count)
6408 try {
6409 if (!handle || !count) {
6410 return RNP_ERROR_NULL_POINTER;
6411 }
6412 pgp_key_t *key = get_key_prefer_public(handle);
6413 *count = key->subkey_count();
6414 return RNP_SUCCESS;
6415 }
6416 FFI_GUARD
6417
6418 rnp_result_t
rnp_key_get_subkey_at(rnp_key_handle_t handle,size_t idx,rnp_key_handle_t * subkey)6419 rnp_key_get_subkey_at(rnp_key_handle_t handle, size_t idx, rnp_key_handle_t *subkey)
6420 try {
6421 if (!handle || !subkey) {
6422 return RNP_ERROR_NULL_POINTER;
6423 }
6424 pgp_key_t *key = get_key_prefer_public(handle);
6425 if (idx >= key->subkey_count()) {
6426 return RNP_ERROR_BAD_PARAMETERS;
6427 }
6428 pgp_key_search_t locator = {};
6429 locator.type = PGP_KEY_SEARCH_FINGERPRINT;
6430 locator.by.fingerprint = key->get_subkey_fp(idx);
6431 return rnp_locate_key_int(handle->ffi, locator, subkey);
6432 }
6433 FFI_GUARD
6434
6435 rnp_result_t
rnp_key_get_default_key(rnp_key_handle_t primary_key,const char * usage,uint32_t flags,rnp_key_handle_t * default_key)6436 rnp_key_get_default_key(rnp_key_handle_t primary_key,
6437 const char * usage,
6438 uint32_t flags,
6439 rnp_key_handle_t *default_key)
6440 try {
6441 if (!primary_key || !usage || !default_key) {
6442 return RNP_ERROR_NULL_POINTER;
6443 }
6444 uint8_t keyflag = 0;
6445 bool no_primary = false;
6446 if (!str_to_key_flag(usage, &keyflag)) {
6447 return RNP_ERROR_BAD_PARAMETERS;
6448 }
6449 if (flags & RNP_KEY_SUBKEYS_ONLY) {
6450 no_primary = true;
6451 flags &= ~RNP_KEY_SUBKEYS_ONLY;
6452 }
6453 if (flags) {
6454 FFI_LOG(primary_key->ffi, "Invalid flags: %" PRIu32, flags);
6455 return RNP_ERROR_BAD_PARAMETERS;
6456 }
6457 pgp_key_t *key = get_key_prefer_public(primary_key);
6458 if (!key) {
6459 return RNP_ERROR_BAD_PARAMETERS;
6460 }
6461 pgp_key_t *defkey = find_suitable_key(
6462 PGP_OP_UNKNOWN, key, &primary_key->ffi->key_provider, keyflag, no_primary);
6463 if (!defkey) {
6464 *default_key = NULL;
6465 return RNP_ERROR_NO_SUITABLE_KEY;
6466 }
6467
6468 pgp_key_search_t search = {(pgp_key_search_type_t) 0};
6469 search.type = PGP_KEY_SEARCH_FINGERPRINT;
6470 search.by.fingerprint = defkey->fp();
6471
6472 bool require_secret = keyflag != PGP_KF_ENCRYPT;
6473 rnp_result_t ret =
6474 rnp_locate_key_int(primary_key->ffi, search, default_key, require_secret);
6475
6476 if (!*default_key && !ret) {
6477 return RNP_ERROR_NO_SUITABLE_KEY;
6478 }
6479
6480 return ret;
6481 }
6482 FFI_GUARD
6483
6484 rnp_result_t
rnp_key_get_alg(rnp_key_handle_t handle,char ** alg)6485 rnp_key_get_alg(rnp_key_handle_t handle, char **alg)
6486 try {
6487 if (!handle || !alg) {
6488 return RNP_ERROR_NULL_POINTER;
6489 }
6490 pgp_key_t *key = get_key_prefer_public(handle);
6491 return get_map_value(pubkey_alg_map, key->alg(), alg);
6492 }
6493 FFI_GUARD
6494
6495 rnp_result_t
rnp_key_get_bits(rnp_key_handle_t handle,uint32_t * bits)6496 rnp_key_get_bits(rnp_key_handle_t handle, uint32_t *bits)
6497 try {
6498 if (!handle || !bits) {
6499 return RNP_ERROR_NULL_POINTER;
6500 }
6501 pgp_key_t *key = get_key_prefer_public(handle);
6502 size_t _bits = key->material().bits();
6503 if (!_bits) {
6504 return RNP_ERROR_BAD_PARAMETERS;
6505 }
6506 *bits = _bits;
6507 return RNP_SUCCESS;
6508 }
6509 FFI_GUARD
6510
6511 rnp_result_t
rnp_key_get_dsa_qbits(rnp_key_handle_t handle,uint32_t * qbits)6512 rnp_key_get_dsa_qbits(rnp_key_handle_t handle, uint32_t *qbits)
6513 try {
6514 if (!handle || !qbits) {
6515 return RNP_ERROR_NULL_POINTER;
6516 }
6517 pgp_key_t *key = get_key_prefer_public(handle);
6518 size_t _qbits = key->material().qbits();
6519 if (!_qbits) {
6520 return RNP_ERROR_BAD_PARAMETERS;
6521 }
6522 *qbits = _qbits;
6523 return RNP_SUCCESS;
6524 }
6525 FFI_GUARD
6526
6527 rnp_result_t
rnp_key_get_curve(rnp_key_handle_t handle,char ** curve)6528 rnp_key_get_curve(rnp_key_handle_t handle, char **curve)
6529 try {
6530 if (!handle || !curve) {
6531 return RNP_ERROR_NULL_POINTER;
6532 }
6533 pgp_key_t * key = get_key_prefer_public(handle);
6534 pgp_curve_t _curve = key->curve();
6535 if (_curve == PGP_CURVE_UNKNOWN) {
6536 return RNP_ERROR_BAD_PARAMETERS;
6537 }
6538 const char *curvename = NULL;
6539 if (!curve_type_to_str(_curve, &curvename)) {
6540 return RNP_ERROR_BAD_PARAMETERS;
6541 }
6542 char *curvenamecp = strdup(curvename);
6543 if (!curvenamecp) {
6544 return RNP_ERROR_OUT_OF_MEMORY;
6545 }
6546 *curve = curvenamecp;
6547 return RNP_SUCCESS;
6548 }
6549 FFI_GUARD
6550
6551 rnp_result_t
rnp_key_get_fprint(rnp_key_handle_t handle,char ** fprint)6552 rnp_key_get_fprint(rnp_key_handle_t handle, char **fprint)
6553 try {
6554 if (!handle || !fprint) {
6555 return RNP_ERROR_NULL_POINTER;
6556 }
6557
6558 const pgp_fingerprint_t &fp = get_key_prefer_public(handle)->fp();
6559 return hex_encode_value(fp.fingerprint, fp.length, fprint);
6560 }
6561 FFI_GUARD
6562
6563 rnp_result_t
rnp_key_get_keyid(rnp_key_handle_t handle,char ** keyid)6564 rnp_key_get_keyid(rnp_key_handle_t handle, char **keyid)
6565 try {
6566 if (!handle || !keyid) {
6567 return RNP_ERROR_NULL_POINTER;
6568 }
6569
6570 pgp_key_t *key = get_key_prefer_public(handle);
6571 return hex_encode_value(key->keyid().data(), key->keyid().size(), keyid);
6572 }
6573 FFI_GUARD
6574
6575 rnp_result_t
rnp_key_get_grip(rnp_key_handle_t handle,char ** grip)6576 rnp_key_get_grip(rnp_key_handle_t handle, char **grip)
6577 try {
6578 if (!handle || !grip) {
6579 return RNP_ERROR_NULL_POINTER;
6580 }
6581
6582 const pgp_key_grip_t &kgrip = get_key_prefer_public(handle)->grip();
6583 return hex_encode_value(kgrip.data(), kgrip.size(), grip);
6584 }
6585 FFI_GUARD
6586
6587 static const pgp_key_grip_t *
rnp_get_grip_by_fp(rnp_ffi_t ffi,const pgp_fingerprint_t & fp)6588 rnp_get_grip_by_fp(rnp_ffi_t ffi, const pgp_fingerprint_t &fp)
6589 {
6590 pgp_key_t *key = NULL;
6591 if (ffi->pubring) {
6592 key = rnp_key_store_get_key_by_fpr(ffi->pubring, fp);
6593 }
6594 if (!key && ffi->secring) {
6595 key = rnp_key_store_get_key_by_fpr(ffi->secring, fp);
6596 }
6597 return key ? &key->grip() : NULL;
6598 }
6599
6600 rnp_result_t
rnp_key_get_primary_grip(rnp_key_handle_t handle,char ** grip)6601 rnp_key_get_primary_grip(rnp_key_handle_t handle, char **grip)
6602 try {
6603 if (!handle || !grip) {
6604 return RNP_ERROR_NULL_POINTER;
6605 }
6606
6607 pgp_key_t *key = get_key_prefer_public(handle);
6608 if (!key->is_subkey()) {
6609 return RNP_ERROR_BAD_PARAMETERS;
6610 }
6611 if (!key->has_primary_fp()) {
6612 *grip = NULL;
6613 return RNP_SUCCESS;
6614 }
6615 const pgp_key_grip_t *pgrip = rnp_get_grip_by_fp(handle->ffi, key->primary_fp());
6616 if (!pgrip) {
6617 *grip = NULL;
6618 return RNP_SUCCESS;
6619 }
6620 return hex_encode_value(pgrip->data(), pgrip->size(), grip);
6621 }
6622 FFI_GUARD
6623
6624 rnp_result_t
rnp_key_get_primary_fprint(rnp_key_handle_t handle,char ** fprint)6625 rnp_key_get_primary_fprint(rnp_key_handle_t handle, char **fprint)
6626 try {
6627 if (!handle || !fprint) {
6628 return RNP_ERROR_NULL_POINTER;
6629 }
6630
6631 pgp_key_t *key = get_key_prefer_public(handle);
6632 if (!key->is_subkey()) {
6633 return RNP_ERROR_BAD_PARAMETERS;
6634 }
6635 if (!key->has_primary_fp()) {
6636 *fprint = NULL;
6637 return RNP_SUCCESS;
6638 }
6639 const pgp_fingerprint_t &fp = key->primary_fp();
6640 return hex_encode_value(fp.fingerprint, fp.length, fprint);
6641 }
6642 FFI_GUARD
6643
6644 rnp_result_t
rnp_key_allows_usage(rnp_key_handle_t handle,const char * usage,bool * result)6645 rnp_key_allows_usage(rnp_key_handle_t handle, const char *usage, bool *result)
6646 try {
6647 if (!handle || !usage || !result) {
6648 return RNP_ERROR_NULL_POINTER;
6649 }
6650 uint8_t flag = 0;
6651 if (!str_to_key_flag(usage, &flag)) {
6652 return RNP_ERROR_BAD_PARAMETERS;
6653 }
6654 pgp_key_t *key = get_key_prefer_public(handle);
6655 if (!key) {
6656 return RNP_ERROR_BAD_PARAMETERS;
6657 }
6658 *result = key->flags() & flag;
6659 return RNP_SUCCESS;
6660 }
6661 FFI_GUARD
6662
6663 rnp_result_t
rnp_key_get_creation(rnp_key_handle_t handle,uint32_t * result)6664 rnp_key_get_creation(rnp_key_handle_t handle, uint32_t *result)
6665 try {
6666 if (!handle || !result) {
6667 return RNP_ERROR_NULL_POINTER;
6668 }
6669 pgp_key_t *key = get_key_prefer_public(handle);
6670 if (!key) {
6671 return RNP_ERROR_BAD_PARAMETERS;
6672 }
6673 *result = key->creation();
6674 return RNP_SUCCESS;
6675 }
6676 FFI_GUARD
6677
6678 rnp_result_t
rnp_key_is_revoked(rnp_key_handle_t handle,bool * result)6679 rnp_key_is_revoked(rnp_key_handle_t handle, bool *result)
6680 try {
6681 if (!handle || !result) {
6682 return RNP_ERROR_NULL_POINTER;
6683 }
6684 pgp_key_t *key = get_key_prefer_public(handle);
6685 if (!key) {
6686 return RNP_ERROR_BAD_PARAMETERS;
6687 }
6688 *result = key->revoked();
6689 return RNP_SUCCESS;
6690 }
6691 FFI_GUARD
6692
6693 rnp_result_t
rnp_key_is_valid(rnp_key_handle_t handle,bool * result)6694 rnp_key_is_valid(rnp_key_handle_t handle, bool *result)
6695 try {
6696 if (!handle || !result) {
6697 return RNP_ERROR_NULL_POINTER;
6698 }
6699 pgp_key_t *key = get_key_require_public(handle);
6700 if (!key) {
6701 return RNP_ERROR_BAD_PARAMETERS;
6702 }
6703 if (!key->validated()) {
6704 key->validate(*handle->ffi->pubring);
6705 }
6706 if (!key->validated()) {
6707 return RNP_ERROR_VERIFICATION_FAILED;
6708 }
6709 *result = key->valid();
6710 return RNP_SUCCESS;
6711 }
6712 FFI_GUARD
6713
6714 rnp_result_t
rnp_key_valid_till(rnp_key_handle_t handle,uint32_t * result)6715 rnp_key_valid_till(rnp_key_handle_t handle, uint32_t *result)
6716 try {
6717 if (!result) {
6718 return RNP_ERROR_NULL_POINTER;
6719 }
6720 uint64_t res = 0;
6721 rnp_result_t ret = rnp_key_valid_till64(handle, &res);
6722 if (ret) {
6723 return ret;
6724 }
6725 if (res == UINT64_MAX) {
6726 *result = UINT32_MAX;
6727 } else if (res >= UINT32_MAX) {
6728 *result = UINT32_MAX - 1;
6729 } else {
6730 *result = (uint32_t) res;
6731 }
6732 return RNP_SUCCESS;
6733 }
6734 FFI_GUARD
6735
6736 rnp_result_t
rnp_key_valid_till64(rnp_key_handle_t handle,uint64_t * result)6737 rnp_key_valid_till64(rnp_key_handle_t handle, uint64_t *result)
6738 try {
6739 if (!handle || !result) {
6740 return RNP_ERROR_NULL_POINTER;
6741 }
6742 pgp_key_t *key = get_key_require_public(handle);
6743 if (!key) {
6744 return RNP_ERROR_BAD_PARAMETERS;
6745 }
6746
6747 if (!key->validated()) {
6748 key->validate(*handle->ffi->pubring);
6749 }
6750 if (!key->validated()) {
6751 return RNP_ERROR_VERIFICATION_FAILED;
6752 }
6753
6754 if (key->is_subkey()) {
6755 /* check validity time of the primary key as well */
6756 pgp_key_t *primary = rnp_key_store_get_primary_key(handle->ffi->pubring, key);
6757 if (!primary) {
6758 /* no primary key - subkey considered as never valid */
6759 *result = 0;
6760 return RNP_SUCCESS;
6761 }
6762 if (!primary->validated()) {
6763 primary->validate(*handle->ffi->pubring);
6764 }
6765 if (!primary->validated()) {
6766 return RNP_ERROR_VERIFICATION_FAILED;
6767 }
6768 *result = key->valid_till();
6769 } else {
6770 *result = key->valid_till();
6771 }
6772 return RNP_SUCCESS;
6773 }
6774 FFI_GUARD
6775
6776 rnp_result_t
rnp_key_get_expiration(rnp_key_handle_t handle,uint32_t * result)6777 rnp_key_get_expiration(rnp_key_handle_t handle, uint32_t *result)
6778 try {
6779 if (!handle || !result) {
6780 return RNP_ERROR_NULL_POINTER;
6781 }
6782 pgp_key_t *key = get_key_prefer_public(handle);
6783 if (!key) {
6784 return RNP_ERROR_BAD_PARAMETERS;
6785 }
6786 *result = key->expiration();
6787 return RNP_SUCCESS;
6788 }
6789 FFI_GUARD
6790
6791 rnp_result_t
rnp_key_set_expiration(rnp_key_handle_t key,uint32_t expiry)6792 rnp_key_set_expiration(rnp_key_handle_t key, uint32_t expiry)
6793 try {
6794 if (!key) {
6795 return RNP_ERROR_NULL_POINTER;
6796 }
6797
6798 pgp_key_t *pkey = get_key_prefer_public(key);
6799 if (!pkey) {
6800 return RNP_ERROR_BAD_PARAMETERS;
6801 }
6802 pgp_key_t *skey = get_key_require_secret(key);
6803 if (!skey) {
6804 FFI_LOG(key->ffi, "Secret key required.");
6805 return RNP_ERROR_BAD_PARAMETERS;
6806 }
6807
6808 if (pkey->is_primary()) {
6809 if (!pgp_key_set_expiration(
6810 pkey, skey, expiry, key->ffi->pass_provider, key->ffi->context)) {
6811 return RNP_ERROR_GENERIC;
6812 }
6813 pkey->revalidate(*key->ffi->pubring);
6814 if (pkey != skey) {
6815 skey->revalidate(*key->ffi->secring);
6816 }
6817 return RNP_SUCCESS;
6818 }
6819
6820 /* for subkey we need primary key */
6821 if (!pkey->has_primary_fp()) {
6822 FFI_LOG(key->ffi, "Primary key fp not available.");
6823 return RNP_ERROR_BAD_PARAMETERS;
6824 }
6825
6826 pgp_key_search_t search = {};
6827 search.type = PGP_KEY_SEARCH_FINGERPRINT;
6828 search.by.fingerprint = pkey->primary_fp();
6829 pgp_key_t *prim_sec = find_key(key->ffi, &search, KEY_TYPE_SECRET, true);
6830 if (!prim_sec) {
6831 FFI_LOG(key->ffi, "Primary secret key not found.");
6832 return RNP_ERROR_KEY_NOT_FOUND;
6833 }
6834 if (!pgp_subkey_set_expiration(
6835 pkey, prim_sec, skey, expiry, key->ffi->pass_provider, key->ffi->context)) {
6836 return RNP_ERROR_GENERIC;
6837 }
6838 prim_sec->revalidate(*key->ffi->secring);
6839 pgp_key_t *prim_pub = find_key(key->ffi, &search, KEY_TYPE_PUBLIC, true);
6840 if (prim_pub) {
6841 prim_pub->revalidate(*key->ffi->pubring);
6842 }
6843 return RNP_SUCCESS;
6844 }
6845 FFI_GUARD
6846
6847 rnp_result_t
rnp_key_get_revocation_reason(rnp_key_handle_t handle,char ** result)6848 rnp_key_get_revocation_reason(rnp_key_handle_t handle, char **result)
6849 try {
6850 if (!handle || !result) {
6851 return RNP_ERROR_NULL_POINTER;
6852 }
6853 pgp_key_t *key = get_key_prefer_public(handle);
6854 if (!key || !key->revoked()) {
6855 return RNP_ERROR_BAD_PARAMETERS;
6856 }
6857
6858 *result = strdup(key->revocation().reason.c_str());
6859 if (!*result) {
6860 return RNP_ERROR_OUT_OF_MEMORY;
6861 }
6862 return RNP_SUCCESS;
6863 }
6864 FFI_GUARD
6865
6866 static rnp_result_t
rnp_key_is_revoked_with_code(rnp_key_handle_t handle,bool * result,int code)6867 rnp_key_is_revoked_with_code(rnp_key_handle_t handle, bool *result, int code)
6868 {
6869 if (!handle || !result) {
6870 return RNP_ERROR_NULL_POINTER;
6871 }
6872 pgp_key_t *key = get_key_prefer_public(handle);
6873 if (!key || !key->revoked()) {
6874 return RNP_ERROR_BAD_PARAMETERS;
6875 }
6876
6877 *result = key->revocation().code == code;
6878 return RNP_SUCCESS;
6879 }
6880
6881 rnp_result_t
rnp_key_is_superseded(rnp_key_handle_t handle,bool * result)6882 rnp_key_is_superseded(rnp_key_handle_t handle, bool *result)
6883 try {
6884 return rnp_key_is_revoked_with_code(handle, result, PGP_REVOCATION_SUPERSEDED);
6885 }
6886 FFI_GUARD
6887
6888 rnp_result_t
rnp_key_is_compromised(rnp_key_handle_t handle,bool * result)6889 rnp_key_is_compromised(rnp_key_handle_t handle, bool *result)
6890 try {
6891 return rnp_key_is_revoked_with_code(handle, result, PGP_REVOCATION_COMPROMISED);
6892 }
6893 FFI_GUARD
6894
6895 rnp_result_t
rnp_key_is_retired(rnp_key_handle_t handle,bool * result)6896 rnp_key_is_retired(rnp_key_handle_t handle, bool *result)
6897 try {
6898 return rnp_key_is_revoked_with_code(handle, result, PGP_REVOCATION_RETIRED);
6899 }
6900 FFI_GUARD
6901
6902 rnp_result_t
rnp_key_get_protection_type(rnp_key_handle_t key,char ** type)6903 rnp_key_get_protection_type(rnp_key_handle_t key, char **type)
6904 try {
6905 if (!key || !type) {
6906 return RNP_ERROR_NULL_POINTER;
6907 }
6908 if (!key->sec) {
6909 return RNP_ERROR_BAD_PARAMETERS;
6910 }
6911
6912 const pgp_s2k_t &s2k = key->sec->pkt().sec_protection.s2k;
6913 const char * res = "Unknown";
6914 if (s2k.usage == PGP_S2KU_NONE) {
6915 res = "None";
6916 }
6917 if ((s2k.usage == PGP_S2KU_ENCRYPTED) && (s2k.specifier != PGP_S2KS_EXPERIMENTAL)) {
6918 res = "Encrypted";
6919 }
6920 if ((s2k.usage == PGP_S2KU_ENCRYPTED_AND_HASHED) &&
6921 (s2k.specifier != PGP_S2KS_EXPERIMENTAL)) {
6922 res = "Encrypted-Hashed";
6923 }
6924 if ((s2k.specifier == PGP_S2KS_EXPERIMENTAL) &&
6925 (s2k.gpg_ext_num == PGP_S2K_GPG_NO_SECRET)) {
6926 res = "GPG-None";
6927 }
6928 if ((s2k.specifier == PGP_S2KS_EXPERIMENTAL) &&
6929 (s2k.gpg_ext_num == PGP_S2K_GPG_SMARTCARD)) {
6930 res = "GPG-Smartcard";
6931 }
6932
6933 return ret_str_value(res, type);
6934 }
6935 FFI_GUARD
6936
6937 rnp_result_t
rnp_key_get_protection_mode(rnp_key_handle_t key,char ** mode)6938 rnp_key_get_protection_mode(rnp_key_handle_t key, char **mode)
6939 try {
6940 if (!key || !mode) {
6941 return RNP_ERROR_NULL_POINTER;
6942 }
6943 if (!key->sec) {
6944 return RNP_ERROR_BAD_PARAMETERS;
6945 }
6946
6947 if (key->sec->pkt().sec_protection.s2k.usage == PGP_S2KU_NONE) {
6948 return ret_str_value("None", mode);
6949 }
6950 if (key->sec->pkt().sec_protection.s2k.specifier == PGP_S2KS_EXPERIMENTAL) {
6951 return ret_str_value("Unknown", mode);
6952 }
6953
6954 return get_map_value(cipher_mode_map, key->sec->pkt().sec_protection.cipher_mode, mode);
6955 }
6956 FFI_GUARD
6957
6958 static bool
pgp_key_has_encryption_info(const pgp_key_t * key)6959 pgp_key_has_encryption_info(const pgp_key_t *key)
6960 {
6961 return (key->pkt().sec_protection.s2k.usage != PGP_S2KU_NONE) &&
6962 (key->pkt().sec_protection.s2k.specifier != PGP_S2KS_EXPERIMENTAL);
6963 }
6964
6965 rnp_result_t
rnp_key_get_protection_cipher(rnp_key_handle_t key,char ** cipher)6966 rnp_key_get_protection_cipher(rnp_key_handle_t key, char **cipher)
6967 try {
6968 if (!key || !cipher) {
6969 return RNP_ERROR_NULL_POINTER;
6970 }
6971 if (!key->sec) {
6972 return RNP_ERROR_BAD_PARAMETERS;
6973 }
6974 if (!pgp_key_has_encryption_info(key->sec)) {
6975 return RNP_ERROR_BAD_PARAMETERS;
6976 }
6977
6978 return get_map_value(symm_alg_map, key->sec->pkt().sec_protection.symm_alg, cipher);
6979 }
6980 FFI_GUARD
6981
6982 rnp_result_t
rnp_key_get_protection_hash(rnp_key_handle_t key,char ** hash)6983 rnp_key_get_protection_hash(rnp_key_handle_t key, char **hash)
6984 try {
6985 if (!key || !hash) {
6986 return RNP_ERROR_NULL_POINTER;
6987 }
6988 if (!key->sec) {
6989 return RNP_ERROR_BAD_PARAMETERS;
6990 }
6991 if (!pgp_key_has_encryption_info(key->sec)) {
6992 return RNP_ERROR_BAD_PARAMETERS;
6993 }
6994
6995 return get_map_value(hash_alg_map, key->sec->pkt().sec_protection.s2k.hash_alg, hash);
6996 }
6997 FFI_GUARD
6998
6999 rnp_result_t
rnp_key_get_protection_iterations(rnp_key_handle_t key,size_t * iterations)7000 rnp_key_get_protection_iterations(rnp_key_handle_t key, size_t *iterations)
7001 try {
7002 if (!key || !iterations) {
7003 return RNP_ERROR_NULL_POINTER;
7004 }
7005 if (!key->sec) {
7006 return RNP_ERROR_BAD_PARAMETERS;
7007 }
7008 if (!pgp_key_has_encryption_info(key->sec)) {
7009 return RNP_ERROR_BAD_PARAMETERS;
7010 }
7011
7012 if (key->sec->pkt().sec_protection.s2k.specifier == PGP_S2KS_ITERATED_AND_SALTED) {
7013 *iterations = pgp_s2k_decode_iterations(key->sec->pkt().sec_protection.s2k.iterations);
7014 } else {
7015 *iterations = 1;
7016 }
7017 return RNP_SUCCESS;
7018 }
7019 FFI_GUARD
7020
7021 rnp_result_t
rnp_key_is_locked(rnp_key_handle_t handle,bool * result)7022 rnp_key_is_locked(rnp_key_handle_t handle, bool *result)
7023 try {
7024 if (handle == NULL || result == NULL)
7025 return RNP_ERROR_NULL_POINTER;
7026
7027 pgp_key_t *key = get_key_require_secret(handle);
7028 if (!key) {
7029 return RNP_ERROR_NO_SUITABLE_KEY;
7030 }
7031 *result = key->is_locked();
7032 return RNP_SUCCESS;
7033 }
7034 FFI_GUARD
7035
7036 rnp_result_t
rnp_key_lock(rnp_key_handle_t handle)7037 rnp_key_lock(rnp_key_handle_t handle)
7038 try {
7039 if (handle == NULL)
7040 return RNP_ERROR_NULL_POINTER;
7041
7042 pgp_key_t *key = get_key_require_secret(handle);
7043 if (!key) {
7044 return RNP_ERROR_NO_SUITABLE_KEY;
7045 }
7046 if (!key->lock()) {
7047 return RNP_ERROR_GENERIC;
7048 }
7049 return RNP_SUCCESS;
7050 }
7051 FFI_GUARD
7052
7053 rnp_result_t
rnp_key_unlock(rnp_key_handle_t handle,const char * password)7054 rnp_key_unlock(rnp_key_handle_t handle, const char *password)
7055 try {
7056 if (!handle) {
7057 return RNP_ERROR_NULL_POINTER;
7058 }
7059 pgp_key_t *key = get_key_require_secret(handle);
7060 if (!key) {
7061 return RNP_ERROR_NO_SUITABLE_KEY;
7062 }
7063 bool ok = false;
7064 if (password) {
7065 pgp_password_provider_t prov = {
7066 .callback = rnp_password_provider_string,
7067 .userdata = reinterpret_cast<void *>(const_cast<char *>(password))};
7068 ok = key->unlock(prov);
7069 } else {
7070 ok = key->unlock(handle->ffi->pass_provider);
7071 }
7072 if (!ok) {
7073 // likely a bad password
7074 return RNP_ERROR_BAD_PASSWORD;
7075 }
7076 return RNP_SUCCESS;
7077 }
7078 FFI_GUARD
7079
7080 rnp_result_t
rnp_key_is_protected(rnp_key_handle_t handle,bool * result)7081 rnp_key_is_protected(rnp_key_handle_t handle, bool *result)
7082 try {
7083 if (handle == NULL || result == NULL)
7084 return RNP_ERROR_NULL_POINTER;
7085
7086 pgp_key_t *key = get_key_require_secret(handle);
7087 if (!key) {
7088 return RNP_ERROR_NO_SUITABLE_KEY;
7089 }
7090 *result = key->is_protected();
7091 return RNP_SUCCESS;
7092 }
7093 FFI_GUARD
7094
7095 rnp_result_t
rnp_key_protect(rnp_key_handle_t handle,const char * password,const char * cipher,const char * cipher_mode,const char * hash,size_t iterations)7096 rnp_key_protect(rnp_key_handle_t handle,
7097 const char * password,
7098 const char * cipher,
7099 const char * cipher_mode,
7100 const char * hash,
7101 size_t iterations)
7102 try {
7103 rnp_key_protection_params_t protection = {};
7104
7105 // checks
7106 if (!handle || !password) {
7107 return RNP_ERROR_NULL_POINTER;
7108 }
7109
7110 if (cipher && !str_to_cipher(cipher, &protection.symm_alg)) {
7111 FFI_LOG(handle->ffi, "Invalid cipher: %s", cipher);
7112 return RNP_ERROR_BAD_PARAMETERS;
7113 }
7114 if (cipher_mode && !str_to_cipher_mode(cipher_mode, &protection.cipher_mode)) {
7115 FFI_LOG(handle->ffi, "Invalid cipher mode: %s", cipher_mode);
7116 return RNP_ERROR_BAD_PARAMETERS;
7117 }
7118 if (hash && !str_to_hash_alg(hash, &protection.hash_alg)) {
7119 FFI_LOG(handle->ffi, "Invalid hash: %s", hash);
7120 return RNP_ERROR_BAD_PARAMETERS;
7121 }
7122 protection.iterations = iterations;
7123
7124 // get the key
7125 pgp_key_t *key = get_key_require_secret(handle);
7126 if (!key) {
7127 return RNP_ERROR_NO_SUITABLE_KEY;
7128 }
7129 pgp_key_pkt_t * decrypted_key = NULL;
7130 const std::string pass = password;
7131 if (key->encrypted()) {
7132 pgp_password_ctx_t ctx = {.op = PGP_OP_PROTECT, .key = key};
7133 decrypted_key = pgp_decrypt_seckey(*key, handle->ffi->pass_provider, ctx);
7134 if (!decrypted_key) {
7135 return RNP_ERROR_GENERIC;
7136 }
7137 }
7138 bool res = key->protect(
7139 decrypted_key ? *decrypted_key : key->pkt(), protection, pass, handle->ffi->rng());
7140 delete decrypted_key;
7141 return res ? RNP_SUCCESS : RNP_ERROR_GENERIC;
7142 }
7143 FFI_GUARD
7144
7145 rnp_result_t
rnp_key_unprotect(rnp_key_handle_t handle,const char * password)7146 rnp_key_unprotect(rnp_key_handle_t handle, const char *password)
7147 try {
7148 // checks
7149 if (!handle) {
7150 return RNP_ERROR_NULL_POINTER;
7151 }
7152
7153 // get the key
7154 pgp_key_t *key = get_key_require_secret(handle);
7155 if (!key) {
7156 return RNP_ERROR_NO_SUITABLE_KEY;
7157 }
7158 bool ok = false;
7159 if (password) {
7160 pgp_password_provider_t prov = {
7161 .callback = rnp_password_provider_string,
7162 .userdata = reinterpret_cast<void *>(const_cast<char *>(password))};
7163 ok = key->unprotect(prov, handle->ffi->rng());
7164 } else {
7165 ok = key->unprotect(handle->ffi->pass_provider, handle->ffi->rng());
7166 }
7167 if (!ok) {
7168 // likely a bad password
7169 return RNP_ERROR_BAD_PASSWORD;
7170 }
7171 return RNP_SUCCESS;
7172 }
7173 FFI_GUARD
7174
7175 rnp_result_t
rnp_key_is_primary(rnp_key_handle_t handle,bool * result)7176 rnp_key_is_primary(rnp_key_handle_t handle, bool *result)
7177 try {
7178 if (handle == NULL || result == NULL)
7179 return RNP_ERROR_NULL_POINTER;
7180
7181 pgp_key_t *key = get_key_prefer_public(handle);
7182 if (key->format == PGP_KEY_STORE_G10) {
7183 // we can't currently determine this for a G10 secret key
7184 return RNP_ERROR_NO_SUITABLE_KEY;
7185 }
7186 *result = key->is_primary();
7187 return RNP_SUCCESS;
7188 }
7189 FFI_GUARD
7190
7191 rnp_result_t
rnp_key_is_sub(rnp_key_handle_t handle,bool * result)7192 rnp_key_is_sub(rnp_key_handle_t handle, bool *result)
7193 try {
7194 if (handle == NULL || result == NULL)
7195 return RNP_ERROR_NULL_POINTER;
7196
7197 pgp_key_t *key = get_key_prefer_public(handle);
7198 if (key->format == PGP_KEY_STORE_G10) {
7199 // we can't currently determine this for a G10 secret key
7200 return RNP_ERROR_NO_SUITABLE_KEY;
7201 }
7202 *result = key->is_subkey();
7203 return RNP_SUCCESS;
7204 }
7205 FFI_GUARD
7206
7207 rnp_result_t
rnp_key_have_secret(rnp_key_handle_t handle,bool * result)7208 rnp_key_have_secret(rnp_key_handle_t handle, bool *result)
7209 try {
7210 if (handle == NULL || result == NULL)
7211 return RNP_ERROR_NULL_POINTER;
7212
7213 *result = handle->sec != NULL;
7214 return RNP_SUCCESS;
7215 }
7216 FFI_GUARD
7217
7218 rnp_result_t
rnp_key_have_public(rnp_key_handle_t handle,bool * result)7219 rnp_key_have_public(rnp_key_handle_t handle, bool *result)
7220 try {
7221 if (handle == NULL || result == NULL)
7222 return RNP_ERROR_NULL_POINTER;
7223 *result = handle->pub != NULL;
7224 return RNP_SUCCESS;
7225 }
7226 FFI_GUARD
7227
7228 static rnp_result_t
key_to_bytes(pgp_key_t * key,uint8_t ** buf,size_t * buf_len)7229 key_to_bytes(pgp_key_t *key, uint8_t **buf, size_t *buf_len)
7230 {
7231 pgp_dest_t memdst = {};
7232
7233 if (init_mem_dest(&memdst, NULL, 0)) {
7234 return RNP_ERROR_OUT_OF_MEMORY;
7235 }
7236
7237 key->write(memdst);
7238 if (memdst.werr) {
7239 dst_close(&memdst, true);
7240 return RNP_ERROR_OUT_OF_MEMORY;
7241 }
7242
7243 *buf_len = memdst.writeb;
7244 *buf = (uint8_t *) mem_dest_own_memory(&memdst);
7245 dst_close(&memdst, true);
7246 if (*buf_len && !*buf) {
7247 return RNP_ERROR_OUT_OF_MEMORY;
7248 }
7249 return RNP_SUCCESS;
7250 }
7251
7252 rnp_result_t
rnp_get_public_key_data(rnp_key_handle_t handle,uint8_t ** buf,size_t * buf_len)7253 rnp_get_public_key_data(rnp_key_handle_t handle, uint8_t **buf, size_t *buf_len)
7254 try {
7255 // checks
7256 if (!handle || !buf || !buf_len) {
7257 return RNP_ERROR_NULL_POINTER;
7258 }
7259
7260 pgp_key_t *key = handle->pub;
7261 if (!key) {
7262 return RNP_ERROR_NO_SUITABLE_KEY;
7263 }
7264 return key_to_bytes(key, buf, buf_len);
7265 }
7266 FFI_GUARD
7267
7268 rnp_result_t
rnp_get_secret_key_data(rnp_key_handle_t handle,uint8_t ** buf,size_t * buf_len)7269 rnp_get_secret_key_data(rnp_key_handle_t handle, uint8_t **buf, size_t *buf_len)
7270 try {
7271 // checks
7272 if (!handle || !buf || !buf_len) {
7273 return RNP_ERROR_NULL_POINTER;
7274 }
7275
7276 pgp_key_t *key = handle->sec;
7277 if (!key) {
7278 return RNP_ERROR_NO_SUITABLE_KEY;
7279 }
7280 return key_to_bytes(key, buf, buf_len);
7281 }
7282 FFI_GUARD
7283
7284 static bool
add_json_string_field(json_object * jso,const char * key,const char * value)7285 add_json_string_field(json_object *jso, const char *key, const char *value)
7286 {
7287 json_object *jsostr = json_object_new_string(value);
7288 if (!jsostr) {
7289 return false;
7290 }
7291 json_object_object_add(jso, key, jsostr);
7292 return true;
7293 }
7294
7295 static bool
add_json_int_field(json_object * jso,const char * key,int32_t value)7296 add_json_int_field(json_object *jso, const char *key, int32_t value)
7297 {
7298 json_object *jsoval = json_object_new_int(value);
7299 if (!jsoval) {
7300 return false;
7301 }
7302 json_object_object_add(jso, key, jsoval);
7303 return true;
7304 }
7305
7306 static bool
add_json_key_usage(json_object * jso,uint8_t key_flags)7307 add_json_key_usage(json_object *jso, uint8_t key_flags)
7308 {
7309 json_object *jsoarr = json_object_new_array();
7310 if (!jsoarr) {
7311 return false;
7312 }
7313 for (size_t i = 0; i < ARRAY_SIZE(key_usage_map); i++) {
7314 if (key_usage_map[i].id & key_flags) {
7315 json_object *jsostr = json_object_new_string(key_usage_map[i].str);
7316 if (!jsostr || json_object_array_add(jsoarr, jsostr)) {
7317 json_object_put(jsoarr);
7318 return false;
7319 }
7320 }
7321 }
7322 if (json_object_array_length(jsoarr)) {
7323 json_object_object_add(jso, "usage", jsoarr);
7324 } else {
7325 json_object_put(jsoarr);
7326 }
7327 return true;
7328 }
7329
7330 static bool
add_json_key_flags(json_object * jso,uint8_t key_flags)7331 add_json_key_flags(json_object *jso, uint8_t key_flags)
7332 {
7333 json_object *jsoarr = json_object_new_array();
7334 if (!jsoarr) {
7335 return false;
7336 }
7337 for (size_t i = 0; i < ARRAY_SIZE(key_flags_map); i++) {
7338 if (key_flags_map[i].id & key_flags) {
7339 json_object *jsostr = json_object_new_string(key_flags_map[i].str);
7340 if (!jsostr || json_object_array_add(jsoarr, jsostr)) {
7341 json_object_put(jsoarr);
7342 return false;
7343 }
7344 }
7345 }
7346 if (json_object_array_length(jsoarr)) {
7347 json_object_object_add(jso, "flags", jsoarr);
7348 } else {
7349 json_object_put(jsoarr);
7350 }
7351 return true;
7352 }
7353
7354 static rnp_result_t
add_json_mpis(json_object * jso,...)7355 add_json_mpis(json_object *jso, ...)
7356 {
7357 va_list ap;
7358 const char * name;
7359 rnp_result_t ret = RNP_ERROR_GENERIC;
7360
7361 va_start(ap, jso);
7362 while ((name = va_arg(ap, const char *))) {
7363 pgp_mpi_t *val = va_arg(ap, pgp_mpi_t *);
7364 if (!val) {
7365 ret = RNP_ERROR_BAD_PARAMETERS;
7366 goto done;
7367 }
7368 char *hex = mpi2hex(val);
7369 if (!hex) {
7370 // this could probably be other things
7371 ret = RNP_ERROR_OUT_OF_MEMORY;
7372 goto done;
7373 }
7374 json_object *jsostr = json_object_new_string(hex);
7375 free(hex);
7376 if (!jsostr) {
7377 ret = RNP_ERROR_OUT_OF_MEMORY;
7378 goto done;
7379 }
7380 json_object_object_add(jso, name, jsostr);
7381 }
7382 ret = RNP_SUCCESS;
7383
7384 done:
7385 va_end(ap);
7386 return ret;
7387 }
7388
7389 static rnp_result_t
add_json_public_mpis(json_object * jso,pgp_key_t * key)7390 add_json_public_mpis(json_object *jso, pgp_key_t *key)
7391 {
7392 const pgp_key_material_t &km = key->material();
7393 switch (km.alg) {
7394 case PGP_PKA_RSA:
7395 case PGP_PKA_RSA_ENCRYPT_ONLY:
7396 case PGP_PKA_RSA_SIGN_ONLY:
7397 return add_json_mpis(jso, "n", &km.rsa.n, "e", &km.rsa.e, NULL);
7398 case PGP_PKA_ELGAMAL:
7399 case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
7400 return add_json_mpis(jso, "p", &km.eg.p, "g", &km.eg.g, "y", &km.eg.y, NULL);
7401 case PGP_PKA_DSA:
7402 return add_json_mpis(
7403 jso, "p", &km.dsa.p, "q", &km.dsa.q, "g", &km.dsa.g, "y", &km.dsa.y, NULL);
7404 case PGP_PKA_ECDH:
7405 case PGP_PKA_ECDSA:
7406 case PGP_PKA_EDDSA:
7407 case PGP_PKA_SM2:
7408 return add_json_mpis(jso, "point", &km.ec.p, NULL);
7409 default:
7410 return RNP_ERROR_NOT_SUPPORTED;
7411 }
7412 return RNP_SUCCESS;
7413 }
7414
7415 static rnp_result_t
add_json_secret_mpis(json_object * jso,pgp_key_t * key)7416 add_json_secret_mpis(json_object *jso, pgp_key_t *key)
7417 {
7418 const pgp_key_material_t &km = key->material();
7419 switch (key->alg()) {
7420 case PGP_PKA_RSA:
7421 case PGP_PKA_RSA_ENCRYPT_ONLY:
7422 case PGP_PKA_RSA_SIGN_ONLY:
7423 return add_json_mpis(
7424 jso, "d", &km.rsa.d, "p", &km.rsa.p, "q", &km.rsa.q, "u", &km.rsa.u, NULL);
7425 case PGP_PKA_ELGAMAL:
7426 case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
7427 return add_json_mpis(jso, "x", &km.eg.x, NULL);
7428 case PGP_PKA_DSA:
7429 return add_json_mpis(jso, "x", &km.dsa.x, NULL);
7430 case PGP_PKA_ECDH:
7431 case PGP_PKA_ECDSA:
7432 case PGP_PKA_EDDSA:
7433 case PGP_PKA_SM2:
7434 return add_json_mpis(jso, "x", &km.ec.x, NULL);
7435 default:
7436 return RNP_ERROR_NOT_SUPPORTED;
7437 }
7438 return RNP_SUCCESS;
7439 }
7440
7441 static rnp_result_t
add_json_sig_mpis(json_object * jso,const pgp_signature_t * sig)7442 add_json_sig_mpis(json_object *jso, const pgp_signature_t *sig)
7443 {
7444 pgp_signature_material_t material = {};
7445 try {
7446 if (!sig->parse_material(material)) {
7447 return RNP_ERROR_BAD_PARAMETERS;
7448 }
7449 } catch (const std::exception &e) {
7450 RNP_LOG("%s", e.what());
7451 return RNP_ERROR_OUT_OF_MEMORY;
7452 }
7453 switch (sig->palg) {
7454 case PGP_PKA_RSA:
7455 case PGP_PKA_RSA_ENCRYPT_ONLY:
7456 case PGP_PKA_RSA_SIGN_ONLY:
7457 return add_json_mpis(jso, "sig", &material.rsa.s, NULL);
7458 case PGP_PKA_ELGAMAL:
7459 case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
7460 return add_json_mpis(jso, "r", &material.eg.r, "s", &material.eg.s, NULL);
7461 case PGP_PKA_DSA:
7462 return add_json_mpis(jso, "r", &material.dsa.r, "s", &material.dsa.s, NULL);
7463 case PGP_PKA_ECDSA:
7464 case PGP_PKA_EDDSA:
7465 case PGP_PKA_SM2:
7466 return add_json_mpis(jso, "r", &material.ecc.r, "s", &material.ecc.s, NULL);
7467 default:
7468 // TODO: we could use info->unknown and add a hex string of raw data here
7469 return RNP_ERROR_NOT_SUPPORTED;
7470 }
7471 return RNP_SUCCESS;
7472 }
7473
7474 static bool
add_json_user_prefs(json_object * jso,const pgp_user_prefs_t & prefs)7475 add_json_user_prefs(json_object *jso, const pgp_user_prefs_t &prefs)
7476 {
7477 // TODO: instead of using a string "Unknown" as a fallback for these,
7478 // we could add a string of hex/dec (or even an int)
7479 if (!prefs.symm_algs.empty()) {
7480 json_object *jsoarr = json_object_new_array();
7481 if (!jsoarr) {
7482 return false;
7483 }
7484 json_object_object_add(jso, "ciphers", jsoarr);
7485 for (auto alg : prefs.symm_algs) {
7486 const char * name = id_str_pair::lookup(symm_alg_map, alg, "Unknown");
7487 json_object *jsoname = json_object_new_string(name);
7488 if (!jsoname || json_object_array_add(jsoarr, jsoname)) {
7489 return false;
7490 }
7491 }
7492 }
7493 if (!prefs.hash_algs.empty()) {
7494 json_object *jsoarr = json_object_new_array();
7495 if (!jsoarr) {
7496 return false;
7497 }
7498 json_object_object_add(jso, "hashes", jsoarr);
7499 for (auto alg : prefs.hash_algs) {
7500 const char * name = id_str_pair::lookup(hash_alg_map, alg, "Unknown");
7501 json_object *jsoname = json_object_new_string(name);
7502 if (!jsoname || json_object_array_add(jsoarr, jsoname)) {
7503 return false;
7504 }
7505 }
7506 }
7507 if (!prefs.z_algs.empty()) {
7508 json_object *jsoarr = json_object_new_array();
7509 if (!jsoarr) {
7510 return false;
7511 }
7512 json_object_object_add(jso, "compression", jsoarr);
7513 for (auto alg : prefs.z_algs) {
7514 const char * name = id_str_pair::lookup(compress_alg_map, alg, "Unknown");
7515 json_object *jsoname = json_object_new_string(name);
7516 if (!jsoname || json_object_array_add(jsoarr, jsoname)) {
7517 return false;
7518 }
7519 }
7520 }
7521 if (!prefs.ks_prefs.empty()) {
7522 json_object *jsoarr = json_object_new_array();
7523 if (!jsoarr) {
7524 return false;
7525 }
7526 json_object_object_add(jso, "key server preferences", jsoarr);
7527 for (auto flag : prefs.ks_prefs) {
7528 const char * name = id_str_pair::lookup(key_server_prefs_map, flag, "Unknown");
7529 json_object *jsoname = json_object_new_string(name);
7530 if (!jsoname || json_object_array_add(jsoarr, jsoname)) {
7531 return false;
7532 }
7533 }
7534 }
7535 if (!prefs.key_server.empty()) {
7536 if (!add_json_string_field(jso, "key server", prefs.key_server.c_str())) {
7537 return false;
7538 }
7539 }
7540 return true;
7541 }
7542
7543 static rnp_result_t
add_json_subsig(json_object * jso,bool is_sub,uint32_t flags,const pgp_subsig_t * subsig)7544 add_json_subsig(json_object *jso, bool is_sub, uint32_t flags, const pgp_subsig_t *subsig)
7545 {
7546 // userid (if applicable)
7547 if (!is_sub) {
7548 json_object *jsouid = json_object_new_int(subsig->uid);
7549 if (!jsouid) {
7550 return RNP_ERROR_OUT_OF_MEMORY;
7551 }
7552 json_object_object_add(jso, "userid", jsouid);
7553 }
7554 // trust
7555 json_object *jsotrust = json_object_new_object();
7556 if (!jsotrust) {
7557 return RNP_ERROR_OUT_OF_MEMORY;
7558 }
7559 json_object_object_add(jso, "trust", jsotrust);
7560 // trust (level)
7561 json_object *jsotrust_level = json_object_new_int(subsig->trustlevel);
7562 if (!jsotrust_level) {
7563 return RNP_ERROR_OUT_OF_MEMORY;
7564 }
7565 json_object_object_add(jsotrust, "level", jsotrust_level);
7566 // trust (amount)
7567 json_object *jsotrust_amount = json_object_new_int(subsig->trustamount);
7568 if (!jsotrust_amount) {
7569 return RNP_ERROR_OUT_OF_MEMORY;
7570 }
7571 json_object_object_add(jsotrust, "amount", jsotrust_amount);
7572 // key flags (usage)
7573 if (!add_json_key_usage(jso, subsig->key_flags)) {
7574 return RNP_ERROR_OUT_OF_MEMORY;
7575 }
7576 // key flags (other)
7577 if (!add_json_key_flags(jso, subsig->key_flags)) {
7578 return RNP_ERROR_OUT_OF_MEMORY;
7579 }
7580 // preferences
7581 const pgp_user_prefs_t &prefs = subsig->prefs;
7582 if (!prefs.symm_algs.empty() || !prefs.hash_algs.empty() || !prefs.z_algs.empty() ||
7583 !prefs.ks_prefs.empty() || !prefs.key_server.empty()) {
7584 json_object *jsoprefs = json_object_new_object();
7585 if (!jsoprefs) {
7586 return RNP_ERROR_OUT_OF_MEMORY;
7587 }
7588 json_object_object_add(jso, "preferences", jsoprefs);
7589 if (!add_json_user_prefs(jsoprefs, prefs)) {
7590 return RNP_ERROR_OUT_OF_MEMORY;
7591 }
7592 }
7593 const pgp_signature_t *sig = &subsig->sig;
7594 // version
7595 json_object *jsoversion = json_object_new_int(sig->version);
7596 if (!jsoversion) {
7597 return RNP_ERROR_OUT_OF_MEMORY;
7598 }
7599 json_object_object_add(jso, "version", jsoversion);
7600 // signature type
7601 auto type = id_str_pair::lookup(sig_type_map, sig->type());
7602 if (!add_json_string_field(jso, "type", type)) {
7603 return RNP_ERROR_OUT_OF_MEMORY;
7604 }
7605 // signer key type
7606 const char *key_type = id_str_pair::lookup(pubkey_alg_map, sig->palg);
7607 if (!add_json_string_field(jso, "key type", key_type)) {
7608 return RNP_ERROR_OUT_OF_MEMORY;
7609 }
7610 // hash
7611 const char *hash = id_str_pair::lookup(hash_alg_map, sig->halg);
7612 if (!add_json_string_field(jso, "hash", hash)) {
7613 return RNP_ERROR_OUT_OF_MEMORY;
7614 }
7615 // creation time
7616 json_object *jsocreation_time = json_object_new_int64(sig->creation());
7617 if (!jsocreation_time) {
7618 return RNP_ERROR_OUT_OF_MEMORY;
7619 }
7620 json_object_object_add(jso, "creation time", jsocreation_time);
7621 // expiration (seconds)
7622 json_object *jsoexpiration = json_object_new_int64(sig->expiration());
7623 if (!jsoexpiration) {
7624 return RNP_ERROR_OUT_OF_MEMORY;
7625 }
7626 json_object_object_add(jso, "expiration", jsoexpiration);
7627 // signer
7628 json_object *jsosigner = NULL;
7629 // TODO: add signer fingerprint as well (no support internally yet)
7630 if (sig->has_keyid()) {
7631 jsosigner = json_object_new_object();
7632 if (!jsosigner) {
7633 return RNP_ERROR_OUT_OF_MEMORY;
7634 }
7635 char keyid[PGP_KEY_ID_SIZE * 2 + 1];
7636 pgp_key_id_t signer = sig->keyid();
7637 if (!rnp::hex_encode(signer.data(), signer.size(), keyid, sizeof(keyid))) {
7638 return RNP_ERROR_GENERIC;
7639 }
7640 if (!add_json_string_field(jsosigner, "keyid", keyid)) {
7641 json_object_put(jsosigner);
7642 return RNP_ERROR_OUT_OF_MEMORY;
7643 }
7644 }
7645 json_object_object_add(jso, "signer", jsosigner);
7646 // mpis
7647 json_object *jsompis = NULL;
7648 if (flags & RNP_JSON_SIGNATURE_MPIS) {
7649 jsompis = json_object_new_object();
7650 if (!jsompis) {
7651 return RNP_ERROR_OUT_OF_MEMORY;
7652 }
7653 rnp_result_t tmpret;
7654 if ((tmpret = add_json_sig_mpis(jsompis, sig))) {
7655 json_object_put(jsompis);
7656 return tmpret;
7657 }
7658 }
7659 json_object_object_add(jso, "mpis", jsompis);
7660 return RNP_SUCCESS;
7661 }
7662
7663 static rnp_result_t
key_to_json(json_object * jso,rnp_key_handle_t handle,uint32_t flags)7664 key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
7665 {
7666 pgp_key_t *key = get_key_prefer_public(handle);
7667
7668 // type
7669 const char *str = id_str_pair::lookup(pubkey_alg_map, key->alg(), NULL);
7670 if (!str) {
7671 return RNP_ERROR_BAD_PARAMETERS;
7672 }
7673 if (!add_json_string_field(jso, "type", str)) {
7674 return RNP_ERROR_OUT_OF_MEMORY;
7675 }
7676 // length
7677 if (!add_json_int_field(jso, "length", key->material().bits())) {
7678 return RNP_ERROR_OUT_OF_MEMORY;
7679 }
7680 // curve / alg-specific items
7681 switch (key->alg()) {
7682 case PGP_PKA_ECDH: {
7683 const char *hash_name =
7684 id_str_pair::lookup(hash_alg_map, key->material().ec.kdf_hash_alg, NULL);
7685 if (!hash_name) {
7686 return RNP_ERROR_BAD_PARAMETERS;
7687 }
7688 const char *cipher_name =
7689 id_str_pair::lookup(symm_alg_map, key->material().ec.key_wrap_alg, NULL);
7690 if (!cipher_name) {
7691 return RNP_ERROR_BAD_PARAMETERS;
7692 }
7693 json_object *jsohash = json_object_new_string(hash_name);
7694 if (!jsohash) {
7695 return RNP_ERROR_OUT_OF_MEMORY;
7696 }
7697 json_object_object_add(jso, "kdf hash", jsohash);
7698 json_object *jsocipher = json_object_new_string(cipher_name);
7699 if (!jsocipher) {
7700 return RNP_ERROR_OUT_OF_MEMORY;
7701 }
7702 json_object_object_add(jso, "key wrap cipher", jsocipher);
7703 }
7704 [[fallthrough]];
7705 case PGP_PKA_ECDSA:
7706 case PGP_PKA_EDDSA:
7707 case PGP_PKA_SM2: {
7708 const char *curve_name = NULL;
7709 if (!curve_type_to_str(key->material().ec.curve, &curve_name)) {
7710 return RNP_ERROR_BAD_PARAMETERS;
7711 }
7712 json_object *jsocurve = json_object_new_string(curve_name);
7713 if (!jsocurve) {
7714 return RNP_ERROR_OUT_OF_MEMORY;
7715 }
7716 json_object_object_add(jso, "curve", jsocurve);
7717 } break;
7718 default:
7719 break;
7720 }
7721
7722 // keyid
7723 char keyid[PGP_KEY_ID_SIZE * 2 + 1];
7724 if (!rnp::hex_encode(key->keyid().data(), key->keyid().size(), keyid, sizeof(keyid))) {
7725 return RNP_ERROR_GENERIC;
7726 }
7727 if (!add_json_string_field(jso, "keyid", keyid)) {
7728 return RNP_ERROR_OUT_OF_MEMORY;
7729 }
7730 // fingerprint
7731 char fpr[PGP_FINGERPRINT_SIZE * 2 + 1];
7732 if (!rnp::hex_encode(key->fp().fingerprint, key->fp().length, fpr, sizeof(fpr))) {
7733 return RNP_ERROR_GENERIC;
7734 }
7735 if (!add_json_string_field(jso, "fingerprint", fpr)) {
7736 return RNP_ERROR_OUT_OF_MEMORY;
7737 }
7738 // grip
7739 char grip[PGP_KEY_GRIP_SIZE * 2 + 1];
7740 if (!rnp::hex_encode(key->grip().data(), key->grip().size(), grip, sizeof(grip))) {
7741 return RNP_ERROR_GENERIC;
7742 }
7743 if (!add_json_string_field(jso, "grip", grip)) {
7744 return RNP_ERROR_OUT_OF_MEMORY;
7745 }
7746 // revoked
7747 json_object *jsorevoked = json_object_new_boolean(key->revoked() ? true : false);
7748 if (!jsorevoked) {
7749 return RNP_ERROR_OUT_OF_MEMORY;
7750 }
7751 json_object_object_add(jso, "revoked", jsorevoked);
7752 // creation time
7753 json_object *jsocreation_time = json_object_new_int64(key->creation());
7754 if (!jsocreation_time) {
7755 return RNP_ERROR_OUT_OF_MEMORY;
7756 }
7757 json_object_object_add(jso, "creation time", jsocreation_time);
7758 // expiration
7759 json_object *jsoexpiration = json_object_new_int64(key->expiration());
7760 if (!jsoexpiration) {
7761 return RNP_ERROR_OUT_OF_MEMORY;
7762 }
7763 json_object_object_add(jso, "expiration", jsoexpiration);
7764 // key flags (usage)
7765 if (!add_json_key_usage(jso, key->flags())) {
7766 return RNP_ERROR_OUT_OF_MEMORY;
7767 }
7768 // key flags (other)
7769 if (!add_json_key_flags(jso, key->flags())) {
7770 return RNP_ERROR_OUT_OF_MEMORY;
7771 }
7772 // parent / subkeys
7773 if (key->is_primary()) {
7774 json_object *jsosubkeys_arr = json_object_new_array();
7775 if (!jsosubkeys_arr) {
7776 return RNP_ERROR_OUT_OF_MEMORY;
7777 }
7778 json_object_object_add(jso, "subkey grips", jsosubkeys_arr);
7779 for (auto &subfp : key->subkey_fps()) {
7780 const pgp_key_grip_t *subgrip = rnp_get_grip_by_fp(handle->ffi, subfp);
7781 if (!subgrip) {
7782 continue;
7783 }
7784 if (!rnp::hex_encode(subgrip->data(), subgrip->size(), grip, sizeof(grip))) {
7785 return RNP_ERROR_GENERIC;
7786 }
7787 json_object *jsostr = json_object_new_string(grip);
7788 if (!jsostr || json_object_array_add(jsosubkeys_arr, jsostr)) {
7789 json_object_put(jsostr);
7790 return RNP_ERROR_OUT_OF_MEMORY;
7791 }
7792 }
7793 } else if (key->has_primary_fp()) {
7794 auto pgrip = rnp_get_grip_by_fp(handle->ffi, key->primary_fp());
7795 if (pgrip) {
7796 if (!rnp::hex_encode(pgrip->data(), pgrip->size(), grip, sizeof(grip))) {
7797 return RNP_ERROR_GENERIC;
7798 }
7799 if (!add_json_string_field(jso, "primary key grip", grip)) {
7800 return RNP_ERROR_OUT_OF_MEMORY;
7801 }
7802 }
7803 }
7804 // public
7805 json_object *jsopublic = json_object_new_object();
7806 if (!jsopublic) {
7807 return RNP_ERROR_OUT_OF_MEMORY;
7808 }
7809 bool have_sec = handle->sec != NULL;
7810 bool have_pub = handle->pub != NULL;
7811 json_object_object_add(jso, "public key", jsopublic);
7812 json_object_object_add(
7813 jsopublic, "present", json_object_new_boolean(have_pub ? true : false));
7814 if (flags & RNP_JSON_PUBLIC_MPIS) {
7815 json_object *jsompis = json_object_new_object();
7816 if (!jsompis) {
7817 return RNP_ERROR_OUT_OF_MEMORY;
7818 }
7819 json_object_object_add(jsopublic, "mpis", jsompis);
7820 rnp_result_t tmpret;
7821 if ((tmpret = add_json_public_mpis(jsompis, key))) {
7822 return tmpret;
7823 }
7824 }
7825 // secret
7826 json_object *jsosecret = json_object_new_object();
7827 if (!jsosecret) {
7828 return RNP_ERROR_OUT_OF_MEMORY;
7829 }
7830 json_object_object_add(jso, "secret key", jsosecret);
7831 json_object_object_add(
7832 jsosecret, "present", json_object_new_boolean(have_sec ? true : false));
7833 if (have_sec) {
7834 bool locked = handle->sec->is_locked();
7835 if (flags & RNP_JSON_SECRET_MPIS) {
7836 if (locked) {
7837 json_object_object_add(jsosecret, "mpis", NULL);
7838 } else {
7839 json_object *jsompis = json_object_new_object();
7840 if (!jsompis) {
7841 return RNP_ERROR_OUT_OF_MEMORY;
7842 }
7843 json_object_object_add(jsosecret, "mpis", jsompis);
7844 rnp_result_t tmpret;
7845 if ((tmpret = add_json_secret_mpis(jsompis, handle->sec))) {
7846 return tmpret;
7847 }
7848 }
7849 }
7850 json_object *jsolocked = json_object_new_boolean(locked ? true : false);
7851 if (!jsolocked) {
7852 return RNP_ERROR_OUT_OF_MEMORY;
7853 }
7854 json_object_object_add(jsosecret, "locked", jsolocked);
7855 json_object *jsoprotected =
7856 json_object_new_boolean(handle->sec->is_protected() ? true : false);
7857 if (!jsoprotected) {
7858 return RNP_ERROR_OUT_OF_MEMORY;
7859 }
7860 json_object_object_add(jsosecret, "protected", jsoprotected);
7861 }
7862 // userids
7863 if (key->is_primary()) {
7864 json_object *jsouids_arr = json_object_new_array();
7865 if (!jsouids_arr) {
7866 return RNP_ERROR_OUT_OF_MEMORY;
7867 }
7868 json_object_object_add(jso, "userids", jsouids_arr);
7869 for (size_t i = 0; i < key->uid_count(); i++) {
7870 json_object *jsouid = json_object_new_string(key->get_uid(i).str.c_str());
7871 if (!jsouid || json_object_array_add(jsouids_arr, jsouid)) {
7872 json_object_put(jsouid);
7873 return RNP_ERROR_OUT_OF_MEMORY;
7874 }
7875 }
7876 }
7877 // signatures
7878 if (flags & RNP_JSON_SIGNATURES) {
7879 json_object *jsosigs_arr = json_object_new_array();
7880 if (!jsosigs_arr) {
7881 return RNP_ERROR_OUT_OF_MEMORY;
7882 }
7883 json_object_object_add(jso, "signatures", jsosigs_arr);
7884 for (size_t i = 0; i < key->sig_count(); i++) {
7885 json_object *jsosig = json_object_new_object();
7886 if (!jsosig || json_object_array_add(jsosigs_arr, jsosig)) {
7887 json_object_put(jsosig);
7888 return RNP_ERROR_OUT_OF_MEMORY;
7889 }
7890 rnp_result_t tmpret;
7891 if ((tmpret =
7892 add_json_subsig(jsosig, key->is_subkey(), flags, &key->get_sig(i)))) {
7893 return tmpret;
7894 }
7895 }
7896 }
7897 return RNP_SUCCESS;
7898 }
7899
7900 rnp_result_t
rnp_key_to_json(rnp_key_handle_t handle,uint32_t flags,char ** result)7901 rnp_key_to_json(rnp_key_handle_t handle, uint32_t flags, char **result)
7902 try {
7903 rnp_result_t ret = RNP_ERROR_GENERIC;
7904 json_object *jso = NULL;
7905
7906 // checks
7907 if (!handle || !result) {
7908 return RNP_ERROR_NULL_POINTER;
7909 }
7910 jso = json_object_new_object();
7911 if (!jso) {
7912 ret = RNP_ERROR_OUT_OF_MEMORY;
7913 goto done;
7914 }
7915 if ((ret = key_to_json(jso, handle, flags))) {
7916 goto done;
7917 }
7918 *result = (char *) json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY);
7919 if (!*result) {
7920 goto done;
7921 }
7922 *result = strdup(*result);
7923 if (!*result) {
7924 ret = RNP_ERROR_OUT_OF_MEMORY;
7925 goto done;
7926 }
7927
7928 ret = RNP_SUCCESS;
7929 done:
7930 json_object_put(jso);
7931 return ret;
7932 }
7933 FFI_GUARD
7934
7935 static rnp_result_t
rnp_dump_src_to_json(pgp_source_t * src,uint32_t flags,char ** result)7936 rnp_dump_src_to_json(pgp_source_t *src, uint32_t flags, char **result)
7937 {
7938 rnp_dump_ctx_t dumpctx = {};
7939 json_object * jso = NULL;
7940 rnp_result_t ret = RNP_ERROR_GENERIC;
7941
7942 if (flags & RNP_JSON_DUMP_MPI) {
7943 dumpctx.dump_mpi = true;
7944 flags &= ~RNP_JSON_DUMP_MPI;
7945 }
7946 if (flags & RNP_JSON_DUMP_RAW) {
7947 dumpctx.dump_packets = true;
7948 flags &= ~RNP_JSON_DUMP_RAW;
7949 }
7950 if (flags & RNP_JSON_DUMP_GRIP) {
7951 dumpctx.dump_grips = true;
7952 flags &= ~RNP_JSON_DUMP_GRIP;
7953 }
7954 if (flags) {
7955 return RNP_ERROR_BAD_PARAMETERS;
7956 }
7957
7958 ret = stream_dump_packets_json(&dumpctx, src, &jso);
7959 if (ret) {
7960 goto done;
7961 }
7962
7963 *result = (char *) json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY);
7964 if (!*result) {
7965 goto done;
7966 }
7967 *result = strdup(*result);
7968 if (!*result) {
7969 ret = RNP_ERROR_OUT_OF_MEMORY;
7970 goto done;
7971 }
7972
7973 ret = RNP_SUCCESS;
7974 done:
7975 json_object_put(jso);
7976 return ret;
7977 }
7978
7979 rnp_result_t
rnp_key_packets_to_json(rnp_key_handle_t handle,bool secret,uint32_t flags,char ** result)7980 rnp_key_packets_to_json(rnp_key_handle_t handle, bool secret, uint32_t flags, char **result)
7981 try {
7982 pgp_key_t * key = NULL;
7983 rnp_result_t ret = RNP_ERROR_GENERIC;
7984 pgp_dest_t memdst = {};
7985 pgp_source_t memsrc = {};
7986
7987 if (!handle || !result) {
7988 return RNP_ERROR_NULL_POINTER;
7989 }
7990
7991 key = secret ? handle->sec : handle->pub;
7992 if (!key || (key->format == PGP_KEY_STORE_G10)) {
7993 return RNP_ERROR_BAD_PARAMETERS;
7994 }
7995
7996 if (init_mem_dest(&memdst, NULL, 0)) {
7997 return RNP_ERROR_OUT_OF_MEMORY;
7998 }
7999
8000 key->write(memdst);
8001 if (memdst.werr) {
8002 ret = RNP_ERROR_BAD_PARAMETERS;
8003 goto done;
8004 }
8005
8006 if (init_mem_src(&memsrc, mem_dest_get_memory(&memdst), memdst.writeb, false)) {
8007 ret = RNP_ERROR_BAD_STATE;
8008 goto done;
8009 }
8010
8011 ret = rnp_dump_src_to_json(&memsrc, flags, result);
8012 done:
8013 dst_close(&memdst, true);
8014 src_close(&memsrc);
8015 return ret;
8016 }
8017 FFI_GUARD
8018
8019 rnp_result_t
rnp_dump_packets_to_json(rnp_input_t input,uint32_t flags,char ** result)8020 rnp_dump_packets_to_json(rnp_input_t input, uint32_t flags, char **result)
8021 try {
8022 if (!input || !result) {
8023 return RNP_ERROR_NULL_POINTER;
8024 }
8025
8026 return rnp_dump_src_to_json(&input->src, flags, result);
8027 }
8028 FFI_GUARD
8029
8030 rnp_result_t
rnp_dump_packets_to_output(rnp_input_t input,rnp_output_t output,uint32_t flags)8031 rnp_dump_packets_to_output(rnp_input_t input, rnp_output_t output, uint32_t flags)
8032 try {
8033 if (!input || !output) {
8034 return RNP_ERROR_NULL_POINTER;
8035 }
8036
8037 rnp_dump_ctx_t dumpctx = {};
8038
8039 if (flags & RNP_DUMP_MPI) {
8040 dumpctx.dump_mpi = true;
8041 flags &= ~RNP_DUMP_MPI;
8042 }
8043 if (flags & RNP_DUMP_RAW) {
8044 dumpctx.dump_packets = true;
8045 flags &= ~RNP_DUMP_RAW;
8046 }
8047 if (flags & RNP_DUMP_GRIP) {
8048 dumpctx.dump_grips = true;
8049 flags &= ~RNP_DUMP_GRIP;
8050 }
8051 if (flags) {
8052 return RNP_ERROR_BAD_PARAMETERS;
8053 }
8054
8055 rnp_result_t ret = stream_dump_packets(&dumpctx, &input->src, &output->dst);
8056 output->keep = true;
8057 return ret;
8058 }
8059 FFI_GUARD
8060
8061 // move to next key
8062 static bool
key_iter_next_key(rnp_identifier_iterator_t it)8063 key_iter_next_key(rnp_identifier_iterator_t it)
8064 {
8065 // check if we not reached the end of the ring
8066 *it->keyp = std::next(*it->keyp);
8067 if (*it->keyp != it->store->keys.end()) {
8068 it->uididx = 0;
8069 return true;
8070 }
8071 // if we are currently on pubring, switch to secring (if not empty)
8072 if (it->store == it->ffi->pubring && !it->ffi->secring->keys.empty()) {
8073 it->store = it->ffi->secring;
8074 *it->keyp = it->store->keys.begin();
8075 it->uididx = 0;
8076 return true;
8077 }
8078 // we've gone through both rings
8079 it->store = NULL;
8080 return false;
8081 }
8082
8083 // move to next item (key or userid)
8084 static bool
key_iter_next_item(rnp_identifier_iterator_t it)8085 key_iter_next_item(rnp_identifier_iterator_t it)
8086 {
8087 switch (it->type) {
8088 case PGP_KEY_SEARCH_KEYID:
8089 case PGP_KEY_SEARCH_FINGERPRINT:
8090 case PGP_KEY_SEARCH_GRIP:
8091 return key_iter_next_key(it);
8092 case PGP_KEY_SEARCH_USERID:
8093 it->uididx++;
8094 while (it->uididx >= (*it->keyp)->uid_count()) {
8095 if (!key_iter_next_key(it)) {
8096 return false;
8097 }
8098 it->uididx = 0;
8099 }
8100 break;
8101 default:
8102 assert(false);
8103 break;
8104 }
8105 return true;
8106 }
8107
8108 static bool
key_iter_first_key(rnp_identifier_iterator_t it)8109 key_iter_first_key(rnp_identifier_iterator_t it)
8110 {
8111 if (rnp_key_store_get_key_count(it->ffi->pubring)) {
8112 it->store = it->ffi->pubring;
8113 } else if (rnp_key_store_get_key_count(it->ffi->secring)) {
8114 it->store = it->ffi->secring;
8115 } else {
8116 it->store = NULL;
8117 return false;
8118 }
8119 *it->keyp = it->store->keys.begin();
8120 it->uididx = 0;
8121 return true;
8122 }
8123
8124 static bool
key_iter_first_item(rnp_identifier_iterator_t it)8125 key_iter_first_item(rnp_identifier_iterator_t it)
8126 {
8127 switch (it->type) {
8128 case PGP_KEY_SEARCH_KEYID:
8129 case PGP_KEY_SEARCH_FINGERPRINT:
8130 case PGP_KEY_SEARCH_GRIP:
8131 return key_iter_first_key(it);
8132 case PGP_KEY_SEARCH_USERID:
8133 if (!key_iter_first_key(it)) {
8134 return false;
8135 }
8136 it->uididx = 0;
8137 while (it->uididx >= (*it->keyp)->uid_count()) {
8138 if (!key_iter_next_key(it)) {
8139 return false;
8140 }
8141 }
8142 break;
8143 default:
8144 assert(false);
8145 break;
8146 }
8147 return true;
8148 }
8149
8150 static bool
key_iter_get_item(const rnp_identifier_iterator_t it,char * buf,size_t buf_len)8151 key_iter_get_item(const rnp_identifier_iterator_t it, char *buf, size_t buf_len)
8152 {
8153 const pgp_key_t *key = &**it->keyp;
8154 switch (it->type) {
8155 case PGP_KEY_SEARCH_KEYID: {
8156 if (!rnp::hex_encode(key->keyid().data(), key->keyid().size(), buf, buf_len)) {
8157 return false;
8158 }
8159 break;
8160 }
8161 case PGP_KEY_SEARCH_FINGERPRINT:
8162 if (!rnp::hex_encode(key->fp().fingerprint, key->fp().length, buf, buf_len)) {
8163 return false;
8164 }
8165 break;
8166 case PGP_KEY_SEARCH_GRIP:
8167 if (!rnp::hex_encode(key->grip().data(), key->grip().size(), buf, buf_len)) {
8168 return false;
8169 }
8170 break;
8171 case PGP_KEY_SEARCH_USERID: {
8172 if (it->uididx >= key->uid_count()) {
8173 return false;
8174 }
8175 const pgp_userid_t &uid = key->get_uid(it->uididx);
8176 if (uid.str.size() >= buf_len) {
8177 return false;
8178 }
8179 memcpy(buf, uid.str.c_str(), uid.str.size() + 1);
8180 } break;
8181 default:
8182 assert(false);
8183 break;
8184 }
8185 return true;
8186 }
8187
8188 rnp_result_t
rnp_identifier_iterator_create(rnp_ffi_t ffi,rnp_identifier_iterator_t * it,const char * identifier_type)8189 rnp_identifier_iterator_create(rnp_ffi_t ffi,
8190 rnp_identifier_iterator_t *it,
8191 const char * identifier_type)
8192 try {
8193 rnp_result_t ret = RNP_ERROR_GENERIC;
8194 struct rnp_identifier_iterator_st *obj = NULL;
8195
8196 // checks
8197 if (!ffi || !it || !identifier_type) {
8198 return RNP_ERROR_NULL_POINTER;
8199 }
8200 // create iterator
8201 obj = (struct rnp_identifier_iterator_st *) calloc(1, sizeof(*obj));
8202 if (!obj) {
8203 return RNP_ERROR_OUT_OF_MEMORY;
8204 }
8205 obj->ffi = ffi;
8206 obj->keyp = new std::list<pgp_key_t>::iterator();
8207 obj->uididx = 0;
8208 // parse identifier type
8209 obj->type = static_cast<pgp_key_search_type_t>(
8210 id_str_pair::lookup(identifier_type_map, identifier_type, PGP_KEY_SEARCH_UNKNOWN));
8211 if (obj->type == PGP_KEY_SEARCH_UNKNOWN) {
8212 ret = RNP_ERROR_BAD_PARAMETERS;
8213 goto done;
8214 }
8215 obj->tbl = json_object_new_object();
8216 if (!obj->tbl) {
8217 ret = RNP_ERROR_OUT_OF_MEMORY;
8218 goto done;
8219 }
8220 // move to first item (if any)
8221 key_iter_first_item(obj);
8222 *it = obj;
8223
8224 ret = RNP_SUCCESS;
8225 done:
8226 if (ret) {
8227 rnp_identifier_iterator_destroy(obj);
8228 }
8229 return ret;
8230 }
8231 FFI_GUARD
8232
8233 rnp_result_t
rnp_identifier_iterator_next(rnp_identifier_iterator_t it,const char ** identifier)8234 rnp_identifier_iterator_next(rnp_identifier_iterator_t it, const char **identifier)
8235 try {
8236 rnp_result_t ret = RNP_ERROR_GENERIC;
8237
8238 // checks
8239 if (!it || !identifier) {
8240 return RNP_ERROR_NULL_POINTER;
8241 }
8242 // initialize the result to NULL
8243 *identifier = NULL;
8244 // this means we reached the end of the rings
8245 if (!it->store) {
8246 return RNP_SUCCESS;
8247 }
8248 // get the item
8249 if (!key_iter_get_item(it, it->buf, sizeof(it->buf))) {
8250 return RNP_ERROR_GENERIC;
8251 }
8252 bool exists;
8253 bool iterator_valid = true;
8254 while ((exists = json_object_object_get_ex(it->tbl, it->buf, NULL))) {
8255 if (!((iterator_valid = key_iter_next_item(it)))) {
8256 break;
8257 }
8258 if (!key_iter_get_item(it, it->buf, sizeof(it->buf))) {
8259 return RNP_ERROR_GENERIC;
8260 }
8261 }
8262 // see if we actually found a new entry
8263 if (!exists) {
8264 // TODO: Newer json-c has a useful return value for json_object_object_add,
8265 // which doesn't require the json_object_object_get_ex check below.
8266 json_object_object_add(it->tbl, it->buf, NULL);
8267 if (!json_object_object_get_ex(it->tbl, it->buf, NULL)) {
8268 ret = RNP_ERROR_OUT_OF_MEMORY;
8269 goto done;
8270 }
8271 *identifier = it->buf;
8272 }
8273 // prepare for the next one
8274 if (iterator_valid) {
8275 key_iter_next_item(it);
8276 }
8277 ret = RNP_SUCCESS;
8278
8279 done:
8280 if (ret) {
8281 *identifier = NULL;
8282 }
8283 return ret;
8284 }
8285 FFI_GUARD
8286
8287 rnp_result_t
rnp_identifier_iterator_destroy(rnp_identifier_iterator_t it)8288 rnp_identifier_iterator_destroy(rnp_identifier_iterator_t it)
8289 try {
8290 if (it) {
8291 json_object_put(it->tbl);
8292 if (it->keyp) {
8293 delete it->keyp;
8294 }
8295 free(it);
8296 }
8297 return RNP_SUCCESS;
8298 }
8299 FFI_GUARD
8300
8301 rnp_result_t
rnp_guess_contents(rnp_input_t input,char ** contents)8302 rnp_guess_contents(rnp_input_t input, char **contents)
8303 try {
8304 if (!input || !contents) {
8305 return RNP_ERROR_NULL_POINTER;
8306 }
8307
8308 pgp_armored_msg_t msgtype = PGP_ARMORED_UNKNOWN;
8309 if (is_armored_source(&input->src)) {
8310 msgtype = rnp_armored_get_type(&input->src);
8311 } else {
8312 msgtype = rnp_armor_guess_type(&input->src);
8313 }
8314 const char *msg = id_str_pair::lookup(armor_type_map, msgtype);
8315 size_t len = strlen(msg);
8316 *contents = (char *) calloc(1, len + 1);
8317 if (!*contents) {
8318 return RNP_ERROR_OUT_OF_MEMORY;
8319 }
8320 memcpy(*contents, msg, len);
8321 return RNP_SUCCESS;
8322 }
8323 FFI_GUARD
8324
8325 rnp_result_t
rnp_enarmor(rnp_input_t input,rnp_output_t output,const char * type)8326 rnp_enarmor(rnp_input_t input, rnp_output_t output, const char *type)
8327 try {
8328 pgp_armored_msg_t msgtype = PGP_ARMORED_UNKNOWN;
8329 if (!input || !output) {
8330 return RNP_ERROR_NULL_POINTER;
8331 }
8332 if (type) {
8333 msgtype = static_cast<pgp_armored_msg_t>(
8334 id_str_pair::lookup(armor_type_map, type, PGP_ARMORED_UNKNOWN));
8335 if (msgtype == PGP_ARMORED_UNKNOWN) {
8336 RNP_LOG("Unsupported armor type: %s", type);
8337 return RNP_ERROR_BAD_PARAMETERS;
8338 }
8339 } else {
8340 msgtype = rnp_armor_guess_type(&input->src);
8341 if (!msgtype) {
8342 RNP_LOG("Unrecognized data to armor (try specifying a type)");
8343 return RNP_ERROR_BAD_PARAMETERS;
8344 }
8345 }
8346 rnp_result_t ret = rnp_armor_source(&input->src, &output->dst, msgtype);
8347 output->keep = !ret;
8348 return ret;
8349 }
8350 FFI_GUARD
8351
8352 rnp_result_t
rnp_dearmor(rnp_input_t input,rnp_output_t output)8353 rnp_dearmor(rnp_input_t input, rnp_output_t output)
8354 try {
8355 if (!input || !output) {
8356 return RNP_ERROR_NULL_POINTER;
8357 }
8358 rnp_result_t ret = rnp_dearmor_source(&input->src, &output->dst);
8359 output->keep = !ret;
8360 return ret;
8361 }
8362 FFI_GUARD
8363
8364 rnp_result_t
rnp_output_pipe(rnp_input_t input,rnp_output_t output)8365 rnp_output_pipe(rnp_input_t input, rnp_output_t output)
8366 try {
8367 if (!input || !output) {
8368 return RNP_ERROR_NULL_POINTER;
8369 }
8370 rnp_result_t ret = dst_write_src(&input->src, &output->dst);
8371 output->keep = !ret;
8372 return ret;
8373 }
8374 FFI_GUARD
8375
8376 rnp_result_t
rnp_output_armor_set_line_length(rnp_output_t output,size_t llen)8377 rnp_output_armor_set_line_length(rnp_output_t output, size_t llen)
8378 try {
8379 if (!output || !llen) {
8380 return RNP_ERROR_BAD_PARAMETERS;
8381 }
8382 return armored_dst_set_line_length(&output->dst, llen);
8383 }
8384 FFI_GUARD
8385
8386 const char *
rnp_backend_string()8387 rnp_backend_string()
8388 {
8389 return rnp::backend_string();
8390 }
8391
8392 const char *
rnp_backend_version()8393 rnp_backend_version()
8394 {
8395 return rnp::backend_version();
8396 }
8397