From hans at guardianproject.info Sun Mar 2 18:41:51 2014 From: hans at guardianproject.info (Hans of Guardian) Date: Sun, 2 Mar 2014 12:41:51 -0500 Subject: making iconv optional on Android References: <2049380890.32.1393777490391.JavaMail.jenkins@debeater> Message-ID: It looks like iconv has become required by configure in gnupg. Can this be optional for Android? Android is UTF-8 throughout, and iconv is not currently used. .hc Begin forwarded message: > From: jenkins on debeater > Date: March 2, 2014 11:24:50 AM EST > To: hans at guardianproject.info > Subject: Build failed in Jenkins: gnupg-for-android-eighthave-git-release-branches #46 > > See > > ------------------------------------------ > [...truncated 6857 lines...] > checking for ld used by GCC... /opt/android-ndk-r9b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/arm-linux-androideabi/bin/ld > checking if the linker (/opt/android-ndk-r9b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/arm-linux-androideabi/bin/ld) is GNU ld... yes > checking for shared library run path origin... done > checking for iconv... no, consider installing GNU libiconv > configure: checking for gettext > checking whether NLS is requested... yes > checking for msgfmt... /usr/bin/msgfmt > checking for gmsgfmt... /usr/bin/msgfmt > checking for xgettext... /usr/bin/xgettext > checking for msgmerge... /usr/bin/msgmerge > checking for CFPreferencesCopyAppValue... no > checking for CFLocaleCopyCurrent... no > checking for GNU gettext in libc... no > checking for iconv... (cached) no, consider installing GNU libiconv > checking for GNU gettext in libintl... no > checking whether to use NLS... no > checking for strchr... yes > checking for nl_langinfo and CODESET... no > checking for LC_MESSAGES... yes > configure: checking for header files > checking for ANSI C header files... (cached) yes > checking for string.h... (cached) yes > checking for unistd.h... (cached) yes > checking langinfo.h usability... no > checking langinfo.h presence... no > checking for langinfo.h... no > checking termio.h usability... yes > checking termio.h presence... yes > checking for termio.h... yes > checking locale.h usability... yes > checking locale.h presence... yes > checking for locale.h... yes > checking getopt.h usability... yes > checking getopt.h presence... yes > checking for getopt.h... yes > checking pty.h usability... no > checking pty.h presence... no > checking for pty.h... no > checking utmp.h usability... yes > checking utmp.h presence... yes > checking for utmp.h... yes > checking pwd.h usability... yes > checking pwd.h presence... yes > checking for pwd.h... yes > checking for inttypes.h... (cached) yes > checking signal.h usability... yes > checking signal.h presence... yes > checking for signal.h... yes > checking whether time.h and sys/time.h may both be included... yes > configure: checking for system characteristics > checking for an ANSI C-conforming const... yes > checking for inline... inline > checking for working volatile... yes > checking for size_t... yes > checking for mode_t... yes > checking return type of signal handlers... void > checking whether sys_siglist is declared... yes > checking for sys/socket.h... yes > checking for sys/time.h... yes > checking for unistd.h... (cached) yes > checking for wchar.h... yes > checking for stdint.h... (cached) yes > checking for socklen_t... yes > checking for library containing inet_addr... none required > checking endianess... big (assumed) > checking for byte typedef... no > checking for ushort typedef... no > checking for ulong typedef... no > checking for u16 typedef... no > checking for u32 typedef... no > checking size of unsigned short... 2 > checking size of unsigned int... 4 > checking size of unsigned long... 4 > checking size of unsigned long long... 8 > checking whether time.h and sys/time.h may both be included... (cached) yes > checking size of time_t... 4 > checking whether time_t is unsigned... no > configure: checking for library functions > checking whether getpagesize is declared... yes > checking for _LARGEFILE_SOURCE value needed for large files... no > checking for vprintf... yes > checking for _doprnt... no > checking for pid_t... yes > checking vfork.h usability... no > checking vfork.h presence... no > checking for vfork.h... no > checking for fork... yes > checking for vfork... yes > checking for working fork... cross > configure: WARNING: result yes guessed because of cross compilation > checking for working vfork... (cached) yes > checking for strerror... yes > checking for strlwr... no > checking for tcgetattr... no > checking for mmap... yes > checking for canonicalize_file_name... no > checking for strcasecmp... yes > checking for strncasecmp... yes > checking for ctermid... no > checking for times... yes > checking for gmtime_r... yes > checking for strtoull... yes > checking for unsetenv... yes > checking for fcntl... yes > checking for ftruncate... yes > checking for canonicalize_file_name... (cached) no > checking for gettimeofday... yes > checking for getrusage... yes > checking for getrlimit... yes > checking for setrlimit... yes > checking for clock_gettime... yes > checking for atexit... yes > checking for raise... yes > checking for getpagesize... no > checking for strftime... yes > checking for nl_langinfo... no > checking for setlocale... yes > checking for waitpid... yes > checking for wait4... no > checking for sigaction... yes > checking for sigprocmask... yes > checking for pipe... yes > checking for getaddrinfo... yes > checking for ttyname... yes > checking for rand... no > checking for ftello... yes > checking for fsync... yes > checking for stat... yes > checking for lstat... yes > checking for struct sigaction... yes > checking for sigset_t... yes > checking for signal.h... (cached) yes > checking for memicmp... no > checking for stpcpy... no > checking for strsep... yes > checking for strlwr... (cached) no > checking for strtoul... yes > checking for memmove... yes > checking for stricmp... no > checking for strtol... yes > checking for memrchr... yes > checking for isascii... yes > checking for timegm... no > checking for getrusage... (cached) yes > checking for setrlimit... (cached) yes > checking for stat... (cached) yes > checking for setlocale... (cached) yes > checking for flockfile... yes > checking for funlockfile... yes > checking for fopencookie... no > checking for funopen... yes > checking for getpwnam... yes > checking for getpwuid... yes > checking for getenv... yes > checking for inet_pton... yes > checking for working alloca.h... yes > checking for alloca... yes > checking for stdlib.h... (cached) yes > checking for GNU libc compatible malloc... (cached) yes > checking for long long int... yes > checking for long double... yes > checking whether stat file-mode macros are broken... no > checking for unsigned long long int... yes > checking for mkdtemp... yes > checking for setenv... yes > checking for unsetenv... (cached) yes > checking for unsetenv() return type... int > checking for stdint.h... (cached) yes > checking for SIZE_MAX... yes > checking absolute name of ... ///opt/android-ndk-r9b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8/include/stdint.h > checking whether stdint.h conforms to C99... no > checking sys/inttypes.h usability... no > checking sys/inttypes.h presence... no > checking for sys/inttypes.h... no > checking sys/bitypes.h usability... no > checking sys/bitypes.h presence... no > checking for sys/bitypes.h... no > checking for bit size of ptrdiff_t... 32 > checking for bit size of sig_atomic_t... 32 > checking for bit size of size_t... 32 > checking for bit size of wchar_t... 32 > checking for bit size of wint_t... 32 > checking whether sig_atomic_t is signed... yes > checking whether wchar_t is signed... no > checking whether wint_t is signed... no > checking for ptrdiff_t integer literal suffix... > checking for sig_atomic_t integer literal suffix... > checking for size_t integer literal suffix... u > checking for wchar_t integer literal suffix... u > checking for wint_t integer literal suffix... u > checking for strpbrk... yes > checking for unistd.h... (cached) yes > checking for stdint.h... (cached) yes > checking for sys/stat.h... (cached) yes > checking for unistd.h... (cached) yes > checking direct.h usability... no > checking direct.h presence... no > checking for direct.h... no > checking if mkdir takes one argument... no > checking whether regular expression support is requested... yes > checking for library containing regcomp... none required > checking for regcomp... yes > configure: WARNING: cross compiling; assuming regexp libray is not broken > checking zlib.h usability... yes > checking zlib.h presence... yes > checking for zlib.h... yes > checking for deflateInit2_ in -lz... yes > checking for bzlib.h... no > checking whether readline via "-lreadline" is present and sane... no > checking whether readline via "-lreadline -ltermcap" is present and sane... no > checking whether readline via "-lreadline -lcurses" is present and sane... no > checking whether readline via "-lreadline -lncurses" is present and sane... no > configure: checking for cc features > checking if gcc ignores unknown -Wno-* options... yes > checking if gcc supports -Wdeclaration-after-statement... yes > checking if gcc supports -Wpointer-arith... yes > configure: checking system features for estream-printf > checking for stdint.h... (cached) yes > checking for long long int... (cached) yes > checking for long double... yes > checking for intmax_t... yes > checking for uintmax_t... yes > checking for ptrdiff_t... yes > checking size of unsigned long... (cached) 4 > checking size of void *... 4 > checking for nl_langinfo and THOUSANDS_SEP... no > configure: checking system features for estream > configure: > *** > *** The system does not provide a working iconv function. Please > *** install a suitable library; for example GNU Libiconv which is > *** available at: > *** http://ftp.gnu.org/gnu/libiconv/ > *** > configure: error: > *** > *** Required libraries not found. Please consult the above messages > *** and install them before running configure again. > *** > make: *** [gnupg/Makefile] Error 1 > make: Leaving directory ` > Build step 'Execute shell' marked build as failure > $ /opt/android-sdk/platform-tools/adb disconnect localhost:33510 > [android] Stopping Android emulator > [android] Archiving emulator log > $ /opt/android-sdk/platform-tools/adb kill-server > Terminating xvnc. > $ vncserver -kill :57 > Killing Xvnc4 process ID 29027 From hans at guardianproject.info Sun Mar 2 18:51:37 2014 From: hans at guardianproject.info (Hans of Guardian) Date: Sun, 2 Mar 2014 12:51:37 -0500 Subject: integrating Android into the GnuPG workflow Message-ID: Hey Werner, I'm hoping that the Android port can be considered an official port of GnuPG, at the very least in terms of the code that's in the gnupg.org repos, but also for the whole package. I've set up our Jenkins build server to build each commit to the gnupg.org repos so that there is automatic feedback when a commit breaks the Android build. Right now, I've also been manually following up on those, which takes a fair amount of time. And the longer build stays broken on Android, then updating the GPGA app to the latest code becomes in effect a new porting effort. So I wanted to discuss what needs to happen to smooth out this process. We have contributing a little bit of funding, and we are hoping to contribute more in the future, that always helps. But I think it would be good to also discuss how we can make this process more efficient so that the Android port can stay up-to-date in the time between funding. .hc From buanzo at buanzo.com.ar Mon Mar 3 22:36:10 2014 From: buanzo at buanzo.com.ar (Arturo 'Buanzo' Busleiman) Date: Mon, 3 Mar 2014 18:36:10 -0300 Subject: Best androisd-gnupg methodology? Message-ID: Hello everyone! I am working on an android port of an app of mine called Jiffy. I would really like NOT to use bouncycastle/spongycastle. Instead i would like to recommend the user to install an android gnupg app, and have my app use that for pubring and crypto operations. A couple days ago there was a mention of the current status of gnupg on android, so I decided to take a chance and ask this community for advice. Even if the advice is one word it will be highly valuable to me. Thank you. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gniibe at fsij.org Tue Mar 4 04:06:00 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 04 Mar 2014 12:06:00 +0900 Subject: [PATCH] agent: API change of agent_key_from_file In-Reply-To: <1393214613.6874.1.camel@cfw2.gniibe.org> References: <1393214613.6874.1.camel@cfw2.gniibe.org> Message-ID: <1393902360.1734.7.camel@cfw2.gniibe.org> On 2014-02-24 at 13:03 +0900, NIIBE Yutaka wrote: > My proposal fix is to change the semantics of agent_key_from_file a > bit. Currently, callers of agent_key_from_file know that private key > is on smartcard by examining S_SKEY. I'd like to change this function > to return the content of S_SKEY always (even if the private key is on > smartcard), so that we can check the key type later. We can examine > the SHADOW_INFO to know it's on smartcard or not. The patch is revised. I changed comments for new API, too. agent: API change of agent_key_from_file. * agent/findkey.c (agent_key_from_file): Always return S-expression. * agent/command.c (cmd_passwd): Distinguish by SHADOW_INFO. (cmd_export_key): Likewise. Free SHADOW_INFO. (cmd_keytocard): Likewise. Release S_SKEY. * agent/pkdecrypt.c (agent_pkdecrypt): Likewise. * agent/pksign.c (agent_pksign_do): Likewise. Use the S-expression to know the key type. Signed-off-by: NIIBE Yutaka OK to push? diff --git a/agent/command.c b/agent/command.c index 4fa40d9..d1e53cd 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1667,7 +1667,7 @@ cmd_passwd (assuan_context_t ctx, char *line) &s_skey, &passphrase); if (err) ; - else if (!s_skey) + else if (shadow_info) { log_error ("changing a smartcard PIN is not yet supported\n"); err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); @@ -2126,6 +2126,7 @@ cmd_export_key (assuan_context_t ctx, char *line) int openpgp; char *cache_nonce; char *passphrase = NULL; + unsigned char *shadow_info = NULL; openpgp = has_option (line, "--openpgp"); cache_nonce = option_value (line, "--cache-nonce"); @@ -2163,15 +2164,13 @@ cmd_export_key (assuan_context_t ctx, char *line) /* Get the key from the file. With the openpgp flag we also ask for the passphrase so that we can use it to re-encrypt it. */ err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip, - NULL, CACHE_MODE_IGNORE, NULL, &s_skey, + &shadow_info, CACHE_MODE_IGNORE, NULL, &s_skey, openpgp ? &passphrase : NULL); if (err) goto leave; - if (!s_skey) + if (shadow_info) { - /* Key is on a smartcard. Actually we should not see this here - because we do not pass a shadow_info variable to the above - function, thus it will return this error directly. */ + /* Key is on a smartcard. */ err = gpg_error (GPG_ERR_UNUSABLE_SECKEY); goto leave; } @@ -2241,6 +2240,7 @@ cmd_export_key (assuan_context_t ctx, char *line) gcry_sexp_release (s_skey); xfree (ctrl->server_local->keydesc); ctrl->server_local->keydesc = NULL; + xfree (shadow_info); return leave_cmd (ctx, err); } @@ -2260,7 +2260,7 @@ cmd_keytocard (assuan_context_t ctx, char *line) unsigned char *keydata; size_t keydatalen, timestamplen; const char *serialno, *timestamp_str, *id; - unsigned char *shadow_info; + unsigned char *shadow_info = NULL; unsigned char *shdkey; time_t timestamp; @@ -2305,12 +2305,20 @@ cmd_keytocard (assuan_context_t ctx, char *line) return gpg_error (GPG_ERR_INV_VALUE); err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip, - NULL, CACHE_MODE_IGNORE, NULL, &s_skey, NULL); + &shadow_info, CACHE_MODE_IGNORE, NULL, + &s_skey, NULL); if (err) - return err; - if (!s_skey) - /* Key is on a smartcard already. */ - return gpg_error (GPG_ERR_UNUSABLE_SECKEY); + { + xfree (shadow_info); + return err; + } + if (shadow_info) + { + /* Key is on a smartcard already. */ + xfree (shadow_info); + gcry_sexp_release (s_skey); + return gpg_error (GPG_ERR_UNUSABLE_SECKEY); + } keydatalen = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); keydata = xtrymalloc_secure (keydatalen + 30); diff --git a/agent/findkey.c b/agent/findkey.c index 6464b02..7b24c55 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -537,9 +537,9 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) /* Return the secret key as an S-Exp in RESULT after locating it using - the GRIP. Stores NULL at RESULT if the operation shall be diverted - to a token; in this case an allocated S-expression with the - shadow_info part from the file is stored at SHADOW_INFO. + the GRIP. If the operation shall be diverted to a token, an + allocated S-expression with the shadow_info part from the file is + stored at SHADOW_INFO; if not NULL will be stored at SHADOW_INFO. CACHE_MODE defines now the cache shall be used. DESC_TEXT may be set to present a custom description for the pinentry. LOOKUP_TTL is an optional function to convey a TTL to the cache manager; we do @@ -562,7 +562,6 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, unsigned char *buf; size_t len, buflen, erroff; gcry_sexp_t s_skey; - int got_shadow_info = 0; *result = NULL; if (shadow_info) @@ -638,7 +637,6 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, { memcpy (*shadow_info, s, n); rc = 0; - got_shadow_info = 1; } } if (rc) @@ -654,7 +652,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, } gcry_sexp_release (s_skey); s_skey = NULL; - if (rc || got_shadow_info) + if (rc) { xfree (buf); if (r_passphrase) diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 9924d6d..14aa78f 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -79,7 +79,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, goto leave; } - if (!s_skey) + if (shadow_info) { /* divert operation to the smartcard */ if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL)) diff --git a/agent/pksign.c b/agent/pksign.c index 4d0a240..0886150 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -299,31 +299,20 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce, goto leave; } - if (!s_skey) + if (shadow_info) { /* Divert operation to the smartcard */ - gcry_sexp_t s_pkey, l; - const char *name; size_t len; unsigned char *buf = NULL; + int key_type; int is_RSA = 0; int is_ECDSA = 0; - /* Check keytype by public key */ - rc = agent_public_key_from_file (ctrl, ctrl->keygrip, &s_pkey); - if (rc) - { - log_error ("failed to read the public key\n"); - goto leave; - } - l = gcry_sexp_cadr (s_pkey); - name = gcry_sexp_nth_data (l, 0, &len); - if (len == 3 && !memcmp (name, "rsa", 3)) + key_type = agent_is_dsa_key (s_skey); + if (key_type == 0) is_RSA = 1; - else if (len == 5 && !memcmp (name, "ecdsa", 5)) + else if (key_type == GCRY_PK_ECDSA) is_ECDSA = 1; - gcry_sexp_release (l); - gcry_sexp_release (s_pkey); rc = divert_pksign (ctrl, ctrl->digest.value, -- From mail at tgries.de Tue Mar 4 10:50:29 2014 From: mail at tgries.de (Thomas Gries) Date: Tue, 04 Mar 2014 10:50:29 +0100 Subject: Every version of GnuTLS found to vulnerable to certification bypass. Message-ID: <5315A1E5.3090809@tgries.de> *** to whom it may concern *** Every version of GnuTLS found to vulnerable to certification bypass. See http://packetstormsecurity.com/files/125521/GNU-Transport-Layer-Security-Library-3.2.12.html and look on Twitter for gnutls The relevant patch appears to be https://www.gitorious.org/gnutls/gnutls/commit/6aa26f78150ccbdf0aec1878a41c17c41d358a3b -------------- next part -------------- An HTML attachment was scrubbed... URL: From mail at tgries.de Wed Mar 5 01:39:39 2014 From: mail at tgries.de (Thomas Gries) Date: Wed, 05 Mar 2014 01:39:39 +0100 Subject: Every version of GnuTLS found to vulnerable to certification bypass. In-Reply-To: <5315AF51.6010108@fifthhorseman.net> References: <5315A1E5.3090809@tgries.de> <5315AF51.6010108@fifthhorseman.net> Message-ID: <5316724B.6060407@tgries.de> Am 04.03.2014 11:47, schrieb Daniel Kahn Gillmor: >> Every version of GnuTLS found to vulnerable to certification bypass. > why are you writing this to the gnupg development mailing list? > > gnupg is entirely independent of gnutls. Perhaps you are right, but https://twitter.com/kennwhite/status/440941032616624128 says: and you should answer him, if he is wrong, or mixing up things. One other aspect is that all apt-transport using things are victims, too. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: hfgddjij.png Type: image/png Size: 21502 bytes Desc: not available URL: From infinity0 at pwned.gg Wed Mar 5 02:33:17 2014 From: infinity0 at pwned.gg (Ximin Luo) Date: Wed, 05 Mar 2014 01:33:17 +0000 Subject: Every version of GnuTLS found to vulnerable to certification bypass. In-Reply-To: <5316724B.6060407@tgries.de> References: <5315A1E5.3090809@tgries.de> <5315AF51.6010108@fifthhorseman.net> <5316724B.6060407@tgries.de> Message-ID: <53167EDD.70307@pwned.gg> On 05/03/14 00:39, Thomas Gries wrote: > Am 04.03.2014 11:47, schrieb Daniel Kahn Gillmor: >>> Every version of GnuTLS found to vulnerable to certification bypass. >> why are you writing this to the gnupg development mailing list? >> >> gnupg is entirely independent of gnutls. > Perhaps you are right, but > https://twitter.com/kennwhite/status/440941032616624128 says: > > and you should answer him, if he is wrong, or mixing up things. > One other aspect is that all apt-transport using things are victims, too. > APT uses GPG and is not affected. It looks like that article has patched this up, but "a second layer of protection" is still not correct; GPG is the *only* layer of protection that APT relies on. TLS is Transport Layer Security, not end-to-end security, which is what matters in a distributed system. X -- GPG: 4096R/1318EFAC5FBBDBCE git://github.com/infinity0/pubkeys.git -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 880 bytes Desc: OpenPGP digital signature URL: From gniibe at fsij.org Wed Mar 5 06:09:37 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 05 Mar 2014 14:09:37 +0900 Subject: Every version of GnuTLS found to vulnerable to certification bypass. In-Reply-To: <53167EDD.70307@pwned.gg> References: <5315A1E5.3090809@tgries.de> <5315AF51.6010108@fifthhorseman.net> <5316724B.6060407@tgries.de> <53167EDD.70307@pwned.gg> Message-ID: <1393996177.5662.1.camel@cfw2.gniibe.org> I think that he just checked the dependencies. On my Debian box, it's: gnupg2 -> libcurl3-gnutls -> libgnutls26 So, it's related somehow. But I don't think it make sense to call all those software victims. -- From dshaw at jabberwocky.com Wed Mar 5 07:21:07 2014 From: dshaw at jabberwocky.com (David Shaw) Date: Wed, 5 Mar 2014 01:21:07 -0500 Subject: Every version of GnuTLS found to vulnerable to certification bypass. In-Reply-To: <1393996177.5662.1.camel@cfw2.gniibe.org> References: <5315A1E5.3090809@tgries.de> <5315AF51.6010108@fifthhorseman.net> <5316724B.6060407@tgries.de> <53167EDD.70307@pwned.gg> <1393996177.5662.1.camel@cfw2.gniibe.org> Message-ID: <894E8B23-92A0-485A-A511-61EA0C93D5DE@jabberwocky.com> On Mar 5, 2014, at 12:09 AM, NIIBE Yutaka wrote: > I think that he just checked the dependencies. > > On my Debian box, it's: > > gnupg2 -> libcurl3-gnutls -> libgnutls26 > > So, it's related somehow. GnuPG can use libcurl to talk to keyservers. So if a particular libcurl is linked to gnutls it would be possible for there to be a keyserver rigged with a cert appearing to be a different keyserver. Of course, if such a server returned an incorrect key, that key wouldn't have the proper fingerprint or verify in the web of trust. Still, I could see if someone was doing the wrong thing and trusting a key merely because it came from a particular server they could get into trouble, but then they shouldn't have been doing that in the first place. Which is not to minimize what is clearly a very serious bug - just that it doesn't affect the security of GnuPG directly. > But I don't think it make sense to call all those software victims. Agreed. David From ueno at gnu.org Wed Mar 5 06:52:49 2014 From: ueno at gnu.org (Daiki Ueno) Date: Wed, 5 Mar 2014 14:52:49 +0900 Subject: [PATCH gpgme] doc: Fix documentation of struct data types Message-ID: <1393998769-20432-1-git-send-email-ueno@gnu.org> * gpgme.texi (Key Management): Document is_cardkey and card_number members of gpgme_subkey_t. (Decrypt): Remove description of the non-existent wrong_key_usage member of gpgme_recipient_t. (Verify): Document pka_address member of gpgme_signature_t. (Creating a Signature): Add missing member names in gpgme_new_signature_t. (Registering I/O Callbacks): Fix reference of gpgme_io_cbs struct. --- doc/gpgme.texi | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 3f31492..4425396 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -2689,6 +2689,12 @@ timestamp is invalid, and 0 if it is not available. @item long int expires This is the expiration timestamp of the subkey, or 0 if the subkey does not expire. + + at item unsigned int is_cardkey : 1 +True if the secret key is stored on a smart card. + + at item char *card_number +The serial number of a smart card holding this key or @code{NULL}. @end table @end deftp @@ -4213,9 +4219,6 @@ or @code{NULL} if this is the last element. @item gpgme_pubkey_algo_t The public key algorithm used in the encryption. - at item unsigned int wrong_key_usage : 1 -This is true if the key was not used according to its policy. - @item char *keyid This is the key ID of the key (in hexadecimal digits) used as recipient. @@ -4509,6 +4512,9 @@ The public key algorithm used to create this signature. @item gpgme_hash_algo_t The hash algorithm used to create this signature. + + at item char *pka_address +The mailbox from the PKA information or @code{NULL}. @end table @end deftp @@ -4945,10 +4951,10 @@ list, or @code{NULL} if this is the last element. @item gpgme_sig_mode_t type The type of this signature. - at item gpgme_pubkey_algo_t + at item gpgme_pubkey_algo_t pubkey_algo The public key algorithm used to create this signature. - at item gpgme_hash_algo_t + at item gpgme_hash_algo_t hash_algo The hash algorithm used to create this signature. @item unsigned int sig_class @@ -5400,7 +5406,7 @@ list of possible @code{gpgme_event_io_t} types. @node Registering I/O Callbacks @subsubsection Registering I/O Callbacks - at deftp {Data type} {struct gpgme_io_cb_ts} + at deftp {Data type} {struct gpgme_io_cbs} @tindex gpgme_event_io_t This structure is used to store the I/O callback interface functions described in the previous section. It has the following members: @@ -5410,7 +5416,7 @@ described in the previous section. It has the following members: This is the function called by @acronym{GPGME} to register an I/O callback handler. It must be specified. - at item void *add_data + at item void *add_priv This is passed as the first argument to the @code{add} function when it is called by @acronym{GPGME}. For example, it can be used to determine the event loop to which the file descriptor should be added. @@ -5424,14 +5430,14 @@ This is the function called by @acronym{GPGME} to signal an event for an operation. It must be specified, because at least the start event must be processed. - at item void *event_data + at item void *event_priv This is passed as the first argument to the @code{event} function when it is called by @acronym{GPGME}. For example, it can be used to determine the context in which the event has occured. @end table @end deftp - at deftypefun void gpgme_set_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cb_ts *@var{io_cbs}}) + at deftypefun void gpgme_set_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cbs *@var{io_cbs}}) The function @code{gpgme_set_io_cbs} enables the I/O callback interface for the context @var{ctx}. The I/O callback functions are specified by @var{io_cbs}. @@ -5440,7 +5446,7 @@ If @var{io_cbs}->@code{add} is @code{NULL}, the I/O callback interface is disabled for the context, and normal operation is restored. @end deftypefun - at deftypefun void gpgme_get_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cb_ts *@var{io_cbs}}) + at deftypefun void gpgme_get_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cbs *@var{io_cbs}}) The function @code{gpgme_get_io_cbs} returns the I/O callback functions set with @code{gpgme_set_io_cbs} in @var{io_cbs}. @end deftypefun @@ -5630,7 +5636,7 @@ main (int argc, char *argv[]) gpgme_error_t err; gpgme_data_t sig, text; int i; - struct gpgme_io_cb_ts io_cbs = + struct gpgme_io_cbs io_cbs = @{ add_io_cb, &loop, -- 1.8.4.2 From gniibe at fsij.org Thu Mar 6 03:18:06 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 06 Mar 2014 11:18:06 +0900 Subject: [PATCH] Fix g10/trust.c. Message-ID: <1394072286.1535.2.camel@cfw2.gniibe.org> Hello, Current master doesn't work well for key generation (it runs forever). I think that it is due to simple typo in: commit 62fb86c6589f7f74dad4741db31b3aefa0848420 Author: Werner Koch Date: Mon Feb 10 17:05:54 2014 +0100 gpg: Allow building without any trust model support. Here's a fix. I'm going to push this fix, as this is obvious. diff --git a/g10/trust.c b/g10/trust.c index 32cd934..c8a1c2c 100644 --- a/g10/trust.c +++ b/g10/trust.c @@ -55,7 +55,7 @@ register_trusted_keyid (u32 *keyid) #ifdef NO_TRUST_MODELS (void)keyid; #else - register_trusted_keyid (keyid); + tdb_register_trusted_keyid (keyid); #endif } @@ -66,7 +66,7 @@ register_trusted_key (const char *string) #ifdef NO_TRUST_MODELS (void)string; #else - register_trusted_key (string); + tdb_register_trusted_key (string); #endif } @@ -247,7 +247,7 @@ update_ownertrust (PKT_public_key *pk, unsigned int new_trust) (void)pk; (void)new_trust; #else - update_ownertrust (pk, new_trust); + tdb_update_ownertrust (pk, new_trust); #endif } -- From gniibe at fsij.org Thu Mar 6 08:39:02 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 06 Mar 2014 16:39:02 +0900 Subject: [PATCH] Fix g10/trust.c. In-Reply-To: <1394072286.1535.2.camel@cfw2.gniibe.org> References: <1394072286.1535.2.camel@cfw2.gniibe.org> Message-ID: <1394091542.16075.3.camel@cfw2.gniibe.org> On 2014-03-06 at 11:18 +0900, NIIBE Yutaka wrote: > Here's a fix. I'm going to push this fix, as this is obvious. > > diff --git a/g10/trust.c b/g10/trust.c Pushed. Building master, I also noticed a problem of the function get_membuf_shrink in common/membuf.c. But, since I think it is in a state of flux, I don't touch it now. -- From wk at gnupg.org Thu Mar 6 08:49:11 2014 From: wk at gnupg.org (Werner Koch) Date: Thu, 06 Mar 2014 08:49:11 +0100 Subject: [PATCH] Fix g10/trust.c. In-Reply-To: <1394072286.1535.2.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Thu, 06 Mar 2014 11:18:06 +0900") References: <1394072286.1535.2.camel@cfw2.gniibe.org> Message-ID: <87fvmvkbrc.fsf@vigenere.g10code.de> On Thu, 6 Mar 2014 03:18, gniibe at fsij.org said: > Here's a fix. I'm going to push this fix, as this is obvious. Thanks. My apologies for breaking the code. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Fri Mar 7 06:41:32 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 07 Mar 2014 14:41:32 +0900 Subject: Changes from 2.0 branch to master? Message-ID: <1394170892.3737.5.camel@cfw2.gniibe.org> Hello, I think that current master needs patches from 2.0 branch. Following 21 commits in 2.0 branch should be also applied to master. The sign "*" means that it requires manual edit. I've looked through the changes in 2.0 since January 2013 to now. * Bring the fix for bug 739 on 1.4 over to 2.0 (bug 1479) author David Shaw Fri, 1 Mar 2013 03:48:58 +0900 (13:48 -0500) commit fe85638284880805b80778fe87ae551d3de0ca32 Emulate curl_easy_getinfo and CURLINFO_RESPONSE_CODE in curl-shim. author David Shaw Sun, 3 Mar 2013 10:07:27 +0900 (20:07 -0500) commit 7808e4a763692b8bcd95264d39caf85fad32f0bd Differentiate between success (full or partial), not-found, and failure. author David Shaw Sun, 3 Mar 2013 10:39:48 +0900 (20:39 -0500) commit 6d0e41815a726ad4b170ed18cc772a1817559299 * Allow marking options as ignored. author Werner Koch Thu, 18 Apr 2013 21:40:43 +0900 (14:40 +0200) commit 54c54e2824aab5716a187bbbf6dff8860d6a6056 Ignore obsolete option --disable-keypad. author Werner Koch Thu, 18 Apr 2013 21:40:43 +0900 (14:40 +0200) commit e24e92d7e244edd578c0c1f0fba6e0070cb5f104 Allow building gpgkeys_ldap with the 32 bit mingw-w64 toolchain. author Werner Koch Wed, 24 Apr 2013 00:04:56 +0900 (17:04 +0200) commit a557a74615774b228dae14cf83a92ec26e2b03b5 w32: Almost everywhere include winsock2.h before windows.h. author Werner Koch Wed, 24 Apr 2013 01:06:46 +0900 (18:06 +0200) commit 40ca0022a7035ce5c3d715f36e0c70f310ea4c61 Fix syntax error for building on APPLE. author Werner Koch Thu, 25 Apr 2013 20:00:16 +0900 (12:00 +0100) commit 8ddf604659b93754ffa6dea295678a8adc293f90 agent: Fix binary vs. text mode problem in ssh. author Werner Koch Wed, 3 Jul 2013 20:10:29 +0900 (13:10 +0200) commit ed056d67c7c93306b68829f83a2565e978dcfd9b ssh: Add support for Putty. author Werner Koch Wed, 3 Jul 2013 20:29:47 +0900 (13:29 +0200) commit 9f32499f99a0817f63f7a73b09bdcebe60d4775d agent: Make --allow-mark-trusted the default. author Werner Koch Wed, 3 Jul 2013 22:20:25 +0900 (15:20 +0200) commit 90b419f3e9d05e509348d047e05fcc79e87be6cf * w32: Remove unused code. author Werner Koch Thu, 1 Aug 2013 21:02:50 +0900 (14:02 +0200) commit 1b89863ec195dbfdbc33432569a7b2e7f0f83821 gpg: Remove legacy keyserver examples from the template conf file. author Werner Koch Tue, 6 Aug 2013 17:04:12 +0900 (10:04 +0200) commit f3c5cc8bcd37e38b5d65db6a50466e22d03d1f0c Improve libcurl detection. author Werner Koch Tue, 6 Aug 2013 17:31:54 +0900 (10:31 +0200) commit 110b52fffa77b339e6d59eba939408f7e87e7138 gpgv: Init Libgcrypt to avoid syslog warning. author Werner Koch Mon, 19 Aug 2013 18:22:11 +0900 (11:22 +0200) commit 3966eb244518d5612385d35a5149f7164a9fb707 * agent: Fix UPDATESTARTUPTTY for ssh. author Werner Koch Mon, 19 Aug 2013 18:44:59 +0900 (11:44 +0200) commit 9f5578c29adba6d4f7d3650121d07322c2f8d254 keyserver: Allow use of cURL's default CA store. author Werner Koch Fri, 4 Oct 2013 15:28:12 +0900 (08:28 +0200) commit e957b9b3f408491f36660499b215aebcf2633a95 gpg: Protect against rogue keyservers sending secret keys. author Werner Koch Fri, 4 Oct 2013 20:44:39 +0900 (13:44 +0200) commit e7abed3448c1c1a4e756c12f95b665b517d22ebe * gpg: Print a "not found" message for an unknown key in --key-edit. author Werner Koch Sat, 5 Oct 2013 01:34:56 +0900 (18:34 +0200) commit 0bf54e60d31389812d05c3fd29bece876204561d gpg: Do not require a trustdb with --always-trust. author Werner Koch Fri, 11 Oct 2013 16:25:58 +0900 (09:25 +0200) commit 1a0eeaacd1bf09fe5125dbc3f56016bc20f3512e * common: Fix build problem with Sun Studio compiler. author Werner Koch Fri, 15 Nov 2013 17:08:58 +0900 (09:08 +0100) commit 571bcd4662a351cfa55bbf1a79ed1bc26da5780f -- From gniibe at fsij.org Fri Mar 7 08:07:02 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 07 Mar 2014 16:07:02 +0900 Subject: Gnuk 1.1.2 Message-ID: <1394176022.3737.7.camel@cfw2.gniibe.org> Hello, Development version of Gnuk 1.1.2 was released. Gnuk is an implementation of Cryptographic Token for GnuPG, and it runs on STM32F103. This is an experimental version. While it's daily use for me, this version is for developers, basically. In this version, I added the support of secp256k1 curve for ECDSA signature. When enabled (manual editing is required to remove -DRSA_SIG or -DRSA_AUTH), you can use the ECC key with development version of GnuPG 2.1.x. The feature is intended to be used for Bitcoin transaction. I would like to support Bitcoin, while I don't recommend Bitcoin. Note that Gnuk Token is just a place for a private key, we need to modify some Bitcoin client program so that it can use Gnuk Token through GnuPG agent. Well, I realize that most "Bitcoin users" are not real users, in fact. For me, users of Bitcoin should have their own private keys. Gnuk Token with the feature of secp256k1 curve is for those who want to control their own computing. Here is the list of noteworthy change (in 1.1.2): * Experimental ECC support for secp256k1. After configure, you can edit the DEFS variable in src/Makefile, so that Gnuk can support ECDSA with NIST P256 (for authentication), and ECDSA with secp256k1 (for signature). Note that this is pretty much experimental, and subjects to change. For Japanese people who like bleeding edge, I still have a little campaign of FST-01 wit Gnuk 1.1.1: http://www.gniibe.org/shop/gnuk_1_1_x-on-fst-01 (in Japanese) Links: Gnuk Documentation: http://www.fsij.org/doc-gnuk/ Gnuk Repository: http://gitorious.org/gnuk/ FST-01 introduction: http://www.seeedstudio.com/wiki/index.php?title=FST-01 FST-01 Gnuk Handbook (in Japanese); http://no-passwd.net/fst-01-gnuk-handbook/ Enjoy, -- From gniibe at fsij.org Fri Mar 7 04:17:18 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 07 Mar 2014 12:17:18 +0900 Subject: [PATCH] scd: writekey support of ECC In-Reply-To: <1393215660.6874.3.camel@cfw2.gniibe.org> References: <1393215660.6874.3.camel@cfw2.gniibe.org> Message-ID: <1394162238.3737.3.camel@cfw2.gniibe.org> On 2014-02-24 at 13:21 +0900, NIIBE Yutaka wrote: > Last year, I lost the opportunity to merge my work of ECC smartcard > support (specifically, ECDSA). IIRC, we didn't have any agreements on > ECDH. I implemented ECDSA (with NIST P-256) on Gnuk around March > 2013, and submitted partial change of GnuPG. Perhaps, it was just the > code enough to use with OpenSSH, and I forgot to send writekey change. > > Here are changes. It will by by two commits. Revised. This is in a single patch. Built and tested with current development version of Gnuk. The change is localized to app-openpgp.c. OK to commit? (I'm also waiting approval of gpg-agent change.) scd: writekey support of ECC. * scd/app-openpgp.c (CURVE_SEC_P256K1, get_algo_byte): New. (store_fpr): Support ECC keys with varargs. (get_ecc_key_parameters, get_curve_name): Support secp256k1. (parse_ecc_curve): Likewise. (build_ecdsa_privkey_template, rsa_writekey, ecdsa_writekey): New. (ecdh_writekey): New. Not implemented yet. (do_writekey): Call rsa_writekey, ecdsa_writekey, or ecdh_writekey. (do_genkey): Follow the change of store_fpr. Signed-off-by: NIIBE Yutaka diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 3d7136f..7129666 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1,6 +1,6 @@ /* app-openpgp.c - The OpenPGP card application. * Copyright (C) 2003, 2004, 2005, 2007, 2008, - * 2009, 2013 Free Software Foundation, Inc. + * 2009, 2013, 2014 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -143,7 +144,9 @@ enum { CURVE_NIST_P256, CURVE_NIST_P384, - CURVE_NIST_P521 + CURVE_NIST_P521, + CURVE_SEC_P256K1, + CURVE_UNKOWN, }; @@ -735,24 +738,56 @@ parse_login_data (app_t app) xfree (relptr); } + +static unsigned char +get_algo_byte (key_type_t key_type) +{ + if (key_type == KEY_TYPE_ECDSA) + return 19; + else if (key_type == KEY_TYPE_ECDH) + return 18; + else + return 1; /* RSA */ +} + /* Note, that FPR must be at least 20 bytes. */ static gpg_error_t store_fpr (app_t app, int keynumber, u32 timestamp, - const unsigned char *m, size_t mlen, - const unsigned char *e, size_t elen, - unsigned char *fpr, unsigned int card_version) + unsigned char *fpr, unsigned int card_version, + key_type_t key_type, + ...) { unsigned int n, nbits; unsigned char *buffer, *p; int tag, tag2; int rc; + const unsigned char *m; + size_t mlen; + va_list ap; + int argc; + int i; - for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ - ; - for (; elen && !*e; elen--, e++) /* strip leading zeroes */ - ; + n = 6; /* key packet version, 4-byte timestamps, and algorithm */ + if (key_type == KEY_TYPE_RSA || key_type == KEY_TYPE_ECDSA) + argc = 2; + else if (key_type == KEY_TYPE_ECDH) + argc = 3; + else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + va_start (ap, key_type); + for (i = 0; i < argc; i++) + { + m = va_arg (ap, const unsigned char *); + mlen = va_arg (ap, size_t); + for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ + ; + if (key_type == KEY_TYPE_RSA || i == 1) + n += 2; + n += mlen; + } + va_end (ap); - n = 6 + 2 + mlen + 2 + elen; p = buffer = xtrymalloc (3 + n); if (!buffer) return gpg_error_from_syserror (); @@ -765,15 +800,24 @@ store_fpr (app_t app, int keynumber, u32 timestamp, *p++ = timestamp >> 16; *p++ = timestamp >> 8; *p++ = timestamp; - *p++ = 1; /* RSA */ - nbits = count_bits (m, mlen); - *p++ = nbits >> 8; - *p++ = nbits; - memcpy (p, m, mlen); p += mlen; - nbits = count_bits (e, elen); - *p++ = nbits >> 8; - *p++ = nbits; - memcpy (p, e, elen); p += elen; + *p++ = get_algo_byte (key_type); + + va_start (ap, key_type); + for (i = 0; i < argc; i++) + { + m = va_arg (ap, const unsigned char *); + mlen = va_arg (ap, size_t); + for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ + ; + if (key_type == KEY_TYPE_RSA || i == 1) + { + nbits = count_bits (m, mlen); + *p++ = nbits >> 8; + *p++ = nbits; + } + memcpy (p, m, mlen); p += mlen; + } + va_end (ap); gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3); @@ -889,11 +933,16 @@ get_ecc_key_parameters (int curve, int *r_n_bits, const char **r_curve_oid) *r_n_bits = 384; *r_curve_oid = "1.3.132.0.34"; } - else + else if (curve == CURVE_NIST_P521) { *r_n_bits = 521; *r_curve_oid = "1.3.132.0.35"; } + else + { + *r_n_bits = 256; + *r_curve_oid = "1.3.132.0.10"; + } } static void @@ -1234,8 +1283,10 @@ get_curve_name (int curve) return "NIST P-256"; else if (curve == CURVE_NIST_P384) return "NIST P-384"; - else + else if (curve == CURVE_NIST_P521) return "NIST P-521"; + else + return "secp256k1"; } @@ -1456,7 +1507,7 @@ get_public_key (app_t app, int keyno) = get_curve_name (app->app_local->keyattr[keyno].ecdsa.curve); err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdsa(curve%s)(q%b)))", + "(public-key(ecc(curve%s)(q%b)))", curve_name, mlen, mbuf); if (err) goto leave; @@ -2500,8 +2551,6 @@ add_tlv (unsigned char *buffer, unsigned int tag, size_t length) } -/* Build the private key template as specified in the OpenPGP specs - v2.0 section 4.3.3.7. */ static gpg_error_t build_privkey_template (app_t app, int keyno, const unsigned char *rsa_n, size_t rsa_n_len, @@ -2648,6 +2697,74 @@ build_privkey_template (app_t app, int keyno, return 0; } +static gpg_error_t +build_ecdsa_privkey_template (app_t app, int keyno, + const unsigned char *ecc_d, size_t ecc_d_len, + unsigned char **result, size_t *resultlen) +{ + unsigned char privkey[2]; + size_t privkey_len; + unsigned char exthdr[2+2+1]; + size_t exthdr_len; + unsigned char suffix[2+1]; + size_t suffix_len; + unsigned char *tp; + size_t datalen; + unsigned char *template; + size_t template_size; + + *result = NULL; + *resultlen = 0; + + /* Build the 7f48 cardholder private key template. */ + datalen = 0; + tp = privkey; + + tp += add_tlv (tp, 0x91, ecc_d_len); /* Tag 0x91??? */ + datalen += ecc_d_len; + + privkey_len = tp - privkey; + + /* Build the extended header list without the private key template. */ + tp = exthdr; + *tp++ = keyno ==0 ? 0xb6 : keyno == 1? 0xb8 : 0xa4; + *tp++ = 0; + tp += add_tlv (tp, 0x7f48, privkey_len); + exthdr_len = tp - exthdr; + + /* Build the 5f48 suffix of the data. */ + tp = suffix; + tp += add_tlv (tp, 0x5f48, datalen); + suffix_len = tp - suffix; + + /* Now concatenate everything. */ + template_size = (1 + 1 /* 0x4d and len. */ + + exthdr_len + + privkey_len + + suffix_len + + datalen); + tp = template = xtrymalloc_secure (template_size); + if (!template) + return gpg_error_from_syserror (); + + tp += add_tlv (tp, 0x4d, exthdr_len + privkey_len + suffix_len + datalen); + memcpy (tp, exthdr, exthdr_len); + tp += exthdr_len; + memcpy (tp, privkey, privkey_len); + tp += privkey_len; + memcpy (tp, suffix, suffix_len); + tp += suffix_len; + + memcpy (tp, ecc_d, ecc_d_len); + tp += ecc_d_len; + + assert (tp - template == template_size); + + *result = template; + *resultlen = tp - template; + return 0; +} + /* Helper for do_writekley to change the size of a key. Not ethat this deletes the entire key without asking. */ @@ -2749,26 +2866,15 @@ change_keyattr_from_string (app_t app, } -/* Handle the WRITEKEY command for OpenPGP. This function expects a - canonical encoded S-expression with the secret key in KEYDATA and - its length (for assertions) in KEYDATALEN. KEYID needs to be the - usual keyid which for OpenPGP is the string "OPENPGP.n" with - n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall - get overwritten. PINCB and PINCB_ARG are the usual arguments for - the pinentry callback. */ static gpg_error_t -do_writekey (app_t app, ctrl_t ctrl, - const char *keyid, unsigned int flags, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg, - const unsigned char *keydata, size_t keydatalen) +rsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) { gpg_error_t err; - int force = (flags & 1); - int keyno; - const unsigned char *buf, *tok; - size_t buflen, toklen; - int depth, last_depth1, last_depth2; + const unsigned char *tok; + size_t toklen; + int last_depth1, last_depth2; const unsigned char *rsa_n = NULL; const unsigned char *rsa_e = NULL; const unsigned char *rsa_p = NULL; @@ -2782,52 +2888,6 @@ do_writekey (app_t app, ctrl_t ctrl, unsigned char fprbuf[20]; u32 created_at = 0; - (void)ctrl; - - if (!strcmp (keyid, "OPENPGP.1")) - keyno = 0; - else if (!strcmp (keyid, "OPENPGP.2")) - keyno = 1; - else if (!strcmp (keyid, "OPENPGP.3")) - keyno = 2; - else - return gpg_error (GPG_ERR_INV_ID); - - err = does_key_exist (app, keyno, 0, force); - if (err) - return err; - - - /* - Parse the S-expression - */ - buf = keydata; - buflen = keydatalen; - depth = 0; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen)) - { - if (!tok) - ; - else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen)) - log_info ("protected-private-key passed to writekey\n"); - else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) - log_info ("shadowed-private-key passed to writekey\n"); - err = gpg_error (GPG_ERR_BAD_SECKEY); - goto leave; - } - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen)) - { - err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); - goto leave; - } last_depth1 = depth; while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) && depth && depth >= last_depth1) @@ -3100,9 +3160,198 @@ do_writekey (app_t app, ctrl_t ctrl, goto leave; } - err = store_fpr (app, keyno, created_at, - rsa_n, rsa_n_len, rsa_e, rsa_e_len, - fprbuf, app->card_version); + err = store_fpr (app, keyno, created_at, fprbuf, app->card_version, + KEY_TYPE_RSA, rsa_n, rsa_n_len, rsa_e, rsa_e_len); + if (err) + goto leave; + + + leave: + xfree (template); + return err; +} + + +static gpg_error_t +ecdh_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) +{ + return GPG_ERR_NOT_IMPLEMENTED; +} + + +static gpg_error_t +ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) +{ + gpg_error_t err; + const unsigned char *tok; + size_t toklen; + int last_depth1, last_depth2; + const unsigned char *ecc_q = NULL; + const unsigned char *ecc_d = NULL; + size_t ecc_q_len, ecc_d_len; + unsigned char *template = NULL; + size_t template_len; + unsigned char fprbuf[20]; + u32 created_at = 0; + int curve = CURVE_UNKOWN; + + /* (private-key(ecdsa(curve%s)(q%m)(d%m))): curve = "1.2.840.10045.3.1.7" */ + /* (private-key(ecc(curve%s)(q%m)(d%m))): curve = "secp256k1" */ + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + + if (tok && toklen == 5 && !memcmp (tok, "curve", 5)) + { + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + + if (tok && toklen == 19 && !memcmp (tok, "1.2.840.10045.3.1.7", 19)) + curve = CURVE_NIST_P256; + else if (tok && toklen == 9 && !memcmp (tok, "secp256k1", 9)) + curve = CURVE_SEC_P256K1; + } + else if (tok && toklen == 1) + { + const unsigned char **mpi; + size_t *mpi_len; + + switch (*tok) + { + case 'q': mpi = &ecc_q; mpi_len = &ecc_q_len; break; + case 'd': mpi = &ecc_d; mpi_len = &ecc_d_len; break; + default: mpi = NULL; mpi_len = NULL; break; + } + if (mpi && *mpi) + { + err = gpg_error (GPG_ERR_DUP_VALUE); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && mpi) + { + /* Strip off leading zero bytes and save. */ + for (;toklen && !*tok; toklen--, tok++) + ; + *mpi = tok; + *mpi_len = toklen; + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + /* Parse other attributes. */ + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen)) + { + if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen))) + goto leave; + if (tok) + { + for (created_at=0; toklen && *tok && *tok >= '0' && *tok <= '9'; + tok++, toklen--) + created_at = created_at*10 + (*tok - '0'); + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + + + /* Check that we have all parameters and that they match the card + description. */ + if (!created_at) + { + log_error (_("creation timestamp missing\n")); + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + + if (opt.verbose) + log_info ("ECC private key size is %u bytes\n", (unsigned int)ecc_d_len); + + /* We need to remove the cached public key. */ + xfree (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; + app->app_local->pk[keyno].read_done = 0; + + if (app->app_local->extcap.is_v2) + { + /* Build the private key template as described in section 4.3.3.7 of + the OpenPGP card specs version 2.0. */ + int exmode; + + err = build_ecdsa_privkey_template (app, keyno, + ecc_d, ecc_d_len, + &template, &template_len); + if (err) + goto leave; + + /* Prepare for storing the key. */ + err = verify_chv3 (app, pincb, pincb_arg); + if (err) + goto leave; + + /* Store the key. */ + if (app->app_local->cardcap.ext_lc_le && template_len > 254) + exmode = 1; /* Use extended length w/o a limit. */ + else if (app->app_local->cardcap.cmd_chaining && template_len > 254) + exmode = -254; + else + exmode = 0; + err = iso7816_put_data_odd (app->slot, exmode, 0x3fff, + template, template_len); + } + else + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (err) + { + log_error (_("failed to store the key: %s\n"), gpg_strerror (err)); + goto leave; + } + + err = store_fpr (app, keyno, created_at, fprbuf, app->card_version, + KEY_TYPE_ECDSA, + curve == CURVE_NIST_P256? + "\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" + : "\05\x2b\x81\x04\x00\x0a", + curve == CURVE_NIST_P256? 9 : 6, + ecc_q, ecc_q_len); if (err) goto leave; @@ -3112,6 +3361,89 @@ do_writekey (app_t app, ctrl_t ctrl, return err; } +/* Handle the WRITEKEY command for OpenPGP. This function expects a + canonical encoded S-expression with the secret key in KEYDATA and + its length (for assertions) in KEYDATALEN. KEYID needs to be the + usual keyid which for OpenPGP is the string "OPENPGP.n" with + n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall + get overwritten. PINCB and PINCB_ARG are the usual arguments for + the pinentry callback. */ +static gpg_error_t +do_writekey (app_t app, ctrl_t ctrl, + const char *keyid, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *keydata, size_t keydatalen) +{ + gpg_error_t err; + int force = (flags & 1); + int keyno; + const unsigned char *buf, *tok; + size_t buflen, toklen; + int depth; + + (void)ctrl; + + if (!strcmp (keyid, "OPENPGP.1")) + keyno = 0; + else if (!strcmp (keyid, "OPENPGP.2")) + keyno = 1; + else if (!strcmp (keyid, "OPENPGP.3")) + keyno = 2; + else + return gpg_error (GPG_ERR_INV_ID); + + err = does_key_exist (app, keyno, 0, force); + if (err) + return err; + + + /* + Parse the S-expression + */ + buf = keydata; + buflen = keydatalen; + depth = 0; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen)) + { + if (!tok) + ; + else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen)) + log_info ("protected-private-key passed to writekey\n"); + else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) + log_info ("shadowed-private-key passed to writekey\n"); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 3 && memcmp ("rsa", tok, toklen) == 0) + rsa_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0 + && (keyno == 0 || keyno == 2)) + || (tok && toklen == 5 && memcmp ("ecdsa", tok, toklen) == 0)) + ecdsa_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0 + && keyno == 1) + || (tok && toklen == 4 && memcmp ("ecdh", tok, toklen) == 0)) + ecdh_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else + { + err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); + goto leave; + } + + leave: + return err; +} + + /* Handle the GENKEY command. */ static gpg_error_t @@ -3234,8 +3566,8 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, send_status_info (ctrl, "KEY-CREATED-AT", numbuf, (size_t)strlen(numbuf), NULL, 0); - rc = store_fpr (app, keyno, (u32)created_at, - m, mlen, e, elen, fprbuf, app->card_version); + rc = store_fpr (app, keyno, (u32)created_at, fprbuf, app->card_version, + KEY_TYPE_RSA, m, mlen, e, elen); if (rc) goto leave; send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf); @@ -3973,8 +4305,10 @@ parse_ecc_curve (const unsigned char *buffer, size_t buflen) curve = CURVE_NIST_P384; else if (buflen == 6 && buffer[5] == 0x23) curve = CURVE_NIST_P521; - else + else if (buflen == 9) curve = CURVE_NIST_P256; + else + curve = CURVE_SEC_P256K1; return curve; } -- From wk at gnupg.org Fri Mar 7 10:51:00 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 07 Mar 2014 10:51:00 +0100 Subject: Changes from 2.0 branch to master? In-Reply-To: <1394170892.3737.5.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Fri, 07 Mar 2014 14:41:32 +0900") References: <1394170892.3737.5.camel@cfw2.gniibe.org> Message-ID: <8761nqficf.fsf@vigenere.g10code.de> On Fri, 7 Mar 2014 06:41, gniibe at fsij.org said: > Bring the fix for bug 739 on 1.4 over to 2.0 (bug 1479) > author David Shaw > Fri, 1 Mar 2013 03:48:58 +0900 (13:48 -0500) > commit fe85638284880805b80778fe87ae551d3de0ca32 This is not required because of: 2010-07-16 Werner Koch * http.h (HTTP_FLAG_IGNORE_CL): Add flag . * http.c (WITHOUT_GNU_PTH): Test macro for Pth support. (http_parse_uri): s/xcalloc/xtrycalloc/. (send_request): Replace of discrete allocation and sprintf by xtryasprintf. (http_wait_response): Replace HTTP_FLAG_NO_SHUTDOWN by HTTP_FLAG_SHUTDOWN to change the default to no shutdown. > Emulate curl_easy_getinfo and CURLINFO_RESPONSE_CODE in curl-shim. > author David Shaw > Sun, 3 Mar 2013 10:07:27 +0900 (20:07 -0500) > commit 7808e4a763692b8bcd95264d39caf85fad32f0bd Not required because curl is not anymore used. > Differentiate between success (full or partial), not-found, and failure. > author David Shaw > Sun, 3 Mar 2013 10:39:48 +0900 (20:39 -0500) > commit 6d0e41815a726ad4b170ed18cc772a1817559299 I'll make sure that the new dirmngr code works similar. > * > Allow marking options as ignored. > author Werner Koch > Thu, 18 Apr 2013 21:40:43 +0900 (14:40 +0200) > commit 54c54e2824aab5716a187bbbf6dff8860d6a6056 Taken. > Ignore obsolete option --disable-keypad. > author Werner Koch > Thu, 18 Apr 2013 21:40:43 +0900 (14:40 +0200) > commit e24e92d7e244edd578c0c1f0fba6e0070cb5f104 Taken. > Allow building gpgkeys_ldap with the 32 bit mingw-w64 toolchain. > author Werner Koch > Wed, 24 Apr 2013 00:04:56 +0900 (17:04 +0200) > commit a557a74615774b228dae14cf83a92ec26e2b03b5 To be considered for the new dirmngr. > w32: Almost everywhere include winsock2.h before windows.h. > author Werner Koch > Wed, 24 Apr 2013 01:06:46 +0900 (18:06 +0200) > commit 40ca0022a7035ce5c3d715f36e0c70f310ea4c61 To many changes with a lot of white space changes. It will be easier to fix that by looking at the warnings. > Fix syntax error for building on APPLE. > author Werner Koch > Thu, 25 Apr 2013 20:00:16 +0900 (12:00 +0100) > commit 8ddf604659b93754ffa6dea295678a8adc293f90 Taken. > agent: Fix binary vs. text mode problem in ssh. > author Werner Koch > Wed, 3 Jul 2013 20:10:29 +0900 (13:10 +0200) > commit ed056d67c7c93306b68829f83a2565e978dcfd9b Taken. > ssh: Add support for Putty. > author Werner Koch > Wed, 3 Jul 2013 20:29:47 +0900 (13:29 +0200) > commit 9f32499f99a0817f63f7a73b09bdcebe60d4775d Taken. > > agent: Make --allow-mark-trusted the default. > author Werner Koch > Wed, 3 Jul 2013 22:20:25 +0900 (15:20 +0200) > commit 90b419f3e9d05e509348d047e05fcc79e87be6cf Taken. > w32: Remove unused code. > author Werner Koch > Thu, 1 Aug 2013 21:02:50 +0900 (14:02 +0200) > commit 1b89863ec195dbfdbc33432569a7b2e7f0f83821 Taken. > gpg: Remove legacy keyserver examples from the template conf file. > author Werner Koch > Tue, 6 Aug 2013 17:04:12 +0900 (10:04 +0200) > commit f3c5cc8bcd37e38b5d65db6a50466e22d03d1f0c Taken. > > Improve libcurl detection. > author Werner Koch > Tue, 6 Aug 2013 17:31:54 +0900 (10:31 +0200) > commit 110b52fffa77b339e6d59eba939408f7e87e7138 Taken. However we donot use libcurl. > gpgv: Init Libgcrypt to avoid syslog warning. > author Werner Koch > Mon, 19 Aug 2013 18:22:11 +0900 (11:22 +0200) > commit 3966eb244518d5612385d35a5149f7164a9fb707 Taken. > agent: Fix UPDATESTARTUPTTY for ssh. > author Werner Koch > Mon, 19 Aug 2013 18:44:59 +0900 (11:44 +0200) > commit 9f5578c29adba6d4f7d3650121d07322c2f8d254 Taken. > keyserver: Allow use of cURL's default CA store. > author Werner Koch > Fri, 4 Oct 2013 15:28:12 +0900 (08:28 +0200) > commit e957b9b3f408491f36660499b215aebcf2633a95 Not needed. > gpg: Protect against rogue keyservers sending secret keys. > author Werner Koch > Fri, 4 Oct 2013 20:44:39 +0900 (13:44 +0200) > commit e7abed3448c1c1a4e756c12f95b665b517d22ebe Taken. > gpg: Print a "not found" message for an unknown key in --key-edit. > author Werner Koch > Sat, 5 Oct 2013 01:34:56 +0900 (18:34 +0200) > commit 0bf54e60d31389812d05c3fd29bece876204561d Taken > gpg: Do not require a trustdb with --always-trust. > author Werner Koch > Fri, 11 Oct 2013 16:25:58 +0900 (09:25 +0200) > commit 1a0eeaacd1bf09fe5125dbc3f56016bc20f3512e Taken. Also added fix for Bug 1622. > common: Fix build problem with Sun Studio compiler. > author Werner Koch > Fri, 15 Nov 2013 17:08:58 +0900 (09:08 +0100) > commit 571bcd4662a351cfa55bbf1a79ed1bc26da5780f Taken. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Mar 7 13:59:40 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 07 Mar 2014 13:59:40 +0100 Subject: integrating Android into the GnuPG workflow In-Reply-To: (Hans of Guardian's message of "Sun, 2 Mar 2014 12:51:37 -0500") References: Message-ID: <87pplydv0j.fsf@vigenere.g10code.de> On Sun, 2 Mar 2014 18:51, hans at guardianproject.info said: > I've set up our Jenkins build server to build each commit to the gnupg.org repos so that there is automatic feedback when a commit breaks the Android build. I have noticed mails from the buold server ending up in my spam folder. Need to see what is the ause for that. > Right now, I've also been manually following up on those, which takes > a fair amount of time. And the longer build stays broken on Android, > then updating the GPGA app to the latest code becomes in effect a new > porting effort. With the build service it will be easy to fix build breaks but doing functional tests is a different thing. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Mar 7 13:55:28 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 07 Mar 2014 13:55:28 +0100 Subject: making iconv optional on Android In-Reply-To: (Hans of Guardian's message of "Sun, 2 Mar 2014 12:41:51 -0500") References: <2049380890.32.1393777490391.JavaMail.jenkins@debeater> Message-ID: <87txbadv7j.fsf@vigenere.g10code.de> On Sun, 2 Mar 2014 18:41, hans at guardianproject.info said: > It looks like iconv has become required by configure in gnupg. Can this be optional for Android? Android is UTF-8 throughout, and iconv is not currently used. I think that is possible. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Mar 7 15:33:02 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 07 Mar 2014 15:33:02 +0100 Subject: integrating Android into the GnuPG workflow In-Reply-To: <87pplydv0j.fsf@vigenere.g10code.de> (Werner Koch's message of "Fri, 07 Mar 2014 13:59:40 +0100") References: <87pplydv0j.fsf@vigenere.g10code.de> Message-ID: <87iorqdqox.fsf@vigenere.g10code.de> On Fri, 7 Mar 2014 13:59, wk at gnupg.org said: > I have noticed mails from the buold server ending up in my spam folder. The reason is that the mails are from root at guardianproject which triggers my backscatter filter. I added an exception but it is in general not a good idea to send such mails with a From root address Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From hans at guardianproject.info Sat Mar 8 03:32:39 2014 From: hans at guardianproject.info (Hans of Guardian) Date: Fri, 7 Mar 2014 21:32:39 -0500 Subject: integrating Android into the GnuPG workflow In-Reply-To: <87pplydv0j.fsf@vigenere.g10code.de> References: <87pplydv0j.fsf@vigenere.g10code.de> Message-ID: On Mar 7, 2014, at 7:59 AM, Werner Koch wrote: > On Sun, 2 Mar 2014 18:51, hans at guardianproject.info said: > >> I've set up our Jenkins build server to build each commit to the gnupg.org repos so that there is automatic feedback when a commit breaks the Android build. > > I have noticed mails from the buold server ending up in my spam folder. > Need to see what is the ause for that. Those emails are sent from root at guardianproject.info since that is an email account that we actually check (a list actually). If someone gets one of those emails without knowing where it came from, they can reply and we will get that email. >> Right now, I've also been manually following up on those, which takes >> a fair amount of time. And the longer build stays broken on Android, >> then updating the GPGA app to the latest code becomes in effect a new >> porting effort. > > With the build service it will be easy to fix build breaks but doing > functional tests is a different thing. Ok, so its currently feasible for GnuPG committers to handle fixing build breaks as they happen? If so, that's good news. Most of the GnuPG test suite is currently running as part of the Jenkins builds, so that should help. We do need to write more tests for the Android-specific side of things. .hc From wk at gnupg.org Sat Mar 8 11:25:12 2014 From: wk at gnupg.org (Werner Koch) Date: Sat, 08 Mar 2014 11:25:12 +0100 Subject: integrating Android into the GnuPG workflow In-Reply-To: (Hans of Guardian's message of "Fri, 7 Mar 2014 21:32:39 -0500") References: <87pplydv0j.fsf@vigenere.g10code.de> Message-ID: <874n39dm2f.fsf@vigenere.g10code.de> On Sat, 8 Mar 2014 03:32, hans at guardianproject.info said: > Ok, so its currently feasible for GnuPG committers to handle fixing > build breaks as they happen? If so, that's good news. Most of the Yes, the next task will be to add a configure option to build without libiconv. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From hans at guardianproject.info Sat Mar 8 19:02:35 2014 From: hans at guardianproject.info (Hans of Guardian) Date: Sat, 8 Mar 2014 13:02:35 -0500 Subject: integrating Android into the GnuPG workflow In-Reply-To: <874n39dm2f.fsf@vigenere.g10code.de> References: <87pplydv0j.fsf@vigenere.g10code.de> <874n39dm2f.fsf@vigenere.g10code.de> Message-ID: <856DBFAA-80F3-41E5-A9E7-38823A80A7A0@guardianproject.info> On Mar 8, 2014, at 5:25 AM, Werner Koch wrote: > On Sat, 8 Mar 2014 03:32, hans at guardianproject.info said: > >> Ok, so its currently feasible for GnuPG committers to handle fixing >> build breaks as they happen? If so, that's good news. Most of the > > Yes, the next task will be to add a configure option to build without > libiconv. I don't know m4, so I can't help much there. Oddly, it sounds like building GnuPG for Windows and Android will have a lot of parallels. (Or is Windows using iconv?). For for anyone committing to GnuPG, feel free to send me questions about GPG on Android, whether by email, IRC, XMPP, etc. .hc From wk at gnupg.org Sun Mar 9 10:20:08 2014 From: wk at gnupg.org (Werner Koch) Date: Sun, 09 Mar 2014 10:20:08 +0100 Subject: integrating Android into the GnuPG workflow In-Reply-To: <856DBFAA-80F3-41E5-A9E7-38823A80A7A0@guardianproject.info> (Hans of Guardian's message of "Sat, 8 Mar 2014 13:02:35 -0500") References: <87pplydv0j.fsf@vigenere.g10code.de> <874n39dm2f.fsf@vigenere.g10code.de> <856DBFAA-80F3-41E5-A9E7-38823A80A7A0@guardianproject.info> Message-ID: <87y50jd8zb.fsf@vigenere.g10code.de> On Sat, 8 Mar 2014 19:02, hans at guardianproject.info said: > I don't know m4, so I can't help much there. Oddly, it sounds like This is not an autoconf thing but pure coding. Not a big task. > building GnuPG for Windows and Android will have a lot of parallels. > (Or is Windows using iconv?). Sure it is. The change was only that it is not anymore dlopened but required. The dlopen was used in gpg 1 times so that gpg was able to work without any DLLs. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Mon Mar 10 07:52:28 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 10 Mar 2014 15:52:28 +0900 Subject: Changes from 2.0 branch to master? In-Reply-To: <8761nqficf.fsf@vigenere.g10code.de> References: <1394170892.3737.5.camel@cfw2.gniibe.org> <8761nqficf.fsf@vigenere.g10code.de> Message-ID: <1394434348.1794.4.camel@cfw2.gniibe.org> Thank you. I looked through more... to the date of gnupg-2.1.0beta3. I think that we should consider picking following nine changes to master. Five commits are about the keyserver. Those can't be applied directly. I includes them here for the references. I'm going to evaluate two commits of mine, soon. Remaining two commits are minor. ======= Minor ============ commit 7db5c81e3a40b60e146f29c6744a33fd1b88c090 Author: Werner Koch Date: Fri Nov 16 10:35:33 2012 +0100 Comment fixes. -- Reported-by: Daniel Kahn Gillmor commit 1731ed88491559aca395bc0596cdc0ee3ea1fa3e Author: Werner Koch Date: Fri Mar 30 15:29:35 2012 +0200 Cast second value of a ?: to void in estream.c. * common/estream.c (ESTREAM_MUTEX_LOCK): Cast pth_mutex_acquire result to void. Some compilers choke on mixing void and int in an conditional operator. Reported by Nelson H. F. Beebe. ======= Mine ============ commit 4f557cb9c2ebe274d6aacc60a09cd919055d01ed Author: NIIBE Yutaka Date: Mon Jun 18 15:08:01 2012 +0900 scd: acquire lock in new_reader_slot. * scd/apdu.c (new_reader_slot): Acquire lock. (open_ct_reader, open_pcsc_reader_direct, open_pcsc_reader_wrapped) (open_ccid_reader, open_rapdu_reader): Release lock. -- Fixes a test case of: No libpcsclite1 installed. Run gpg-agent Run command "gpg-connect-agent learn /bye" with no card/token Sometimes it fails: ERR 100663356 Not supported While it should be always: ERR 100663404 Card error commit 233b5ab1ad90588e7a40d2009b9f10d91e3b0c7d Author: NIIBE Yutaka Date: Mon Jun 18 14:52:53 2012 +0900 scd: move lock_slot, trylock_slot, unlock_slot functions. * scd/apdu.c (lock_slot, trylock_slot, unlock_slot): Move. -- This is for upcoming changes. ======= Keyserver ============ commit 8c32d4de57b8b0b5e1be3022d4056a854c568745 Author: David Shaw Date: Thu Dec 20 18:12:29 2012 -0500 Make sure srvcount is initialized. * keyserver/gpgkeys_hkp.c (srv_replace): Initialize srvcount. commit 732f3d1d4786239db5f31f82cc04ec79326cc13c Author: David Shaw Date: Tue Dec 18 00:08:51 2012 -0500 No point in defaulting try-dns-srv to on if we don't have SRV support. * keyserver/gpgkeys_hkp.c (main): Only default try-dns-srv to on if we have SRV support in the first place. commit 6b1f71055ebab36989e2089cfde319d2ba40ada7 Author: David Shaw Date: Mon Dec 17 23:52:15 2012 -0500 Issue 1447: Pass proper Host header and SNI when SRV is used with curl. * configure.ac: Check for inet_ntop. * m4/libcurl.m4: Provide a #define for the version of the curl library. * keyserver/gpgkeys_hkp.c (main, srv_replace): Call getaddrinfo() on each target. Once we find one that resolves to an address (whether IPv4 or IPv6), pass it into libcurl via CURLOPT_RESOLVE using the SRV name as the "host". Force the HTTP Host header to be the same. commit cbe98b2cb1e40ba253300e604996681ae191e363 Author: David Shaw Date: Sat Dec 15 10:35:19 2012 -0500 Part of issue 1447: Pass proper Host header when SRV is used. * common/http.c (send_request, connect_server): Set proper Host header (no :port, host is that of the SRV) when SRV is used in the curl-shim. commit ba9e974f1fd85b3dbbfb5e26d7a14f71d07c7cf2 Author: David Shaw Date: Sat Dec 15 10:11:11 2012 -0500 Fix issue 1446: honor ports given in SRV responses. * common/http.c (send_request, connect_server, http_open): Use a struct srv instead of a single srvtag so we can pass the chosen host and port back to the caller. (connect_server): Use the proper port in the HAVE_GETADDRINFO case. * keyserver/curl-shim.c (curl_easy_perform): Use struct srv and log chosen host and port. * keyserver/gpgkeys_hkp.c (main): Properly take the port given by SRV. -- From wk at gnupg.org Mon Mar 10 08:38:02 2014 From: wk at gnupg.org (Werner Koch) Date: Mon, 10 Mar 2014 08:38:02 +0100 Subject: [PATCH] scd: writekey support of ECC In-Reply-To: <1394162238.3737.3.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Fri, 07 Mar 2014 12:17:18 +0900") References: <1393215660.6874.3.camel@cfw2.gniibe.org> <1394162238.3737.3.camel@cfw2.gniibe.org> Message-ID: <87fvmqcxlx.fsf@vigenere.g10code.de> On Fri, 7 Mar 2014 04:17, gniibe at fsij.org said: > + va_start (ap, key_type); > + for (i = 0; i < argc; i++) > + { > + } > + va_end (ap); > + va_start (ap, key_type); A second va_start is not portable. va_copy may be used but that is also problematic because it is not available on all platforms. Either build an array of pointers, use them as you like, and only then do a final va_end. Or use just one va_start but collect everything right away using membuf_t. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Mar 10 08:41:28 2014 From: wk at gnupg.org (Werner Koch) Date: Mon, 10 Mar 2014 08:41:28 +0100 Subject: [PATCH] agent: API change of agent_key_from_file In-Reply-To: <1393902360.1734.7.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Tue, 04 Mar 2014 12:06:00 +0900") References: <1393214613.6874.1.camel@cfw2.gniibe.org> <1393902360.1734.7.camel@cfw2.gniibe.org> Message-ID: <87bnxecxg7.fsf@vigenere.g10code.de> On Tue, 4 Mar 2014 04:06, gniibe at fsij.org said: > OK to push? Okay. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Mar 10 15:46:33 2014 From: wk at gnupg.org (Werner Koch) Date: Mon, 10 Mar 2014 15:46:33 +0100 Subject: Changes from 2.0 branch to master? In-Reply-To: <1394434348.1794.4.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Mon, 10 Mar 2014 15:52:28 +0900") References: <1394170892.3737.5.camel@cfw2.gniibe.org> <8761nqficf.fsf@vigenere.g10code.de> <1394434348.1794.4.camel@cfw2.gniibe.org> Message-ID: <87a9cyaz7a.fsf@vigenere.g10code.de> On Mon, 10 Mar 2014 07:52, gniibe at fsij.org said: > commit 7db5c81e3a40b60e146f29c6744a33fd1b88c090 > Author: Werner Koch > Date: Fri Nov 16 10:35:33 2012 +0100 > > Comment fixes. Taken. > commit 1731ed88491559aca395bc0596cdc0ee3ea1fa3e > Author: Werner Koch > Date: Fri Mar 30 15:29:35 2012 +0200 > > Cast second value of a ?: to void in estream.c. > > * common/estream.c (ESTREAM_MUTEX_LOCK): Cast pth_mutex_acquire result > to void. Some compilers choke on mixing void and int in an > conditional operator. Reported by Nelson H. F. Beebe. Not anymore required. However, I have to look into the npth vs. pth issues again. Something is wrong there. > commit 4f557cb9c2ebe274d6aacc60a09cd919055d01ed > Author: NIIBE Yutaka > Date: Mon Jun 18 15:08:01 2012 +0900 > > scd: acquire lock in new_reader_slot. Taken. > commit 233b5ab1ad90588e7a40d2009b9f10d91e3b0c7d > Author: NIIBE Yutaka > Date: Mon Jun 18 14:52:53 2012 +0900 > > scd: move lock_slot, trylock_slot, unlock_slot functions. Done while resolving conflicts in above commit. > commit 8c32d4de57b8b0b5e1be3022d4056a854c568745 > Author: David Shaw > Date: Thu Dec 20 18:12:29 2012 -0500 > > Make sure srvcount is initialized. > > * keyserver/gpgkeys_hkp.c (srv_replace): Initialize srvcount. Not needed. > > commit 732f3d1d4786239db5f31f82cc04ec79326cc13c > Author: David Shaw > Date: Tue Dec 18 00:08:51 2012 -0500 > > No point in defaulting try-dns-srv to on if we don't have SRV support. > > * keyserver/gpgkeys_hkp.c (main): Only default try-dns-srv to on if we > have SRV support in the first place. Not needed. > commit 6b1f71055ebab36989e2089cfde319d2ba40ada7 > Author: David Shaw > Date: Mon Dec 17 23:52:15 2012 -0500 > > Issue 1447: Pass proper Host header and SNI when SRV is used with curl. > > * configure.ac: Check for inet_ntop. > > * m4/libcurl.m4: Provide a #define for the version of the curl > library. Applied these patches for reference. > commit cbe98b2cb1e40ba253300e604996681ae191e363 > Author: David Shaw > Date: Sat Dec 15 10:35:19 2012 -0500 > > Part of issue 1447: Pass proper Host header when SRV is used. > > * common/http.c (send_request, connect_server): Set proper Host header > (no :port, host is that of the SRV) when SRV is used in the > curl-shim. Need to look closer at this. > commit ba9e974f1fd85b3dbbfb5e26d7a14f71d07c7cf2 > Author: David Shaw > Date: Sat Dec 15 10:11:11 2012 -0500 > > Fix issue 1446: honor ports given in SRV responses. > > * common/http.c (send_request, connect_server, http_open): Use a > struct srv instead of a single srvtag so we can pass the chosen host > and port back to the caller. > (connect_server): Use the proper port in the HAVE_GETADDRINFO case. and this ... -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gnupg-devel at mlists.thewrittenword.com Mon Mar 10 21:43:43 2014 From: gnupg-devel at mlists.thewrittenword.com (Albert Chin) Date: Mon, 10 Mar 2014 15:43:43 -0500 Subject: gpgme_get_sub_protocol() returning gpgme_protocol_t instead of gpgme_error_t? Message-ID: <20140310204343.GH5483@thewrittenword.com> src/gpgme.c has: gpgme_error_t gpgme_get_sub_protocol (gpgme_ctx_t ctx) { TRACE2 (DEBUG_CTX, "gpgme_get_sub_protocol", ctx, "ctx->sub_protocol=%i (%s)", ctx->sub_protocol, gpgme_get_protocol_name (ctx->sub_protocol) ? gpgme_get_protocol_name (ctx->sub_protocol) : "invalid"); return ctx->sub_protocol; } but sub_protocol is of type: struct gpgme_context { ... /* Engine's sub protocol. */ gpgme_protocol_t sub_protocol; ... } So why doesn't isn't gpgme_get_sub_protocol declared to return gpgme_protocol_t instead? -- albert chin (china at thewrittenword.com) From gnupg-devel at mlists.thewrittenword.com Mon Mar 10 21:47:43 2014 From: gnupg-devel at mlists.thewrittenword.com (Albert Chin) Date: Mon, 10 Mar 2014 15:47:43 -0500 Subject: void * pointer math in src/gpgme.c Message-ID: <20140310204743.GI5483@thewrittenword.com> gpgme_io_writen() in src/gpgme.c does math on a void function pointer (buffer) which causes a problem for non-GNU compilers. int gpgme_io_writen (int fd, const void *buffer, size_t count) { int ret = 0; TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_writen", fd, "buffer=%p, count=%u", buffer, count); while (count) { ret = _gpgme_io_write (fd, buffer, count); if (ret < 0) break; buffer += ret; count -= ret; ret = 0; } return TRACE_SYSRES (ret); } -- albert chin (china at thewrittenword.com) From gniibe at fsij.org Tue Mar 11 08:29:20 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 11 Mar 2014 16:29:20 +0900 Subject: [PATCH] agent: API change of agent_key_from_file In-Reply-To: <87bnxecxg7.fsf@vigenere.g10code.de> References: <1393214613.6874.1.camel@cfw2.gniibe.org> <1393902360.1734.7.camel@cfw2.gniibe.org> <87bnxecxg7.fsf@vigenere.g10code.de> Message-ID: <1394522960.9009.2.camel@cfw2.gniibe.org> On 2014-03-10 at 08:41 +0100, Werner Koch wrote: > On Tue, 4 Mar 2014 04:06, gniibe at fsij.org said: > > > OK to push? > > Okay. Done. -- From wk at gnupg.org Tue Mar 11 13:49:23 2014 From: wk at gnupg.org (Werner Koch) Date: Tue, 11 Mar 2014 13:49:23 +0100 Subject: gpgme_get_sub_protocol() returning gpgme_protocol_t instead of gpgme_error_t? In-Reply-To: <20140310204343.GH5483@thewrittenword.com> (Albert Chin's message of "Mon, 10 Mar 2014 15:43:43 -0500") References: <20140310204343.GH5483@thewrittenword.com> Message-ID: <87pplsaoj0.fsf@vigenere.g10code.de> On Mon, 10 Mar 2014 21:43, gnupg-devel at mlists.thewrittenword.com said: > So why doesn't isn't gpgme_get_sub_protocol declared to return > gpgme_protocol_t instead? enum/int mismatch. Fixed. gpgme.h already used gpgme_protocol_t. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Mar 11 13:53:00 2014 From: wk at gnupg.org (Werner Koch) Date: Tue, 11 Mar 2014 13:53:00 +0100 Subject: void * pointer math in src/gpgme.c In-Reply-To: <20140310204743.GI5483@thewrittenword.com> (Albert Chin's message of "Mon, 10 Mar 2014 15:47:43 -0500") References: <20140310204743.GI5483@thewrittenword.com> Message-ID: <87lhwgaocz.fsf@vigenere.g10code.de> On Mon, 10 Mar 2014 21:47, gnupg-devel at mlists.thewrittenword.com said: > gpgme_io_writen() in src/gpgme.c does math on a void function pointer > (buffer) which causes a problem for non-GNU compilers. Fixed. Thanks. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Wed Mar 12 05:36:15 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 12 Mar 2014 13:36:15 +0900 Subject: [PATCH] scd: writekey support of ECC In-Reply-To: <87fvmqcxlx.fsf@vigenere.g10code.de> References: <1393215660.6874.3.camel@cfw2.gniibe.org> <1394162238.3737.3.camel@cfw2.gniibe.org> <87fvmqcxlx.fsf@vigenere.g10code.de> Message-ID: <1394598975.1540.4.camel@cfw2.gniibe.org> On 2014-03-10 at 08:38 +0100, Werner Koch wrote: > On Fri, 7 Mar 2014 04:17, gniibe at fsij.org said: > > > + va_start (ap, key_type); > > + for (i = 0; i < argc; i++) > > + { > > > + } > > + va_end (ap); > > > + va_start (ap, key_type); > > A second va_start is not portable. Thanks for review. I realized that here will be just a single use of multiple va_start in GnuPG. I don't want to introduce new portability issue. Here is revised version. I use array. I'm going to summarize possible changes for OpenPGP card specification in wiki.gnupg.org. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 3d7136f..da1bec9 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1,6 +1,6 @@ /* app-openpgp.c - The OpenPGP card application. * Copyright (C) 2003, 2004, 2005, 2007, 2008, - * 2009, 2013 Free Software Foundation, Inc. + * 2009, 2013, 2014 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -143,7 +144,9 @@ enum { CURVE_NIST_P256, CURVE_NIST_P384, - CURVE_NIST_P521 + CURVE_NIST_P521, + CURVE_SEC_P256K1, + CURVE_UNKOWN, }; @@ -735,24 +738,58 @@ parse_login_data (app_t app) xfree (relptr); } + +static unsigned char +get_algo_byte (key_type_t key_type) +{ + if (key_type == KEY_TYPE_ECDSA) + return 19; + else if (key_type == KEY_TYPE_ECDH) + return 18; + else + return 1; /* RSA */ +} + +#define MAX_ARGS_STORE_FPR 3 + /* Note, that FPR must be at least 20 bytes. */ static gpg_error_t store_fpr (app_t app, int keynumber, u32 timestamp, - const unsigned char *m, size_t mlen, - const unsigned char *e, size_t elen, - unsigned char *fpr, unsigned int card_version) + unsigned char *fpr, unsigned int card_version, + key_type_t key_type, + ...) { unsigned int n, nbits; unsigned char *buffer, *p; int tag, tag2; int rc; + const unsigned char *m[MAX_ARGS_STORE_FPR]; + size_t mlen[MAX_ARGS_STORE_FPR]; + va_list ap; + int argc; + int i; - for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ - ; - for (; elen && !*e; elen--, e++) /* strip leading zeroes */ - ; + n = 6; /* key packet version, 4-byte timestamps, and algorithm */ + if (key_type == KEY_TYPE_RSA || key_type == KEY_TYPE_ECDSA) + argc = 2; + else if (key_type == KEY_TYPE_ECDH) + argc = 3; + else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + va_start (ap, key_type); + for (i = 0; i < argc; i++) + { + m[i] = va_arg (ap, const unsigned char *); + mlen[i] = va_arg (ap, size_t); + for (; mlen[i] && !*m[i]; mlen[i]--, m[i]++) /* strip leading zeroes */ + ; + if (key_type == KEY_TYPE_RSA || i == 1) + n += 2; + n += mlen[i]; + } + va_end (ap); - n = 6 + 2 + mlen + 2 + elen; p = buffer = xtrymalloc (3 + n); if (!buffer) return gpg_error_from_syserror (); @@ -765,15 +802,19 @@ store_fpr (app_t app, int keynumber, u32 timestamp, *p++ = timestamp >> 16; *p++ = timestamp >> 8; *p++ = timestamp; - *p++ = 1; /* RSA */ - nbits = count_bits (m, mlen); - *p++ = nbits >> 8; - *p++ = nbits; - memcpy (p, m, mlen); p += mlen; - nbits = count_bits (e, elen); - *p++ = nbits >> 8; - *p++ = nbits; - memcpy (p, e, elen); p += elen; + *p++ = get_algo_byte (key_type); + + for (i = 0; i < argc; i++) + { + if (key_type == KEY_TYPE_RSA || i == 1) + { + nbits = count_bits (m[i], mlen[i]); + *p++ = nbits >> 8; + *p++ = nbits; + } + memcpy (p, m[i], mlen[i]); + p += mlen[i]; + } gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3); @@ -889,11 +930,16 @@ get_ecc_key_parameters (int curve, int *r_n_bits, const char **r_curve_oid) *r_n_bits = 384; *r_curve_oid = "1.3.132.0.34"; } - else + else if (curve == CURVE_NIST_P521) { *r_n_bits = 521; *r_curve_oid = "1.3.132.0.35"; } + else + { + *r_n_bits = 256; + *r_curve_oid = "1.3.132.0.10"; + } } static void @@ -1234,8 +1280,10 @@ get_curve_name (int curve) return "NIST P-256"; else if (curve == CURVE_NIST_P384) return "NIST P-384"; - else + else if (curve == CURVE_NIST_P521) return "NIST P-521"; + else + return "secp256k1"; } @@ -1456,7 +1504,7 @@ get_public_key (app_t app, int keyno) = get_curve_name (app->app_local->keyattr[keyno].ecdsa.curve); err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdsa(curve%s)(q%b)))", + "(public-key(ecc(curve%s)(q%b)))", curve_name, mlen, mbuf); if (err) goto leave; @@ -2500,8 +2548,6 @@ add_tlv (unsigned char *buffer, unsigned int tag, size_t length) } -/* Build the private key template as specified in the OpenPGP specs - v2.0 section 4.3.3.7. */ static gpg_error_t build_privkey_template (app_t app, int keyno, const unsigned char *rsa_n, size_t rsa_n_len, @@ -2648,6 +2694,74 @@ build_privkey_template (app_t app, int keyno, return 0; } +static gpg_error_t +build_ecdsa_privkey_template (app_t app, int keyno, + const unsigned char *ecc_d, size_t ecc_d_len, + unsigned char **result, size_t *resultlen) +{ + unsigned char privkey[2]; + size_t privkey_len; + unsigned char exthdr[2+2+1]; + size_t exthdr_len; + unsigned char suffix[2+1]; + size_t suffix_len; + unsigned char *tp; + size_t datalen; + unsigned char *template; + size_t template_size; + + *result = NULL; + *resultlen = 0; + + /* Build the 7f48 cardholder private key template. */ + datalen = 0; + tp = privkey; + + tp += add_tlv (tp, 0x91, ecc_d_len); /* Tag 0x91??? */ + datalen += ecc_d_len; + + privkey_len = tp - privkey; + + /* Build the extended header list without the private key template. */ + tp = exthdr; + *tp++ = keyno ==0 ? 0xb6 : keyno == 1? 0xb8 : 0xa4; + *tp++ = 0; + tp += add_tlv (tp, 0x7f48, privkey_len); + exthdr_len = tp - exthdr; + + /* Build the 5f48 suffix of the data. */ + tp = suffix; + tp += add_tlv (tp, 0x5f48, datalen); + suffix_len = tp - suffix; + + /* Now concatenate everything. */ + template_size = (1 + 1 /* 0x4d and len. */ + + exthdr_len + + privkey_len + + suffix_len + + datalen); + tp = template = xtrymalloc_secure (template_size); + if (!template) + return gpg_error_from_syserror (); + + tp += add_tlv (tp, 0x4d, exthdr_len + privkey_len + suffix_len + datalen); + memcpy (tp, exthdr, exthdr_len); + tp += exthdr_len; + memcpy (tp, privkey, privkey_len); + tp += privkey_len; + memcpy (tp, suffix, suffix_len); + tp += suffix_len; + + memcpy (tp, ecc_d, ecc_d_len); + tp += ecc_d_len; + + assert (tp - template == template_size); + + *result = template; + *resultlen = tp - template; + return 0; +} + /* Helper for do_writekley to change the size of a key. Not ethat this deletes the entire key without asking. */ @@ -2749,26 +2863,15 @@ change_keyattr_from_string (app_t app, } -/* Handle the WRITEKEY command for OpenPGP. This function expects a - canonical encoded S-expression with the secret key in KEYDATA and - its length (for assertions) in KEYDATALEN. KEYID needs to be the - usual keyid which for OpenPGP is the string "OPENPGP.n" with - n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall - get overwritten. PINCB and PINCB_ARG are the usual arguments for - the pinentry callback. */ static gpg_error_t -do_writekey (app_t app, ctrl_t ctrl, - const char *keyid, unsigned int flags, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg, - const unsigned char *keydata, size_t keydatalen) +rsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) { gpg_error_t err; - int force = (flags & 1); - int keyno; - const unsigned char *buf, *tok; - size_t buflen, toklen; - int depth, last_depth1, last_depth2; + const unsigned char *tok; + size_t toklen; + int last_depth1, last_depth2; const unsigned char *rsa_n = NULL; const unsigned char *rsa_e = NULL; const unsigned char *rsa_p = NULL; @@ -2782,52 +2885,6 @@ do_writekey (app_t app, ctrl_t ctrl, unsigned char fprbuf[20]; u32 created_at = 0; - (void)ctrl; - - if (!strcmp (keyid, "OPENPGP.1")) - keyno = 0; - else if (!strcmp (keyid, "OPENPGP.2")) - keyno = 1; - else if (!strcmp (keyid, "OPENPGP.3")) - keyno = 2; - else - return gpg_error (GPG_ERR_INV_ID); - - err = does_key_exist (app, keyno, 0, force); - if (err) - return err; - - - /* - Parse the S-expression - */ - buf = keydata; - buflen = keydatalen; - depth = 0; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen)) - { - if (!tok) - ; - else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen)) - log_info ("protected-private-key passed to writekey\n"); - else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) - log_info ("shadowed-private-key passed to writekey\n"); - err = gpg_error (GPG_ERR_BAD_SECKEY); - goto leave; - } - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) - goto leave; - if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen)) - { - err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); - goto leave; - } last_depth1 = depth; while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) && depth && depth >= last_depth1) @@ -3100,9 +3157,198 @@ do_writekey (app_t app, ctrl_t ctrl, goto leave; } - err = store_fpr (app, keyno, created_at, - rsa_n, rsa_n_len, rsa_e, rsa_e_len, - fprbuf, app->card_version); + err = store_fpr (app, keyno, created_at, fprbuf, app->card_version, + KEY_TYPE_RSA, rsa_n, rsa_n_len, rsa_e, rsa_e_len); + if (err) + goto leave; + + + leave: + xfree (template); + return err; +} + + +static gpg_error_t +ecdh_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) +{ + return GPG_ERR_NOT_IMPLEMENTED; +} + + +static gpg_error_t +ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, int keyno, + const unsigned char *buf, size_t buflen, int depth) +{ + gpg_error_t err; + const unsigned char *tok; + size_t toklen; + int last_depth1, last_depth2; + const unsigned char *ecc_q = NULL; + const unsigned char *ecc_d = NULL; + size_t ecc_q_len, ecc_d_len; + unsigned char *template = NULL; + size_t template_len; + unsigned char fprbuf[20]; + u32 created_at = 0; + int curve = CURVE_UNKOWN; + + /* (private-key(ecdsa(curve%s)(q%m)(d%m))): curve = "1.2.840.10045.3.1.7" */ + /* (private-key(ecc(curve%s)(q%m)(d%m))): curve = "secp256k1" */ + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + + if (tok && toklen == 5 && !memcmp (tok, "curve", 5)) + { + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + + if (tok && toklen == 19 && !memcmp (tok, "1.2.840.10045.3.1.7", 19)) + curve = CURVE_NIST_P256; + else if (tok && toklen == 9 && !memcmp (tok, "secp256k1", 9)) + curve = CURVE_SEC_P256K1; + } + else if (tok && toklen == 1) + { + const unsigned char **mpi; + size_t *mpi_len; + + switch (*tok) + { + case 'q': mpi = &ecc_q; mpi_len = &ecc_q_len; break; + case 'd': mpi = &ecc_d; mpi_len = &ecc_d_len; break; + default: mpi = NULL; mpi_len = NULL; break; + } + if (mpi && *mpi) + { + err = gpg_error (GPG_ERR_DUP_VALUE); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && mpi) + { + /* Strip off leading zero bytes and save. */ + for (;toklen && !*tok; toklen--, tok++) + ; + *mpi = tok; + *mpi_len = toklen; + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + /* Parse other attributes. */ + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen)) + { + if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen))) + goto leave; + if (tok) + { + for (created_at=0; toklen && *tok && *tok >= '0' && *tok <= '9'; + tok++, toklen--) + created_at = created_at*10 + (*tok - '0'); + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + + + /* Check that we have all parameters and that they match the card + description. */ + if (!created_at) + { + log_error (_("creation timestamp missing\n")); + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + + if (opt.verbose) + log_info ("ECC private key size is %u bytes\n", (unsigned int)ecc_d_len); + + /* We need to remove the cached public key. */ + xfree (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; + app->app_local->pk[keyno].read_done = 0; + + if (app->app_local->extcap.is_v2) + { + /* Build the private key template as described in section 4.3.3.7 of + the OpenPGP card specs version 2.0. */ + int exmode; + + err = build_ecdsa_privkey_template (app, keyno, + ecc_d, ecc_d_len, + &template, &template_len); + if (err) + goto leave; + + /* Prepare for storing the key. */ + err = verify_chv3 (app, pincb, pincb_arg); + if (err) + goto leave; + + /* Store the key. */ + if (app->app_local->cardcap.ext_lc_le && template_len > 254) + exmode = 1; /* Use extended length w/o a limit. */ + else if (app->app_local->cardcap.cmd_chaining && template_len > 254) + exmode = -254; + else + exmode = 0; + err = iso7816_put_data_odd (app->slot, exmode, 0x3fff, + template, template_len); + } + else + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (err) + { + log_error (_("failed to store the key: %s\n"), gpg_strerror (err)); + goto leave; + } + + err = store_fpr (app, keyno, created_at, fprbuf, app->card_version, + KEY_TYPE_ECDSA, + curve == CURVE_NIST_P256? + "\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" + : "\05\x2b\x81\x04\x00\x0a", + curve == CURVE_NIST_P256? 9 : 6, + ecc_q, ecc_q_len); if (err) goto leave; @@ -3112,6 +3358,89 @@ do_writekey (app_t app, ctrl_t ctrl, return err; } +/* Handle the WRITEKEY command for OpenPGP. This function expects a + canonical encoded S-expression with the secret key in KEYDATA and + its length (for assertions) in KEYDATALEN. KEYID needs to be the + usual keyid which for OpenPGP is the string "OPENPGP.n" with + n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall + get overwritten. PINCB and PINCB_ARG are the usual arguments for + the pinentry callback. */ +static gpg_error_t +do_writekey (app_t app, ctrl_t ctrl, + const char *keyid, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *keydata, size_t keydatalen) +{ + gpg_error_t err; + int force = (flags & 1); + int keyno; + const unsigned char *buf, *tok; + size_t buflen, toklen; + int depth; + + (void)ctrl; + + if (!strcmp (keyid, "OPENPGP.1")) + keyno = 0; + else if (!strcmp (keyid, "OPENPGP.2")) + keyno = 1; + else if (!strcmp (keyid, "OPENPGP.3")) + keyno = 2; + else + return gpg_error (GPG_ERR_INV_ID); + + err = does_key_exist (app, keyno, 0, force); + if (err) + return err; + + + /* + Parse the S-expression + */ + buf = keydata; + buflen = keydatalen; + depth = 0; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen)) + { + if (!tok) + ; + else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen)) + log_info ("protected-private-key passed to writekey\n"); + else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) + log_info ("shadowed-private-key passed to writekey\n"); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 3 && memcmp ("rsa", tok, toklen) == 0) + rsa_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0 + && (keyno == 0 || keyno == 2)) + || (tok && toklen == 5 && memcmp ("ecdsa", tok, toklen) == 0)) + ecdsa_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0 + && keyno == 1) + || (tok && toklen == 4 && memcmp ("ecdh", tok, toklen) == 0)) + ecdh_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth); + else + { + err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); + goto leave; + } + + leave: + return err; +} + + /* Handle the GENKEY command. */ static gpg_error_t @@ -3234,8 +3563,8 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, send_status_info (ctrl, "KEY-CREATED-AT", numbuf, (size_t)strlen(numbuf), NULL, 0); - rc = store_fpr (app, keyno, (u32)created_at, - m, mlen, e, elen, fprbuf, app->card_version); + rc = store_fpr (app, keyno, (u32)created_at, fprbuf, app->card_version, + KEY_TYPE_RSA, m, mlen, e, elen); if (rc) goto leave; send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf); @@ -3973,8 +4302,10 @@ parse_ecc_curve (const unsigned char *buffer, size_t buflen) curve = CURVE_NIST_P384; else if (buflen == 6 && buffer[5] == 0x23) curve = CURVE_NIST_P521; - else + else if (buflen == 9) curve = CURVE_NIST_P256; + else + curve = CURVE_SEC_P256K1; return curve; } -- From wk at gnupg.org Wed Mar 12 09:03:40 2014 From: wk at gnupg.org (Werner Koch) Date: Wed, 12 Mar 2014 09:03:40 +0100 Subject: [PATCH] scd: writekey support of ECC In-Reply-To: <1394598975.1540.4.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Wed, 12 Mar 2014 13:36:15 +0900") References: <1393215660.6874.3.camel@cfw2.gniibe.org> <1394162238.3737.3.camel@cfw2.gniibe.org> <87fvmqcxlx.fsf@vigenere.g10code.de> <1394598975.1540.4.camel@cfw2.gniibe.org> Message-ID: <87ha739737.fsf@vigenere.g10code.de> On Wed, 12 Mar 2014 05:36, gniibe at fsij.org said: > Here is revised version. I use array. Looks good. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From gniibe at fsij.org Wed Mar 12 09:28:05 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Wed, 12 Mar 2014 17:28:05 +0900 Subject: [PATCH] scd: writekey support of ECC In-Reply-To: <87ha739737.fsf@vigenere.g10code.de> References: <1393215660.6874.3.camel@cfw2.gniibe.org> <1394162238.3737.3.camel@cfw2.gniibe.org> <87fvmqcxlx.fsf@vigenere.g10code.de> <1394598975.1540.4.camel@cfw2.gniibe.org> <87ha739737.fsf@vigenere.g10code.de> Message-ID: <1394612885.10605.2.camel@cfw2.gniibe.org> On 2014-03-12 at 09:03 +0100, Werner Koch wrote: > On Wed, 12 Mar 2014 05:36, gniibe at fsij.org said: > > > Here is revised version. I use array. > > Looks good. Thanks for the review. I applied and pushed it. -- From hans at guardianproject.info Wed Mar 12 19:23:44 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Wed, 12 Mar 2014 14:23:44 -0400 Subject: gpgme still failing on Android In-Reply-To: <54037697.58.1394647675573.JavaMail.jenkins@debeater> References: <54037697.58.1394647675573.JavaMail.jenkins@debeater> Message-ID: <5320A630.4070307@guardianproject.info> Commit 02ba35c1b6a2cbb3361b2f2ad507c53564b2be0b broke gpgme on Android, and its still failing. We talked in the past about reinstating static paths for Android since its kludgey to rely on env vars like PATH on Android. What is the path forward on this? .hc Here's the breakage report: -------- Original Message -------- Subject: Build failed in Jenkins: gnupg-for-android-eighthave-git-release-branches #58 Date: Wed, 12 Mar 2014 14:07:55 -0400 (EDT) To: hans at guardianproject.info See ------------------------------------------ [...truncated 19561 lines...] CCM dec | 93.05 ns/B 10.25 MiB/s - c/B CCM auth | 49.71 ns/B 19.19 MiB/s - c/B GCM enc | 201.3 ns/B 4.74 MiB/s - c/B GCM dec | 200.7 ns/B 4.75 MiB/s - c/B GCM auth | 153.5 ns/B 6.21 MiB/s - c/B = ARCFOUR | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 26.65 ns/B 35.78 MiB/s - c/B STREAM dec | 26.16 ns/B 36.45 MiB/s - c/B = DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 418.2 ns/B 2.28 MiB/s - c/B ECB dec | 409.2 ns/B 2.33 MiB/s - c/B CBC enc | 439.0 ns/B 2.17 MiB/s - c/B CBC dec | 443.9 ns/B 2.15 MiB/s - c/B CFB enc | 450.3 ns/B 2.12 MiB/s - c/B CFB dec | 464.1 ns/B 2.06 MiB/s - c/B OFB enc | 445.4 ns/B 2.14 MiB/s - c/B OFB dec | 446.3 ns/B 2.14 MiB/s - c/B CTR enc | 445.6 ns/B 2.14 MiB/s - c/B CTR dec | 439.0 ns/B 2.17 MiB/s - c/B = TWOFISH128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 33.03 ns/B 28.87 MiB/s - c/B ECB dec | 32.49 ns/B 29.35 MiB/s - c/B CBC enc | 49.28 ns/B 19.35 MiB/s - c/B CBC dec | 43.87 ns/B 21.74 MiB/s - c/B CFB enc | 42.68 ns/B 22.35 MiB/s - c/B CFB dec | 51.38 ns/B 18.56 MiB/s - c/B OFB enc | 43.93 ns/B 21.71 MiB/s - c/B OFB dec | 42.33 ns/B 22.53 MiB/s - c/B CTR enc | 44.45 ns/B 21.46 MiB/s - c/B CTR dec | 44.29 ns/B 21.53 MiB/s - c/B CCM enc | 91.40 ns/B 10.43 MiB/s - c/B CCM dec | 92.29 ns/B 10.33 MiB/s - c/B CCM auth | 47.82 ns/B 19.94 MiB/s - c/B GCM enc | 201.0 ns/B 4.75 MiB/s - c/B GCM dec | 200.6 ns/B 4.75 MiB/s - c/B GCM auth | 156.3 ns/B 6.10 MiB/s - c/B = SERPENT128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 1612.1 ns/B 0.592 MiB/s - c/B ECB dec | 1765.7 ns/B 0.540 MiB/s - c/B CBC enc | 1634.5 ns/B 0.583 MiB/s - c/B CBC dec | 228.9 ns/B 4.17 MiB/s - c/B CFB enc | 1637.1 ns/B 0.583 MiB/s - c/B CFB dec | 258.4 ns/B 3.69 MiB/s - c/B OFB enc | 1649.9 ns/B 0.578 MiB/s - c/B OFB dec | 1634.3 ns/B 0.584 MiB/s - c/B CTR enc | 268.7 ns/B 3.55 MiB/s - c/B CTR dec | 246.9 ns/B 3.86 MiB/s - c/B CCM enc | 1917.4 ns/B 0.497 MiB/s - c/B CCM dec | 1883.6 ns/B 0.506 MiB/s - c/B CCM auth | 1654.6 ns/B 0.576 MiB/s - c/B GCM enc | 417.5 ns/B 2.28 MiB/s - c/B GCM dec | 405.6 ns/B 2.35 MiB/s - c/B GCM auth | 152.3 ns/B 6.26 MiB/s - c/B = SERPENT192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 1601.6 ns/B 0.595 MiB/s - c/B ECB dec | 1754.8 ns/B 0.543 MiB/s - c/B CBC enc | 1656.6 ns/B 0.576 MiB/s - c/B CBC dec | 258.7 ns/B 3.69 MiB/s - c/B CFB enc | 1620.9 ns/B 0.588 MiB/s - c/B CFB dec | 259.2 ns/B 3.68 MiB/s - c/B OFB enc | 1627.0 ns/B 0.586 MiB/s - c/B OFB dec | 1655.2 ns/B 0.576 MiB/s - c/B CTR enc | 248.9 ns/B 3.83 MiB/s - c/B CTR dec | 271.4 ns/B 3.51 MiB/s - c/B CCM enc | 1934.5 ns/B 0.493 MiB/s - c/B CCM dec | 1944.5 ns/B 0.490 MiB/s - c/B CCM auth | 1661.2 ns/B 0.574 MiB/s - c/B GCM enc | 409.0 ns/B 2.33 MiB/s - c/B GCM dec | 449.0 ns/B 2.12 MiB/s - c/B GCM auth | 154.6 ns/B 6.17 MiB/s - c/B = SERPENT256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 1625.2 ns/B 0.587 MiB/s - c/B ECB dec | 1720.2 ns/B 0.554 MiB/s - c/B CBC enc | 1619.8 ns/B 0.589 MiB/s - c/B CBC dec | 253.2 ns/B 3.77 MiB/s - c/B CFB enc | 1621.1 ns/B 0.588 MiB/s - c/B CFB dec | 253.5 ns/B 3.76 MiB/s - c/B OFB enc | 1608.1 ns/B 0.593 MiB/s - c/B OFB dec | 1644.2 ns/B 0.580 MiB/s - c/B CTR enc | 248.0 ns/B 3.84 MiB/s - c/B CTR dec | 250.4 ns/B 3.81 MiB/s - c/B CCM enc | 2068.9 ns/B 0.461 MiB/s - c/B CCM dec | 1935.8 ns/B 0.493 MiB/s - c/B CCM auth | 1642.6 ns/B 0.581 MiB/s - c/B GCM enc | 355.3 ns/B 2.68 MiB/s - c/B GCM dec | 402.6 ns/B 2.37 MiB/s - c/B GCM auth | 163.0 ns/B 5.85 MiB/s - c/B = RFC2268_40 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 240.0 ns/B 3.97 MiB/s - c/B ECB dec | 225.4 ns/B 4.23 MiB/s - c/B CBC enc | 253.9 ns/B 3.76 MiB/s - c/B CBC dec | 257.9 ns/B 3.70 MiB/s - c/B CFB enc | 255.0 ns/B 3.74 MiB/s - c/B CFB dec | 277.7 ns/B 3.43 MiB/s - c/B OFB enc | 254.8 ns/B 3.74 MiB/s - c/B OFB dec | 254.2 ns/B 3.75 MiB/s - c/B CTR enc | 256.5 ns/B 3.72 MiB/s - c/B CTR dec | 255.3 ns/B 3.74 MiB/s - c/B = RFC2268_128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 239.8 ns/B 3.98 MiB/s - c/B ECB dec | 229.4 ns/B 4.16 MiB/s - c/B CBC enc | 253.0 ns/B 3.77 MiB/s - c/B CBC dec | 257.6 ns/B 3.70 MiB/s - c/B CFB enc | 253.2 ns/B 3.77 MiB/s - c/B CFB dec | 279.4 ns/B 3.41 MiB/s - c/B OFB enc | 253.7 ns/B 3.76 MiB/s - c/B OFB dec | 254.5 ns/B 3.75 MiB/s - c/B CTR enc | 254.7 ns/B 3.74 MiB/s - c/B CTR dec | 255.4 ns/B 3.73 MiB/s - c/B = SEED | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 264.8 ns/B 3.60 MiB/s - c/B ECB dec | 266.5 ns/B 3.58 MiB/s - c/B CBC enc | 275.3 ns/B 3.46 MiB/s - c/B CBC dec | 285.9 ns/B 3.34 MiB/s - c/B CFB enc | 282.9 ns/B 3.37 MiB/s - c/B CFB dec | 340.9 ns/B 2.80 MiB/s - c/B OFB enc | 276.7 ns/B 3.45 MiB/s - c/B OFB dec | 284.7 ns/B 3.35 MiB/s - c/B CTR enc | 276.8 ns/B 3.45 MiB/s - c/B CTR dec | 285.3 ns/B 3.34 MiB/s - c/B CCM enc | 577.6 ns/B 1.65 MiB/s - c/B CCM dec | 573.6 ns/B 1.66 MiB/s - c/B CCM auth | 286.3 ns/B 3.33 MiB/s - c/B GCM enc | 450.9 ns/B 2.12 MiB/s - c/B GCM dec | 450.8 ns/B 2.12 MiB/s - c/B GCM auth | 154.0 ns/B 6.19 MiB/s - c/B = CAMELLIA128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 38.82 ns/B 24.56 MiB/s - c/B ECB dec | 37.82 ns/B 25.21 MiB/s - c/B CBC enc | 57.40 ns/B 16.61 MiB/s - c/B CBC dec | 53.20 ns/B 17.93 MiB/s - c/B CFB enc | 49.66 ns/B 19.20 MiB/s - c/B CFB dec | 58.48 ns/B 16.31 MiB/s - c/B OFB enc | 50.31 ns/B 18.96 MiB/s - c/B OFB dec | 50.74 ns/B 18.79 MiB/s - c/B CTR enc | 50.02 ns/B 19.07 MiB/s - c/B CTR dec | 51.09 ns/B 18.67 MiB/s - c/B CCM enc | 108.1 ns/B 8.82 MiB/s - c/B CCM dec | 106.3 ns/B 8.97 MiB/s - c/B CCM auth | 58.25 ns/B 16.37 MiB/s - c/B GCM enc | 207.1 ns/B 4.61 MiB/s - c/B GCM dec | 205.4 ns/B 4.64 MiB/s - c/B GCM auth | 157.3 ns/B 6.06 MiB/s - c/B = CAMELLIA192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 53.91 ns/B 17.69 MiB/s - c/B ECB dec | 62.21 ns/B 15.33 MiB/s - c/B CBC enc | 78.50 ns/B 12.15 MiB/s - c/B CBC dec | 75.98 ns/B 12.55 MiB/s - c/B CFB enc | 79.27 ns/B 12.03 MiB/s - c/B CFB dec | 81.36 ns/B 11.72 MiB/s - c/B OFB enc | 78.02 ns/B 12.22 MiB/s - c/B OFB dec | 78.55 ns/B 12.14 MiB/s - c/B CTR enc | 69.45 ns/B 13.73 MiB/s - c/B CTR dec | 70.34 ns/B 13.56 MiB/s - c/B CCM enc | 146.6 ns/B 6.51 MiB/s - c/B CCM dec | 150.2 ns/B 6.35 MiB/s - c/B CCM auth | 79.21 ns/B 12.04 MiB/s - c/B GCM enc | 229.8 ns/B 4.15 MiB/s - c/B GCM dec | 231.7 ns/B 4.12 MiB/s - c/B GCM auth | 152.8 ns/B 6.24 MiB/s - c/B = CAMELLIA256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 60.90 ns/B 15.66 MiB/s - c/B ECB dec | 61.58 ns/B 15.49 MiB/s - c/B CBC enc | 80.76 ns/B 11.81 MiB/s - c/B CBC dec | 78.63 ns/B 12.13 MiB/s - c/B CFB enc | 78.75 ns/B 12.11 MiB/s - c/B CFB dec | 81.16 ns/B 11.75 MiB/s - c/B OFB enc | 77.83 ns/B 12.25 MiB/s - c/B OFB dec | 78.12 ns/B 12.21 MiB/s - c/B CTR enc | 69.75 ns/B 13.67 MiB/s - c/B CTR dec | 70.92 ns/B 13.45 MiB/s - c/B CCM enc | 144.6 ns/B 6.59 MiB/s - c/B CCM dec | 144.8 ns/B 6.59 MiB/s - c/B CCM auth | 76.03 ns/B 12.54 MiB/s - c/B GCM enc | 227.4 ns/B 4.19 MiB/s - c/B GCM dec | 227.9 ns/B 4.19 MiB/s - c/B GCM auth | 155.5 ns/B 6.13 MiB/s - c/B = SALSA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 37.51 ns/B 25.43 MiB/s - c/B STREAM dec | 36.50 ns/B 26.13 MiB/s - c/B = SALSA20R12 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 28.15 ns/B 33.88 MiB/s - c/B STREAM dec | 28.73 ns/B 33.20 MiB/s - c/B = GOST28147 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 309.3 ns/B 3.08 MiB/s - c/B ECB dec | 326.6 ns/B 2.92 MiB/s - c/B CBC enc | 325.4 ns/B 2.93 MiB/s - c/B CBC dec | 357.0 ns/B 2.67 MiB/s - c/B CFB enc | 331.4 ns/B 2.88 MiB/s - c/B CFB dec | 354.7 ns/B 2.69 MiB/s - c/B OFB enc | 326.5 ns/B 2.92 MiB/s - c/B OFB dec | 325.5 ns/B 2.93 MiB/s - c/B CTR enc | 329.0 ns/B 2.90 MiB/s - c/B CTR dec | 338.8 ns/B 2.82 MiB/s - c/B = DONE. ------------------------------ gpgme tests: Running gpgme/t-version DONE. Running gpgme/t-engine-info DONE. Running gpgme/t-data DONE. Running gpgme/run-import --verbose pubkey-1.asc run-import: file run-support.h line 133: Invalid crypto engine Running gpgme/run-import --verbose pubdemo.asc run-import: file run-support.h line 133: Invalid crypto engine Running gpgme/run-import --verbose pubkey-1.asc run-import: file run-support.h line 133: Invalid crypto engine Running gpgme/run-keylist --verbose run-keylist: file run-support.h line 133: Invalid crypto engine Running gpgme/run-import --verbose seckey-1.asc run-import: file run-support.h line 133: Invalid crypto engine Running gpgme/run-import --verbose secdemo.asc run-import: file run-support.h line 133: Invalid crypto engine Running gpgme/run-keylist --verbose run-keylist: file run-support.h line 133: Invalid crypto engine FAILED + tail -1 /tmp/tmp.vPCkDX8TfZ + cut -b1-7 + [ FAILED != SUCCESS ] + echo /data/data/info.guardianproject.gpg/app_opt/tests/run-tests.sh FAILED! /data/data/info.guardianproject.gpg/app_opt/tests/run-tests.sh FAILED! + false Build step 'Execute shell' marked build as failure $ /opt/android-sdk/platform-tools/adb disconnect localhost:52968 [android] Stopping Android emulator [android] Archiving emulator log $ /opt/android-sdk/platform-tools/adb kill-server Terminating xvnc. $ vncserver -kill :58 Killing Xvnc4 process ID 826 From wk at gnupg.org Wed Mar 12 19:41:13 2014 From: wk at gnupg.org (Werner Koch) Date: Wed, 12 Mar 2014 19:41:13 +0100 Subject: gpgme still failing on Android In-Reply-To: <5320A630.4070307@guardianproject.info> (Hans-Christoph Steiner's message of "Wed, 12 Mar 2014 14:23:44 -0400") References: <54037697.58.1394647675573.JavaMail.jenkins@debeater> <5320A630.4070307@guardianproject.info> Message-ID: <87wqfz5kfq.fsf@vigenere.g10code.de> On Wed, 12 Mar 2014 19:23, hans at guardianproject.info said: > its still failing. We talked in the past about reinstating static paths for > Android since its kludgey to rely on env vars like PATH on Android. What is The discussion diverted to some general Unix/Android topics and I forgot about the last on topic thing: > Okay - which path? Build time configuration or runtime configuration? > A fixed directory for Android seems to be the best appraoch Yes, a build time config is perfect. Well, I'll do that tomorrow. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From hans at guardianproject.info Thu Mar 13 02:01:39 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Wed, 12 Mar 2014 21:01:39 -0400 Subject: how to install the po translations on Android In-Reply-To: <871tyqwbqt.fsf@vigenere.g10code.de> References: <530B9221.6050409@guardianproject.info> <878ut0xprg.fsf@vigenere.g10code.de> <530BA67D.9010606@guardianproject.info> <530BC9C2.7040405@guardianproject.info> <87vbw3wods.fsf@vigenere.g10code.de> <530CB84D.8080308@guardianproject.info> <871tyqwbqt.fsf@vigenere.g10code.de> Message-ID: <53210373.2080808@guardianproject.info> On 02/26/2014 02:53 AM, Werner Koch wrote: > On Tue, 25 Feb 2014 16:35, hans at guardianproject.info said: > >> The gettext it is looking for is the C functions for loading the translations? > > yes. > >> That's my guess. libintl is not provided by Android. It might be possible to >> build the full GNU gettext for Android, but it might also be quite painful. > > I am pretty sure that this is possible. Bruno's code is highly portable. > >> Another option I'm considering is using libintl-lite or related fork: > > I don't known. But there is another option. For historicial reasons > GnuPG for Windows uses its own gettext implementaion. It is part of > libgpg-error but only build and used under Windows - should be easy to > modify it to work on all OSes. There are some limitations in the code; > for example the mo files must be utf-8 encoded (which is easy to > achieve) and only the additional Germanic plural is supported. This sounds like a great way to get started with the translations. I tried my hand at getting gettext to build on Android but didn't have any luck. Based on my past experience with gnulib, which gettext depends on, I fear it is a non-trivial task. So I'd like to try using the gettext replacement built into libgpg-error. I tried a bit to disentangle the code from Windows, but didn't get too far. I wanted first to ask what the best approach would be. It seems that there probably should be some internal flag for "use internal gettext", then Windows and Android would set that flag. I don't think Android needs all the stuff in the HAVE_WIN32 section of libgpg-error/src/Makefile.am, for example. Attached is my attempt so far. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: enable_libgpg-error_gettext.patch Type: text/x-patch Size: 1163 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Thu Mar 13 14:20:16 2014 From: wk at gnupg.org (Werner Koch) Date: Thu, 13 Mar 2014 14:20:16 +0100 Subject: gpgme still failing on Android In-Reply-To: <87wqfz5kfq.fsf@vigenere.g10code.de> (Werner Koch's message of "Wed, 12 Mar 2014 19:41:13 +0100") References: <54037697.58.1394647675573.JavaMail.jenkins@debeater> <5320A630.4070307@guardianproject.info> <87wqfz5kfq.fsf@vigenere.g10code.de> Message-ID: <87ha725j73.fsf@vigenere.g10code.de> On Wed, 12 Mar 2014 19:41, wk at gnupg.org said: > Well, I'll do that tomorrow. Run the gpgme configure like this: ./configure --enable-fixed-path="/path/to/GnuPG" or ./configure --enable-fixed-path="/path/to/GnuPG:/alternate/path/to/GnuPG" Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From hans at guardianproject.info Fri Mar 14 01:18:24 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Thu, 13 Mar 2014 20:18:24 -0400 Subject: gnupg-for-java updated for GnuPG 2.x Message-ID: <53224AD0.8090707@guardianproject.info> GPG for Android is based on gnupg-for-java, which was written years ago by Stefan Richter: https://github.com/smartrevolution/gnupg-for-java We have done a lot of work to it, including new features, many bug fixes, and a port from GnuPG 1.4 to GnuPG 2.1. I've finally split out our work from the Android project into its own repository: https://github.com/guardianproject/gnupg-for-java This should run on any platform where Java and JNI are supported, but I have only tested this on Android. Patches welcome! Be aware: it does require GnuPG 2.x, the passphrase handling has been remove since GnuPG 2.x handles passphrases via gpg-agent. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 14 01:19:53 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Thu, 13 Mar 2014 20:19:53 -0400 Subject: gpgme still failing on Android In-Reply-To: <87ha725j73.fsf@vigenere.g10code.de> References: <54037697.58.1394647675573.JavaMail.jenkins@debeater> <5320A630.4070307@guardianproject.info> <87wqfz5kfq.fsf@vigenere.g10code.de> <87ha725j73.fsf@vigenere.g10code.de> Message-ID: <53224B29.3020007@guardianproject.info> On 03/13/2014 09:20 AM, Werner Koch wrote: > On Wed, 12 Mar 2014 19:41, wk at gnupg.org said: > >> Well, I'll do that tomorrow. > > Run the gpgme configure like this: > > ./configure --enable-fixed-path="/path/to/GnuPG" > > or > > ./configure --enable-fixed-path="/path/to/GnuPG:/alternate/path/to/GnuPG" Success! Thanks. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From rjh at sixdemonbag.org Fri Mar 14 06:27:09 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Thu, 13 Mar 2014 22:27:09 -0700 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <53224AD0.8090707@guardianproject.info> References: <53224AD0.8090707@guardianproject.info> Message-ID: <5322932D.3080407@sixdemonbag.org> > We have done a lot of work to it, including new features, many bug fixes, and > a port from GnuPG 1.4 to GnuPG 2.1. I've finally split out our work from the > Android project into its own repository: Unfortunately, this does not build under Ubuntu 13.10 with the latest Oracle JDK. rjh at ubuntu:~/Projects/gnupg-for-java$ javac -version javac 1.7.0_51 rjh at ubuntu:~/Projects/gnupg-for-java$ ant Buildfile: /home/rjh/Projects/gnupg-for-java/build.xml prepare: compile-java: [javac] /home/rjh/Projects/gnupg-for-java/build.xml:15: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds gen-jni-header: prepare: compile-java: [javac] /home/rjh/Projects/gnupg-for-java/build.xml:15: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds generate-jni-headers: [exec] make: Nothing to be done for `header'. gen-jni-library: recompile-c-code: [exec] gcc -g -m64 -Werror -Wall -Wno-deprecated-declarations -fPIC -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -DLARGEFILE_SOURCE=1 -I/usr/lib/jvm/java-7-oracle/include -I/usr/lib/jvm/java-7-oracle/include/linux -c GnuPGData.c [exec] GnuPGData.c: In function ?Java_com_freiheit_gnupg_GnuPGData_gpgmeDataRead?: [exec] GnuPGData.c:135:13: error: variable ?written? set but not used [-Werror=unused-but-set-variable] [exec] ssize_t written; [exec] ^ [exec] cc1: all warnings being treated as errors [exec] make: *** [GnuPGData.o] Error 1 BUILD FAILED /home/rjh/Projects/gnupg-for-java/build.xml:84: The following error occurred while executing this line: /home/rjh/Projects/gnupg-for-java/build.xml:77: exec returned: 2 Total time: 2 seconds From hans at guardianproject.info Fri Mar 14 15:47:57 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 10:47:57 -0400 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <5322932D.3080407@sixdemonbag.org> References: <53224AD0.8090707@guardianproject.info> <5322932D.3080407@sixdemonbag.org> Message-ID: <5323169D.8030107@guardianproject.info> On 03/14/2014 01:27 AM, Robert J. Hansen wrote: >> We have done a lot of work to it, including new features, many bug fixes, and >> a port from GnuPG 1.4 to GnuPG 2.1. I've finally split out our work from the >> Android project into its own repository: > > Unfortunately, this does not build under Ubuntu 13.10 with the latest > Oracle JDK. I pushed a couple fixes, it should build now. It does for me at least on OpenJDK 1.6. I've only used this code on Android so far, so there are probably a couple of setup details that might need to be fixed for it to work on desktop platforms. For example, I haven't used the included test suite before (we have written tests in Android). But it would be good to have that test suite working. That means fixing them for the GnuPG batch mode changes and passphrase handling. Also, it should be used with gpgme 1.4.3 using GnuPG 2.x as the "engine". With GnuPG 2.x, the old style of passphrase handling no longer works. That's why all the passphrase code was removed from gnupg-for-java. With GnuPG 2.x, gpg-agent will handle prompting the user for the passphrase, as well as passphrase caching. If you want to use GnuPG 1.4 with this, then you'll have to figure out how to include that old code in a way that works with the GnuPG 2.x stuff. I recommend using GnuPG 2.x though. That means configuring gpgme to use `gpg2` rather than `gpg`. I think gpgme 1.4.3 defaults to gpg2. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From hans at guardianproject.info Fri Mar 14 16:10:09 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 11:10:09 -0400 Subject: adding TOFU/POP to GnuPG Message-ID: <53231BD1.50902@guardianproject.info> One simple idea has proven quite useful in improving security in other protocols, but remains unimplemented in OpenPGP/GnuPG (as far as I know): Trust On First Use/Persistence of Pseudonym (TOFU/POP). TOFU/POP is how the vast majority of people validate ssh host keys. The idea is to mark a key with some degree of trust on the first use (in ssh, its full trust). Then that creates a pseudonym for the service in question (i.e. the ssh server you ssh'ed to) which is persisted forever. I think that this idea would also be quite useful with OpenPGP. I can see it two ways: * full SSH style TOFU/POP keyring: the process of adding a key to your local keyring marks it as trusted. signatures also mark keys as trusted * or a more GnuPG style: adding a key to the local keyring adds some trust, but not as much as a signature. While this does not provide as strong a verification as an OpenPGP signature on a key, it is also much more likely to actually happen, and does provide a benefit. It also does not prevent users from doing stricter verification at any time. Comments, flames, examples? .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From rjh at sixdemonbag.org Fri Mar 14 17:25:36 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 09:25:36 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53231BD1.50902@guardianproject.info> References: <53231BD1.50902@guardianproject.info> Message-ID: <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> > One simple idea has proven quite useful in improving security in other > protocols, but remains unimplemented in OpenPGP/GnuPG (as far as I know): > Trust On First Use/Persistence of Pseudonym (TOFU/POP). Googling for "TOFU/POP" doesn't turn up anything in the first two pages of Google results that isn't associated with you. My initial reaction is, "until it becomes more widely known, let's not do this -- GnuPG is a place for established technologies, not a place technologies go to become established." > * full SSH style TOFU/POP keyring: the process of adding a key to your local > keyring marks it as trusted. signatures also mark keys as trusted You've just made signatures effectively meaningless. The only way a signature can have meaning is if it's on a certificate that for whatever reason isn't part of your local keyring. > * or a more GnuPG style: adding a key to the local keyring adds some trust, > but not as much as a signature. You're just redefining what "untrusted" means. > While this does not provide as strong a verification as an OpenPGP signature > on a key, it is also much more likely to actually happen, and does provide a > benefit. What benefit? It offers nothing that "trust-model always" doesn't. If you want to always trust certificates in your keyring, then set your gpg.conf accordingly. From dkg at fifthhorseman.net Fri Mar 14 18:00:53 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 13:00:53 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53231BD1.50902@guardianproject.info> References: <53231BD1.50902@guardianproject.info> Message-ID: <532335C5.8030009@fifthhorseman.net> Hi Hans-- On 03/14/2014 11:10 AM, Hans-Christoph Steiner wrote: > One simple idea has proven quite useful in improving security in other > protocols, but remains unimplemented in OpenPGP/GnuPG (as far as I know): > Trust On First Use/Persistence of Pseudonym (TOFU/POP). I have a TOFU/POP workflow already that works with GnuPG, but it's a very clunky one, and the tool itself could facilitate this kind of workflow. i agree with your general goal here, thanks for pushing this. > TOFU/POP is how the > vast majority of people validate ssh host keys. The idea is to mark a key > with some degree of trust on the first use (in ssh, its full trust). Then > that creates a pseudonym for the service in question (i.e. the ssh server you > ssh'ed to) which is persisted forever. It's critically important that we clearly distinguish "trust" from "key validity". In no way should any TOFU/POP workflow encourage the automated setting of trust on any OpenPGP certificate. The acronym "TOFU" is misleading in this context. we're not delegating certifying authority to a given key; we're granting it some flavor of temporary validity based on its persistence. it's also worth distinguishing between keys themselves and certificates (keys + user IDs + signatures that bind them to each other). Note that the thing we care about is some sort of smoother workflow to help users track key+userID validity -- not key validity or full certificate validity (because some certs have multiple User IDs and we may only have evidence of persistent use of some of the associated User IDs). I'm pretty sure you know this, and didn't mean to suggest automated setting of trust or key validity without User ID validity, so i'm going to re-state your proposal points using clearer terminology , and then see where we can go from there. Sorry for the pedantry, but i think it's critical that we get the concepts right before we can figure out what the right proposals are to make things work: > * full SSH style TOFU/POP keyring: the process of adding a key to your local > keyring marks it as trusted. signatures also mark keys as trusted this would be: "the process of adding an OpenPGP certificate to your local keyring makes all user IDs on the certificate automatically valid" > * or a more GnuPG style: adding a key to the local keyring adds some trust, > but not as much as a signature. I think this would be "having an OpenPGP certificate in your local keyring sets all user IDs in that certificate at marginal validity as a baseline" I'm not comfortable with either approach. mere inclusion in the local keyring is insufficient for increased User ID validity for several reasons, not least of which is pretty scary interaction with keyring maintenance. * keyring refresh from keyservers is critical to check for revocations and subkey rollover -- this is routine maintenance * keyring refresh currently allows arbitrary updates by the keyholder, including addition of new User IDs to existing keys * therefore, routine maintenance would allow injection of arbitrary new User IDs which would be considered valid under this scheme. GPG has an unusual role in the OpenPGP ecosystem: it's both a message encrypter/decrypter/signer/validator *and* a keyring/contact/identity manager. It's the role as a keyring/contact/identity manager that we want to flesh out here. I think to do this right, gpg would need to maintain some extra internal state about every combination, and use that state to assign validity to that combination based on TOFU/POP principles. Here's a rough sketch of a simple mechanism, not intended as a final draft, just something concrete for dissection and analysis: * let's call each combination a "Contact" -- note that some keys will belong to multiple Contacts (keys with multiple user IDs), and some user IDs will also belong to multiple Contacts (e.g. users with more than one active key with the same UserID on each key, like those undergoing a key transition). * GnuPG could hold a "persistence" state for each Contact, consisting of a last-seen timestamp T. This state would be private to the keyring and never published or exported. When a key is newly imported, all Contacts on the key would be set to * GnuPG would have a tunable persistence decay parameter D, which describes seconds until discard. * GnuPG needs to be able to receive a signal from the user (presumably sent via an application) that a given Contact has been observed (meaning that the key has been seen in use by the associated User ID). When this happens, GnuPG updates for this Contact. * when GnuPG is asked about the validity of the Contact, it first checks its usual signature chain validity mechanism; if that validity is less than "marginal", it returns "none" if (now-T) ? D, or "marginal" if (now-T) < D. So, for example, enigmail or other MUAs could take advantage of this mechanism the following way: it would do what it normally does in all the current cases, but it would make two changes in its handling of a message that has a body correctly signed by key K and a From: address U, and it knows of a Contact: * if the validity of is already marginal or better, it should signal gnupg that the contact has been observed. (this is the "persistence of presence") * if the validty of is none, then the MUA can display an extra button offering to "accept this contact" (this wording needs help!). if the user clicks the button, enigmail should signal GnuPG that the contact has been observed. Additionally, when the user *sends* a message to a given Contact and encrypts it to that contacts key, enigmail might want to signal GnuPG that this Contact has been observed. Open questions -------------- A) accepting extras vs. ruling out others? TOFU is normally used to rule out or explicitly reject other keys for the same remote peer. but there are legitimate cases where there are two Contacts for a given User ID. should this mechanism refuse to work (e.g. "you already know the key for user ID U, and this isn't it") if it sees a new key for that user? B) persistence synchronization across devices? If the user maintains multiple devices, how should the set of persistence data be stored across devices? C) representing frequency of observation the described scheme above is simple (which is good) but it doesn't have a way to distinguish between a situation where you've exchanged 35 e-mails with a given user, and where you've just gotten an e-mail from someone who you've never talked with before. the only distinction is time of last observation. a more complex scheme could in some way account for activity, and base the thresholds or decay based on that activity (see the TACK mechanism for "learning" a pin for a similar idea). What do you think about the above? --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 14 18:11:18 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 13:11:18 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> Message-ID: <53233836.7070208@guardianproject.info> On 03/14/2014 12:25 PM, Robert J. Hansen wrote: >> One simple idea has proven quite useful in improving security in other >> protocols, but remains unimplemented in OpenPGP/GnuPG (as far as I know): >> Trust On First Use/Persistence of Pseudonym (TOFU/POP). > > Googling for "TOFU/POP" doesn't turn up anything in the first two pages of > Google results that isn't associated with you. My initial reaction is, "until > it becomes more widely known, let's not do this -- GnuPG is a place for > established technologies, not a place technologies go to become established." The term TOFU/POP is not widely used, but that does not mean that the concept is not widely used or deployed. SSH has used this model since the 90s, and SSH has good track record of security. I've never heard another term for describing how SSH verifies host keys, perhaps there is a better one. >> * full SSH style TOFU/POP keyring: the process of adding a key to your local >> keyring marks it as trusted. signatures also mark keys as trusted > > You've just made signatures effectively meaningless. The only way a signature > can have meaning is if it's on a certificate that for whatever reason isn't > part of your local keyring. Yup, that would be one effect of this model, to make it so that signatures on keys don't change the level of trust of keys in the keyring. Signatures could still be used to decide whether to include a key in your keyring. The big benefit here is that it is very simple to represent and use. In my experience, most OpenPGP users do not ever sign other keys anyhow, and managing trust settings is even more rare. >> * or a more GnuPG style: adding a key to the local keyring adds some trust, >> but not as much as a signature. > > You're just redefining what "untrusted" means. > >> While this does not provide as strong a verification as an OpenPGP signature >> on a key, it is also much more likely to actually happen, and does provide a >> benefit. > > What benefit? It offers nothing that "trust-model always" doesn't. If you > want to always trust certificates in your keyring, then set your gpg.conf > accordingly. One key difference would be assuming one key per email address. SSH assumes one host key per hostname (FQDN). That is how SSH can judge whether to prompt you with "unknown key, trust it?" versus "this key does not match this host". This kind of like "trust-model always", but its subtly different. It would have to be represented differently to the user to make sense. For example, the key import process should not just blindly import new keys. Instead, it should walk the user thru the process, i.e. "do you want to trust this key for this email address?" .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From dkg at fifthhorseman.net Fri Mar 14 18:15:25 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 13:15:25 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <532335C5.8030009@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> Message-ID: <5323392D.10802@fifthhorseman.net> On 03/14/2014 01:00 PM, Daniel Kahn Gillmor wrote: > I have a TOFU/POP workflow already that works with GnuPG, but it's a > very clunky one, and the tool itself could facilitate this kind of > workflow. i agree with your general goal here, thanks for pushing this. I should follow up on this more clearly instead of just hinting. here's what i do (roughly): When i get a key that i'm willing to use for future correspondence, but that i haven't verified via any of my usual strong mechanisms that would permit a direct certification, i make a local (non-exportable) OpenPGP certification on the reasonable-looking User IDs associated with that key from an unpublished dedicated "local-certifying" key, which i have marked with marginal ownertrust. These certifications are usually time-limited (--ask-cert-expire), and they include a free-form textual OpenPGP notation (--cert-notation) that i use to record any notes about how and where i've used the key, and why i've decided that the key+UserID is acceptable for use. when the certification expires, the contact becomes unusable again, but i can review my local certifications for signature dates and notes (--list-options show-notations --check-sigs) for hints about when and why i did this, and can pretty easily refresh the persistence. This does *not* prevent two keys from being active for a given User ID at the same time, though. Sorry this isn't outlined more clearly, and that my scripts for managing this use case aren't particularly suited for publication. If anyone has more specific questions about the workflow or suggestions for improvements, i'm all ears. Happy hacking, --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From rjh at sixdemonbag.org Fri Mar 14 18:26:50 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 10:26:50 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53233836.7070208@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> Message-ID: <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> > The term TOFU/POP is not widely used, but that does not mean that the concept > is not widely used or deployed. If the concept is widely used and deployed, then there should be a name by which it can be referred to and looked up. If there isn't a commonly-used name associated with a concept, that tells me the concept is probably ad hoc and in need of codification. That doesn't mean it's a bad idea: it just means there's nowhere I can look up to find detailed information. That's what makes me cautious more than anything else. > Yup, that would be one effect of this model, to make it so that signatures on > keys don't change the level of trust of keys in the keyring. Can't support your idea. You're talking about a radical change to the model presented in RFC4880, and I think GnuPG should stick close to RFC4880. > In my experience, most OpenPGP users do not ever sign other keys > anyhow, and managing trust settings is even more rare. My experience is similar, but that's not a reason to make radical changes that draw GnuPG away from RFC4880. > One key difference would be assuming one key per email address. Unfounded assumption: there are *many, many* users who don't follow this rule. People forget passphrases and generate new certificates with astonishing regularity. People also migrate to new certificates with longer primary signing key lengths without invalidating their previous certificates. Further, people can generate user IDs with whatever email address they want: look at how many user IDs claim to be "president at whitehouse.gov", for instance. I don't think this is a good idea for GnuPG. I think Daniel is right in that there could be a good idea here waiting to be brought out, but I think it would be best served as something similar to Enigmail. GnuPG's mission is to provide conformant, high-quality implementations of the OpenPGP and S/MIME RFCs. Let's not expand that mission to include things unrelated to those RFCs. From wk at gnupg.org Fri Mar 14 18:26:30 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 14 Mar 2014 18:26:30 +0100 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <5323169D.8030107@guardianproject.info> (Hans-Christoph Steiner's message of "Fri, 14 Mar 2014 10:47:57 -0400") References: <53224AD0.8090707@guardianproject.info> <5322932D.3080407@sixdemonbag.org> <5323169D.8030107@guardianproject.info> Message-ID: <87pploy9mg.fsf@vigenere.g10code.de> On Fri, 14 Mar 2014 15:47, hans at guardianproject.info said: > include that old code in a way that works with the GnuPG 2.x stuff. I > recommend using GnuPG 2.x though. That means configuring gpgme to use `gpg2` > rather than `gpg`. I think gpgme 1.4.3 defaults to gpg2. Actually the next gpgme version will use gpg2 by default and only fallback to gpg1 if gpg2 is not installed. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Mar 14 18:25:13 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 14 Mar 2014 18:25:13 +0100 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53231BD1.50902@guardianproject.info> (Hans-Christoph Steiner's message of "Fri, 14 Mar 2014 11:10:09 -0400") References: <53231BD1.50902@guardianproject.info> Message-ID: <87txb0y9om.fsf@vigenere.g10code.de> On Fri, 14 Mar 2014 16:10, hans at guardianproject.info said: > * full SSH style TOFU/POP keyring: the process of adding a key to your local > keyring marks it as trusted. signatures also mark keys as trusted You can't compare ssh's key management to GnuPG's. Indeed ssh works the way you describe it but ssh also uses the only the bare key without any metadata. In our Steed paper [1] we looked in how to implement a TOFC (aka TOFU) system into OpenPGP and S/MIME. In Steed we do not want to talk about key ids or fingerprints but use only the mail address to identify the key. To evaluate whether a MitM has been mounted we will need to keep a list of recent contacts. That requires closer interaction with the MUAs and can't be done by gpg alone. However, to make things easier GnuPG should keep that list of contacts. > * or a more GnuPG style: adding a key to the local keyring adds some trust, > but not as much as a signature. Not a good idea because the keyring has always been used as white pages or as a cache for the keyservers. Redefining it to gpg's known_hosts is not a good idea at all. Further the notion of different trust levels is hard to define and to explain. For that reason we basically use only 3 levels: - Bad - Might be good but needs manual inspection due to expiration, revocation, no computed trust. - Good GPGME uses flags named red, yellow, and green for tehse levels and some MUAs put a such colored frame around the message. With Steed a mail would be rendered yellow on the very first (few) contact(s) and latter either green or red. In case a key has been superseded due to a lost passphrase, the mail would be rendered red but a list of previous contacts will be displayed to help the user to evaluate what might have happened. Unfortunately certain circumstances delayed the development of a prototype but there is still a lot of interest in such a system. >does provide a benefit. It also does not prevent users from doing >stricter verification at any time. Users won't do that. Salam-Shalom, Werner [1] http://g10code.com/steed.html -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Fri Mar 14 18:46:42 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 13:46:42 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> Message-ID: <53234082.5070609@fifthhorseman.net> On 03/14/2014 01:26 PM, Robert J. Hansen wrote: > I don't think this is a good idea for GnuPG. I think Daniel is right in > that there could be a good idea here waiting to be brought out, but I > think it would be best served as something similar to Enigmail. GnuPG's > mission is to provide conformant, high-quality implementations of the > OpenPGP and S/MIME RFCs. Let's not expand that mission to include > things unrelated to those RFCs. GnuPG does not limit itself to the RFCs, particularly when it comes to its role as a keyring/contact manager for OpenPGP. the OpenPGP RFC (4880) does not make any statements about how the network of identity certifications should actually be evaluated other than implying that some sort of validity calculation should be done by the implementation. RFC 4880 mentions a description of "trust signatures" (public indications of ownertrust, which most people don't use) and "trust packets" (private records about which certifiers the user is willing to rely on, which are by definition implementation-specific) and has a vague one-off reference to "validity calculations" in the revocation section -- that's it. But the feature of deciding which keys do actually belong to which users ("validity calculations") is a critical task performed by gpg, and implementations like enigmail and other MUAs rely on GnuPG to perform this task correctly. Implementing TOFU/POP in enigmail itself instead of pushing the information into GnuPG would mean that other users of GnuPG (who already rely on GnuPG for existing validity calculations) wouldn't get the benefit of the decisions the user already made in enigmail. That would be a mistake. If GnuPG wasn't already in the business of doing these validity calculations, there might be more merit in Robert's argument, but in practice, this is one of the core features of the tool. So any consideration about extending or modifying user ID validity calculations is *definitely* in-scope for GnuPG. --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 14 18:54:08 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 13:54:08 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> Message-ID: <53234240.3000506@guardianproject.info> On 03/14/2014 01:26 PM, Robert J. Hansen wrote: >> The term TOFU/POP is not widely used, but that does not mean that the concept >> is not widely used or deployed. > > If the concept is widely used and deployed, then there should be a name by > which it can be referred to and looked up. If there isn't a commonly-used > name associated with a concept, that tells me the concept is probably ad hoc > and in need of codification. That doesn't mean it's a bad idea: it just means > there's nowhere I can look up to find detailed information. That's what makes > me cautious more than anything else. > >> Yup, that would be one effect of this model, to make it so that signatures on >> keys don't change the level of trust of keys in the keyring. > > Can't support your idea. You're talking about a radical change to the model > presented in RFC4880, and I think GnuPG should stick close to RFC4880. > >> In my experience, most OpenPGP users do not ever sign other keys anyhow, and >> managing trust settings is even more rare. > > My experience is similar, but that's not a reason to make radical changes that > draw GnuPG away from RFC4880. Do you use SSH? That is the key verification model I am talking about. I think you're missing the point if you are calling the SSH model ad hoc and in need of codification. Its been the same for almost 20 years. Its widely deployed, used, and understood. But perhaps its not widely documented, probably because its so simple it doesn't need to be. OpenPGP is so over-complicated, and seemingly only getting more so. And that is making it less and less relevant. Who cares about the standards if hardly anyone actually uses them?! Hundreds of millions of people use email, there are only about 55,000 people in the OpenPGP strong set. That is the sad state of OpenPGP. >> One key difference would be assuming one key per email address. > > Unfounded assumption: there are *many, many* users who don't follow this > rule. People forget passphrases and generate new certificates with > astonishing regularity. People also migrate to new certificates with longer > primary signing key lengths without invalidating their previous certificates. > Further, people can generate user IDs with whatever email address they want: > look at how many user IDs claim to be "president at whitehouse.gov", for instance. The user would be responsible for maintaining which key is assigned to a given email address in their own keyring. The user would always manually approve all additions and changes to keyId+email mappings in their local keyring. That's the very basis of TOFU/POP. Ideally there would only be one key per email address, but a workaround should be possible for people who insist on multiples. > I don't think this is a good idea for GnuPG. I think Daniel is right in that > there could be a good idea here waiting to be brought out, but I think it > would be best served as something similar to Enigmail. GnuPG's mission is to > provide conformant, high-quality implementations of the OpenPGP and S/MIME > RFCs. Let's not expand that mission to include things unrelated to those RFCs. GnuPG has configurable trust models, I think this can be implemented as such a trust model. Then all of the programs (e.g. Enigmail) that use gnupg as its engine can choose to use it. People who want all the complications of the full OpenPGP standard can still use that. I'm not talking about changing the defaults, but just giving another option. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From hans at guardianproject.info Fri Mar 14 19:00:04 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 14:00:04 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <532335C5.8030009@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> Message-ID: <532343A4.2020501@guardianproject.info> On 03/14/2014 01:00 PM, Daniel Kahn Gillmor wrote: > Hi Hans-- > > On 03/14/2014 11:10 AM, Hans-Christoph Steiner wrote: > >> One simple idea has proven quite useful in improving security in other >> protocols, but remains unimplemented in OpenPGP/GnuPG (as far as I know): >> Trust On First Use/Persistence of Pseudonym (TOFU/POP). > > I have a TOFU/POP workflow already that works with GnuPG, but it's a > very clunky one, and the tool itself could facilitate this kind of > workflow. i agree with your general goal here, thanks for pushing this. > >> TOFU/POP is how the >> vast majority of people validate ssh host keys. The idea is to mark a key >> with some degree of trust on the first use (in ssh, its full trust). Then >> that creates a pseudonym for the service in question (i.e. the ssh server you >> ssh'ed to) which is persisted forever. > > It's critically important that we clearly distinguish "trust" from "key > validity". In no way should any TOFU/POP workflow encourage the > automated setting of trust on any OpenPGP certificate. The acronym > "TOFU" is misleading in this context. we're not delegating certifying > authority to a given key; we're granting it some flavor of temporary > validity based on its persistence. > > it's also worth distinguishing between keys themselves and certificates > (keys + user IDs + signatures that bind them to each other). Note that > the thing we care about is some sort of smoother workflow to help users > track key+userID validity -- not key validity or full certificate > validity (because some certs have multiple User IDs and we may only have > evidence of persistent use of some of the associated User IDs). > > I'm pretty sure you know this, and didn't mean to suggest automated > setting of trust or key validity without User ID validity, so i'm going > to re-state your proposal points using clearer terminology , and then > see where we can go from there. Sorry for the pedantry, but i think > it's critical that we get the concepts right before we can figure out > what the right proposals are to make things work: > >> * full SSH style TOFU/POP keyring: the process of adding a key to your local >> keyring marks it as trusted. signatures also mark keys as trusted > > this would be: "the process of adding an OpenPGP certificate to your > local keyring makes all user IDs on the certificate automatically valid" > >> * or a more GnuPG style: adding a key to the local keyring adds some trust, >> but not as much as a signature. > > I think this would be "having an OpenPGP certificate in your local > keyring sets all user IDs in that certificate at marginal validity as a > baseline" > > I'm not comfortable with either approach. mere inclusion in the local > keyring is insufficient for increased User ID validity for several > reasons, not least of which is pretty scary interaction with keyring > maintenance. > > * keyring refresh from keyservers is critical to check for revocations > and subkey rollover -- this is routine maintenance > * keyring refresh currently allows arbitrary updates by the keyholder, > including addition of new User IDs to existing keys > * therefore, routine maintenance would allow injection of arbitrary new > User IDs which would be considered valid under this scheme. > > > GPG has an unusual role in the OpenPGP ecosystem: it's both a message > encrypter/decrypter/signer/validator *and* a keyring/contact/identity > manager. > > It's the role as a keyring/contact/identity manager that we want to > flesh out here. I think to do this right, gpg would need to maintain > some extra internal state about every combination, and use > that state to assign validity to that combination based on TOFU/POP > principles. > > Here's a rough sketch of a simple mechanism, not intended as a final > draft, just something concrete for dissection and analysis: > > * let's call each combination a "Contact" -- note that > some keys will belong to multiple Contacts (keys with multiple user > IDs), and some user IDs will also belong to multiple Contacts (e.g. > users with more than one active key with the same UserID on each key, > like those undergoing a key transition). > > * GnuPG could hold a "persistence" state for each Contact, consisting > of a last-seen timestamp T. This state would be private to the keyring > and never published or exported. When a key is newly imported, all > Contacts on the key would be set to > > * GnuPG would have a tunable persistence decay parameter D, which > describes seconds until discard. > > * GnuPG needs to be able to receive a signal from the user (presumably > sent via an application) that a given Contact has been observed (meaning > that the key has been seen in use by the associated User ID). When this > happens, GnuPG updates for this Contact. > > * when GnuPG is asked about the validity of the Contact, it first > checks its usual signature chain validity mechanism; if that validity is > less than "marginal", it returns "none" if (now-T) ? D, or "marginal" if > (now-T) < D. > > So, for example, enigmail or other MUAs could take advantage of this > mechanism the following way: it would do what it normally does in all > the current cases, but it would make two changes in its handling of a > message that has a body correctly signed by key K and a From: address U, > and it knows of a Contact: > > * if the validity of is already marginal or better, it should > signal gnupg that the contact has been observed. (this is the > "persistence of presence") > > * if the validty of is none, then the MUA can display an extra > button offering to "accept this contact" (this wording needs help!). if > the user clicks the button, enigmail should signal GnuPG that the > contact has been observed. > > Additionally, when the user *sends* a message to a given Contact and > encrypts it to that contacts key, enigmail might want to signal GnuPG > that this Contact has been observed. > > > Open questions > -------------- > > A) accepting extras vs. ruling out others? > > TOFU is normally used to rule out or explicitly reject other keys for > the same remote peer. but there are legitimate cases where there are > two Contacts for a given User ID. should this mechanism refuse to work > (e.g. "you already know the key for user ID U, and this isn't it") if it > sees a new key for that user? > > > B) persistence synchronization across devices? > > If the user maintains multiple devices, how should the set of > persistence data be stored across devices? > > > C) representing frequency of observation > > the described scheme above is simple (which is good) but it doesn't > have a way to distinguish between a situation where you've exchanged 35 > e-mails with a given user, and where you've just gotten an e-mail from > someone who you've never talked with before. the only distinction is > time of last observation. a more complex scheme could in some way > account for activity, and base the thresholds or decay based on that > activity (see the TACK mechanism for "learning" a pin for a similar idea). > > What do you think about the above? > > --dkg My goal in bringing up TOFU/POP is to simplify things, OpenPGP is already way over-complicated so adding more fine grained control over new aspects would only make things worse for the large majority. The goal is to make a small subset of OpenPGP that is usable by anyone who uses email. Simplicity also makes security analysis a lot easier. Yes, this would reduce the flexibility but OpenPGP is far too complicated for the vast majority of users to understand. Its taken me years of using it to feel I have some grasp, and I still feel lost it in. So I'm talking about a mode that is designed for anyone who can use email. I am not talking about changing the existing, standard OpenPGP model, so those who want all that complexity and flexibility can choose that route. Key to this idea is that the user would always manually approve all additions and changes to keyId+email mappings in their local keyring. That's the very basis of TOFU/POP. Ideally there would only be one key per email address, but workaround should be possible for people who insist on multiples, for the sake of compatibility. But I think the interface should strongly encourage a one-to-one mapping of key<-->email. In the pure TOFU/POP model, keyservers would only used for updates about revokation, expiry, and subkeys. As for my language, sorry I don't speak proper OpenPGP/IETF speak. I've tried to learn it, but it has so many arcane details that it does not stick in my brain. So I'll stick to standard English and try to make myself understood. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From rjh at sixdemonbag.org Fri Mar 14 19:31:35 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 11:31:35 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53234240.3000506@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> <53234240.3000506@guardianproject.info> Message-ID: <20140314113135.Horde.Q9r4WY1HQkY7y5tkpdNraw1@mail.sixdemonbag.org> > Do you use SSH? Yep. > That is the key verification model I am talking about. I know. > But perhaps its not widely documented, > probably because its so simple it doesn't need to be. There is nothing in engineering so simple it doesn't need to be documented. If you look at a stretch of railroad track, for instance, you'll find each length of track is stamped with an ID number. This ID number corresponds to a specific batch of steel. If a length of track breaks, the manufacturer is notified and in short order every length of track everywhere that came out of that batch of steel gets inspected for manufacturing defects. We're talking about a simple piece of steel. No moving parts. All it has to do is sit there and be tough, and yet we still document and track it -- because that's engineering. Compared to that, SSH key exchange and management is orders of magnitude more complicated. That it isn't documented anywhere even after 20 years does not fill me with warm fuzzies. > OpenPGP is so over-complicated, and seemingly only getting more so. And that > is making it less and less relevant. Who cares about the standards if hardly > anyone actually uses them?! This is an argument for abandoning OpenPGP and building something better. It is not an argument for expanding GnuPG's scope. > The user would be responsible for maintaining which key is assigned > to a given... Users tend to be highly irresponsible. > email address in their own keyring. The user would always manually > approve all additions and changes to keyId+email mappings in their > local keyring. Breaks the keyserver network, sort-of kind-of, as DKG has already said. > GnuPG has configurable trust models, I think this can be implemented > as such a trust model. GnuPG implements the OpenPGP trust model. If you can get this introduced to the OpenPGP standard then I'll be all for introducing it to GnuPG. Until then, I don't believe it belongs here. It should go into the supporting software ecosystem. From rjh at sixdemonbag.org Fri Mar 14 19:38:18 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 11:38:18 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53234082.5070609@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> <53234082.5070609@fifthhorseman.net> Message-ID: <20140314113818.Horde.cGXGXXnFyBo2gPKSRYfwRg3@mail.sixdemonbag.org> Quoting Daniel Kahn Gillmor : > GnuPG does not limit itself to the RFCs, particularly when it comes to > its role as a keyring/contact manager for OpenPGP. Correct, but this is for historical reasons. When GnuPG was in a pre-1.0 state, Werner made the (entirely reasonable) decision that GnuPG should as far as possible be a drop-in replacement for PGP. That meant emulating all of PGP's feature set, including the key management that had organically grown in the PGP community since 1992. There is no historical reason to support TOFU/POP. We're talking about adding significant complexity and a nontrivial amount of code for something which at present has minimal community demand. If a different trust mechanism than the WoT existed in 1992 and had become GnuPG's preferred system today, and someone came on-list saying "hey, I have an idea: let's do the WoT," I'd also say, "no, let's not: this is not within the remit of OpenPGP, and I think GnuPG is strongest when it stays close to the RFCs." > If GnuPG wasn't already in the business of doing these validity > calculations, there might be more merit in Robert's argument, but in > practice, this is one of the core features of the tool. So any > consideration about extending or modifying user ID validity calculations > is *definitely* in-scope for GnuPG. I emphatically disagree. Just because we have inherited one set of historical baggage is not a sufficient reason to believe we should introduce new things in that same vein. From wk at gnupg.org Fri Mar 14 19:38:20 2014 From: wk at gnupg.org (Werner Koch) Date: Fri, 14 Mar 2014 19:38:20 +0100 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53234240.3000506@guardianproject.info> (Hans-Christoph Steiner's message of "Fri, 14 Mar 2014 13:54:08 -0400") References: <53231BD1.50902@guardianproject.info> <20140314092536.Horde.Axwgsxvn69poFnIynELUHQ1@mail.sixdemonbag.org> <53233836.7070208@guardianproject.info> <20140314102650.Horde.-PmP7ALLkRNb5mFTes7kag2@mail.sixdemonbag.org> <53234240.3000506@guardianproject.info> Message-ID: <87bnx8y6ar.fsf@vigenere.g10code.de> On Fri, 14 Mar 2014 18:54, hans at guardianproject.info said: > OpenPGP is so over-complicated, and seemingly only getting more so. And that Compared to CMS OpenPGP is a quite lean and stable protocol. Changes to the protocol are very rare: We only have a few RFCs adding new cipher or public key algorithms. The thing is that OpenPGP provides a lot of _optional features_ which can be used to model any kind of PKI. Most of them are not in real use and for GnuPG I try to limit the options presented to users. Still there are too many of them and I agree that the interaction of the user with the software should be limited to the bare needs. We experts can still to play or use with almost everything from the standard and even exchange encrypted messages with all users. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Fri Mar 14 20:07:09 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 15:07:09 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <532343A4.2020501@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> Message-ID: <5323535D.9060901@fifthhorseman.net> On 03/14/2014 02:00 PM, Hans-Christoph Steiner wrote: > My goal in bringing up TOFU/POP is to simplify things, OpenPGP is already way > over-complicated so adding more fine grained control over new aspects would > only make things worse for the large majority. The goal is to make a small > subset of OpenPGP that is usable by anyone who uses email. Simplicity also > makes security analysis a lot easier. You may not want OpenPGP for this, then. OpenPGP clients have to cope with data that they see that covers the whole spec, even if they want to present a simplified interface for users. But if you want interoperability with the installed set of OpenPGP users, as small as that group may be, this is the standard to use. > Yes, this would reduce the flexibility but OpenPGP is far too complicated for > the vast majority of users to understand. Its taken me years of using it to > feel I have some grasp, and I still feel lost it in. So I'm talking about a > mode that is designed for anyone who can use email. I am not talking about > changing the existing, standard OpenPGP model, so those who want all that > complexity and flexibility can choose that route. you'll note that the only user-facing parts of my proposal were a single button added to the MUA, and a possible configurable knob for GnuPG itself (the decay parameter D, which we can presumably choose a reasonable default for so users won't see it). I'm with you on not exposing extra complexity to the users; there is already too much exposed. > Key to this idea is that the user would always manually approve all additions > and changes to keyId+email mappings in their local keyring. That's the very > basis of TOFU/POP. Ideally there would only be one key per email address, but > workaround should be possible for people who insist on multiples, for the sake > of compatibility. But I think the interface should strongly encourage a > one-to-one mapping of key<-->email. This also seems quite possible, within the constraints i mentioned above. you'd want to modify the decision about when to present the button to the user, probably. > In the pure TOFU/POP model, keyservers would only used for updates about > revokation, expiry, and subkeys. how does new key discovery work if keyservers are not used in this context? what about new User ID discovery on existing keys? > As for my language, sorry I don't speak proper OpenPGP/IETF speak. I've tried > to learn it, but it has so many arcane details that it does not stick in my > brain. So I'll stick to standard English and try to make myself understood. Unfortunately, there is no standard English for some of these concepts, and in other cases, the standard English refers to multiple things that we need to distinguish between as implementers. so it's critical to use unambiguous terminology if we want to nail down what we're actually hoping to do. Please try. "trust" in the OpenPGP world (and in the X.509 world) is an indication that the user is willing to rely on certifications made by the key in question. "validity" is whether the key and the user ID should go together. "this key+UserID is valid" is the same as "we should expect the person identified by this User ID to use this key". --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 14 21:28:01 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 16:28:01 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <5323535D.9060901@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> Message-ID: <53236651.5010103@guardianproject.info> On 03/14/2014 03:07 PM, Daniel Kahn Gillmor wrote: > On 03/14/2014 02:00 PM, Hans-Christoph Steiner wrote: > >> My goal in bringing up TOFU/POP is to simplify things, OpenPGP is already way >> over-complicated so adding more fine grained control over new aspects would >> only make things worse for the large majority. The goal is to make a small >> subset of OpenPGP that is usable by anyone who uses email. Simplicity also >> makes security analysis a lot easier. > > You may not want OpenPGP for this, then. OpenPGP clients have to cope > with data that they see that covers the whole spec, even if they want to > present a simplified interface for users. > > But if you want interoperability with the installed set of OpenPGP > users, as small as that group may be, this is the standard to use. Sure, it doesn't need to be OpenPGP. But GnuPG seemed like a natural place to try this out since all of the pieces are there, and its widely deployed and tested. >> Yes, this would reduce the flexibility but OpenPGP is far too complicated for >> the vast majority of users to understand. Its taken me years of using it to >> feel I have some grasp, and I still feel lost it in. So I'm talking about a >> mode that is designed for anyone who can use email. I am not talking about >> changing the existing, standard OpenPGP model, so those who want all that >> complexity and flexibility can choose that route. > > you'll note that the only user-facing parts of my proposal were a single > button added to the MUA, and a possible configurable knob for GnuPG > itself (the decay parameter D, which we can presumably choose a > reasonable default for so users won't see it). > > I'm with you on not exposing extra complexity to the users; there is > already too much exposed. I also worry that complicated systems can also be gamed more easily without people noticing. >> Key to this idea is that the user would always manually approve all additions >> and changes to keyId+email mappings in their local keyring. That's the very >> basis of TOFU/POP. Ideally there would only be one key per email address, but >> workaround should be possible for people who insist on multiples, for the sake >> of compatibility. But I think the interface should strongly encourage a >> one-to-one mapping of key<-->email. > > This also seems quite possible, within the constraints i mentioned > above. you'd want to modify the decision about when to present the > button to the user, probably. > >> In the pure TOFU/POP model, keyservers would only used for updates about >> revokation, expiry, and subkeys. > > how does new key discovery work if keyservers are not used in this > context? what about new User ID discovery on existing keys? Yeah, keyservers would be used for getting new keys too. Getting new IDs from keyservers would be fine too, as long as the interface asks the user to accept the new key+ID mapping. Having key signatures on the keyservers should be optional, not default. I think a nice, simple idea to explore here is "secure introductions". Basically, if you send multiple people an encrypted email, you include a signature marking the key+email combos as trusted. Then if the recipients trust your key+email, their program will automatically import any new key+email combos (i.e. download and mark them as trusted). The whole public key could be contained in the secure introduction. >> As for my language, sorry I don't speak proper OpenPGP/IETF speak. I've tried >> to learn it, but it has so many arcane details that it does not stick in my >> brain. So I'll stick to standard English and try to make myself understood. > > Unfortunately, there is no standard English for some of these concepts, > and in other cases, the standard English refers to multiple things that > we need to distinguish between as implementers. so it's critical to > use unambiguous terminology if we want to nail down what we're actually > hoping to do. Please try. > > "trust" in the OpenPGP world (and in the X.509 world) is an indication > that the user is willing to rely on certifications made by the key in > question. "validity" is whether the key and the user ID should go > together. "this key+UserID is valid" is the same as "we should expect > the person identified by this User ID to use this key". > > --dkg If we are implementing trust models that we cannot explain in plain English, how then do you expect to represent them to users who have no idea about the implementations? .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From dkg at fifthhorseman.net Fri Mar 14 21:48:30 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 16:48:30 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53236651.5010103@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> Message-ID: <53236B1E.1030001@fifthhorseman.net> On 03/14/2014 04:28 PM, Hans-Christoph Steiner wrote: > If we are implementing trust models that we cannot explain in plain English, > how then do you expect to represent them to users who have no idea about the > implementations? Hard engineering and design work. I'm not saying it's easy, or that our community has a history of getting it right in the past, but we have to do it. People who design and build complex technology need to have specific terms for the components and subsystems they work on, and to use those terms to communicate clearly with each other even when the end user is ultimately presented with something that hides much of that complexity. If you tried to build a blender with no other vocabulary than "mix" and "chop" and "puree", you wouldn't end up with anything particularly usable in the kitchen (and it would probably be dangerous!), even though most people just see those buttons and have no idea what's going on inside their blender or what it took to design and build it. We're designing and building blenders here. We need to know about tensile strength and mechanical gearing and rotational velocity and voltage allowances and fluid dynamics and spatter patterns and user interface conventions and failure modes and load testing and viscosity and a lot of other details that go deeper than "mix" and "chop" and "puree". Regards, --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 14 22:03:56 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 17:03:56 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <87txb0y9om.fsf@vigenere.g10code.de> References: <53231BD1.50902@guardianproject.info> <87txb0y9om.fsf@vigenere.g10code.de> Message-ID: <53236EBC.3080609@guardianproject.info> On 03/14/2014 01:25 PM, Werner Koch wrote: > On Fri, 14 Mar 2014 16:10, hans at guardianproject.info said: > >> * full SSH style TOFU/POP keyring: the process of adding a key to your local >> keyring marks it as trusted. signatures also mark keys as trusted > > You can't compare ssh's key management to GnuPG's. Indeed ssh works the > way you describe it but ssh also uses the only the bare key without any > metadata. > > In our Steed paper [1] we looked in how to implement a TOFC (aka TOFU) > system into OpenPGP and S/MIME. In Steed we do not want to talk about > key ids or fingerprints but use only the mail address to identify the > key. To evaluate whether a MitM has been mounted we will need to keep a > list of recent contacts. That requires closer interaction with the MUAs > and can't be done by gpg alone. However, to make things easier GnuPG > should keep that list of contacts. I think that STEED definitely represents an improvement and has a solid ideas in it. Requiring involvement with MUAs makes it a lot harder to get adoption. >> * or a more GnuPG style: adding a key to the local keyring adds some trust, >> but not as much as a signature. > > Not a good idea because the keyring has always been used as white pages > or as a cache for the keyservers. Redefining it to gpg's known_hosts is > not a good idea at all. I propose using this trust model for people starting new, or for people willing to switch to it. It would not be compatible with standard OpenPGP habits. > Further the notion of different trust levels is hard to define and to > explain. For that reason we basically use only 3 levels: > > - Bad > - Might be good but needs manual inspection due to expiration, > revocation, no computed trust. > - Good > > GPGME uses flags named red, yellow, and green for tehse levels and some > MUAs put a such colored frame around the message. That makes sense. This is what OTR clients generally do, and it seems workable. But I think most OTR users are always chatting in "might be good" mode. So "might be good" mode might be not all that useful. I think expiration for email is not that useful. Just revokation should handle that all. > With Steed a mail would be rendered yellow on the very first (few) > contact(s) and latter either green or red. In case a key has been > superseded due to a lost passphrase, the mail would be rendered red but > a list of previous contacts will be displayed to help the user to > evaluate what might have happened. Unfortunately certain circumstances > delayed the development of a prototype but there is still a lot of > interest in such a system. > > >> does provide a benefit. It also does not prevent users from doing >> stricter verification at any time. > > Users won't do that. I agree, a good system should not rely on it, but it should provide the opportunity for the at-risk users who will actually do that. We work with a lot of people who actually verify PGP and OTR fingerprints, and we are involved in trainings to teach at-risk people how to do that. >> OpenPGP is so over-complicated, and seemingly only getting more so. And that > > Compared to CMS OpenPGP is a quite lean and stable protocol. Changes to > the protocol are very rare: We only have a few RFCs adding new cipher or > public key algorithms. Oh yes, there are definitely far worse culprits. X.509/TLS comes to mind as well. > The thing is that OpenPGP provides a lot of _optional features_ which > can be used to model any kind of PKI. Most of them are not in real use > and for GnuPG I try to limit the options presented to users. Still > there are too many of them and I agree that the interaction of the user > with the software should be limited to the bare needs. We experts can > still to play or use with almost everything from the standard and even > exchange encrypted messages with all users. I view GnuPG has a toolbox of trusted crypto components. That is why I think it is a good system to base such a system on .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From dkg at fifthhorseman.net Fri Mar 14 22:10:56 2014 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Fri, 14 Mar 2014 17:10:56 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53236651.5010103@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> Message-ID: <53237060.3050705@fifthhorseman.net> On 03/14/2014 04:28 PM, Hans-Christoph Steiner wrote: > Sure, it doesn't need to be OpenPGP. But GnuPG seemed like a natural place to > try this out since all of the pieces are there, and its widely deployed and > tested. if you don't care about interoperability with the existing OpenPGP userbase, i think using OpenPGP gets you stuck in a maze of compatibility and complexity concerns. > I also worry that complicated systems can also be gamed more easily without > people noticing. This is definitely true. > I think a nice, simple idea to explore here is "secure introductions". > Basically, if you send multiple people an encrypted email, you include a > signature marking the key+email combos as trusted. Then if the recipients > trust your key+email, their program will automatically import any new > key+email combos (i.e. download and mark them as trusted). The whole public > key could be contained in the secure introduction. again, I think you're conflating belief in key+userid validity with trust here, and that conflation is likely to violate people's assumptions and preferences. humans are actually pretty good at understanding the difference between "do you know who this person is?" and "is this person someone you can rely on?" -- the difference is significant. how many hops into such a chain should these "secure introductions" propagate automatically? The other angle that needs consideration for a TOFU/POP workflow is what sort of experience people should have when things fail. This is the achilles heel of TOFU/POP, and despite it coming up rarely in experience, it actually matters tremendously to the security of the entire scheme. What do you think a user should see when a new key appears for one of their contacts, for whom they already have a key? is there a way that the user can distinguish between legitimate key rollover and an impersonation attack? What signals do they have to detect and deal with the situation that are better than "click OK to get on with your work?" --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1010 bytes Desc: OpenPGP digital signature URL: From rjh at sixdemonbag.org Fri Mar 14 22:36:31 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 14:36:31 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53236B1E.1030001@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> <53236B1E.1030001@fifthhorseman.net> Message-ID: <20140314143631.Horde.Pw7UV4LZtLudW81CWxPoKQ3@mail.sixdemonbag.org> > Hard engineering and design work. Mark this day: for once I wholly agree with DKG. :) Well-said and well-explained. From rjh at sixdemonbag.org Fri Mar 14 22:54:43 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Fri, 14 Mar 2014 14:54:43 -0700 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53237060.3050705@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> <53237060.3050705@fifthhorseman.net> Message-ID: <20140314145443.Horde.wom1NstFARc1sJyk9t-CuQ1@mail.sixdemonbag.org> So far in this thread I've said an awful lot of "no, I don't think this is appropriate for GnuPG." I don't like saying that: I'd much rather find ways to do cool things rather than find reasons not to even try. I think there's a place for this sort of thing, and it's worth looking at how other people have already done similar things. We might be able to learn from their experiences. What seems most on-point to me is PGP's experience using an email proxy. Rather than ship with plugins for every imaginable email client, PGP set up an invisible mail proxy to do opportunistic signing and encryption. It would snoop on your email client's connection with the server and, if an outbound email message was addressed to someone for whom PGP had a valid certificate, would encrypt (and optionally sign) it. The goal here was to make email encryption completely invisible to the end-user. I personally found the proxy to be touchy, but in the main it worked well. (I don't know much about GnuPG's STEED project: it's possible it works in much the same way.) A similar thing could be used to achieve many of the goals of TOFU/POP without adding any complexity to GnuPG itself. The email proxy could be a completely separate application with its own custom logic to handle whatever trust calculations were needed, and if necessary it could call out to GnuPG to adjust the local keyring. There is a *lot* of work to be done with solidifying the idea behind a TOFU/POP-based scheme and figuring out how to make it interact nicely with the rest of the OpenPGP ecosystem. But I believe that it can be done, and that it can be done outside of GnuPG. That's hardly without precedent, either: for instance, GnuPG's keyserver support is provided by external applications -- TOFU/POP support via a mail proxy could be an external application as well. A word of warning, though: once you set up automated mail proxies that do cryptographic operations, you wind up with things like seeing PGP-signed spam mails. One in four desktop PCs is compromised by malware nowadays, and many of them serve as spam botnets -- that, combined with an email proxy that does automatic signing, and a long passphrase timeout, gets really bad really fast. In a similar vein, let's keep in mind that our solution *will* get hijacked at some point, and think of how to minimize the risk. From ekleog at gmail.com Fri Mar 14 22:43:43 2014 From: ekleog at gmail.com (Leo Gaspard) Date: Fri, 14 Mar 2014 22:43:43 +0100 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53236EBC.3080609@guardianproject.info> References: <53231BD1.50902@guardianproject.info> <87txb0y9om.fsf@vigenere.g10code.de> <53236EBC.3080609@guardianproject.info> Message-ID: <20140314214343.GC26060@leortable> On Fri, Mar 14, 2014 at 05:03:56PM -0400, Hans-Christoph Steiner wrote: > I view GnuPG has a toolbox of trusted crypto components. That is why I think > it is a good system to base such a system on (Assuming "has" was meant to be "as".) Why not use libgcrypt, then? AFAIK, This one is actually meant to be a toolbox of trusted crypto components. From hans at guardianproject.info Sat Mar 15 00:08:38 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 19:08:38 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314214343.GC26060@leortable> References: <53231BD1.50902@guardianproject.info> <87txb0y9om.fsf@vigenere.g10code.de> <53236EBC.3080609@guardianproject.info> <20140314214343.GC26060@leortable> Message-ID: <53238BF6.8010709@guardianproject.info> On 03/14/2014 05:43 PM, Leo Gaspard wrote: > On Fri, Mar 14, 2014 at 05:03:56PM -0400, Hans-Christoph Steiner wrote: >> I view GnuPG has a toolbox of trusted crypto components. That is why I think >> it is a good system to base such a system on > > (Assuming "has" was meant to be "as".) > > Why not use libgcrypt, then? AFAIK, This one is actually meant to be a toolbox > of trusted crypto components. Not all relevant crypto-related components are in libgcrypt. Key management, for example. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From hans at guardianproject.info Sat Mar 15 00:39:43 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 14 Mar 2014 19:39:43 -0400 Subject: adding TOFU/POP to GnuPG In-Reply-To: <53237060.3050705@fifthhorseman.net> References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> <53237060.3050705@fifthhorseman.net> Message-ID: <5323933F.9000408@guardianproject.info> On 03/14/2014 05:10 PM, Daniel Kahn Gillmor wrote: > On 03/14/2014 04:28 PM, Hans-Christoph Steiner wrote: >> Sure, it doesn't need to be OpenPGP. But GnuPG seemed like a natural place to >> try this out since all of the pieces are there, and its widely deployed and >> tested. > > if you don't care about interoperability with the existing OpenPGP > userbase, i think using OpenPGP gets you stuck in a maze of > compatibility and complexity concerns. > >> I also worry that complicated systems can also be gamed more easily without >> people noticing. > > This is definitely true. > >> I think a nice, simple idea to explore here is "secure introductions". >> Basically, if you send multiple people an encrypted email, you include a >> signature marking the key+email combos as trusted. Then if the recipients >> trust your key+email, their program will automatically import any new >> key+email combos (i.e. download and mark them as trusted). The whole public >> key could be contained in the secure introduction. > > again, I think you're conflating belief in key+userid validity with > trust here, and that conflation is likely to violate people's > assumptions and preferences. > > humans are actually pretty good at understanding the difference between > "do you know who this person is?" and "is this person someone you can > rely on?" -- the difference is significant. > > how many hops into such a chain should these "secure introductions" > propagate automatically? > > The other angle that needs consideration for a TOFU/POP workflow is what > sort of experience people should have when things fail. This is the > achilles heel of TOFU/POP, and despite it coming up rarely in > experience, it actually matters tremendously to the security of the > entire scheme. > > What do you think a user should see when a new key appears for one of > their contacts, for whom they already have a key? is there a way that > the user can distinguish between legitimate key rollover and an > impersonation attack? What signals do they have to detect and deal with > the situation that are better than "click OK to get on with your work?" Humans are very good at making value and trust judgments, computers are terrible at it even with help from humans. So we should leave that to humans to distinguish and not attempt to make computers do it. Crypto protocols should focus on the parts that computers are good at, and the software that is based on those protocols must focus on representing the true state of affairs as understandable as possible. What needs exploring are other approaches. For example, thinking more like a biologist and basing decisions on lots and lots of observations. Computers are good at observing and checking keys, so let's give them lots of opportunity to do so. The hard part here is then representing decisions that the user must make, and guiding them through concrete actions. That must happen in any existing, functional crypto system, be it WoT, TOFU/POP, CAs, whatever. There are points where the user must make a decision. Usable crypto systems are not mathematical proofs: there will always be messy things that the user will have to think about them. The realistic goal is minimizing them and making them understandable. There are lots of details here to be resolved of course, and I don't personally have time now to really work on them. I am just happy to spur discussion here. As for blenders, I regularly am involved in crypto design processes and work to avoid jargon. I think it is not only possible, but indeed leads to better design. And I think its generally a waste of time to debate metaphors. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Mon Mar 17 11:37:20 2014 From: wk at gnupg.org (Werner Koch) Date: Mon, 17 Mar 2014 11:37:20 +0100 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314214343.GC26060@leortable> (Leo Gaspard's message of "Fri, 14 Mar 2014 22:43:43 +0100") References: <53231BD1.50902@guardianproject.info> <87txb0y9om.fsf@vigenere.g10code.de> <53236EBC.3080609@guardianproject.info> <20140314214343.GC26060@leortable> Message-ID: <87ha6xun4v.fsf@vigenere.g10code.de> On Fri, 14 Mar 2014 22:43, ekleog at gmail.com said: > Why not use libgcrypt, then? AFAIK, This one is actually meant to be a toolbox Libgcrypt does not implement protocols but provides low-level building blocks. Look at the SLOC (count source lines of code) as an indication: 69786 libgcrypt-1.5.0-betaN Crypto primitives 11392 libgpg-error-1.10 Shared error codes 171180 gnupg-2.1.0beta2 GnuPG proper 31145 libksba-1.2.0 X.509 / CMS support 17974 libassuan-2.0.1 IPC library 43763 gpgme-1.3.0 Library API to GnuPG. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Mar 17 11:50:02 2014 From: wk at gnupg.org (Werner Koch) Date: Mon, 17 Mar 2014 11:50:02 +0100 Subject: adding TOFU/POP to GnuPG In-Reply-To: <20140314145443.Horde.wom1NstFARc1sJyk9t-CuQ1@mail.sixdemonbag.org> (Robert J. Hansen's message of "Fri, 14 Mar 2014 14:54:43 -0700") References: <53231BD1.50902@guardianproject.info> <532335C5.8030009@fifthhorseman.net> <532343A4.2020501@guardianproject.info> <5323535D.9060901@fifthhorseman.net> <53236651.5010103@guardianproject.info> <53237060.3050705@fifthhorseman.net> <20140314145443.Horde.wom1NstFARc1sJyk9t-CuQ1@mail.sixdemonbag.org> Message-ID: <87d2hlumjp.fsf@vigenere.g10code.de> On Fri, 14 Mar 2014 22:54, rjh at sixdemonbag.org said: > sign) it. The goal here was to make email encryption completely > invisible to the end-user. I personally found the proxy to be touchy, > but in the main it worked well. We experimented with that in the past (e.g. the Windows proxy GPGrelay) but it turned out that you often run into problems with that because the integration in the MUA is not really provided. Another drawback is that it does not work with systems like Notes or Outlook/Exchange. The funny thing is that those two MUA are also the most troublesome with integrating direct support. Thus in the end there is not much use for it. Sure, the PGP Universal Server has an advantage for their business. > (I don't know much about GnuPG's STEED project: it's possible it works > in much the same way.) It is just an idea for now but it is based on the experience of adding OpenPGP support to almost all MUAs. By building upon this work we can easily add the required support to make crypto invisible most of the time. It is also possible to provide a dedicated MUA for all 3 major OSes which should satisfy the need for most users (see http://mailpile.is). Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From rjh at sixdemonbag.org Tue Mar 18 01:41:21 2014 From: rjh at sixdemonbag.org (Robert J. Hansen) Date: Mon, 17 Mar 2014 20:41:21 -0400 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <53224AD0.8090707@guardianproject.info> References: <53224AD0.8090707@guardianproject.info> Message-ID: <53279631.9030408@sixdemonbag.org> > This should run on any platform where Java and JNI are supported, but I have > only tested this on Android. Patches welcome! Be aware: it does require > GnuPG 2.x, the passphrase handling has been remove since GnuPG 2.x handles > passphrases via gpg-agent. Doing a recent pull (a couple of hours ago), the build is still bombing out due to the lack of a "context.h" file. Is this meant to be automatically generated, or is it missing from the source tree? From hans at guardianproject.info Tue Mar 18 03:01:43 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Mon, 17 Mar 2014 22:01:43 -0400 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <53279631.9030408@sixdemonbag.org> References: <53224AD0.8090707@guardianproject.info> <53279631.9030408@sixdemonbag.org> Message-ID: <5327A907.4060803@guardianproject.info> On 03/17/2014 08:41 PM, Robert J. Hansen wrote: >> This should run on any platform where Java and JNI are supported, but I have >> only tested this on Android. Patches welcome! Be aware: it does require >> GnuPG 2.x, the passphrase handling has been remove since GnuPG 2.x handles >> passphrases via gpg-agent. > > Doing a recent pull (a couple of hours ago), the build is still bombing > out due to the lack of a "context.h" file. Is this meant to be > automatically generated, or is it missing from the source tree? context.h was from gpgme, but I just pushed a fix to remove that requirement. gnupg-for-java does still require the private gpgme header data.h, but its now included in the gnupg-for-java git until someone finds a way to do the same thing with the public gpgme API. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From wk at gnupg.org Tue Mar 18 11:24:36 2014 From: wk at gnupg.org (Werner Koch) Date: Tue, 18 Mar 2014 11:24:36 +0100 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <5327A907.4060803@guardianproject.info> (Hans-Christoph Steiner's message of "Mon, 17 Mar 2014 22:01:43 -0400") References: <53224AD0.8090707@guardianproject.info> <53279631.9030408@sixdemonbag.org> <5327A907.4060803@guardianproject.info> Message-ID: <87d2hju7mj.fsf@vigenere.g10code.de> On Tue, 18 Mar 2014 03:01, hans at guardianproject.info said: > gnupg-for-java does still require the private gpgme header data.h, but its > now included in the gnupg-for-java git until someone finds a way to do the > same thing with the public gpgme API. Can you please explain that? data.h is internal to gpgme and should never be exposed to anyother library. If there is a need for certain information we need to find a way to do that. BTW, what do you think of putting the Java bindings into gpgme proper. We have the lang/ directory for such bindings. The advantage is that this would allow to access internal data structures. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From hans at guardianproject.info Tue Mar 18 15:05:19 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Tue, 18 Mar 2014 10:05:19 -0400 Subject: gnupg-for-java updated for GnuPG 2.x In-Reply-To: <87d2hju7mj.fsf@vigenere.g10code.de> References: <53224AD0.8090707@guardianproject.info> <53279631.9030408@sixdemonbag.org> <5327A907.4060803@guardianproject.info> <87d2hju7mj.fsf@vigenere.g10code.de> Message-ID: <5328529F.20903@guardianproject.info> On 03/18/2014 06:24 AM, Werner Koch wrote: > On Tue, 18 Mar 2014 03:01, hans at guardianproject.info said: > >> gnupg-for-java does still require the private gpgme header data.h, but its >> now included in the gnupg-for-java git until someone finds a way to do the >> same thing with the public gpgme API. > > Can you please explain that? data.h is internal to gpgme and should > never be exposed to anyother library. If there is a need for certain > information we need to find a way to do that. The header is included to get the gpgme_data_t struct for two different optimizations. I'm open to better ways to implement these :) The first case is for adding GnuPGData.size() to improve ByteArrayOutputStream performance. Since ByteArrayOutputStreams are used to get data out of GnuPGData, add a size() method so that the ByteArrayOutputStream can pre-allocate the memory needed, or at least close to the final number. https://github.com/guardianproject/gnupg-for-java/commit/1c912a1b333968f6f4314cae2e7516e4703d306e JNIEXPORT jsize JNICALL Java_com_freiheit_gnupg_GnuPGData_gpgmeSize(JNIEnv* env, jobject self, jlong data) { return (jsize) (DATA(data))->data.mem.size; } The second use allows the use of POSIX FILE streams when creating GnuPGData for files. Previously, GnuPGData(File f) would load the entire contents of the file into memory, then pass a memory gpgme_data_t to gpgme. This is horrible when working with large files or machines with limited memory. This patch uses the gpgme function for creating a gpgme_data_t from a POSIX FILE stream. https://github.com/guardianproject/gnupg-for-java/commit/7f842086c4956a8ed5d55e242b162325618a64fa JNIEXPORT void JNICALL Java_com_freiheit_gnupg_GnuPGData_gpgmeDataRelease(JNIEnv* env, jobject self, jlong data) { gpgme_data_t dh = DATA(data); if (dh->data.stream != NULL) fclose(dh->data.stream); gpgme_data_release(dh); } > BTW, what do you think of putting the Java bindings into gpgme proper. > We have the lang/ directory for such bindings. The advantage is that > this would allow to access internal data structures. Its too big a project to include into gpgme like that. That would hamper the development process and the build process. But moving the main repo to gnupg.org could make sense, if you want to adopt it as an official GnuPG Java binding. I'd change the package to org.gnupg then too. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 969 bytes Desc: OpenPGP digital signature URL: From hans at guardianproject.info Fri Mar 21 21:49:29 2014 From: hans at guardianproject.info (Hans-Christoph Steiner) Date: Fri, 21 Mar 2014 16:49:29 -0400 Subject: how to import a .pkr file with multiple keys using gpgme? Message-ID: <532CA5D9.8070508@guardianproject.info> If I have a .pkr file with multiple keys in it, I can import it from the command line using: `gpg --import public-keys.pkr`. I cannot find a way to do this with gpgme. When I using gpgme_op_import(), it complains of a bad key format: result->imports == NULL, result->imported = 0, result->not_imported = 0 com.freiheit.gnupg.GnuPGException: 53: Unusable public key I'm using gpgme 1.4.3 and gpg2 2.0.17. .hc -- PGP fingerprint: 5E61 C878 0F86 295C E17D 8677 9F0F E587 374B BE81 From gniibe at fsij.org Tue Mar 25 08:43:14 2014 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 25 Mar 2014 16:43:14 +0900 Subject: Smartcard EdDSA Support Message-ID: <1395733394.6984.2.camel@cfw2.gniibe.org> Hello, I have implemented the Twisted Edwards curve computation routine for Gnuk, and I am currently considering to integrate this routine. My primary target is using the curve with OpenSSH, so, I will use "INTERNAL AUTHENTICATE" smartcard command of ISO 7816. Other than that, we need to extend the OpenPGPcard specification, and corresponding parts of the GnuPG implementation. There are three places. (1) Importing key to card (2) Public key representation (3) Algorithm attributes For (1), I think that we can follow the way of tentative ECDSA implementation. For (2), there are two ways, standard EdDSA representation (y-coordinate only + parity of x, little endian) or no-compression representation (big endian) which starts with 04. It would be good to use no-compression representation, as it sounds more compatible. For (3), it will be algorithm ID + OID. (we need new algorithm ID for EdDSA.) I'm not sure if we will have EdDSA with different curves in future, but if there is such a possibility, OID is required. Any comments are appreciated. No, I haven't tested the code on the target board yet. It has been only tested on host. I need to integrate it first, as the code is somewhat big. Usually, I test code on the target board on RAM, but this time, it is bigger than 20kB RAM. -- From wk at gnupg.org Tue Mar 25 14:10:08 2014 From: wk at gnupg.org (Werner Koch) Date: Tue, 25 Mar 2014 14:10:08 +0100 Subject: Smartcard EdDSA Support In-Reply-To: <1395733394.6984.2.camel@cfw2.gniibe.org> (NIIBE Yutaka's message of "Tue, 25 Mar 2014 16:43:14 +0900") References: <1395733394.6984.2.camel@cfw2.gniibe.org> Message-ID: <871txqo24v.fsf@vigenere.g10code.de> On Tue, 25 Mar 2014 08:43, gniibe at fsij.org said: > I have implemented the Twisted Edwards curve computation routine for > Gnuk, and I am currently considering to integrate this routine. Cool. I was about to ask you for this. For those who do not follow the commits: I implemented ssh-ed25519 support for gpg-agent on Saturday. > For (2), there are two ways, standard EdDSA representation > (y-coordinate only + parity of x, little endian) or no-compression > representation (big endian) which starts with 04. It would be good to > use no-compression representation, as it sounds more compatible. I strongly in favor of the standard representation. The only problem I see is that it does not fit into the compression flag byte model. Having exactly 32 bytes would really be nice but if it turns out that an indicator byte would be helpful, we need to look into that. I have not looked at Simon's TLS I-D for Ed25519 but I recall that a new flag byte value was discussed. A flag byte with the MSBit cleared would be helpful for implementers because the key could be considered as any kind of number without running into the sign problems (cf. ASN.1's octet-string vs. integer trouble). And the compression is actually part of the specification. However, with a flag byte implementers would be free to do either of them. This is actual the crucial part to get Ed25519 into OpenPGP. I hoped that Watson Ladd's I-D would soon be usable as a spec but it turned out that he shifted his attention a bit to more general questions. Thus we may want to do our own thing and don't wait for the committee^WCFRG. > For (3), it will be algorithm ID + OID. (we need new algorithm ID for > EdDSA.) I'm not sure if we will have EdDSA with different curves in > future, but if there is such a possibility, OID is required. There is Curve41417 which is also an Edwards curve and I assume that Bernstein and Lange developed it with EdDSA in mind. I have not seen the specs, though. > No, I haven't tested the code on the target board yet. It has been > only tested on host. I need to integrate it first, as the code is > somewhat big. Usually, I test code on the target board on RAM, but > this time, it is bigger than 20kB RAM. Would you be able to save RAM or flash by using uncompressed points? Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Mar 27 18:00:33 2014 From: wk at gnupg.org (Werner Koch) Date: Thu, 27 Mar 2014 18:00:33 +0100 Subject: New --quick-sign-key Message-ID: <87y4zvlgpa.fsf@vigenere.g10code.de> Hi, I have recently been asked how to simply sign a key with a script. Given that this question has been raised often enough, I implemented two new commands: gpg2 --quick-sign-key FINGERPRINT [NAMESTRINGS] gpg2 --quick-lsign-key FINGERPRINT [NAMESTRINGS] Without the NAMESTRINGS the command signs all active user ids of the key patching the FINGERPRINT of the primary key. With the NAMESTRINGS only those user ids which match on of the name strings are signed. The matching is a simple ascii-case-insensitive matching and does not yet reflect the full gpg user id selection method. Backporting that to 2.0 would be some editing work because I had do change quite some lines. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From edfinnerty at gmx.com Mon Mar 31 00:07:15 2014 From: edfinnerty at gmx.com (Ed Finnerty) Date: Mon, 31 Mar 2014 01:07:15 +0300 Subject: NSS 3.16 incompatibility Message-ID: <53389593.80602@gmx.com> Hello, Running this script: #!/bin/sh # Create an input file with random content dd if=/dev/urandom of=input.bin bs=1K count=1 # Loop forever while : ; do # Cleanup previous output rm -f out.bin # Encrypt input, write to out.bin gpgsm -e -r email at address input.bin 2>/dev/null > out.bin # Decrypt with cmsutil cmsutil -D -d ~/.thunderbird/yourprofile.default -i out.bin -v -n # If cmsutil, break out of the loop if [[ $? != 0 ]] ; then echo "GOTCHA" break fi done # While loop done Will eventually produce this output: NSS has been initialized. Got default certdb cmsutil: failed to decode message. cmsutil: problem decoding: SEC_ERROR_BAD_DATABASE: security library: bad database. GOTCHA Here's more info: $ gpgsm --version gpgsm (GnuPG) 2.0.22 libgcrypt 1.5.3 libksba 1.3.0 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Home: ~/.gnupg Supported algorithms: Cipher: 3DES, AES, AES192, AES256, SERPENT128, SERPENT192, SERPENT256, SEED, CAMELLIA128, CAMELLIA192, CAMELLIA256 Pubkey: RSA, ECDSA Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224, WHIRLPOOL I'm using NSS 3.16. Obviously, you need to have the proper certificates imported with gpgsm, certutil, etc. What's happening? Thanks.