1 /*
2  * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <assert.h>
28 #include <string.h>
29 
30 #include <rekey/rnp_key_store.h>
31 #include <librekey/key_store_pgp.h>
32 #include <librekey/key_store_g10.h>
33 #include <librepgp/stream-packet.h>
34 #include "crypto.h"
35 #include "pgp-key.h"
36 #include "defaults.h"
37 #include "utils.h"
38 
39 static const uint8_t DEFAULT_SYMMETRIC_ALGS[] = {
40   PGP_SA_AES_256, PGP_SA_AES_192, PGP_SA_AES_128, PGP_SA_TRIPLEDES};
41 static const uint8_t DEFAULT_HASH_ALGS[] = {
42   PGP_HASH_SHA256, PGP_HASH_SHA384, PGP_HASH_SHA512, PGP_HASH_SHA224, PGP_HASH_SHA1};
43 static const uint8_t DEFAULT_COMPRESS_ALGS[] = {
44   PGP_C_ZLIB, PGP_C_BZIP2, PGP_C_ZIP, PGP_C_NONE};
45 
46 static pgp_map_t pubkey_alg_map[] = {
47   {PGP_PKA_RSA, "RSA (Encrypt or Sign)"},
48   {PGP_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"},
49   {PGP_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"},
50   {PGP_PKA_ELGAMAL, "Elgamal (Encrypt-Only)"},
51   {PGP_PKA_DSA, "DSA"},
52   {PGP_PKA_ECDH, "ECDH"},
53   {PGP_PKA_ECDSA, "ECDSA"},
54   {PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign"},
55   {PGP_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)"},
56   {PGP_PKA_EDDSA, "EdDSA"},
57   {PGP_PKA_SM2, "SM2"},
58   {PGP_PKA_PRIVATE00, "Private/Experimental"},
59   {PGP_PKA_PRIVATE01, "Private/Experimental"},
60   {PGP_PKA_PRIVATE02, "Private/Experimental"},
61   {PGP_PKA_PRIVATE03, "Private/Experimental"},
62   {PGP_PKA_PRIVATE04, "Private/Experimental"},
63   {PGP_PKA_PRIVATE05, "Private/Experimental"},
64   {PGP_PKA_PRIVATE06, "Private/Experimental"},
65   {PGP_PKA_PRIVATE07, "Private/Experimental"},
66   {PGP_PKA_PRIVATE08, "Private/Experimental"},
67   {PGP_PKA_PRIVATE09, "Private/Experimental"},
68   {PGP_PKA_PRIVATE10, "Private/Experimental"},
69   {0x00, NULL}, /* this is the end-of-array marker */
70 };
71 
72 static bool
load_generated_g10_key(pgp_key_t * dst,pgp_key_pkt_t * newkey,pgp_key_t * primary_key,pgp_key_t * pubkey)73 load_generated_g10_key(pgp_key_t *    dst,
74                        pgp_key_pkt_t *newkey,
75                        pgp_key_t *    primary_key,
76                        pgp_key_t *    pubkey)
77 {
78     bool               ok = false;
79     pgp_dest_t         memdst = {};
80     pgp_source_t       memsrc = {};
81     rnp_key_store_t *  key_store = NULL;
82     list               key_ptrs = NULL; /* holds primary and pubkey, when used */
83     pgp_key_provider_t prov = {};
84 
85     // this should generally be zeroed
86     assert(dst->type() == 0);
87     // if a primary is provided, make sure it's actually a primary key
88     assert(!primary_key || primary_key->is_primary());
89     // if a pubkey is provided, make sure it's actually a public key
90     assert(!pubkey || pubkey->is_public());
91     // G10 always needs pubkey here
92     assert(pubkey);
93 
94     if (init_mem_dest(&memdst, NULL, 0)) {
95         goto end;
96     }
97 
98     if (!g10_write_seckey(&memdst, newkey, NULL)) {
99         RNP_LOG("failed to write generated seckey");
100         goto end;
101     }
102 
103     // this would be better on the stack but the key store does not allow it
104     try {
105         key_store = new rnp_key_store_t();
106     } catch (const std::exception &e) {
107         RNP_LOG("%s", e.what());
108         goto end;
109     }
110 
111     // if this is a subkey, add the primary in first
112     if (primary_key && !list_append(&key_ptrs, &primary_key, sizeof(primary_key))) {
113         goto end;
114     }
115     // G10 needs the pubkey for copying some attributes (key version, creation time, etc)
116     if (!list_append(&key_ptrs, &pubkey, sizeof(pubkey))) {
117         goto end;
118     }
119 
120     prov.callback = rnp_key_provider_key_ptr_list;
121     prov.userdata = key_ptrs;
122 
123     if (init_mem_src(&memsrc, mem_dest_get_memory(&memdst), memdst.writeb, false)) {
124         goto end;
125     }
126 
127     if (!rnp_key_store_g10_from_src(key_store, &memsrc, &prov)) {
128         goto end;
129     }
130     if (rnp_key_store_get_key_count(key_store) != 1) {
131         goto end;
132     }
133     // if a primary key is provided, it should match the sub with regards to type
134     assert(!primary_key || (primary_key->is_secret() == key_store->keys.front().is_secret()));
135     try {
136         *dst = pgp_key_t(key_store->keys.front());
137         ok = true;
138     } catch (const std::exception &e) {
139         RNP_LOG("Failed to copy key: %s", e.what());
140         ok = false;
141     }
142 end:
143     delete key_store;
144     src_close(&memsrc);
145     dst_close(&memdst, true);
146     list_destroy(&key_ptrs);
147     return ok;
148 }
149 
150 static uint8_t
pk_alg_default_flags(pgp_pubkey_alg_t alg)151 pk_alg_default_flags(pgp_pubkey_alg_t alg)
152 {
153     // just use the full capabilities as the ultimate fallback
154     return pgp_pk_alg_capabilities(alg);
155 }
156 
157 // TODO: Similar as pgp_pick_hash_alg but different enough to
158 //       keep another version. This will be changed when refactoring crypto
159 static void
adjust_hash_alg(rnp_keygen_crypto_params_t & crypto)160 adjust_hash_alg(rnp_keygen_crypto_params_t &crypto)
161 {
162     if (!crypto.hash_alg) {
163         crypto.hash_alg = (pgp_hash_alg_t) DEFAULT_HASH_ALGS[0];
164     }
165 
166     if ((crypto.key_alg != PGP_PKA_DSA) && (crypto.key_alg != PGP_PKA_ECDSA)) {
167         return;
168     }
169 
170     pgp_hash_alg_t min_hash = (crypto.key_alg == PGP_PKA_ECDSA) ?
171                                 ecdsa_get_min_hash(crypto.ecc.curve) :
172                                 dsa_get_min_hash(crypto.dsa.q_bitlen);
173 
174     if (pgp_digest_length(crypto.hash_alg) < pgp_digest_length(min_hash)) {
175         crypto.hash_alg = min_hash;
176     }
177 }
178 
179 static void
keygen_merge_crypto_defaults(rnp_keygen_crypto_params_t & crypto)180 keygen_merge_crypto_defaults(rnp_keygen_crypto_params_t &crypto)
181 {
182     // default to RSA
183     if (!crypto.key_alg) {
184         crypto.key_alg = PGP_PKA_RSA;
185     }
186 
187     switch (crypto.key_alg) {
188     case PGP_PKA_RSA:
189         if (!crypto.rsa.modulus_bit_len) {
190             crypto.rsa.modulus_bit_len = DEFAULT_RSA_NUMBITS;
191         }
192         break;
193 
194     case PGP_PKA_SM2:
195         if (!crypto.hash_alg) {
196             crypto.hash_alg = PGP_HASH_SM3;
197         }
198         if (!crypto.ecc.curve) {
199             crypto.ecc.curve = PGP_CURVE_SM2_P_256;
200         }
201         break;
202 
203     case PGP_PKA_ECDH:
204     case PGP_PKA_ECDSA: {
205         if (!crypto.hash_alg) {
206             crypto.hash_alg = (pgp_hash_alg_t) DEFAULT_HASH_ALGS[0];
207         }
208         break;
209     }
210 
211     case PGP_PKA_EDDSA:
212         if (!crypto.ecc.curve) {
213             crypto.ecc.curve = PGP_CURVE_ED25519;
214         }
215         break;
216 
217     case PGP_PKA_DSA: {
218         if (!crypto.dsa.p_bitlen) {
219             crypto.dsa.p_bitlen = DSA_DEFAULT_P_BITLEN;
220         }
221         if (!crypto.dsa.q_bitlen) {
222             crypto.dsa.q_bitlen = dsa_choose_qsize_by_psize(crypto.dsa.p_bitlen);
223         }
224         break;
225     }
226     default:
227         break;
228     }
229 
230     adjust_hash_alg(crypto);
231 }
232 
233 static bool
validate_keygen_primary(const rnp_keygen_primary_desc_t * desc)234 validate_keygen_primary(const rnp_keygen_primary_desc_t *desc)
235 {
236     /* Confirm that the specified pk alg can certify.
237      * gpg requires this, though the RFC only says that a V4 primary
238      * key SHOULD be a key capable of certification.
239      */
240     if (!(pgp_pk_alg_capabilities(desc->crypto.key_alg) & PGP_KF_CERTIFY)) {
241         RNP_LOG("primary key alg (%d) must be able to sign", desc->crypto.key_alg);
242         return false;
243     }
244 
245     // check key flags
246     if (!desc->cert.key_flags) {
247         // these are probably not *technically* required
248         RNP_LOG("key flags are required");
249         return false;
250     } else if (desc->cert.key_flags & ~pgp_pk_alg_capabilities(desc->crypto.key_alg)) {
251         // check the flags against the alg capabilities
252         RNP_LOG("usage not permitted for pk algorithm");
253         return false;
254     }
255 
256     // require a userid
257     if (!desc->cert.userid[0]) {
258         RNP_LOG("userid is required for primary key");
259         return false;
260     }
261     return true;
262 }
263 
264 static uint32_t
get_numbits(const rnp_keygen_crypto_params_t * crypto)265 get_numbits(const rnp_keygen_crypto_params_t *crypto)
266 {
267     switch (crypto->key_alg) {
268     case PGP_PKA_RSA:
269     case PGP_PKA_RSA_ENCRYPT_ONLY:
270     case PGP_PKA_RSA_SIGN_ONLY:
271         return crypto->rsa.modulus_bit_len;
272     case PGP_PKA_ECDSA:
273     case PGP_PKA_ECDH:
274     case PGP_PKA_EDDSA:
275     case PGP_PKA_SM2: {
276         if (const ec_curve_desc_t *curve = get_curve_desc(crypto->ecc.curve)) {
277             return curve->bitlen;
278         } else {
279             return 0;
280         }
281     }
282     case PGP_PKA_DSA:
283         return crypto->dsa.p_bitlen;
284     case PGP_PKA_ELGAMAL:
285     case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
286         return crypto->elgamal.key_bitlen;
287     default:
288         return 0;
289     }
290 }
291 
292 static void
set_default_user_prefs(pgp_user_prefs_t & prefs)293 set_default_user_prefs(pgp_user_prefs_t &prefs)
294 {
295     if (prefs.symm_algs.empty()) {
296         prefs.set_symm_algs(
297           std::vector<uint8_t>(DEFAULT_SYMMETRIC_ALGS,
298                                DEFAULT_SYMMETRIC_ALGS + ARRAY_SIZE(DEFAULT_SYMMETRIC_ALGS)));
299     }
300     if (prefs.hash_algs.empty()) {
301         prefs.set_hash_algs(std::vector<uint8_t>(
302           DEFAULT_HASH_ALGS, DEFAULT_HASH_ALGS + ARRAY_SIZE(DEFAULT_HASH_ALGS)));
303     }
304     if (prefs.z_algs.empty()) {
305         prefs.set_z_algs(std::vector<uint8_t>(
306           DEFAULT_COMPRESS_ALGS, DEFAULT_COMPRESS_ALGS + ARRAY_SIZE(DEFAULT_COMPRESS_ALGS)));
307     }
308 }
309 
310 static const char *
pgp_show_pka(pgp_pubkey_alg_t pka)311 pgp_show_pka(pgp_pubkey_alg_t pka)
312 {
313     return pgp_str_from_map(pka, pubkey_alg_map);
314 }
315 
316 static void
keygen_primary_merge_defaults(rnp_keygen_primary_desc_t & desc)317 keygen_primary_merge_defaults(rnp_keygen_primary_desc_t &desc)
318 {
319     keygen_merge_crypto_defaults(desc.crypto);
320     set_default_user_prefs(desc.cert.prefs);
321 
322     if (!desc.cert.key_flags) {
323         // set some default key flags if none are provided
324         desc.cert.key_flags = pk_alg_default_flags(desc.crypto.key_alg);
325     }
326     if (desc.cert.userid[0] == '\0') {
327         snprintf((char *) desc.cert.userid,
328                  sizeof(desc.cert.userid),
329                  "%s %d-bit key <%s@localhost>",
330                  pgp_show_pka(desc.crypto.key_alg),
331                  get_numbits(&desc.crypto),
332                  getenv_logname());
333     }
334 }
335 
336 bool
pgp_generate_primary_key(rnp_keygen_primary_desc_t * desc,bool merge_defaults,pgp_key_t * primary_sec,pgp_key_t * primary_pub,pgp_key_store_format_t secformat)337 pgp_generate_primary_key(rnp_keygen_primary_desc_t *desc,
338                          bool                       merge_defaults,
339                          pgp_key_t *                primary_sec,
340                          pgp_key_t *                primary_pub,
341                          pgp_key_store_format_t     secformat)
342 {
343     // validate args
344     if (!desc || !primary_pub || !primary_sec) {
345         return false;
346     }
347     if (primary_sec->type() || primary_pub->type()) {
348         RNP_LOG("invalid parameters (should be zeroed)");
349         return false;
350     }
351 
352     // merge some defaults in, if requested
353     if (merge_defaults) {
354         try {
355             keygen_primary_merge_defaults(*desc);
356         } catch (const std::exception &e) {
357             RNP_LOG("%s", e.what());
358             return false;
359         }
360     }
361 
362     // now validate the keygen fields
363     if (!validate_keygen_primary(desc)) {
364         return false;
365     }
366 
367     // generate the raw key and fill tag/secret fields
368     pgp_transferable_key_t tkeysec;
369     if (!pgp_generate_seckey(&desc->crypto, &tkeysec.key, true)) {
370         return false;
371     }
372 
373     pgp_transferable_userid_t *uid =
374       transferable_key_add_userid(tkeysec, (char *) desc->cert.userid);
375     if (!uid) {
376         RNP_LOG("failed to add userid");
377         return false;
378     }
379 
380     if (!transferable_userid_certify(
381           tkeysec.key, *uid, tkeysec.key, desc->crypto.hash_alg, desc->cert)) {
382         RNP_LOG("failed to certify key");
383         return false;
384     }
385 
386     pgp_transferable_key_t tkeypub;
387     try {
388         tkeypub = pgp_transferable_key_t(tkeysec, true);
389         *primary_pub = tkeypub;
390     } catch (const std::exception &e) {
391         RNP_LOG("failed to copy public key part: %s", e.what());
392         return false;
393     }
394 
395     switch (secformat) {
396     case PGP_KEY_STORE_GPG:
397     case PGP_KEY_STORE_KBX:
398         try {
399             *primary_sec = tkeysec;
400         } catch (const std::exception &e) {
401             RNP_LOG("%s", e.what());
402             return false;
403         }
404         break;
405     case PGP_KEY_STORE_G10:
406         if (!load_generated_g10_key(primary_sec, &tkeysec.key, NULL, primary_pub)) {
407             RNP_LOG("failed to load generated key");
408             return false;
409         }
410         break;
411     default:
412         RNP_LOG("invalid format");
413         return false;
414     }
415 
416     /* mark it as valid */
417     primary_pub->mark_valid();
418     primary_sec->mark_valid();
419     /* refresh key's data */
420     return primary_pub->refresh_data() && primary_sec->refresh_data();
421 }
422 
423 static bool
validate_keygen_subkey(rnp_keygen_subkey_desc_t * desc)424 validate_keygen_subkey(rnp_keygen_subkey_desc_t *desc)
425 {
426     if (!desc->binding.key_flags) {
427         RNP_LOG("key flags are required");
428         return false;
429     } else if (desc->binding.key_flags & ~pgp_pk_alg_capabilities(desc->crypto.key_alg)) {
430         // check the flags against the alg capabilities
431         RNP_LOG("usage not permitted for pk algorithm");
432         return false;
433     }
434     return true;
435 }
436 
437 static void
keygen_subkey_merge_defaults(rnp_keygen_subkey_desc_t & desc)438 keygen_subkey_merge_defaults(rnp_keygen_subkey_desc_t &desc)
439 {
440     keygen_merge_crypto_defaults(desc.crypto);
441     if (!desc.binding.key_flags) {
442         // set some default key flags if none are provided
443         desc.binding.key_flags = pk_alg_default_flags(desc.crypto.key_alg);
444     }
445 }
446 
447 bool
pgp_generate_subkey(rnp_keygen_subkey_desc_t * desc,bool merge_defaults,pgp_key_t * primary_sec,pgp_key_t * primary_pub,pgp_key_t * subkey_sec,pgp_key_t * subkey_pub,const pgp_password_provider_t * password_provider,pgp_key_store_format_t secformat)448 pgp_generate_subkey(rnp_keygen_subkey_desc_t *     desc,
449                     bool                           merge_defaults,
450                     pgp_key_t *                    primary_sec,
451                     pgp_key_t *                    primary_pub,
452                     pgp_key_t *                    subkey_sec,
453                     pgp_key_t *                    subkey_pub,
454                     const pgp_password_provider_t *password_provider,
455                     pgp_key_store_format_t         secformat)
456 {
457     pgp_transferable_subkey_t tskeysec;
458     pgp_transferable_subkey_t tskeypub;
459     const pgp_key_pkt_t *     primary_seckey = NULL;
460     pgp_key_pkt_t *           decrypted_primary_seckey = NULL;
461     pgp_password_ctx_t        ctx = {};
462     bool                      ok = false;
463 
464     // validate args
465     if (!desc || !primary_sec || !primary_pub || !subkey_sec || !subkey_pub) {
466         RNP_LOG("NULL args");
467         goto end;
468     }
469     if (!primary_sec->is_primary() || !primary_pub->is_primary() ||
470         !primary_sec->is_secret() || !primary_pub->is_public()) {
471         RNP_LOG("invalid parameters");
472         goto end;
473     }
474     if (subkey_sec->type() || subkey_pub->type()) {
475         RNP_LOG("invalid parameters (should be zeroed)");
476         goto end;
477     }
478 
479     // merge some defaults in, if requested
480     if (merge_defaults) {
481         keygen_subkey_merge_defaults(*desc);
482     }
483 
484     // now validate the keygen fields
485     if (!validate_keygen_subkey(desc)) {
486         goto end;
487     }
488 
489     ctx = {.op = PGP_OP_ADD_SUBKEY, .key = primary_sec};
490 
491     // decrypt the primary seckey if needed (for signatures)
492     if (primary_sec->encrypted()) {
493         decrypted_primary_seckey = pgp_decrypt_seckey(primary_sec, password_provider, &ctx);
494         if (!decrypted_primary_seckey) {
495             goto end;
496         }
497         primary_seckey = decrypted_primary_seckey;
498     } else {
499         primary_seckey = &primary_sec->pkt();
500     }
501 
502     // generate the raw key pair
503     if (!pgp_generate_seckey(&desc->crypto, &tskeysec.subkey, false)) {
504         goto end;
505     }
506 
507     if (!transferable_subkey_bind(
508           *primary_seckey, tskeysec, desc->crypto.hash_alg, desc->binding)) {
509         RNP_LOG("failed to add subkey binding signature");
510         goto end;
511     }
512 
513     try {
514         *subkey_pub = pgp_key_t(pgp_transferable_subkey_t(tskeysec, true), primary_pub);
515     } catch (const std::exception &e) {
516         RNP_LOG("failed to copy public subkey part: %s", e.what());
517         goto end;
518     }
519 
520     switch (secformat) {
521     case PGP_KEY_STORE_GPG:
522     case PGP_KEY_STORE_KBX:
523         try {
524             *subkey_sec = pgp_key_t(tskeysec, primary_sec);
525         } catch (const std::exception &e) {
526             RNP_LOG("%s", e.what());
527             goto end;
528         }
529         break;
530     case PGP_KEY_STORE_G10:
531         if (!load_generated_g10_key(subkey_sec, &tskeysec.subkey, primary_sec, subkey_pub)) {
532             RNP_LOG("failed to load generated key");
533             goto end;
534         }
535         break;
536     default:
537         RNP_LOG("invalid format");
538         goto end;
539         break;
540     }
541 
542     subkey_pub->mark_valid();
543     subkey_sec->mark_valid();
544     ok = subkey_pub->refresh_data(primary_pub) && subkey_sec->refresh_data(primary_sec);
545 end:
546     if (decrypted_primary_seckey) {
547         delete decrypted_primary_seckey;
548     }
549     return ok;
550 }
551 
552 static void
keygen_merge_defaults(rnp_keygen_primary_desc_t * primary_desc,rnp_keygen_subkey_desc_t * subkey_desc)553 keygen_merge_defaults(rnp_keygen_primary_desc_t *primary_desc,
554                       rnp_keygen_subkey_desc_t * subkey_desc)
555 {
556     if (!primary_desc->cert.key_flags && !subkey_desc->binding.key_flags) {
557         // if no flags are set for either the primary key nor subkey,
558         // we can set up some typical defaults here (these are validated
559         // later against the alg capabilities)
560         primary_desc->cert.key_flags = PGP_KF_SIGN | PGP_KF_CERTIFY;
561         subkey_desc->binding.key_flags = PGP_KF_ENCRYPT;
562     }
563 }
564 
565 static void
print_keygen_crypto(const rnp_keygen_crypto_params_t * crypto)566 print_keygen_crypto(const rnp_keygen_crypto_params_t *crypto)
567 {
568     printf("key_alg: %s (%d)\n", pgp_show_pka(crypto->key_alg), crypto->key_alg);
569     if (crypto->key_alg == PGP_PKA_RSA) {
570         printf("bits: %u\n", crypto->rsa.modulus_bit_len);
571     } else {
572         printf("curve: %d\n", crypto->ecc.curve);
573     }
574     printf("hash_alg: %s (%d)\n", pgp_show_hash_alg(crypto->hash_alg), crypto->hash_alg);
575 }
576 
577 static void
print_keygen_primary(const rnp_keygen_primary_desc_t * desc)578 print_keygen_primary(const rnp_keygen_primary_desc_t *desc)
579 {
580     printf("Keygen (primary)\n");
581     print_keygen_crypto(&desc->crypto);
582 }
583 
584 static void
print_keygen_subkey(const rnp_keygen_subkey_desc_t * desc)585 print_keygen_subkey(const rnp_keygen_subkey_desc_t *desc)
586 {
587     printf("Keygen (subkey)\n");
588     print_keygen_crypto(&desc->crypto);
589 }
590 
591 bool
pgp_generate_keypair(rng_t * rng,rnp_keygen_primary_desc_t * primary_desc,rnp_keygen_subkey_desc_t * subkey_desc,bool merge_defaults,pgp_key_t * primary_sec,pgp_key_t * primary_pub,pgp_key_t * subkey_sec,pgp_key_t * subkey_pub,pgp_key_store_format_t secformat)592 pgp_generate_keypair(rng_t *                    rng,
593                      rnp_keygen_primary_desc_t *primary_desc,
594                      rnp_keygen_subkey_desc_t * subkey_desc,
595                      bool                       merge_defaults,
596                      pgp_key_t *                primary_sec,
597                      pgp_key_t *                primary_pub,
598                      pgp_key_t *                subkey_sec,
599                      pgp_key_t *                subkey_pub,
600                      pgp_key_store_format_t     secformat)
601 {
602     bool ok = false;
603 
604     if (rnp_get_debug(__FILE__)) {
605         print_keygen_primary(primary_desc);
606         print_keygen_subkey(subkey_desc);
607     }
608 
609     // validate args
610     if (!primary_desc || !subkey_desc || !primary_sec || !primary_pub || !subkey_sec ||
611         !subkey_pub) {
612         RNP_LOG("NULL args");
613         goto end;
614     }
615 
616     // merge some defaults in, if requested
617     if (merge_defaults) {
618         keygen_merge_defaults(primary_desc, subkey_desc);
619     }
620 
621     // generate the primary key
622     primary_desc->crypto.rng = rng;
623     if (!pgp_generate_primary_key(
624           primary_desc, merge_defaults, primary_sec, primary_pub, secformat)) {
625         RNP_LOG("failed to generate primary key");
626         goto end;
627     }
628 
629     // generate the subkey
630     subkey_desc->crypto.rng = rng;
631     if (!pgp_generate_subkey(subkey_desc,
632                              merge_defaults,
633                              primary_sec,
634                              primary_pub,
635                              subkey_sec,
636                              subkey_pub,
637                              NULL,
638                              secformat)) {
639         RNP_LOG("failed to generate subkey");
640         goto end;
641     }
642     ok = true;
643 end:
644     return ok;
645 }
646