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