diff options
Diffstat (limited to 'g10/keygen.c')
-rw-r--r-- | g10/keygen.c | 159 |
1 files changed, 139 insertions, 20 deletions
diff --git a/g10/keygen.c b/g10/keygen.c index 0f7a6a0aa..665a32c30 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -89,7 +89,8 @@ enum para_name { pSERIALNO, pCARDBACKUPKEY, pHANDLE, - pKEYSERVER + pKEYSERVER, + pMAILINGLIST }; struct para_data_s { @@ -102,6 +103,7 @@ struct para_data_s { unsigned int usage; struct revocation_key revkey; char value[1]; + int is_mailing_list; } u; }; @@ -807,7 +809,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk, cache_public_key (sub_pk); err = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_psk, 0x19, - 0, timestamp, 0, NULL, NULL, cache_nonce); + 0, timestamp, 0, NULL, NULL, NULL, cache_nonce); if (err) log_error ("make_keysig_packet failed for backsig: %s\n", gpg_strerror (err)); @@ -915,7 +917,7 @@ write_direct_sig (KBNODE root, PKT_public_key *psk, /* Make the signature. */ err = make_keysig_packet (&sig, pk, NULL,NULL, psk, 0x1F, - 0, timestamp, 0, + 0, timestamp, 0, NULL, keygen_add_revkey, revkey, cache_nonce); if (err) { @@ -931,13 +933,13 @@ write_direct_sig (KBNODE root, PKT_public_key *psk, } - /* Write a self-signature to the first user id in ROOT using the key PSK. USE and TIMESTAMP give the extra data we need for the signature. */ static gpg_error_t write_selfsigs (KBNODE root, PKT_public_key *psk, - unsigned int use, u32 timestamp, const char *cache_nonce) + unsigned int use, u32 timestamp, + int mailing_list, const char *cache_nonce) { gpg_error_t err; PACKET *pkt; @@ -945,6 +947,7 @@ write_selfsigs (KBNODE root, PKT_public_key *psk, PKT_user_id *uid; KBNODE node; PKT_public_key *pk; + struct notation *notations = NULL; if (opt.verbose) log_info (_("writing self signature\n")); @@ -968,10 +971,95 @@ write_selfsigs (KBNODE root, PKT_public_key *psk, signature creation is able to retrieve the public key. */ cache_public_key (pk); + if (mailing_list) + /* Add the mailing-list notation. */ + { + char *notation = "[email protected]=1"; + struct notation *notation_blob; + + notation_blob = string_to_notation (notation, 0); + if (! notation_blob) + { + log_bug ("Failed to create notation: %s\n", notation); + return gpg_error (GPG_ERR_INTERNAL); + } + + notation_blob->next = notations; + notations = notation_blob; + } + + if (mailing_list) + /* Add the subscriber-list-session-key notation. */ + { + char *notation = "[email protected]"; + struct pk_list pk_list; + /* The public key encrypted session key as a packet. */ + iobuf_t pk_esk; + DEK session_key_initial; + char *buffer; + size_t len; + struct notation *notation_blob; + + /* The initial session key encrypted with the new subscriber's + public key. */ + /* Initialize PK_LIST with just the encryption key. */ + pk_list.next = NULL; + pk_list.pk = pk; + /* Don't throw the key id. */ + pk_list.flags = 0; + + pk_esk = iobuf_temp (); + if (! pk_esk) + { + log_bug ("Out of memory allocating pk_esk\n"); + return gpg_error (GPG_ERR_INTERNAL); + } + + memset (&session_key_initial, 0, sizeof (session_key_initial)); + session_key_initial.algo = default_cipher_algo (); + make_session_key (&session_key_initial); + + /* We don't need ctrl: we are certain that pk_list doesn't + contain a mailing list key, which is the only thing that + write_pubkey_enc_from_list needs ctrl for. */ + err = write_pubkey_enc_from_list (NULL, &pk_list, + &session_key_initial, pk_esk); + if (err) + { + log_bug ("Failed to generate PK-ESK packet: %s\n", + gpg_strerror (err)); + return err; + } + + buffer = iobuf_get_temp_buffer (pk_esk); + len = iobuf_get_temp_length (pk_esk); + + notation_blob = blob_to_notation (notation, buffer, len); + if (! notation_blob) + { + log_bug ("Failed to create notation: %s=<SE-ESK packet, %zd bytes>\n", + notation, len); + return gpg_error (GPG_ERR_INTERNAL); + } + + { + FILE *fp = fopen ("/tmp/subscriber-list-session-key", "w"); + fwrite (buffer, len, 1, fp); + fclose (fp); + } + + notation_blob->next = notations; + notations = notation_blob; + } + + /* Make the signature. */ + /* We pass a callback (keygen_add_std_prefs) to add some extra data + to the self-signature. */ err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13, - 0, timestamp, 0, + 0, timestamp, 0, notations, keygen_add_std_prefs, pk, cache_nonce); + free_notation (notations); if (err) { log_error ("make_keysig_packet failed: %s\n", gpg_strerror (err)); @@ -991,9 +1079,10 @@ write_selfsigs (KBNODE root, PKT_public_key *psk, signature creation time. PRI_PSK is the key use for signing. SUB_PSK is a key used to create a back-signature; that one is only used if USE has the PUBKEY_USAGE_SIG capability. */ -static int +int write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk, - unsigned int use, u32 timestamp, const char *cache_nonce) + unsigned int use, u32 timestamp, const char *cache_nonce, + struct notation *notations) { gpg_error_t err; PACKET *pkt; @@ -1029,7 +1118,7 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk, oduap.usage = use; oduap.pk = sub_pk; err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18, - 0, timestamp, 0, + 0, timestamp, 0, notations, keygen_add_key_flags_and_expire, &oduap, cache_nonce); if (err) @@ -2471,7 +2560,7 @@ uid_already_in_keyblock (kbnode_t keyblock, const char *uid) the function prevents the creation of an already existing user ID. IF FULL is not set some prompts are not shown. */ static char * -ask_user_id (int mode, int full, KBNODE keyblock) +ask_user_id (int mode, int full, int mailing_list, KBNODE keyblock) { char *answer; char *aname, *acomment, *amail, *uid; @@ -2557,7 +2646,10 @@ ask_user_id (int mode, int full, KBNODE keyblock) } } if (!acomment) { - if (full) { + if (mailing_list) { + xfree (acomment); + acomment = xstrdup ("mailing list"); + } else if (full) { for(;;) { xfree(acomment); acomment = cpr_get("keygen.comment",_("Comment: ")); @@ -2766,7 +2858,7 @@ generate_user_id (KBNODE keyblock, const char *uidstr) } else { - p = ask_user_id (1, 1, keyblock); + p = ask_user_id (1, 1, 0, keyblock); if (!p) return NULL; /* Canceled. */ uid = uid_from_string (p); @@ -2974,6 +3066,8 @@ get_parameter_u32( struct para_data_s *para, enum para_name key ) return r->u.expire; if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE ) return r->u.usage; + if( r->key == pMAILINGLIST ) + return r->u.is_mailing_list; return (unsigned int)strtoul( r->u.value, NULL, 10 ); } @@ -3436,13 +3530,14 @@ quickgen_set_para (struct para_data_s *para, int for_subkey, * Unattended generation of a standard key. */ void -quick_generate_keypair (ctrl_t ctrl, const char *uid) +quick_generate_keypair (ctrl_t ctrl, const char *uid, int mailing_list) { gpg_error_t err; struct para_data_s *para = NULL; struct para_data_s *r; struct output_control_s outctrl; int use_tty; + const char *mailing_list_comment = " (mailing list)"; memset (&outctrl, 0, sizeof outctrl); @@ -3452,9 +3547,12 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid) && gnupg_isatty (fileno (stdout)) && gnupg_isatty (fileno (stderr))); - r = xmalloc_clear (sizeof *r + strlen (uid)); + r = xmalloc_clear (sizeof *r + strlen (uid) + + (mailing_list ? strlen (mailing_list_comment) : 0)); r->key = pUSERID; strcpy (r->u.value, uid); + if (mailing_list_comment) + strcat (r->u.value, mailing_list_comment); r->next = para; para = r; @@ -3476,6 +3574,15 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid) goto leave; } + if (mailing_list) + { + r = xcalloc (1, sizeof *r ); + r->key = pMAILINGLIST; + r->u.is_mailing_list = 1; + r->next = para; + para = r; + } + /* Check whether such a user ID already exists. */ { KEYDB_HANDLE kdbhd; @@ -3545,7 +3652,7 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid) * mode). */ void -generate_keypair (ctrl_t ctrl, int full, const char *fname, +generate_keypair (ctrl_t ctrl, int full, int mailing_list, const char *fname, const char *card_serialno, int card_backup_key) { unsigned int nbits; @@ -3577,6 +3684,15 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, return; } + if (mailing_list) + { + r = xcalloc (1, sizeof *r ); + r->key = pMAILINGLIST; + r->u.is_mailing_list = 1; + r->next = para; + para = r; + } + if (card_serialno) { #ifdef ENABLE_CARD_SUPPORT @@ -3787,7 +3903,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, r->next = para; para = r; - uid = ask_user_id (0, full, NULL); + uid = ask_user_id (0, full, mailing_list, NULL); if (!uid) { log_error(_("Key generation canceled.\n")); @@ -4071,6 +4187,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, write_uid (pub_root, s ); err = write_selfsigs (pub_root, pri_psk, get_parameter_uint (para, pKEYUSAGE), timestamp, + get_parameter_uint (para, pMAILINGLIST), cache_nonce); } @@ -4088,7 +4205,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, get_parameter_u32 (para, pKEYEXPIRE)); if (!err) err = write_keybinding (pub_root, pri_psk, NULL, - PUBKEY_USAGE_AUTH, timestamp, cache_nonce); + PUBKEY_USAGE_AUTH, timestamp, cache_nonce, + NULL); } if (!err && get_parameter (para, pSUBKEYTYPE)) @@ -4129,7 +4247,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, if (!err) err = write_keybinding (pub_root, pri_psk, sub_psk, get_parameter_uint (para, pSUBKEYUSAGE), - timestamp, cache_nonce); + timestamp, cache_nonce, NULL); did_sub = 1; } @@ -4334,7 +4452,8 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock) sub_psk = node->pkt->pkt.public_key; /* Write the binding signature. */ - err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL); + err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, + NULL, NULL); if (err) goto leave; @@ -4437,7 +4556,7 @@ generate_card_subkeypair (kbnode_t pub_keyblock, sub_pk = node->pkt->pkt.public_key; assert (sub_pk); err = write_keybinding (pub_keyblock, pri_pk, sub_pk, - use, cur_time, NULL); + use, cur_time, NULL, NULL); } leave: |