From dkg at fifthhorseman.net Tue Jan 2 22:25:03 2018 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Tue, 02 Jan 2018 16:25:03 -0500 Subject: [PATCH] build: Increase libassuan min version to 2.5.0 In-Reply-To: <87zi6bywhq.fsf@wheatstone.g10code.de> References: <87lghwwlsx.fsf@wheatstone.g10code.de> <87608zlqij.fsf@fifthhorseman.net> <87zi6bywhq.fsf@wheatstone.g10code.de> Message-ID: <87inckeyxc.fsf@fifthhorseman.net> On Fri 2017-12-22 09:53:21 +0100, Werner Koch wrote: > On Thu, 21 Dec 2017 22:28, dkg at fifthhorseman.net said: >> PS what i'd really *like* in terms of dependency creep is a new release >> of libgpg-error that includes yat2m and gpgscm, so i can make it a >> build-dependency of gnupg itself, and get the gnupg package out of > > I am slowly working in it but gpgscm has a lot og gnupg dependencies; > Some need to be ported to libgpg-error and other may better be > re-written in scheme as part of the gnupg test suite. > > If it is really urgent I could soon do a release with yat2m but without > gpgscm. it's not really urgent, but i would hope that transitioning to a standard form of yat2m would not block on the changes needed by gpgscm. --dkg From bernhard at intevation.de Thu Jan 4 17:13:16 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Thu, 4 Jan 2018 17:13:16 +0100 Subject: WKD spec, draft 05 Message-ID: <201801041713.20636.bernhard@intevation.de> Moin Werner, a happy new year to you and all GnuPG people! Just saw today that you have published a v05 of https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service (I like the diff tool [1] to check changes.) * What is a good way to track the development of the draft? Does the IETF offer a tool to send me an email if a new revision is published? Could you drop me (and the devel-list) an email if a new revision is there? * The new requirement for serving WELLKNOWN/policy to be able to detect the existence of the service makes sense to me. Especially because I believe that the draft should state that the server MUST prevent walking the list of available pubkeys for privacy reasons, for instance by disabling the directory display function of a web server. Can you add the statement to the next revision? Rationale for suggesting: MUST over SHOULD: I can see usecases where re-using the .well-known/openpgpkey/hu/ as way to publish all OpenPGP pubkeys at once, but I'd say that this is the exceptional case and there are better methods of publishing a set of pubkeys, e.g. by using a single file with serveral pubkeys or by generating a HTML page with all email addresses. * There is a typo in v05: The file contains keywords and optioanlly values probably should be The file contains keywords and optional values Best Regards, Bernhard [1] https://www.ietf.org/rfcdiff?url1=draft-koch-openpgp-webkey-service-04&url2=draft-koch-openpgp-webkey-service-05&difftype=--html -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 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: 473 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Fri Jan 5 13:13:37 2018 From: wk at gnupg.org (Werner Koch) Date: Fri, 05 Jan 2018 13:13:37 +0100 Subject: WKD spec, draft 05 In-Reply-To: <201801041713.20636.bernhard@intevation.de> (Bernhard Reiter's message of "Thu, 4 Jan 2018 17:13:16 +0100") References: <201801041713.20636.bernhard@intevation.de> Message-ID: <87a7xsqz9q.fsf@wheatstone.g10code.de> On Thu, 4 Jan 2018 17:13, bernhard at intevation.de said: > Just saw today that you have published a v05 of > https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service The old version was about to expire thus I published a revision. > * What is a good way to track the development of the draft? > Does the IETF offer a tool to send me an email if a new revision is > published? Could you drop me (and the devel-list) an email if a new I don't think so. It is recorded at the WG page https://tools.ietf.org/wg/openpgp/ But note that the latest rfc4880bis draft -03 https://datatracker.ietf.org/doc/draft-ietf-openpgp-rfc4880bis/ is not anymore record4d there. I assume this is because the IETF closed the WG (but not the mailing list). > * The new requirement for serving WELLKNOWN/policy to be able to detect > the existence of the service makes sense to me. Especially because I believe GnuPG uses it to detect whether a domain supports WKD at all. Since the last release Dirmngr caches this info but needs a way to check whether it is supported at all. > that the draft should state that the server MUST prevent walking > the list of available pubkeys for privacy reasons, for instance by disabling > the directory display function of a web server. These are public keys and testing for their existence is trivial as it it with all mail addresses. If someone wants to add an index file for this it is at their discretion and we should not impose a restriction on this. A SHOULD NOT would be okay, though. > * There is a typo in v05: Fixed. Thanks. 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: 227 bytes Desc: not available URL: From bernhard at intevation.de Mon Jan 8 08:48:41 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Mon, 8 Jan 2018 08:48:41 +0100 Subject: WKD spec, draft 05 In-Reply-To: <87a7xsqz9q.fsf@wheatstone.g10code.de> References: <201801041713.20636.bernhard@intevation.de> <87a7xsqz9q.fsf@wheatstone.g10code.de> Message-ID: <201801080848.49719.bernhard@intevation.de> Am Freitag 05 Januar 2018 13:13:37 schrieb Werner Koch: > >? that the draft should state that the server MUST prevent walking > > the list of available pubkeys for privacy reasons, for instance by > > disabling the directory display function of a web server. > > These are public keys and testing for their existence is trivial as it > it with all mail addresses. ? The problem ist not the pubkeys, but it can be used to detect all existing email addresses of an email domain (that have pubkeys). An advantage of WKD is that you do not need to publish your email address to everyone and it would get lost if people publish all the email addresses' pubkeys at once. > If someone wants to add an index file for this it is at their discretion > and we should not impose a restriction on this. I agree that it could be used in a good way, if done deliberately. So I was undecided over "MUST" or "SHOULD NOT" at first. Overal I like to design for the simple case and prevent unthoughtful default configuration and later in the wild use. I guess a number of sites will have a directory listing enabled by default, so I'd rather give them a clear hint to disable it. And sites you actually want to publish a list of the email addresses they serve should be required to do extra efforts. In addition I do not want WELLKNOWN/hu/ to become an interface to find all pubkeys for an email domain. So I'm favouring the "MUST" now. > A SHOULD NOT would be okay, though. Adding a "SHOULD NOT" and a mention in the security considerations is an improvement, thanks for adding it! Best Regards, Bernhard -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 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: 473 bytes Desc: This is a digitally signed message part. URL: From aheinecke at intevation.de Mon Jan 8 19:19:17 2018 From: aheinecke at intevation.de (Andre Heinecke) Date: Mon, 08 Jan 2018 19:19:17 +0100 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts Message-ID: <1830532.otWbhZNTya@esus> Hi, The pinentry-mode should be mentioned in my opinion in the doc / manpage of the passphrase options because they won't work if the pinentry-mode is not set to loopback. This is similar to the already mentioned --batch requirement. Attached Patch does this. Best 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-doc-Note-pinentry-mode-for-passphrase-opts.patch Type: text/x-patch Size: 2222 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: This is a digitally signed message part. URL: From dkg at fifthhorseman.net Mon Jan 8 22:54:35 2018 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 08 Jan 2018 16:54:35 -0500 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts In-Reply-To: <1830532.otWbhZNTya@esus> References: <1830532.otWbhZNTya@esus> Message-ID: <87d12k6mp0.fsf@fifthhorseman.net> On Mon 2018-01-08 19:19:17 +0100, Andre Heinecke wrote: > The pinentry-mode should be mentioned in my opinion in the doc / manpage of > the passphrase options because they won't work if the pinentry-mode is not set > to loopback. This is similar to the already mentioned --batch requirement. I agree with the sentiment behind this change. however, some of the wording can be improved: > Note that this passphrase is only used if the option @option{--batch} > -has also been given. This is different from GnuPG version 1.x. > +has also been given and @option{--pinentry-mode} has to be set to @code{loopback}. > +This is different from GnuPG version 1.x and 2.0.x. this should say something like "the requirement for loopback mode was introduced in GnuPG version 2.1.$whatever". That makes it clearer and less ambiguous to people who are trying to understand how to configure a bunch of systems with different versions installed. --dkg From aheinecke at intevation.de Tue Jan 9 08:52:07 2018 From: aheinecke at intevation.de (Andre Heinecke) Date: Tue, 09 Jan 2018 08:52:07 +0100 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts In-Reply-To: <87d12k6mp0.fsf@fifthhorseman.net> References: <1830532.otWbhZNTya@esus> <87d12k6mp0.fsf@fifthhorseman.net> Message-ID: <1660728.9KMfWaAYFe@esus> Hi, On Monday, January 8, 2018 4:54:35 PM CET Daniel Kahn Gillmor wrote: > this should say something like "the requirement for loopback mode was > introduced in GnuPG version 2.1.$whatever". That makes it clearer and > less ambiguous to people who are trying to understand how to configure a > bunch of systems with different versions installed. Attached is a Version that takes this into account. I simplifyied to "since Version 2.0 and since Version 2.1" There were some 2.1 versions where the agent had to be configured with allow-pinentry-loopback etc. but I think we can disregard such detail. Best 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-doc-Note-pinentry-mode-for-passphrase-opts.patch Type: text/x-patch Size: 2488 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Tue Jan 9 09:53:03 2018 From: wk at gnupg.org (Werner Koch) Date: Tue, 09 Jan 2018 09:53:03 +0100 Subject: WKD spec, draft 05 In-Reply-To: <201801080848.49719.bernhard@intevation.de> (Bernhard Reiter's message of "Mon, 8 Jan 2018 08:48:41 +0100") References: <201801041713.20636.bernhard@intevation.de> <87a7xsqz9q.fsf@wheatstone.g10code.de> <201801080848.49719.bernhard@intevation.de> Message-ID: <877esrl8gg.fsf@wheatstone.g10code.de> On Mon, 8 Jan 2018 08:48, bernhard at intevation.de said: > The problem ist not the pubkeys, but it can be used to detect all existing > email addresses of an email domain (that have pubkeys). An advantage You can do that with and without an index file. It might be easier with an index file because you can get the list of local-part hashes all at once. But in any case you need to compile a list of local-parts to test whether the has exists. However, spammers have more resources than everyone else and thus it does not really matter whether they do lots of https queries or simply sending test mails. >> A SHOULD NOT would be okay, though. > > Adding a "SHOULD NOT" and a mention in the security considerations is an > improvement, thanks for adding it! Thanks for suggesting this. 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: 227 bytes Desc: not available URL: From bernhard at intevation.de Tue Jan 9 10:10:18 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Tue, 9 Jan 2018 10:10:18 +0100 Subject: WKD spec, draft 05 In-Reply-To: <877esrl8gg.fsf@wheatstone.g10code.de> References: <201801041713.20636.bernhard@intevation.de> <201801080848.49719.bernhard@intevation.de> <877esrl8gg.fsf@wheatstone.g10code.de> Message-ID: <201801091010.18886.bernhard@intevation.de> Am Dienstag 09 Januar 2018 09:53:03 schrieb Werner Koch: > On Mon, ?8 Jan 2018 08:48, bernhard at intevation.de said: > > The problem ist not the pubkeys, but it can be used to detect all > > existing email addresses of an email domain (that have pubkeys). > You can do that with and without an index file. ?It might be easier with > an index file because you can get the list of local-part hashes all at > once. If you agree that it is harder without index file, than we are on the same page, as security economics is always about making some "attacks" a bit harder. > But in any case you need to compile a list of local-parts to test > whether the has exists. ?However, spammers have more resources than > everyone else and thus it does not really matter whether they do lots of > https queries or simply sending test mails. I guess some standards counter measures could be used to make it less feasable to walk all email address hashes if there are no index files. Server providers e.g could tarpit or auto-blacklist requestors based on requests to honey email addresses. So far I believe it does matter (at least a little bit). Best Regards, Bernhard -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 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: 473 bytes Desc: This is a digitally signed message part. URL: From marcoagpinto at mail.telepac.pt Tue Jan 9 14:47:10 2018 From: marcoagpinto at mail.telepac.pt (Marco A.G.Pinto) Date: Tue, 9 Jan 2018 13:47:10 +0000 Subject: Kleopatra - typo in bit size? Message-ID: <21eba509-6c39-b1b0-d90a-8310d9f9968e@mail.telepac.pt> Hello! While using the option to create a new pair of keys: [13:40] <+marcoagpinto> aheinecke: I believe I found a typo in Kleopatra [13:40] <+marcoagpinto> :) [13:40] <+marcoagpinto> in the crypto algorith names [13:40] <+marcoagpinto> let me try to find it [13:41] <+marcoagpinto> ACDSA [13:42] <+marcoagpinto> NIST P-256 [13:42] <+marcoagpinto> NIST P-384 [13:42] <+marcoagpinto> NIST P-521 [13:42] <+marcoagpinto> shouldn't it be "P-512" instead of "P-521"? Thanks! Kind regards from the Gpg4win pt_PT translator, ???????? >Marco A.G.Pinto ?????????? ---------------------- -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: emails_signature2017msc.png Type: image/png Size: 11632 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From dgouttegattat at incenp.org Tue Jan 9 16:38:49 2018 From: dgouttegattat at incenp.org (Damien Goutte-Gattat) Date: Tue, 9 Jan 2018 15:38:49 +0000 Subject: Kleopatra - typo in bit size? In-Reply-To: <21eba509-6c39-b1b0-d90a-8310d9f9968e@mail.telepac.pt> References: <21eba509-6c39-b1b0-d90a-8310d9f9968e@mail.telepac.pt> Message-ID: <3d40d1a6-0b19-8904-30f3-efc805786600@incenp.org> On 01/09/2018 01:47 PM, Marco A.G.Pinto wrote: > [13:42] <+marcoagpinto> NIST P-521 > [13:42] <+marcoagpinto> shouldn't it be "P-512" instead of "P-521"? No, it's really P-521. That's the name of the curve, which stems from the fact that the modulus for that curve is $2^{521} - 1$, as defined in . Damien -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From dkg at fifthhorseman.net Tue Jan 9 18:12:51 2018 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Tue, 09 Jan 2018 12:12:51 -0500 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts In-Reply-To: <1660728.9KMfWaAYFe@esus> References: <1830532.otWbhZNTya@esus> <87d12k6mp0.fsf@fifthhorseman.net> <1660728.9KMfWaAYFe@esus> Message-ID: <87po6j552k.fsf@fifthhorseman.net> On Tue 2018-01-09 08:52:07 +0100, Andre Heinecke wrote: > On Monday, January 8, 2018 4:54:35 PM CET Daniel Kahn Gillmor wrote: >> this should say something like "the requirement for loopback mode was >> introduced in GnuPG version 2.1.$whatever". That makes it clearer and >> less ambiguous to people who are trying to understand how to configure a >> bunch of systems with different versions installed. > > Attached is a Version that takes this into account. I simplifyied to "since > Version 2.0 and since Version 2.1" There were some 2.1 versions where the > agent had to be configured with allow-pinentry-loopback etc. but I think we can > disregard such detail. works for me. --dkg PS I'm seeing a "bad signature" from you on the received e-mails that include these patches. i dunno whether that's something you want to debug, but i'm happy to try to diagnose it with you off-list if you would find that useful. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 832 bytes Desc: not available URL: From ben at adversary.org Wed Jan 10 23:51:02 2018 From: ben at adversary.org (Ben McGinnes) Date: Thu, 11 Jan 2018 09:51:02 +1100 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts In-Reply-To: <87po6j552k.fsf@fifthhorseman.net> References: <1830532.otWbhZNTya@esus> <87d12k6mp0.fsf@fifthhorseman.net> <1660728.9KMfWaAYFe@esus> <87po6j552k.fsf@fifthhorseman.net> Message-ID: <20180110225102.3k4ykstv5v7fqsaq@adversary.org> On Tue, Jan 09, 2018 at 12:12:51PM -0500, Daniel Kahn Gillmor wrote: > > PS I'm seeing a "bad signature" from you on the received e-mails > that include these patches. i dunno whether that's something you > want to debug, but i'm happy to try to diagnose it with you > off-list if you would find that useful. Really? Both of those emails came up as "good signatures" for me, albeit with the usual warnings that identity couldn't be confirmed because I haven't signed or trusted Andre's key, but other than that it seemed fine. Regards, Ben P.S. You might need to refresh my own key since I recently added a new signing subkey. ;) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 228 bytes Desc: not available URL: From dkg at fifthhorseman.net Thu Jan 11 14:54:14 2018 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Thu, 11 Jan 2018 08:54:14 -0500 Subject: [PATCH] doc: Note pinentry-mode for passphrase opts In-Reply-To: <20180110225102.3k4ykstv5v7fqsaq@adversary.org> References: <1830532.otWbhZNTya@esus> <87d12k6mp0.fsf@fifthhorseman.net> <1660728.9KMfWaAYFe@esus> <87po6j552k.fsf@fifthhorseman.net> <20180110225102.3k4ykstv5v7fqsaq@adversary.org> Message-ID: <87efmw1oxl.fsf@fifthhorseman.net> On Thu 2018-01-11 09:51:02 +1100, Ben McGinnes wrote: > On Tue, Jan 09, 2018 at 12:12:51PM -0500, Daniel Kahn Gillmor wrote: >> >> PS I'm seeing a "bad signature" from you on the received e-mails >> that include these patches. i dunno whether that's something you >> want to debug, but i'm happy to try to diagnose it with you >> off-list if you would find that useful. > > Really? Both of those emails came up as "good signatures" for me, > albeit with the usual warnings that identity couldn't be confirmed thanks to Ben and Neal for the feedback, i'm now tracking the problem in a local toolchain -- I can confirm that i have at least one set of tools that does verify andre's signature correctly. I can follow up on list here if folks are interested once i've got a proper diagnosis. > because I haven't signed or trusted Andre's key, but other than that > it seemed fine. (nitpick: you should never need to "trust" Andre's key to verify signatures from it! i think you just mean that neither you nor anyone that you trust has directly certified Andre's key) --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 832 bytes Desc: not available URL: From dashohoxha at gmail.com Tue Jan 16 19:05:45 2018 From: dashohoxha at gmail.com (Dashamir Hoxha) Date: Tue, 16 Jan 2018 19:05:45 +0100 Subject: GSoC project about improving EasyGnuPG Message-ID: Hi, I have created a GSoC project about improving EasyGnuPG: https://wiki.debian.org/SummerOfCode2018/Projects/EasyGnuPG If anyone would like to be a co-mentor (there can be several ones) I would appreciate it. Thanks, Dashamir -------------- next part -------------- An HTML attachment was scrubbed... URL: From James.Bottomley at HansenPartnership.com Fri Jan 19 06:27:37 2018 From: James.Bottomley at HansenPartnership.com (James Bottomley) Date: Thu, 18 Jan 2018 21:27:37 -0800 Subject: [RFC 2/4] agent: add tpm specific functions In-Reply-To: <1516339524.3014.59.camel@HansenPartnership.com> References: <1516339524.3014.59.camel@HansenPartnership.com> Message-ID: <1516339657.3014.61.camel@HansenPartnership.com> This commit adds code to handle the three specific functions needed to make the agent TPM aware, namely the ability to load a key from shadow information, the ability to sign a digest with that key, the ability to decrypt with the key and the ability to import a key to the TPM. The TPM2 is a bit of an esoteric beast, so all TPM specific callouts are confined inside this code. Additionaly, it requires the tss2 library to function, so the code is designed such that if the library isn't present then all TPM functions simply fail. This allows the code to be compiled with TPM support, but not require that the support library be present on the system. Signed-off-by: James Bottomley --- agent/Makefile.am | 1 + agent/tpm2.c | 784 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ agent/tpm2.h | 22 ++ 3 files changed, 807 insertions(+) create mode 100644 agent/tpm2.c create mode 100644 agent/tpm2.h diff --git a/agent/Makefile.am b/agent/Makefile.am index ce29462b2..bc3d43a0f 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -51,6 +51,7 @@ gpg_agent_SOURCES = \ protect.c \ trustlist.c \ divert-scd.c \ + tpm2.c \ cvt-openpgp.c cvt-openpgp.h \ call-scd.c \ learncard.c diff --git a/agent/tpm2.c b/agent/tpm2.c new file mode 100644 index 000000000..1df22e2a8 --- /dev/null +++ b/agent/tpm2.c @@ -0,0 +1,784 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../common/i18n.h" +#include "../common/sexp-parse.h" + +#include +#include +#include +#include +#include +#include + +/* List of tss2 functions we use. This is macro jiggery-pokery: + * the F argument gives us the ability to run an arbitrary macro over + * the function list as for each function do macro F */ +#define _TSS2_LIST(F) \ + F(TSS_Create); \ + F(TSS_SetProperty); \ + F(TSS_Execute); \ + F(TSS_ResponseCode_toString); \ + F(TPM2B_PUBLIC_Unmarshal); \ + F(TPM2B_PRIVATE_Unmarshal); \ + F(TSS_TPM2B_PUBLIC_Marshal); \ + F(TSS_TPMT_PUBLIC_Marshal); \ + F(TSS_TPM2B_PRIVATE_Marshal); \ + F(TSS_UINT16_Marshal); \ + F(TSS_TPMT_SENSITIVE_Marshal); \ + F(TSS_SetProperty); \ + F(TSS_GetDigestSize); \ + F(TSS_Hash_Generate); \ + F(TSS_AES_EncryptCFB); \ + F(TSS_Delete); + +/* create static declarations for the function pointers */ +#define _DL_DECLARE(func) \ + static typeof(func) *p##func +_TSS2_LIST(_DL_DECLARE); + +static const char *tpm2_dir; + +/* The TPM builds a small database of active files representing key + * parameters used for authentication and session encryption. Make sure + * they're contained in a separate directory to avoid stepping on any + * other application uses of the TPM */ +static const char * +tpm2_set_unique_tssdir(void) +{ + char *prefix = getenv("XDG_RUNTIME_DIR"), *template, + *dir; + int len = 0; + + if (!prefix) + prefix = "/tmp"; + + len = snprintf(NULL, 0, "%s/tss2.XXXXXX", prefix); + if (len <= 0) + return NULL; + template = xtrymalloc(len + 1); + if (!template) + return NULL; + + len++; + len = snprintf(template, len, "%s/tss2.XXXXXX", prefix); + + dir = mkdtemp(template); + + return dir; +} + +/* now dynamically load the tss library (if it exists) and resolve the + * above symbols. This allows us simply to return 0 for tpm2_init on + * systems where there is no TPM library */ +static int +tpm2_init(void) +{ + static int inited = 0; + const char *sym; + void *dl; + + if (inited) + return 0; + + dl = dlopen(TSS2_LIB, RTLD_LAZY); + + if (!dl) + { + log_error("opening of tss2 library failed %s\n", strerror(errno)); + return GPG_ERR_CARD_NOT_PRESENT; + } + + /* load each symbol pointer and check for existence */ +# define _DL_SYM(func) \ + sym = #func; \ + p##func = dlsym(dl, #func); \ + if (p##func == NULL) \ + goto out_symfail + + _TSS2_LIST(_DL_SYM); + + tpm2_dir = tpm2_set_unique_tssdir(); + if (!tpm2_dir) + /* make this non fatal */ + log_error("Failed to set unique TPM directory\n"); + inited = 1; + return 0; + + out_symfail: + log_error("Failed to find symbol %s in tss2 library\n", sym); + return GPG_ERR_CARD_NOT_PRESENT; +} + +static void +tpm2_error(TPM_RC rc, char *prefix) +{ + const char *msg, *submsg, *num; + + pTSS_ResponseCode_toString(&msg, &submsg, &num, rc); + log_error("%s gave TPM2 Error: %s%s%s", prefix, msg, submsg, num); +} + +#define _TSS_CHECK(f) \ + rc = f; \ + if (rc != TPM_RC_SUCCESS) \ + { \ + tpm2_error(rc, #f); \ + return GPG_ERR_CARD; \ + } + +int +tpm2_start(TSS_CONTEXT **tssc) +{ + TPM_RC rc; + int ret; + + ret = tpm2_init(); + if (ret) + return ret; + + _TSS_CHECK(pTSS_Create(tssc)); + _TSS_CHECK(pTSS_SetProperty(*tssc, TPM_DATA_DIR, tpm2_dir)); + return 0; +} + +void +tpm2_end(TSS_CONTEXT *tssc) +{ + pTSS_Delete(tssc); +} + +void +tpm2_flush_handle(TSS_CONTEXT *tssc, TPM_HANDLE h) +{ + FlushContext_In in; + + if (!h) + return; + + in.flushHandle = h; + pTSS_Execute(tssc, NULL, + (COMMAND_PARAMETERS *)&in, + NULL, + TPM_CC_FlushContext, + TPM_RH_NULL, NULL, 0); +} + +static int +tpm2_get_hmac_handle(TSS_CONTEXT *tssc, TPM_HANDLE *handle, + TPM_HANDLE salt_key) +{ + TPM_RC rc; + StartAuthSession_In in; + StartAuthSession_Out out; + StartAuthSession_Extra extra; + + memset(&in, 0, sizeof(in)); + memset(&extra, 0 , sizeof(extra)); + in.bind = TPM_RH_NULL; + in.sessionType = TPM_SE_HMAC; + in.authHash = TPM_ALG_SHA256; + in.tpmKey = TPM_RH_NULL; + in.symmetric.algorithm = TPM_ALG_AES; + in.symmetric.keyBits.aes = 128; + in.symmetric.mode.aes = TPM_ALG_CFB; + if (salt_key) { + ReadPublic_In rin; + ReadPublic_Out rout; + + rin.objectHandle = salt_key; + rc = pTSS_Execute (tssc, + (RESPONSE_PARAMETERS *)&rout, + (COMMAND_PARAMETERS *)&rin, + NULL, + TPM_CC_ReadPublic, + TPM_RH_NULL, NULL, 0); + if (rc) { + tpm2_error(rc, "TPM2_ReadPublic"); + return GPG_ERR_CARD; + } + + /* don't care what rout returns, the purpose of the operation was + * to get the public key parameters into the tss so it can + * construct the salt */ + in.tpmKey = salt_key; + } + rc = pTSS_Execute(tssc, + (RESPONSE_PARAMETERS *)&out, + (COMMAND_PARAMETERS *)&in, + (EXTRA_PARAMETERS *)&extra, + TPM_CC_StartAuthSession, + TPM_RH_NULL, NULL, 0); + if (rc) { + tpm2_error(rc, "TPM2_StartAuthSession"); + return GPG_ERR_CARD; + } + + *handle = out.sessionHandle; + + return 0; +} + +static int +tpm2_exec_with_auth(ctrl_t ctrl, TSS_CONTEXT *tssc, int cmd, char *cmd_str, + void *out, void *in) +{ + TPM_HANDLE ah; + struct pin_entry_info_s *pi; + TPM_RC rc; + + pi = gcry_xmalloc_secure(sizeof(*pi) + MAX_PASSPHRASE_LEN + 10); + pi->max_length = MAX_PASSPHRASE_LEN; + pi->min_digits = 0; /* want a real passphrase */ + pi->max_digits = 16; + pi->max_tries = 3; + rc = agent_askpin(ctrl, NULL, "TPM Key Passphrase", NULL, pi, NULL, 0); + if (rc) { + gcry_free (pi); + return rc; + } + + rc = tpm2_get_hmac_handle(tssc, &ah, 0); + if (rc) + return rc; + + rc = pTSS_Execute(tssc, out, in, NULL, + cmd, + ah, pi->pin, 0, + TPM_RH_NULL, NULL, 0); + gcry_free (pi); + if (rc) { + tpm2_error(rc, cmd_str); + tpm2_flush_handle(tssc, ah); + switch (rc & 0xFF) { + case TPM_RC_BAD_AUTH: + case TPM_RC_AUTH_FAIL: + return GPG_ERR_BAD_PASSPHRASE; + default: + return GPG_ERR_CARD; + } + } + return 0; +} + +static gpg_error_t +parse_tpm2_shadow_info (const unsigned char *shadow_info, + uint32_t *parent, + const char **pub, int *pub_len, + const char **priv, int *priv_len) +{ + const unsigned char *s; + size_t n; + int i; + + s = shadow_info; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + *parent = 0; + for (i = 0; i < n; i++) { + *parent *= 10; + *parent += atoi_1(s+i); + } + + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + *pub_len = n; + *pub = s; + + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + *priv_len = n; + *priv = s; + + return 0; +} + +int +tpm2_load_key(TSS_CONTEXT *tssc, const unsigned char *shadow_info, + TPM_HANDLE *key) +{ + uint32_t parent; + Load_In in; + Load_Out out; + const char *pub, *priv; + int ret, pub_len, priv_len; + TPM_RC rc; + BYTE *buf; + uint32_t size; + + ret = parse_tpm2_shadow_info (shadow_info, &parent, &pub, &pub_len, + &priv, &priv_len); + if (ret) + return ret; + + in.parentHandle = parent; + + buf = (BYTE *)priv; + size = priv_len; + pTPM2B_PRIVATE_Unmarshal(&in.inPrivate, &buf, &size); + + buf = (BYTE *)pub; + size = pub_len; + pTPM2B_PUBLIC_Unmarshal(&in.inPublic, &buf, &size, FALSE); + + rc = pTSS_Execute(tssc, + (RESPONSE_PARAMETERS *)&out, + (COMMAND_PARAMETERS *)&in, + NULL, + TPM_CC_Load, + TPM_RS_PW, NULL, 0, + TPM_RH_NULL, NULL, 0); + if (rc != TPM_RC_SUCCESS) { + tpm2_error(rc, "TPM2_Load"); + return GPG_ERR_CARD; + } + + *key = out.objectHandle; + + return 0; +} + +int +tpm2_sign(ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key, + const unsigned char *digest, size_t digestlen, + unsigned char **r_sig, size_t *r_siglen) +{ + Sign_In in; + Sign_Out out; + int ret; + + /* The TPM insists on knowing the digest type, so + * calculate that from the size */ + in.inScheme.scheme = TPM_ALG_RSASSA; + switch (digestlen) { + case 20: + in.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA1; + break; + case 32: + in.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA256; + break; + case 48: + in.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA384; + break; +#ifdef TPM_ALG_SHA512 + case 64: + in.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA512; + break; +#endif + default: + log_error("Unknown signature digest length, cannot deduce hash type for TPM\n"); + return GPG_ERR_NO_SIGNATURE_SCHEME; + } + in.digest.t.size = digestlen; + memcpy(in.digest.t.buffer, digest, digestlen); + in.keyHandle = key; + in.validation.tag = TPM_ST_HASHCHECK; + in.validation.hierarchy = TPM_RH_NULL; + in.validation.digest.t.size = 0; + + ret = tpm2_exec_with_auth(ctrl, tssc, TPM_CC_Sign, "TPM2_Sign", &out, &in); + if (ret) + return ret; + + *r_siglen = out.signature.signature.rsassa.sig.t.size; + *r_sig = xtrymalloc(*r_siglen); + if (!r_sig) + return GPG_ERR_ENOMEM; + + memcpy(*r_sig, out.signature.signature.rsassa.sig.t.buffer, *r_siglen); + + return 0; +} + +static int +sexp_to_tpm2_sensitive(TPMT_SENSITIVE *s, gcry_sexp_t key) +{ + gcry_mpi_t p; + gcry_sexp_t l; + int rc = -1; + size_t len; + + s->sensitiveType = TPM_ALG_RSA; + s->seedValue.b.size = 0; + + l = gcry_sexp_find_token (key, "p", 0); + if (!l) + return rc; + p = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l); + len = sizeof(s->sensitive.rsa.t.buffer); + rc = gcry_mpi_print (GCRYMPI_FMT_USG, s->sensitive.rsa.t.buffer, len, &len, p); + s->sensitive.rsa.t.size = len; + gcry_mpi_release (p); + + return rc; +} + +static int +sexp_to_tpm2_public(TPMT_PUBLIC *p, gcry_sexp_t key) +{ + gcry_mpi_t n, e; + gcry_sexp_t l; + int rc = -1, i; + size_t len; + /* longer than an int */ + unsigned char ebuf[5]; + uint32_t exp = 0; + + p->type = TPM_ALG_RSA; + p->nameAlg = TPM_ALG_SHA256; + /* note: all our keys are decrypt only. This is because + * we use the TPM2_RSA_Decrypt operation for both signing + * and decryption (see e_tpm2.c for details) */ + p->objectAttributes.val = TPMA_OBJECT_NODA | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_SIGN | + TPMA_OBJECT_USERWITHAUTH; + p->authPolicy.t.size = 0; + p->parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL; + p->parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; + + l = gcry_sexp_find_token (key, "n", 0); + if (!l) + return rc; + n = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l); + len = sizeof(p->unique.rsa.t.buffer); + p->parameters.rsaDetail.keyBits = gcry_mpi_get_nbits (n); + rc = gcry_mpi_print (GCRYMPI_FMT_USG, p->unique.rsa.t.buffer, len, &len, n); + p->unique.rsa.t.size = len; + gcry_mpi_release (n); + if (rc) + return rc; + rc = -1; + l = gcry_sexp_find_token (key, "e", 0); + if (!l) + return rc; + e = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l); + len = sizeof (ebuf); + rc = gcry_mpi_print (GCRYMPI_FMT_USG, ebuf, len, &len, e); + gcry_mpi_release (e); + if (rc) + return rc; + if (len > 4) + return -1; + + /* MPI are simply big endian integers, so convert to uint32 */ + for (i = 0; i < len; i++) { + exp <<= 8; + exp += ebuf[i]; + } + if (exp == 0x10001) + p->parameters.rsaDetail.exponent = 0; + else + p->parameters.rsaDetail.exponent = exp; + return 0; +} + +static int +sexp_to_tpm2(TPMT_PUBLIC *p, TPMT_SENSITIVE *s, gcry_sexp_t s_skey) +{ + gcry_sexp_t l1, l2; + int rc = -1; + + /* find the value of (private-key */ + l1 = gcry_sexp_nth (s_skey, 1); + if (!l1) + return rc; + + l2 = gcry_sexp_find_token (l1, "rsa", 0); + if (!l2) + goto out; + + rc = sexp_to_tpm2_public(p, l2); + if (!rc) + rc = sexp_to_tpm2_sensitive(s, l2); + + gcry_sexp_release(l2); + + out: + gcry_sexp_release(l1); + return rc; +} + +/* copied from TPM implementation code */ +static TPM_RC +tpm2_ObjectPublic_GetName(TPM2B_NAME *name, + TPMT_PUBLIC *tpmtPublic) +{ + TPM_RC rc = 0; + uint16_t written = 0; + TPMT_HA digest; + uint32_t sizeInBytes; + uint8_t buffer[MAX_RESPONSE_SIZE]; + + /* marshal the TPMT_PUBLIC */ + if (rc == 0) { + INT32 size = MAX_RESPONSE_SIZE; + uint8_t *buffer1 = buffer; + rc = pTSS_TPMT_PUBLIC_Marshal(tpmtPublic, &written, &buffer1, &size); + } + /* hash the public area */ + if (rc == 0) { + sizeInBytes = pTSS_GetDigestSize(tpmtPublic->nameAlg); + digest.hashAlg = tpmtPublic->nameAlg; /* Name digest algorithm */ + /* generate the TPMT_HA */ + rc = pTSS_Hash_Generate(&digest, + written, buffer, + 0, NULL); + } + if (rc == 0) { + /* copy the digest */ + memcpy(name->t.name + sizeof(TPMI_ALG_HASH), (uint8_t *)&digest.digest, sizeInBytes); + /* copy the hash algorithm */ + TPMI_ALG_HASH nameAlgNbo = htons(tpmtPublic->nameAlg); + memcpy(name->t.name, (uint8_t *)&nameAlgNbo, sizeof(TPMI_ALG_HASH)); + /* set the size */ + name->t.size = sizeInBytes + sizeof(TPMI_ALG_HASH); + } + return rc; +} + +/* + * Cut down version of Part 4 Supporting Routines 7.6.3.10 + * + * Hard coded to symmetrically encrypt with aes128 as the inner + * wrapper and no outer wrapper but with a prototype that allows + * drop in replacement with a tss equivalent + */ +TPM_RC tpm2_SensitiveToDuplicate(TPMT_SENSITIVE *s, + TPM2B_NAME *name, + TPM_ALG_ID nalg, + TPMT_SYM_DEF_OBJECT *symdef, + TPM2B_DATA *innerkey, + TPM2B_PRIVATE *p) +{ + BYTE *buf = p->t.buffer; + + p->t.size = 0; + memset(p, 0, sizeof(*p)); + + /* hard code AES CFB */ + if (symdef->algorithm == TPM_ALG_AES + && symdef->mode.aes == TPM_ALG_CFB) { + TPMT_HA hash; + const int hlen = pTSS_GetDigestSize(nalg); + TPM2B *digest = (TPM2B *)buf; + TPM2B *s2b; + int32_t size; + unsigned char null_iv[AES_128_BLOCK_SIZE_BYTES]; + UINT16 bsize, written = 0; + + /* WARNING: don't use the static null_iv trick here: + * the AES routines alter the passed in iv */ + memset(null_iv, 0, sizeof(null_iv)); + + /* reserve space for hash before the encrypted sensitive */ + bsize = sizeof(digest->size) + hlen; + buf += bsize; + p->t.size += bsize; + s2b = (TPM2B *)buf; + + /* marshal the digest size */ + buf = (BYTE *)&digest->size; + bsize = hlen; + size = 2; + pTSS_UINT16_Marshal(&bsize, &written, &buf, &size); + + /* marshal the unencrypted sensitive in place */ + size = sizeof(*s); + bsize = 0; + buf = s2b->buffer; + pTSS_TPMT_SENSITIVE_Marshal(s, &bsize, &buf, &size); + buf = (BYTE *)&s2b->size; + size = 2; + pTSS_UINT16_Marshal(&bsize, &written, &buf, &size); + + bsize = bsize + sizeof(s2b->size); + p->t.size += bsize; + + /* compute hash of unencrypted marshalled sensitive and + * write to the digest buffer */ + hash.hashAlg = nalg; + pTSS_Hash_Generate(&hash, bsize, s2b, + name->t.size, name->t.name, + 0, NULL); + memcpy(digest->buffer, &hash.digest, hlen); + + /* encrypt hash and sensitive in place */ + pTSS_AES_EncryptCFB(p->t.buffer, + symdef->keyBits.aes, + innerkey->b.buffer, + null_iv, + p->t.size, + p->t.buffer); + } else if (symdef->algorithm == TPM_ALG_NULL) { + TPM2B *s2b = (TPM2B *)buf; + int32_t size = sizeof(*s); + UINT16 bsize = 0, written = 0; + + buf = s2b->buffer; + + /* marshal the unencrypted sensitive in place */ + pTSS_TPMT_SENSITIVE_Marshal(s, &bsize, &buf, &size); + buf = (BYTE *)&s2b->size; + size = 2; + pTSS_UINT16_Marshal(&bsize, &written, &buf, &size); + + p->b.size += bsize + sizeof(s2b->size); + } else { + printf("Unknown symmetric algorithm\n"); + return TPM_RC_SYMMETRIC; + } + + return TPM_RC_SUCCESS; +} + +static void +tpm2_encrypt_duplicate(Import_In *iin, TPMT_SENSITIVE *s) +{ + TPM2B_NAME name; + TPMT_PUBLIC *p = &iin->objectPublic.publicArea; + const int aes_key_bits = 128; + const int aes_key_bytes = aes_key_bits/8; + + tpm2_ObjectPublic_GetName(&name, p); + gcry_randomize(iin->encryptionKey.t.buffer, + aes_key_bytes, GCRY_STRONG_RANDOM); + iin->encryptionKey.t.size = aes_key_bytes; + + /* set random iin.symSeed */ + iin->inSymSeed.t.size = 0; + iin->symmetricAlg.algorithm = TPM_ALG_AES; + iin->symmetricAlg.keyBits.aes = aes_key_bits; + iin->symmetricAlg.mode.aes = TPM_ALG_CFB; + + tpm2_SensitiveToDuplicate(s, &name, p->nameAlg, &iin->symmetricAlg, + &iin->encryptionKey, &iin->duplicate); +} + +int +tpm2_import_key(ctrl_t ctrl, TSS_CONTEXT *tssc, char *pub, int *pub_len, + char *priv, int *priv_len, gcry_sexp_t s_skey) +{ + Import_In iin; + Import_Out iout; + TPMT_SENSITIVE s; + TPM_HANDLE ah; + TPM_RC rc; + + uint32_t size; + uint16_t len; + BYTE *buffer; + int ret; + char *passphrase; + + iin.parentHandle = TPM2_PARENT; + ret = sexp_to_tpm2(&iin.objectPublic.publicArea, &s, s_skey); + if (ret) { + log_error("Failed to parse Key s-expression: key corrupt?\n"); + return ret; + } + + /* add an authorization password to the key which the TPM will check */ + + ret = agent_ask_new_passphrase (ctrl, _("Please enter the TPM Authorization passphrase for the key."), &passphrase); + if (ret) + return ret; + s.authValue.b.size = strlen(passphrase); + memcpy(s.authValue.b.buffer, passphrase, s.authValue.b.size); + + /* We're responsible for securing the data in transmission to the + * TPM here. The TPM provides parameter encryption via a session, + * but only for the first parameter. For TPM2_Import, the first + * parameter is a symmetric key used to encrypt the sensitive data, + * so we must populate this key with random value and encrypt the + * sensitive data with it */ + tpm2_encrypt_duplicate(&iin, &s); + + /* use salted parameter encryption to hide the key. First we read + * the public parameters of the parent key and use them to agree an + * encryption for the first parameter */ + rc = tpm2_get_hmac_handle(tssc, &ah, TPM2_PARENT); + if (rc) + return GPG_ERR_CARD; + + rc = pTSS_Execute(tssc, + (RESPONSE_PARAMETERS *)&iout, + (COMMAND_PARAMETERS *)&iin, + NULL, + TPM_CC_Import, + ah, NULL, TPMA_SESSION_DECRYPT, + TPM_RH_NULL, NULL, 0); + if (rc) { + tpm2_error(rc, "TPM2_Import"); + /* failure means auth handle is not flushed */ + tpm2_flush_handle(tssc, ah); + return GPG_ERR_CARD; + } + + size = sizeof(TPM2B_PUBLIC); + buffer = pub; + len = 0; + pTSS_TPM2B_PUBLIC_Marshal(&iin.objectPublic, + &len, &buffer, &size); + *pub_len = len; + + size = sizeof(TPM2B_PRIVATE); + buffer = priv; + len = 0; + pTSS_TPM2B_PRIVATE_Marshal(&iout.outPrivate, + &len, &buffer, &size); + *priv_len = len; + + return 0; +} + +int +tpm2_decrypt(ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key, + const char *ciphertext, int ciphertext_len, + char **decrypt, size_t *decrypt_len) +{ + RSA_Decrypt_In in; + RSA_Decrypt_Out out; + int ret; + + in.keyHandle = key; + in.inScheme.scheme = TPM_ALG_RSAES; + in.cipherText.t.size = ciphertext_len; + memcpy (in.cipherText.t.buffer, ciphertext, ciphertext_len); + in.label.t.size = 0; + + ret = tpm2_exec_with_auth(ctrl, tssc, TPM_CC_RSA_Decrypt, "TPM2_RSA_Decrypt", + &out, &in); + if (ret) + return ret; + + *decrypt_len = out.message.t.size; + *decrypt = xtrymalloc(out.message.t.size); + memcpy (*decrypt, out.message.t.buffer, out.message.t.size); + + return 0; +} diff --git a/agent/tpm2.h b/agent/tpm2.h new file mode 100644 index 000000000..2e168032f --- /dev/null +++ b/agent/tpm2.h @@ -0,0 +1,22 @@ +#ifndef _TPM2_H +#define _TPM2_H + +#include + +#define TSS2_LIB "libtss.so.0" +#define TPM2_PARENT 0x81000001 + +int tpm2_start(TSS_CONTEXT **tssc); +void tpm2_end(TSS_CONTEXT *tssc); +void tpm2_flush_handle(TSS_CONTEXT *tssc, TPM_HANDLE h); +int tpm2_load_key(TSS_CONTEXT *tssc, const unsigned char *shadow_info, + TPM_HANDLE *key); +int tpm2_sign(ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key, + const unsigned char *digest, size_t digestlen, + unsigned char **r_sig, size_t *r_siglen); +int tpm2_import_key(ctrl_t ctrl, TSS_CONTEXT *tssc, char *pub, int *pub_len, + char *priv, int *priv_len, gcry_sexp_t s_skey); +int tpm2_decrypt(ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key, + const char *ciphertext, int ciphertext_len, + char **decrypt, size_t *decrypt_len); +#endif -- 2.12.3 From James.Bottomley at HansenPartnership.com Fri Jan 19 06:28:30 2018 From: James.Bottomley at HansenPartnership.com (James Bottomley) Date: Thu, 18 Jan 2018 21:28:30 -0800 Subject: [RFC 3/4] agent: plumb in TPM handling In-Reply-To: <1516339524.3014.59.camel@HansenPartnership.com> References: <1516339524.3014.59.camel@HansenPartnership.com> Message-ID: <1516339710.3014.62.camel@HansenPartnership.com> This code installs diversions for pksign and pkdecrypt to do the operations via the TPM if a TPM shadowed key is present. It also adds an extra assuan command KEYTOTPM which moves an existing private key to a TPM shadowed key. The way TPM shadowing works is that the public and private key parts are fed in to the TPM command TPM2_Import. The output of this command is a TPM specific public and private key data where the private key data is symmetrically encrypted using a TPM internal key. If this physical TPM is ever lost or cleared, that TPM internal key will likewise be lost and nothing will ever be able to read the private key. Once the import is done, the shadow information for the key is updated to be a three part list consisting of the parent key (hard coded to 81000001 which is the Microsoft preferred RSA incarnation of the storage seed) and the public and private TPM data blobs. Now when a TPM shadowed key is used, the data blobs must be loaded into the TPM with TPM2_Load before any operation can be performed. Signed-off-by: James Bottomley --- agent/Makefile.am | 1 + agent/agent.h | 13 ++++ agent/command.c | 57 ++++++++++++++++ agent/divert-tpm2.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++ agent/pkdecrypt.c | 8 ++- agent/pksign.c | 14 ++-- 6 files changed, 274 insertions(+), 6 deletions(-) create mode 100644 agent/divert-tpm2.c diff --git a/agent/Makefile.am b/agent/Makefile.am index bc3d43a0f..f0a52ad3b 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -51,6 +51,7 @@ gpg_agent_SOURCES = \ protect.c \ trustlist.c \ divert-scd.c \ + divert-tpm2.c \ tpm2.c \ cvt-openpgp.c cvt-openpgp.h \ call-scd.c \ diff --git a/agent/agent.h b/agent/agent.h index 2df2fde53..0ff487a59 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -417,6 +417,7 @@ gpg_error_t agent_public_key_from_file (ctrl_t ctrl, gcry_sexp_t *result); int agent_is_dsa_key (gcry_sexp_t s_key); int agent_is_eddsa_key (gcry_sexp_t s_key); +int agent_is_tpm2_key(gcry_sexp_t s_key); int agent_key_available (const unsigned char *grip); gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, int *r_keytype, @@ -532,6 +533,18 @@ gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag); void agent_reload_trustlist (void); +/*-- divert-tpm2.c --*/ +int divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text, + const unsigned char *digest, size_t digestlen, int algo, + const unsigned char *shadow_info, unsigned char **r_sig, + size_t *r_siglen); +int divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text, + const unsigned char *cipher, + const unsigned char *shadow_info, + char **r_buf, size_t *r_len, int *r_padding); +int divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip, + gcry_sexp_t s_skey); + /*-- divert-scd.c --*/ int divert_pksign (ctrl_t ctrl, const char *desc_text, diff --git a/agent/command.c b/agent/command.c index 57e9de75b..c5f275f01 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1222,6 +1222,11 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, if (err) goto leave; } + else if (strcmp (shadow_info_type, "tpm2-v1") == 0) + { + serialno = xstrdup("TPM-Protected"); + idstr = NULL; + } else { log_error ("Unrecognised shadow key type %s\n", shadow_info_type); @@ -2608,6 +2613,57 @@ cmd_keytocard (assuan_context_t ctx, char *line) +static const char hlp_keytotpm[] = + "KEYTOTPM \n" + "\n"; +static gpg_error_t +cmd_keytotpm (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err = 0; + unsigned char grip[20]; + gcry_sexp_t s_skey; + unsigned char *shadow_info = NULL; + + if (ctrl->restricted) + return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); + + err = parse_keygrip (ctx, line, grip); + if (err) + goto leave; + + if (agent_key_available (grip)) + { + err =gpg_error (GPG_ERR_NO_SECKEY); + goto leave; + } + + err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip, + &shadow_info, CACHE_MODE_IGNORE, NULL, + &s_skey, NULL); + if (err) + { + xfree (shadow_info); + goto leave; + } + if (shadow_info) + { + /* Key is on a TPM or smartcard already. */ + xfree (shadow_info); + gcry_sexp_release (s_skey); + err = gpg_error (GPG_ERR_UNUSABLE_SECKEY); + goto leave; + } + + err = divert_tpm2_writekey (ctrl, grip, s_skey); + gcry_sexp_release (s_skey); + + leave: + return leave_cmd (ctx, err); +} + + + static const char hlp_getval[] = "GETVAL \n" "\n" @@ -3273,6 +3329,7 @@ register_commands (assuan_context_t ctx) { "RELOADAGENT", cmd_reloadagent,hlp_reloadagent }, { "GETINFO", cmd_getinfo, hlp_getinfo }, { "KEYTOCARD", cmd_keytocard, hlp_keytocard }, + { "KEYTOTPM", cmd_keytotpm, hlp_keytotpm }, { NULL } }; int i, rc; diff --git a/agent/divert-tpm2.c b/agent/divert-tpm2.c new file mode 100644 index 000000000..dc3110d0b --- /dev/null +++ b/agent/divert-tpm2.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" +#include "../common/i18n.h" +#include "../common/sexp-parse.h" + +#include "tpm2.h" + +int +divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text, + const unsigned char *digest, size_t digestlen, int algo, + const unsigned char *shadow_info, unsigned char **r_sig, + size_t *r_siglen) +{ + TSS_CONTEXT *tssc; + TPM_HANDLE key; + int ret; + + ret = tpm2_start(&tssc); + if (ret) + return ret; + ret = tpm2_load_key(tssc, shadow_info, &key); + if (ret) + goto out; + ret = tpm2_sign(ctrl, tssc, key, digest, digestlen, r_sig, r_siglen); + + tpm2_flush_handle(tssc, key); + + out: + tpm2_end(tssc); + return ret; +} + +static unsigned char * +make_tpm2_shadow_info (uint32_t parent, const char *pub, int pub_len, + const char *priv, int priv_len) +{ + gcry_sexp_t s_exp; + size_t len; + char *info; + + gcry_sexp_build(&s_exp, NULL, "(%u%b%b)", parent, pub_len, pub, priv_len, priv); + + len = gcry_sexp_sprint(s_exp, GCRYSEXP_FMT_CANON, NULL, 0); + info = xtrymalloc(len); + gcry_sexp_sprint(s_exp, GCRYSEXP_FMT_CANON, info, len); + + gcry_sexp_release(s_exp); + + return (unsigned char *)info; +} + +static gpg_error_t +agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip, + int parent, char *pub, int pub_len, + char *priv, int priv_len) +{ + gpg_error_t err; + unsigned char *shadow_info; + unsigned char *shdkey; + unsigned char *pkbuf; + size_t len; + gcry_sexp_t s_pkey; + + err = agent_public_key_from_file (ctrl, grip, &s_pkey); + len = gcry_sexp_sprint(s_pkey, GCRYSEXP_FMT_CANON, NULL, 0); + pkbuf = xtrymalloc (len); + gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, len); + gcry_sexp_release (s_pkey); + + shadow_info = make_tpm2_shadow_info (parent, pub, pub_len, priv, priv_len); + if (!shadow_info) { + xfree (pkbuf); + return gpg_error_from_syserror (); + } + + err = agent_shadow_key_type (pkbuf, shadow_info, "tpm2-v1", &shdkey); + xfree (shadow_info); + xfree (pkbuf); + if (err) + { + log_error ("shadowing the key failed: %s\n", gpg_strerror (err)); + return err; + } + + len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); + err = agent_write_private_key (grip, shdkey, len, 1 /*force*/); + xfree (shdkey); + if (err) + log_error ("error writing key: %s\n", gpg_strerror (err)); + + return err; +} + +int +divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip, + gcry_sexp_t s_skey) +{ + TSS_CONTEXT *tssc; + int ret, pub_len, priv_len; + /* priv is always shielded so no special handling required */ + char pub[sizeof(TPM2B_PUBLIC)], priv[sizeof(TPM2B_PRIVATE)]; + + ret = tpm2_start(&tssc); + if (ret) + return ret; + ret = tpm2_import_key (ctrl, tssc, pub, &pub_len, priv, &priv_len, s_skey); + if (ret) + goto out; + ret = agent_write_tpm2_shadow_key (ctrl, grip, TPM2_PARENT, pub, pub_len, + priv, priv_len); + out: + tpm2_end(tssc); + return ret; +} + +int +divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text, + const unsigned char *cipher, + const unsigned char *shadow_info, + char **r_buf, size_t *r_len, int *r_padding) +{ + TSS_CONTEXT *tssc; + TPM_HANDLE key; + int ret; + const unsigned char *s; + size_t n; + + *r_padding = 0; + + (void)desc_text; + + s = cipher; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "enc-val")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (smatch (&s, n, "rsa")) + { + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "a")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + n = snext (&s); + } + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + + /* know we have RSA to decrypt at s,n */ + + ret = tpm2_start(&tssc); + if (ret) + return ret; + ret = tpm2_load_key(tssc, shadow_info, &key); + if (ret) + goto out; + ret = tpm2_decrypt(ctrl, tssc, key, s, n, r_buf, r_len); + + tpm2_flush_handle(tssc, key); + + out: + tpm2_end(tssc); + return ret; + +} diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 06a8e0b6f..6f766ca63 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -86,8 +86,12 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, goto leave; } - rc = divert_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info, - &buf, &len, r_padding); + if (agent_is_tpm2_key (s_skey)) + rc = divert_tpm2_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info, + &buf, &len, r_padding); + else + rc = divert_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info, + &buf, &len, r_padding); if (rc) { log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc)); diff --git a/agent/pksign.c b/agent/pksign.c index f54af0817..dae2638f4 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -353,10 +353,16 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce, if (desc_text) agent_modify_description (desc_text, NULL, s_skey, &desc2); - err = divert_pksign (ctrl, desc2? desc2 : desc_text, - data, datalen, - ctrl->digest.algo, - shadow_info, &buf, &len); + if (agent_is_tpm2_key (s_skey)) + err = divert_tpm2_pksign (ctrl, desc2? desc2 : desc_text, + data, datalen, + ctrl->digest.algo, + shadow_info, &buf, &len); + else + err = divert_pksign (ctrl, desc2? desc2 : desc_text, + data, datalen, + ctrl->digest.algo, + shadow_info, &buf, &len); xfree (desc2); } if (err) -- 2.12.3 From James.Bottomley at HansenPartnership.com Fri Jan 19 06:29:26 2018 From: James.Bottomley at HansenPartnership.com (James Bottomley) Date: Thu, 18 Jan 2018 21:29:26 -0800 Subject: [RFC 4/4] g10: add ability to transfer a private key to the tpm In-Reply-To: <1516339524.3014.59.camel@HansenPartnership.com> References: <1516339524.3014.59.camel@HansenPartnership.com> Message-ID: <1516339766.3014.63.camel@HansenPartnership.com> Exactly like the gpg --edit-key command keytosc, keytotpm has been added which immedately converts the private key file to TPM shadowed form. Once this is done, the key cannot be recovered and may only be used via the TPM of the computer system on which the conversion was done. If that system is ever lost, or its TPM cleared, the shadowed key becomes unusable. Signed-off-by: James Bottomley --- g10/call-agent.c | 22 ++++++++++++++++++++++ g10/call-agent.h | 3 +++ g10/keyedit.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/g10/call-agent.c b/g10/call-agent.c index 61d06c663..356ec8539 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -759,6 +759,28 @@ agent_scd_apdu (const char *hexapdu, unsigned int *r_sw) return err; } +int +agent_keytotpm (ctrl_t ctrl, const char *hexgrip) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + struct default_inq_parm_s parm; + + snprintf(line, DIM(line), "KEYTOTPM %s\n", hexgrip); + + rc = start_agent (ctrl, 0); + if (rc) + return rc; + parm.ctx = agent_ctx; + parm.ctrl = ctrl; + + rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm, + NULL, NULL); + if (rc) + log_log (GPGRT_LOGLVL_ERROR, _("error from TPM: %s\n"), gpg_strerror (rc)); + return rc; +} + int agent_keytocard (const char *hexgrip, int keyno, int force, diff --git a/g10/call-agent.h b/g10/call-agent.h index f45b64d90..85c939fa0 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -88,6 +88,9 @@ gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw); /* Update INFO with the attribute NAME. */ int agent_scd_getattr (const char *name, struct agent_card_info_s *info); +/* send the KEYTOTPM command */ +int agent_keytotpm (ctrl_t ctrl, const char *hexgrip); + /* Send the KEYTOCARD command. */ int agent_keytocard (const char *hexgrip, int keyno, int force, const char *serialno, const char *timestamp); diff --git a/g10/keyedit.c b/g10/keyedit.c index 81344eb79..fd82f2d21 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1241,7 +1241,7 @@ enum cmdids #endif /*!NO_TRUST_MODELS*/ cmdSHOWPREF, cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, - cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, + cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdKEYTOTPM, cmdBKUPTOCARD, cmdCLEAN, cmdMINIMIZE, cmdGRIP, cmdNOP }; @@ -1292,6 +1292,8 @@ static struct N_("add a key to a smartcard")}, { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("move a key to a smartcard")}, + { "keytotpm", cmdKEYTOTPM, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, + N_("convert a key to TPM form using the local TPM")}, { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("move a backup key to a smartcard")}, #endif /*ENABLE_CARD_SUPPORT */ @@ -1789,6 +1791,47 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, } break; + case cmdKEYTOTPM: + /* FIXME need to store the key and not commit until later */ + { + KBNODE node = NULL; + switch (count_selected_keys (keyblock)) + { + case 0: + if (cpr_get_answer_is_yes + ("keyedit.keytocard.use_primary", + /* TRANSLATORS: Please take care: This is about + moving the key and not about removing it. */ + _("Really move the primary key? (y/N) "))) + node = keyblock; + break; + case 1: + for (node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && node->flag & NODFLG_SELKEY) + break; + } + break; + default: + tty_printf (_("You must select exactly one key.\n")); + break; + } + if (node) + { + PKT_public_key *xxpk = node->pkt->pkt.public_key; + char *hexgrip; + + hexkeygrip_from_pk (xxpk, &hexgrip); + if (!agent_keytotpm (ctrl, hexgrip)) + { + redisplay = 1; + } + xfree (hexgrip); + } + } + break; + case cmdKEYTOCARD: { KBNODE node = NULL; -- 2.12.3 From James.Bottomley at HansenPartnership.com Fri Jan 19 06:26:40 2018 From: James.Bottomley at HansenPartnership.com (James Bottomley) Date: Thu, 18 Jan 2018 21:26:40 -0800 Subject: [RFC 1/4] agent: expose shadow key type In-Reply-To: <1516339524.3014.59.camel@HansenPartnership.com> References: <1516339524.3014.59.camel@HansenPartnership.com> Message-ID: <1516339600.3014.60.camel@HansenPartnership.com> For TPM support it is necessary to indroduce another type of shadow key, so allow other agent functions to extract the type so they can make the right decisions based on it. Signed-off-by: James Bottomley --- agent/agent.h | 10 +++++++- agent/command.c | 21 +++++++++++++---- agent/findkey.c | 5 ++-- agent/protect.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 90 insertions(+), 18 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index 687635dc7..2df2fde53 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -420,7 +420,8 @@ int agent_is_eddsa_key (gcry_sexp_t s_key); int agent_key_available (const unsigned char *grip); gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, int *r_keytype, - unsigned char **r_shadow_info); + unsigned char **r_shadow_info, + unsigned char **r_shadow_info_type); gpg_error_t agent_delete_key (ctrl_t ctrl, const char *desc_text, const unsigned char *grip, int force, int only_stubs); @@ -502,8 +503,15 @@ unsigned char *make_shadow_info (const char *serialno, const char *idstring); int agent_shadow_key (const unsigned char *pubkey, const unsigned char *shadow_info, unsigned char **result); +int agent_shadow_key_type (const unsigned char *pubkey, + const unsigned char *shadow_info, + const unsigned char *type, + unsigned char **result); gpg_error_t agent_get_shadow_info (const unsigned char *shadowkey, unsigned char const **shadow_info); +gpg_error_t agent_get_shadow_info_type (const unsigned char *shadowkey, + unsigned char const **shadow_info, + unsigned char **shadow_type); gpg_error_t parse_shadow_info (const unsigned char *shadow_info, char **r_hexsn, char **r_idstr, int *r_pinlen); gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo, diff --git a/agent/command.c b/agent/command.c index 7c7e8a4bc..57e9de75b 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1134,7 +1134,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, char hexgrip[40+1]; char *fpr = NULL; int keytype; - unsigned char *shadow_info = NULL; + unsigned char *shadow_info = NULL, *shadow_info_type = NULL; char *serialno = NULL; char *idstr = NULL; const char *keytypestr; @@ -1145,7 +1145,8 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, char ttlbuf[20]; char flagsbuf[5]; - err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info); + err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info, + &shadow_info_type); if (err) { if (in_ssh && gpg_err_code (err) == GPG_ERR_NOT_FOUND) @@ -1215,9 +1216,18 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, if (shadow_info) { - err = parse_shadow_info (shadow_info, &serialno, &idstr, NULL); - if (err) - goto leave; + if (strcmp (shadow_info_type, "t1-v1") == 0) + { + err = parse_shadow_info (shadow_info, &serialno, &idstr, NULL); + if (err) + goto leave; + } + else + { + log_error ("Unrecognised shadow key type %s\n", shadow_info_type); + err = GPG_ERR_BAD_KEY; + goto leave; + } } if (!data) @@ -1252,6 +1262,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, leave: xfree (fpr); + xfree (shadow_info_type); xfree (shadow_info); xfree (serialno); xfree (idstr); diff --git a/agent/findkey.c b/agent/findkey.c index e3e9a123f..d6c600e71 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -1359,7 +1359,8 @@ agent_key_available (const unsigned char *grip) S-expression. */ gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, - int *r_keytype, unsigned char **r_shadow_info) + int *r_keytype, unsigned char **r_shadow_info, + unsigned char **r_shadow_info_type) { gpg_error_t err; unsigned char *buf; @@ -1406,7 +1407,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, const unsigned char *s; size_t n; - err = agent_get_shadow_info (buf, &s); + err = agent_get_shadow_info_type (buf, &s, r_shadow_info_type); if (!err) { n = gcry_sexp_canon_len (s, 0, NULL, NULL); diff --git a/agent/protect.c b/agent/protect.c index 16ae715e1..0920667d1 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -1499,9 +1499,10 @@ make_shadow_info (const char *serialno, const char *idstring) to. The input parameters are expected to be valid canonicalized S-expressions */ int -agent_shadow_key (const unsigned char *pubkey, - const unsigned char *shadow_info, - unsigned char **result) +agent_shadow_key_type (const unsigned char *pubkey, + const unsigned char *shadow_info, + const unsigned char *type, + unsigned char **result) { const unsigned char *s; const unsigned char *point; @@ -1557,7 +1558,7 @@ agent_shadow_key (const unsigned char *pubkey, assert (depth == 1); /* Calculate required length by taking in account: the "shadowed-" - prefix, the "shadowed", "t1-v1" as well as some parenthesis */ + prefix, the "shadowed", shadow type as well as some parenthesis */ n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; *result = xtrymalloc (n); p = (char*)*result; @@ -1567,7 +1568,7 @@ agent_shadow_key (const unsigned char *pubkey, /* (10:public-key ...)*/ memcpy (p, pubkey+14, point - (pubkey+14)); p += point - (pubkey+14); - p = stpcpy (p, "(8:shadowed5:t1-v1"); + p += sprintf (p, "(8:shadowed%d:%s", (int)strlen(type), type); memcpy (p, shadow_info, shadow_info_len); p += shadow_info_len; *p++ = ')'; @@ -1577,11 +1578,20 @@ agent_shadow_key (const unsigned char *pubkey, return 0; } +int +agent_shadow_key (const unsigned char *pubkey, + const unsigned char *shadow_info, + unsigned char **result) +{ + return agent_shadow_key_type (pubkey, shadow_info, "t1-v1", result); +} + /* Parse a canonical encoded shadowed key and return a pointer to the - inner list with the shadow_info */ + inner list with the shadow_info and the shadow type */ gpg_error_t -agent_get_shadow_info (const unsigned char *shadowkey, - unsigned char const **shadow_info) +agent_get_shadow_info_type (const unsigned char *shadowkey, + unsigned char const **shadow_info, + unsigned char **shadow_type) { const unsigned char *s; size_t n; @@ -1633,17 +1643,59 @@ agent_get_shadow_info (const unsigned char *shadowkey, n = snext (&s); if (!n) return gpg_error (GPG_ERR_INV_SEXP); - if (smatch (&s, n, "t1-v1")) + if (shadow_type) { + char *buf = xtrymalloc(n+1); + memcpy(buf, s, n); + buf[n] = '\0'; + *shadow_type = buf; + } + + if (smatch (&s, n, "t1-v1") || smatch(&s, n, "tpm2-v1")) { if (*s != '(') return gpg_error (GPG_ERR_INV_SEXP); - *shadow_info = s; + if (shadow_info) + *shadow_info = s; } else return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); return 0; } +gpg_error_t +agent_get_shadow_info(const unsigned char *shadowkey, + unsigned char const **shadow_info) +{ + return agent_get_shadow_info_type(shadowkey, shadow_info, NULL); +} + +int +agent_is_tpm2_key(gcry_sexp_t s_skey) +{ + unsigned char *buf; + unsigned char *type; + size_t len; + gpg_error_t err; + + err = make_canon_sexp(s_skey, &buf, &len); + if (err) + return 0; + + err = agent_get_shadow_info_type(buf, NULL, &type); + if (err) + return 0; + + err = strcmp(type, "tpm2-v1") == 0; + xfree(type); + return err; +} + +gpg_error_t +agent_get_shadow_type(const unsigned char *shadowkey, + unsigned char **shadow_type) +{ + return agent_get_shadow_info_type(shadowkey, NULL, shadow_type); +} /* Parse the canonical encoded SHADOW_INFO S-expression. On success the hex encoded serial number is returned as a malloced strings at -- 2.12.3 From James.Bottomley at HansenPartnership.com Fri Jan 19 06:25:24 2018 From: James.Bottomley at HansenPartnership.com (James Bottomley) Date: Thu, 18 Jan 2018 21:25:24 -0800 Subject: [RFC 0/4] TPM support for gpg Message-ID: <1516339524.3014.59.camel@HansenPartnership.com> This patch series adds TPM 2.0 support to gnupg. TPMs are useful as an alternative to key cards: they provide the same security against key theft and the same cryptographic protections. ?The main difference is that TPMs are universally present in every laptop, so they provide a simple and ubiquitous solution to key security. ?The only real down side is that unlike key cards, TPM protected keys cannot be transferred between laptops, you must instead keep an offline backup copy of the key can then be transferred to the TPM of any new laptop. The way TPM protection works is slightly different from key cards. ?Instead of moving the key inside the card, the TPM converts any given key to a TPM specific representation (meaning it's encrypted by a special key that only the TPM possesses). ?The TPM represenation must be stored offline somewhere and if it is lost, so is the protected key. ?The way I implemented this is to use the TPM to convert the key to protected representation and then store it in the shadow_info of a shadowed-private-key using a shadow type of tpm2-v1. ?The TPM can handle an arbitrary number of keys, but the price is the shadow_info stores the keys and must be preserved. This implementation is an RFC, because ordinarily TPM support would be integrated into the cryptosystem rather than the application but since gnupg already integrates key cards via a diversion mechanism, it was also easy to follow this route for TPM support. ?The main difference between the TPM and the card is that there's no need for a separate daemon to run the card, so I integrated diversion support directly into the agent. The way to use this is simple: I added a new command to keyedit.c: keytotpm which converts an existing encrypted private key to TPM representation. This conversion is done immediately the command completes and cannot be undone. ?Once converted, all the usual gpg operations go transparently through the TPM, so it should be largely invisible to a user. James --- James Bottomley (4): agent: expose shadow key type agent: add tpm specific functions agent: plumb in TPM handling g10: add ability to transfer a private key to the tpm agent/Makefile.am | 2 + agent/agent.h | 23 +- agent/command.c | 78 +++++- agent/divert-tpm2.c | 187 +++++++++++++ agent/findkey.c | 5 +- agent/pkdecrypt.c | 8 +- agent/pksign.c | 14 +- agent/protect.c | 72 ++++- agent/tpm2.c | 784 ++++++++++++++++++++++++++++++++++++++++++++++++++++ agent/tpm2.h | 22 ++ g10/call-agent.c | 22 ++ g10/call-agent.h | 3 + g10/keyedit.c | 45 ++- 13 files changed, 1240 insertions(+), 25 deletions(-) create mode 100644 agent/divert-tpm2.c create mode 100644 agent/tpm2.c create mode 100644 agent/tpm2.h -- 2.12.3 From dashohoxha at gmail.com Mon Jan 22 09:00:21 2018 From: dashohoxha at gmail.com (Dashamir Hoxha) Date: Mon, 22 Jan 2018 09:00:21 +0100 Subject: GSoC project about improving EasyGnuPG In-Reply-To: References: Message-ID: On Tue, Jan 16, 2018 at 7:05 PM, Dashamir Hoxha wrote: > Hi, > > I have created a GSoC project about improving EasyGnuPG: > https://wiki.debian.org/SummerOfCode2018/Projects/EasyGnuPG > > If anyone would like to be a co-mentor (there can be several ones) > I would appreciate it. > By the way, I am also going to have a lightening talk at FOSDEM: https://fosdem.org/2018/schedule/event/easy_gnupg/ And I will also try to participate at the key-signing event: https://fosdem.org/2018/keysigning/ > > Thanks, > Dashamir > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Alexander.Strobel at giepa.de Tue Jan 23 11:45:01 2018 From: Alexander.Strobel at giepa.de (Alexander Strobel) Date: Tue, 23 Jan 2018 11:45:01 +0100 Subject: "decryption forced to fail" due to missing signature? Message-ID: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> Thunderbird/Enigmail shows an error "decryption failed" when I decrypt an email that was not signed. For testing I did an en/decryption on command line and see the error "gpg: decryption forced to fail" when I decrypt my file. Here is what I did with GnuPG v2.2.4: c:\users\...>dir * > toencrypt.txt c:\users\...>gpg --encrypt toencrypt.txt c:\users\...> gpg -vv -o decrypted.txt --decrypt toencrypt.txt.gpg # off=0 ctb=85 tag=1 hlen=3 plen=524 :pubkey enc packet: version 3, algo 1, keyid AC4E42952F82C45E data: [4095 bits] gpg: public key is AC4E42952F82C45E gpg: using subkey AC4E42952F82C45E instead of primary key 874D04CCA111C47B gpg: public key encrypted data: good DEK # off=527 ctb=c9 tag=9 hlen=2 plen=0 partial new-ctb :encrypted data packet: length: unknown gpg: using subkey AC4E42952F82C45E instead of primary key 874D04CCA111C47B gpg: encrypted with 4096-bit RSA key, ID AC4E42952F82C45E, created 2015-01-27 "Alexander Strobel (Giegerich & Partner GmbH)" gpg: AES256 encrypted data # off=547 ctb=a3 tag=8 hlen=1 plen=0 indeterminate :compressed packet: algo=2 # off=549 ctb=ad tag=11 hlen=3 plen=1495 :literal data packet: mode b (62), created 1516703454, name="toencrypt.txt", raw data: 1476 bytes gpg: original file name='toencrypt.txt' gpg: WARNING: message was not integrity protected gpg: decryption forced to fail As long as I use GnuPG 1.4.22 it is working as expected: c:\users\...>dir * > toencrypt.txt c:\users\...>gpg --encrypt toencrypt.txt c:\users\...> gpg -vv -o decrypted.txt --decrypt toencrypt.txt.gpg :pubkey enc packet: version 3, algo 1, keyid AC4E42952F82C45E data: [4095 bits] gpg: public key is 2F82C45E gpg: can't handle public key algorithm 22 gpg: can't handle public key algorithm 18 gpg: using subkey 2F82C45E instead of primary key A111C47B You need a passphrase to unlock the secret key for user: "Alexander Strobel (Giegerich & Partner GmbH)" gpg: using subkey 2F82C45E instead of primary key A111C47B 4096-bit RSA key, ID 2F82C45E, created 2015-01-27 (main key ID A111C47B) gpg: public key encrypted data: good DEK :encrypted data packet: length: 390 gpg: encrypted with 4096-bit RSA key, ID 2F82C45E, created 2015-01-27 "Alexander Strobel (Giegerich & Partner GmbH)" gpg: AES256 encrypted data :compressed packet: algo=2 :literal data packet: mode b (62), created 1516704178, name="toencrypt.txt", raw data: 835 bytes gpg: original file name='toencrypt.txt' gpg: decryption okay gpg: WARNING: message was not integrity protected Is this behavior intended? Best regards Alex Strobel gpg4o.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Tue Jan 23 15:17:31 2018 From: wk at gnupg.org (Werner Koch) Date: Tue, 23 Jan 2018 15:17:31 +0100 Subject: "decryption forced to fail" due to missing signature? In-Reply-To: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> (Alexander Strobel's message of "Tue, 23 Jan 2018 11:45:01 +0100") References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> Message-ID: <87tvvc1wxw.fsf@wheatstone.g10code.de> On Tue, 23 Jan 2018 11:45, Alexander.Strobel at giepa.de said: > gpg: WARNING: message was not integrity protected > > > Is this behavior intended? Yes. The MDC feature has been deployed 17 years ago and we can expect that all implementation use this. Not using MDC (i.e. authenticated encryption) is not a good idea due to real world attacks which may reveal the plaintext. It seems that some Bouncy Castle based implementations do not create MDC packets. 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: 227 bytes Desc: not available URL: From look at my.amazin.horse Tue Jan 23 14:20:25 2018 From: look at my.amazin.horse (Vincent Breitmoser) Date: Tue, 23 Jan 2018 14:20:25 +0100 Subject: "decryption forced to fail" due to missing signature? In-Reply-To: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> Message-ID: <20180123132024.GA32741@calamity> Hi Alexander, This is correct behavior on the decryption side: The data is encrypted as an SEDP (tag 9) packet, instead of an Integrity Protected SEDP (tag 18), so it does not use the MDC feature. Since OpenPGP uses CFB, it's extremely dangerous to consider SEDPs without either MDC or a signature as secure. In fact, RFC 4880 states "(It is important, that) implementers treat MDC errors and decompression failures as security problems." I'm glad that gpg behaves the way it does here, a quick look at git says it's been that way since 10/2015 (GnuPG 2.1.9). The real mystery is why `gpg --encrypt` creates an SEDP instead of IPSEDP. This used to depend on the recipient key's MDC feature flag, but I thought it had been enabled by default for a while now, at least for AES? Your key does have that flag, so an MDC should have been added one way or another. - V From Alexander.Strobel at giepa.de Tue Jan 23 16:28:16 2018 From: Alexander.Strobel at giepa.de (Alexander Strobel) Date: Tue, 23 Jan 2018 16:28:16 +0100 Subject: [CleanNet Spam:] Re: "decryption forced to fail" due to missing signature? In-Reply-To: <20180123132024.GA32741@calamity> References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> <20180123132024.GA32741@calamity> Message-ID: Am 23.01.2018 um 14:20 schrieb Vincent Breitmoser: > Hi Alexander, > > ... > > The real mystery is why `gpg --encrypt` creates an SEDP instead of > IPSEDP. This used to depend on the recipient key's MDC feature flag, but > I thought it had been enabled by default for a while now, at least for > AES? Your key does have that flag, so an MDC should have been added one > way or another. Thanks for your explanation, Vincent. I figured out why I ran into this problem: For testing with BouncyCastle I added "disable-mdc" to my gpg.conf ... But this does not solve the inconsistency in "showing an error and still return decrypted data" I see when MDC is missing. Maybe someone can explain this to me? :) Thanks in advance Alex Strobel -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Wed Jan 24 08:47:28 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 24 Jan 2018 08:47:28 +0100 Subject: [CleanNet Spam:] Re: "decryption forced to fail" due to missing signature? In-Reply-To: (Alexander Strobel's message of "Tue, 23 Jan 2018 16:28:16 +0100") References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> <20180123132024.GA32741@calamity> Message-ID: <877es71ywf.fsf@wheatstone.g10code.de> On Tue, 23 Jan 2018 16:28, Alexander.Strobel at giepa.de said: > But this does not solve the inconsistency in "showing an error and still > return decrypted data" I see when MDC is missing. Maybe someone can As a Unix tool gpg streams the data and does not buffer it. Thus at the time it detects a mad MDC it is too late to remove the already written data. Of course it could simply reject all non-MDC data packets but that would make debugging harder and someone else would complain why data is written despite that the signature is broken - in that case there is no way for gpg to detects this beforehand. 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: 227 bytes Desc: not available URL: From patrick at enigmail.net Wed Jan 24 08:41:13 2018 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 24 Jan 2018 08:41:13 +0100 Subject: [CleanNet Spam:] Re: "decryption forced to fail" due to missing signature? In-Reply-To: References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> <20180123132024.GA32741@calamity> Message-ID: On 23.01.18 16:28, Alexander Strobel wrote: > Am 23.01.2018 um 14:20 schrieb Vincent Breitmoser: >> Hi Alexander, >> >> ... >> >> The real mystery is why `gpg --encrypt` creates an SEDP instead of >> IPSEDP. This used to depend on the recipient key's MDC feature flag, but >> I thought it had been enabled by default for a while now, at least for >> AES? Your key does have that flag, so an MDC should have been added one >> way or another. > > Thanks for your explanation, Vincent. > I figured out why I ran into this problem: For testing with BouncyCastle > I added "disable-mdc" to my gpg.conf ... > > But this does not solve the inconsistency in "showing an error and still > return decrypted data" I see when MDC is missing. Maybe someone can > explain this to me? :) The message can be decrypted, so there is no reason from the point of view of GnuPG to not deliver it - together with an indication that there is some "error". It's up to the user (mail client) to decide how to handle the decrypted data and the error message. And apparently Enigmail doesn't have a good idea how to handle this reasonably. -Patrick From neal at walfield.org Wed Jan 24 10:49:21 2018 From: neal at walfield.org (Neal H. Walfield) Date: Wed, 24 Jan 2018 10:49:21 +0100 Subject: [CleanNet Spam:] Re: "decryption forced to fail" due to missing signature? In-Reply-To: <877es71ywf.fsf@wheatstone.g10code.de> References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> <20180123132024.GA32741@calamity> <877es71ywf.fsf@wheatstone.g10code.de> Message-ID: <874lnbsi1q.wl-neal@walfield.org> At Wed, 24 Jan 2018 08:47:28 +0100, Werner Koch wrote: > On Tue, 23 Jan 2018 16:28, Alexander.Strobel at giepa.de said: > > > But this does not solve the inconsistency in "showing an error and still > > return decrypted data" I see when MDC is missing. Maybe someone can > > As a Unix tool gpg streams the data and does not buffer it. Thus at > the time it detects a mad MDC it is too late to remove the already > written data. Streaming doesn't imply no buffering. It means that the size of the buffer is O(1) even though the size of the stream is O(n). Even a 1 byte buffer is a buffer. Given that some minimal amount of buffering is going on, it is possible to not output the last bit of data if the MDC doesn't match. Since most emails are small (gmail appears to enforce a maximum message size of 25 MB, for instance), one could set the buffer to 25 MB to make sure nearly all emails have their MDC checked. The question is: is a 25 MB buffer too large? Well, I don't think you can buy a desktop machine or phone with less than a few GB of ram today. So, 25 MB is probably safe. For servers with high-levels of concurrency, and small embedded devices, it might be reasonable to provide an option to control the amount of buffering. But, even here 1 MB will probably be acceptable, which, if managed carefully (e.g., only flush 50% of the buffer when it is full) should hopefully corrupt the output enough that it becomes unusable even if the MDC failure is ignored. FWIW, this is the approach that I'm taking in Sequoia. :) Neal From peter at digitalbrains.com Wed Jan 24 13:22:38 2018 From: peter at digitalbrains.com (Peter Lebbing) Date: Wed, 24 Jan 2018 13:22:38 +0100 Subject: Suppressing non-integrity-protected data (was: "decryption forced to fail" due to missing signature?) In-Reply-To: <874lnbsi1q.wl-neal@walfield.org> References: <1dbfd443-c6c7-e301-c57a-eab94e226b14@giepa.de> <20180123132024.GA32741@calamity> <877es71ywf.fsf@wheatstone.g10code.de> <874lnbsi1q.wl-neal@walfield.org> Message-ID: <4588fab7-b0d0-bc9d-7c12-2042eaebede5@digitalbrains.com> On 24/01/18 10:49, Neal H. Walfield wrote: > But, even here > 1 MB will probably be acceptable, which, if managed carefully (e.g., > only flush 50% of the buffer when it is full) should hopefully corrupt > the output enough that it becomes unusable even if the MDC failure is > ignored. Could you define "unusable"? As the data is already deliberately corrupted, we need to define what is the "use" of this corrupted data. If it is to function as a plaintext oracle to the attacker, at what point is that purpose no longer fulfilled? Or is there some other purpose for the corrupted data? Or is there another reason altogether to prevent access to the result of decryption, i.e., what is the threat model we're discussing? Peter. -- I use the GNU Privacy Guard (GnuPG) in combination with Enigmail. You can send me encrypted mail if you want some privacy. My key is available at -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Thu Jan 25 18:29:22 2018 From: wk at gnupg.org (Werner Koch) Date: Thu, 25 Jan 2018 18:29:22 +0100 Subject: draft-ietf-openpgp-rfc4880bis-04 Message-ID: <871sidzw25.fsf@wheatstone.g10code.de> Hi! I just published version 04 of rfc4880bis: In case you want to look at the diff to -03 in a browser: See https://gitlab.com/openpgp-wg/rfc4880bis for the repo. Changes since -03: - Additional data for AEAD has been changed to include only the packet tag but not the packet length. - Chunked AEAD mode is not used with SKESK and Secret-Key packets. - Examples for AD are provided. - Protocol numbers for AEDH and AEDSA are reserved. - TripleDES as implicit preference and mandatory algorithm has been replaced by AES-128. - RSA and ECDSA are now mandatory. - DSA and Elgamal are now optional. Note that the last 3 changes have not explicitly been discussed in the WG. The reservation of AEDH and AEDSA was requested by Derek back in April 2016, I decided to include them so that they don't get lost. Current GnuPG master has support for AEAD encryption except for the protection of secret-keys. 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: 227 bytes Desc: not available URL: From thb at libreoffice.org Tue Jan 30 15:18:10 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 15:18:10 +0100 Subject: [PATCH 5/5] port: first cut at building cpp binding natively on W32 In-Reply-To: <20180130141810.4073-1-thb@libreoffice.org> References: <20180130141810.4073-1-thb@libreoffice.org> Message-ID: <20180130141810.4073-5-thb@libreoffice.org> From: Thorsten Behrens Signed-off-by: Thorsten Behrens --- lang/cpp/src/callbacks.cpp | 2 ++ lang/cpp/src/data.h | 5 +++++ lang/cpp/src/editinteractor.cpp | 6 ++++-- lang/cpp/src/gpgmepp_export.h | 12 ++++++++---- lang/cpp/src/interfaces/dataprovider.h | 5 +++++ lang/cpp/src/key.cpp | 6 ++++++ lang/cpp/src/key.h | 1 - lang/qt/src/qgpgme_export.h | 12 ++++++++---- 8 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lang/cpp/src/callbacks.cpp b/lang/cpp/src/callbacks.cpp index f7692a03..50983943 100644 --- a/lang/cpp/src/callbacks.cpp +++ b/lang/cpp/src/callbacks.cpp @@ -40,7 +40,9 @@ #include #include #include +#if HAVE_UNISTD_H #include +#endif #include static inline gpgme_error_t make_err_from_syserror() diff --git a/lang/cpp/src/data.h b/lang/cpp/src/data.h index cc7906fb..7b171f12 100644 --- a/lang/cpp/src/data.h +++ b/lang/cpp/src/data.h @@ -31,6 +31,11 @@ #include #include +#ifdef _MSC_VER +# include +typedef SSIZE_T ssize_t; +#endif + namespace GpgME { diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp index 3e294889..518fe7ea 100644 --- a/lang/cpp/src/editinteractor.cpp +++ b/lang/cpp/src/editinteractor.cpp @@ -32,9 +32,11 @@ #include -#ifdef _WIN32 +#ifdef _MSC_VER # include -#include +# include +# include + typedef SSIZE_T ssize_t; #else # include #endif diff --git a/lang/cpp/src/gpgmepp_export.h b/lang/cpp/src/gpgmepp_export.h index 0e5302f2..ac5a0076 100644 --- a/lang/cpp/src/gpgmepp_export.h +++ b/lang/cpp/src/gpgmepp_export.h @@ -30,14 +30,14 @@ # ifndef GPGMEPP_EXPORT # ifdef BUILDING_GPGMEPP /* We are building this library */ -# ifdef WIN32 +# ifdef _MSC_VER # define GPGMEPP_EXPORT __declspec(dllexport) # else # define GPGMEPP_EXPORT __attribute__((visibility("default"))) # endif # else /* We are using this library */ -# ifdef WIN32 +# ifdef _MSC_VER # define GPGMEPP_EXPORT __declspec(dllimport) # else # define GPGMEPP_EXPORT __attribute__((visibility("default"))) @@ -46,7 +46,7 @@ # endif # ifndef GPGMEPP_NO_EXPORT -# ifdef WIN32 +# ifdef _MSC_VER # define GPGMEPP_NO_EXPORT # else # define GPGMEPP_NO_EXPORT __attribute__((visibility("hidden"))) @@ -55,7 +55,11 @@ #endif #ifndef GPGMEPP_DEPRECATED -# define GPGMEPP_DEPRECATED __attribute__ ((__deprecated__)) +# ifdef _MSC_VER +# define GPGMEPP_DEPRECATED __declspec(deprecated("deprecated")) +# else +# define GPGMEPP_DEPRECATED __attribute__ ((__deprecated__)) +# endif #endif #ifndef GPGMEPP_DEPRECATED_EXPORT diff --git a/lang/cpp/src/interfaces/dataprovider.h b/lang/cpp/src/interfaces/dataprovider.h index c8f387d6..348ff6d7 100644 --- a/lang/cpp/src/interfaces/dataprovider.h +++ b/lang/cpp/src/interfaces/dataprovider.h @@ -31,6 +31,11 @@ #include +#ifdef _MSC_VER +# include +typedef SSIZE_T ssize_t; +#endif + namespace GpgME { diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp index 66fdea96..d14ad0a0 100644 --- a/lang/cpp/src/key.cpp +++ b/lang/cpp/src/key.cpp @@ -33,10 +33,16 @@ #include #include +#if HAVE_STRINGS_H #include +#endif #include #include +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + const GpgME::Key::Null GpgME::Key::null; namespace GpgME diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h index 829bd266..360dfca8 100644 --- a/lang/cpp/src/key.h +++ b/lang/cpp/src/key.h @@ -30,7 +30,6 @@ #include "gpgmefw.h" #include -#include #include #include diff --git a/lang/qt/src/qgpgme_export.h b/lang/qt/src/qgpgme_export.h index 72927fe3..9298f2f0 100644 --- a/lang/qt/src/qgpgme_export.h +++ b/lang/qt/src/qgpgme_export.h @@ -40,14 +40,14 @@ # ifndef QGPGME_EXPORT # ifdef BUILDING_QGPGME /* We are building this library */ -# ifdef WIN32 +# ifdef _WIN32 # define QGPGME_EXPORT __declspec(dllexport) # else # define QGPGME_EXPORT __attribute__((visibility("default"))) # endif # else /* We are using this library */ -# ifdef WIN32 +# ifdef _WIN32 # define QGPGME_EXPORT __declspec(dllimport) # else # define QGPGME_EXPORT __attribute__((visibility("default"))) @@ -56,7 +56,7 @@ # endif # ifndef QGPGME_NO_EXPORT -# ifdef WIN32 +# ifdef _WIN32 # define QGPGME_NO_EXPORT # else # define QGPGME_NO_EXPORT __attribute__((visibility("hidden"))) @@ -65,7 +65,11 @@ #endif #ifndef QGPGME_DEPRECATED -# define QGPGME_DEPRECATED __attribute__ ((__deprecated__)) +# ifdef _MSC_VER +# define QGPGME_DEPRECATED __declspec(deprecated("deprecated")) +# else +# define QGPGME_DEPRECATED __attribute__ ((__deprecated__)) +# endif #endif #ifndef QGPGME_DEPRECATED_EXPORT -- 2.13.6 From thb at libreoffice.org Tue Jan 30 15:18:08 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 15:18:08 +0100 Subject: [PATCH 3/5] build: add option to disable building documentation In-Reply-To: <20180130141810.4073-1-thb@libreoffice.org> References: <20180130141810.4073-1-thb@libreoffice.org> Message-ID: <20180130141810.4073-3-thb@libreoffice.org> From: Thorsten Behrens Signed-off-by: Thorsten Behrens --- Makefile.am | 8 +++++++- configure.ac | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index e47ace50..5b081f20 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,13 +27,19 @@ EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \ ChangeLog-2011 m4/ChangeLog-2011 contrib/ChangeLog-2011 +if BUILD_DOC +doc = doc +else +doc = +endif + if RUN_GPG_TESTS tests = tests else tests = endif -SUBDIRS = src ${tests} doc lang +SUBDIRS = src ${tests} ${doc} lang # Fix the version of the spec file and create a file named VERSION # to be used for patch's Prereq: feature. diff --git a/configure.ac b/configure.ac index 608c376c..7ba8249d 100644 --- a/configure.ac +++ b/configure.ac @@ -510,6 +510,16 @@ AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP", # +# Options to disable doc building +# +build_doc=yes +AC_ARG_ENABLE([doc], AC_HELP_STRING([--disable-doc], + [do not build the documentation]), + build_doc=$enableval, build_doc=yes) +AM_CONDITIONAL([BUILD_DOC], [test "x$build_doc" != xno]) + + +# # Options to disable some regression tests # run_gpgconf_test="yes" -- 2.13.6 From thb at libreoffice.org Tue Jan 30 15:18:07 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 15:18:07 +0100 Subject: [PATCH 2/5] core: for W32 gpgrt_lock_init needs explicit calling In-Reply-To: <20180130141810.4073-1-thb@libreoffice.org> References: <20180130141810.4073-1-thb@libreoffice.org> Message-ID: <20180130141810.4073-2-thb@libreoffice.org> From: Thorsten Behrens -- Make sure the gpgrt_lock_init gets called in libgpg-error, otherwise several critical section statics are uninitialized on W32. Signed-off-by: Thorsten Behrens --- src/version.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/version.c b/src/version.c index 99698fa7..8f2844e9 100644 --- a/src/version.c +++ b/src/version.c @@ -66,6 +66,9 @@ do_subsystem_inits (void) return; #ifdef HAVE_W32_SYSTEM + // initialize libgpg-error stuff + gpg_err_init(); + /* We need to make sure that the sockets are initialized. */ { WSADATA wsadat; -- 2.13.6 From thb at libreoffice.org Tue Jan 30 15:18:06 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 15:18:06 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C Message-ID: <20180130141810.4073-1-thb@libreoffice.org> From: Thorsten Behrens * lang/cpp/src/context.h: add bool parameter * lang/cpp/src/context.cpp: run gpgme_op_export with GPGME_EXPORT_MODE_MINIMAL if flag is set Signed-off-by: Thorsten Behrens --- lang/cpp/src/context.cpp | 16 ++++++++-------- lang/cpp/src/context.h | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp index 135e4d56..dbc98156 100644 --- a/lang/cpp/src/context.cpp +++ b/lang/cpp/src/context.cpp @@ -557,14 +557,14 @@ KeyGenerationResult Context::keyGenerationResult() const } } -Error Context::exportPublicKeys(const char *pattern, Data &keyData) +Error Context::exportPublicKeys(const char *pattern, Data &keyData, bool minimal) { d->lastop = Private::Export; Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0)); + return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); } -Error Context::exportPublicKeys(const char *patterns[], Data &keyData) +Error Context::exportPublicKeys(const char *patterns[], Data &keyData, bool minimal) { d->lastop = Private::Export; #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN @@ -574,17 +574,17 @@ Error Context::exportPublicKeys(const char *patterns[], Data &keyData) } #endif Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0)); + return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); } -Error Context::startPublicKeyExport(const char *pattern, Data &keyData) +Error Context::startPublicKeyExport(const char *pattern, Data &keyData, bool minimal) { d->lastop = Private::Export; Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0)); + return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); } -Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) +Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, bool minimal) { d->lastop = Private::Export; #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN @@ -594,7 +594,7 @@ Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) } #endif Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0)); + return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); } ImportResult Context::importKeys(const Data &data) diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h index 4cd5b307..d97d7dd8 100644 --- a/lang/cpp/src/context.h +++ b/lang/cpp/src/context.h @@ -178,10 +178,10 @@ public: // Key Export // - GpgME::Error exportPublicKeys(const char *pattern, Data &keyData); - GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData); - GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData); - GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData); + GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, bool minimal=false); + GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, bool minimal=false); + GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, bool minimal=false); + GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, bool minimal=false); // // Key Import -- 2.13.6 From thb at libreoffice.org Tue Jan 30 15:18:09 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 15:18:09 +0100 Subject: [PATCH 4/5] port: first cut at native W32 building In-Reply-To: <20180130141810.4073-1-thb@libreoffice.org> References: <20180130141810.4073-1-thb@libreoffice.org> Message-ID: <20180130141810.4073-4-thb@libreoffice.org> From: Thorsten Behrens Signed-off-by: Thorsten Behrens --- m4/ax_cxx_compile_stdcxx.m4 | 2 +- src/Makefile.am | 2 +- src/dirinfo.c | 4 ++++ src/mbox-util.c | 2 ++ src/priv-io.h | 3 +++ src/util.h | 3 +++ src/versioninfo.rc.in | 1 - src/vfs-mount.c | 4 ++++ src/w32-glib-io.c | 1 + src/w32-util.c | 2 +- 10 files changed, 20 insertions(+), 4 deletions(-) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 index de3d0121..6834edd6 100644 --- a/m4/ax_cxx_compile_stdcxx.m4 +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -156,7 +156,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ #error "This is not a C++ compiler" -#elif __cplusplus < 201103L +#elif __cplusplus < 201103L && !(defined _MSC_VER) #error "This is not a C++11 compiler" diff --git a/src/Makefile.am b/src/Makefile.am index ce6f1d4e..c056f80e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,7 +120,7 @@ LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) SUFFIXES = .rc .lo .rc.lo: - $(LTRCCOMPILE) -i "$<" -o "$@" + $(LTRCCOMPILE) -i $< -o $@ gpgme_res = versioninfo.lo no_undefined = -no-undefined diff --git a/src/dirinfo.c b/src/dirinfo.c index 73744124..285ed097 100644 --- a/src/dirinfo.c +++ b/src/dirinfo.c @@ -33,6 +33,10 @@ DEFINE_STATIC_LOCK (dirinfo_lock); +#ifndef F_OK +#define F_OK 0 +#endif + /* Constants used internally to select the data. */ enum { diff --git a/src/mbox-util.c b/src/mbox-util.c index 0dafc2a2..a2adaf31 100644 --- a/src/mbox-util.c +++ b/src/mbox-util.c @@ -28,7 +28,9 @@ #include #include #include +#if HAVE_UNISTD_H #include +#endif #include #include "mbox-util.h" diff --git a/src/priv-io.h b/src/priv-io.h index 23061756..6861eae0 100644 --- a/src/priv-io.h +++ b/src/priv-io.h @@ -36,6 +36,9 @@ #ifdef HAVE_SYS_TYPES_H # include #endif +#if _MSC_VER +typedef int pid_t; +#endif /* A single file descriptor passed to spawn. For child fds, dup_to diff --git a/src/util.h b/src/util.h index b4043ed1..45a17566 100644 --- a/src/util.h +++ b/src/util.h @@ -39,6 +39,9 @@ #ifdef HAVE_UNISTD_H # include #endif +#ifdef _MSC_VER +typedef int pid_t; +#endif #include "gpgme.h" diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in index 2b1cc811..00cbc751 100644 --- a/src/versioninfo.rc.in +++ b/src/versioninfo.rc.in @@ -14,7 +14,6 @@ #line __LINE__ "versioninfo.rc.in" -#include VS_VERSION_INFO VERSIONINFO diff --git a/src/vfs-mount.c b/src/vfs-mount.c index 68a8efe9..66d7e076 100644 --- a/src/vfs-mount.c +++ b/src/vfs-mount.c @@ -68,7 +68,11 @@ _gpgme_vfs_mount_status_handler (void *priv, const char *code, const char *args) if (err) return err; +#if _MSC_VER + if (! _stricmp ("MOUNTPOINT", code)) +#else if (! strcasecmp ("MOUNTPOINT", code)) +#endif { if (opd->result.mount_dir) free (opd->result.mount_dir); diff --git a/src/w32-glib-io.c b/src/w32-glib-io.c index 66dc9bf7..a80653f8 100644 --- a/src/w32-glib-io.c +++ b/src/w32-glib-io.c @@ -37,6 +37,7 @@ #ifdef HAVE_SYS_TYPES_H # include #endif +#include #include #include #include diff --git a/src/w32-util.c b/src/w32-util.c index 5b02c7ea..5c474499 100644 --- a/src/w32-util.c +++ b/src/w32-util.c @@ -721,7 +721,7 @@ my_mkstemp (char *tmpl) v /= 62; XXXXXX[5] = letters[v % 62]; - fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL); if (fd >= 0) { gpg_err_set_errno (save_errno); -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:12:54 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 20:12:54 +0100 Subject: [PATCH 1/3] build: permit disabling rpath Message-ID: <20180130191256.12813-1-thb@libreoffice.org> From: Thorsten Behrens Signed-off-by: Thorsten Behrens --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 992d1bd..426492a 100644 --- a/configure.ac +++ b/configure.ac @@ -398,6 +398,9 @@ if test "$gcry_cv_visibility_attribute" = "yes" \ CFLAGS="$CFLAGS -fvisibility=hidden" fi +# permit disabling rpath +AC_LIB_RPATH + # # Check whether ld supports a version script. # (Actually not a check but a list of systems which are known to support it.) -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:12:56 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 20:12:56 +0100 Subject: [PATCH 3/3] port: get this to build with clang-cl on W32 In-Reply-To: <20180130191256.12813-1-thb@libreoffice.org> References: <20180130191256.12813-1-thb@libreoffice.org> Message-ID: <20180130191256.12813-3-thb@libreoffice.org> From: Stephan Bergmann Signed-off-by: Thorsten Behrens --- src/gpg-error.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index 46e8f53..e359262 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -142,7 +142,7 @@ typedef unsigned int gpg_error_t; /* GCC feature test. */ -#if __GNUC__ +#if defined __GNUC__ # define _GPG_ERR_GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:12:55 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 20:12:55 +0100 Subject: [PATCH 2/3] port: first cut at native W32 building In-Reply-To: <20180130191256.12813-1-thb@libreoffice.org> References: <20180130191256.12813-1-thb@libreoffice.org> Message-ID: <20180130191256.12813-2-thb@libreoffice.org> From: Thorsten Behrens Signed-off-by: Thorsten Behrens --- src/Makefile.am | 10 ++++++---- src/estream-printf.c | 6 +++++- src/estream.c | 16 ++++++++++++++-- src/gpg-error.c | 2 ++ src/init.c | 6 +++--- src/mkheader.c | 14 +++++++++++++- src/versioninfo.rc.in | 2 -- src/w32-estream.c | 5 +++++ src/w32-gettext.c | 4 ++-- 9 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4446612..253da3b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,8 +38,10 @@ bin_PROGRAMS = gpg-error if HAVE_W32_SYSTEM noinst_PROGRAMS = gen-w32-lock-obj +exe_extension = .exe else noinst_PROGRAMS = gen-posix-lock-obj +exe_extension = endif # Distributed lock object definitions for cross compilation. @@ -264,7 +266,7 @@ gpg-error.def: Makefile gpg-error.def.in # It is correct to use $(CC_FOR_BUILD) here. We want to run the # program at build time. -mkerrcodes: mkerrcodes.c mkerrcodes.h Makefile +mkerrcodes${exe_extension}: mkerrcodes.c mkerrcodes.h Makefile $(CC_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkerrcodes.c if HAVE_W32CE_SYSTEM @@ -274,7 +276,7 @@ mkw32errmap: mkw32errmap.c mkw32errmap.tab.h Makefile $(CC_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkw32errmap.c endif -code-from-errno.h: mkerrcodes Makefile +code-from-errno.h: mkerrcodes${exe_extension} Makefile ./mkerrcodes | $(AWK) -f $(srcdir)/mkerrcodes2.awk >$@ errnos-sym.h: Makefile mkstrtable.awk errnos.in @@ -283,7 +285,7 @@ errnos-sym.h: Makefile mkstrtable.awk errnos.in $(srcdir)/errnos.in >$@ -mkheader: mkheader.c Makefile +mkheader${exe_extension}: mkheader.c Makefile $(CC_FOR_BUILD) -g -O0 -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c parts_of_gpg_error_h = \ @@ -310,7 +312,7 @@ endif # We also depend on versioninfo.rc because that is build by # config.status and thus has up-to-date version numbers. -gpg-error.h: Makefile mkheader $(parts_of_gpg_error_h) \ +gpg-error.h: Makefile mkheader${exe_extension} $(parts_of_gpg_error_h) \ versioninfo.rc ../config.h $(pre_mkheader_cmds) ./mkheader $(host_os) $(host_triplet) $(srcdir)/gpg-error.h.in \ diff --git a/src/estream-printf.c b/src/estream-printf.c index f1cbcde..194d814 100644 --- a/src/estream-printf.c +++ b/src/estream-printf.c @@ -85,7 +85,11 @@ #include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif #include #include #include diff --git a/src/estream.c b/src/estream.c index dd2b289..e466a30 100644 --- a/src/estream.c +++ b/src/estream.c @@ -74,12 +74,15 @@ # include #endif #include -#include #include #include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif #include #include #include @@ -112,6 +115,15 @@ #ifdef HAVE_W32_SYSTEM +# ifndef S_IRUSR +# define S_IRUSR _S_IREAD +# endif +# ifndef S_IWUSR +# define S_IWUSR _S_IWRITE +# endif +# ifndef S_IXUSR +# define S_IXUSR 0x00400000 +# endif # ifndef S_IRGRP # define S_IRGRP S_IRUSR # endif diff --git a/src/gpg-error.c b/src/gpg-error.c index f890883..2c36e36 100644 --- a/src/gpg-error.c +++ b/src/gpg-error.c @@ -98,6 +98,8 @@ i18n_init (void) #include +#define strncasecmp _strnicmp +#define strcasecmp _stricmp static char * get_locale_dir (void) diff --git a/src/init.c b/src/init.c index 89475d3..1fb83b1 100644 --- a/src/init.c +++ b/src/init.c @@ -88,7 +88,7 @@ gpg_error_t _gpg_err_init (void) { #ifdef HAVE_W32_SYSTEM -# ifdef DLL_EXPORT +# ifdef HAVE_DLL_INIT /* We always have a constructor and thus this function is called automatically. Due to the way the C init code of mingw works, the constructors are called before our DllMain function is @@ -130,7 +130,7 @@ _gpg_err_init (void) void _gpg_err_deinit (int mode) { -#if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT) +#if defined (HAVE_W32_SYSTEM) && !defined(HAVE_DLL_INIT) struct tls_space_s *tls; tls = TlsGetValue (tls_index); @@ -558,7 +558,7 @@ _gpg_w32ce_strerror (int err) /* Entry point called by the DLL loader. */ -#ifdef DLL_EXPORT +#ifdef HAVE_DLL_INIT int WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) { diff --git a/src/mkheader.c b/src/mkheader.c index 997cab5..4b345d1 100644 --- a/src/mkheader.c +++ b/src/mkheader.c @@ -16,7 +16,11 @@ #include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif #define PGM "mkheader" @@ -410,12 +414,20 @@ try_include_file (const char *fname, int lnr, const char *name, repl_flag = !!strchr (name, '&'); incfname = mk_include_name (name, repl_flag? host_triplet : NULL); +#ifdef _WIN32 + rc = _access (incfname, 04); +#else rc = access (incfname, R_OK); +#endif if (rc && repl_flag) { free (incfname); incfname = mk_include_name (name, host_os); +#ifdef _WIN32 + rc = _access (incfname, 04); +#else rc = access (incfname, R_OK); +#endif } if (!rc) include_file (fname, lnr, name, outf); diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in index 0986a42..6bfd3ec 100644 --- a/src/versioninfo.rc.in +++ b/src/versioninfo.rc.in @@ -14,8 +14,6 @@ #line __LINE__ "versioninfo.rc.in" -#include - VS_VERSION_INFO VERSIONINFO FILEVERSION @BUILD_FILEVERSION@ diff --git a/src/w32-estream.c b/src/w32-estream.c index 2122c59..1a16d8f 100644 --- a/src/w32-estream.c +++ b/src/w32-estream.c @@ -45,6 +45,11 @@ #include "gpgrt-int.h" +#ifdef _WIN32 +/* no ssize_t in windows std headers, emulate for native build */ +typedef SSIZE_T ssize_t; +#endif + /* * In order to support es_poll on Windows, we create a proxy shim that * we use as the estream I/O functions. This shim creates reader and diff --git a/src/w32-gettext.c b/src/w32-gettext.c index 3b54ebd..71716ce 100644 --- a/src/w32-gettext.c +++ b/src/w32-gettext.c @@ -1180,7 +1180,7 @@ static char *current_domainname; DLL. If used as a static lib we can't control the process set; for example it might be used with a main module which is not build with mingw and thus does not know how to call the constructors. */ -#ifdef DLL_EXPORT +#ifdef HAVE_DLL_INIT static void module_init (void) _GPG_ERR_CONSTRUCTOR; #endif static void @@ -1195,7 +1195,7 @@ module_init (void) } } -#if !defined(DLL_EXPORT) || !defined(_GPG_ERR_HAVE_CONSTRUCTOR) +#if !defined(HAVE_DLL_INIT) || !defined(_GPG_ERR_HAVE_CONSTRUCTOR) void _gpg_w32__init_gettext_module (void) { -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:29:30 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 20:29:30 +0100 Subject: [PATCH 1/2] port: avoid breaking configure on cygwin Message-ID: <20180130192931.13686-1-thb@libreoffice.org> From: Thorsten Behrens -- Signed-off-by: Thorsten Behrens --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e824b39..eec8190 100644 --- a/configure.ac +++ b/configure.ac @@ -456,10 +456,12 @@ else [Defined if LOCAL_PEEREID is supported (NetBSD specific)]) else # (Open)Solaris - AC_CHECK_FUNCS([getpeerucred], AC_CHECK_HEADERS([ucred.h])) + AC_CHECK_FUNCS([getpeerucred]) if test $ac_cv_func_getpeerucred != yes; then # FreeBSD AC_CHECK_FUNCS([getpeereid]) + else + AC_CHECK_HEADERS([ucred.h]) fi fi fi -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:29:31 2018 From: thb at libreoffice.org (thb at libreoffice.org) Date: Tue, 30 Jan 2018 20:29:31 +0100 Subject: [PATCH 2/2] port: first cut at native W32 building In-Reply-To: <20180130192931.13686-1-thb@libreoffice.org> References: <20180130192931.13686-1-thb@libreoffice.org> Message-ID: <20180130192931.13686-2-thb@libreoffice.org> From: Thorsten Behrens Co-authored-by: Stephan Bergmann Signed-off-by: Thorsten Behrens --- src/Makefile.am | 8 ++++---- src/assuan-handler.c | 2 +- src/mkheader.c | 2 +- src/versioninfo.rc.in | 1 - 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index f353e29..0792ec8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -83,7 +83,7 @@ endif if HAVE_W32_SYSTEM -LTRCCOMPILE = $(LIBTOOL) --mode=compile $(RC) \ +LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RC) \ `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \ sed -e 's/-I/--include-dir /g;s/-D/--define /g'` @@ -144,11 +144,11 @@ install-exec-hook: $(DESTDIR)$(bindir)/gpgcedev.dll endif -mkheader: mkheader.c Makefile +mkheader$(EXEEXT): mkheader.c Makefile $(CC_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c -assuan.h: assuan.h.in mkheader $(parts_of_assuan_h) - ./mkheader $(host_os) $(srcdir)/assuan.h.in \ +assuan.h: assuan.h.in mkheader$(EXEEXT) $(parts_of_assuan_h) + ./mkheader$(EXEEXT) $(host_os) $(srcdir)/assuan.h.in \ @VERSION@ @VERSION_NUMBER@ >$@ diff --git a/src/assuan-handler.c b/src/assuan-handler.c index 2299fcd..5cc0fb0 100644 --- a/src/assuan-handler.c +++ b/src/assuan-handler.c @@ -396,7 +396,7 @@ static struct { { "INPUT", std_handler_input, std_help_input, 0 }, { "OUTPUT", std_handler_output, std_help_output, 0 }, - { } }; +}; /** diff --git a/src/mkheader.c b/src/mkheader.c index 0ee0944..e7a6f5c 100644 --- a/src/mkheader.c +++ b/src/mkheader.c @@ -100,7 +100,7 @@ write_special (const char *fname, int lnr, const char *tag) "# include \n" "#endif\n", stdout); else - fputs ("#include \n", stdout); + fputs ("#include \n", stdout); } else if (!strcmp (tag, "include:types")) { diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in index f9e7cb4..0c235c3 100644 --- a/src/versioninfo.rc.in +++ b/src/versioninfo.rc.in @@ -15,7 +15,6 @@ #line __LINE__ "versioninfo.rc.in" -#include VS_VERSION_INFO VERSIONINFO -- 2.13.6 From thb at libreoffice.org Tue Jan 30 20:57:33 2018 From: thb at libreoffice.org (Thorsten Behrens) Date: Tue, 30 Jan 2018 20:57:33 +0100 Subject: LibreOffice with gpgme/OpenPGP support for ODF signing and document encryption Message-ID: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> 'evening all, so to put the chunk of patches I've just sent to this list into perspective (and also perhaps you've heard about it elsewhere) - we spent some time last year to provide LibreOffice with a working OpenPGP backend to the already-existing X509 xml crypto engine. Which means, for the upcoming LibreOffice 6.0, you should be able to transparently use your GPG keys for doing the obvious things. On Windows, OSX, and Linux. The part that was surprisingly difficult was getting gpgme + dependencies to build on cygwin+msvc, which is a hard requirement for LibreOffice on that platform. Still, with the patches on the list now, the code builds and works (albeit some 5% or so gross hackery remains, to work around libtool sillyness - this stays downstream until I've figured out a cleaner way). Please do reach out for questions; I'll be at FOSDEM this coming weekend. All the best, -- Thorsten -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: Digital signature URL: From gniibe at fsij.org Wed Jan 31 00:33:53 2018 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 31 Jan 2018 08:33:53 +0900 Subject: [PATCH 1/2] port: avoid breaking configure on cygwin In-Reply-To: <20180130192931.13686-1-thb@libreoffice.org> References: <20180130192931.13686-1-thb@libreoffice.org> Message-ID: <871si6syzi.fsf@fsij.org> thb at libreoffice.org wrote: > Signed-off-by: Thorsten Behrens > --- > configure.ac | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) I think it's to libassuan, right? I am currently (back) porting gnupg/agent/command-ssh.c thing to libassuan, which touches same files. > --- a/configure.ac > +++ b/configure.ac > @@ -456,10 +456,12 @@ else > [Defined if LOCAL_PEEREID is supported (NetBSD specific)]) > else > # (Open)Solaris > - AC_CHECK_FUNCS([getpeerucred], AC_CHECK_HEADERS([ucred.h])) > + AC_CHECK_FUNCS([getpeerucred]) > if test $ac_cv_func_getpeerucred != yes; then > # FreeBSD > AC_CHECK_FUNCS([getpeereid]) > + else > + AC_CHECK_HEADERS([ucred.h]) > fi > fi > fi > -- Please describe your problem. For me, it is just moving the check (I compared the resulted configure scripts (with your change, original)). I wonder the reason why original version breaked on Cygwin and how. I'd just moving the check unconditional (like one in gnupg), since we also need to check sys/ucred.h. -- From thb at libreoffice.org Wed Jan 31 01:41:40 2018 From: thb at libreoffice.org (Thorsten Behrens) Date: Wed, 31 Jan 2018 01:41:40 +0100 Subject: [PATCH 1/2] port: avoid breaking configure on cygwin In-Reply-To: <871si6syzi.fsf@fsij.org> References: <20180130192931.13686-1-thb@libreoffice.org> <871si6syzi.fsf@fsij.org> Message-ID: <20180131004140.2kz727wuo4lf6j55@thinkpad.thebehrens.net> NIIBE Yutaka wrote: > I think it's to libassuan, right? > Right - and sorry should've tagged the patch series accordingly. > I wonder the reason why original version breaked on Cygwin and how. > IIRC the nested macro got m4 or autoconf's knickers in a twist - > I'd just moving the check unconditional (like one in gnupg), since > we also need to check sys/ucred.h. > Fine by me, cygwin/msvc gonna be a bit of a moving target anyway for a while, I suspect. Cheers, -- Thorsten -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: Digital signature URL: From wk at gnupg.org Wed Jan 31 09:59:47 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 09:59:47 +0100 Subject: LibreOffice with gpgme/OpenPGP support for ODF signing and document encryption In-Reply-To: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> (Thorsten Behrens's message of "Tue, 30 Jan 2018 20:57:33 +0100") References: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> Message-ID: <87fu6mtncs.fsf@wheatstone.g10code.de> On Tue, 30 Jan 2018 20:57, thb at libreoffice.org said: > Which means, for the upcoming LibreOffice 6.0, you should be able to > transparently use your GPG keys for doing the obvious things. On > Windows, OSX, and Linux. :-) > The part that was surprisingly difficult was getting gpgme + > dependencies to build on cygwin+msvc, which is a hard requirement for Dues that mean LibreOffice for Windows is a Cygwin build? What does Cygwin+msvc mean - this seems to be a controdiction to me. > Please do reach out for questions; I'll be at FOSDEM this coming > weekend. Let's have a brief meeting there. I'll send you my ophone number. 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: 227 bytes Desc: not available URL: From wk at gnupg.org Wed Jan 31 10:02:20 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 10:02:20 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C In-Reply-To: <20180130141810.4073-1-thb@libreoffice.org> (thb@libreoffice.org's message of "Tue, 30 Jan 2018 15:18:06 +0100") References: <20180130141810.4073-1-thb@libreoffice.org> Message-ID: <87bmhatn8j.fsf@wheatstone.g10code.de> On Tue, 30 Jan 2018 15:18, thb at libreoffice.org said: > -Error Context::exportPublicKeys(const char *pattern, Data &keyData) > +Error Context::exportPublicKeys(const char *pattern, Data &keyData, That is an ABI change and thus a no-go. Also the use of a dedicated flag for a very special option is not a good idea. We need a clean design for this. You should also explain why you need this. 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: 227 bytes Desc: not available URL: From bernhard at intevation.de Wed Jan 31 10:25:32 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Wed, 31 Jan 2018 10:25:32 +0100 Subject: LibreOffice with gpgme/OpenPGP support for ODF signing and document encryption In-Reply-To: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> References: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> Message-ID: <201801311025.36253.bernhard@intevation.de> Hi Thorsten, Am Dienstag 30 Januar 2018 20:57:33 schrieb Thorsten Behrens: > Which means, for the upcoming LibreOffice 6.0, you should be able to > transparently use your GPG keys for doing the obvious things. On > Windows, OSX, and Linux. thanks for sharing the news and submitting patches! Personally I cannot judge if and how they can be integrated. Gpg4win crosscompiles for windows and thus cygwin+msvc seems to be a new toolchain. > The part that was surprisingly difficult was getting gpgme + > dependencies to build on cygwin+msvc, which is a hard requirement for > LibreOffice on that platform. Still, with the patches on the list now, > the code builds and works (albeit some 5% or so gross hackery remains, > to work around libtool sillyness - this stays downstream until I've > figured out a cleaner way). Can you send a link to the code that you have in your public repo somwhere? Also it would be cool if you document your contract somewhere, so it stays on record. (For some of the contracts related to Gpg4win, we used https://wiki.gnupg.org/Gpg4win, at your deliberation you can use the wiki as well. At least I'd like to link to it. :) ) Best Regards, Bernhard -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 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: 473 bytes Desc: This is a digitally signed message part. URL: From bernhard at intevation.de Wed Jan 31 10:57:35 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Wed, 31 Jan 2018 10:57:35 +0100 Subject: WKD submission without email client Message-ID: <201801311057.39369.bernhard@intevation.de> Werner, Andre, just wondering today: If my email client does not yet support managing of my pubkeys via WKD do we somewhere have instructions or scripts to do this manually? There is https://wiki.gnupg.org/WKS?highlight=%28submission%29#Test_your_installation which basically are instructions how to do this manually with gpg-wks-client This can be improved and there are systems where we do not have gpg-wks-client available or it is not easy to send the mail properly. a) Debian Stable (Stretch) does not have gpg-wks-client by default https://packages.debian.org/source/stretch/gnupg2 (Testing has it meanwhile, thanks dkg). b) On windows Gpg4win 3 comes with gpg-wks-client, but I guess that the part of feeding the output email into the email may not work that easily. Potential solutions: * Add a cross plattform python script that may be able to be downloaded and used and works more easily. * Provide gpg-wks-client for more plattforms (backport) * Add instructions for windows that are step by step * Add this to Kleopatra or GpgOL to cover larger fractions of users on windows. And then place it on the wiki. Best Regards, Bernhard -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 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: 473 bytes Desc: This is a digitally signed message part. URL: From thb at libreoffice.org Wed Jan 31 11:13:33 2018 From: thb at libreoffice.org (Thorsten Behrens) Date: Wed, 31 Jan 2018 11:13:33 +0100 Subject: LibreOffice with gpgme/OpenPGP support for ODF signing and document encryption In-Reply-To: <201801311025.36253.bernhard@intevation.de> References: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> <201801311025.36253.bernhard@intevation.de> Message-ID: <20180131101333.dhqlkihrztd7ke2z@thinkpad.thebehrens.net> Hi Bernhard, Bernhard Reiter wrote: > Personally I cannot judge if and how they can be integrated. > Gpg4win crosscompiles for windows and thus cygwin+msvc seems > to be a new toolchain. > I know, and that was the challenge at least for the pieces that we needed to link into LibreOffice. For obvious reasons, it is a hard requirement that LibreOffice builds from source, including all 3rd party dependencies. > Can you send a link to the code that you have in your public repo somwhere? > Here goes: - gpgme: https://cgit.freedesktop.org/libreoffice/core/tree/external/gpgmepp - libassuan: https://cgit.freedesktop.org/libreoffice/core/tree/external/libassuan - libgpg-error: https://cgit.freedesktop.org/libreoffice/core/tree/external/libgpg-error > Also it would be cool if you document your contract somewhere, so it > stays on record. > We've collected some pointers here: https://wiki.documentfoundation.org/Development/gpg4libre The feature itself was funded last year by the German Federal Office for Information Security, for which the LibreOffice project is very grateful. Cheers, -- Thorsten -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: Digital signature URL: From wk at gnupg.org Wed Jan 31 11:15:01 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 11:15:01 +0100 Subject: WKD submission without email client In-Reply-To: <201801311057.39369.bernhard@intevation.de> (Bernhard Reiter's message of "Wed, 31 Jan 2018 10:57:35 +0100") References: <201801311057.39369.bernhard@intevation.de> Message-ID: <87y3kes5ay.fsf@wheatstone.g10code.de> On Wed, 31 Jan 2018 10:57, bernhard at intevation.de said: > just wondering today: If my email client does not yet support managing of my > pubkeys via WKD do we somewhere have instructions or scripts to do this > manually? The long term idea is to have an abstract interface in gpg, for example "gpg --publish" which takes care of publishing a key. In the meantime gpg-wks-client can be used on _standard_ Unix boxes; there is a man page but the real problem is that on Windows and, according to what I have heard, the standard sendmail wrapper is not anymore installed by default on Linux boxes. Thus the only way to send an email is by using a MUA that supports publishing a key (Kmail and Enigmail right now) > * Add a cross plattform python script that may be able to > be downloaded and used and works more easily. Python is usually not available on Windows. For Unix we could do a standard script but that is not really better than the existing client. > * Provide gpg-wks-client for more plattforms (backport) It is available for all platforms, whether a distro installs it is not our choice. > * Add instructions for windows that are step by step Does not work because we can't send mail from the command line. > * Add this to Kleopatra or GpgOL to cover larger fractions of > users on windows. It is possible to do this for GpgOL. Kleopatra needs a MUA. 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: 227 bytes Desc: not available URL: From thb at libreoffice.org Wed Jan 31 11:29:46 2018 From: thb at libreoffice.org (Thorsten Behrens) Date: Wed, 31 Jan 2018 11:29:46 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C In-Reply-To: <87bmhatn8j.fsf@wheatstone.g10code.de> References: <20180130141810.4073-1-thb@libreoffice.org> <87bmhatn8j.fsf@wheatstone.g10code.de> Message-ID: <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> Werner Koch wrote: > That is an ABI change and thus a no-go. > Right - needs recompiling all client code. Though for c++, ABI tends to break all the time, so how large a problem is that really? > Also the use of a dedicated flag for a very special option is not a > good idea. We need a clean design for this. > I took inspiration from other places in context.h ;) More seriously, I only see bad options here. We either: - introduce global state - duplicate all four exportPublic-functions & add a qualifier to the method names - or admit this was an oversight to not expose the gpgme_op_export() flags from c++, and break ABI Which one would you prefer? > You should also explain why you need this. > Eh, that should be obvious? I need to opionally export keys minimally, but the cpp binding does not expose gpgme_op_export()'s flag parameter. I also cannot (easily) fallback to using the C binding directly, due to stuff being class-private. Cheers, -- Thorsten -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: Digital signature URL: From thb at libreoffice.org Wed Jan 31 11:44:02 2018 From: thb at libreoffice.org (Thorsten Behrens) Date: Wed, 31 Jan 2018 11:44:02 +0100 Subject: LibreOffice with gpgme/OpenPGP support for ODF signing and document encryption In-Reply-To: <87fu6mtncs.fsf@wheatstone.g10code.de> References: <20180130195733.earyp73mbqw5gqbd@thinkpad.thebehrens.net> <87fu6mtncs.fsf@wheatstone.g10code.de> Message-ID: <20180131104402.gkvsk73hrl7ttzxy@thinkpad.thebehrens.net> Werner Koch wrote: > Dues that mean LibreOffice for Windows is a Cygwin build? > > What does Cygwin+msvc mean - this seems to be a controdiction to me. > LibreOffice is a beast - so the --build is cygwin, _except_ for the compiler, which is msvc. And --host is obviously W32/W64 native. There are hysterical reasons for that odd setup. ;) > Let's have a brief meeting there. I'll send you my ophone number. > Happy to! Cheers, -- Thorsten -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 949 bytes Desc: Digital signature URL: From bernhard at intevation.de Wed Jan 31 12:29:58 2018 From: bernhard at intevation.de (Bernhard Reiter) Date: Wed, 31 Jan 2018 12:29:58 +0100 Subject: WKD submission without email client In-Reply-To: <87y3kes5ay.fsf@wheatstone.g10code.de> References: <201801311057.39369.bernhard@intevation.de> <87y3kes5ay.fsf@wheatstone.g10code.de> Message-ID: <201801311230.05384.bernhard@intevation.de> Am Mittwoch 31 Januar 2018 11:15:01 schrieb Werner Koch: > > If my email client does not yet support managing of > > my pubkeys via WKD do we somewhere have instructions or scripts to do > > this manually? > > The long term idea is to have an abstract interface in gpg, for example > "gpg --publish" which takes care of publishing a key. In the meantime > gpg-wks-client can be used on _standard_ Unix boxes; At first thought I believe that sending email should not be done directly from "gpg". SMTP and the authentication to the receiving server is complex that I see it in GnuPG on the long run. We really need to build WKD managing into more email clients. > > * Add a cross plattform python script that may be able to > > be downloaded and used and works more easily. > > Python is usually not available on Windows. For Unix we could do a > standard script but that is not really better than the existing client. The smtpclient module would be cross plattform and is part of Python's standard library. Okay, on windows we would need to either bundle Python itself into a single binary or have users download Python. I'd say that the step of sending the email is hard even on GNU-systems so in case there is no sendmail or no gpg-wks-client, it would be useful to have. An alternative would be a go implementation and a single binary https://godoc.org/net/smtp but we would need to build one for each hardware plattform. > > * Provide gpg-wks-client for more plattforms (backport) > > It is available for all platforms, whether a distro installs it is not > our choice. But a practical problem for our users on these platforms. > > * Add instructions for windows that are step by step > > Does not work because we can't send mail from the command line. Maybe we'll find a way to do with with several typical windows clients like Outlook, Thunderbird, Claws.. Best, Bernhard -- www.intevation.de/~bernhard ? +49 541 33 508 3-3 Intevation GmbH, Osnabr?ck, DE; Amtsgericht Osnabr?ck, HRB 18998 Gesch?ftsf?hrer Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: This is a digitally signed message part. URL: From aheinecke at intevation.de Wed Jan 31 14:07:28 2018 From: aheinecke at intevation.de (Andre Heinecke) Date: Wed, 31 Jan 2018 14:07:28 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C In-Reply-To: <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> References: <20180130141810.4073-1-thb@libreoffice.org> <87bmhatn8j.fsf@wheatstone.g10code.de> <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> Message-ID: <1659414.VPt5P5tGK7@esus> Hi, On Wednesday, January 31, 2018 11:29:46 AM CET Thorsten Behrens wrote: > Werner Koch wrote: > > That is an ABI change and thus a no-go. > > > Right - needs recompiling all client code. Though for c++, ABI tends > to break all the time, so how large a problem is that really? I try to keep ABI changes to a minimum. I don't think its necessary here to break ABI. ABI breaks always mean work for packagers and if we can avoid that easily we should ;-) > > Also the use of a dedicated flag for a very special option is not a > > good idea. We need a clean design for this. > > > I took inspiration from other places in context.h ;) > > More seriously, I only see bad options here. We either: > - introduce global state > - duplicate all four exportPublic-functions & add a qualifier to the > method names > - or admit this was an oversight to not expose the gpgme_op_export() > flags from c++, and break ABI > > Which one would you prefer? exportPublicKeys is already overloaded so adding another overload is not an ABI Break. Just add another overload with a generic flags parameter and define ExportFlags as an enum with the values of gpgme's export flags. The other patches look ok to me. Thanks! 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: 228 bytes Desc: This is a digitally signed message part. URL: From wk at gnupg.org Wed Jan 31 14:01:38 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 14:01:38 +0100 Subject: WKD submission without email client In-Reply-To: <201801311230.05384.bernhard@intevation.de> (Bernhard Reiter's message of "Wed, 31 Jan 2018 12:29:58 +0100") References: <201801311057.39369.bernhard@intevation.de> <87y3kes5ay.fsf@wheatstone.g10code.de> <201801311230.05384.bernhard@intevation.de> Message-ID: <87lggerxl9.fsf@wheatstone.g10code.de> On Wed, 31 Jan 2018 12:29, bernhard at intevation.de said: > from "gpg". SMTP and the authentication to the receiving server is complex > that I see it in GnuPG on the long run. Na, that is not complex. The real problem is to tell the user that the credentials and parameters for the mail account are also required by GnuPG. That would be surprising. Even if you can do that the standard MUA would anyway received the challenge and the user needs to find out how to pass this to gpg. > We really need to build WKD managing into more email clients. Ack. > Maybe we'll find a way to do with with several typical windows clients like Outlook, Thunderbird, Claws.. Sending arbitray MIME mails with TB is complicated to impossible but fortunately TB already supports WKD. 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: 227 bytes Desc: not available URL: From wk at gnupg.org Wed Jan 31 19:34:58 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 19:34:58 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C In-Reply-To: <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> (Thorsten Behrens's message of "Wed, 31 Jan 2018 11:29:46 +0100") References: <20180130141810.4073-1-thb@libreoffice.org> <87bmhatn8j.fsf@wheatstone.g10code.de> <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> Message-ID: <87a7wtri5p.fsf@wheatstone.g10code.de> On Wed, 31 Jan 2018 11:29, thb at libreoffice.org said: > Right - needs recompiling all client code. Though for c++, ABI tends > to break all the time, so how large a problem is that really? That might be the case for many C++ libaries, but we simply have higher standards. An ABI break is an ABI break and at least calls for a SO number bump. However we try not to do this because that essentially means that we need to maintain two branches. > I took inspiration from other places in context.h ;) Okay; I better leave the decision on the C++ API to Andre. > Eh, that should be obvious? I need to opionally export keys minimally, > but the cpp binding does not expose gpgme_op_export()'s flag Please just write it into the commit message. In a few years we may need to investigate why and where this option is used. 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: 227 bytes Desc: not available URL: From wk at gnupg.org Wed Jan 31 19:39:43 2018 From: wk at gnupg.org (Werner Koch) Date: Wed, 31 Jan 2018 19:39:43 +0100 Subject: [PATCH 1/5] cpp: expose minimal key export flag from C In-Reply-To: <1659414.VPt5P5tGK7@esus> (Andre Heinecke's message of "Wed, 31 Jan 2018 14:07:28 +0100") References: <20180130141810.4073-1-thb@libreoffice.org> <87bmhatn8j.fsf@wheatstone.g10code.de> <20180131102946.xz3sdfq6ggbfwapl@thinkpad.thebehrens.net> <1659414.VPt5P5tGK7@esus> Message-ID: <87607hrhxs.fsf@wheatstone.g10code.de> On Wed, 31 Jan 2018 14:07, aheinecke at intevation.de said: > The other patches look ok to me. I noticed things like -# ifdef WIN32 +# ifdef _MSC_VER # define GPGMEPP_EXPORT __declspec(dllexport) which clearly is a regression. After all this boils down to the question whether and how we want to support native building and - worse - on a really strange combination of platforms. Let's talk in Brussels about it. 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: 227 bytes Desc: not available URL: