From dkg at fifthhorseman.net Fri Apr 1 17:56:08 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 01 Apr 2016 12:56:08 -0300 Subject: using gpg 2.1 under su or sudo Message-ID: <871t6pnx0n.fsf@alice.fifthhorseman.net> Some server administrators connect to their machines via ssh, and then use sudo or su to switch to a different user account for administering specific services. For example, the qux service for example.org might be running as the quxd user on machine.example.org; an admin might "ssh machine.example.org" and then "su - quxd" to configure or administer the service. if the service administration requires the use of GnuPG with secret key material (key generation, signing, encryption, certification, etc) and the administrator is using "modern" GnuPG (the 2.1 branch or later) then they're likely to have a problem because of gpg-agent. in this situation: * there is no X11 session * it's unlikely that there is a user dbus session running for quxd * there may be no system dbus session at all * the TTY attached to the console is owned by the admin's account (thanks to sshd), not by quxd, so while the quxd shell (and spawned subprocesses) can read and write to it thanks to inheriting the file descriptors, the backgrounded gpg-agent has closed those file descriptors and its spawned pinentry cannot connect to the pty even to display the curses fallback. So there appears to be no way for gpg-agent to prompt the user via any sort of normal pinentry here. Does anyone have a suggestion about how to facilitate this particular workflow? One approach is: echo 'allow-loopback-pinentry:0:1' | gpgconf --change-options gpg-agent echo pinentry-mode loopback >> ~/.gnupg/gpg.conf # why isn't pinentry-mode settable via gpgconf? but this means that the user only gets prompted once for the password (no strength checking, no confirmation), and it's also tedious setup for this account -- it'd be better if things "just worked". Any suggestions about what to do for this scenario? --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 948 bytes Desc: not available URL: From dkg at fifthhorseman.net Fri Apr 1 00:33:29 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Thu, 31 Mar 2016 18:33:29 -0400 Subject: GPG_NAME vs. --gpg2-is-gpg vs. documentation vs. installation In-Reply-To: <87bn5wyq3j.fsf@alice.fifthhorseman.net> References: <87bn5wyq3j.fsf@alice.fifthhorseman.net> Message-ID: <8760w2b7ly.fsf@alice.fifthhorseman.net> On Wed 2016-03-30 10:53:20 -0400, Daniel Kahn Gillmor wrote: > configure.ac defines a GPG_NAME variable that determines what we call > gpg. it also offers a --gpg2-is-gpg option, which sets the config > variable NAME_OF_INSTALLED_GPG. These can be set independently from one > another, which is a little confusing, and NAME_OF_INSTALLED_GPG does > *not* set GPG_NAME if it is not otherwise set. One other confusing option along these lines is PACKAGE_GT -- should PACKAGE_GT remain gnupg2? --dkg From ludwig at enigmail.net Sat Apr 2 11:16:42 2016 From: ludwig at enigmail.net (=?UTF-8?B?THVkd2lnIEjDvGdlbHNjaMOkZmVy?=) Date: Sat, 2 Apr 2016 11:16:42 +0200 Subject: Detection of a revocation certificate prior to import Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Hi, is it possible to identify a revocation certificate prior to import? - --list-packets does not seem to be very specific. We want to do this in Enigmail prior to import providing a preview. THX in advance! Ludwig -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJW/434AAoJEDrb+m0Aoeb+OOsP/1mubGlbIhuAAII1luYqyfWg KS4zDrYy96rX9OvX5TRhqH/ZWtzcWtaVBxpj9FSKR4SczwbZmUdIU9yB0hxkwBTN uIMIDh/+o4oqtf+6E2CFVdBSbzxR7aqLhVUIAfJluY1zyqB6z1vNCys5I7AYkcZl H1DXdA9DLyg3QukQuqnGrLMAg8aB5j2/FYkCXe7xmhrH1vTGFe5KN0R6lSXrOQ8S xq4G7WXghs4PRmSYpFnJzFqI81H97CJz/985fHB4Btx96n+VrCySxhLB3zs4gtC2 FL+w/Xn41j7t7pwr6hbePJryHc2RHrfvf9NGasTQA8shHkOUZprNDsVuIdx5VOAX MLoI2SfAKNtHLEahBhVGXUrwdqG7WlD4VogSNl+bQAn/Tukhy23VTGbowufb0gQJ XduYeI82koaLC7lVR9/71m4H5G0N3mgxd6jwnrJry0tQkOGVM6HEh+sCsHW1TUVO GHHg+h0riFMkmp32GaNzVEsSM2KctjE7pLNaDYqRDxgbtMWoNrzlZRitBztTQyRc FBWiJmGwRIvaVGpppXPEUqEHpNoI2KIh84Yz6oTse0jvtgzSec8XSYyuqSAmVH+0 bhDkm4FatNjVO8RB0ZYqpcdm/yHUoRRz+zE20omOksDgwlPsOxmeLz3gwWFnzZA8 MHp2YKBog5OAg+4cOdO/ =92Wo -----END PGP SIGNATURE----- From wk at gnupg.org Sat Apr 2 14:51:44 2016 From: wk at gnupg.org (Werner Koch) Date: Sat, 02 Apr 2016 14:51:44 +0200 Subject: GPG_NAME vs. --gpg2-is-gpg vs. documentation vs. installation In-Reply-To: <8760w2b7ly.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Thu, 31 Mar 2016 18:33:29 -0400") References: <87bn5wyq3j.fsf@alice.fifthhorseman.net> <8760w2b7ly.fsf@alice.fifthhorseman.net> Message-ID: <87wpogb2cf.fsf@wheatstone.g10code.de> On Fri, 1 Apr 2016 00:33, dkg at fifthhorseman.net said: > One other confusing option along these lines is PACKAGE_GT -- should > PACKAGE_GT remain gnupg2? It might be confusing but I don't see a real problem that the gettext domain is called gnupg2. Changing that would likely create only more friction and migration problems. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Mon Apr 4 04:06:56 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Sun, 03 Apr 2016 23:06:56 -0300 Subject: GPG_NAME vs. --gpg2-is-gpg vs. documentation vs. installation In-Reply-To: <87wpogb2cf.fsf@wheatstone.g10code.de> References: <87bn5wyq3j.fsf@alice.fifthhorseman.net> <8760w2b7ly.fsf@alice.fifthhorseman.net> <87wpogb2cf.fsf@wheatstone.g10code.de> Message-ID: <87wpoew2in.fsf@alice.fifthhorseman.net> On Sat 2016-04-02 09:51:44 -0300, Werner Koch wrote: > On Fri, 1 Apr 2016 00:33, dkg at fifthhorseman.net said: > >> One other confusing option along these lines is PACKAGE_GT -- should >> PACKAGE_GT remain gnupg2? > > It might be confusing but I don't see a real problem that the gettext > domain is called gnupg2. Changing that would likely create only more > friction and migration problems. That's fine with me, and i agree that keeping the two packages quite distinct from each other in gettext is a good thing. --dkg From dgouttegattat at incenp.org Mon Apr 4 21:41:15 2016 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Mon, 4 Apr 2016 21:41:15 +0200 Subject: [PATCH 1/3] Implement C_GenerateRandom. In-Reply-To: <20160404163505.16320.70157@thinkbox.jade-hamburg.de> References: <20160404163505.16320.70157@thinkbox.jade-hamburg.de> Message-ID: <1459798875-19859-1-git-send-email-dgouttegattat@incenp.org> > Here we trust that the server does not return more than requested. In > the interest of robustness it is probably best to check that. You're right. Please find a modified patch below. This version checks whether we got exactly the requested amount of random bytes (no more, no less), and returns an error if that is not the case. Since the caller of C_GenerateRandom has no way of knowing how many bytes were effectively obtained from the token, I think we should not return OK unless we can provide him with exactly what he has asked. -- >8 -- * src/agent.c (scute_agent_get_random, get_challenge_data_cb): New functions. * src/agent.h (scute_agent_get_random): New prototype. * src/p11-generaterandom.c (C_GenerateRandom): Implement feature. Signed-off-by: Damien Goutte-Gattat --- src/agent.c | 36 ++++++++++++++++++++++++++++++++++++ src/agent.h | 3 +++ src/p11-generaterandom.c | 28 +++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/agent.c b/src/agent.c index b51dc7e..d2ca9b9 100644 --- a/src/agent.c +++ b/src/agent.c @@ -1281,6 +1281,42 @@ scute_agent_get_cert (int no, struct cert *cert) return 0; } +struct random_request +{ + unsigned char *buffer; + size_t len; +}; + +gpg_error_t +get_challenge_data_cb (void *opaque, const void *line, size_t len) +{ + struct random_request *request = opaque; + + if ( len != request->len ) + return gpg_error (GPG_ERR_INV_LENGTH); + + memcpy (request->buffer, line, len); + + return 0; +} + +gpg_error_t +scute_agent_get_random (unsigned char *data, size_t len) +{ + char command[16]; + gpg_error_t err; + struct random_request request; + + snprintf (command, sizeof(command), "SCD RANDOM %lu", len); + + request.buffer = data; + request.len = len; + err = assuan_transact (agent_ctx, command, get_challenge_data_cb, + &request, NULL, NULL, NULL, NULL); + + return err; +} + void scute_agent_finalize (void) diff --git a/src/agent.h b/src/agent.h index 6ac479f..6f3f6df 100644 --- a/src/agent.h +++ b/src/agent.h @@ -113,4 +113,7 @@ gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted); /* Try to get certificate for key numer NO. */ gpg_error_t scute_agent_get_cert (int no, struct cert *cert); +/* Get random bytes from the card. */ +gpg_error_t scute_agent_get_random (unsigned char *data, size_t len); + #endif /* AGENT_H */ diff --git a/src/p11-generaterandom.c b/src/p11-generaterandom.c index f192e9d..e8b20d9 100644 --- a/src/p11-generaterandom.c +++ b/src/p11-generaterandom.c @@ -33,14 +33,32 @@ #include "cryptoki.h" +#include "locking.h" +#include "slots.h" +#include "agent.h" +#include "error-mapping.h" + CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { - /* FIXME: Implement me. */ - (void) hSession; - (void) pRandomData; - (void) ulRandomLen; - return CKR_FUNCTION_NOT_SUPPORTED; + CK_RV err; + slot_iterator_t slot; + session_iterator_t session; + + if (pRandomData == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + err = scute_global_lock (); + if (err) + return err; + + err = slots_lookup_session (hSession, &slot, &session); + if (!err) + err = scute_gpg_err_to_ck (scute_agent_get_random (pRandomData, + ulRandomLen)); + + scute_global_unlock (); + return err; } -- 2.7.4 From wk at gnupg.org Tue Apr 5 11:22:55 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 05 Apr 2016 11:22:55 +0200 Subject: [PATCH 2/3] avoid hardcoded use of gpg2 in gpgcompose documentation In-Reply-To: <1459353063-6898-2-git-send-email-dkg@fifthhorseman.net> (Daniel Kahn Gillmor's message of "Wed, 30 Mar 2016 11:51:02 -0400") References: <1459353063-6898-1-git-send-email-dkg@fifthhorseman.net> <1459353063-6898-2-git-send-email-dkg@fifthhorseman.net> Message-ID: <878u0s2yvk.fsf@wheatstone.g10code.de> On Wed, 30 Mar 2016 17:51, dkg at fifthhorseman.net said: > * g10/gpgcompose.c: use GPG_NAME configure variable instead of > hardcoded string "gpg2" in example output. I have done this as part of 7b58a11f. However, I also changed the build system to build gpgcompose when configure has been run with --enable-maintainer-mode. The reason for this is that gpgcompose diverts in some details too much from the other tools and thus I fear that we will run into portability problems. This should also be an indication that gpgcompose may change at any time without notice. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Apr 5 11:29:41 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 05 Apr 2016 11:29:41 +0200 Subject: GPG_NAME vs. --gpg2-is-gpg vs. documentation vs. installation In-Reply-To: <878u10yn2r.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Wed, 30 Mar 2016 11:58:36 -0400") References: <87bn5wyq3j.fsf@alice.fifthhorseman.net> <87io04j9ea.fsf@wheatstone.g10code.de> <878u10yn2r.fsf@alice.fifthhorseman.net> Message-ID: <874mbg2yka.fsf@wheatstone.g10code.de> On Wed, 30 Mar 2016 17:58, dkg at fifthhorseman.net said: > Thanks! I've just sent a series of three patches that start down this > path. Thanks. However, I took a different approach which should yield the same result. Now GnuPg builds binaries gpg and gpgv and onlys installs them as gpg2/gpgv2. This has the advantage that eventually we can make --enable-gpg2-is-gpg the default without chnaging anything else in the source (e.g. the tests). Thus in the gnupg build tree gpg is now always called gpg. > Ideally, they would affect the names and the content of the generated > manpages and info documentation as well -- for the experimental debian Will come soon. > try to produce a similar approach for the "classic" branch: something > like ./configure --enable-gpg1-is-gpg (it would default to "yes" for Yep. In this case I would suggest to rename gpg.c to gpg1.c and use your install-hook to rename gpg1 to gpg in the target directory. We also need to rename the man page. > Does that seem like a sensible approach? Yes. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From aheinecke at intevation.de Tue Apr 5 12:42:08 2016 From: aheinecke at intevation.de (Andre Heinecke) Date: Tue, 05 Apr 2016 12:42:08 +0200 Subject: [PATCH] libgpg-error: Fix windows build Message-ID: <5821882.xz7X3DreAU@esus> Hi, libgpg-error fails to compile for windows without optimization because it uses the FD_ISSET macro and does not link against ws2_32. Attached patch provides a simple replacement function for FD_ISSET to be used on Windows. Please apply this or fix it in another way, code should not rely on optimization behavior to compile. To reproduce the build error: ../configure --host=i686-w64-mingw32 CFLAGS= make Regards, Andre -- Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/ Intevation GmbH, Neuer Graben 17, 49074 Osnabr?ck | AG Osnabr?ck, HR B 18998 Gesch?ftsf?hrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Add-FD_ISSET-replacement-for-Windows.patch Type: text/x-patch Size: 1952 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 648 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Tue Apr 5 15:47:08 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 05 Apr 2016 15:47:08 +0200 Subject: [PATCH] libgpg-error: Fix windows build In-Reply-To: <5821882.xz7X3DreAU@esus> (Andre Heinecke's message of "Tue, 05 Apr 2016 12:42:08 +0200") References: <5821882.xz7X3DreAU@esus> Message-ID: <87inzw182r.fsf@wheatstone.g10code.de> On Tue, 5 Apr 2016 12:42, aheinecke at intevation.de said: > libgpg-error fails to compile for windows without optimization because it uses > the FD_ISSET macro and does not link against ws2_32. Actually gpgrt_poll returns EOPNOTSUPP under Windows and thus tehre is no need to use that macro. I am working on a poll implementation for Windows, though. I have thus pushed a simpler fix. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Apr 5 15:54:25 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 05 Apr 2016 15:54:25 +0200 Subject: [PATCH 2/3] Check whether the card has a RNG. In-Reply-To: <1459262679-16490-3-git-send-email-dgouttegattat@incenp.org> (Damien Goutte-Gattat's message of "Tue, 29 Mar 2016 16:44:38 +0200") References: <1459262679-16490-1-git-send-email-dgouttegattat@incenp.org> <1459262679-16490-3-git-send-email-dgouttegattat@incenp.org> Message-ID: <87egak17qm.fsf@wheatstone.g10code.de> On Tue, 29 Mar 2016 16:44, dgouttegattat at incenp.org said: > + else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen)) > + { > + /* FIXME: Should we parse the line properly instead of assuming > + that the gc capability will always be at the beginning? */ > + sscanf (line, "gc=%d", &(parm->rng_available)); Yes, please. Here is a snippet from GnuPG which does this. I grant you the right to use this under "GPLv2+ with exception for Mozilla" as used by Scute. --8<---------------cut here---------------start------------->8--- else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen)) { char *p, *p2, *buf; int abool; buf = p = unescape_status_string (line); if (buf) { for (p = strtok (buf, " "); p; p = strtok (NULL, " ")) { p2 = strchr (p, '='); if (p2) { *p2++ = 0; abool = (*p2 == '1'); if (!strcmp (p, "ki")) parm->extcap.ki = abool; else if (!strcmp (p, "aac")) parm->extcap.aac = abool; else if (!strcmp (p, "si")) parm->status_indicator = strtoul (p2, NULL, 10); } } xfree (buf); } } --8<---------------cut here---------------end--------------->8--- Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 180 bytes Desc: not available URL: From wk at gnupg.org Tue Apr 5 15:57:18 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 05 Apr 2016 15:57:18 +0200 Subject: [PATCH 0/3] scute: Implement C_GenerateRandom function. In-Reply-To: <1459262679-16490-1-git-send-email-dgouttegattat@incenp.org> (Damien Goutte-Gattat's message of "Tue, 29 Mar 2016 16:44:36 +0200") References: <1459262679-16490-1-git-send-email-dgouttegattat@incenp.org> Message-ID: <878u0s17lt.fsf@wheatstone.g10code.de> Hi, Thanks for working on Scute. Justus: Can you please take care of Damien's patches. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From erik.nellessen at informatik.hu-berlin.de Tue Apr 5 19:14:45 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Tue, 5 Apr 2016 17:14:45 +0000 Subject: Bad signature when generating key in OpenPGP Java Card Applet Message-ID: <5703F285.5050908@informatik.hu-berlin.de> Hi everybody, I am running an OpenPGP Java card applet on an Android Smartphone via HCE. So for the PC side, this looks like a normal Java card. The communication with GnuPG works fine (i.e. gpg2 --card-status works), until I generate a key on the card (via gpg2 --card-edit, then "admin", then "generate"). I also tried the ykneo-openpgp-applet, which resulted in the same error. I get the following error on the PC: DBG: rsa_verify data:+01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ DBG: ffffffffffffffffffffff003031300d06096086480165030402010500042026 \ DBG: 5a93d234241bd20bf0773b6011fd037cbe8b985d487116dc08e6914f38dbd1 DBG: rsa_verify sig:+060c442ed6074b6b7dba6dcac223be83d251c7230f34d62cd81c5f38d8146f88 \ DBG: 14b477b3d9e60106cfb01fc372e9cf82929b1de4d760c74550b53559de717b20 \ DBG: 48b264ad1116e035fd0de5c8c2a43cbcf3d84fabc76a84500fc2b2652dcde19b \ DBG: 7a46f32d5e4871913bd5b8f3051fb4ca9a00a32542e6e194553b98ce6843c8b4 \ DBG: 3ba5049f78a7957dcce6a272f939d2016bc33d48819976ce89a3bf7d7d335eaa \ DBG: e0bbc913c011e8dfea8c6b2e506b59d8214eeae1ed4abe1e9ed6bf32475a3c65 \ DBG: 373eea3c9caa1058c5c11a506c931e26fc34ced607a8afb57ca1f69ccdfa24cf \ DBG: 8f3d062cff8685db11e7a3f60f98cbede2f116ab0d89bc0eab275cd90b79b1a1 DBG: rsa_verify n:+b81244edd096c6646a1c6d9a91142f01919cc71f4f289696572fe933f9c69aed \ DBG: 87752404f460e03c2768f285e491fdf074b6439293f8d58695e6e1af993f4046 \ DBG: a9a31c5633e464009a96e6c0481c1f894eb6b04f1c2ea34cb2ece43a7b832973 \ DBG: 0cb4ce384de20e1e5a5b48617293f76fad3ea56abbb2f932540d4176a9afcb47 \ DBG: 5c973904f8c96381ee736e73fa631966ca1f5746a3703662a48fb0aeb89824cc \ DBG: 75637e8cef57cd08a93c685455055b8c2e62e3b450d5880e8138cf4c6cdc15ff \ DBG: 3716edcd96b96946b387abe38a0df1abeeeb53462f5038bfffc853bb55a3e66d \ DBG: 2ae50003b1bdd89357b168aad127fdfe474d78f57020f517ddc0f02b204fda99 DBG: rsa_verify e:+010001 DBG: rsa_verify cmp:+01ffffffffffffffff003031300d060960864801650304020105000420265a93 \ DBG: d234241bd20bf0773b6011fd037cbe8b985d487116dc08e6914f38dbd1000000 \ DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ DBG: 00000000000000000000000000000000000000000000000000000000000000 DBG: rsa_verify => Falsche Unterschrift gpg: Pr?fung der erstellten Signatur ist fehlgeschlagen: Falsche Unterschrift gpg: Beglaubigung fehlgeschlagen: Falsche Unterschrift gpg: make_keysig_packet failed: Falsche Unterschrift Schl?sselerzeugung fehlgeschlagen: Falsche Unterschrift (The last four lines say, that the verification of the signature has failed, "Bad signature". Sorry, my gpg2 produces german error messages.) As you can see, the "data" and the "cmp" part are totally equal except for the (I guess PKCS1) padding (I checked this via diff and meld, it really is the same). So I think that the difference in the paddings is the reason for which the signature verification fails. I guess, that the data given to the rsa_verify function is not padded as it should be. The logs from the smartphone show, that the data has been transferred to the PC without padding: Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 Sending APDU (257 bytes): 060C442ED6074B6B7DBA6DCAC223BE83D251C7230F34D62CD81C5F38D8146F8814B477B3D9E60106CFB01FC372E9CF82929B1DE4D760C74550B53559DE717B2048B264AD1116E035FD0DE5C8C2A43CBCF3D84FABC76A84500FC2B2652DCDE19B7A46F32D5E4871913BD5B8F3051FB4CA9A00A32542E6E194553B98CE6843C8B43BA5049F78A7957DCCE6A272F939D2016BC33D48819976CE89A3BF7D7D335EAAE0BBC913C011E8DFEA8C6B2E506B59D8214EEAE1ED4ABE1E9ED6BF32475A3C65373EEA3C9CAA1058C5C11A506C931E26FC34CED607A8AFB57CA1F69CCDFA24CF8F3D062CFF8685DB11E7A3F60F98CBEDE2F116AB0D89BC0EAB275CD90B79B16101 Received APDU (5 bytes): 00C0000001 Sending APDU (3 bytes): A19000 I think, the data received from the card and the data generated to be compared must be padded in the same way. Or even better, the padding (and the trailing zeros) should be removed before verifying the signature. I am running gpg (GnuPG) 2.0.26 libgcrypt 1.6.3 on Debian Jessie. Using gpg (GnuPG) 1.4.18 results in the same error. Can anyone reproduce this error (using a normal Java Card instead of the Android smartphone should not change anything)? Or am I missing something here? Kind regards, Erik Nellessen From dgouttegattat at incenp.org Wed Apr 6 09:16:57 2016 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Wed, 6 Apr 2016 09:16:57 +0200 Subject: [PATCH v2 0/3] scute: Implement C_GenerateRandom function. In-Reply-To: <87egak17qm.fsf@wheatstone.g10code.de> References: <87egak17qm.fsf@wheatstone.g10code.de> Message-ID: <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> Hi, Thank you Werner for the parsing code snippet, that was very helpful! For convenience, I re-send the whole modified patch set. Damien Goutte-Gattat (3): Implement C_GenerateRandom. Check whether the card has a RNG. Add test for C_GenerateRandom. src/agent.c | 60 +++++++++++++++++++++++++++ src/agent.h | 5 +++ src/p11-generaterandom.c | 28 ++++++++++--- src/p11-gettokeninfo.c | 7 +++- src/slots.c | 9 ++++ src/slots.h | 3 ++ tests/Makefile.am | 2 +- tests/t-generaterandom.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 tests/t-generaterandom.c -- 2.7.4 From dgouttegattat at incenp.org Wed Apr 6 09:16:59 2016 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Wed, 6 Apr 2016 09:16:59 +0200 Subject: [PATCH v2 2/3] Check whether the card has a RNG. In-Reply-To: <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> References: <87egak17qm.fsf@wheatstone.g10code.de> <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> Message-ID: <1459927020-4238-3-git-send-email-dgouttegattat@incenp.org> * src/agent.c (learn_status_cb): Learn from the agent whether the card supports GET CHALLENGE. * src/agent.h (struct agent_card_info_s): New member rng_available. * src/p11-gettokeninfo (C_GetTokenInfo): Set CKF_RNG flag. * src/slots.c (slot_token_has_rng): New function. * src/slots.h (slot_token_has_rng): New prototype. Parse card capabilities -- Now that C_GenerateRandom is implemented, we can inform the client application that a RNG is available on the token. But support for the GET CHALLENGE operation does not seem to be mandatory as per the OpenPGP Card specification, so we should first make sure that the inserted token does support it. The code for parsing the EXTCAP line is taken from GnuPG, with Werner's permission to reuse it under the same licensing terms as the rest of Scute. Signed-off-by: Damien Goutte-Gattat --- src/agent.c | 24 ++++++++++++++++++++++++ src/agent.h | 2 ++ src/p11-gettokeninfo.c | 7 +++++-- src/slots.c | 9 +++++++++ src/slots.h | 3 +++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/agent.c b/src/agent.c index e2ed31e..8fc48e0 100644 --- a/src/agent.c +++ b/src/agent.c @@ -846,6 +846,30 @@ learn_status_cb (void *opaque, const char *line) } } } + else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen)) + { + char *p, *p2, *buf; + int abool; + + buf = p = unescape_status_string (line); + if (buf) + { + for (p = strtok (buf, " "); p; p = strtok (NULL, " ")) + { + p2 = strchr (p, '='); + if (p2) + { + *p2++ = 0; + abool = (*p2 == '1'); + if (!strcmp (p, "gc")) + parm->rng_available = abool; + /* We're currently not interested in the + * other capabilities. */ + } + } + free (buf); + } + } return 0; } diff --git a/src/agent.h b/src/agent.h index 6f3f6df..0d6bb30 100644 --- a/src/agent.h +++ b/src/agent.h @@ -73,6 +73,8 @@ struct agent_card_info_s char grip1[41]; char grip2[41]; char grip3[41]; + int rng_available; /* True if the GET CHALLENGE operation + is supported. */ }; diff --git a/src/p11-gettokeninfo.c b/src/p11-gettokeninfo.c index 88d77be..c0a2417 100644 --- a/src/p11-gettokeninfo.c +++ b/src/p11-gettokeninfo.c @@ -72,8 +72,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo) pInfo->flags = CKF_TOKEN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED; - /* FIXME: Support this later: CKF_RNG. - FIXME: CKF_USER_PIN_INITIALIZED only if PIN is not default pin? + + if (slot_token_has_rng (slot)) + pInfo->flags |= CKF_RNG; + + /* FIXME: CKF_USER_PIN_INITIALIZED only if PIN is not default pin? FIXME: CKF_LOGIN_REQUIRED needed? We could implement login via the "SCD CHECKPIN" command. I am not sure how this mixes with CKF_PROTECTED_AUTHENTICATION_PATH. diff --git a/src/slots.c b/src/slots.c index 136d64e..810be0b 100644 --- a/src/slots.c +++ b/src/slots.c @@ -657,6 +657,15 @@ slot_get_id (slot_iterator_t slot) return slot; } +/* Return true if the token supports the GET CHALLENGE operation. */ +bool +slot_token_has_rng (slot_iterator_t id) +{ + struct slot *slot = scute_table_data (slots, id); + + return slot->info.rng_available; +} + /* Mechanism management. */ diff --git a/src/slots.h b/src/slots.h index e36be27..3624c55 100644 --- a/src/slots.h +++ b/src/slots.h @@ -116,6 +116,9 @@ void slot_token_pincount (slot_iterator_t id, int *max, int *len); /* Return the ID of slot SLOT. */ CK_SLOT_ID slot_get_id (slot_iterator_t slot); +/* Return true if the token supports the GET CHALLENGE operation. */ +bool slot_token_has_rng (slot_iterator_t id); + /* Begin iterating over the list of mechanisms. If succeeds, will be followed up by a slot_iterate_end. */ -- 2.7.4 From dgouttegattat at incenp.org Wed Apr 6 09:16:58 2016 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Wed, 6 Apr 2016 09:16:58 +0200 Subject: [PATCH v2 1/3] Implement C_GenerateRandom. In-Reply-To: <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> References: <87egak17qm.fsf@wheatstone.g10code.de> <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> Message-ID: <1459927020-4238-2-git-send-email-dgouttegattat@incenp.org> * src/agent.c (scute_agent_get_random, get_challenge_data_cb): New functions. * src/agent.h (scute_agent_get_random): New prototype. * src/p11-generaterandom.c (C_GenerateRandom): Implement feature. Signed-off-by: Damien Goutte-Gattat --- src/agent.c | 36 ++++++++++++++++++++++++++++++++++++ src/agent.h | 3 +++ src/p11-generaterandom.c | 28 +++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/agent.c b/src/agent.c index b51dc7e..e2ed31e 100644 --- a/src/agent.c +++ b/src/agent.c @@ -1281,6 +1281,42 @@ scute_agent_get_cert (int no, struct cert *cert) return 0; } +struct random_request +{ + unsigned char *buffer; + size_t len; +}; + +gpg_error_t +get_challenge_data_cb (void *opaque, const void *line, size_t len) +{ + struct random_request *request = opaque; + + if (len != request->len) + return gpg_error (GPG_ERR_INV_LENGTH); + + memcpy (request->buffer, line, len); + + return 0; +} + +gpg_error_t +scute_agent_get_random (unsigned char *data, size_t len) +{ + char command[16]; + gpg_error_t err; + struct random_request request; + + snprintf (command, sizeof(command), "SCD RANDOM %lu", len); + + request.buffer = data; + request.len = len; + err = assuan_transact (agent_ctx, command, get_challenge_data_cb, + &request, NULL, NULL, NULL, NULL); + + return err; +} + void scute_agent_finalize (void) diff --git a/src/agent.h b/src/agent.h index 6ac479f..6f3f6df 100644 --- a/src/agent.h +++ b/src/agent.h @@ -113,4 +113,7 @@ gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted); /* Try to get certificate for key numer NO. */ gpg_error_t scute_agent_get_cert (int no, struct cert *cert); +/* Get random bytes from the card. */ +gpg_error_t scute_agent_get_random (unsigned char *data, size_t len); + #endif /* AGENT_H */ diff --git a/src/p11-generaterandom.c b/src/p11-generaterandom.c index f192e9d..e8b20d9 100644 --- a/src/p11-generaterandom.c +++ b/src/p11-generaterandom.c @@ -33,14 +33,32 @@ #include "cryptoki.h" +#include "locking.h" +#include "slots.h" +#include "agent.h" +#include "error-mapping.h" + CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { - /* FIXME: Implement me. */ - (void) hSession; - (void) pRandomData; - (void) ulRandomLen; - return CKR_FUNCTION_NOT_SUPPORTED; + CK_RV err; + slot_iterator_t slot; + session_iterator_t session; + + if (pRandomData == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + err = scute_global_lock (); + if (err) + return err; + + err = slots_lookup_session (hSession, &slot, &session); + if (!err) + err = scute_gpg_err_to_ck (scute_agent_get_random (pRandomData, + ulRandomLen)); + + scute_global_unlock (); + return err; } -- 2.7.4 From dgouttegattat at incenp.org Wed Apr 6 09:17:00 2016 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Wed, 6 Apr 2016 09:17:00 +0200 Subject: [PATCH v2 3/3] Add test for C_GenerateRandom. In-Reply-To: <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> References: <87egak17qm.fsf@wheatstone.g10code.de> <1459927020-4238-1-git-send-email-dgouttegattat@incenp.org> Message-ID: <1459927020-4238-4-git-send-email-dgouttegattat@incenp.org> * tests/Makefile.am (TESTS): Add t-generaterandom test. * tests/t-generaterandom.c: New file. Signed-off-by: Damien Goutte-Gattat --- tests/Makefile.am | 2 +- tests/t-generaterandom.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/t-generaterandom.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 644eeb0..6c19071 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,7 +33,7 @@ noinst_HEADERS = t-support.h TESTS = t-link t-getfunctionlist t-initialize t-getinfo t-getslotlist \ t-getslotinfo t-gettokeninfo t-getmechanismlist t-getmechanisminfo \ t-opensession t-closeallsessions t-getsessioninfo \ - t-findobjects t-getattribute t-auth + t-findobjects t-getattribute t-auth t-generaterandom noinst_PROGRAMS = $(TESTS) diff --git a/tests/t-generaterandom.c b/tests/t-generaterandom.c new file mode 100644 index 0000000..675138d --- /dev/null +++ b/tests/t-generaterandom.c @@ -0,0 +1,105 @@ +/* t-generaterandom.c - Regression test. + Copyright (C) 2016 g10 Code GmbH + + This file is part of Scute. + + Scute is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Scute is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Scute; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, g10 Code GmbH gives permission + to link this library: with the Mozilla Foundation's code for + Mozilla (or with modified versions of it that use the same license + as the "Mozilla" code), and distribute the linked executables. You + must obey the GNU General Public License in all respects for all of + the code used other than "Mozilla". If you modify this file, you + may extend this exception to your version of the file, but you are + not obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + +#include +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + CK_RV err; + CK_SLOT_ID_PTR slots; + CK_ULONG slots_count; + unsigned int i; + + (void) argc; + (void) argv; + + init_cryptoki (); + + err = C_GetSlotList (true, NULL, &slots_count); + fail_if_err (err); + + if (slots_count == 0) + { + printf ("Skipping test because no token is present.\n"); + return 77; + } + + printf ("Number of slots with tokens: %lu\n", slots_count); + slots = malloc (sizeof (CK_SLOT_ID) * slots_count); + if (!slots) + fail_if_err (CKR_HOST_MEMORY); + + err = C_GetSlotList (true, slots, &slots_count); + fail_if_err (err); + + for (i = 0; i < slots_count; i++) + { + CK_TOKEN_INFO info; + + printf ("%2i. Slot ID %lu\n", i, slots[i]); + + err = C_GetTokenInfo (slots[i], &info); + fail_if_err (err); + + if ((info.flags & CKF_RNG) > 0) + { + CK_SESSION_HANDLE session; + unsigned char buffer[16]; + unsigned int j; + + printf(" RNG available\n"); + + err = C_OpenSession (slots[i], CKF_SERIAL_SESSION, NULL, NULL, + &session); + fail_if_err (err); + + printf (" Session ID: %lu\n", session); + + err = C_GenerateRandom (session, buffer, sizeof(buffer)); + fail_if_err (err); + + printf (" Random bytes: 0x"); + for (j = 0; j < sizeof(buffer); j++) + printf ("%02x", buffer[j]); + printf ("\n"); + + err = C_CloseSession (session); + fail_if_err (err); + } + else + printf (" No RNG available on token\n"); + } + + return 0; +} -- 2.7.4 From erik.nellessen at informatik.hu-berlin.de Wed Apr 6 17:29:06 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Wed, 6 Apr 2016 17:29:06 +0200 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <5703F285.5050908@informatik.hu-berlin.de> References: <5703F285.5050908@informatik.hu-berlin.de> Message-ID: <57052B42.9080704@informatik.hu-berlin.de> I could reproduce the error today on another system. I also got the error messages in English: gpg: checking created signature failed: Bad signature gpg: signing failed: Bad signature gpg: make_keysig_packet failed: Bad signature Key generation failed: Bad signature Today's system is openSUSE 13.2 (Harlequin) (x86_64) with gpg (GnuPG) 2.0.26 libgcrypt 1.6.1. The debian system was i386, by the way. Any kind of help would be appreciated! Kind regards, Erik Nellessen Am 05.04.2016 um 19:14 schrieb Erik Nellessen: > Hi everybody, > > I am running an OpenPGP Java card applet on an Android Smartphone via HCE. So for the PC side, this looks like a normal Java card. The communication with GnuPG works fine (i.e. gpg2 --card-status works), until I generate a key on the card (via gpg2 --card-edit, then "admin", then "generate"). I also tried the ykneo-openpgp-applet, which resulted in the same error. > > I get the following error on the PC: > > DBG: rsa_verify data:+01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \ > DBG: ffffffffffffffffffffff003031300d06096086480165030402010500042026 \ > DBG: 5a93d234241bd20bf0773b6011fd037cbe8b985d487116dc08e6914f38dbd1 > DBG: rsa_verify sig:+060c442ed6074b6b7dba6dcac223be83d251c7230f34d62cd81c5f38d8146f88 \ > DBG: 14b477b3d9e60106cfb01fc372e9cf82929b1de4d760c74550b53559de717b20 \ > DBG: 48b264ad1116e035fd0de5c8c2a43cbcf3d84fabc76a84500fc2b2652dcde19b \ > DBG: 7a46f32d5e4871913bd5b8f3051fb4ca9a00a32542e6e194553b98ce6843c8b4 \ > DBG: 3ba5049f78a7957dcce6a272f939d2016bc33d48819976ce89a3bf7d7d335eaa \ > DBG: e0bbc913c011e8dfea8c6b2e506b59d8214eeae1ed4abe1e9ed6bf32475a3c65 \ > DBG: 373eea3c9caa1058c5c11a506c931e26fc34ced607a8afb57ca1f69ccdfa24cf \ > DBG: 8f3d062cff8685db11e7a3f60f98cbede2f116ab0d89bc0eab275cd90b79b1a1 > DBG: rsa_verify n:+b81244edd096c6646a1c6d9a91142f01919cc71f4f289696572fe933f9c69aed \ > DBG: 87752404f460e03c2768f285e491fdf074b6439293f8d58695e6e1af993f4046 \ > DBG: a9a31c5633e464009a96e6c0481c1f894eb6b04f1c2ea34cb2ece43a7b832973 \ > DBG: 0cb4ce384de20e1e5a5b48617293f76fad3ea56abbb2f932540d4176a9afcb47 \ > DBG: 5c973904f8c96381ee736e73fa631966ca1f5746a3703662a48fb0aeb89824cc \ > DBG: 75637e8cef57cd08a93c685455055b8c2e62e3b450d5880e8138cf4c6cdc15ff \ > DBG: 3716edcd96b96946b387abe38a0df1abeeeb53462f5038bfffc853bb55a3e66d \ > DBG: 2ae50003b1bdd89357b168aad127fdfe474d78f57020f517ddc0f02b204fda99 > DBG: rsa_verify e:+010001 > DBG: rsa_verify cmp:+01ffffffffffffffff003031300d060960864801650304020105000420265a93 \ > DBG: d234241bd20bf0773b6011fd037cbe8b985d487116dc08e6914f38dbd1000000 \ > DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ > DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ > DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ > DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ > DBG: 0000000000000000000000000000000000000000000000000000000000000000 \ > DBG: 00000000000000000000000000000000000000000000000000000000000000 > DBG: rsa_verify => Falsche Unterschrift > gpg: Pr?fung der erstellten Signatur ist fehlgeschlagen: Falsche Unterschrift > gpg: Beglaubigung fehlgeschlagen: Falsche Unterschrift > gpg: make_keysig_packet failed: Falsche Unterschrift > Schl?sselerzeugung fehlgeschlagen: Falsche Unterschrift > > (The last four lines say, that the verification of the signature has failed, "Bad signature". Sorry, my gpg2 produces german error messages.) > > As you can see, the "data" and the "cmp" part are totally equal except for the (I guess PKCS1) padding (I checked this via diff and meld, it really is the same). So I think that the difference in the paddings is the reason for which the signature verification fails. I guess, that the data given to the rsa_verify function is not padded as it should be. The logs from the smartphone show, that the data has been transferred to the PC without padding: > > Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 > Sending APDU (257 bytes): 060C442ED6074B6B7DBA6DCAC223BE83D251C7230F34D62CD81C5F38D8146F8814B477B3D9E60106CFB01FC372E9CF82929B1DE4D760C74550B53559DE717B2048B264AD1116E035FD0DE5C8C2A43CBCF3D84FABC76A84500FC2B2652DCDE19B7A46F32D5E4871913BD5B8F3051FB4CA9A00A32542E6E194553B98CE6843C8B43BA5049F78A7957DCCE6A272F939D2016BC33D48819976CE89A3BF7D7D335EAAE0BBC913C011E8DFEA8C6B2E506B59D8214EEAE1ED4ABE1E9ED6BF32475A3C65373EEA3C9CAA1058C5C11A506C931E26FC34CED607A8AFB57CA1F69CCDFA24CF8F3D062CFF8685DB11E7A3F60F98CBEDE2F116AB0D89BC0EAB275CD90B79B16101 > Received APDU (5 bytes): 00C0000001 > Sending APDU (3 bytes): A19000 > > I think, the data received from the card and the data generated to be compared must be padded in the same way. Or even better, the padding (and the trailing zeros) should be removed before verifying the signature. > > I am running gpg (GnuPG) 2.0.26 libgcrypt 1.6.3 on Debian Jessie. Using gpg (GnuPG) 1.4.18 results in the same error. > > Can anyone reproduce this error (using a normal Java Card instead of the Android smartphone should not change anything)? Or am I missing something here? > > Kind regards, > Erik Nellessen > > _______________________________________________ > Gnupg-devel mailing list > Gnupg-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gnupg-devel > From wk at gnupg.org Wed Apr 6 18:38:54 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 06 Apr 2016 18:38:54 +0200 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <57052B42.9080704@informatik.hu-berlin.de> (Erik Nellessen's message of "Wed, 6 Apr 2016 17:29:06 +0200") References: <5703F285.5050908@informatik.hu-berlin.de> <57052B42.9080704@informatik.hu-berlin.de> Message-ID: <87wpoavgip.fsf@wheatstone.g10code.de> On Wed, 6 Apr 2016 17:29, erik.nellessen at informatik.hu-berlin.de said: > Today's system is openSUSE 13.2 (Harlequin) (x86_64) with gpg (GnuPG) > 2.0.26 libgcrypt 1.6.1. The debian system was i386, by the way. Please try to use gnupg 2.1.11 - we have changed a lot of things and it is easier for us to comment on this version. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From erik.nellessen at informatik.hu-berlin.de Thu Apr 7 09:28:33 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Thu, 7 Apr 2016 07:28:33 +0000 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <87wpoavgip.fsf@wheatstone.g10code.de> References: <5703F285.5050908@informatik.hu-berlin.de> <57052B42.9080704@informatik.hu-berlin.de> <87wpoavgip.fsf@wheatstone.g10code.de> Message-ID: <57060C21.1030605@informatik.hu-berlin.de> I just used gpg (GnuPG) 2.1.11 libgcrypt 1.6.5. The error is still the same, but the debug messages are different (actually, you do not see the data in the rsa_verify function anymore, although it still might be different). You can find a log of the whole procedure in the attachment. On the smart card side, the APDUs seem to have stayed the same. Kind regards, Erik Werner Koch: > On Wed, 6 Apr 2016 17:29, erik.nellessen at informatik.hu-berlin.de said: > >> Today's system is openSUSE 13.2 (Harlequin) (x86_64) with gpg (GnuPG) >> 2.0.26 libgcrypt 1.6.1. The debian system was i386, by the way. > > Please try to use gnupg 2.1.11 - we have changed a lot of things and it > is easier for us to comment on this version. > > > Salam-Shalom, > > Werner > -------------- next part -------------- :~$ LANG=en_US.utf8 gpg2 --card-edit --debug-level guru --debug-all gpg: Note: no default option file '/home/erik/.gnupg/gpg.conf' gpg: enabled debug flags: packet mpi crypto filter iobuf memory cache memstat trust hashing cardio ipc clock lookup extprog gpg: DBG: [not enabled in the source] start gpg: DBG: chan_4 <- OK Pleased to meet you, process 1641 gpg: DBG: connection to agent established gpg: DBG: chan_4 -> RESET gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION ttyname=/dev/pts/1 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION ttytype=xterm gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION display=:0.0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION xauthority=/home/erik/.Xauthority gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION putenv=DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-7FO1qPiGso,guid=aa46306c499eb658f19fcd31570608df gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> GETINFO version gpg: DBG: chan_4 <- D 2.1.11 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION allow-pinentry-notify gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> OPTION agent-awareness=2.1.0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> AGENT_ID gpg: DBG: chan_4 <- ERR 67109139 Unbekanntes IPC Kommando gpg: DBG: chan_4 -> SCD GETINFO version gpg: DBG: chan_4 <- D 2.1.11 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD SERIALNO openpgp gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD SERIALNO openpgp gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> LEARN --sendinfo gpg: DBG: chan_4 <- S SIG-COUNTER 0 gpg: DBG: chan_4 <- S CHV-STATUS +0+127+127+127+3+3+3 gpg: DBG: chan_4 <- S DISP-SEX 9 gpg: DBG: chan_4 <- S EXTCAP gc=1+ki=1+fc=1+pd=0+mcl3=1216+aac=0+sm=2+si=0+dec=0+bt=0 gpg: DBG: chan_4 <- S APPTYPE OPENPGP gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 0 gpg: DBG: chan_4 <- S READER REINER SCT cyberJack RFID basis 00 00 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR KEY-ATTR gpg: DBG: chan_4 <- S KEY-ATTR 1 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 2 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 3 1 rsa2048 17 4 gpg: DBG: chan_4 <- OK Reader ...........: REINER SCT cyberJack RFID basis 00 00 Application ID ...: D2760001240102000000000000010000 Version ..........: 2.0 Manufacturer .....: test card Serial number ....: 00000001 Name of cardholder: [not set] Language prefs ...: [not set] Sex ..............: unspecified URL of public key : [not set] Login data .......: [not set] Signature PIN ....: forced Key attributes ...: rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none] gpg/card> admin Admin commands are allowed gpg/card> generate gpg: DBG: chan_4 -> SCD GETATTR SERIALNO gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR KEY-FPR gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR CHV-STATUS gpg: DBG: chan_4 <- S CHV-STATUS +0+127+127+127+3+3+3 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR DISP-NAME gpg: DBG: chan_4 <- S DISP-NAME gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR EXTCAP gpg: DBG: chan_4 <- S EXTCAP gc=1+ki=1+fc=1+pd=0+mcl3=1216+aac=0+sm=2+si=0+dec=0+bt=0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR KEY-ATTR gpg: DBG: chan_4 <- S KEY-ATTR 1 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 2 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 3 1 rsa2048 17 4 gpg: DBG: chan_4 <- OK Make off-card backup of encryption key? (Y/n) Please note that the factory settings of the PINs are PIN = '123456' Admin PIN = '12345678' You should change them using the command --change-pin gpg: DBG: chan_4 -> SCD SETATTR CHV-STATUS-1 %01 gpg: DBG: chan_4 <- INQUIRE PINENTRY_LAUNCHED 1643 gpg: DBG: chan_4 -> END gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD CHECKPIN D2760001240102000000000000010000 gpg: DBG: chan_4 <- INQUIRE PINENTRY_LAUNCHED 1646 gpg: DBG: chan_4 -> END gpg: DBG: chan_4 <- OK Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Testi Testman Email address: a at a.com Comment: You selected this USER-ID: "Testi Testman " Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O gpg: DBG: chan_4 -> SCD GENKEY --timestamp=20160407T071659 --force 1 gpg: DBG: chan_4 <- S KEY-DATA n E9522084E62695179A5A994B65B7C9DB0888DEA61AA863AC2FC620F674ABA7610D1978D7B40EAD0F3C00C284E2588E3A8914794C42F82B5EE43A86B31905F7497DA4F64FED0B93AA8F65E79BDC597EA715B953BB9E595767358D6AB2890A8BDAEE86B3F271A0061524209EA93271ED8848BE02B28949525844B6823FB67FA289963E499079916358952B17A688EDD72B7833047594B5E90AB88CFE14EA39C6B22592D9E5FF70F611781A2C009361471A9F22AB73F69E5E12DD3120A2CB0970DD614F9C70D18226455069D6DD53FB78D08AD47CAA6508A8DF10D8288807C4D4256D55A4BFB2C6C7B60DD9C802A39D6ED2C1B30A62070CBDB11369EEDC4481E483 gpg: DBG: chan_4 <- S KEY-DATA e 010001 gpg: DBG: chan_4 <- S KEY-CREATED-AT 1460013419 gpg: DBG: chan_4 <- S KEY-FPR D897716E922C7C29834F1817D98CCAAB0465A457 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD SERIALNO openpgp gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 0 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> LEARN --sendinfo gpg: DBG: chan_4 <- S PROGRESS learncard k 0 0 gpg: DBG: chan_4 <- S SIG-COUNTER 0 gpg: DBG: chan_4 <- S CHV-STATUS +1+127+127+127+3+3+3 gpg: DBG: chan_4 <- S KEY-TIME 1 1460013419 gpg: DBG: chan_4 <- S KEY-FPR 1 D897716E922C7C29834F1817D98CCAAB0465A457 gpg: DBG: chan_4 <- S DISP-SEX 9 gpg: DBG: chan_4 <- S EXTCAP gc=1+ki=1+fc=1+pd=0+mcl3=1216+aac=0+sm=2+si=0+dec=0+bt=0 gpg: DBG: chan_4 <- S APPTYPE OPENPGP gpg: DBG: chan_4 <- S SERIALNO D2760001240102000000000000010000 0 gpg: DBG: chan_4 <- S READER REINER SCT cyberJack RFID basis 00 00 gpg: DBG: chan_4 <- S KEYPAIRINFO 21679AB1B97650047BAC34B163AA064E63B4DEAF OPENPGP.1 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SCD GETATTR KEY-ATTR gpg: DBG: chan_4 <- S KEY-ATTR 1 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 2 1 rsa2048 17 4 gpg: DBG: chan_4 <- S KEY-ATTR 3 1 rsa2048 17 4 gpg: DBG: chan_4 <- OK gpg: DBG: get_keygrip for public key gpg: DBG: keygrip= 21 67 9A B1 B9 76 50 04 7B AC 34 B1 63 AA 06 4E 63 B4 DE AF gpg: DBG: [not enabled in the source] keydb_new gpg: DBG: [not enabled in the source] keydb_search enter gpg: DBG: keydb_search: 1 search descriptions: gpg: DBG: keydb_search 0: LONG_KID: 'D98CCAAB0465A457' gpg: DBG: keydb: kid_not_found_p (d98ccaab0465a457) => indeterminate gpg: DBG: keydb_search: searching keyring (resource 0 of 1) gpg: DBG: keyring_search: need_uid = 0; need_words = 0; need_keyid = 1; need_fpr = 0; any_skip = 0 gpg: DBG: fd_cache_open (/home/erik/.gnupg/pubring.gpg) not cached gpg: DBG: iobuf-1.0: open '/home/erik/.gnupg/pubring.gpg' desc=file_filter(fd) fd=5 gpg: DBG: keyring_search: initializing offset table. (need_keyid: 1 => 1) gpg: DBG: keyring_search: searching from start of resource. gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=418 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=269 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=261 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: parse_packet(iob=1): type=6 length=418 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 8192 bytes gpg: DBG: parse_packet(iob=1): type=14 length=1037 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=0 (ok), read 2367 bytes gpg: DBG: parse_packet(iob=1): type=6 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=6 gpg: DBG: parse_packet(iob=1): type=14 length=525 (search.keyring.c.1115) gpg: DBG: free_packet() type=14 gpg: DBG: iobuf-1.0: underflow: buffer size: 8192; still buffered: 0 => space for 8192 bytes gpg: DBG: iobuf-1.0: underflow: A->FILTER (8192 bytes) gpg: DBG: iobuf-1.0: A->FILTER() returned rc=-1 (EOF), read 0 bytes gpg: DBG: /home/erik/.gnupg/pubring.gpg: close fd/handle 5 gpg: DBG: fd_cache_close (/home/erik/.gnupg/pubring.gpg) new slot created gpg: DBG: keyring_search: no matches (EOF) gpg: DBG: keydb_search: searched keyring (resource 0 of 1) => EOF gpg: DBG: keydb: kid_not_found_insert (d98ccaab0465a457) gpg: DBG: [not enabled in the source] keydb_search leave (not found) gpg: DBG: iobuf-1.0: close '?' gpg: DBG: chan_4 -> RESET gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SIGKEY 21679AB1B97650047BAC34B163AA064E63B4DEAF gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SETKEYDESC Please+enter+the+passphrase+to+unlock+the+OpenPGP+secret+key:%0A%22[User+ID+not+found]%22%0A2048-bit+RSA+key,+ID+0465A457,%0Acreated+2016-04-07.%0A gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> SETHASH 8 2E0579774217718B235D6DD367B66EF10E838E3F3B4DC9C3E9D103F0AC9F6146 gpg: DBG: chan_4 <- OK gpg: DBG: chan_4 -> PKSIGN gpg: DBG: chan_4 <- ERR 16777224 Falsche Unterschrift gpg: signing failed: Bad signature gpg: make_keysig_packet failed: Bad signature Key generation failed: Bad signature gpg: DBG: free_packet() type=6 gpg: DBG: free_packet() type=13 gpg: DBG: chan_4 -> SCD SETATTR CHV-STATUS-1 %00 gpg: DBG: chan_4 <- OK From gniibe at fsij.org Fri Apr 8 09:02:31 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 08 Apr 2016 16:02:31 +0900 Subject: Curve25519 ECDH encryption issue Message-ID: <57075787.9050307@fsij.org> Hello, It is possible for a person to (manually) craft an encrypted message by Curve25519 ECDH with an ephemeral key V = O. I say "manually", because GnuPG itself never generates such an ephemeral key. The recipient obtains the shared secret by calculating S = rV where (r, R) is the recipient's key pair. Because multiplying O by any scalar value is O, anyone can obtain the shared secret, thus, can decrypt the "encrypted" message. This means that it is possible to craft a looking-like-encrypted-message which should be only decrypted by recipient(s), but actually anyone can decrypt it without the recipient private key. Current implementation dumps core for such a message (because of libgcrypt), but I'm modifying libgcrypt to be compatible to NaCl API now, so it won't dumps core. I think that expected GnuPG behavior in this case is returns an error, not decrypting the message. Is it right? I know that receiving an encrypted message does not necessarily means that the information is classified or it is only the recipient who can access the information (as the sender can do anything). -- From wk at gnupg.org Fri Apr 8 10:31:32 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 08 Apr 2016 10:31:32 +0200 Subject: Curve25519 ECDH encryption issue In-Reply-To: <57075787.9050307@fsij.org> (NIIBE Yutaka's message of "Fri, 08 Apr 2016 16:02:31 +0900") References: <57075787.9050307@fsij.org> Message-ID: <87mvp4mrh7.fsf@wheatstone.g10code.de> On Fri, 8 Apr 2016 09:02, gniibe at fsij.org said: > I think that expected GnuPG behavior in this case is returns an error, > not decrypting the message. Is it right? That is probably the best solution. The other would be to detect the case, decrypt, and print a warning. But that requires a new diagnostic string for a very rare case. Thus I think it is better to return an error like GPG_ERR_BAD_MPI. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From erik.nellessen at informatik.hu-berlin.de Fri Apr 8 17:11:36 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Fri, 8 Apr 2016 15:11:36 +0000 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <57060C21.1030605@informatik.hu-berlin.de> References: <5703F285.5050908@informatik.hu-berlin.de> <57052B42.9080704@informatik.hu-berlin.de> <87wpoavgip.fsf@wheatstone.g10code.de> <57060C21.1030605@informatik.hu-berlin.de> Message-ID: <5707CA28.60309@informatik.hu-berlin.de> By the way, as you can see here https://developers.yubico.com/PGP/ (especially if you read "Importing keys" and "Card edit"), Yubico instructs its users to generate the keys on the PC and import them on the token. Maybe this is for the same reason? I tried their procedure and it also works in my setting. But generating the key on the token would be the saver way and should also be possible, in my opinion. Erik Nellessen: > I just used gpg (GnuPG) 2.1.11 libgcrypt 1.6.5. The error is still the same, but the debug messages are different (actually, you do not see the data in the rsa_verify function anymore, although it still might be different). You can find a log of the whole procedure in the attachment. On the smart card side, the APDUs seem to have stayed the same. > > Kind regards, > Erik > > Werner Koch: >> On Wed, 6 Apr 2016 17:29, erik.nellessen at informatik.hu-berlin.de said: >> >>> Today's system is openSUSE 13.2 (Harlequin) (x86_64) with gpg (GnuPG) >>> 2.0.26 libgcrypt 1.6.1. The debian system was i386, by the way. >> >> Please try to use gnupg 2.1.11 - we have changed a lot of things and it >> is easier for us to comment on this version. >> >> >> Salam-Shalom, >> >> Werner >> > > > > _______________________________________________ > Gnupg-devel mailing list > Gnupg-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gnupg-devel > From ineiev at gnu.org Fri Apr 8 19:47:39 2016 From: ineiev at gnu.org (Ineiev) Date: Fri, 8 Apr 2016 13:47:39 -0400 Subject: [PINENTRY PATCH] tty button-related fixes and refinements Message-ID: <20160408174738.GA26817@gnu.org> Hello, I attach some fixes I've come up with when playing with non-ASCII texts in buttons. The first one simplifies key checking code a little bit; the second one fixes a few bugs in underscore processing; the third one lets the user see the localized message even if the pinentry doesn't support its accelerators (by the way, I think that pinentry should localize the messages that aren't customized from the agent, like "Press any key to continue."); the last one adds a default message to a call of button() so that pinentry won't skip a button when its text is localized. Thank you! -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-tty-Refactor-usage-of-tolower.patch Type: text/x-diff Size: 1993 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-tty-Fix-underscore-processing-in-accelerators.patch Type: text/x-diff Size: 1517 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-tty-Show-supplied-message-when-using-default.patch Type: text/x-diff Size: 2184 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0004-tty-Avoid-using-button-with-NULL-default-text.patch Type: text/x-diff Size: 910 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: Digital signature URL: From dkg at fifthhorseman.net Sat Apr 9 01:37:04 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 08 Apr 2016 20:37:04 -0300 Subject: [Bug 1565963] Re: gpg secret keys not migrated after upgrade to gnupg 2.1 In-Reply-To: <20160408153505.31472.44290.malone@chaenomeles.canonical.com> References: <20160404191913.19100.42552.malonedeb@soybean.canonical.com> <20160408153505.31472.44290.malone@chaenomeles.canonical.com> Message-ID: <87lh4nr7tr.fsf@alice.fifthhorseman.net> Over on https://bugs.launchpad.net/bugs/1565963, Timo Aaltonen has found a repeatable scenario where the secret keyring has not been successfully migrated properly when switching over to gnupg 2.1: On Fri 2016-04-08 12:35:05 -0300, Timo Aaltonen wrote: > :: tjaalton at wilson:~/.gnupg> ls -al > total 1092 > drwx------ 3 tjaalton tjaalton 4096 huhti 8 18:21 . > drwxr-xr-x 42 tjaalton tjaalton 4096 huhti 8 18:25 .. > -rw------- 1 tjaalton tjaalton 8081 maali 20 2015 gpg.conf > -rw-rw-r-- 1 tjaalton tjaalton 0 huhti 8 00:09 .gpg-v21-migrated > drw------- 2 tjaalton tjaalton 4096 maali 20 2015 private-keys-v1.d > -rw------- 1 tjaalton tjaalton 1669 maali 20 2015 public.key > -rw------- 1 tjaalton tjaalton 517605 maali 20 2015 pubring.gpg > -rw------- 1 tjaalton tjaalton 600 maali 17 22:44 random_seed > -rw------- 1 tjaalton tjaalton 7322 maali 20 2015 secring.gpg > srwxrwxr-x 1 tjaalton tjaalton 0 huhti 8 00:37 S.gpg-agent > -rw------- 1 tjaalton tjaalton 4520 maali 20 2015 trustdb.gpg > > don't see anything wrong there It's a little unusual to have ~/.gnupg/private-keys-v1.d not be u+x, as that would imply that the directory isn't listable. This is probably causing problems for the gpg-agent. When i test with this setup, i can verify that the migration doeesn't happen properly, although .gpg-v21-migrated gets created anyway. from a new user account, with gpg1 as 1.4.20 and gpg2 as 2.1.11, i ran the following three commands: gpg1 --gen-key mkdir -m 0600 ~/.gnupg/private-keys-v1.d gpg2 --list-secret-keys The final command returns an error code of 2 and produces these messages to the terminal: gpg: starting migration from earlier GnuPG versions gpg: porting secret keys from '/home/demouser/.gnupg/secring.gpg' to gpg-agent gpg: key C93913FC/C93913FC: error sending to agent: Permission denied gpg: error building skey array: Permission denied gpg: migration succeeded I have no idea how this directory got the u+x bit cleared, but maybe that's something that either: a) gpg-agent could clean up on its own, or b) should cause gpg-agent to not create the .gpg-v21-migrated marker file wdyt? --dkg From wk at gnupg.org Sat Apr 9 11:53:36 2016 From: wk at gnupg.org (Werner Koch) Date: Sat, 09 Apr 2016 11:53:36 +0200 Subject: [Bug 1565963] Re: gpg secret keys not migrated after upgrade to gnupg 2.1 In-Reply-To: <87lh4nr7tr.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Fri, 08 Apr 2016 20:37:04 -0300") References: <20160404191913.19100.42552.malonedeb@soybean.canonical.com> <20160408153505.31472.44290.malone@chaenomeles.canonical.com> <87lh4nr7tr.fsf@alice.fifthhorseman.net> Message-ID: <87a8l3kt0f.fsf@wheatstone.g10code.de> On Sat, 9 Apr 2016 01:37, dkg at fifthhorseman.net said: > It's a little unusual to have ~/.gnupg/private-keys-v1.d not be u+x, as > that would imply that the directory isn't listable. This is probably > causing problems for the gpg-agent. Yes, gpg-agent provide commands to list private keys and we may eventually use that feature to speed up the --list-secret-keys command in certain cases. > I have no idea how this directory got the u+x bit cleared, but maybe > that's something that either: > > a) gpg-agent could clean up on its own, or That is a good idea. ~/.gnupg is anyway a property of GnuPG and thus gpg-agent should be allowed to change the permissions. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Sat Apr 9 20:57:36 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Sat, 09 Apr 2016 14:57:36 -0400 Subject: [Bug 1565963] Re: gpg secret keys not migrated after upgrade to gnupg 2.1 In-Reply-To: <87a8l3kt0f.fsf@wheatstone.g10code.de> References: <20160404191913.19100.42552.malonedeb@soybean.canonical.com> <20160408153505.31472.44290.malone@chaenomeles.canonical.com> <87lh4nr7tr.fsf@alice.fifthhorseman.net> <87a8l3kt0f.fsf@wheatstone.g10code.de> Message-ID: <87potyvcdb.fsf@alice.fifthhorseman.net> On Sat 2016-04-09 05:53:36 -0400, Werner Koch wrote: > On Sat, 9 Apr 2016 01:37, dkg at fifthhorseman.net said: > >> It's a little unusual to have ~/.gnupg/private-keys-v1.d not be u+x, as >> that would imply that the directory isn't listable. This is probably >> causing problems for the gpg-agent. > > Yes, gpg-agent provide commands to list private keys and we may > eventually use that feature to speed up the --list-secret-keys command > in certain cases. Makes sense. At any rate, the lack of u+x appears to make gpg-agent fail to do the initial key import. >> I have no idea how this directory got the u+x bit cleared, but maybe >> that's something that either: >> >> a) gpg-agent could clean up on its own, or > > That is a good idea. ~/.gnupg is anyway a property of GnuPG and thus > gpg-agent should be allowed to change the permissions. Shall i open an issue in https://bugs.gnupg.org/ about this? --dkg From wk at gnupg.org Sun Apr 10 14:39:48 2016 From: wk at gnupg.org (Werner Koch) Date: Sun, 10 Apr 2016 14:39:48 +0200 Subject: [Bug 1565963] Re: gpg secret keys not migrated after upgrade to gnupg 2.1 In-Reply-To: <87potyvcdb.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Sat, 09 Apr 2016 14:57:36 -0400") References: <20160404191913.19100.42552.malonedeb@soybean.canonical.com> <20160408153505.31472.44290.malone@chaenomeles.canonical.com> <87lh4nr7tr.fsf@alice.fifthhorseman.net> <87a8l3kt0f.fsf@wheatstone.g10code.de> <87potyvcdb.fsf@alice.fifthhorseman.net> Message-ID: <87lh4lk57v.fsf@wheatstone.g10code.de> On Sat, 9 Apr 2016 20:57, dkg at fifthhorseman.net said: > Shall i open an issue in https://bugs.gnupg.org/ about this? better do that. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Mon Apr 11 15:40:03 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 11 Apr 2016 22:40:03 +0900 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <5703F285.5050908@informatik.hu-berlin.de> References: <5703F285.5050908@informatik.hu-berlin.de> Message-ID: <570BA933.3050002@fsij.org> On 04/06/2016 02:14 AM, Erik Nellessen wrote: > Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 This is strange. I think that this is the cause of your problem. It should be: 002A9E9A20265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 I mean, scdaemon removes the prefix (which specifies the hash algo) 3031300D060960864801650304020105000420 before sending card. What version of scdaemon are you using? -- From philip.colmer at linaro.org Mon Apr 11 15:59:48 2016 From: philip.colmer at linaro.org (Philip Colmer) Date: Mon, 11 Apr 2016 14:59:48 +0100 Subject: Using LDAP keyservers with gpg 2.1 Message-ID: I've configured our LDAP server to act as a keyserver for use with GnuPG. In testing, with version 1.x and 2.0, sending keys to the keyserver works. However, with version 2.1.11, it isn't working. Part of the challenge seems to be how to specify authentication information in gpg 2.1 but I've also tried temporarily changing the permissions on our LDAP server so that anyone can write to the appropriate OU and it still fails: gpg: sending key DC6F3C29 to ldaps://login.linaro.org gpg: DBG: chan_3 -> KS_PUT gpg: DBG: chan_3 <- INQUIRE KEYBLOCK gpg: DBG: chan_3 -> [ 44 20 99 01 25 30 44 04 56 fe 8f d2 01 08 00 c2 ...(982 byte(s) skipped) ] gpg: DBG: chan_3 -> [ 44 20 20 4f ad 28 53 1c 95 8a ae 0f 57 5f 35 fc ...(231 byte(s) skipped) ] gpg: DBG: chan_3 -> END gpg: DBG: chan_3 <- INQUIRE KEYBLOCK_INFO gpg: DBG: chan_3 -> D pub:e:2048:1:4625A9B1DC6F3C29:1459523538:1460128338::::::::::%0Auid:::::1459523538::::Philip Colmer :::::::%0Asig::::4625A9B1DC6F3C29:1459523538:::::::::::%0Asub:e:2048:1:87E613C66F047E92:1459523538:1460128338::::::::::%0A gpg: DBG: chan_3 -> END gpg: DBG: chan_3 <- ERR 767 Cannot contact LDAP server This is with the gpg configuration set to guru debug level. How can I debug this further, please? I suspect that the actual error is getting buried somewhere, unfortunately. Regards Philip From aheinecke at intevation.de Mon Apr 11 19:17:49 2016 From: aheinecke at intevation.de (Andre Heinecke) Date: Mon, 11 Apr 2016 19:17:49 +0200 Subject: GpgME C++ / Qt language providers ready for merge? Message-ID: <2630330.71C78IVE5L@esus> Hi, I've integrated the C++ and Qt Libraries for GpgME from the KDE Initiative as language provider into GpgME in the branch "gpgmepp". I think that branch is now ready for a merge into master. Build can be controlled by the --enable-languages configure option. So --enable-languages=no Will build only the C library. GpgMEpp is a C++ wrapper / binding around GpgME closely follows the API of GpgME itself. (Requires C++11) QGpgME is more of a "Qt library" to work with GpgMEpp then a binding. Has a Job based Qt API that takes Qt data structures as gpgme data type providers. (Requires Qt5 and GpgMEpp) The API is mostly compatible with KF5GpgMEpp and KF5QGpgME which was released as part of KDE-Applications. Small changes might be caused by the removal of boost classes from public API as I've ported both libraries away from boost to c++11. My current plan is to no longer release KF5GpgMEpp with KDE-Applications 16.08 and depend on the libraries from GpgME for that release. Regards, Andre -- Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/ Intevation GmbH, Neuer Graben 17, 49074 Osnabr?ck | AG Osnabr?ck, HR B 18998 Gesch?ftsf?hrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 648 bytes Desc: This is a digitally signed message part. URL: From dkg at fifthhorseman.net Mon Apr 11 22:05:37 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 11 Apr 2016 16:05:37 -0400 Subject: GpgME C++ / Qt language providers ready for merge? In-Reply-To: <2630330.71C78IVE5L@esus> References: <2630330.71C78IVE5L@esus> Message-ID: <87wpo3ud0u.fsf@alice.fifthhorseman.net> On Mon 2016-04-11 13:17:49 -0400, Andre Heinecke wrote: > I've integrated the C++ and Qt Libraries for GpgME from the KDE Initiative as > language provider into GpgME in the branch "gpgmepp". > > I think that branch is now ready for a merge into master. > > Build can be controlled by the --enable-languages configure option. So > > --enable-languages=no > > Will build only the C library. > > GpgMEpp is a C++ wrapper / binding around GpgME closely follows the API of > GpgME itself. (Requires C++11) > > QGpgME is more of a "Qt library" to work with GpgMEpp then a binding. Has a > Job based Qt API that takes Qt data structures as gpgme data type providers. > (Requires Qt5 and GpgMEpp) > > The API is mostly compatible with KF5GpgMEpp and KF5QGpgME which > was released as part of KDE-Applications. Small changes might be caused by the > removal of boost classes from public API as I've ported both libraries away > from boost to c++11. > > My current plan is to no longer release KF5GpgMEpp with KDE-Applications 16.08 > and depend on the libraries from GpgME for that release. looks reasonable to me. I'm assuming that in debian, we'd have the gpgme1.0 package (maintained by pkg-gnupg-maint) take over the binary packages from the gpgmepp souce package (maintained by the Debian Qt/KDE maintainers). I've cc'ed both groups on this e-mail so that people are aware of the situation. --dkg From dkg at fifthhorseman.net Tue Apr 12 01:05:10 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 11 Apr 2016 19:05:10 -0400 Subject: [Bug 1565963] Re: gpg secret keys not migrated after upgrade to gnupg 2.1 In-Reply-To: <87lh4lk57v.fsf@wheatstone.g10code.de> References: <20160404191913.19100.42552.malonedeb@soybean.canonical.com> <20160408153505.31472.44290.malone@chaenomeles.canonical.com> <87lh4nr7tr.fsf@alice.fifthhorseman.net> <87a8l3kt0f.fsf@wheatstone.g10code.de> <87potyvcdb.fsf@alice.fifthhorseman.net> <87lh4lk57v.fsf@wheatstone.g10code.de> Message-ID: <87bn5fu4pl.fsf@alice.fifthhorseman.net> On Sun 2016-04-10 08:39:48 -0400, Werner Koch wrote: > On Sat, 9 Apr 2016 20:57, dkg at fifthhorseman.net said: > >> Shall i open an issue in https://bugs.gnupg.org/ about this? > > better do that. ok, i've created this: https://bugs.gnupg.org/gnupg/issue2312 Thanks for the followup, Werner. --dkg From dkg at fifthhorseman.net Tue Apr 12 04:10:55 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 11 Apr 2016 22:10:55 -0400 Subject: Detection of a revocation certificate prior to import In-Reply-To: References: Message-ID: <871t6bshjk.fsf@alice.fifthhorseman.net> On Sat 2016-04-02 05:16:42 -0400, Ludwig H?gelsch?fer wrote: > is it possible to identify a revocation certificate prior to import? > > - --list-packets does not seem to be very specific. > > We want to do this in Enigmail prior to import providing a preview. i don't know of any way to do this in gpg directly :/ I do note that GnuPG 2.1 automatically creates the revocation certificates (in ~/.gnupg/openpgp-revocs.d) as files named *.rev. But they're stored in ascii-armored form, with "-----BEGIN PGP PUBLIC KEY BLOCK-----" headers :/ --dkg From gniibe at fsij.org Tue Apr 12 05:21:31 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 12 Apr 2016 12:21:31 +0900 Subject: Curve25519 ECDH encryption issue In-Reply-To: <87mvp4mrh7.fsf@wheatstone.g10code.de> References: <57075787.9050307@fsij.org> <87mvp4mrh7.fsf@wheatstone.g10code.de> Message-ID: <570C69BB.3090007@fsij.org> On 04/08/2016 05:31 PM, Werner Koch wrote: > On Fri, 8 Apr 2016 09:02, gniibe at fsij.org said: > >> I think that expected GnuPG behavior in this case is returns an error, >> not decrypting the message. Is it right? > > That is probably the best solution. The other would be to detect the > case, decrypt, and print a warning. But that requires a new diagnostic > string for a very rare case. Thus I think it is better to return an > error like GPG_ERR_BAD_MPI. OK, we agree that it raises an error. Then, the question is which should do, GnuPG or libgcrypt? If it's GnuPG, it will be something like following; It's not yet final version (as we need to implement recognizing ECC ECDH and handling of detection of all zero accurately duplicating _gcry_ecc_mont_decodepoint in libgcrypt). In the mail of mine to libgcrypt, I said once it should be GnuPG to validate the input (to be compatible to the implementation which uses NaCl's API). However, writing the code below, I'm inclined to have different opinion now. I think that it's better for libgcrypt to raise the error. diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 8c09b8c..ad8d8c2 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -77,6 +77,36 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, goto leave; } + /* + * Input validation for X25519 ECDH. + */ + if (agent_is_cv25519_key (s_skey)) + { + gcry_sexp_t data_e = NULL; + int i; + + rc = sexp_extract_param (s_cipher, NULL, "e", &data_e, NULL); + if (rc) + goto leave; + rc = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buf, &len, data_e); + if (rc) + goto leave; + + /* Check if it's all zero. */ + if (buf[0] == 0x40 && len == 33) + for (i = 0; i < 32; i++) + if (buf[i+1] != 0) + break; + + xfree (buf); + buf = NULL; + if (i == 33) + { /* Return error when it's all zero. */ + rc = gpg_error (GPG_ERR_INV_DATA); + goto leave; + } + } + if (shadow_info) { /* divert operation to the smartcard */ -- From patrick at enigmail.net Tue Apr 12 08:24:04 2016 From: patrick at enigmail.net (Patrick Brunschwig) Date: Tue, 12 Apr 2016 08:24:04 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: <871t6bshjk.fsf@alice.fifthhorseman.net> References: <871t6bshjk.fsf@alice.fifthhorseman.net> Message-ID: <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> On 12.04.16 04:10, Daniel Kahn Gillmor wrote: > On Sat 2016-04-02 05:16:42 -0400, Ludwig H?gelsch?fer wrote: >> is it possible to identify a revocation certificate prior to import? >> >> - --list-packets does not seem to be very specific. >> >> We want to do this in Enigmail prior to import providing a preview. > > i don't know of any way to do this in gpg directly :/ I do note that > GnuPG 2.1 automatically creates the revocation certificates (in > ~/.gnupg/openpgp-revocs.d) as files named *.rev. But they're stored in > ascii-armored form, with "-----BEGIN PGP PUBLIC KEY BLOCK-----" headers Using --list-packets works for me: a revocation certificate contains a single signature packet with a specific signature class (0x20 = revocation cert). If it comes alone, it is a certificate that can be used to revoke a key; if it is part of a key, the key is revoked. -Patrick From wk at gnupg.org Tue Apr 12 14:42:16 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 12 Apr 2016 14:42:16 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> (Patrick Brunschwig's message of "Tue, 12 Apr 2016 08:24:04 +0200") References: <871t6bshjk.fsf@alice.fifthhorseman.net> <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> Message-ID: <87vb3ngfrr.fsf@wheatstone.g10code.de> On Tue, 12 Apr 2016 08:24, patrick at enigmail.net said: > Using --list-packets works for me: Do not use --list-packets to autmate tasks! That command has no well defined semantics and should thus not be used by any tools. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Apr 12 14:46:55 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 12 Apr 2016 14:46:55 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: ("Ludwig =?utf-8?Q?H=C3=BCgelsch=C3=A4fer=22's?= message of "Sat, 2 Apr 2016 11:16:42 +0200") References: Message-ID: <87r3ebgfk0.fsf@wheatstone.g10code.de> On Sat, 2 Apr 2016 11:16, ludwig at enigmail.net said: > is it possible to identify a revocation certificate prior to import? No. If there is a revocation certificate availabale it needs to be applied ASAP. If you refresh a key a revocation certificate would be imported anyway. If you want to protect against accidental import you may do what GnuPG does: --8<---------------cut here---------------start------------->8--- To avoid an accidental use of this file, a colon has been inserted before the 5 dashes below. Remove this colon with a text editor before importing and publishing this revocation certificate. :-----BEGIN PGP PUBLIC KEY BLOCK----- --8<---------------cut here---------------end--------------->8--- Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Tue Apr 12 16:21:56 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 12 Apr 2016 23:21:56 +0900 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <570BA933.3050002@fsij.org> References: <5703F285.5050908@informatik.hu-berlin.de> <570BA933.3050002@fsij.org> Message-ID: <570D0484.3050808@fsij.org> On 04/11/2016 10:40 PM, NIIBE Yutaka wrote: > On 04/06/2016 02:14 AM, Erik Nellessen wrote: >> Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 > > This is strange. I think that this is the cause of your problem. > It should be: > > 002A9E9A20265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 > > I mean, scdaemon removes the prefix (which specifies the hash algo) > > 3031300D060960864801650304020105000420 > > before sending card. Sorry, I was wrong. The APDU is correct (the prefix is removed and added again in the code scd/app-openpgp.c). I didn't read the code of adding the prefix again, and misunderstood. I think that your OpenPGPcard implementation does some mistake for the calculation of length of padding string. For 2048-bit RSA, the length of octet is 256 (N=256). I checked OpenPGPcard specification. It says (in 7.2.8 PSO: COMPUTE DIGITAL SIGNATURE): The DSI format for RSA: According to PKCS #1 the DSI is generated internally by the card and has the following structure: Description Length Value ---------------------------------------- Start byte 1 00 Block type 1 01 Padding string (PS) N-3-L FF...FF Separator 1 00 Data field L Digestinfo ---------------------------------------- With SHA256 hash, L=19+32=51. So, the length of PS should be 202 (= 256 - 3 - 51). It seems that it was computed as the length of PS=8 by the applet. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: OpenPGP digital signature URL: From dkg at fifthhorseman.net Tue Apr 12 16:38:39 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Tue, 12 Apr 2016 10:38:39 -0400 Subject: Detection of a revocation certificate prior to import In-Reply-To: <87vb3ngfrr.fsf@wheatstone.g10code.de> References: <871t6bshjk.fsf@alice.fifthhorseman.net> <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> <87vb3ngfrr.fsf@wheatstone.g10code.de> Message-ID: <87bn5erixc.fsf@alice.fifthhorseman.net> On Tue 2016-04-12 08:42:16 -0400, Werner Koch wrote: > On Tue, 12 Apr 2016 08:24, patrick at enigmail.net said: > >> Using --list-packets works for me: > > Do not use --list-packets to autmate tasks! That command has no well > defined semantics and should thus not be used by any tools. In that case, we could really use an automatable feature that permits this kind of inspection. Saying "if a revocation certificate exists, it should be imported" doesn't account for the use case that Patrick is aiming for: the user is importing things and considering what to do with them. We want to actively encourage people to generate and store revocation certificates, and we should make the workflow (both for generating them and for consuming them) as user-friendly as possible. This means not everyone will understand about removing the leading colon from a text file, and we want to encourage GUI tools (like enigmail) from being able to detect them; to explain to the user what the consequences will be if they import them; to encourage publication to the keyservers; etc... --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 948 bytes Desc: not available URL: From erik.nellessen at informatik.hu-berlin.de Tue Apr 12 18:09:41 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Tue, 12 Apr 2016 16:09:41 +0000 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <570D0484.3050808@fsij.org> References: <5703F285.5050908@informatik.hu-berlin.de> <570BA933.3050002@fsij.org> <570D0484.3050808@fsij.org> Message-ID: <570D1DC5.3050400@informatik.hu-berlin.de> You are right, the applet does not compute the signature as described in the specification. Maybe the cause of the problem is, that the environment on my android smartphone behaves differently than on a real Java Card when creating the PKCS1 padding. The question is, if the padding creation in the smartphone environment is not correct according to PKCS1. It could also be, that PKCS1 does not prescribe padding to the full key length and both paddings are correct according to PKCS1. In any case, I will raise the question in jCardSim, which provides the RSA interfaces on the smartphone. For now, thank you very much! Erik NIIBE Yutaka: > On 04/11/2016 10:40 PM, NIIBE Yutaka wrote: >> On 04/06/2016 02:14 AM, Erik Nellessen wrote: >>> Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 >> >> This is strange. I think that this is the cause of your problem. >> It should be: >> >> 002A9E9A20265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 >> >> I mean, scdaemon removes the prefix (which specifies the hash algo) >> >> 3031300D060960864801650304020105000420 >> >> before sending card. > > Sorry, I was wrong. The APDU is correct (the prefix is removed and > added again in the code scd/app-openpgp.c). I didn't read the code > of adding the prefix again, and misunderstood. > > > I think that your OpenPGPcard implementation does some mistake for the > calculation of length of padding string. > > For 2048-bit RSA, the length of octet is 256 (N=256). I checked > OpenPGPcard specification. It says (in 7.2.8 PSO: COMPUTE DIGITAL > SIGNATURE): > > The DSI format for RSA: > According to PKCS #1 the DSI is generated internally by the card > and has the following structure: > > Description Length Value > ---------------------------------------- > Start byte 1 00 > Block type 1 01 > Padding string (PS) N-3-L FF...FF > Separator 1 00 > Data field L Digestinfo > ---------------------------------------- > > With SHA256 hash, L=19+32=51. So, the length of PS should be 202 > (= 256 - 3 - 51). > > It seems that it was computed as the length of PS=8 by the applet. > > > > _______________________________________________ > Gnupg-devel mailing list > Gnupg-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gnupg-devel > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: OpenPGP digital signature URL: From patrick at enigmail.net Wed Apr 13 08:11:36 2016 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 13 Apr 2016 08:11:36 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: <87bn5erixc.fsf@alice.fifthhorseman.net> References: <871t6bshjk.fsf@alice.fifthhorseman.net> <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> <87vb3ngfrr.fsf@wheatstone.g10code.de> <87bn5erixc.fsf@alice.fifthhorseman.net> Message-ID: <9e60a95c-4025-c02e-91b2-e58f6301c0d1@enigmail.net> On 12.04.16 16:38, Daniel Kahn Gillmor wrote: > On Tue 2016-04-12 08:42:16 -0400, Werner Koch wrote: >> On Tue, 12 Apr 2016 08:24, patrick at enigmail.net said: >> >>> Using --list-packets works for me: >> >> Do not use --list-packets to autmate tasks! That command has no well >> defined semantics and should thus not be used by any tools. > > In that case, we could really use an automatable feature that permits > this kind of inspection. > > Saying "if a revocation certificate exists, it should be imported" > doesn't account for the use case that Patrick is aiming for: the user is > importing things and considering what to do with them. > > We want to actively encourage people to generate and store revocation > certificates, and we should make the workflow (both for generating them > and for consuming them) as user-friendly as possible. This means not > everyone will understand about removing the leading colon from a text > file, and we want to encourage GUI tools (like enigmail) from being able > to detect them; to explain to the user what the consequences will be if > they import them; to encourage publication to the keyservers; etc... ... or in other words, if we should not use --list-packets, how else can we detect a revocation certificate? -Patrick From wk at gnupg.org Wed Apr 13 09:30:27 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 13 Apr 2016 09:30:27 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: <9e60a95c-4025-c02e-91b2-e58f6301c0d1@enigmail.net> (Patrick Brunschwig's message of "Wed, 13 Apr 2016 08:11:36 +0200") References: <871t6bshjk.fsf@alice.fifthhorseman.net> <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> <87vb3ngfrr.fsf@wheatstone.g10code.de> <87bn5erixc.fsf@alice.fifthhorseman.net> <9e60a95c-4025-c02e-91b2-e58f6301c0d1@enigmail.net> Message-ID: <87shyqc6ek.fsf@wheatstone.g10code.de> On Wed, 13 Apr 2016 08:11, patrick at enigmail.net said: > ... or in other words, if we should not use --list-packets, how else can > we detect a revocation certificate? The question is why you want to do this? Do you want to filter signatures you are merging into a key? I can understand that there might be a need to avoid key-signatures which play havoc with ones key (Use a keyserver to list on my key) but I can't see a reason not to merge a self-signature. You should consider an OpenPGP key a distributed object with the technical need for regular syncing. Or do you want to avoid accidental merging of a pre-created revocation certificate? In this case I described a way to avoid this. If that is not sufficient, I we can make the --dry-run option work for --import so that you get only the stats. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Wed Apr 13 14:52:10 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Wed, 13 Apr 2016 08:52:10 -0400 Subject: GpgME C++ / Qt language providers ready for merge? In-Reply-To: <1852889.YS60DxvzeD@tuxin> References: <2630330.71C78IVE5L@esus> <87wpo3ud0u.fsf@alice.fifthhorseman.net> <1852889.YS60DxvzeD@tuxin> Message-ID: <87d1ptacxx.fsf@alice.fifthhorseman.net> On Wed 2016-04-13 08:18:44 -0400, Sandro Knau? wrote: >> looks reasonable to me. I'm assuming that in debian, we'd have the >> gpgme1.0 package (maintained by pkg-gnupg-maint) take over the binary >> packages from the gpgmepp souce package (maintained by the Debian Qt/KDE >> maintainers). I've cc'ed both groups on this e-mail so that people are >> aware of the situation. > > Ah, this information is already spreading around :D That is good. Yes, Debian > Qt/KDE maintainers would have to remove KF5GpgMEpp. But if I see it correcly > we won't need to react directly and can wait till all application are switched > over to gpgmepp. We should make sure, that both can be install in paralell. > But this should be possible, because we have different namespaces. yep, i think we'll be able to do that with pretty loose coordination, just wanted to be sure it's visible to everyone involved. If upstream is going to make this change, i'd hope that it's sooner rather than later, so that we can get the transition into debian and well-settled before any sort of freeze next year. > PS: debian-qt-kde - is mostly a list, that is spammed by the bugs > pkg-kde-talk - is more the talk list about general topics like this one thanks for the redirection :) --dkg From patrick at enigmail.net Wed Apr 13 17:23:55 2016 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 13 Apr 2016 17:23:55 +0200 Subject: Detection of a revocation certificate prior to import In-Reply-To: <87shyqc6ek.fsf@wheatstone.g10code.de> References: <871t6bshjk.fsf@alice.fifthhorseman.net> <715ac206-a7fc-3429-423e-7cc09c408c34@enigmail.net> <87vb3ngfrr.fsf@wheatstone.g10code.de> <87bn5erixc.fsf@alice.fifthhorseman.net> <9e60a95c-4025-c02e-91b2-e58f6301c0d1@enigmail.net> <87shyqc6ek.fsf@wheatstone.g10code.de> Message-ID: On 13.04.16 09:30, Werner Koch wrote: > On Wed, 13 Apr 2016 08:11, patrick at enigmail.net said: > >> ... or in other words, if we should not use --list-packets, how else can >> we detect a revocation certificate? > > The question is why you want to do this? Do you want to filter > signatures you are merging into a key? I can understand that there > might be a need to avoid key-signatures which play havoc with ones key > (Use a keyserver to list on my key) but I can't see a reason not to > merge a self-signature. You should consider an OpenPGP key a > distributed object with the technical need for regular syncing. > > Or do you want to avoid accidental merging of a pre-created revocation > certificate? In this case I described a way to avoid this. If that is > not sufficient, I we can make the --dry-run option work for --import so > that you get only the stats. Enigmail displays a dialog to the user *before* the keys are imported to allow the user to determine what he is about to import. In case the user is about to import a revocation certificate, we display a message like "you are about to import a revocation certificate for key X. Are you sure you want to proceed?". This is particularly useful if you are accidentally about to import a revocation cert for your own key. The problem with your workaround is that a) it's not guaranteed that everybody uses this method b) it does not help if you want to know which key is concerned -Patrick From erik.nellessen at informatik.hu-berlin.de Thu Apr 14 15:33:43 2016 From: erik.nellessen at informatik.hu-berlin.de (Erik Nellessen) Date: Thu, 14 Apr 2016 15:33:43 +0200 Subject: Bad signature when generating key in OpenPGP Java Card Applet In-Reply-To: <570D1DC5.3050400@informatik.hu-berlin.de> References: <5703F285.5050908@informatik.hu-berlin.de> <570BA933.3050002@fsij.org> <570D0484.3050808@fsij.org> <570D1DC5.3050400@informatik.hu-berlin.de> Message-ID: <570F9C37.5000602@informatik.hu-berlin.de> The problem really was in jCardSim. I created an issue here: https://github.com/licel/jcardsim/issues/82 They fixed the bug and I was able to generate the key on the card. Thank you very much for your help! Erik Erik Nellessen: > You are right, the applet does not compute the signature as described in the specification. > > Maybe the cause of the problem is, that the environment on my android smartphone behaves differently than on a real Java Card when creating the PKCS1 padding. The question is, if the padding creation in the smartphone environment is not correct according to PKCS1. It could also be, that PKCS1 does not prescribe padding to the full key length and both paddings are correct according to PKCS1. > > In any case, I will raise the question in jCardSim, which provides the RSA interfaces on the smartphone. > > For now, thank you very much! > > Erik > > NIIBE Yutaka: >> On 04/11/2016 10:40 PM, NIIBE Yutaka wrote: >>> On 04/06/2016 02:14 AM, Erik Nellessen wrote: >>>> Received APDU (57 bytes): 002A9E9A333031300D060960864801650304020105000420265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 >>> >>> This is strange. I think that this is the cause of your problem. >>> It should be: >>> >>> 002A9E9A20265A93D234241BD20BF0773B6011FD037CBE8B985D487116DC08E6914F38DBD100 >>> >>> I mean, scdaemon removes the prefix (which specifies the hash algo) >>> >>> 3031300D060960864801650304020105000420 >>> >>> before sending card. >> >> Sorry, I was wrong. The APDU is correct (the prefix is removed and >> added again in the code scd/app-openpgp.c). I didn't read the code >> of adding the prefix again, and misunderstood. >> >> >> I think that your OpenPGPcard implementation does some mistake for the >> calculation of length of padding string. >> >> For 2048-bit RSA, the length of octet is 256 (N=256). I checked >> OpenPGPcard specification. It says (in 7.2.8 PSO: COMPUTE DIGITAL >> SIGNATURE): >> >> The DSI format for RSA: >> According to PKCS #1 the DSI is generated internally by the card >> and has the following structure: >> >> Description Length Value >> ---------------------------------------- >> Start byte 1 00 >> Block type 1 01 >> Padding string (PS) N-3-L FF...FF >> Separator 1 00 >> Data field L Digestinfo >> ---------------------------------------- >> >> With SHA256 hash, L=19+32=51. So, the length of PS should be 202 >> (= 256 - 3 - 51). >> >> It seems that it was computed as the length of PS=8 by the applet. >> >> >> >> _______________________________________________ >> Gnupg-devel mailing list >> Gnupg-devel at gnupg.org >> http://lists.gnupg.org/mailman/listinfo/gnupg-devel >> > > > > > _______________________________________________ > Gnupg-devel mailing list > Gnupg-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gnupg-devel > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: OpenPGP digital signature URL: From justus at g10code.com Thu Apr 14 16:41:10 2016 From: justus at g10code.com (Justus Winter) Date: Thu, 14 Apr 2016 16:41:10 +0200 Subject: [PATCH 1/3] agent: Update key format document. Message-ID: <1460644872-8729-1-git-send-email-justus@g10code.com> * agent/keyformat.txt: Drop obsolete paragraph. Signed-off-by: Justus Winter --- agent/keyformat.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 42c4b1f..04bc6ed 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -43,23 +43,6 @@ optional but required for some operations to calculate the fingerprint of the key. This timestamp should be a string with the number of seconds since Epoch or an ISO time string (yyyymmddThhmmss). -Actually this form should not be used for regular purposes and only -accepted by gpg-agent with the configuration option: ---allow-non-canonical-key-format. The regular way to represent the -keys is in canonical representation[3]: - -(private-key - (rsa - (n #00e0ce9..[some bytes not shown]..51#) - (e #010001#) - (d #046129F..[some bytes not shown]..81#) - (p #00e861b..[some bytes not shown]..f1#) - (q #00f7a7c..[some bytes not shown]..61#) - (u #304559a..[some bytes not shown]..9b#) - ) - (uri http://foo.bar x-foo:whatever_you_want) -) - Protected Private Key Format ============================== -- 2.1.4 From justus at g10code.com Thu Apr 14 16:41:11 2016 From: justus at g10code.com (Justus Winter) Date: Thu, 14 Apr 2016 16:41:11 +0200 Subject: [PATCH 2/3] agent: Convert key format document to org. In-Reply-To: <1460644872-8729-1-git-send-email-justus@g10code.com> References: <1460644872-8729-1-git-send-email-justus@g10code.com> Message-ID: <1460644872-8729-2-git-send-email-justus@g10code.com> * agent/keyformat.txt: Convert to org mode. Signed-off-by: Justus Winter --- agent/keyformat.txt | 76 ++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 04bc6ed..9c91336 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -1,11 +1,11 @@ -keyformat.txt (wk 2001-12-18) ------------------------------ +keyformat.txt emacs, please switch to -*- org -*- mode +------------- Some notes on the format of the secret keys used with gpg-agent. -Location of keys -================ +* Location of keys + The secret keys[1] are stored on a per file basis in a directory below the ~/.gnupg home directory. This directory is named @@ -16,9 +16,8 @@ and should have permissions 700. The secret keys are stored in files with a name matching the hexadecimal representation of the keygrip[2] and suffixed with ".key". +* Unprotected Private Key Format -Unprotected Private Key Format -============================== The content of the file is an S-Expression like the ones used with Libgcrypt. Here is an example of an unprotected file: @@ -43,9 +42,8 @@ optional but required for some operations to calculate the fingerprint of the key. This timestamp should be a string with the number of seconds since Epoch or an ISO time string (yyyymmddThhmmss). +* Protected Private Key Format -Protected Private Key Format -============================== A protected key is like this: (protected-private-key @@ -69,7 +67,7 @@ optional; the isotimestamp is 15 bytes long (e.g. "19610711T172000"). The currently defined protection modes are: -1. openpgp-s2k3-sha1-aes-cbc +** openpgp-s2k3-sha1-aes-cbc This describes an algorithm using using AES in CBC mode for encryption, SHA-1 for integrity protection and the String to Key @@ -118,7 +116,7 @@ The currently defined protection modes are: the stored one - If they don't match the integrity of the key is not given. -2. openpgp-native +** openpgp-native This is a wrapper around the OpenPGP Private Key Transport format which resembles the standard OpenPGP format and allows the use of an @@ -155,10 +153,8 @@ The currently defined protection modes are: (uri http://foo.bar x-foo:whatever_you_want) (comment whatever)) +* Shadowed Private Key Format - -Shadowed Private Key Format -============================ To keep track of keys stored on IC cards we use a third format for private kyes which are called shadow keys as they are only a reference to keys stored on a token: @@ -185,9 +181,7 @@ readers don't allow passing a variable length PIN. More items may be added to the list. - -OpenPGP Private Key Transfer Format -=================================== +* OpenPGP Private Key Transfer Format This format is used to transfer keys between gpg and gpg-agent. @@ -200,28 +194,26 @@ This format is used to transfer keys between gpg and gpg-agent. (protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)) -* V is the packet version number (3 or 4). -* PUBKEYALGO is a Libgcrypt algo name -* CURVENAME is the name of the curve - only used with ECC. -* P1 .. PN are the parameters; the public parameters are never encrypted - the secrect key parameters are encrypted if the "protection" list is - given. To make this more explicit each parameter is preceded by a - flag "_" for cleartext or "e" for encrypted text. -* CSUM is the deprecated 16 bit checksum as defined by OpenPGP. This - is an optional element. -* If PROTTYPE is "sha1" the new style SHA1 checksum is used if it is "sum" - the old 16 bit checksum (above) is used and if it is "none" no - protection at all is used. -* PROTALGO is a Libgcrypt style cipher algorithm name -* IV is the initialization verctor. -* S2KMODE is the value from RFC-4880. -* S2KHASH is a a libgcrypt style hash algorithm identifier. -* S2KSALT is the 8 byte salt -* S2KCOUNT is the count value from RFC-4880. - - -Persistent Passphrase Format -============================ + * V is the packet version number (3 or 4). + * PUBKEYALGO is a Libgcrypt algo name + * CURVENAME is the name of the curve - only used with ECC. + * P1 .. PN are the parameters; the public parameters are never encrypted + the secrect key parameters are encrypted if the "protection" list is + given. To make this more explicit each parameter is preceded by a + flag "_" for cleartext or "e" for encrypted text. + * CSUM is the deprecated 16 bit checksum as defined by OpenPGP. This + is an optional element. + * If PROTTYPE is "sha1" the new style SHA1 checksum is used if it is "sum" + the old 16 bit checksum (above) is used and if it is "none" no + protection at all is used. + * PROTALGO is a Libgcrypt style cipher algorithm name + * IV is the initialization verctor. + * S2KMODE is the value from RFC-4880. + * S2KHASH is a a libgcrypt style hash algorithm identifier. + * S2KSALT is the 8 byte salt + * S2KCOUNT is the count value from RFC-4880. + +* Persistent Passphrase Format To allow persistent storage of cached passphrases we use a scheme similar to the private-key storage format. This is a master @@ -314,14 +306,8 @@ hashed: (protected-at "20100915T111722") ) +* Notes - - - - - -Notes: -====== [1] I usually use the terms private and secret key exchangeable but prefer the term secret key because it can be visually be better distinguished from the term public key. -- 2.1.4 From justus at g10code.com Thu Apr 14 16:41:12 2016 From: justus at g10code.com (Justus Winter) Date: Thu, 14 Apr 2016 16:41:12 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <1460644872-8729-1-git-send-email-justus@g10code.com> References: <1460644872-8729-1-git-send-email-justus@g10code.com> Message-ID: <1460644872-8729-3-git-send-email-justus@g10code.com> * agent/findkey.c (write_extended_private_key): New function. (agent_write_private_key): Detect if an existing file is in extended format and update the key within if it is. (read_key_file): Handle the new format. * agent/keyformat.txt: Document the new format. * common/Makefile.am: Add the new files. * common/private-keys.c: New file. * common/private-keys.h: Likewise. * common/t-private-keys.c: Likewise. * common/util.h (alphap, alnump): New macros. -- GnuPG 2.3+ will use a new format to store private keys that is both more flexible and easier to read and edit by human beings. The new format stores name,value-pairs using the common mail and http header convention. This patch adds the parser and support code and prepares GnuPG 2.1 for the new format. Signed-off-by: Justus Winter --- agent/findkey.c | 161 +++++++++++- agent/keyformat.txt | 78 +++++- common/Makefile.am | 7 +- common/private-keys.c | 666 ++++++++++++++++++++++++++++++++++++++++++++++++ common/private-keys.h | 99 +++++++ common/t-private-keys.c | 543 +++++++++++++++++++++++++++++++++++++++ common/util.h | 3 + 7 files changed, 1547 insertions(+), 10 deletions(-) create mode 100644 common/private-keys.c create mode 100644 common/private-keys.h create mode 100644 common/t-private-keys.c diff --git a/agent/findkey.c b/agent/findkey.c index 3cf8d0c..a78709c 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -35,6 +35,7 @@ #include "agent.h" #include "i18n.h" #include "../common/ssh-utils.h" +#include "../common/private-keys.h" #ifndef O_BINARY #define O_BINARY 0 @@ -51,6 +52,75 @@ struct try_unprotect_arg_s }; +static gpg_error_t +write_extended_private_key (char *fname, estream_t fp, + const void *buf, size_t len) +{ + gpg_error_t err; + pkc_t pk = NULL; + gcry_sexp_t key = NULL; + int remove = 0; + int line; + + err = pkc_parse (&pk, &line, fp); + if (err) + { + log_error ("error parsing '%s' line %d: %s\n", + fname, line, gpg_strerror (err)); + goto leave; + } + + err = gcry_sexp_sscan (&key, NULL, buf, len); + if (err) + goto leave; + + err = pkc_set_private_key (pk, key); + if (err) + goto leave; + + err = es_fseek (fp, 0, SEEK_SET); + if (err) + goto leave; + + err = pkc_write (pk, fp); + if (err) + { + log_error ("error writing '%s': %s\n", fname, gpg_strerror (err)); + remove = 1; + goto leave; + } + + if (ftruncate (es_fileno (fp), es_ftello (fp))) + { + err = gpg_error_from_syserror (); + log_error ("error truncating '%s': %s\n", fname, gpg_strerror (err)); + remove = 1; + goto leave; + } + + if (es_fclose (fp)) + { + err = gpg_error_from_syserror (); + log_error ("error closing '%s': %s\n", fname, gpg_strerror (err)); + remove = 1; + goto leave; + } + else + fp = NULL; + + bump_key_eventcounter (); + + leave: + if (fp) + es_fclose (fp); + if (remove) + gnupg_remove (fname); + xfree (fname); + gcry_sexp_release (key); + pkc_release (pk); + return err; +} + /* Write an S-expression formatted key to our key storage. With FORCE passed as true an existing key with the given GRIP will get overwritten. */ @@ -77,7 +147,7 @@ agent_write_private_key (const unsigned char *grip, return gpg_error (GPG_ERR_EEXIST); } - fp = es_fopen (fname, force? "wb,mode=-rw" : "wbx,mode=-rw"); + fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw"); if (!fp) { gpg_error_t tmperr = gpg_error_from_syserror (); @@ -86,6 +156,38 @@ agent_write_private_key (const unsigned char *grip, return tmperr; } + /* See if an existing key is in extended format. */ + if (force) + { + gpg_error_t rc; + char first; + + if (es_fread (&first, 1, 1, fp) != 1) + { + rc = gpg_error_from_syserror (); + log_error ("error reading first byte from '%s': %s\n", + fname, strerror (errno)); + xfree (fname); + es_fclose (fp); + return rc; + } + + rc = es_fseek (fp, 0, SEEK_SET); + if (rc) + { + log_error ("error seeking in '%s': %s\n", fname, strerror (errno)); + xfree (fname); + es_fclose (fp); + return rc; + } + + if (first != '(') + { + /* Key is in extended format. */ + return write_extended_private_key (fname, fp, buffer, length); + } + } + if (es_fwrite (buffer, length, 1, fp) != 1) { gpg_error_t tmperr = gpg_error_from_syserror (); @@ -95,6 +197,18 @@ agent_write_private_key (const unsigned char *grip, xfree (fname); return tmperr; } + + /* When force is given, the file might have to be truncated. */ + if (force && ftruncate (es_fileno (fp), es_ftello (fp))) + { + gpg_error_t tmperr = gpg_error_from_syserror (); + log_error ("error truncating '%s': %s\n", fname, gpg_strerror (tmperr)); + es_fclose (fp); + gnupg_remove (fname); + xfree (fname); + return tmperr; + } + if (es_fclose (fp)) { gpg_error_t tmperr = gpg_error_from_syserror (); @@ -531,6 +645,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) size_t buflen, erroff; gcry_sexp_t s_skey; char hexgrip[40+4+1]; + char first; *result = NULL; @@ -548,6 +663,50 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) return rc; } + if (es_fread (&first, 1, 1, fp) != 1) + { + rc = gpg_error_from_syserror (); + log_error ("error reading first byte from '%s': %s\n", + fname, strerror (errno)); + xfree (fname); + es_fclose (fp); + return rc; + } + + rc = es_fseek (fp, 0, SEEK_SET); + if (rc) + { + log_error ("error seeking in '%s': %s\n", fname, strerror (errno)); + xfree (fname); + es_fclose (fp); + return rc; + } + + if (first != '(') + { + /* Key is in extended format. */ + pkc_t pk; + int line; + + rc = pkc_parse (&pk, &line, fp); + es_fclose (fp); + + if (rc) + log_error ("error parsing '%s' line %d: %s\n", + fname, line, gpg_strerror (rc)); + else + { + rc = pkc_get_private_key (pk, result); + pkc_release (pk); + if (rc) + log_error ("error getting private key from '%s': %s\n", + fname, gpg_strerror (rc)); + } + + xfree (fname); + return rc; + } + if (fstat (es_fileno (fp), &st)) { rc = gpg_error_from_syserror (); diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 9c91336..95dd2bb 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -16,7 +16,71 @@ and should have permissions 700. The secret keys are stored in files with a name matching the hexadecimal representation of the keygrip[2] and suffixed with ".key". -* Unprotected Private Key Format +* Extended Private Key Format + +GnuPG 2.3+ will use a new format to store private keys that is both +more flexible and easier to read and edit by human beings. The new +format stores name,value-pairs using the common mail and http header +convention. Example (here indented with two spaces): + + Description: Key to sign all GnuPG released tarballs. + The key is actually stored on a smart card. + Use-for-ssh: yes + OpenSSH-cert: long base64 encoded string wrapped so that this + key file can be easily edited with a standard editor. + Key: (shadowed-private-key + (rsa + (n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900 + 2961D8AEA153424DC851EF13B83AC64FBE365C59DC1BD3E83017C90D4365B4 + 83E02859FC13DB5842A00E969480DB96CE6F7D1C03600392B8E08EF0C01FC7 + 19F9F9086B25AD39B4F1C2A2DF3E2BE317110CFFF21D4A11455508FE407997 + 601260816C8422297C0637BB291C3A079B9CB38A92CE9E551F80AA0EBF4F0E + 72C3F250461E4D31F23A7087857FC8438324A013634563D34EFDDCBF2EA80D + F9662C9CCD4BEF2522D8BDFED24CEF78DC6B309317407EAC576D889F88ADA0 + 8C4FFB480981FB68C5C6CA27503381D41018E6CDC52AAAE46B166BDC10637A + E186A02BA2497FDC5D1221#) + (e #00010001#) + (shadowed t1-v1 + (#D2760001240102000005000011730000# OPENPGP.1) + ))) + +GnuPG 2.2 is able to read and update keys using the new format, but +will not create new files using the new format. Furthermore, it only +makes use of the value stored under the name 'Key:'. + +Keys in the extended format can be recognized by looking at the first +byte of the file. If it starts with a '(' it is a naked S-expression, +otherwise it is a key in extended format. + +** Names + +A name must start with a letter and end with a colon. Valid +characters are all ASCII letters, numbers and the hyphen. Comparison +of names is done case insensitively. Names may be used several times +to represent an array of values. + +The name "Key:" is special in that it may occur only once and the +associated value holds the actual S-expression with the cryptographic +key. The S-expression is formatted using the 'Advanced Format' +(GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters so that +the file can be easily inspected and edited. See section 'Private Key +Format' below for details. + +** Values + +Values are UTF-8 encoded strings. Values can be wrapped at any point, +and continued in the next line indicated by leading whitespace. A +continuation line with one leading space does not introduce a blank so +that the lines can be effectively concatenated. A blank line as part +of a continuation line encodes a newline. + +** Comments + +Lines containing only whitespace, and lines starting with whitespace +followed by '#' are considered to be comments and are ignored. + +* Private Key Format +** Unprotected Private Key Format The content of the file is an S-Expression like the ones used with Libgcrypt. Here is an example of an unprotected file: @@ -42,7 +106,7 @@ optional but required for some operations to calculate the fingerprint of the key. This timestamp should be a string with the number of seconds since Epoch or an ISO time string (yyyymmddThhmmss). -* Protected Private Key Format +** Protected Private Key Format A protected key is like this: @@ -67,7 +131,7 @@ optional; the isotimestamp is 15 bytes long (e.g. "19610711T172000"). The currently defined protection modes are: -** openpgp-s2k3-sha1-aes-cbc +*** openpgp-s2k3-sha1-aes-cbc This describes an algorithm using using AES in CBC mode for encryption, SHA-1 for integrity protection and the String to Key @@ -116,7 +180,7 @@ The currently defined protection modes are: the stored one - If they don't match the integrity of the key is not given. -** openpgp-native +*** openpgp-native This is a wrapper around the OpenPGP Private Key Transport format which resembles the standard OpenPGP format and allows the use of an @@ -153,7 +217,7 @@ The currently defined protection modes are: (uri http://foo.bar x-foo:whatever_you_want) (comment whatever)) -* Shadowed Private Key Format +** Shadowed Private Key Format To keep track of keys stored on IC cards we use a third format for private kyes which are called shadow keys as they are only a reference @@ -181,7 +245,7 @@ readers don't allow passing a variable length PIN. More items may be added to the list. -* OpenPGP Private Key Transfer Format +** OpenPGP Private Key Transfer Format This format is used to transfer keys between gpg and gpg-agent. @@ -213,7 +277,7 @@ This format is used to transfer keys between gpg and gpg-agent. * S2KSALT is the 8 byte salt * S2KCOUNT is the count value from RFC-4880. -* Persistent Passphrase Format +** Persistent Passphrase Format To allow persistent storage of cached passphrases we use a scheme similar to the private-key storage format. This is a master diff --git a/common/Makefile.am b/common/Makefile.am index de6a4a8..4a35f64 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -89,7 +89,8 @@ common_sources = \ strlist.c strlist.h \ call-gpg.c call-gpg.h \ exectool.c exectool.h \ - server-help.c server-help.h + server-help.c server-help.h \ + private-keys.c private-keys.h if HAVE_W32_SYSTEM common_sources += w32-reg.c w32-afunix.c w32-afunix.h @@ -154,7 +155,8 @@ endif module_tests = t-stringhelp t-timestuff \ t-convert t-percent t-gettime t-sysutils t-sexputil \ t-session-env t-openpgp-oid t-ssh-utils \ - t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist + t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \ + t-private-keys if !HAVE_W32CE_SYSTEM module_tests += t-exechelp endif @@ -203,6 +205,7 @@ t_zb32_LDADD = $(t_common_ldadd) t_mbox_util_LDADD = $(t_common_ldadd) t_iobuf_LDADD = $(t_common_ldadd) t_strlist_LDADD = $(t_common_ldadd) +t_private_keys_LDADD = $(t_common_ldadd) # System specific test if HAVE_W32_SYSTEM diff --git a/common/private-keys.c b/common/private-keys.c new file mode 100644 index 0000000..1525f92 --- /dev/null +++ b/common/private-keys.c @@ -0,0 +1,666 @@ +/* private-keys.c - Parser and writer for the extended private key format. + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "private-keys.h" +#include "strlist.h" +#include "util.h" + +struct private_key_container +{ + struct private_key_entry *first; + struct private_key_entry *last; +}; + + +struct private_key_entry +{ + struct private_key_entry *prev; + struct private_key_entry *next; + + /* The name. Comments and blank lines have NAME set to NULL. */ + char *name; + + /* The value as stored in the file. We store it when when we parse + a file so that we can reproduce it. */ + strlist_t raw_value; + + /* The decoded value. */ + char *value; +}; + + + +/* Allocation and deallocation. */ + +/* Allocate a private key container structure. */ +pkc_t +pkc_new (void) +{ + return xtrycalloc (1, sizeof (struct private_key_container)); +} + + +static void +pke_release (pke_t entry) +{ + if (entry == NULL) + return; + + xfree (entry->name); + xfree (entry->value); + free_strlist (entry->raw_value); + xfree (entry); +} + + +/* Release a private key container structure. */ +void +pkc_release (pkc_t pk) +{ + pke_t e, next; + + if (pk == NULL) + return; + + for (e = pk->first; e; e = next) + { + next = e->next; + pke_release (e); + } + + xfree (pk); +} + + + +/* Dealing with names and values. */ + +/* Check whether the given name is valid. Valid names start with a + letter, end with a colon, and contain only alphanumeric characters + and the hyphen. */ +static int +valid_name (const char *name) +{ + size_t i, len = strlen (name); + + if (! alphap (name) || len == 0 || name[len - 1] != ':') + return 0; + + for (i = 1; i < len - 1; i++) + if (! alnump (&name[i]) && name[i] != '-') + return 0; + + return 1; +} + + +/* Makes sure that ENTRY has a RAW_VALUE. */ +static gpg_error_t +assert_raw_value (pke_t entry) +{ + size_t len, offset; +#define LINELEN 70 + char buf[LINELEN+3]; + + if (entry->raw_value) + return 0; + + len = strlen (entry->value); + offset = 0; + while (len) + { + size_t amount, linelen = LINELEN; + + /* On the first line we need to subtract space for the name. */ + if (entry->raw_value == NULL && strlen (entry->name) < linelen) + linelen -= strlen (entry->name); + + /* See if the rest of the value fits in this line. */ + if (len <= linelen) + amount = len; + else + { + size_t i; + + /* Find a suitable space to break on. */ + for (i = linelen - 1; linelen - i < 30 && linelen - i > offset; i--) + if (ascii_isspace (entry->value[i])) + break; + + if (ascii_isspace (entry->value[i])) + { + /* Found one. */ + amount = i; + } + else + { + /* Just induce a hard break. */ + amount = linelen; + } + } + + snprintf (buf, sizeof buf, " %.*s\n", (int) amount, + &entry->value[offset]); + append_to_strlist (&entry->raw_value, buf); + offset += amount; + len -= amount; + } + +#undef LINELEN + return 0; +} + + +/* Computes the length of the value encoded as continuation. If + *SWALLOW_WS is set, all whitespace at the beginning of S is + swallowed. If START is given, a pointer to the beginning of the + value is stored there. */ +static size_t +continuation_length (const char *s, int *swallow_ws, const char **start) +{ + size_t len; + + if (*swallow_ws) + { + /* The previous line was a blank line and we inserted a newline. + Swallow all whitespace at the beginning of this line. */ + while (ascii_isspace (*s)) + s++; + } + else + { + /* Iff a continuation starts with more than one space, it + encodes a space. */ + if (ascii_isspace (*s)) + s++; + } + + /* Strip whitespace at the end. */ + len = strlen (s); + while (len > 0 && ascii_isspace (s[len-1])) + len--; + + if (len == 0) + { + /* Blank lines encode newlines. */ + len = 1; + s = "\n"; + *swallow_ws = 1; + } + else + *swallow_ws = 0; + + if (start) + *start = s; + + return len; +} + + +/* Makes sure that ENTRY has a VALUE. */ +static gpg_error_t +assert_value (pke_t entry) +{ + size_t len; + int swallow_ws; + strlist_t s; + char *p; + + if (entry->value) + return 0; + + len = 0; + swallow_ws = 0; + for (s = entry->raw_value; s; s = s->next) + len += continuation_length (s->d, &swallow_ws, NULL); + + /* Add one for the terminating zero. */ + len += 1; + + entry->value = p = xtrymalloc (len); + if (entry->value == NULL) + return gpg_error_from_syserror (); + + swallow_ws = 0; + for (s = entry->raw_value; s; s = s->next) + { + const char *start; + size_t l = continuation_length (s->d, &swallow_ws, &start); + + memcpy (p, start, l); + p += l; + } + + *p++ = 0; + assert (p - entry->value == len); + + return 0; +} + + +/* Get the name. */ +char * +pke_name (pke_t pke) +{ + return pke->name; +} + + +/* Get the value. */ +char * +pke_value (pke_t pke) +{ + assert_value (pke); + return pke->value; +} + + + +/* Adding and modifying values. */ + +/* Add (NAME, VALUE, RAW_VALUE) to PK. NAME may be NULL for comments + and blank lines. At least one of VALUE and RAW_VALUE must be + given. If PRESERVE_ORDER is not given, entries with the same name + are grouped. */ +static gpg_error_t +_pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value, + int preserve_order) +{ + pke_t e; + + assert (value || raw_value); + + if (name && ! valid_name (name)) + return gpg_error (GPG_ERR_INV_NAME); + + if (name && strcasecmp (name, "Key:") == 0 && pkc_lookup (pk, "Key:")) + return gpg_error (GPG_ERR_INV_NAME); + + e = xtrycalloc (1, sizeof *e); + if (e == NULL) + return gpg_error_from_syserror (); + + e->name = name; + e->value = value; + e->raw_value = raw_value; + + if (pk->first) + { + pke_t last; + + if (preserve_order) + last = pk->last; + else + { + /* See if there is already an entry with NAME. */ + last = pkc_lookup (pk, name); + + /* If so, find the last in that block. */ + if (last) + while (last->next) + { + pke_t next = last->next; + + if (next->name && strcasecmp (next->name, name) == 0) + last = next; + else + break; + } + /* Otherwise, just find the last entry. */ + else + last = pk->last; + } + + if (last->next) + { + e->prev = last; + e->next = last->next; + last->next = e; + e->next->prev = e; + } + else + { + e->prev = last; + last->next = e; + pk->last = e; + } + } + else + pk->first = pk->last = e; + + return 0; +} + + +/* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it + is not updated but the new entry is appended. */ +gpg_error_t +pkc_add (pkc_t pk, const char *name, const char *value) +{ + char *k, *v; + + k = xtrystrdup (name); + if (k == NULL) + return gpg_error_from_syserror (); + + v = xtrystrdup (value); + if (v == NULL) + { + xfree (k); + return gpg_error_from_syserror (); + } + + return _pkc_add (pk, k, v, NULL, 0); +} + + +/* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it + is updated with VALUE. If multiple entries with NAME exist, the + first entry is updated. */ +gpg_error_t +pkc_set (pkc_t pk, const char *name, const char *value) +{ + pke_t e; + + if (! valid_name (name)) + return GPG_ERR_INV_NAME; + + e = pkc_lookup (pk, name); + if (e) + { + char *v; + + v = xtrystrdup (value); + if (v == NULL) + return gpg_error_from_syserror (); + + free_strlist (e->raw_value); + e->raw_value = NULL; + xfree (e->value); + e->value = v; + + return 0; + } + else + return pkc_add (pk, name, value); +} + + +/* Delete the given entry from PK. */ +void +pkc_delete (pkc_t pk, pke_t entry) +{ + if (entry->prev) + entry->prev->next = entry->next; + else + pk->first = entry->next; + + if (entry->next) + entry->next->prev = entry->prev; + else + pk->last = entry->prev; + + pke_release (entry); +} + + + +/* Lookup and iteration. */ + +/* Get the first non-comment entry. */ +pke_t +pkc_first (pkc_t pk) +{ + pke_t entry; + for (entry = pk->first; entry; entry = entry->next) + if (entry->name) + return entry; + return NULL; +} + + +/* Get the first entry with the given name. */ +pke_t +pkc_lookup (pkc_t pk, const char *name) +{ + pke_t entry; + for (entry = pk->first; entry; entry = entry->next) + if (entry->name && strcasecmp (entry->name, name) == 0) + return entry; + return NULL; +} + + +/* Get the next non-comment entry. */ +pke_t +pke_next (pke_t entry) +{ + for (entry = entry->next; entry; entry = entry->next) + if (entry->name) + return entry; + return NULL; +} + + +/* Get the next entry with the given name. */ +pke_t +pke_next_value (pke_t entry, const char *name) +{ + for (entry = entry->next; entry; entry = entry->next) + if (entry->name && strcasecmp (entry->name, name) == 0) + return entry; + return NULL; +} + + + +/* Private key handling. */ + +/* Get the private key. */ +gpg_error_t +pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp) +{ + pke_t e; + + e = pkc_lookup (pk, "Key:"); + if (e == NULL) + return gpg_error (GPG_ERR_MISSING_KEY); + + assert_value (e); + return gcry_sexp_sscan (retsexp, NULL, e->value, strlen (e->value)); +} + + +/* Set the private key. */ +gpg_error_t +pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp) +{ + gpg_error_t err; + char *raw, *clean, *p; + size_t len, i; + + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); + + raw = xtrymalloc (len); + if (raw == NULL) + return gpg_error_from_syserror (); + + clean = xtrymalloc (len); + if (clean == NULL) + { + xfree (raw); + return gpg_error_from_syserror (); + } + + gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, raw, len); + + /* Strip any whitespace at the end. */ + i = strlen (raw) - 1; + while (i && ascii_isspace (raw[i])) + { + raw[i] = 0; + i--; + } + + /* Replace any newlines with spaces, remove superfluous whitespace. */ + len = strlen (raw); + for (p = clean, i = 0; i < len; i++) + { + char c = raw[i]; + + /* Collapse contiguous and superfluous spaces. */ + if (ascii_isspace (c) && i > 0 + && (ascii_isspace (raw[i-1]) || raw[i-1] == '(' || raw[i-1] == ')')) + continue; + + if (c == '\n') + c = ' '; + + *p++ = c; + } + *p = 0; + + err = pkc_set (pk, "Key:", clean); + xfree (raw); + xfree (clean); + return err; +} + + + +/* Parsing and serialization. */ + +/* Parse STREAM and return a newly allocated private key container + structure in RESULT. If ERRLINEP is given, the line number the + parser was last considering is stored there. */ +gpg_error_t +pkc_parse (pkc_t *result, int *errlinep, estream_t stream) +{ + gpg_error_t err = 0; + gpgrt_ssize_t len; + char *buf = NULL; + size_t buf_len = 0; + char *name = NULL; + strlist_t raw_value = NULL; + + + *result = pkc_new (); + if (*result == NULL) + return gpg_error_from_syserror (); + + if (errlinep) + *errlinep = 0; + while ((len = es_read_line (stream, &buf, &buf_len, NULL))) + { + char *p; + if (errlinep) + *errlinep += 1; + + /* Skip any whitespace. */ + for (p = buf; *p && ascii_isspace (*p); p++) + /* Do nothing. */; + + if (name && (spacep (buf) || *p == 0)) + { + /* A continuation. */ + append_to_strlist (&raw_value, buf); + continue; + } + + /* No continuation. Add the current entry if any. */ + if (raw_value) + { + err = _pkc_add (*result, name, NULL, raw_value, 1); + if (err) + goto leave; + } + + /* And prepare for the next one. */ + name = NULL; + raw_value = NULL; + + if (*p != 0 && *p != '#') + { + char *colon, *value, tmp; + + colon = strchr (buf, ':'); + if (colon == NULL) + { + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + + value = colon + 1; + tmp = *value; + *value = 0; + name = xstrdup (p); + *value = tmp; + + if (name == NULL) + { + err = gpg_error_from_syserror (); + goto leave; + } + + append_to_strlist (&raw_value, value); + continue; + } + + append_to_strlist (&raw_value, buf); + } + + /* Add the final entry. */ + if (raw_value) + err = _pkc_add (*result, name, NULL, raw_value, 1); + + leave: + gpgrt_free (buf); + + return err; +} + + +/* Write a representation of PK to STREAM. */ +gpg_error_t +pkc_write (pkc_t pk, estream_t stream) +{ + pke_t entry; + strlist_t s; + + for (entry = pk->first; entry; entry = entry->next) + { + if (entry->name) + es_fputs (entry->name, stream); + + assert_raw_value (entry); + for (s = entry->raw_value; s; s = s->next) + es_fputs (s->d, stream); + + if (es_ferror (stream)) + return gpg_error_from_syserror (); + } + + return 0; +} diff --git a/common/private-keys.h b/common/private-keys.h new file mode 100644 index 0000000..1691f75 --- /dev/null +++ b/common/private-keys.h @@ -0,0 +1,99 @@ +/* private-keys.c - Parser and writer for the extended private key format. + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef GNUPG_COMMON_PRIVATE_KEYS_H +#define GNUPG_COMMON_PRIVATE_KEYS_H + +struct private_key_container; +typedef struct private_key_container *pkc_t; + +struct private_key_entry; +typedef struct private_key_entry *pke_t; + + + +/* Memory management, and dealing with entries. */ + +/* Allocate a private key container structure. */ +pkc_t pkc_new (void); + +/* Release a private key container structure. */ +void pkc_release (pkc_t pk); + +/* Get the name. */ +char *pke_name (pke_t pke); + +/* Get the value. */ +char *pke_value (pke_t pke); + + + +/* Lookup and iteration. */ + +/* Get the first non-comment entry. */ +pke_t pkc_first (pkc_t pk); + +/* Get the first entry with the given name. */ +pke_t pkc_lookup (pkc_t pk, const char *name); + +/* Get the next non-comment entry. */ +pke_t pke_next (pke_t entry); + +/* Get the next entry with the given name. */ +pke_t pke_next_value (pke_t entry, const char *name); + + + +/* Adding and modifying values. */ + +/* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it + is not updated but the new entry is appended. */ +gpg_error_t pkc_add (pkc_t pk, const char *name, const char *value); + +/* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it + is updated with VALUE. If multiple entries with NAME exist, the + first entry is updated. */ +gpg_error_t pkc_set (pkc_t pk, const char *name, const char *value); + +/* Delete the given entry from PK. */ +void pkc_delete (pkc_t pk, pke_t pke); + + + +/* Private key handling. */ + +/* Get the private key. */ +gpg_error_t pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp); + +/* Set the private key. */ +gpg_error_t pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp); + + + +/* Parsing and serialization. */ + +/* Parse STREAM and return a newly allocated private key container + structure in RESULT. If ERRLINEP is given, the line number the + parser was last considering is stored there. */ +gpg_error_t pkc_parse (pkc_t *result, int *errlinep, estream_t stream); + +/* Write a representation of PK to STREAM. */ +gpg_error_t pkc_write (pkc_t pk, estream_t stream); + +#endif /* GNUPG_COMMON_PRIVATE_KEYS_H */ diff --git a/common/t-private-keys.c b/common/t-private-keys.c new file mode 100644 index 0000000..06415a1 --- /dev/null +++ b/common/t-private-keys.c @@ -0,0 +1,543 @@ +/* t-private-keys.c - Module test for private-keys.c + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "private-keys.h" + +static int verbose; + +void +test_getting_values (pkc_t pk) +{ + pke_t e; + + e = pkc_lookup (pk, "Comment:"); + assert (e); + + /* Names are case-insensitive. */ + e = pkc_lookup (pk, "comment:"); + assert (e); + e = pkc_lookup (pk, "COMMENT:"); + assert (e); + + e = pkc_lookup (pk, "SomeOtherName:"); + assert (e); +} + + +void +test_key_extraction (pkc_t pk) +{ + gpg_error_t err; + gcry_sexp_t key; + + err = pkc_get_private_key (pk, &key); + assert (err == 0); + assert (key); + + if (verbose) + gcry_sexp_dump (key); + + gcry_sexp_release (key); +} + + +void +test_iteration (pkc_t pk) +{ + int i; + pke_t e; + + i = 0; + for (e = pkc_first (pk); e; e = pke_next (e)) + i++; + assert (i == 4); + + i = 0; + for (e = pkc_lookup (pk, "Comment:"); + e; + e = pke_next_value (e, "Comment:")) + i++; + assert (i == 3); +} + + +void +test_whitespace (pkc_t pk) +{ + pke_t e; + + e = pkc_lookup (pk, "One:"); + assert (e); + assert (strcmp (pke_value (e), "WithoutWhitespace") == 0); + + e = pkc_lookup (pk, "Two:"); + assert (e); + assert (strcmp (pke_value (e), "With Whitespace") == 0); + + e = pkc_lookup (pk, "Three:"); + assert (e); + assert (strcmp (pke_value (e), + "Blank lines in continuations encode newlines.\n" + "Next paragraph.") == 0); +} + + +struct +{ + char *value; + void (*test_func) (pkc_t); +} tests[] = + { + { + "# This is a comment followed by an empty line\n" + "\n", + NULL, + }, + { + "# This is a comment followed by two empty lines, Windows style\r\n" + "\r\n" + "\r\n", + NULL, + }, + { + "# Some name,value pairs\n" + "Comment: Some comment.\n" + "SomeOtherName: Some value.\n", + test_getting_values, + }, + { + " # Whitespace is preserved as much as possible\r\n" + "Comment:Some comment.\n" + "SomeOtherName: Some value. \n", + test_getting_values, + }, + { + "# Values may be continued in the next line as indicated by leading\n" + "# space\n" + "Comment: Some rather long\n" + " comment that is continued in the next line.\n" + "\n" + " Blank lines with or without whitespace are allowed within\n" + " continuations to allow paragraphs.\n" + "SomeOtherName: Some value.\n", + test_getting_values, + }, + { + "# Names may be given multiple times forming an array of values\n" + "Comment: Some comment, element 0.\n" + "Comment: Some comment, element 1.\n" + "Comment: Some comment, element 2.\n" + "SomeOtherName: Some value.\n", + test_iteration, + }, + { + "# One whitespace at the beginning of a continuation is swallowed.\n" + "One: Without\n" + " Whitespace\n" + "Two: With\n" + " Whitespace\n" + "Three: Blank lines in continuations encode newlines.\n" + "\n" + " Next paragraph.\n", + test_whitespace, + }, + { + "Description: Key to sign all GnuPG released tarballs.\n" + " The key is actually stored on a smart card.\n" + "Use-for-ssh: yes\n" + "OpenSSH-cert: long base64 encoded string wrapped so that this\n" + " key file can be easily edited with a standard editor.\n" + "Key: (shadowed-private-key\n" + " (rsa\n" + " (n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900\n" + " 2961D8AEA153424DC851EF13B83AC64FBE365C59DC1BD3E83017C90D4365B4\n" + " 83E02859FC13DB5842A00E969480DB96CE6F7D1C03600392B8E08EF0C01FC7\n" + " 19F9F9086B25AD39B4F1C2A2DF3E2BE317110CFFF21D4A11455508FE407997\n" + " 601260816C8422297C0637BB291C3A079B9CB38A92CE9E551F80AA0EBF4F0E\n" + " 72C3F250461E4D31F23A7087857FC8438324A013634563D34EFDDCBF2EA80D\n" + " F9662C9CCD4BEF2522D8BDFED24CEF78DC6B309317407EAC576D889F88ADA0\n" + " 8C4FFB480981FB68C5C6CA27503381D41018E6CDC52AAAE46B166BDC10637A\n" + " E186A02BA2497FDC5D1221#)\n" + " (e #00010001#)\n" + " (shadowed t1-v1\n" + " (#D2760001240102000005000011730000# OPENPGP.1)\n" + " )))\n", + test_key_extraction, + }, + }; + + +static char * +pkc_to_string (pkc_t pk) +{ + gpg_error_t err; + char *buf; + size_t len; + estream_t sink; + + sink = es_fopenmem (0, "rw"); + assert (sink); + + err = pkc_write (pk, sink); + assert (err == 0); + + len = es_ftell (sink); + buf = xmalloc (len+1); + assert (buf); + + es_fseek (sink, 0, SEEK_SET); + es_read (sink, buf, len, NULL); + buf[len] = 0; + + es_fclose (sink); + return buf; +} + + +void dummy_free (void *p) { (void) p; } +void *dummy_realloc (void *p, size_t s) { (void) s; return p; } + +void +run_tests (void) +{ + gpg_error_t err; + pkc_t pk; + + int i; + for (i = 0; i < DIM (tests); i++) + { + estream_t source; + char *buf; + size_t len; + + len = strlen (tests[i].value); + source = es_mopen (tests[i].value, len, len, + 0, dummy_realloc, dummy_free, "r"); + assert (source); + + err = pkc_parse (&pk, NULL, source); + assert (err == 0); + assert (pk); + + if (verbose) + { + err = pkc_write (pk, es_stderr); + assert (err == 0); + } + + buf = pkc_to_string (pk); + assert (memcmp (tests[i].value, buf, len) == 0); + + es_fclose (source); + xfree (buf); + + if (tests[i].test_func) + tests[i].test_func (pk); + + pkc_release (pk); + } +} + + +void +run_modification_tests (void) +{ + gpg_error_t err; + pkc_t pk; + pke_t e; + gcry_sexp_t key; + char *buf; + + pk = pkc_new (); + assert (pk); + + pkc_set (pk, "Foo:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Bar\n") == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "Baz"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\n") == 0); + xfree (buf); + + pkc_set (pk, "Bar:", "Bazzel"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_add (pk, "Foo:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_add (pk, "DontExistYet:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\nDontExistYet: Bar\n") + == 0); + xfree (buf); + + pkc_delete (pk, pkc_lookup (pk, "DontExistYet:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pke_next_value (pkc_lookup (pk, "Foo:"), "Foo:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pkc_lookup (pk, "Foo:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Bar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pkc_first (pk)); + buf = pkc_to_string (pk); + assert (strcmp (buf, "") == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "A really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: A really long value spanning across multiple" + " lines that has to be\n wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "XA really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: XA really long value spanning across multiple" + " lines that has to\n be wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "XXXXA really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: XXXXA really long value spanning across multiple" + " lines that has\n to be wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "Areallylongvaluespanningacrossmultiplelines" + "thathastobewrappedataconvenientspacethatisnotthere."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Areallylongvaluespanningacrossmultiplelinesthat" + "hastobewrappedataco\n nvenientspacethatisnotthere.\n") + == 0); + xfree (buf); + pkc_release (pk); + + pk = pkc_new (); + assert (pk); + + err = gcry_sexp_build (&key, NULL, "(hello world)"); + assert (err == 0); + assert (key); + + err = pkc_set_private_key (pk, key); + gcry_sexp_release (key); + assert (err == 0); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Key: (hello world)\n") == 0); + xfree (buf); + pkc_release (pk); +} + + +void +convert (const char *fname) +{ + gpg_error_t err; + estream_t source; + gcry_sexp_t key; + char *buf; + size_t buflen; + gpgrt_ssize_t nread; + struct stat st; + pkc_t pk; + + source = es_fopen (fname, "rb"); + if (source == NULL) + goto leave; + + if (fstat (es_fileno (source), &st)) + goto leave; + + buflen = st.st_size; + buf = xtrymalloc (buflen+1); + assert (buf); + + if (es_fread (buf, buflen, 1, source) != 1) + goto leave; + + err = gcry_sexp_sscan (&key, NULL, buf, buflen); + if (err) + { + fprintf (stderr, "malformed s-expression in %s\n", fname); + exit (1); + } + + pk = pkc_new (); + assert (pk); + + err = pkc_set_private_key (pk, key); + assert (err == 0); + + err = pkc_write (pk, es_stdout); + assert (err == 0); + + return; + + leave: + perror (fname); + exit (1); +} + + +void +parse (const char *fname) +{ + gpg_error_t err; + estream_t source; + char *buf; + pkc_t pk_a, pk_b; + pke_t e; + int line; + + source = es_fopen (fname, "rb"); + if (source == NULL) + { + perror (fname); + exit (1); + } + + err = pkc_parse (&pk_a, &line, source); + if (err) + { + fprintf (stderr, "failed to parse %s line %d: %s\n", + fname, line, gpg_strerror (err)); + exit (1); + } + + buf = pkc_to_string (pk_a); + xfree (buf); + + pk_b = pkc_new (); + assert (pk_b); + + for (e = pkc_first (pk_a); e; e = pke_next (e)) + { + gcry_sexp_t key = NULL; + + if (strcasecmp (pke_name (e), "Key:") == 0) + { + err = pkc_get_private_key (pk_a, &key); + if (err) + key = NULL; + } + + if (key) + { + err = pkc_set_private_key (pk_b, key); + assert (err == 0); + } + else + { + err = pkc_add (pk_b, pke_name (e), pke_value (e)); + assert (err == 0); + } + } + + buf = pkc_to_string (pk_b); + if (verbose) + fprintf (stdout, "%s", buf); + xfree (buf); +} + + +void +print_usage (void) +{ + fprintf (stderr, + "usage: t-private-keys [--verbose]" + " [--convert " + " || --parse ]\n"); + exit (2); +} + + +int +main (int argc, char **argv) +{ + enum { TEST, CONVERT, PARSE } command = TEST; + + if (argc) + { argc--; argv++; } + if (argc && !strcmp (argv[0], "--verbose")) + { + verbose = 1; + argc--; argv++; + } + + if (argc && !strcmp (argv[0], "--convert")) + { + command = CONVERT; + argc--; argv++; + if (argc != 1) + print_usage (); + } + + if (argc && !strcmp (argv[0], "--parse")) + { + command = PARSE; + argc--; argv++; + if (argc != 1) + print_usage (); + } + + switch (command) + { + case TEST: + run_tests (); + run_modification_tests (); + break; + + case CONVERT: + convert (*argv); + break; + + case PARSE: + parse (*argv); + break; + } + + return 0; +} diff --git a/common/util.h b/common/util.h index 6410b11..466c519 100644 --- a/common/util.h +++ b/common/util.h @@ -333,6 +333,9 @@ int _gnupg_isatty (int fd); /*-- Macros to replace ctype ones to avoid locale problems. --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') #define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define alphap(p) ((*(p) >= 'A' && *(p) <= 'Z') \ + || (*(p) >= 'a' && *(p) <= 'z')) +#define alnump(p) (alphap (p) || digitp (p)) #define hexdigitp(a) (digitp (a) \ || (*(a) >= 'A' && *(a) <= 'F') \ || (*(a) >= 'a' && *(a) <= 'f')) -- 2.1.4 From ben at adversary.org Thu Apr 14 16:34:51 2016 From: ben at adversary.org (Ben McGinnes) Date: Fri, 15 Apr 2016 00:34:51 +1000 Subject: GPGME XML schemas In-Reply-To: <20160325173837.GF2963@adversary.org> References: <20160325173837.GF2963@adversary.org> Message-ID: <20160414143451.GB69340@adversary.org> On Sat, Mar 26, 2016 at 04:38:37AM +1100, Ben McGinnes wrote: > > I can also generate documentation from the .xsd file and I'll add > the results of that a bit later. I finally got around to doing this bit and there's now a docs directory in the same branch (ben/xml) with DocBook 5.0 docs generated from gpgmekeys.xsd and an XHTML version made with an XSLT from the DocBook version. It comes with 29 images (PNG) created from the schema map/diagram. Regards, Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 630 bytes Desc: not available URL: From ineiev at gnu.org Thu Apr 14 18:18:17 2016 From: ineiev at gnu.org (Ineiev) Date: Thu, 14 Apr 2016 12:18:17 -0400 Subject: [STABLE-BRANCH-1-4 PATCH] g10: secmem leak Message-ID: <20160414161817.GA9527@gnu.org> Hello, I attach a patch for GnuPG-bug 1371. in short, secure memory is leaked because proc_parameter_file() adds new entries to the head of the list of parameters, and these entries aren't accessible to the caller that releases the list. When multiple keys are generated in a batch, the secure memory is fragmented very soon, so more keys can't be generated. The patch adds the new parameters next to the head of the list instead, so they can be released in the caller. BTW, the 2-0 branch is also affected and can be fixed in a similar way; the 2-1 branch is not affected, because the new parameters are appended to the tail of the list with append_to_parameter(). Thank you! -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-g10-Fix-secmem-leak.patch Type: text/x-diff Size: 2525 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: Digital signature URL: From wk at gnupg.org Thu Apr 14 19:43:22 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 14 Apr 2016 19:43:22 +0200 Subject: [STABLE-BRANCH-1-4 PATCH] g10: secmem leak In-Reply-To: <20160414161817.GA9527@gnu.org> (ineiev@gnu.org's message of "Thu, 14 Apr 2016 12:18:17 -0400") References: <20160414161817.GA9527@gnu.org> Message-ID: <87r3e85bnp.fsf@wheatstone.g10code.de> On Thu, 14 Apr 2016 18:18, ineiev at gnu.org said: > I attach a patch for GnuPG-bug 1371. in short, secure memory > is leaked because proc_parameter_file() adds new entries > to the head of the list of parameters, and these entries > aren't accessible to the caller that releases the list. Thanks for the patch - I will look at it later. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From aheinecke at intevation.de Fri Apr 15 09:38:59 2016 From: aheinecke at intevation.de (Andre Heinecke) Date: Fri, 15 Apr 2016 09:38:59 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <1460644872-8729-3-git-send-email-justus@g10code.com> References: <1460644872-8729-1-git-send-email-justus@g10code.com> <1460644872-8729-3-git-send-email-justus@g10code.com> Message-ID: <3052732.oQQdDzmVxa@esus> Hi Justus, On Thursday 14 April 2016 16:41:12 Justus Winter wrote: > GnuPG 2.3+ will use a new format to store private keys that is both > more flexible and easier to read and edit by human beings. The new > format stores name,value-pairs using the common mail and http header > convention. > > This patch adds the parser and support code and prepares GnuPG 2.1 for > the new format. I feel a bit that this should have been discussed before implementing it. For any changes to key storage (public or private) I would have argued to switch to sqlite. The amount of Bugs and performance problems by using non-standard formats has been a problem in GnuPG in my (limited) experience. Sqlite databases are also easily editable by power users with standard tools and you would not need yet another GnuPG specific file format with a parser etc. it would imo also solve your requirement to store meta data. Regards, Andre -- Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/ Intevation GmbH, Neuer Graben 17, 49074 Osnabr?ck | AG Osnabr?ck, HR B 18998 Gesch?ftsf?hrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 648 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Fri Apr 15 11:09:41 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 15 Apr 2016 11:09:41 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <3052732.oQQdDzmVxa@esus> (Andre Heinecke's message of "Fri, 15 Apr 2016 09:38:59 +0200") References: <1460644872-8729-1-git-send-email-justus@g10code.com> <1460644872-8729-3-git-send-email-justus@g10code.com> <3052732.oQQdDzmVxa@esus> Message-ID: <87r3e71bmy.fsf@wheatstone.g10code.de> On Fri, 15 Apr 2016 09:38, aheinecke at intevation.de said: > I feel a bit that this should have been discussed before implementing it. For As usual with new features we provide it on a read-only base first to avoid backward compatibility problems. > any changes to key storage (public or private) I would have argued to switch > to sqlite. The amount of Bugs and performance problems by using That is a big fat no-go! gpg-agent is designed to take good care of the secret keys and thus we go into great lengths to protect them from leaking. Putting them in a SQL database is dangerous because we have no control over the way they are stored and we would need to link gpg-agent to a huge amount of extra code. Direct use of the file system is a better place for these objects. > formats has been a problem in GnuPG in my (limited) experience. The secret keys are stored one key per file and I am not aware of any problems. In fact we developed this format a decade ago with the special purpose to store secret keys. > and you would not need yet another GnuPG specific file format with a parser etc. > it would imo also solve your requirement to store meta data. Nope. It is already possible to store meta data in the key files. We do this for more than a decade. However, it requires extra tools (as does a SQL DB) which is admin unfriendly. Also a textual representation is always better than binary blurbs somewhere on the disk. The immediate use cases for the new formats will be: - Allow to set a confirm flag for all kind of keys and not only for ssh use via the sshcontrol file. - Persistent store for ssh certificates for use by the ssh-agent protocol. We will also take the opportunity of the new format to make use of OCB-AES based protection of secret keys for those who need this (the gpg4vs-nfd project). Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From aheinecke at intevation.de Fri Apr 15 11:35:18 2016 From: aheinecke at intevation.de (Andre Heinecke) Date: Fri, 15 Apr 2016 11:35:18 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <87r3e71bmy.fsf@wheatstone.g10code.de> References: <1460644872-8729-1-git-send-email-justus@g10code.com> <3052732.oQQdDzmVxa@esus> <87r3e71bmy.fsf@wheatstone.g10code.de> Message-ID: <1797729.zODfQSzL4g@esus> Hi, On Friday 15 April 2016 11:09:41 Werner Koch wrote: > On Fri, 15 Apr 2016 09:38, aheinecke at intevation.de said: > > I feel a bit that this should have been discussed before implementing it. > > For > As usual with new features we provide it on a read-only base first to > avoid backward compatibility problems. Yes and that is good but still it is another migration to a new format. The migration from 2.0 to 2.1 with the new secret key storage is painful enough my initial reaction was that I'm scared of another migration so that GNUPGHOME will be incompatible between different distributions I use. But thinking a bit more about this It probably won't hurt as much as the 2.0 / 1 incompatibility in secret key storage. As this only will be an additional problem if GnuPG < 2.1.11 but > 2.1.0 is used in parallel with a 2.3 version. (And I was hoping a bit for a migration to a versioned format (sql) to end all migrations) > > any changes to key storage (public or private) I would have argued to > > switch to sqlite. The amount of Bugs and performance problems by using > > That is a big fat no-go! gpg-agent is designed to take good care of the > secret keys and thus we go into great lengths to protect them from > leaking. Putting them in a SQL database is dangerous because we have no > control over the way they are stored and we would need to link gpg-agent > to a huge amount of extra code. Direct use of the file system is a > better place for these objects. Just to be clear, I'm not talking about the actual key material but the encrypted files that are now in the filesystem. I don't see how putting this data in a sqlite database would hurt security. But I see the point that gpg- agent should not link with sqlite. So I'm agreeing here that sqlite would not be a good option. > Nope. It is already possible to store meta data in the key files. We do > this for more than a decade. However, it requires extra tools (as does > a SQL DB) which is admin unfriendly. Also a textual representation is > always better than binary blurbs somewhere on the disk. > > The immediate use cases for the new formats will be: > > - Allow to set a confirm flag for all kind of keys and not only for ssh > use via the sshcontrol file. > > - Persistent store for ssh certificates for use by the ssh-agent > protocol. > > We will also take the opportunity of the new format to make use of > OCB-AES based protection of secret keys for those who need this (the > gpg4vs-nfd project). Yes I see the need for additional meta-data that is read by gpg-agent. But is there no way to store that meta data without breaking older versions? This would remove the need to first add read support and then later use it and have another migration. Regards, Andre -- Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/ Intevation GmbH, Neuer Graben 17, 49074 Osnabr?ck | AG Osnabr?ck, HR B 18998 Gesch?ftsf?hrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 648 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Fri Apr 15 16:52:59 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 15 Apr 2016 16:52:59 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <1797729.zODfQSzL4g@esus> (Andre Heinecke's message of "Fri, 15 Apr 2016 11:35:18 +0200") References: <1460644872-8729-1-git-send-email-justus@g10code.com> <3052732.oQQdDzmVxa@esus> <87r3e71bmy.fsf@wheatstone.g10code.de> <1797729.zODfQSzL4g@esus> Message-ID: <87zisuyldg.fsf@wheatstone.g10code.de> On Fri, 15 Apr 2016 11:35, aheinecke at intevation.de said: > Yes and that is good but still it is another migration to a new format. The It is not a new format but but an update of an existsing format. > migration from 2.0 to 2.1 with the new secret key storage is painful enough my This is unrelated. We are talking only about files stored under private-keys-v1.d which are an exclusive property of gpg-agent. Neither gpg nor gpgsm are involved. > more about this It probably won't hurt as much as the 2.0 / 1 incompatibility > in secret key storage. As this only will be an additional problem if GnuPG < You mean OpenPGP keys in 2.1 and pre 2.1. Actually it is not an incompatibility but an upgrade path. Once you switched to the new storage method (ie. 2.1) you can't switch back with out 2 additional steps. Remeber that for ages I am talking that secring.gpg and pubring.gpg shall never be used directly but only through --export and import commands. > (And I was hoping a bit for a migration to a versioned format (sql) to > end all migrations) SQL is not a way to end migrations but a way to clobber a DB schema with insane data structures for the purpose of backward compatibility. A complex schema does not help to keep compatibility to old software versions if you need to change that just that schema. > encrypted files that are now in the filesystem. I don't see how putting this > data in a sqlite database would hurt security. But I see the point that gpg- Because there are buffers which keep the keys in user space memory longer than needed. > Yes I see the need for additional meta-data that is read by gpg-agent. But is > there no way to store that meta data without breaking older versions? This > would remove the need to first add read support and then later use it There won't be any breakage. The new storage format will only be used if the user explicitly requested that. Right, older software versions won't be able to read that format and thus can't use the key. But that is the same as with the new OCB-AES protection algorithm. In theory we could easily backport the new format to GnuPG 2.0. But the format will go along with the OCB-AES protection and that requires the use of Libgcrypt 1.7 - I doubt that major distros will upgrade to Libgcrypt 1.7 just for this purpose. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Apr 15 17:42:37 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 15 Apr 2016 17:42:37 +0200 Subject: [Announce] Libgcrypt 1.7.0 released Message-ID: <87vb3iyj2q.fsf@wheatstone.g10code.de> Hello! The GnuPG Project is pleased to announce the availability of Libgcrypt version 1.7.0. This is a new stable version of Libgcrypt with full API and ABI compatibiliy to the 1.6 series. Its main features are new algorithms, curves, and performance improvements. Libgcrypt is a general purpose library of cryptographic building blocks. It is originally based on code used by GnuPG. It does not provide any implementation of OpenPGP or other protocols. Thorough understanding of applied cryptography is required to use Libgcrypt. Noteworthy changes between version 1.6.0 and 1.7.0: =================================================== * New algorithms and modes: - SHA3-224, SHA3-256, SHA3-384, SHA3-512, and MD2 hash algorithms. - SHAKE128 and SHAKE256 extendable-output hash algorithms. - ChaCha20 stream cipher. - Poly1305 message authentication algorithm - ChaCha20-Poly1305 Authenticated Encryption with Associated Data mode. - OCB mode. - HMAC-MD2 for use by legacy applications. * New curves for ECC: - Curve25519. - sec256k1. - GOST R 34.10-2001 and GOST R 34.10-2012. * Performance: - Improved performance of KDF functions. - Assembler optimized implementations of Blowfish and Serpent on ARM. - Assembler optimized implementation of 3DES on x86. - Improved AES using the SSSE3 based vector permutation method by Mike Hamburg. - AVX/BMI is used for SHA-1 and SHA-256 on x86. This is for SHA-1 about 20% faster than SSSE3 and more than 100% faster than the generic C implementation. - 40% speedup for SHA-512 and 72% for SHA-1 on ARM Cortex-A8. - 60-90% speedup for Whirlpool on x86. - 300% speedup for RIPE MD-160. - Up to 11 times speedup for CRC functions on x86. * Other features: - Improved ECDSA and FIPS 186-4 compliance. - Support for Montgomery curves. - gcry_cipher_set_sbox to tweak S-boxes of the gost28147 cipher algorithm. - gcry_mpi_ec_sub to subtract two points on a curve. - gcry_mpi_ec_decode_point to decode an MPI into a point object. - Emulation for broken Whirlpool code prior to 1.6.0. [from 1.6.1] - Flag "pkcs1-raw" to enable PCKS#1 padding with a user supplied hash part. - Parameter "saltlen" to set a non-default salt length for RSA PSS. - A SP800-90A conforming DRNG replaces the former X9.31 alternative random number generator. - Map deprecated RSA algo number to the RSA algo number for better backward compatibility. [from 1.6.2] - Use ciphertext blinding for Elgamal decryption [CVE-2014-3591]. See http://www.cs.tau.ac.il/~tromer/radioexp/ for details. [from 1.6.3] - Fixed data-dependent timing variations in modular exponentiation [related to CVE-2015-0837, Last-Level Cache Side-Channel Attacks are Practical]. [from 1.6.3] - Flag "no-keytest" for ECC key generation. Due to a bug in the parser that flag will also be accepted but ignored by older version of Libgcrypt. [from 1.6.4] - Speed up the random number generator by requiring less extra seeding. [from 1.6.4] - Always verify a created RSA signature to avoid private key leaks due to hardware failures. [from 1.6.4] - Mitigate side-channel attack on ECDH with Weierstrass curves [CVE-2015-7511]. See http://www.cs.tau.ac.IL/~tromer/ecdh/ for details. [from 1.6.5] * Internal changes: - Moved locking out to libgpg-error. - Support of the SYSROOT envvar in the build system. - Refactor some code. - The availability of a 64 bit integer type is now mandatory. * Bug fixes: - Fixed message digest lookup by OID (regression in 1.6.0). - Fixed a build problem on NetBSD - Fixed memory leaks in ECC code. - Fixed some asm build problems and feature detection bugs. For interface changes relative to the 1.6.0 release see below [4]. Note that the 1.6 series will enter end-of-life state on 2017-06-30. Download ======== Source code is hosted at the GnuPG FTP server and its mirrors as listed at https://gnupg.org/download/mirrors.html . On the primary server the source tarball and its digital signature are: ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.bz2 (2477k) ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.bz2.sig That file is bzip2 compressed. A gzip compressed version is here: ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.gz (3309k) ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.gz.sig The same files are also available via HTTP: https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.bz2 https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.bz2.sig https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.gz https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.7.0.tar.gz.sig In order to check that the version of Libgcrypt you downloaded is an original and unmodified file please follow the instructions found at . In short, you may use one of the following mthods: - Check the supplied OpenPGP signature. For example to check the signature of the file libgcrypt-1.7.0.tar.bz2 you would use this command: gpg --verify libgcrypt-1.7.0.tar.bz2.sig libgcrypt-1.7.0.tar.bz2 This checks whether the signature file matches the source file. You should see a message indicating that the signature is good and made by one or more of the release signing keys. - If you are not able to use GnuPG, you have to verify the SHA-1 checksum: sha1sum libgcrypt-1.7.0.tar.bz2 and check that the output matches the first line from the following list: f840b737faafded451a084ae143285ad68bbfb01 libgcrypt-1.7.0.tar.bz2 b6b6cfea349ca18a658a18a6365f5e2ca78fe1cc libgcrypt-1.7.0.tar.gz You should also verify that the checksums above are authentic by matching them with copies of this announcement. Those copies can be found at other mailing lists, web sites, and search engines. Copying ======= Libgcrypt is distributed under the terms of the GNU Lesser General Public License (LGPLv2.1+). The helper programs as well as the documentation are distributed under the terms of the GNU General Public License (GPLv2+). The file LICENSES has notices about contributions that require that these additional notices are distributed. Support ======= For help on developing with Libgcrypt you should read the included manual and optional ask on the gcrypt-devel mailing list [1]. A listing with commercial support offers for Libgcrypt and related software is available at the GnuPG web site [2]. If you are a developer and you may need a certain feature for your project, please do not hesitate to bring it to the gcrypt-devel mailing list for discussion. Maintenance and development of Libgcrypt is mostly financed by donations; see . We currently employ 3 full-time developers, one part-timer, and one contractor to work on GnuPG and closely related software like Libgcrypt. Thanks ====== We like to thank all the people who helped with this release, be it testing, coding, translating, suggesting, auditing, administering the servers, spreading the word, and answering questions on the mailing lists. Also many thanks to all our donors [3]. Special thanks go to Jussi Kivilinna for all of his performance improvement work. For the GnuPG hackers, Werner p.s. This is an announcement only mailing list. Please send replies only to the gcrypt-devel 'at' gnupg.org mailing list. [1] https://lists.gnupg.org/mailman/listinfo/gcrypt-devel [2] https://www.gnupg.org/service.html [3] https://gnupg.org/donate/kudos.html [4] Interface changes relative to the 1.6.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_cipher_final NEW macro. GCRY_CIPHER_MODE_CFB8 NEW constant. GCRY_CIPHER_MODE_OCB NEW. GCRY_CIPHER_MODE_POLY1305 NEW. gcry_cipher_set_sbox NEW macro. gcry_mac_get_algo NEW. GCRY_MAC_HMAC_MD2 NEW. GCRY_MAC_HMAC_SHA3_224 NEW. GCRY_MAC_HMAC_SHA3_256 NEW. GCRY_MAC_HMAC_SHA3_384 NEW. GCRY_MAC_HMAC_SHA3_512 NEW. GCRY_MAC_POLY1305 NEW. GCRY_MAC_POLY1305_AES NEW. GCRY_MAC_POLY1305_CAMELLIA NEW. GCRY_MAC_POLY1305_SEED NEW. GCRY_MAC_POLY1305_SERPENT NEW. GCRY_MAC_POLY1305_TWOFISH NEW. gcry_md_extract NEW. GCRY_MD_FLAG_BUGEMU1 NEW [from 1.6.1]. GCRY_MD_GOSTR3411_CP NEW. GCRY_MD_SHA3_224 NEW. GCRY_MD_SHA3_256 NEW. GCRY_MD_SHA3_384 NEW. GCRY_MD_SHA3_512 NEW. GCRY_MD_SHAKE128 NEW. GCRY_MD_SHAKE256 NEW. gcry_mpi_ec_decode_point NEW. gcry_mpi_ec_sub NEW. GCRY_PK_EDDSA NEW constant. GCRYCTL_GET_TAGLEN NEW. GCRYCTL_SET_SBOX NEW. GCRYCTL_SET_TAGLEN NEW. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 180 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ Gnupg-announce mailing list Gnupg-announce at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-announce From joerg.krause at embedded.rocks Sat Apr 16 09:42:56 2016 From: joerg.krause at embedded.rocks (=?ISO-8859-1?Q?J=F6rg?= Krause) Date: Sat, 16 Apr 2016 09:42:56 +0200 Subject: libgpg-error: Replace syscfg In-Reply-To: <87mvphmvn2.fsf@wheatstone.g10code.de> References: <1458511591.1998.59.camel@embedded.rocks> <877fgw6vru.fsf@wheatstone.g10code.de> <1458560622.13321.21.camel@embedded.rocks> <87mvphmvn2.fsf@wheatstone.g10code.de> Message-ID: <1460792576.8200.28.camel@embedded.rocks> Dear Werner Koch, sorry for my late reply and many thanks for your feedback! On Di, 2016-03-29 at 12:22 +0200, Werner Koch wrote: > On Mon, 21 Mar 2016 12:43, joerg.krause at embedded.rocks said: > > > All the information?gen-posix-lock-obj provides are available at > > compile-time, so I do not see the necessity for a runtime tool to > > fetch > > It is a compile time tool and not a runtime tool Yes, the detection of the platform specific properties is done during build time. However, the README states that "the detection can't be done when cross-compiling", which is not true as the cross-toolchain knows all platform specific properties. Or do I miss something? > > > an internal change to libgpg-error does not introduce a long > > > chain of > > > required ABI changes to all software dependent on libgpg-error. > > > > I understand! However, as I said, there is no difference in the end > > between using gen-posix-lock-obj/syscfg/mkheader generating the > > lock > > part of gpg-error.h and defining the lock object directly in gpg- > > error.h. Both produces the same compilation unit. > > That is true for the current implementaion.??However, this defines a > specific ABI which independent of the actual implementation.??Thus we > can add any time change the internal implementation without affecting > the ABI. Sorry for my ignorance, but I'm not sure I understand the ABI part here. I know that {posix,w32}-lock-obj.h defines a LOCK_ABI_VERSION. Do you mean this by "specific ABI"? If so, the lock-obj is part of that ABI, and the implementation might change in the future, right? Is the problem here that I replaced in 'src/gpg-error.h.in' the '@inclu de:lock-obj@' by the?gpgrt_lock_t definition which might change in future implementations? However, I do not understand: "Thus we?can add any time change the internal implementation without affecting the ABI." What do you mean by changing the internal implementation? And how does a change does not affect the ABI? Best regards J?rg Krause From wk at gnupg.org Wed Apr 20 16:26:18 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 20 Apr 2016 16:26:18 +0200 Subject: The loopback pinentry Message-ID: <87wpnsfjat.fsf@wheatstone.g10code.de> Hi! Since version 2.1 GnuPG has a loopback pinentry mode which does not use the pinentry but sends the request for a passphrase back to the calling application (gpg or gpgsm). This feature was originally implemented for a very specific use case but it turns out that it is very useful for unattended use of GnuPG. To make use of this feature, gpg-agent requires the option --allow-loopback-pinentry. The rationale for requiring an option is that only gpg-agent and pinentry shall be responsible for the passphrase to protect a key. The loopback mode weakens this idea. However, in the majority of use cases gpg-agent is anyway run on the same machine and with the same permissions as gpg. Thus the need for an option to allow the use of the loopback pinentry mode is questionable. I propose to make --allow-loopback-pinentry the default and add an option --no-allow-loopback-pinentry, so that it is possible to disallow the use of the loopback pinentry. This is a simple change but some advanced use cases of GnuPG would benefit from this (e.g. Mailpile). Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 180 bytes Desc: not available URL: From dkg at fifthhorseman.net Wed Apr 20 18:33:52 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Wed, 20 Apr 2016 12:33:52 -0400 Subject: The loopback pinentry In-Reply-To: <87wpnsfjat.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> Message-ID: <87k2js1bpr.fsf@alice.fifthhorseman.net> Hi Werner-- On Wed 2016-04-20 10:26:18 -0400, Werner Koch wrote: > I propose to make --allow-loopback-pinentry the default and add an > option --no-allow-loopback-pinentry, so that it is possible to disallow > the use of the loopback pinentry. This is a simple change but some > advanced use cases of GnuPG would benefit from this (e.g. Mailpile). It seems like it's pretty easy for advanced users like Mailpile to set allow-loopback-pinentry directly for their running gpg-agent (if they need to do so) so that's not a good argument for changing the defaults. Is there a writeup of the expected threat model for gpg-agent? if not, it would be worth writing down a few paragraphs to help clarify decisions like this. --dkg From bre at pagekite.net Wed Apr 20 19:00:41 2016 From: bre at pagekite.net (Bjarni Runar Einarsson) Date: Wed, 20 Apr 2016 17:00:41 -0000 Subject: The loopback pinentry In-Reply-To: <87k2js1bpr.fsf@alice.fifthhorseman.net> References: <87k2js1bpr.fsf@alice.fifthhorseman.net> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Daniel! Daniel Kahn Gillmor wrote: > > I propose to make --allow-loopback-pinentry the default and add an > > option --no-allow-loopback-pinentry, so that it is possible to disallow > > the use of the loopback pinentry. This is a simple change but some > > advanced use cases of GnuPG would benefit from this (e.g. Mailpile). > > It seems like it's pretty easy for advanced users like Mailpile > to set allow-loopback-pinentry directly for their running > gpg-agent (if they need to do so) so that's not a good argument > for changing the defaults. Why do you assume we would run our own gpg-agent? The case where we ship gnupg and everything to a desktop user on OS X or Windows - yes, of course, we actually have no problems there, we can pretty much do whatever we like. It's when we want to play nice with desktop Linux users who already have gpg and a keychain and a desktop, but still want remote access to their Mailpile... that's the scenario where things get complicated. Those users would not be happy with a separate keychain/config/agent just for Mailpile, and they would also not be happy if we edited their main config, potentially other apps, their desktop integration or who knows what else. As far as I'm concerned this isn't about security - this is fixing a regression that took place in 2.0 which broke the ability to use gpg in an unattended/automated way. This proposal goes a long way to fixing that. Cheers, - Bjarni - -- PageKite.net lets your personal computer be part of the web. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJXF7W6AAoJEI4ANxYAz5SRJmsH/1URs92E27MAF9jXlntkDgr+ M75Qnm0fjNYgfGFhXiqI3eVrc6Do37dK5BoboQS4VK8FUvA6Na13updn0sbMl+UN RxF6U4BNQQNocC7yUfvSoo/O/hMlcUAHqQRZCBG9u74rslIbgiL/arj1SIXrp3HT 7gr5Y8AurZVZUb/y3FdAzjqUmpBBlxlZEREWjXmtBtUgx0F6eCYE9vgaYqVGEzzs PPuvXOgvRepsrfio7Xy/efVXaAUdfplhGYFTJkTQ4NJrO/xOaxTVdZTA8htqQ8CC mQ1U4bxseurjy2acC1myOTp7nV9VFhfXnVbULe+NGUYuxObMgeimS3Cism7qTog= =IRWG -----END PGP SIGNATURE----- From bre at pagekite.net Wed Apr 20 18:27:47 2016 From: bre at pagekite.net (Bjarni Runar Einarsson) Date: Wed, 20 Apr 2016 16:27:47 -0000 Subject: The loopback pinentry In-Reply-To: <87wpnsfjat.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello gnupg-devel! Werner Koch wrote: [snip] > > I propose to make --allow-loopback-pinentry the default and add > an option --no-allow-loopback-pinentry, so that it is possible > to disallow the use of the loopback pinentry. This is a simple > change but some advanced use cases of GnuPG would benefit from > this (e.g. Mailpile). > > > Salam-Shalom, > > Werner This would be fantastic; unstoppable pinentry is the largest single road-block that prevents Mailpile from working well with GnuPG 2.0 and up. All of the solutions we currently have on the table involve creating a custom gpg.conf for Mailpile or *editing* the user's gpg.conf to add the settings we need; neither of which are good solutions in our opinion. I would also like to point out that for users with gnupg 1.4 installed, changing this default is in no way reducing security - the desired behaviour is already available by falling back to gnupg 1.4 (as Mailpile currently does). Making automation easier (as Werner is suggesting here) is IMO key to making gpg 1.4 eventually go away. Thanks for looking at this, Werner. All the best, - Bjarni - -- PageKite.net lets your personal computer be part of the web. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJXF63rAAoJEI4ANxYAz5SReBwIAJu4UG1IwleNADC7ridW5dPz g+qLCU0pFHsZuXT6VFU37Qki1Vezd+tA5andycfGmTmqInFRMKWkxD2hHfZSPDMk sW/DaouArJW4qCtIG1meVOfTPq4RLMXX5czbCRdsxFbHMm6DtR3SwnBYJDAwiGBC +9LjQSNmyQ0u4qxl2mJN8E7ed1Z1dXhI5GyRnDcD1HHYQrQ15A2i8uX6Optox1c5 P+pbOqweGdQgDx7jCC/vlZyeGL1bs3eYHDnj2yeOvaMk7La4/HfnssqekZxXJ7cP CPORMiaVm6eKIEcmwkHt57oqdW/iMPF51kKsv1TM8xRFBYGt1fyJbZu6SUk7Bjw= =eqSv -----END PGP SIGNATURE----- From neal at walfield.org Wed Apr 20 21:32:40 2016 From: neal at walfield.org (Neal H. Walfield) Date: Wed, 20 Apr 2016 21:32:40 +0200 Subject: The loopback pinentry In-Reply-To: <87wpnsfjat.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> Message-ID: <87potk13fr.wl-neal@walfield.org> On Wed, 20 Apr 2016 16:26:18 +0200, Werner Koch wrote: > Since version 2.1 GnuPG has a loopback pinentry mode which does not use > the pinentry but sends the request for a passphrase back to the calling > application (gpg or gpgsm). This feature was originally implemented for > a very specific use case but it turns out that it is very useful for > unattended use of GnuPG. > > To make use of this feature, gpg-agent requires the option > --allow-loopback-pinentry. The rationale for requiring an option is > that only gpg-agent and pinentry shall be responsible for the passphrase > to protect a key. The loopback mode weakens this idea. However, in the > majority of use cases gpg-agent is anyway run on the same machine and > with the same permissions as gpg. Thus the need for an option to allow > the use of the loopback pinentry mode is questionable. > > I propose to make --allow-loopback-pinentry the default and add an > option --no-allow-loopback-pinentry, so that it is possible to disallow > the use of the loopback pinentry. This is a simple change but some > advanced use cases of GnuPG would benefit from this (e.g. Mailpile). Should allow-preset-passphrase also be the default? :) Neal From dkg at fifthhorseman.net Wed Apr 20 23:25:25 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Wed, 20 Apr 2016 17:25:25 -0400 Subject: The loopback pinentry In-Reply-To: References: <87k2js1bpr.fsf@alice.fifthhorseman.net> Message-ID: <87ega00y7u.fsf@alice.fifthhorseman.net> On Wed 2016-04-20 13:00:41 -0400, Bjarni Runar Einarsson wrote: > It's when we want to play nice with desktop Linux users who > already have gpg and a keychain and a desktop, but still want > remote access to their Mailpile... that's the scenario where > things get complicated. Those users would not be happy with a > separate keychain/config/agent just for Mailpile, and they would > also not be happy if we edited their main config, potentially > other apps, their desktop integration or who knows what else. So instead you're proposing to effectively silently edit everyone's main config, whether they use mailpile or not? aiui, mailpile is implemented in a browser, with the backend handled by a sensible web framework. fwiw, if i were to run mailpile on my local machine, i'd *rather* have gpg-agent prompt me out-of-band, and avoid having my secret key passphrase handled by both my web browser and by the web framework. But if mailpile really does need to use the loopback, why not detect that allow-loopback-pinentry isn't set, and offer to set it for the user? from a shell, that looks something like: if [ -z "$(gpgconf --list-options gpg-agent | \ awk -F: '/^allow-loopback-pinentry/{ print $10 }')" ]; then read -p 'mailpile needs allow-loopback-pinentry. can we set it? [y/N] " OK if [ "$OK" = y ]; then echo allow-loopback-pinentry:0:1 | gpgconf --change-options gpg-agent gpg-connect-agent reloadagent /bye fi fi or, as you said, you could run your own agent. In fact, even if the defaults change, won't mailpile need to do this kind of work anyway to detect a situation where the user has explicitly placed no-allow-loopback-pinentry in their gpg-agent.conf ? We're arguing about defaults here, not about functionality. doesn't mailpile already have the functionality it needs? why change the defaults? > As far as I'm concerned this isn't about security - this is > fixing a regression that took place in 2.0 which broke the > ability to use gpg in an unattended/automated way. This proposal > goes a long way to fixing that. I'm all for fixing regressions, but i don't see why we should change the defaults for this case. --dkg From bre at pagekite.net Thu Apr 21 01:04:08 2016 From: bre at pagekite.net (Bjarni Runar Einarsson) Date: Wed, 20 Apr 2016 23:04:08 -0000 Subject: The loopback pinentry In-Reply-To: <87ega00y7u.fsf@alice.fifthhorseman.net> References: <87ega00y7u.fsf@alice.fifthhorseman.net> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Daniel, tl;dr: Whenever an app *can* copy all the key material and do as it likes by changing GNUPG_HOME and writing out a custom gpg.conf (or edit gpg.conf directly), then it is it pretty clear that the current defaults for this setting provide no real security. They just making things inconvenient, driving developers like myself to hacky, dangerous workarounds or away from GnuPG entirely. I think everyone agrees that this scenario is the common case. Qubes would be an exception, if this changes for 2.2 we might want to reach out to them and make sure they are aware of the change. Are people aware of any other common cases where the agent is actually isolated and protected from other apps run by the same user? Those are the main points IMO. Discussion and answering individual points follow... Daniel Kahn Gillmor wrote: > > So instead you're proposing to effectively silently edit > everyone's main config, whether they use mailpile or not? No, we're talking about what should be the defaults for the next stable release. I am not sure 2.0 even has the functionality we're discussing, for some reason the GnuPG 2.0.28 on my box appears to have shipped with a man page (and info) that describes a bunch of 2.1 features that don't actually work. ;-) Many of the people who have compiled GnuPG 2.1 from source and use it regularly are probably on this list, so this is hopefully a good place to discuss whether they would consider this a good or bad thing for the next stable release. > aiui, mailpile is implemented in a browser, with the backend > handled by a sensible web framework. Mailpile is not implemented in a browser, it offers a web interface as one of its user interfaces. This means it can be accessed simultaneously from afar and/or locally, depending on the user. There's also a command-line interface which I use quite a bit. :-) > fwiw, if i were to run mailpile on my local machine, i'd > *rather* have gpg-agent prompt me out-of-band, and avoid having > my secret key passphrase handled by both my web browser and by > the web framework. That's your choice. It is a choice that means you won't be able to do certain actions over the network (when you are away from the desktop, you won't be able to fill out the pinentry). For some users that is certainly the right thing, especially when we consider signing and encrypting to be rare, meaningful actions. But if you want to routinely, as a matter of course, encrypt and sign everything, even if you're authoring it remotely using your mobile phone - this becomes a major barrier. Note that just because Mailpile wants loopback pinentry, that doesn't automatically mean it is going to default to sending passphrases over the network. It will frequently be used to manage passphrases within Mailpile itself and silently provide authentication as needed, without any user interaction at all. Especially for keys that were generated by Mailpile in the first place. I'd rather not generate them without a passphrase (so Mailpile generates a strong random one), so I still need a way to automate the authentication. Since my goal is to get people encrypting and signing more and more, I want to make it as convenient as possible. This is why I care a great deal about use cases that differ from the one you have described and differ quite a bit from the common ways GnuPG is currently used. Maybe that's bad, maybe it's good, it depends on your goals. :-) Making the defaults (in both apps) friendly to non-technical people, but providing knobs so the experts and folks with special needs can lock things down seems like a good way to do things. That *does* imply that you don't turn on all the lock-down features by default. Somewhere you draw a line and say "this is good enough". > But if mailpile really does need to use the loopback, why not > detect that allow-loopback-pinentry isn't set, and offer to set > it for the user? This is an option. I think it is a terrible one. As a matter of principle (and sane engineering) Mailpile shouldn't be editing your gpg.conf, ever. I don't want to speak for Neal and Werner, but after discussing with them, I did get the impression that they agree with me on this. > In fact, even if the defaults change, won't mailpile need to do > this kind of work anyway to detect a situation where the user > has explicitly placed no-allow-loopback-pinentry in their > gpg-agent.conf ? If a user has explicitly requested no loopback, then they probably have a good reason and Mailpile should honour that and gracefully fail in the remote scenarios the user has forbidden. If the user only ever wants pinentry to happen through official GnuPG interfaces, that is surely their choice and not one I want to circumvent. But a user that has never expressed a preference: is he really better served by the current defaults? I am not the first (or last) person to express frustration with how hard it is to automate certain things with GnuPG 2+. The current defaults rule out entire classes of interesting applications, for no obvious security benefit. Incidentally, saying "the user can just edit their config if they want to use those apps" is tantamount to saying "non-technical users are not allowed to use this software"... so I really hope nobody says that! :-) There are certainly cases where being able to lock down the setup and disallow 3rd party pinentry is important for security. Having the option to do so is useful. I just don't think that should be the default, since it is largely meaningless in the common case where all the apps run with the same UID and have direct access to the keychain anyway. Cheers, - Bjarni - -- PageKite.net lets your personal computer be part of the web. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJXGAr3AAoJEI4ANxYAz5SRJl8H/iFjcTuWLpZCylp5pEpQQIgc z5kEAp56+qPQdiuTVCWBcM39FIrdZMOa41zG5MLW3SOM+Vju1S7la4TFlKk8g0fc LtO38Ffw45vgOfxgkiScN+mAf2Rb73sNdkKIe6LiWn0hN1Vh4Y/n2nijKubJ5Sqb /RhRT1zSF9DdWOEoo9Z5kM3TD5QgTYrj3CDyEw6LhNjrKuEYbJTymkyuwyIma4sZ Bk4RBvwI7YaG6YFp3R/8wLvflCRnd6aCidDjIGgZeRUVhIe8flFPil2vs/GC35ai Ddw+57z2xtXqymvKB6cvuy9UHCDrWdA6bfbaq9gC1EJOCfMmzVA+BCq1mgftW4o= =Hg/F -----END PGP SIGNATURE----- From gniibe at fsij.org Thu Apr 21 01:25:53 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 21 Apr 2016 08:25:53 +0900 Subject: The loopback pinentry In-Reply-To: <87wpnsfjat.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> Message-ID: <57181001.1020004@fsij.org> On 04/20/2016 11:26 PM, Werner Koch wrote: > I propose to make --allow-loopback-pinentry the default and add an > option --no-allow-loopback-pinentry, so that it is possible to disallow > the use of the loopback pinentry. This is a simple change but some > advanced use cases of GnuPG would benefit from this (e.g. Mailpile). Are there any things (options and the protocol) for gpg-agent to control/record the use of loopback mode for forwarded requests? If so, I think that change of the default would be OK. My concern is that: The change of the default makes the remote access of private keys under gpg-agent rather easier. We need to setup things carefully (more) when we enable forwarding. and/or Modification of the protocol to distinguish remote client (forwarded connection) would be encouraged. Adding options for remote client handling would be needed?, perhaps. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Thu Apr 21 12:49:04 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 12:49:04 +0200 Subject: The loopback pinentry In-Reply-To: <87potk13fr.wl-neal@walfield.org> (Neal H. Walfield's message of "Wed, 20 Apr 2016 21:32:40 +0200") References: <87wpnsfjat.fsf@wheatstone.g10code.de> <87potk13fr.wl-neal@walfield.org> Message-ID: <87h9evck4f.fsf@wheatstone.g10code.de> On Wed, 20 Apr 2016 21:32, neal at walfield.org said: > Should allow-preset-passphrase also be the default? I don't think so. That preset passphrase tool was introduced for those who have a company/law policy that all keys need to be protected even if that protection key is stored on the system in the clear. From a security point of view this does not make sense. having the loopback pinentry mode, the preset-passphrase feature is not anymore needed and new applications should not use it. It is only for unattended use and thus a certain configuration is required, anyway. Before someone asks: The --allow-emacs-pinentry option should be kept because that new emacs mode has actual security implications and should thus not be enabled by default. I also consider that Emacs users can be expected to enter M-x f ~/.gnupg/gpg-agent.conf ;-) Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From patrick at enigmail.net Thu Apr 21 12:54:18 2016 From: patrick at enigmail.net (Patrick Brunschwig) Date: Thu, 21 Apr 2016 12:54:18 +0200 Subject: The loopback pinentry In-Reply-To: <87wpnsfjat.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> Message-ID: <76438a33-18d7-a9fa-1a2c-b95b78b49946@enigmail.net> On 20.04.16 16:26, Werner Koch wrote: [...] > I propose to make --allow-loopback-pinentry the default and add an > option --no-allow-loopback-pinentry, so that it is possible to disallow > the use of the loopback pinentry. This is a simple change but some > advanced use cases of GnuPG would benefit from this (e.g. Mailpile). This is from my point of view a good idea. As GnuPG these days is very often used by other tools, this makes it a lot easier for the tool developers to actually use the loopback-pinentry. -Patrick From wk at gnupg.org Thu Apr 21 12:52:30 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 12:52:30 +0200 Subject: The loopback pinentry In-Reply-To: <57181001.1020004@fsij.org> (NIIBE Yutaka's message of "Thu, 21 Apr 2016 08:25:53 +0900") References: <87wpnsfjat.fsf@wheatstone.g10code.de> <57181001.1020004@fsij.org> Message-ID: <87d1pjcjyp.fsf@wheatstone.g10code.de> On Thu, 21 Apr 2016 01:25, gniibe at fsij.org said: > Are there any things (options and the protocol) for gpg-agent to > control/record the use of loopback mode for forwarded requests? Forward mode (cia --extra-socket or --web-socket) do not allow the loopback mode or any other pinentry mode. The mode is selection using an Assuan OPTION command and the handler starts this way: if (!strcmp (key, "agent-awareness")) { /* The value is a version string telling us of which agent version the caller is aware of. */ ctrl->server_local->allow_fully_canceled = gnupg_compare_version (value, "2.1.0"); } else if (ctrl->restricted) { err = gpg_error (GPG_ERR_FORBIDDEN); } /* All options below are not allowed in restricted mode. */ (RESTRICTED indicates a forwarded connection) > If so, I think that change of the default would be OK. Well, it is fortunately not applicable. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Apr 21 13:07:57 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 13:07:57 +0200 Subject: The loopback pinentry In-Reply-To: <87k2js1bpr.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Wed, 20 Apr 2016 12:33:52 -0400") References: <87wpnsfjat.fsf@wheatstone.g10code.de> <87k2js1bpr.fsf@alice.fifthhorseman.net> Message-ID: <87y487b4oi.fsf@wheatstone.g10code.de> On Wed, 20 Apr 2016 18:33, dkg at fifthhorseman.net said: > It seems like it's pretty easy for advanced users like Mailpile to set > allow-loopback-pinentry directly for their running gpg-agent (if they > need to do so) so that's not a good argument for changing the defaults. Right, we could also add it to gpgconf so that even GUIs can easily change that. I briefly chatted with Bjarni about this and his main concern is that this is an extra step required and folks will forget about this and use for example ad-hoc workarounds instead. If we can make common unattended use cases easier by using other defaults, I believe that will improve the overall security of systems. I am not aware of a threat that option may counter - I introduced it (or well suggested that to Ben Kibbey), to make sure the loopback mode won't break anything. That was easier than to think about possible consequences. Due to the introduction of the restricted modes (--extra-socket) we have a working method for remote access and thus I consider loopback mode safe for now. If we start to use a different (side-)account for gpg-agent we may need to reconsider this. However, we can and should disable loopback mode then on a per-connection base. > Is there a writeup of the expected threat model for gpg-agent? if not, > it would be worth writing down a few paragraphs to help clarify No there is no writeup. Yes, it should be eventually be written. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Apr 21 13:16:31 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 13:16:31 +0200 Subject: The loopback pinentry In-Reply-To: (Bjarni Runar Einarsson's message of "Wed, 20 Apr 2016 17:00:41 -0000") References: <87k2js1bpr.fsf@alice.fifthhorseman.net> Message-ID: <87twivb4a8.fsf@wheatstone.g10code.de> On Wed, 20 Apr 2016 19:00, bre at pagekite.net said: > As far as I'm concerned this isn't about security - this is > fixing a regression that took place in 2.0 which broke the > ability to use gpg in an unattended/automated way. This proposal > goes a long way to fixing that. I feel that I need to comment on this despite that it is a bit off-topic: No, it did not broke the ability for unattended use, but changed the way to do it. With 2.0.8 from 2007, we introduced the envvar PINENTRY_USER_DATA to make unattended use with a non-fixed passphrase possible. What this envvar, along with a custom Pinentry does, is the same as what the loopback pinentry modes provides - just using a different programming model. This was for examples used for an S/MIME based university web mail system. For the OpenPGP (gpg) from GnuPG 2.0, the gpg-agent was only used as a passphrase cache and gpg's --passphrase-fd kept working like in 1.4. Only since 2.1, gpg-agent takes responsibility for the private keys and thus we have a larger change - but also the loopback mode. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Apr 21 14:06:07 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 14:06:07 +0200 Subject: The loopback pinentry In-Reply-To: (Bjarni Runar Einarsson's message of "Wed, 20 Apr 2016 23:04:08 -0000") References: <87ega00y7u.fsf@alice.fifthhorseman.net> Message-ID: <87oa93b1zk.fsf@wheatstone.g10code.de> On Thu, 21 Apr 2016 01:04, bre at pagekite.net said: > Qubes would be an exception, if this changes for 2.2 we might > want to reach out to them and make sure they are aware of the Okay. Let's figure out their needs. Anyone from Qubes reading this thread? > change. Are people aware of any other common cases where the > agent is actually isolated and protected from other apps run by I doubt that there is proper SE_Linux support. Some time agod we talked here about using a side-avvount for the agent, but that is a future thing. dkg: Are you considering this as an option for Stretch? > we're discussing, for some reason the GnuPG 2.0.28 on my box > appears to have shipped with a man page (and info) that describes > a bunch of 2.1 features that don't actually work. ;-) The miracles of conditional Texinfo compilation - sorry. > place. I'd rather not generate them without a passphrase (so > Mailpile generates a strong random one), so I still need a way to > automate the authentication. Please keep in mind that the passphrase is more of fail-safe feature than a everyday protection. If you do not want that a key is used make sure that the key can't be used. I can imagine a feature to mark keys available only for certain types of sessions - the question is how to identify such a session. Right now we have a standard sessions and restricted session via --extra-socket. We may be abale to extend this system. But not for 2.2. > features by default. Somewhere you draw a line and say "this is > good enough". Actually this is the new poilicy we try to implement: Make GnuPG as safe as possible by default but for extra saftey, which anyway requires some kind of training, require the setting of an option. > I don't want to speak for Neal and Werner, but after discussing > with them, I did get the impression that they agree with me on > this. In general, yes. For certain options I would not mind, if a tool re-configures that option to a more sensible value. But if this is the case, we can also chnage the default for that option. > If a user has explicitly requested no loopback, then they > probably have a good reason and Mailpile should honour that and > gracefully fail in the remote scenarios the user has forbidden. There a lot of other options you can enable to make things go wrong. Those who play with the options should know what they do. > automate certain things with GnuPG 2+. The current defaults rule > out entire classes of interesting applications, for no obvious > security benefit. If we want to replace 1.4 by 2.x also for servers we should make it easy. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Apr 21 14:25:02 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 21 Apr 2016 14:25:02 +0200 Subject: The loopback pinentry In-Reply-To: <76438a33-18d7-a9fa-1a2c-b95b78b49946@enigmail.net> (Patrick Brunschwig's message of "Thu, 21 Apr 2016 12:54:18 +0200") References: <87wpnsfjat.fsf@wheatstone.g10code.de> <76438a33-18d7-a9fa-1a2c-b95b78b49946@enigmail.net> Message-ID: <87d1pjb141.fsf@wheatstone.g10code.de> On Thu, 21 Apr 2016 12:54, patrick at enigmail.net said: > This is from my point of view a good idea. As GnuPG these days is very > often used by other tools, this makes it a lot easier for the tool > developers to actually use the loopback-pinentry. However, Enigmail should not use that, because TB it is a plain GUI application. By not using Pinentry you would present the user a different interface than other applications and features[1] like GNOME's integration with the login password won't work. Shalom-Salam, Werner [1] I pondered to prefix it with "mis-" but GNOME folks have selected different trade-offs between security and user experience. -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From patrick at enigmail.net Thu Apr 21 15:29:08 2016 From: patrick at enigmail.net (Patrick Brunschwig) Date: Thu, 21 Apr 2016 15:29:08 +0200 Subject: The loopback pinentry In-Reply-To: <87d1pjb141.fsf@wheatstone.g10code.de> References: <87wpnsfjat.fsf@wheatstone.g10code.de> <76438a33-18d7-a9fa-1a2c-b95b78b49946@enigmail.net> <87d1pjb141.fsf@wheatstone.g10code.de> Message-ID: On 21.04.16 14:25, Werner Koch wrote: > On Thu, 21 Apr 2016 12:54, patrick at enigmail.net said: > >> This is from my point of view a good idea. As GnuPG these days is very >> often used by other tools, this makes it a lot easier for the tool >> developers to actually use the loopback-pinentry. > > However, Enigmail should not use that, because TB it is a plain GUI > application. By not using Pinentry you would present the user a > different interface than other applications and features[1] like GNOME's > integration with the login password won't work. Very true. I didn't say that Enigmail would use it ;-). -Patrick From justus at g10code.com Thu Apr 21 17:13:34 2016 From: justus at g10code.com (Justus Winter) Date: Thu, 21 Apr 2016 17:13:34 +0200 Subject: A new test framework: request for comments and testing Message-ID: <20160421151334.2180.54568@thinkbox.jade-hamburg.de> Hello, I have been working on a new test framework at the beginning of the year. We perceived two main problems with the current Bourne shell-based test framework: * we cannot run it on Windows * writing shell scripts that are portable even across POSIXish systems is a challenge (* the language is not very nice, leading to brittle code with a lot of copying) So we sat down at the Chaos Communication Congress and came up with the idea of using TinySCHEME, a very small and self-contained interpreter. My task was to evaluate the feasibility of that approach. One of the concerns was that choosing Scheme over Bourne shell will be an higher barrier to writing tests. So I took TinySCHEME, created bindings for GnuPGs platform abstractions, and ported the OpenPGP test suite (tests/openpgp) to my new interpreter to make sure that I implemented enough features, like process management. So a test that would look like this with the old framework ~~~ snip ~~~ . $srcdir/defs.inc || exit 3 info Checking decryption of supplied files for i in $plain_files ; do progress $i $GPG -o y --yes $srcdir/$i.asc cmp $i y || error "$i: mismatch" done progress_end ~~~ snap ~~~ can now be expressed like this: ~~~ snip ~~~ (load (with-path "defs.scm")) (for-each-p "Checking decryption of supplied files" (lambda (name) (tr:do (tr:open (in-srcdir (string-append name ".asc"))) (tr:gpg "" '(--yes)) (tr:assert-identity name))) plain-files) ~~~ snap ~~~ And while it might be a little more verbose I believe the advantages outweigh any inconveniences: * it is completely self-contained, doesn't rely on e.g. cmp * it works on Windows * one has a powerful little language at hand facilitating code reuse * robust error handling I have tested the code on Hurd, Linux, and Windows. Please test this patch series on any weird and wonderful platform that you have access to. Using it is easy, just do make check. I pushed my work periodically to the GnuPG repository at git.gnupg.org. The latest iteration is in the branch 'justus/scm-9'. Please accept my apologies for not communicating earlier what I was doing and where we want to go. We plan to merge this after the 2.1.12 release. Please let me know what you think and how it breaks on your favorite platform. Cheers, Justus From dkg at fifthhorseman.net Thu Apr 21 22:29:06 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Thu, 21 Apr 2016 16:29:06 -0400 Subject: The loopback pinentry In-Reply-To: References: <87ega00y7u.fsf@alice.fifthhorseman.net> Message-ID: <8760va1zal.fsf@alice.fifthhorseman.net> Hi Bjarni-- thanks for the detailed response, and for all the quality engineering you're putting into mailpile. I think we still disagree but i can see where you're coming from. a few thoughts: On Wed 2016-04-20 19:04:08 -0400, Bjarni Runar Einarsson wrote: > tl;dr: Whenever an app *can* copy all the key material and do as > it likes by changing GNUPG_HOME and writing out a custom gpg.conf > (or edit gpg.conf directly), then it is it pretty clear that the > current defaults for this setting provide no real security. They > just making things inconvenient, driving developers like myself > to hacky, dangerous workarounds or away from GnuPG entirely. I > think everyone agrees that this scenario is the common case. > > Qubes would be an exception, if this changes for 2.2 we might > want to reach out to them and make sure they are aware of the > change. Are people aware of any other common cases where the > agent is actually isolated and protected from other apps run by > the same user? in some sense, this isn't a question about the agent, but a question about the entirety of $GNUPGHOME, right? as long as the contents of $GNUPGHOME/private-keys-v1.d/ is available to a process, that process can mount a passphrase-guessing attack against the secret key material. The agent is essentially a convenient abstraction that allows well-behaving programs to remain ignorant of the specifics of $GNUPGHOME/private-keys-v1.d. It also happens that this same convenient abstraction can be used to place the private-keys-v1.d in an a location otherwise inaccessible to the processes that request access to those keys, forcing all access through the agent. This isolation is one of the main security promises offered by cryptographic agents. it's similar to the isolation you get from using a smartcard or HSM, but based on operating system isolation instead of hardware isolation. We haven't been able to make use of that promise in gpg for OpenPGP until the 2.1 branch moved all the secret key access into the agent. We're on the cusp of being able to make that promise a reality (the qubes approach is an example), and i'd really like to make sure it's possible and we don't encourage people to deploy code that is hard to use with this isolation.. Here's an attempt at writing a short description of the goals of an isolated cryptographic agent: -------- A cryptographic agent should control access to secret key material. The agent permits use of the secret key material by a supplicant without providing a copy of the secret key material to the supplicant. An isolated cryptographic agent separates the request for use of secret key material from permission for use of secret key material. That is, the system or process requesting use of the key (the "supplicant") can be denied use of the key by the owner/operator of the agent (the "owner"), which the supplicant has no control over. One way of enforcing this split is a per-key or per-session passphrase, known only by the owner, which must be supplied to the agent to permit the use of the secret key material. Another way is with an out-of-band permission mechanism (e.g. a button or GUI interface that the owner has access to, but the supplicant does not). The rationale for this separation is that it allows access to the secret key to be tightly controled and audited, and it doesn't permit the the supplicant to either copy the key or to override the owner's intentions. -------- Does this make sense? I'm happy to see suggestions for other ways to describe the goals of an isolated agent. > Mailpile is not implemented in a browser, it offers a web > interface as one of its user interfaces. This means it can be > accessed simultaneously from afar and/or locally, depending on > the user. There's also a command-line interface which I use quite > a bit. :-) thanks for the clarification, i hadn't realized there was an additional command-line interface. > That's your choice. It is a choice that means you won't be able > to do certain actions over the network (when you are away from > the desktop, you won't be able to fill out the pinentry). For > some users that is certainly the right thing, especially when we > consider signing and encrypting to be rare, meaningful actions. I think you mean signing and decrypting, right? These are the two primary actions that the user takes with their secret key material, which is what is protected by the passphrase. > Note that just because Mailpile wants loopback pinentry, that > doesn't automatically mean it is going to default to sending > passphrases over the network. It will frequently be used to > manage passphrases within Mailpile itself and silently provide > authentication as needed, without any user interaction at all. > Especially for keys that were generated by Mailpile in the first > place. I'd rather not generate them without a passphrase (so > Mailpile generates a strong random one), so I still need a way to > automate the authentication. I'm a little confused by this -- if mailpile is generating the keys, and selecting the passphrase, and hiding all of this from the user, then surely mailpile will be operating its own gpg-agent, in which case you can control the configuration. right? The case we're talking about is a case where mailpile is interacting with an existing keyring and an existing agent, right? > Since my goal is to get people encrypting and signing more and > more, I want to make it as convenient as possible. This is why I > care a great deal about use cases that differ from the one you > have described and differ quite a bit from the common ways GnuPG > is currently used. Maybe that's bad, maybe it's good, it depends > on your goals. :-) i share your goals! :) > Incidentally, saying "the user can just edit their config if they > want to use those apps" is tantamount to saying "non-technical > users are not allowed to use this software"... so I really hope > nobody says that! :-) I definitely didn't say that -- i just observed that an application that is incompatible with isolated agent use, which has access to the configuration settings for gpg-agent, and which asks the user for permission to modify the configuration once as part of account setup, and does that configuration modification via well-documented interfaces like gpgconf, seems entirely sensible to me. (and of course, if the initial setup is entirely controlled by mailpile and it's not interacting with an existing keyring, then setting that configuration without asking is also reasonable) --dkg From bre at pagekite.net Fri Apr 22 00:31:49 2016 From: bre at pagekite.net (Bjarni Runar Einarsson) Date: Thu, 21 Apr 2016 22:31:49 -0000 Subject: The loopback pinentry In-Reply-To: <8760va1zal.fsf@alice.fifthhorseman.net> References: <8760va1zal.fsf@alice.fifthhorseman.net> Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello :) Please accept my apologies for how long this is... again! Daniel Kahn Gillmor wrote: > The agent is essentially a convenient abstraction that [...] > can be used to place the > private-keys-v1.d in an a location otherwise inaccessible to > the processes that request access to those keys, forcing all > access through the agent. > > This isolation is one of the main security promises offered by > cryptographic agents. it's similar to the isolation you get > from using a smartcard or HSM, but based on operating system > isolation instead of hardware isolation. Yes, and it's a great idea and a great feature. I would actually much prefer Mailpile users be able to make use of this architecture as much as possible, which is one of the reasons I'd rather not run my own agent. Unfortunately, Mailpile (and any network server) is incompatible with complete isolation, since there is no standard out-of-band way to request permission (a passphrase, pinentry) over the network. It necessarily must be in-band in these cases, and I think network servers are such fantastically useful things that GnuPG shouldn't rule them out by default. That does not render the other benefits and protections afforded by the agent architecture worthless. You can still share keys between apps, and you can still follow best practices to isolate and protect the key material and crypto operations. The user can still use other channels to revoke any granted permissions (by changing the passphrase). I want Mailpile users to have all of those things, so I don't want Mailpile to have a dedicated agent. I want it to talk to the shared GnuPG, trusting the distro to lock it down and secure it as well as possible in each instance. Of course if it's locked down and secured to the point that Mailpile can't function, then I'll be sad... and that's what this discussion is about, I guess. Regarding key access and passphrases: The need for loopback pinentry could be lessened and better managed if it were possible to specify per-key and per-app (or per long-lived session) credentials (per-app passphrases for example, or per-key pinentry policies). Does the current agent support such things? Can an app request pinentry authentication and get back a token which allows long-term access to that key (and only that key), which the user can then revoke as needed? I don't actually want Mailpile to know the user's passphrase either, if I can avoid it. I just don't know of a way to avoid it - - yet! (An example of this sort of thing in the real world: GMail allows the user to generate a per-device password for logging in to IMAP, which means the IMAP access can be revoked for a single device without the user needing to change their main credentials (I hope to "borrow" this idea for Mailpile in various forms). A network-service-friendly GnuPG agent could well offer similar features.) A different access-token idea: A lesser, weaker access token implementation would be to require a token in order to use the loopback passphrase mechanism itself. Mailpile would need to request that token on setup, and the user would need to grant permission using an out-of-band agent dialog. This would require a bunch of new code in GnuPG, but would be a middle ground between "default forbidden" and "default allowed": "default ask". I don't know if it's justified; my gut feeling would be that an OS like Qubes would use "default ask", but a normal Linux distro that doesn't really provide isolation anyway should still use "default allowed", for the reasons I discussed in my last message. [isolated agent description snipped] > Does this make sense? I'm happy to see suggestions for other > ways to describe the goals of an isolated agent. I think you captured it reasonably well. :-) > I think you mean signing and decrypting, right? These are the > two primary actions that the user takes with their secret key > material, which is what is protected by the passphrase. Yes. My wording was imprecise; I tend to see signing and encrypting as a single operation, since that is what I usually do. I am also sloppy and talk about "encrypting" when I mean the full cycle of encrypting and decrypting. One is worthless without the other, after all. Sorry about the confusion. > I'm a little confused by this -- if mailpile is generating the > keys, and selecting the passphrase, and hiding all of this from > the user, then surely mailpile will be operating its own > gpg-agent, in which case you can control the configuration. > right? I don't *want* to run my own agent. Ever! I had expected to run my own agent *anyway*, because I feared it would be impossible to get the default GnuPG to cooperate. I don't want to and I consider it a messy last-resort hack, but that was where I was headed, and was asking Neal for advice on how best to do it... when he (and Werner) talked me out of it. :-) They pointed out that the loopback pinentry feature could solve the problem without resorting to agent proliferation and GNUPG_HOME hacks, and here we are discussing whether the rest of the community agrees. I can still go back to my hacks if necessary. > once as part of account setup, and does that configuration > modification via well-documented interfaces like gpgconf, seems > entirely sensible to me. This *might* be safe in this particular case, but in general, if apps make a habit of reconfiguring gpg.conf (with or without user permission, users in general will have no idea what they are agreeing to and will just click OK until the annoying popups go away), then that sets the stage for apps breaking either user security or the features other apps depend upon. As a matter of principle, I just don't want to do this sort of thing. Cheers, - Bjarni - -- PageKite.net lets your personal computer be part of the web. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJXGVTjAAoJEI4ANxYAz5SReT8IAItEQBFzTyMzlPgSi5QA9TRB MrU4w5jG1+QjNA+L10UFNVvucFUtHhVh+miwiI1NsXCY+Sg0HXtE6AZqkwTzOcKp 6a7EbOKfxGlN0FsDl1/28lAUelY1RoYka8FlyzDnn28gZN/xnjx8zkw++uYZUqpp C2KqY+dWLSktxANyOQuQVKaROfs9UPVdkYbf/ltxaFVbsHWWz5nDgrFtCLHjSu1V N6KkTtlT+9vcC8+iFJ4REOEHMraH8djQ4hp5y3PvZX0HG7N/DLKRBibivo0BRNNw f6kJmlDHWOSJRKL6EPiiVR6WoSx7uoLltLGVSLoIBGesv7vsPd46hD2/FuUA8Y0= =RLeQ -----END PGP SIGNATURE----- From dkg at fifthhorseman.net Fri Apr 22 06:43:56 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 22 Apr 2016 00:43:56 -0400 Subject: [LIBGPG-ERROR PATCH] add syscfg alias for powerpc-unknown-linux-gnuspe Message-ID: <1461300236-25710-1-git-send-email-dkg@fifthhorseman.net> See https://buildd.debian.org/status/fetch.php?pkg=libgpg-error&arch=powerpcspe&ver=1.21-2&stamp=1458593907, which produces the same header as powerpc-unknown-linux-gnu --- src/mkheader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mkheader.c b/src/mkheader.c index 0d3d6ba..64d0904 100644 --- a/src/mkheader.c +++ b/src/mkheader.c @@ -82,6 +82,7 @@ canon_host_triplet (const char *triplet) {"i486-pc-kfreebsd-gnu", "i686-pc-kfreebsd-gnu"}, {"i586-pc-kfreebsd-gnu"}, {"x86_64-pc-linux-gnuhardened1", "x86_64-pc-linux-gnu" }, + {"powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu" }, { NULL } }; -- 2.8.0.rc3 From wk at gnupg.org Fri Apr 22 09:06:59 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 22 Apr 2016 09:06:59 +0200 Subject: [LIBGPG-ERROR PATCH] add syscfg alias for powerpc-unknown-linux-gnuspe In-Reply-To: <1461300236-25710-1-git-send-email-dkg@fifthhorseman.net> (Daniel Kahn Gillmor's message of "Fri, 22 Apr 2016 00:43:56 -0400") References: <1461300236-25710-1-git-send-email-dkg@fifthhorseman.net> Message-ID: <87y48686ln.fsf@wheatstone.g10code.de> On Fri, 22 Apr 2016 06:43, dkg at fifthhorseman.net said: > + {"powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu" }, Pushed. Thanks. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Fri Apr 22 20:34:41 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 22 Apr 2016 14:34:41 -0400 Subject: gpgv: timestamps, validity, expiration, and revocation Message-ID: <87a8klxzjy.fsf@alice.fifthhorseman.net> hey GnuPG folks-- the gpgv man page (in all three supported branches) says: > gpgv assumes that all keys in the keyring are trustworthy. That does > also mean that it does not check for expired or revoked keys. In addition to this, gpgv appears to be OK with signatures made in the future. But it's not that gpgv doesn't care about timestamps at all: 0) it refuses to check signatures made by keys whose certificates indicate that they were created in the future (that is, where the key was created after "now"), and 1) it refuses to check signatures where the signature itself appears to have been created before the key was created. The attached tarball contains: pubkey.gpg -- a binary-format 2048-bit RSA OpenPGP certificate C47D9EDFF117EE2AA11B162D017D715B3D0C4AF2.key -- the corresponding secret key (for reference/experimentation only) before.txt.asc -- clearsigned message made by the key before certificate creation time during.txt.asc -- clearsigned message made by the key between certificate creation and certificate expiration after.txt.asc -- clearsigned message made by the key after certificate expiration of these, gpg approves of during.txt.asc and after.txt.asc, but not before.txt.asc: 0 dkg at alice:~/gpgv-dates$ gpgv --keyring ./pubkey.gpg before.txt.asc gpgv: Signature made Mon 09 Nov 2015 12:00:03 AM EST using RSA key ID 848F642B gpgv: public key 848F642B is 165 days newer than the signature gpgv: Can't check signature: Time conflict 2 dkg at alice:~/gpgv-dates$ gpgv --keyring ./pubkey.gpg during.txt.asc gpgv: Signature made Fri 22 Apr 2016 02:22:38 PM EDT using RSA key ID 848F642B gpgv: Good signature from "test user " 0 dkg at alice:~/gpgv-dates$ gpgv --keyring ./pubkey.gpg after.txt.asc gpgv: Signature made Fri 08 Jul 2016 12:00:01 AM EDT using RSA key ID 848F642B gpgv: Good signature from "test user " 0 dkg at alice:~/gpgv-dates$ I think this is the wrong tradeoff, and not anything that reasonable use cases would want. I think gpgv should check for revoked or expired keys; if it assumes that all keys in the keyring are trustworthy, then why would it not be willing to rely on those keys' stated (and self-certified) expiration dates or revocation certificates? I'm particularly worried about this because i'm hoping that apt (and other package managers) will move to using gpgv for verification -- there's no reason for a verification-only context (like verifying signed package manifests) to need to bundle in all the complexity that goes with secret key handling. If gpgv doesn't handle these timestamp issues correctly, then package managers relying on gpgv can be subject to archive "freezing", slowing, or replay attacks. Is there a reason to keep the earlier, inconsistent behavior, or should i file a bug report tracking a fix for this? If the earlier behavior must remain in place, what is the GnuPG team's recommendation for systems that just need signature verification but want to respect expiration, revocation, timestamps, etc? --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: gpgv-dates.tgz Type: application/x-gtar-compressed Size: 3086 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 948 bytes Desc: not available URL: From info at chrisheitkamp.de Sun Apr 24 16:40:29 2016 From: info at chrisheitkamp.de (Christoph Heitkamp) Date: Sun, 24 Apr 2016 16:40:29 +0200 Subject: How to obtain a OpenPGP Card manufacturer id? Message-ID: <48804bbf-9ffb-2a78-fe53-d794acdb1519@chrisheitkamp.de> Hello, we want to deploy an OpenPGP card compatible applet to our hackerspace warpzone [1] member cards. We are going to deploy it onto 75..100 cards. According to the specification [2] an unique manufacturer id and S/N are needed. Is there an official way to obtain an manufacturer id from the FSF Europe? I have seen 0x1337 is assigned to Warsaw hackerspace - is it possible to use any free number? If yes I would pleased, if 0x2342 is assigned to us. Or should I use the unmanaged S/N range (FF00..FFFE)? Thank you. Regards, Christoph Heitkamp [1] https://www.warpzone.ms/ [2] http://g10code.com/docs/openpgp-card-3.0.pdf -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 455 bytes Desc: OpenPGP digital signature URL: From me at jojoob.de Sun Apr 24 21:05:05 2016 From: me at jojoob.de (Johannes Burk) Date: Sun, 24 Apr 2016 21:05:05 +0200 Subject: Does GPGME support no-literal, disable-mdc, enarmor/dearmor? Message-ID: <5158015E-C905-4C4A-85D0-9B2CCD8E21E8@jojoob.de> Is there a way in GPGME to encrypt without wrapping the input in a literal data packet (like the --no-literal option for gpg) and to disable MDC protection (like --disable-mdc)? I'm also missing an enarmor/dearmor function. If GPGME does not provide this, I'am asking for a simple alternative. From wk at gnupg.org Mon Apr 25 11:45:29 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 25 Apr 2016 11:45:29 +0200 Subject: How to obtain a OpenPGP Card manufacturer id? In-Reply-To: <48804bbf-9ffb-2a78-fe53-d794acdb1519@chrisheitkamp.de> (Christoph Heitkamp's message of "Sun, 24 Apr 2016 16:40:29 +0200") References: <48804bbf-9ffb-2a78-fe53-d794acdb1519@chrisheitkamp.de> Message-ID: <87wpnmyqbq.fsf@wheatstone.g10code.de> On Sun, 24 Apr 2016 16:40, info at chrisheitkamp.de said: > Is there an official way to obtain an manufacturer id from the FSF Europe? I am maintaining this for the FSF Europe anyway, so the easiest way is to write me ;-). Usually we like to have a snail address like warpzone e.V. Am Hawerkamp 31 48155 M?nster and a contact mail for our files. > If yes I would pleased, if 0x2342 is assigned to us. Well, you asked, it is not used, and the list is anyway short. Thus I have now registered *0x2342 for warpzone e.v.* > Or should I use the unmanaged S/N range (FF00..FFFE)? If now hackerspaces start to ask too often ID, I may eventually suggest to either use that range or share a new range range between hackerspaces and use an hackerspaces internal registry. I do not want that gnupg/g10/card-util.c turns into a hackerspace registry. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 180 bytes Desc: not available URL: From info at chrisheitkamp.de Mon Apr 25 17:55:14 2016 From: info at chrisheitkamp.de (Christoph Heitkamp) Date: Mon, 25 Apr 2016 17:55:14 +0200 Subject: How to obtain a OpenPGP Card manufacturer id? In-Reply-To: <87wpnmyqbq.fsf@wheatstone.g10code.de> References: <48804bbf-9ffb-2a78-fe53-d794acdb1519@chrisheitkamp.de> <87wpnmyqbq.fsf@wheatstone.g10code.de> Message-ID: <784d02a8-ee1d-3dd6-121b-0a6f34e26845@chrisheitkamp.de> Am 25.04.2016 um 11:45 schrieb Werner Koch: > I am maintaining this for the FSF Europe anyway, so the easiest way is > to write me ;-). Usually we like to have a snail address like > > warpzone e.V. > Am Hawerkamp 31 > 48155 M?nster > > and a contact mail for our files. Thank you for your fast response. The snail mail address is ok. The official mail of the hackerspace committee is office at warpzone.ms, but my mail address should be ok, too. > Well, you asked, it is not used, and the list is anyway short. Thus I > have now registered *0x2342 for warpzone e.v.* > If now hackerspaces start to ask too often ID, I may eventually suggest > to either use that range or share a new range range between > hackerspaces and use an hackerspaces internal registry. > I do not want that gnupg/g10/card-util.c turns into a hackerspace > registry. We would gladly share this prefix with other hackerspaces. IMHO most hackerspaces only need to deploy a small amount of cards. I would suggest to use the first 2 byte of the S/N to identify the hackerspace. I'm willing to maintain this list (maybe in a github repo). Regards, Christoph Heitkamp -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 455 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Mon Apr 25 18:28:38 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 25 Apr 2016 18:28:38 +0200 Subject: How to obtain a OpenPGP Card manufacturer id? In-Reply-To: <784d02a8-ee1d-3dd6-121b-0a6f34e26845@chrisheitkamp.de> (Christoph Heitkamp's message of "Mon, 25 Apr 2016 17:55:14 +0200") References: <48804bbf-9ffb-2a78-fe53-d794acdb1519@chrisheitkamp.de> <87wpnmyqbq.fsf@wheatstone.g10code.de> <784d02a8-ee1d-3dd6-121b-0a6f34e26845@chrisheitkamp.de> Message-ID: <87a8khy7nt.fsf@wheatstone.g10code.de> On Mon, 25 Apr 2016 17:55, info at chrisheitkamp.de said: > We would gladly share this prefix with other hackerspaces. IMHO most > hackerspaces only need to deploy a small amount of cards. > I would suggest to use the first 2 byte of the S/N to identify the > hackerspace. I'm willing to maintain this list (maybe in a github repo). Feel free to a add a page to wiki.gnupg.org for that purpose. I'll make gnupg print warpzone for now but if there are more hackerspaces, the printed name may change. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Apr 25 18:30:37 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 25 Apr 2016 18:30:37 +0200 Subject: [PATCH 3/3] common: Add support for the new extended private key format. In-Reply-To: <87zisuyldg.fsf@wheatstone.g10code.de> (Werner Koch's message of "Fri, 15 Apr 2016 16:52:59 +0200") References: <1460644872-8729-1-git-send-email-justus@g10code.com> <3052732.oQQdDzmVxa@esus> <87r3e71bmy.fsf@wheatstone.g10code.de> <1797729.zODfQSzL4g@esus> <87zisuyldg.fsf@wheatstone.g10code.de> Message-ID: <87inz5wt02.fsf@wheatstone.g10code.de> Hi, Justus has pushed the change so that we can eventually make use of that format. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz.