From cvs at cvs.gnupg.org Tue Jun 5 18:20:28 2012 From: cvs at cvs.gnupg.org (by W. Trevor King) Date: Tue, 05 Jun 2012 18:20:28 +0200 Subject: [git] Assuan - branch, master, updated. libassuan-2.0.3-9-gca3f8e4 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPC library used by GnuPG". The branch, master has been updated via ca3f8e4b5bbe5549bd7804cf3bff36be21db1b82 (commit) via 7cf99d04d864fb308159fb928057f59eb4e5a110 (commit) via f40f8033b21bad8801b43676b486dab80c532397 (commit) from 861d19e028af70c7009640efc98eb485fff546d7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ca3f8e4b5bbe5549bd7804cf3bff36be21db1b82 Author: W. Trevor King Date: Fri Apr 20 15:18:03 2012 -0400 src/assuan-handler.c: add help strings for standard commands. Signed-off-by: W. Trevor King diff --git a/src/assuan-handler.c b/src/assuan-handler.c index 28fcdfd..dca5968 100644 --- a/src/assuan-handler.c +++ b/src/assuan-handler.c @@ -49,12 +49,20 @@ dummy_handler (assuan_context_t ctx, char *line) } +static const char std_help_nop[] = + "NOP\n" + "\n" + "No operation. Returns OK without any action."; static gpg_error_t std_handler_nop (assuan_context_t ctx, char *line) { return PROCESS_DONE (ctx, 0); /* okay */ } +static const char std_help_cancel[] = + "CANCEL\n" + "\n" + "Run the server's cancel handler if one has been registered."; static gpg_error_t std_handler_cancel (assuan_context_t ctx, char *line) { @@ -64,6 +72,14 @@ std_handler_cancel (assuan_context_t ctx, char *line) return PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_NOT_IMPLEMENTED, NULL)); } +static const char std_help_option[] = + "OPTION [ [=] ]\n" + "\n" + "Set option to configure server operation. Leading and\n" + "trailing spaces around and are allowed but should be\n" + "ignored. For compatibility reasons, may be prefixed with two\n" + "dashes. The use of the equal sign is optional but suggested if\n" + " is given."; static gpg_error_t std_handler_option (assuan_context_t ctx, char *line) { @@ -117,6 +133,10 @@ std_handler_option (assuan_context_t ctx, char *line) return PROCESS_DONE (ctx, 0); } +static const char std_help_bye[] = + "BYE\n" + "\n" + "Close the connection. The server will reply with OK."; static gpg_error_t std_handler_bye (assuan_context_t ctx, char *line) { @@ -130,12 +150,21 @@ std_handler_bye (assuan_context_t ctx, char *line) return PROCESS_DONE (ctx, 0); } +static const char std_help_auth[] = + "AUTH\n" + "\n" + "Reserved for future extensions."; static gpg_error_t std_handler_auth (assuan_context_t ctx, char *line) { return PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_NOT_IMPLEMENTED, NULL)); } +static const char std_help_reset[] = + "RESET\n" + "\n" + "Reset the connection but not any existing authentication. The server\n" + "should release all resources associated with the connection."; static gpg_error_t std_handler_reset (assuan_context_t ctx, char *line) { @@ -152,6 +181,12 @@ std_handler_reset (assuan_context_t ctx, char *line) return PROCESS_DONE (ctx, err); } +static const char std_help_help[] = + "HELP []\n" + "\n" + "Lists all commands that the server understands as comment lines on\n" + "the status channel. If is given, list detailed help for\n" + "that command."; static gpg_error_t std_handler_help (assuan_context_t ctx, char *line) { @@ -211,7 +246,10 @@ std_handler_help (assuan_context_t ctx, char *line) return PROCESS_DONE (ctx, 0); } - +static const char std_help_end[] = + "END\n" + "\n" + "Used by a client to mark the end of raw data."; static gpg_error_t std_handler_end (assuan_context_t ctx, char *line) { @@ -255,7 +293,13 @@ assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd) } -/* Format is INPUT FD= */ +static const char std_help_input[] = + "INPUT FD[=]\n" + "\n" + "Used by a client to pass an input file descriptor to the server.\n" + "The server opens as a local file descriptor. Without , the\n" + "server opens the file descriptor just sent by the client using\n" + "assuan_sendfd."; static gpg_error_t std_handler_input (assuan_context_t ctx, char *line) { @@ -290,7 +334,13 @@ std_handler_input (assuan_context_t ctx, char *line) } -/* Format is OUTPUT FD= */ +static const char std_help_output[] = + "OUTPUT FD[=]\n" + "\n" + "Used by a client to pass an output file descriptor to the server.\n" + "The server opens as a local file descriptor. Without , the\n" + "server opens the file descriptor just sent by the client using\n" + "assuan_sendfd."; static gpg_error_t std_handler_output (assuan_context_t ctx, char *line) { @@ -331,21 +381,21 @@ std_handler_output (assuan_context_t ctx, char *line) static struct { const char *name; gpg_error_t (*handler)(assuan_context_t, char *line); + const char *help; int always; /* always initialize this command */ } std_cmd_table[] = { - { "NOP", std_handler_nop, 1 }, - { "CANCEL", std_handler_cancel, 1 }, - { "OPTION", std_handler_option, 1 }, - { "BYE", std_handler_bye, 1 }, - { "AUTH", std_handler_auth, 1 }, - { "RESET", std_handler_reset, 1 }, - { "END", std_handler_end, 1 }, - { "HELP", std_handler_help, 1 }, - - { "INPUT", std_handler_input, 0 }, - { "OUTPUT", std_handler_output, 0 }, - { NULL, NULL, 0 } -}; + { "NOP", std_handler_nop, std_help_nop, 1 }, + { "CANCEL", std_handler_cancel, std_help_cancel, 1 }, + { "OPTION", std_handler_option, std_help_option, 1 }, + { "BYE", std_handler_bye, std_help_bye, 1 }, + { "AUTH", std_handler_auth, std_help_auth, 1 }, + { "RESET", std_handler_reset, std_help_reset, 1 }, + { "END", std_handler_end, std_help_end, 1 }, + { "HELP", std_handler_help, std_help_help, 1 }, + + { "INPUT", std_handler_input, std_help_input, 0 }, + { "OUTPUT", std_handler_output, std_help_output, 0 }, + { } }; /** commit 7cf99d04d864fb308159fb928057f59eb4e5a110 Author: W. Trevor King Date: Thu Apr 19 20:19:46 2012 -0400 Update example code for pipe server. * doc/assuan.texi: Fix server example code to use assuan_new. diff --git a/doc/assuan.texi b/doc/assuan.texi index 9ea7804..ddac37a 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -741,6 +741,7 @@ GPGME and an application using GPGME, the context is very extensive and covers utilitary information like memory allocation callbacks as well as specific information associated with client/server operations. + at anchor{function assuan_new} @deftypefun gpg_error_t assuan_new (@w{assuan_context_t *@var{ctx_p}}) The function @code{assuan_new} creates a new context, using the global default memory allocation, log handler and @code{libgpg-error} source. @@ -1230,16 +1231,24 @@ command_handler (int fd) int i; assuan_context_t ctx; + rc = assuan_new (&ctx); + if (rc) + @{ + fprintf (stderr, "server context creation failed: %s\n", + gpg_strerror(rc)); + return; + @} + if (fd == -1) @{ assuan_fd_t filedes[2]; - filedes[0] = assuan_fd_from_posix (0); - filedes[1] = assuan_fd_from_posix (1); - rc = assuan_init_pipe_server (&ctx, filedes); + filedes[0] = assuan_fd_from_posix_fd (0); + filedes[1] = assuan_fd_from_posix_fd (1); + rc = assuan_init_pipe_server (ctx, filedes); @} else - rc = assuan_init_socket_server (&ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED); + rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED); if (rc) @{ fprintf (stderr, "server init failed: %s\n", gpg_strerror (rc)); @@ -1248,13 +1257,16 @@ command_handler (int fd) @end example @noindent -This is the first part of the command handler. In case this is called -as a pipe based server, @var{fd} will be based as @var{fd} and the -code assumes that the server's @code{stdin} and @code{stdout} file -handles are connected to a pipe. The initialization is thus done -using the function: +This is the first part of the command handler. We start of by +allocating a new Assuan context with @code{assuan_new}. + at xref{function assuan_new}. + +In case this is called as a pipe based server, @var{fd} will be based +as @var{fd} and the code assumes that the server's @code{stdin} and + at code{stdout} file handles are connected to a pipe. The +initialization is thus done using the function: - at deftypefun gpg_error_t assuan_init_pipe_server (@w{assuan_context_t *@var{r_ctx}}, @w{assuan_fd_t @var{filedes}[2]}) + at deftypefun gpg_error_t assuan_init_pipe_server (@w{assuan_context_t @var{ctx}}, @w{assuan_fd_t @var{filedes}[2]}) The function takes the two file descriptors from @var{filedes} and returns a new Assuan context at @var{r_ctx}. As usual, a return value @@ -1270,15 +1282,11 @@ by the client to connect to such a server, automagically sets this variable. @end deftypefun - at noindent -If a file descriptor has been passed, the assuan context gets -initialized by the function: - - at deftypefun gpg_error_t assuan_init_socket_server (@w{assuan_context_t *@var{r_ctx}}, @w{assuan_fd_t @var{fd}}, @w{unsigned int @var{flags}}) + at deftypefun gpg_error_t assuan_init_socket_server (@w{assuan_context_t @var{ctx}}, @w{assuan_fd_t @var{fd}}, @w{unsigned int @var{flags}}) -The function takes the file descriptor @var{fd} which is expected to be -associated with a socket and returns a new Assuan context at - at var{r_ctx}. The following bits are currently defined for @var{flags}: +The function takes the file descriptor @var{fd} which is expected to +be associated with a socket and an Assuan context @var{ctx}. The +following bits are currently defined for @var{flags}: @table @code @item ASSUAN_SOCKET_SERVER_FDPASSING @@ -1291,8 +1299,7 @@ bit as it allows better control of the connection state. @end table As usual, a return value of @code{0} indicates success and a failure -is indicated by a returning an error value. In case of error, - at code{NULL} will be stored at @var{r_ctx}. +is indicated by a returning an error value. @end deftypefun @noindent commit f40f8033b21bad8801b43676b486dab80c532397 Author: W. Trevor King Date: Thu Apr 19 20:19:43 2012 -0400 Wrap reference to END with @code. * doc/assuan.texi: Wrap reference to END with @code{}. diff --git a/doc/assuan.texi b/doc/assuan.texi index 1d48391..9ea7804 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -336,8 +336,8 @@ Reset the connection but not any existing authentication. The server should release all resources associated with the connection. @item END -Used by a client to mark the end of raw data. The server may send END -to indicate a partial end of data. +Used by a client to mark the end of raw data. The server may send + at code{END} to indicate a partial end of data. @item HELP Lists all commands that the server understands as comment lines on the ----------------------------------------------------------------------- Summary of changes: doc/assuan.texi | 51 +++++++++++++++++------------- src/assuan-handler.c | 82 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 95 insertions(+), 38 deletions(-) hooks/post-receive -- IPC library used by GnuPG http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jun 8 11:07:36 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 08 Jun 2012 11:07:36 +0200 Subject: [git] GCRYPT - branch, OS2-BRANCH, updated. libgcrypt-1.5.0-35-g683d5d4 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, OS2-BRANCH has been updated via 683d5d45e9bcd6f2ba4dca7ecb7c721170834787 (commit) via bbee6f8543671cf27f5ef3c0986ae56a86bdc5e2 (commit) via b75213fd60dabbc1b0a405789c984ec0ec4e566d (commit) via c897deca8b30aca245222b2cabc131058eb024d4 (commit) from 32dc49474e83140a6717903db3a8885ebaaaf6fb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 683d5d45e9bcd6f2ba4dca7ecb7c721170834787 Author: Werner Koch Date: Mon May 14 10:26:25 2012 +0200 Add curve aliases from RFC-5656. * cipher/ecc.c (curve_aliases): Add "nistp???" entries. diff --git a/cipher/ecc.c b/cipher/ecc.c index bbff7ee..70431fe 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -96,19 +96,24 @@ static const struct { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ { "NIST P-192", "prime192v1" }, /* X9.62 name. */ { "NIST P-192", "secp192r1" }, /* SECP name. */ + { "NIST P-192", "nistp192" }, /* rfc5656. */ { "NIST P-224", "secp224r1" }, { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ + { "NIST P-224", "nistp224" }, /* rfc5656. */ { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ { "NIST P-256", "prime256v1" }, { "NIST P-256", "secp256r1" }, + { "NIST P-256", "nistp256" }, /* rfc5656. */ { "NIST P-384", "secp384r1" }, { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "nistp384" }, /* rfc5656. */ { "NIST P-521", "secp521r1" }, { "NIST P-521", "1.3.132.0.35" }, + { "NIST P-521", "nistp521" }, /* rfc5656. */ { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" }, { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" }, commit bbee6f8543671cf27f5ef3c0986ae56a86bdc5e2 Author: Werner Koch Date: Wed Apr 25 16:35:10 2012 +0200 Add authors with a DCO to AUTHORS. -- diff --git a/AUTHORS b/AUTHORS index 94c1213..c0231d6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,7 +37,7 @@ Disclaims changes. nh at df.lth.se Weak key patches. -GNUPG R?mi Guyomarch 1999-05-25 +GNUPG R??mi Guyomarch 1999-05-25 Assigns past and future changes. (g10/compress.c, g10/encr-data.c, g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c) rguyom at mail.dotcom.fr @@ -96,12 +96,19 @@ Assigns Past and Future Changes openpgp at brainhub.org (cipher/ecc.c and related files) -LIBGCRYPT Ulrich M?ller 2012-02-15 +LIBGCRYPT Ulrich M??ller 2012-02-15 Assigns Past and Future Changes ulm at gentoo.org (Changes to cipher/idea.c and related files) +Authors with a DCO +================== + +DCO:2012-04-16:Tom???? Mr??z +DCO:2012-04-20:Rafa??l Carr?? + + More credits ============ The ATH implementation (src/ath*) has been taken from GPGME and commit b75213fd60dabbc1b0a405789c984ec0ec4e566d Author: Werner Koch Date: Mon Apr 16 11:24:32 2012 +0200 State new contribution rules. * doc/DCO: New. * doc/HACKING: Document new rules. diff --git a/doc/DCO b/doc/DCO new file mode 100644 index 0000000..ee460f6 --- /dev/null +++ b/doc/DCO @@ -0,0 +1,29 @@ +Libgcrypt Developer's Certificate of Origin. Version 1.0 +========================================================= + +By making a contribution to the Libgcrypt project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the free software license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate free + software license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same free software license + (unless I am permitted to submit under a different license), + as indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the free software license(s) + involved. + +Signed-off-by: [Your name and mail address] diff --git a/doc/HACKING b/doc/HACKING index 4e0405d..0cb8d56 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -1,33 +1,86 @@ - Various hacking notes -*- text -*- - ======================= +# HACKING -*- org -*- +#+TITLE: Hacking notes for Libgcrypt +#+STARTUP: showall -No more ChangeLog files ------------------------ +* How to contribute -Do not modify any of the ChangeLog files in Libgcrypt. Starting on -December 1st, 2011 we put change information only in the GIT commit -log, and generate a top-level ChangeLog file from logs at "make dist" -time. As such, there are strict requirements on the form of the -commit log messages. The old ChangeLog files have all be renamed to -ChangeLog-2011 + The following stuff explains some basic procedures you need to + follow if you want to contribute code or documentation. +** No more ChangeLog files -Commit log requirements ------------------------ + Do not modify any of the ChangeLog files in Libgcrypt. Starting on + December 1st, 2011 we put change information only in the GIT commit + log, and generate a top-level ChangeLog file from logs at "make + dist" time. As such, there are strict requirements on the form of + the commit log messages. The old ChangeLog files have all be + renamed to ChangeLog-2011 -Your commit log should always start with a one-line summary, the second -line should be blank, and the remaining lines are usually ChangeLog-style -entries for all affected files. However, it's fine -- even recommended -- -to write a few lines of prose describing the change, when the summary -and ChangeLog entries don't give enough of the big picture. Omit the -leading TABs that you're used to seeing in a "real" ChangeLog file, but -keep the maximum line length at 72 or smaller, so that the generated -ChangeLog lines, each with its leading TAB, will not exceed 80 columns. +** Commit log requirements + Your commit log should always start with a one-line summary, the + second line should be blank, and the remaining lines are usually + ChangeLog-style entries for all affected files. However, it's fine + -- even recommended -- to write a few lines of prose describing the + change, when the summary and ChangeLog entries don't give enough of + the big picture. Omit the leading TABs that you're used to seeing + in a "real" ChangeLog file, but keep the maximum line length at 72 + or smaller, so that the generated ChangeLog lines, each with its + leading TAB, will not exceed 80 columns. +** License policy -Taking optimized MPI code out of GMP: -------------------------------------- + Libgcrypt is currently licensed under the LGPLv2+ with tools and the + manual being under the GPLv2+. We may eventually update to a newer + version of the licenses or a combination of them. It is thus + important, that all contributed code allows for an update of the + license; for example we can't accept code under the LGPLv2(only). + + Libgcrypt used to have a strict policy of requiring copyright + assignments to the FSF. To avoid this major organizational overhead + and to allow inclusion of code, not copyrighted by the FSF, this + policy has been relaxed. It is now also possible to contribute code + by asserting that the contribution is in accordance to the + "Libgcrypt Developer's Certificate of Origin" as found in the file + "DCO". (Except for a slight wording change, this DCO is identical + to the one used by the Linux kernel.) + + If your want to contribute code or documentation to Libgcrypt and + you didn't signed a copyright assignment with the FSF in the past, + you need to take these simple steps: + + - Decide which mail address you want to use. Please have your real + name in the address and not a pseudonym. Anonymous contributions + can only be done if you find a proxy who certifies for you. + + - If your employer or school might claim ownership of code written + by you; you need to talk to them to make sure that you have the + right to contribute under the DCO. + + - Send an OpenPGP signed mail to the gcrypt-devel at gnupg.org mailing + list from your mail address. Include a copy of the DCO as found + in the official master branch. Insert your name and email address + into the DCO in the same way you want to use it later. Example: + + Signed-off-by: Joe R. Hacker + + (If you really need it, you may perform simple transformations of + the mail address: Replacing "@" by " at " or "." by " dot ".) + + - That's it. From now on you only need to add a "Signed-off-by:" + line with your name and mail address to the commit message. It is + recommended to send the patches using a PGP/MIME signed mail. + +** Coding standards + + Please follow the GNU coding standards. If you are in doubt consult + the existing code as an example. Do no re-indent code without a + need. If you really need to do it, use a separate commit for such a + change. + + +* Porting hints +** Taking optimized MPI code out of GMP: I generated the pentium4/* files by glueing the existing assembler prologues to the GMP 4.2.1 assembler files generated with the m4 @@ -42,8 +95,9 @@ Taking optimized MPI code out of GMP: tedious work. -Debugging math stuff: ---------------------- +* Debug hints + +** Debugging math stuff: While debugging the ECC code in libgcrypt, I was in need for some computer algebra system which would allow me to verify the numbers diff --git a/doc/Makefile.am b/doc/Makefile.am index 451d42f..2cf556e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -17,7 +17,7 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -EXTRA_DIST = README.apichanges HACKING \ +EXTRA_DIST = README.apichanges HACKING DCO \ libgcrypt-modules.eps fips-fsm.eps \ libgcrypt-modules.png fips-fsm.png \ libgcrypt-modules.pdf fips-fsm.pdf \ commit c897deca8b30aca245222b2cabc131058eb024d4 Author: Tomas Mraz Date: Wed Apr 4 14:17:09 2012 +0200 Add GCRYCTL_SET_ENFORCED_FIPS_FLAG command. * doc/gcrypt.texi: Add documentation of the new command. * src/fips.c (_gcry_enforced_fips_mode): Report the enforced fips mode only when fips mode is enabled. (_gcry_set_enforced_fips_mode): New function. * src/g10lib.h: Add the _gcry_set_enforced_fips_mode prototype. * src/gcrypt.h.in: Add the GCRYCTL_SET_ENFORCED_FIPS_FLAG. * src/global.c (_gcry_vcontrol): Handle the new command. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index b7817d9..3bd2686 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -595,8 +595,10 @@ initialization (i.e. before @code{gcry_check_version}). In addition to the standard FIPS mode, Libgcrypt may also be put into an Enforced FIPS mode by writing a non-zero value into the file - at file{/etc/gcrypt/fips_enabled}. The Enforced FIPS mode helps to -detect applications which don't fulfill all requirements for using + at file{/etc/gcrypt/fips_enabled} or by using the control command + at code{GCRYCTL_SET_ENFORCED_FIPS_FLAG} before any other calls to +libgcrypt. The Enforced FIPS mode helps to detect applications +which don't fulfill all requirements for using Libgcrypt in FIPS mode (@pxref{FIPS Mode}). Once Libgcrypt has been put into FIPS mode, it is not possible to @@ -804,20 +806,20 @@ proper random device. This command dumps information pertaining to the configuration of the library to the given stream. If NULL is given for @var{stream}, the log system is used. This command may be used before the intialization has -been finished but not before a gcry_version_check. +been finished but not before a @code{gcry_check_version}. @item GCRYCTL_OPERATIONAL_P; Arguments: none This command returns true if the library is in an operational state. This information makes only sense in FIPS mode. In contrast to other functions, this is a pure test function and won't put the library into FIPS mode or change the internal state. This command may be used before -the intialization has been finished but not before a gcry_version_check. +the intialization has been finished but not before a @code{gcry_check_version}. @item GCRYCTL_FIPS_MODE_P; Arguments: none This command returns true if the library is in FIPS mode. Note, that this is no indication about the current state of the library. This command may be used before the intialization has been finished but not -before a gcry_version_check. An application may use this command or +before a @code{gcry_check_version}. An application may use this command or the convenience macro below to check whether FIPS mode is actually active. @@ -833,10 +835,19 @@ implemented as a macro. Running this command puts the library into FIPS mode. If the library is already in FIPS mode, a self-test is triggered and thus the library will be put into operational state. This command may be used before a call -to gcry_check_version and that is actually the recommended way to let an +to @code{gcry_check_version} and that is actually the recommended way to let an application switch the library into FIPS mode. Note that Libgcrypt will reject an attempt to switch to fips mode during or after the intialization. + at item GCRYCTL_SET_ENFORCED_FIPS_FLAG; Arguments: none +Running this command sets the internal flag that puts the library into +the enforced FIPS mode during the FIPS mode initialization. This command +does not affect the library if the library is not put into the FIPS mode and +it must be used before any other libgcrypt library calls that initialize +the library such as @code{gcry_check_version}. Note that Libgcrypt will +reject an attempt to switch to the enforced fips mode during or after +the intialization. + @item GCRYCTL_SELFTEST; Arguments: none This may be used at anytime to have the library run all implemented self-tests. It works in standard and in FIPS mode. Returns 0 on diff --git a/src/fips.c b/src/fips.c index a3445eb..e45baba 100644 --- a/src/fips.c +++ b/src/fips.c @@ -274,9 +274,17 @@ _gcry_fips_mode (void) int _gcry_enforced_fips_mode (void) { + if (!_gcry_fips_mode ()) + return 0; return enforced_fips_mode; } +/* Set a flag telling whether we are in the enforced fips mode. */ +void +_gcry_set_enforced_fips_mode (void) +{ + enforced_fips_mode = 1; +} /* If we do not want to enforce the fips mode, we can set a flag so that the application may check whether it is still in fips mode. diff --git a/src/g10lib.h b/src/g10lib.h index 46d5229..ec86c97 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -327,6 +327,8 @@ int _gcry_fips_mode (void); int _gcry_enforced_fips_mode (void); +void _gcry_set_enforced_fips_mode (void); + void _gcry_inactivate_fips_mode (const char *text); int _gcry_is_fips_mode_inactive (void); diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 8e23ec4..1e9d11d 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -285,7 +285,8 @@ enum gcry_ctl_cmds GCRYCTL_FORCE_FIPS_MODE = 56, GCRYCTL_SELFTEST = 57, /* Note: 58 .. 62 are used internally. */ - GCRYCTL_DISABLE_HWF = 63 + GCRYCTL_DISABLE_HWF = 63, + GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64 }; /* Perform various operations defined by CMD. */ diff --git a/src/global.c b/src/global.c index bde8791..4ce869a 100644 --- a/src/global.c +++ b/src/global.c @@ -599,6 +599,16 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) } break; + case GCRYCTL_SET_ENFORCED_FIPS_FLAG: + if (!any_init_done) + { + /* Not yet intialized at all. Set the enforced fips mode flag */ + _gcry_set_enforced_fips_mode (); + } + else + err = GPG_ERR_GENERAL; + break; + default: /* A call to make sure that the dummy code is linked in. */ _gcry_compat_identification (); ----------------------------------------------------------------------- Summary of changes: AUTHORS | 11 +++++- cipher/ecc.c | 5 +++ doc/DCO | 29 +++++++++++++++ doc/HACKING | 102 ++++++++++++++++++++++++++++++++++++++++++------------- doc/Makefile.am | 2 +- doc/gcrypt.texi | 23 +++++++++--- src/fips.c | 8 ++++ src/g10lib.h | 2 + src/gcrypt.h.in | 3 +- src/global.c | 10 +++++ 10 files changed, 161 insertions(+), 34 deletions(-) create mode 100644 doc/DCO hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jun 13 08:34:25 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Wed, 13 Jun 2012 08:34:25 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, created. gnupg-2.0.19-15-ga3ae211 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been created at a3ae21162ae14a6a1661ef1a6937601f6914528b (commit) - Log ----------------------------------------------------------------- commit a3ae21162ae14a6a1661ef1a6937601f6914528b Author: NIIBE Yutaka Date: Tue Jun 12 14:51:52 2012 +0900 scd fixes on error. * scd/apdu.c (open_pcsc_reader_wrapped): Show error number. * scd/command.c (get_reader_slot): Return -1 on error. diff --git a/scd/apdu.c b/scd/apdu.c index b8bfcec..541dd05 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1728,7 +1728,8 @@ open_pcsc_reader_wrapped (const char *portstr) | (msgbuf[7] << 8 ) | msgbuf[8]); if (err) { - log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); + log_error ("PC/SC OPEN failed: %s (0x%08x)\n", + pcsc_error_string (err), err); /*sw = pcsc_error_to_sw (err);*/ goto command_failed; } diff --git a/scd/command.c b/scd/command.c index be05977..5ef6540 100644 --- a/scd/command.c +++ b/scd/command.c @@ -414,18 +414,19 @@ get_reader_slot (void) int no_service_flag; ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag); + if (no_service_flag) + { + log_info ("no card services - disabling scdaemon\n"); + reader_disabled = 1; + } + /* If we still don't have a slot, we have no readers. Invalidate for now until a reader is attached. */ if(ss->slot == -1) { ss->valid = 0; + return -1; } - - if (no_service_flag) - { - log_info ("no card services - disabling scdaemon\n"); - reader_disabled = 1; - } } /* Return the slot_table index. */ commit 31584d3659497c0fff26f129c8c16a57a9e2330b Author: NIIBE Yutaka Date: Fri Jun 8 13:18:06 2012 +0900 scd: Fix the changes of scd/command.c * scd/command.c (do_reset): Assign slot after setting slot_table. diff --git a/scd/command.c b/scd/command.c index 7865869..be05977 100644 --- a/scd/command.c +++ b/scd/command.c @@ -321,7 +321,7 @@ do_reset (ctrl_t ctrl, int send_reset) break; default: apdu_close_reader (slot); - slot_table[slot].slot = slot = -1; + slot = slot_table[slot].slot = -1; break; } } commit ffd7ebf62963adb044ee56f0e1b87be837b8f179 Author: Werner Koch Date: Wed Dec 14 10:30:01 2011 +0100 scd: Fix resetting and closing of the reader. (Backported by gniibe) * scd/command.c (update_card_removed): Do no act on an invalid VRDR. (do_reset): Ignore apdu_reset error codes for no and inactive card. Close the reader before setting the slot to -1. (update_reader_status_file): Notify the application before closing the reader. -- With this change the scd now works as it did in the past. In particular there is no more endless loop trying to open the reader by the update_reader_status_file ticker function. That bug basically blocked all card operations until the scdaemon was killed. diff --git a/scd/command.c b/scd/command.c index ccb25f1..7865869 100644 --- a/scd/command.c +++ b/scd/command.c @@ -181,6 +181,9 @@ update_card_removed (int slot, int value) { struct server_local_s *sl; + if (slot == -1) + return; + for (sl=session_list; sl; sl = sl->next_session) if (sl->ctrl_backlink && sl->ctrl_backlink->reader_slot == slot) @@ -308,11 +311,19 @@ do_reset (ctrl_t ctrl, int send_reset) tell the application layer about it. */ if (slot != -1 && send_reset && !IS_LOCKED (ctrl) ) { - if (apdu_reset (slot)) - { - slot_table[slot].valid = 0; - } application_notify_card_reset (slot); + switch (apdu_reset (slot)) + { + case 0: + break; + case SW_HOST_NO_CARD: + case SW_HOST_CARD_INACTIVE: + break; + default: + apdu_close_reader (slot); + slot_table[slot].slot = slot = -1; + break; + } } /* If we hold a lock, unlock now. */ @@ -1671,10 +1682,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) ss = &slot_table[slot]; - if (!ss->valid) - BUG (); - - if (ss->any && (ss->status & 1)) + if (ss->valid && ss->any && (ss->status & 1)) flag = 'u'; } rc = assuan_send_data (ctx, &flag, 1); @@ -2213,6 +2221,7 @@ update_reader_status_file (int set_card_removed_flag) if (sw_apdu == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ + application_notify_card_reset (ss->slot); apdu_close_reader (ss->slot); ss->valid = 0; status = 0; commit fae87058eac21b41e6ec0ad6dca1f4b4f806ab73 Author: Werner Koch Date: Mon Dec 12 21:02:54 2011 +0100 scd: Retry command SERIALNO for an inactive card. * scd/command.c (cmd_serialno): Retry once for an inactive card. diff --git a/scd/command.c b/scd/command.c index 0a1f785..ccb25f1 100644 --- a/scd/command.c +++ b/scd/command.c @@ -518,8 +518,10 @@ cmd_serialno (assuan_context_t ctx, char *line) char *serial_and_stamp; char *serial; time_t stamp; + int retries = 0; /* Clear the remove flag so that the open_card is able to reread it. */ + retry: if (!reader_disabled && ctrl->server_local->card_removed) { if ( IS_LOCKED (ctrl) ) @@ -528,7 +530,12 @@ cmd_serialno (assuan_context_t ctx, char *line) } if ((rc = open_card (ctrl, *line? line:NULL))) - return rc; + { + /* In case of an inactive card, retry once. */ + if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1) + goto retry; + return rc; + } rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); if (rc) commit 775a5f4b92fde3151d0faa88fae2b8ccfbea2928 Author: Werner Koch Date: Mon Dec 12 20:34:12 2011 +0100 Fix detection of card removal and insertion. * scd/apdu.c (apdu_connect): Return status codes for no card available and inactive card. * scd/command.c (TEST_CARD_REMOVAL): Also test for GPG_ERR_CARD_RESET. (open_card): Map apdu_connect status to GPG_ERR_CARD_RESET. diff --git a/scd/apdu.c b/scd/apdu.c index b68cd71..b8bfcec 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2596,11 +2596,14 @@ apdu_enum_reader (int slot, int *used) /* Connect a card. This is used to power up the card and make sure - that an ATR is available. */ + that an ATR is available. Depending on the reader backend it may + return an error for an inactive card or if no card is + available. */ int apdu_connect (int slot) { int sw; + unsigned int status; if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; @@ -2625,7 +2628,15 @@ apdu_connect (int slot) scdaemon is fired up and apdu_get_status has not yet been called. Without that we would force a reset of the card with the next call to apdu_get_status. */ - apdu_get_status_internal (slot, 1, 1, NULL, NULL); + apdu_get_status_internal (slot, 1, 1, &status, NULL); + if (sw) + ; + else if (!(status & APDU_CARD_PRESENT)) + sw = SW_HOST_NO_CARD; + else if (((status & APDU_CARD_PRESENT) && !(status & APDU_CARD_ACTIVE)) + || !reader_table[slot].atrlen) + sw = SW_HOST_CARD_INACTIVE; + return sw; } diff --git a/scd/command.c b/scd/command.c index 52b22c6..0a1f785 100644 --- a/scd/command.c +++ b/scd/command.c @@ -60,6 +60,7 @@ int _r = (r); \ if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \ || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \ + || gpg_err_code (_r) == GPG_ERR_CARD_RESET \ || gpg_err_code (_r) == GPG_ERR_ENODEV ) \ update_card_removed ((c)->reader_slot, 1); \ } while (0) @@ -420,9 +421,8 @@ get_reader_slot (void) return 0; } -/* If the card has not yet been opened, do it. Note that this - function returns an Assuan error, so don't map the error a second - time. */ + +/* If the card has not yet been opened, do it. */ static gpg_error_t open_card (ctrl_t ctrl, const char *apptype) { @@ -477,6 +477,8 @@ open_card (ctrl_t ctrl, const char *apptype) { if (sw == SW_HOST_NO_CARD) err = gpg_error (GPG_ERR_CARD_NOT_PRESENT); + else if (sw == SW_HOST_CARD_INACTIVE) + err = gpg_error (GPG_ERR_CARD_RESET); else err = gpg_error (GPG_ERR_CARD); } commit 08178d1e130a856622c0b938a34eb109bde79262 Author: Werner Koch Date: Fri Dec 2 18:09:58 2011 +0100 Support the Cherry ST-2000 card reader. * scd/ccid-driver.c (SCM_SCR331, SCM_SCR331DI, SCM_SCR335) (SCM_SCR3320, SCM_SPR532, CHERRY_ST2000): New constants. (parse_ccid_descriptor): Use them. (scan_or_find_usb_device, ccid_transceive_secure): Handle Cherry ST-2000. Suggested by Matthias-Christian Ott. Conflicts: scd/ccid-driver.c diff --git a/THANKS b/THANKS index 10e8631..7a87406 100644 --- a/THANKS +++ b/THANKS @@ -165,6 +165,7 @@ Martin Schulte schulte at thp.uni-koeln.de Matt Kraai kraai at alumni.carnegiemellon.edu Matthew Skala mskala at ansuz.sooke.bc.ca Matthew Wilcox matthew at wil.cx +Matthias-Christian Ott ott at mirix.org Matthias Urlichs smurf at noris.de Max Valianskiy maxcom at maxcom.ml.org Michael Engels michael.engels at uni-duesseldorf.de diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 3d66f10..9a07c79 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -209,9 +209,19 @@ enum { VENDOR_SCM = 0x04e6, VENDOR_OMNIKEY= 0x076b, VENDOR_GEMPC = 0x08e6, - VENDOR_KAAN = 0x0d46 + VENDOR_KAAN = 0x0d46, + VENDOR_FSIJ = 0x234B }; +/* Some product ids. */ +#define SCM_SCR331 0xe001 +#define SCM_SCR331DI 0x5111 +#define SCM_SCR335 0x5115 +#define SCM_SCR3320 0x5117 +#define SCM_SPR532 0xe003 +#define CHERRY_ST2000 0x003e + + /* A list and a table with special transport descriptions. */ enum { TRANSPORT_USB = 0, /* Standard USB transport. */ @@ -951,12 +961,12 @@ parse_ccid_descriptor (ccid_driver_t handle, */ if (handle->id_vendor == VENDOR_SCM - && handle->max_ifsd > 48 - && ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516) - ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620) - ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0514) - ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504) - ||(handle->id_product == 0x5117 && handle->bcd_device < 0x0522) + && handle->max_ifsd > 48 + && ( (handle->id_product == SCM_SCR331 && handle->bcd_device < 0x0516) + ||(handle->id_product == SCM_SCR331DI && handle->bcd_device < 0x0620) + ||(handle->id_product == SCM_SCR335 && handle->bcd_device < 0x0514) + ||(handle->id_product == SCM_SPR532 && handle->bcd_device < 0x0504) + ||(handle->id_product == SCM_SCR3320 && handle->bcd_device < 0x0522) )) { DEBUGOUT ("enabling workaround for buggy SCM readers\n"); @@ -1136,16 +1146,20 @@ scan_or_find_usb_device (int scan_mode, { ifcdesc = (interface->altsetting + set_no); /* The second condition is for older SCM SPR 532 who did - not know about the assigned CCID class. Instead of - trying to interpret the strings we simply check the - product ID. */ + not know about the assigned CCID class. The third + condition does the same for a Cherry SmartTerminal + ST-2000. Instead of trying to interpret the strings + we simply check the product ID. */ if (ifcdesc && ifcdesc->extra && ((ifcdesc->bInterfaceClass == 11 && ifcdesc->bInterfaceSubClass == 0 && ifcdesc->bInterfaceProtocol == 0) || (ifcdesc->bInterfaceClass == 255 && dev->descriptor.idVendor == VENDOR_SCM - && dev->descriptor.idProduct == 0xe003))) + && dev->descriptor.idProduct == SCM_SPR532) + || (ifcdesc->bInterfaceClass == 255 + && dev->descriptor.idVendor == VENDOR_CHERRY + && dev->descriptor.idProduct == CHERRY_ST2000))) { idev = usb_open (dev); if (!idev) @@ -3080,7 +3094,8 @@ ccid_transceive_secure (ccid_driver_t handle, Lc byte to the APDU. It seems that it will be replaced with the actual length instead of being appended before the APDU is send to the card. */ - cherry_mode = 1; + if (handle->id_product != CHERRY_ST2000) + cherry_mode = 1; break; default: return CCID_DRIVER_ERR_NOT_SUPPORTED; commit dafa7aa621dfe36c5c6cf462d3ec0d6c614ab105 Author: NIIBE Yutaka Date: Thu Jan 13 16:38:31 2011 +0900 fix wLangId in ccid-driver.c This is not a part of pin pad support series of mine. As I found the bug while I am preparing the patches, I report this. As CCID protocol is little endian, wLangId of US English = 0x0409 is represented as two bytes of 0x09 then 0x04. It is really confusing that the code like following is floating around: pin_verify -> wLangId = HOST_TO_CCID_16(0x0904); But, it is 0x0409 (not 0x0904). It is defined in the documentation: http://www.usb.org/developers/docs/USB_LANGIDs.pdf and origin of this table is Microsoft. We can see it at: http://msdn.microsoft.com/en-us/library/bb165625%28VS.80%29.aspx Yes, it would be better not to hard-code 0x0409. It would be better to try current locale of the user, or to use the first entry of string descriptor. I don't have time to implement such a thing... diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 8c362d7..3d66f10 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -3133,8 +3133,8 @@ ccid_transceive_secure (ccid_driver_t handle, if (pinlen_min && pinlen_max && pinlen_min == pinlen_max) msg[17] |= 0x01; /* Max size reached. */ msg[18] = 0xff; /* bNumberMessage: Default. */ - msg[19] = 0x04; /* wLangId-High. */ - msg[20] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */ + msg[19] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */ + msg[20] = 0x04; /* wLangId-High. */ msg[21] = 0; /* bMsgIndex. */ /* bTeoProlog follows: */ msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0; ----------------------------------------------------------------------- hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jun 13 10:47:37 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 13 Jun 2012 10:47:37 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, updated. gnupg-2.0.19-16-gcc13771 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been updated via cc13771675f83624a7d850b73f92e43e085b71c8 (commit) from a3ae21162ae14a6a1661ef1a6937601f6914528b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cc13771675f83624a7d850b73f92e43e085b71c8 Author: Werner Koch Date: Wed Jun 13 09:35:41 2012 +0200 Fix generated ChangeLog entry. -- Finally Jim's git-fix-log thingy comes handy. diff --git a/scripts/git-log-fix b/scripts/git-log-fix index af702fe..6760e86 100644 --- a/scripts/git-log-fix +++ b/scripts/git-log-fix @@ -1,3 +1,10 @@ # This file is expected to be used via gitlog-to-changelog's --amend=FILE # option. It specifies what changes to make to each given SHA1's commit # log and metadata, using Perl-eval'able expressions. + +08178d1e130a856622c0b938a34eb109bde79262 +s/Conflicts:/--/ + +dafa7aa621dfe36c5c6cf462d3ec0d6c614ab105 +# Fix old cherry-picked message. +s/(fix wLangId in.*)/\1\n--/ ----------------------------------------------------------------------- Summary of changes: scripts/git-log-fix | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jun 15 11:07:23 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Fri, 15 Jun 2012 11:07:23 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, updated. gnupg-2.0.19-26-g29b431f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been updated via 29b431fcf97a9e615d34a7a40e570e63834b360a (commit) via 3e39a9aeaadd9d4ea7ea578dc77504bd1fd6e30a (commit) via d138fe5c30c877856b4c397147bb0090705821f8 (commit) via 2586eac997911869008cb3ba57865a7d63a2afc3 (commit) via 685955444823a5ca1190b109043ee773bf206bae (commit) via f78cdf6d45708b67bc3d7bf7b90283254fdd23fd (commit) via 1b0968ce9a642671f902ceddbafb5af4fe51535b (commit) via b480f18e1de71766fc6b4fb3c50e157d0abffda5 (commit) via 7cd8b12e25b6daabedf6fdc2f350327e2116fc78 (commit) via 6dc187f2dbf3b5e7322fa40c7e085da12ad373d2 (commit) from cc13771675f83624a7d850b73f92e43e085b71c8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 29b431fcf97a9e615d34a7a40e570e63834b360a Merge: 3e39a9a cc13771 Author: NIIBE Yutaka Date: Fri Jun 15 16:50:45 2012 +0900 Merge branch 'scd-backport-2-0' of git+ssh://playfair.gnupg.org/git/gnupg into scd-backport-2-0 commit 3e39a9aeaadd9d4ea7ea578dc77504bd1fd6e30a Author: NIIBE Yutaka Date: Fri Jun 15 16:46:59 2012 +0900 scd: Fix merge mistake. * scd/iso7816.c (iso7816_reset_retry_counter): Implement. diff --git a/scd/iso7816.c b/scd/iso7816.c index dd73fc6..12daff9 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -374,7 +374,11 @@ gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, const char *newchv, size_t newchvlen) { - return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL); + int sw; + + sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER, + 2, chvno, newchvlen, newchv); + return map_sw (sw); } commit d138fe5c30c877856b4c397147bb0090705821f8 Author: Werner Koch Date: Thu Dec 15 21:45:35 2011 +0100 scd: Prefer application Geldkarte over DINSIG. * scd/app.c (select_application): Reorder application tests. -- Although the DINSIG application is available on most German cards, it is in reality not used. Thus showing the Geldkarte application is more desirable for a good user experience. Conflicts: scd/app.c diff --git a/scd/app.c b/scd/app.c index a23c4a5..7cbbf6e 100644 --- a/scd/app.c +++ b/scd/app.c @@ -381,11 +381,11 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) err = app_select_nks (app); if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15"))) err = app_select_p15 (app); - if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) - err = app_select_dinsig (app); if (err && is_app_allowed ("geldkarte") && (!name || !strcmp (name, "geldkarte"))) err = app_select_geldkarte (app); + if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) + err = app_select_dinsig (app); if (err && name) err = gpg_error (GPG_ERR_NOT_SUPPORTED); @@ -419,8 +419,10 @@ get_supported_applications (void) "openpgp", "nks", "p15", - "dinsig", "geldkarte", + "dinsig", + /* Note: "undefined" is not listed here because it needs special + treatment by the client. */ NULL }; int idx; commit 2586eac997911869008cb3ba57865a7d63a2afc3 Author: Werner Koch Date: Mon Dec 19 18:26:47 2011 +0100 scd: Fix for card change returning GPG_ERR_CARD_RESET. * scd/apdu.c (apdu_connect): Do not test for zero atrlen. -- When gpg-agent prompts for insertion of a card this error would be returned. Co-authored-by: Ben Kibbey diff --git a/scd/apdu.c b/scd/apdu.c index 2effa8c..0e52909 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -3078,8 +3078,7 @@ apdu_connect (int slot) ; else if (!(status & APDU_CARD_PRESENT)) sw = SW_HOST_NO_CARD; - else if (((status & APDU_CARD_PRESENT) && !(status & APDU_CARD_ACTIVE)) - || !reader_table[slot].atrlen) + else if ((status & APDU_CARD_PRESENT) && !(status & APDU_CARD_ACTIVE)) sw = SW_HOST_CARD_INACTIVE; commit 685955444823a5ca1190b109043ee773bf206bae Author: NIIBE Yutaka Date: Fri Jan 6 13:50:21 2012 +0900 Merge ccid_driver_improvement branch. (backport) * scd/apdu.c (ccid_keypad_operation): Rename from ccid_keypad_verify. (open_ccid_reader): Use ccid_keypad_operation for verify and modify. * scd/ccid-driver.c (VENDOR_VASCO, VASCO_920): New. (ccid_transceive_apdu_level): Permit sending packet where apdulen <= 289. Support receiving packets in a chain. (ccid_transceive_secure): Maximum is 15 for VASCO DIGIPASS 920. Support keypad_modify method such as CHANGE_REFERENCE_DATA: 0x24. diff --git a/scd/apdu.c b/scd/apdu.c index 142426a..2effa8c 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2339,8 +2339,8 @@ check_ccid_keypad (int slot, int command, int pin_mode, static int -ccid_keypad_verify (int slot, int class, int ins, int p0, int p1, - struct pininfo_s *pininfo) +ccid_keypad_operation (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo) { unsigned char apdu[4]; int err, sw; @@ -2411,8 +2411,8 @@ open_ccid_reader (const char *portstr) reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].dump_status_reader = dump_ccid_reader_status; reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader; - reader_table[slot].keypad_verify = ccid_keypad_verify; - reader_table[slot].keypad_modify = NULL; + reader_table[slot].keypad_verify = ccid_keypad_operation; + reader_table[slot].keypad_modify = ccid_keypad_operation; /* Our CCID reader code does not support T=0 at all, thus reset the flag. */ reader_table[slot].is_t0 = 0; diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 9a07c79..5281a2f 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -210,7 +210,8 @@ enum { VENDOR_OMNIKEY= 0x076b, VENDOR_GEMPC = 0x08e6, VENDOR_KAAN = 0x0d46, - VENDOR_FSIJ = 0x234B + VENDOR_FSIJ = 0x234b, + VENDOR_VASCO = 0x1a44 }; /* Some product ids. */ @@ -220,7 +221,7 @@ enum { #define SCM_SCR3320 0x5117 #define SCM_SPR532 0xe003 #define CHERRY_ST2000 0x003e - +#define VASCO_920 0x0920 /* A list and a table with special transport descriptions. */ enum { @@ -2589,8 +2590,8 @@ ccid_transceive_apdu_level (ccid_driver_t handle, /* The maximum length for a short APDU T=1 block is 261. For an extended APDU T=1 block the maximum length 65544; however - extended APDU exchange level is not yet supported. */ - if (apdulen > 261) + extended APDU exchange level is not fully supported yet. */ + if (apdulen > 289) return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */ msg[0] = PC_to_RDR_XfrBlock; @@ -2612,10 +2613,53 @@ ccid_transceive_apdu_level (ccid_driver_t handle, RDR_to_PC_DataBlock, seqno, 5000, 0); if (rc) return rc; - - apdu = msg + 10; - apdulen = msglen - 10; - + + if (msg[9] == 1) + { + size_t total_msglen = msglen; + + while (1) + { + unsigned char status; + + msg = recv_buffer + total_msglen; + + msg[0] = PC_to_RDR_XfrBlock; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = bwi; /* bBWI */ + msg[8] = 0x10; /* Request next data block */ + msg[9] = 0; + set_msg_len (msg, 0); + msglen = 10; + + rc = bulk_out (handle, msg, msglen, 0); + if (rc) + return rc; + + rc = bulk_in (handle, msg, sizeof recv_buffer - total_msglen, &msglen, + RDR_to_PC_DataBlock, seqno, 5000, 0); + if (rc) + return rc; + status = msg[9]; + memmove (msg, msg+10, msglen - 10); + total_msglen += msglen - 10; + if (total_msglen >= sizeof recv_buffer) + return CCID_DRIVER_ERR_OUT_OF_CORE; + + if (status == 0x02) + break; + } + + apdu = recv_buffer + 10; + apdulen = total_msglen - 10; + } + else + { + apdu = msg + 10; + apdulen = msglen - 10; + } + if (resp) { if (apdulen > maxresplen) @@ -3058,7 +3102,7 @@ ccid_transceive_secure (ccid_driver_t handle, if (apdu_buflen >= 4 && apdu_buf[1] == 0x20 && (handle->has_pinpad & 1)) ; else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2)) - return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */ + ; else return CCID_DRIVER_ERR_NO_KEYPAD; @@ -3086,6 +3130,9 @@ ccid_transceive_secure (ccid_driver_t handle, case VENDOR_SCM: /* Tested with SPR 532. */ case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */ break; + case VENDOR_VASCO: /* Tested with DIGIPASS 920 */ + pinlen_max = 15; + break; case VENDOR_CHERRY: /* The CHERRY XX44 keyboard echos an asterisk for each entered character on the keyboard channel. We use a special variant @@ -3120,7 +3167,8 @@ ccid_transceive_secure (ccid_driver_t handle, msg[7] = 0; /* bBWI */ msg[8] = 0; /* RFU */ msg[9] = 0; /* RFU */ - msg[10] = 0; /* Perform PIN verification. */ + msg[10] = apdu_buf[1] == 0x20 ? 0 : 1; + /* Perform PIN verification or PIN modification. */ msg[11] = 0; /* Timeout in seconds. */ msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ if (handle->id_vendor == VENDOR_SCM) @@ -3139,28 +3187,58 @@ ccid_transceive_secure (ccid_driver_t handle, Units are bytes, position is 0. */ } - /* The following is a little endian word. */ - msg[15] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ - msg[16] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ + msglen = 15; + if (apdu_buf[1] == 0x24) + { + msg[msglen++] = 0; /* bInsertionOffsetOld */ + msg[msglen++] = 0; /* bInsertionOffsetNew */ + } - msg[17] = 0x02; /* bEntryValidationCondition: - Validation key pressed */ + /* The following is a little endian word. */ + msg[msglen++] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ + msg[msglen++] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ + + if (apdu_buf[1] == 0x24) + msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01; + /* bConfirmPIN + * 0x00: new PIN once + * 0x01: new PIN twice (confirmation) + * 0x02: old PIN and new PIN once + * 0x03: old PIN and new PIN twice (confirmation) + */ + + msg[msglen] = 0x02; /* bEntryValidationCondition: + Validation key pressed */ if (pinlen_min && pinlen_max && pinlen_min == pinlen_max) - msg[17] |= 0x01; /* Max size reached. */ - msg[18] = 0xff; /* bNumberMessage: Default. */ - msg[19] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */ - msg[20] = 0x04; /* wLangId-High. */ - msg[21] = 0; /* bMsgIndex. */ + msg[msglen] |= 0x01; /* Max size reached. */ + msglen++; + + if (apdu_buf[1] == 0x20) + msg[msglen++] = 0xff; /* bNumberMessage: Default. */ + else + msg[msglen++] = 0x03; /* bNumberMessage. */ + + msg[msglen++] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */ + msg[msglen++] = 0x04; /* wLangId-High. */ + + if (apdu_buf[1] == 0x20) + msg[msglen++] = 0; /* bMsgIndex. */ + else + { + msg[msglen++] = 0; /* bMsgIndex1. */ + msg[msglen++] = 1; /* bMsgIndex2. */ + msg[msglen++] = 2; /* bMsgIndex3. */ + } + /* bTeoProlog follows: */ - msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0; - msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */ - msg[24] = 0; /* The apdulen will be filled in by the reader. */ + msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0; + msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */ + msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */ /* APDU follows: */ - msg[25] = apdu_buf[0]; /* CLA */ - msg[26] = apdu_buf[1]; /* INS */ - msg[27] = apdu_buf[2]; /* P1 */ - msg[28] = apdu_buf[3]; /* P2 */ - msglen = 29; + msg[msglen++] = apdu_buf[0]; /* CLA */ + msg[msglen++] = apdu_buf[1]; /* INS */ + msg[msglen++] = apdu_buf[2]; /* P1 */ + msg[msglen++] = apdu_buf[3]; /* P2 */ if (cherry_mode) msg[msglen++] = 0; /* An EDC is not required. */ commit f78cdf6d45708b67bc3d7bf7b90283254fdd23fd Author: NIIBE Yutaka Date: Tue Dec 20 13:34:27 2011 +0900 Add error log and debug log for pcsc_keypad_verify and pcsc_keypad_modify. * scd/apdu.c (pcsc_keypad_verify): Add debug log and error log. (pcsc_keypad_modify): Likewise. diff --git a/scd/apdu.c b/scd/apdu.c index 38097c0..142426a 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2035,7 +2035,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, { int sw; unsigned char *pin_verify; - unsigned long len = PIN_VERIFY_STRUCTURE_SIZE; + int len = PIN_VERIFY_STRUCTURE_SIZE; unsigned char result[2]; size_t resultlen = 2; @@ -2091,12 +2091,21 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, pin_verify[22] = p1; /* abData[3] */ pin_verify[23] = 0x00; /* abData[4] */ + if (DBG_CARD_IO) + log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n", + class, ins, p0, p1, len, pininfo->maxlen); + sw = control_pcsc (slot, reader_table[slot].pcsc.verify_ioctl, pin_verify, len, result, &resultlen); xfree (pin_verify); if (sw || resultlen < 2) - return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE; + { + log_error ("control_pcsc failed: %d\n", sw); + return sw? sw: SW_HOST_INCOMPLETE_CARD_RESPONSE; + } sw = (result[resultlen-2] << 8) | result[resultlen-1]; + if (DBG_CARD_IO) + log_debug (" response: sw=%04X datalen=%d\n", sw, (unsigned int)resultlen); return sw; } @@ -2108,7 +2117,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, { int sw; unsigned char *pin_modify; - unsigned long len = PIN_MODIFY_STRUCTURE_SIZE; + int len = PIN_MODIFY_STRUCTURE_SIZE; unsigned char result[2]; size_t resultlen = 2; @@ -2175,12 +2184,21 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pin_modify[27] = p1; /* abData[3] */ pin_modify[28] = 0x00; /* abData[4] */ + if (DBG_CARD_IO) + log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n", + class, ins, p0, p1, len, (int)pininfo->maxlen); + sw = control_pcsc (slot, reader_table[slot].pcsc.modify_ioctl, pin_modify, len, result, &resultlen); xfree (pin_modify); if (sw || resultlen < 2) - return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE; + { + log_error ("control_pcsc failed: %d\n", sw); + return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE; + } sw = (result[resultlen-2] << 8) | result[resultlen-1]; + if (DBG_CARD_IO) + log_debug (" response: sw=%04X datalen=%d\n", sw, (unsigned int)resultlen); return sw; } commit 1b0968ce9a642671f902ceddbafb5af4fe51535b Author: NIIBE Yutaka Date: Fri Dec 2 13:57:12 2011 +0900 Fix pinpad input support for passphrase modification. (backport) * apdu.c (pcsc_keypad_verify): Have dummy Lc field with value 0. (pcsc_keypad_modify): Likewise. (pcsc_keypad_modify): It's only for ISO7816_CHANGE_REFERENCE_DATA. bConfirmPIN value is determined by the parameter p0. * app-openpgp.c (do_change_pin): The flag use_keypad should be 0 when reset_mode is on, or resetcode is on. use_keypad only makes sense for iso7816_change_reference_data_kp. * iso7816.h (iso7816_put_data_kp): Remove. (iso7816_reset_retry_counter_kp): Remove. (iso7816_reset_retry_counter_with_rc_kp): Remove. (iso7816_change_reference_data_kp): Add an argument: IS_EXCHANGE. * iso7816.c (iso7816_put_data_kp): Remove. (iso7816_reset_retry_counter_kp): Remove. (iso7816_reset_retry_counter_with_rc_kp): Remove. (iso7816_change_reference_data_kp): Add an argument: IS_EXCHANGE. diff --git a/scd/apdu.c b/scd/apdu.c index 4062b1e..38097c0 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2028,7 +2028,7 @@ check_pcsc_keypad (int slot, int command, int pin_mode, } -#define PIN_VERIFY_STRUCTURE_SIZE 23 +#define PIN_VERIFY_STRUCTURE_SIZE 24 static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, struct pininfo_s *pininfo) @@ -2081,7 +2081,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, pin_verify[12] = 0x00; /* bTeoPrologue[0] */ pin_verify[13] = 0x00; /* bTeoPrologue[1] */ pin_verify[14] = 0x00; /* bTeoPrologue[2] */ - pin_verify[15] = 0x04; /* ulDataLength */ + pin_verify[15] = 0x05; /* ulDataLength */ pin_verify[16] = 0x00; /* ulDataLength */ pin_verify[17] = 0x00; /* ulDataLength */ pin_verify[18] = 0x00; /* ulDataLength */ @@ -2089,6 +2089,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, pin_verify[20] = ins; /* abData[1] */ pin_verify[21] = p0; /* abData[2] */ pin_verify[22] = p1; /* abData[3] */ + pin_verify[23] = 0x00; /* abData[4] */ sw = control_pcsc (slot, reader_table[slot].pcsc.verify_ioctl, pin_verify, len, result, &resultlen); @@ -2100,7 +2101,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, } -#define PIN_MODIFY_STRUCTURE_SIZE 28 +#define PIN_MODIFY_STRUCTURE_SIZE 29 static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, struct pininfo_s *pininfo) @@ -2145,12 +2146,13 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pin_modify[6] = 0x00; /* bInsertionOffsetNew */ pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */ pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */ - pin_modify[9] = 0x03; /* bConfirmPIN - * 0x00: new PIN once - * 0x01: new PIN twice (confirmation) - * 0x02: old PIN and new PIN once - * 0x03: old PIN and new PIN twice (confirmation) - */ + pin_modify[9] = (p0 == 0 ? 0x03 : 0x01); + /* bConfirmPIN + * 0x00: new PIN once + * 0x01: new PIN twice (confirmation) + * 0x02: old PIN and new PIN once + * 0x03: old PIN and new PIN twice (confirmation) + */ pin_modify[10] = 0x02; /* bEntryValidationCondition: Validation key pressed */ if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen) pin_modify[10] |= 0x01; /* Max size reached. */ @@ -2163,7 +2165,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pin_modify[17] = 0x00; /* bTeoPrologue[0] */ pin_modify[18] = 0x00; /* bTeoPrologue[1] */ pin_modify[19] = 0x00; /* bTeoPrologue[2] */ - pin_modify[20] = 0x04; /* ulDataLength */ + pin_modify[20] = 0x05; /* ulDataLength */ pin_modify[21] = 0x00; /* ulDataLength */ pin_modify[22] = 0x00; /* ulDataLength */ pin_modify[23] = 0x00; /* ulDataLength */ @@ -2171,6 +2173,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pin_modify[25] = ins; /* abData[1] */ pin_modify[26] = p0; /* abData[2] */ pin_modify[27] = p1; /* abData[3] */ + pin_modify[28] = 0x00; /* abData[4] */ sw = control_pcsc (slot, reader_table[slot].pcsc.modify_ioctl, pin_modify, len, result, &resultlen); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 4bae875..e50297d 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1974,6 +1974,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (reset_mode) { /* To reset a PIN the Admin PIN is required. */ + use_keypad = 0; app->did_chv3 = 0; rc = verify_chv3 (app, pincb, pincb_arg); if (rc) @@ -1982,37 +1983,40 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (chvno == 2) set_resetcode = 1; } - else if (!use_keypad && (chvno == 1 || chvno == 3)) + else if (chvno == 1 || chvno == 3) { - char *promptbuf = NULL; - const char *prompt; - - if (chvno == 3) + if (!use_keypad) { - minlen = 8; - rc = build_enter_admin_pin_prompt (app, &promptbuf); + char *promptbuf = NULL; + const char *prompt; + + if (chvno == 3) + { + minlen = 8; + rc = build_enter_admin_pin_prompt (app, &promptbuf); + if (rc) + goto leave; + prompt = promptbuf; + } + else + prompt = _("||Please enter the PIN"); + rc = pincb (pincb_arg, prompt, &oldpinvalue); + xfree (promptbuf); + promptbuf = NULL; if (rc) - goto leave; - prompt = promptbuf; - } - else - prompt = _("||Please enter the PIN"); - rc = pincb (pincb_arg, prompt, &oldpinvalue); - xfree (promptbuf); - promptbuf = NULL; - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; - } + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } - if (strlen (oldpinvalue) < minlen) - { - log_info (_("PIN for CHV%d is too short;" - " minimum length is %d\n"), chvno, minlen); - rc = gpg_error (GPG_ERR_BAD_PIN); - goto leave; + if (strlen (oldpinvalue) < minlen) + { + log_info (_("PIN for CHV%d is too short;" + " minimum length is %d\n"), chvno, minlen); + rc = gpg_error (GPG_ERR_BAD_PIN); + goto leave; + } } } else if (chvno == 2) @@ -2024,6 +2028,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, size_t valuelen; int remaining; + use_keypad = 0; minlen = 8; relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL); if (!relptr || valuelen < 7) @@ -2042,24 +2047,21 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, goto leave; } - if (!use_keypad) + rc = pincb (pincb_arg, + _("||Please enter the Reset Code for the card"), + &resetcode); + if (rc) { - rc = pincb (pincb_arg, - _("||Please enter the Reset Code for the card"), - &resetcode); - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; - } - if (strlen (resetcode) < minlen) - { - log_info (_("Reset Code is too short; minimum length is %d\n"), - minlen); - rc = gpg_error (GPG_ERR_BAD_PIN); - goto leave; - } + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } + if (strlen (resetcode) < minlen) + { + log_info (_("Reset Code is too short; minimum length is %d\n"), + minlen); + rc = gpg_error (GPG_ERR_BAD_PIN); + goto leave; } } else @@ -2093,36 +2095,18 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (resetcode) { - if (use_keypad) - { - rc = pincb (pincb_arg, - _("||Please enter the Reset Code for the card and New PIN"), - NULL); - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; - } - rc = iso7816_reset_retry_counter_with_rc_kp (app->slot, 0x81, - &pininfo); - pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ - } - else - { - char *buffer; + char *buffer; - buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1); - if (!buffer) - rc = gpg_error_from_syserror (); - else - { - strcpy (stpcpy (buffer, resetcode), pinvalue); - rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81, - buffer, strlen (buffer)); - wipememory (buffer, strlen (buffer)); - xfree (buffer); - } + buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1); + if (!buffer) + rc = gpg_error_from_syserror (); + else + { + strcpy (stpcpy (buffer, resetcode), pinvalue); + rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81, + buffer, strlen (buffer)); + wipememory (buffer, strlen (buffer)); + xfree (buffer); } } else if (set_resetcode) @@ -2131,48 +2115,18 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, { log_error (_("Reset Code is too short; minimum length is %d\n"), 8); rc = gpg_error (GPG_ERR_BAD_PIN); - } + } else - { - if (use_keypad) - { - rc = pincb (pincb_arg, _("|RN|New Reset Code"), NULL); - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; - } - rc = iso7816_put_data_kp (app->slot, 0xD3, &pininfo); - pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ - } - else - rc = iso7816_put_data (app->slot, 0, 0xD3, - pinvalue, strlen (pinvalue)); - } + rc = iso7816_put_data (app->slot, 0, 0xD3, + pinvalue, strlen (pinvalue)); } else if (reset_mode) { - if (use_keypad) - { - rc = pincb (pincb_arg, _("|N|New PIN"), NULL); - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; - } - rc = iso7816_reset_retry_counter_kp (app->slot, 0x81, &pininfo); - pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ - } - else - { - rc = iso7816_reset_retry_counter (app->slot, 0x81, - pinvalue, strlen (pinvalue)); - if (!rc && !app->app_local->extcap.is_v2) - rc = iso7816_reset_retry_counter (app->slot, 0x82, - pinvalue, strlen (pinvalue)); - } + rc = iso7816_reset_retry_counter (app->slot, 0x81, + pinvalue, strlen (pinvalue)); + if (!rc && !app->app_local->extcap.is_v2) + rc = iso7816_reset_retry_counter (app->slot, 0x82, + pinvalue, strlen (pinvalue)); } else if (!app->app_local->extcap.is_v2) { @@ -2208,7 +2162,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, gpg_strerror (rc)); goto leave; } - rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno, + rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno, 0, &pininfo); /* Dismiss the prompt. */ pincb (pincb_arg, NULL, NULL); diff --git a/scd/iso7816.c b/scd/iso7816.c index 38ce79a..dd73fc6 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -307,16 +307,18 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder verification vector CHVNO. With PININFO non-NULL the keypad of the - reader will be used. */ + reader will be used. If IS_EXCHANGE is 0, a "change reference + data" is done, otherwise an "exchange reference data". */ gpg_error_t -iso7816_change_reference_data_kp (int slot, int chvno, +iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange, iso7816_pininfo_t *pininfo) { int sw; - sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, 0, chvno, - pininfo->mode, pininfo->minlen, pininfo->maxlen, - pininfo->padlen); + sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, + is_exchange ? 1 : 0, + chvno, pininfo->mode, pininfo->minlen, + pininfo->maxlen, pininfo->padlen); return map_sw (sw); } @@ -354,31 +356,6 @@ iso7816_change_reference_data (int slot, int chvno, gpg_error_t -iso7816_reset_retry_counter_kp (int slot, int chvno, - const char *newchv, size_t newchvlen, - iso7816_pininfo_t *pininfo) -{ - int sw; - - if (!newchv || !newchvlen ) - return gpg_error (GPG_ERR_INV_VALUE); - - /* FIXME: The keypad mode has not yet been tested. */ - if (pininfo && pininfo->mode) - sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER, - 2, chvno, newchvlen, newchv, - pininfo->mode, - pininfo->minlen, - pininfo->maxlen, - pininfo->padlen); - else - sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER, - 2, chvno, newchvlen, newchv); - return map_sw (sw); -} - - -gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno, const char *data, size_t datalen) { diff --git a/scd/iso7816.h b/scd/iso7816.h index 6d52702..d12855b 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -68,13 +68,10 @@ gpg_error_t iso7816_change_reference_data (int slot, int chvno, const char *oldchv, size_t oldchvlen, const char *newchv, size_t newchvlen); gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno, + int is_exchange, iso7816_pininfo_t *pininfo); gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, const char *newchv, size_t newchvlen); -gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno, - const char *newchv, - size_t newchvlen, - iso7816_pininfo_t *pininfo); gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno, const char *data, size_t datalen); commit b480f18e1de71766fc6b4fb3c50e157d0abffda5 Author: NIIBE Yutaka Date: Thu Dec 1 11:09:51 2011 +0900 scd: Fix pinpad input support (backport from master) * app-openpgp.c (do_change_pin): Fix pincb messages when use_keypad == 1. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 950968c..4bae875 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1982,7 +1982,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (chvno == 2) set_resetcode = 1; } - else if (chvno == 1 || chvno == 3) + else if (!use_keypad && (chvno == 1 || chvno == 3)) { char *promptbuf = NULL; const char *prompt; @@ -1997,7 +1997,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, } else prompt = _("||Please enter the PIN"); - rc = pincb (pincb_arg, prompt, use_keypad ? NULL : &oldpinvalue); + rc = pincb (pincb_arg, prompt, &oldpinvalue); xfree (promptbuf); promptbuf = NULL; if (rc) @@ -2007,7 +2007,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, goto leave; } - if (!use_keypad && strlen (oldpinvalue) < minlen) + if (strlen (oldpinvalue) < minlen) { log_info (_("PIN for CHV%d is too short;" " minimum length is %d\n"), chvno, minlen); @@ -2040,23 +2040,26 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, log_error (_("Reset Code not or not anymore available\n")); rc = gpg_error (GPG_ERR_BAD_PIN); goto leave; - } - - rc = pincb (pincb_arg, - _("||Please enter the Reset Code for the card"), - &resetcode); - if (rc) - { - log_info (_("PIN callback returned error: %s\n"), - gpg_strerror (rc)); - goto leave; } - if (strlen (resetcode) < minlen) + + if (!use_keypad) { - log_info (_("Reset Code is too short; minimum length is %d\n"), - minlen); - rc = gpg_error (GPG_ERR_BAD_PIN); - goto leave; + rc = pincb (pincb_arg, + _("||Please enter the Reset Code for the card"), + &resetcode); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } + if (strlen (resetcode) < minlen) + { + log_info (_("Reset Code is too short; minimum length is %d\n"), + minlen); + rc = gpg_error (GPG_ERR_BAD_PIN); + goto leave; + } } } else @@ -2090,18 +2093,36 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (resetcode) { - char *buffer; - - buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1); - if (!buffer) - rc = gpg_error_from_syserror (); + if (use_keypad) + { + rc = pincb (pincb_arg, + _("||Please enter the Reset Code for the card and New PIN"), + NULL); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } + rc = iso7816_reset_retry_counter_with_rc_kp (app->slot, 0x81, + &pininfo); + pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ + } else - { - strcpy (stpcpy (buffer, resetcode), pinvalue); - rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81, - buffer, strlen (buffer)); - wipememory (buffer, strlen (buffer)); - xfree (buffer); + { + char *buffer; + + buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1); + if (!buffer) + rc = gpg_error_from_syserror (); + else + { + strcpy (stpcpy (buffer, resetcode), pinvalue); + rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81, + buffer, strlen (buffer)); + wipememory (buffer, strlen (buffer)); + xfree (buffer); + } } } else if (set_resetcode) @@ -2110,18 +2131,48 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, { log_error (_("Reset Code is too short; minimum length is %d\n"), 8); rc = gpg_error (GPG_ERR_BAD_PIN); - } + } else - rc = iso7816_put_data (app->slot, 0, 0xD3, - pinvalue, strlen (pinvalue)); + { + if (use_keypad) + { + rc = pincb (pincb_arg, _("|RN|New Reset Code"), NULL); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } + rc = iso7816_put_data_kp (app->slot, 0xD3, &pininfo); + pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ + } + else + rc = iso7816_put_data (app->slot, 0, 0xD3, + pinvalue, strlen (pinvalue)); + } } else if (reset_mode) { - rc = iso7816_reset_retry_counter (app->slot, 0x81, - pinvalue, strlen (pinvalue)); - if (!rc && !app->app_local->extcap.is_v2) - rc = iso7816_reset_retry_counter (app->slot, 0x82, - pinvalue, strlen (pinvalue)); + if (use_keypad) + { + rc = pincb (pincb_arg, _("|N|New PIN"), NULL); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } + rc = iso7816_reset_retry_counter_kp (app->slot, 0x81, &pininfo); + pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ + } + else + { + rc = iso7816_reset_retry_counter (app->slot, 0x81, + pinvalue, strlen (pinvalue)); + if (!rc && !app->app_local->extcap.is_v2) + rc = iso7816_reset_retry_counter (app->slot, 0x82, + pinvalue, strlen (pinvalue)); + } } else if (!app->app_local->extcap.is_v2) { @@ -2147,6 +2198,16 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, if (use_keypad) { + rc = pincb (pincb_arg, + chvno == 3 ? + _("||Please enter the Admin PIN and New Admin PIN") : + _("||Please enter the PIN and New PIN"), NULL); + if (rc) + { + log_info (_("PIN callback returned error: %s\n"), + gpg_strerror (rc)); + goto leave; + } rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno, &pininfo); /* Dismiss the prompt. */ commit 7cd8b12e25b6daabedf6fdc2f350327e2116fc78 Author: NIIBE Yutaka Date: Tue Nov 29 11:59:32 2011 +0900 scd: PC/SC pinpad support (pinpad input for modify pass phrase). (backport) * iso7816.h (iso7816_change_reference_data_kp): Remove arguments of OLDCHV, OLDCHVLEN, NEWCHV, and NEWCHVLEN. * iso7816.c (iso7816_change_reference_data_kp): Call apdu_keypad_modify. (iso7816_change_reference_data): Don't call iso7816_change_reference_data_kp. * apdu.h (apdu_keypad_modify): New. * apdu.c (pcsc_keypad_modify, apdu_keypad_modify): New. (struct reader_table_s): New memeber function keypad_modify. (new_reader_slot, open_ct_reader, open_ccid_reader) (open_rapdu_reader): Initialize keypad_modify. * app-openpgp.c (do_change_pin): Handle keypad and call iso7816_change_reference_data_kp if it is the case. diff --git a/scd/apdu.c b/scd/apdu.c index a124d1c..4062b1e 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -111,6 +111,7 @@ struct reader_table_s { void (*dump_status_reader)(int); int (*set_progress_cb)(int, gcry_handler_progress_t, void*); int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *); + int (*keypad_modify)(int, int, int, int, int, struct pininfo_s *); struct { ccid_driver_t handle; @@ -317,6 +318,8 @@ static int check_pcsc_keypad (int slot, int command, int pin_mode, int pinlen_min, int pinlen_max, int pin_padlen); static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, struct pininfo_s *pininfo); +static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo); @@ -364,6 +367,7 @@ new_reader_slot (void) reader_table[reader].dump_status_reader = NULL; reader_table[reader].set_progress_cb = NULL; reader_table[reader].keypad_verify = pcsc_keypad_verify; + reader_table[reader].keypad_modify = pcsc_keypad_modify; reader_table[reader].used = 1; reader_table[reader].any_status = 0; @@ -651,6 +655,7 @@ open_ct_reader (int port) reader_table[reader].check_keypad = NULL; reader_table[reader].dump_status_reader = ct_dump_reader_status; reader_table[reader].keypad_verify = NULL; + reader_table[reader].keypad_modify = NULL; dump_reader_status (reader); return reader; @@ -2093,6 +2098,88 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, sw = (result[resultlen-2] << 8) | result[resultlen-1]; return sw; } + + +#define PIN_MODIFY_STRUCTURE_SIZE 28 +static int +pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo) +{ + int sw; + unsigned char *pin_modify; + unsigned long len = PIN_MODIFY_STRUCTURE_SIZE; + unsigned char result[2]; + size_t resultlen = 2; + + if (!reader_table[slot].atrlen + && (sw = reset_pcsc_reader (slot))) + return sw; + + if (pininfo->mode != 1) + return SW_NOT_SUPPORTED; + + if (pininfo->padlen != 0) + return SW_NOT_SUPPORTED; + + if (!pininfo->minlen) + pininfo->minlen = 1; + if (!pininfo->maxlen) + pininfo->maxlen = 25; + + /* Note that the 25 is the maximum value the SPR532 allows. */ + if (pininfo->minlen < 1 || pininfo->minlen > 25 + || pininfo->maxlen < 1 || pininfo->maxlen > 25 + || pininfo->minlen > pininfo->maxlen) + return SW_HOST_INV_VALUE; + + pin_modify = xtrymalloc (len); + if (!pin_modify) + return SW_HOST_OUT_OF_CORE; + + pin_modify[0] = 0x00; /* bTimerOut */ + pin_modify[1] = 0x00; /* bTimerOut2 */ + pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ + pin_modify[3] = 0x00; /* bmPINBlockString */ + pin_modify[4] = 0x00; /* bmPINLengthFormat */ + pin_modify[5] = 0x00; /* bInsertionOffsetOld */ + pin_modify[6] = 0x00; /* bInsertionOffsetNew */ + pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */ + pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */ + pin_modify[9] = 0x03; /* bConfirmPIN + * 0x00: new PIN once + * 0x01: new PIN twice (confirmation) + * 0x02: old PIN and new PIN once + * 0x03: old PIN and new PIN twice (confirmation) + */ + pin_modify[10] = 0x02; /* bEntryValidationCondition: Validation key pressed */ + if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen) + pin_modify[10] |= 0x01; /* Max size reached. */ + pin_modify[11] = 0xff; /* bNumberMessage: Default */ + pin_modify[12] = 0x09; /* wLangId: 0x0409: US English */ + pin_modify[13] = 0x04; /* wLangId: 0x0409: US English */ + pin_modify[14] = 0x00; /* bMsgIndex1 */ + pin_modify[15] = 0x00; /* bMsgIndex2 */ + pin_modify[16] = 0x00; /* bMsgIndex3 */ + pin_modify[17] = 0x00; /* bTeoPrologue[0] */ + pin_modify[18] = 0x00; /* bTeoPrologue[1] */ + pin_modify[19] = 0x00; /* bTeoPrologue[2] */ + pin_modify[20] = 0x04; /* ulDataLength */ + pin_modify[21] = 0x00; /* ulDataLength */ + pin_modify[22] = 0x00; /* ulDataLength */ + pin_modify[23] = 0x00; /* ulDataLength */ + pin_modify[24] = class; /* abData[0] */ + pin_modify[25] = ins; /* abData[1] */ + pin_modify[26] = p0; /* abData[2] */ + pin_modify[27] = p1; /* abData[3] */ + + sw = control_pcsc (slot, reader_table[slot].pcsc.modify_ioctl, + pin_modify, len, result, &resultlen); + xfree (pin_modify); + if (sw || resultlen < 2) + return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE; + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + return sw; +} #ifdef HAVE_LIBUSB /* @@ -2304,6 +2391,7 @@ open_ccid_reader (const char *portstr) reader_table[slot].dump_status_reader = dump_ccid_reader_status; reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader; reader_table[slot].keypad_verify = ccid_keypad_verify; + reader_table[slot].keypad_modify = NULL; /* Our CCID reader code does not support T=0 at all, thus reset the flag. */ reader_table[slot].is_t0 = 0; @@ -2597,6 +2685,7 @@ open_rapdu_reader (int portno, reader_table[slot].check_keypad = NULL; reader_table[slot].dump_status_reader = NULL; reader_table[slot].keypad_verify = NULL; + reader_table[slot].keypad_modify = NULL; dump_reader_status (slot); rapdu_msg_release (msg); @@ -3233,6 +3322,28 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode, } +int +apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + struct pininfo_s pininfo; + + pininfo.mode = pin_mode; + pininfo.minlen = pinlen_min; + pininfo.maxlen = pinlen_max; + pininfo.padlen = pin_padlen; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if (reader_table[slot].keypad_modify) + return reader_table[slot].keypad_modify (slot, class, ins, p0, p1, + &pininfo); + else + return SW_HOST_NOT_SUPPORTED; +} + + /* Dispatcher for the actual send_apdu function. Note, that this function should be called in locked state. */ static int diff --git a/scd/apdu.h b/scd/apdu.h index 5a48f3a..94d7449 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -117,6 +117,9 @@ int apdu_check_keypad (int slot, int command, int pin_mode, int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode, int pinlen_min, int pinlen_max, int pin_padlen); +int apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, + int pin_mode, int pinlen_min, int pinlen_max, + int pin_padlen); int apdu_send_simple (int slot, int extended_mode, int class, int ins, int p0, int p1, int lc, const char *data); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 28ceeac..950968c 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1912,11 +1912,17 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int chvno = atoi (chvnostr); char *resetcode = NULL; char *oldpinvalue = NULL; - char *pinvalue; + char *pinvalue = NULL; int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET); int set_resetcode = 0; + iso7816_pininfo_t pininfo; + int use_keypad = 0; + int minlen = 6; (void)ctrl; + memset (&pininfo, 0, sizeof pininfo); + pininfo.mode = 1; + pininfo.minlen = minlen; if (reset_mode && chvno == 3) { @@ -1960,6 +1966,11 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, { /* Version 2 cards. */ + if (!opt.disable_keypad + && !iso7816_check_keypad (app->slot, + ISO7816_CHANGE_REFERENCE_DATA, &pininfo)) + use_keypad = 1; + if (reset_mode) { /* To reset a PIN the Admin PIN is required. */ @@ -1973,12 +1984,12 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, } else if (chvno == 1 || chvno == 3) { - int minlen = (chvno ==3)? 8 : 6; char *promptbuf = NULL; const char *prompt; if (chvno == 3) { + minlen = 8; rc = build_enter_admin_pin_prompt (app, &promptbuf); if (rc) goto leave; @@ -1986,7 +1997,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, } else prompt = _("||Please enter the PIN"); - rc = pincb (pincb_arg, prompt, &oldpinvalue); + rc = pincb (pincb_arg, prompt, use_keypad ? NULL : &oldpinvalue); xfree (promptbuf); promptbuf = NULL; if (rc) @@ -1996,7 +2007,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, goto leave; } - if (strlen (oldpinvalue) < minlen) + if (!use_keypad && strlen (oldpinvalue) < minlen) { log_info (_("PIN for CHV%d is too short;" " minimum length is %d\n"), chvno, minlen); @@ -2012,8 +2023,8 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, unsigned char *value; size_t valuelen; int remaining; - int minlen = 8; + minlen = 8; relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL); if (!relptr || valuelen < 7) { @@ -2060,17 +2071,20 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, else app->did_chv1 = app->did_chv2 = 0; - /* TRANSLATORS: Do not translate the "|*|" prefixes but - keep it at the start of the string. We need this elsewhere - to get some infos on the string. */ - rc = pincb (pincb_arg, - set_resetcode? _("|RN|New Reset Code") : - chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), - &pinvalue); - if (rc) + if (!use_keypad) { - log_error (_("error getting new PIN: %s\n"), gpg_strerror (rc)); - goto leave; + /* TRANSLATORS: Do not translate the "|*|" prefixes but + keep it at the start of the string. We need this elsewhere + to get some infos on the string. */ + rc = pincb (pincb_arg, + set_resetcode? _("|RN|New Reset Code") : + chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), + &pinvalue); + if (rc) + { + log_error (_("error getting new PIN: %s\n"), gpg_strerror (rc)); + goto leave; + } } @@ -2130,10 +2144,18 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, { /* Version 2 cards. */ assert (chvno == 1 || chvno == 3); - - rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, - oldpinvalue, strlen (oldpinvalue), - pinvalue, strlen (pinvalue)); + + if (use_keypad) + { + rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno, + &pininfo); + /* Dismiss the prompt. */ + pincb (pincb_arg, NULL, NULL); + } + else + rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, + oldpinvalue, strlen (oldpinvalue), + pinvalue, strlen (pinvalue)); } if (pinvalue) diff --git a/scd/iso7816.c b/scd/iso7816.c index 33382f2..38ce79a 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -306,16 +306,29 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) } /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder + verification vector CHVNO. With PININFO non-NULL the keypad of the + reader will be used. */ +gpg_error_t +iso7816_change_reference_data_kp (int slot, int chvno, + iso7816_pininfo_t *pininfo) +{ + int sw; + + sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, 0, chvno, + pininfo->mode, pininfo->minlen, pininfo->maxlen, + pininfo->padlen); + return map_sw (sw); +} + +/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN 0), a "change reference data" is done, otherwise an "exchange reference data". The new reference data is expected in NEWCHV of - length NEWCHVLEN. With PININFO non-NULL the keypad of the reader - will be used. */ + length NEWCHVLEN. */ gpg_error_t -iso7816_change_reference_data_kp (int slot, int chvno, - const char *oldchv, size_t oldchvlen, - const char *newchv, size_t newchvlen, - iso7816_pininfo_t *pininfo) +iso7816_change_reference_data (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen) { int sw; char *buf; @@ -332,35 +345,13 @@ iso7816_change_reference_data_kp (int slot, int chvno, memcpy (buf, oldchv, oldchvlen); memcpy (buf+oldchvlen, newchv, newchvlen); - if (pininfo && pininfo->mode) - sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, - oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf, - pininfo->mode, - pininfo->minlen, - pininfo->maxlen, - pininfo->padlen); - else - sw = apdu_send_simple (slot, 0, 0x00, CMD_CHANGE_REFERENCE_DATA, - oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf); + sw = apdu_send_simple (slot, 0, 0x00, CMD_CHANGE_REFERENCE_DATA, + oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf); xfree (buf); return map_sw (sw); } -/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder - verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN - 0), a "change reference data" is done, otherwise an "exchange - reference data". The new reference data is expected in NEWCHV of - length NEWCHVLEN. */ -gpg_error_t -iso7816_change_reference_data (int slot, int chvno, - const char *oldchv, size_t oldchvlen, - const char *newchv, size_t newchvlen) -{ - return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen, - newchv, newchvlen, NULL); -} - gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno, diff --git a/scd/iso7816.h b/scd/iso7816.h index 6af4701..6d52702 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -68,9 +68,7 @@ gpg_error_t iso7816_change_reference_data (int slot, int chvno, const char *oldchv, size_t oldchvlen, const char *newchv, size_t newchvlen); gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno, - const char *oldchv, size_t oldchvlen, - const char *newchv, size_t newchvlen, - iso7816_pininfo_t *pininfo); + iso7816_pininfo_t *pininfo); gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, const char *newchv, size_t newchvlen); gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno, commit 6dc187f2dbf3b5e7322fa40c7e085da12ad373d2 Author: NIIBE Yutaka Date: Mon Nov 28 16:16:38 2011 +0900 scd: PC/SC pinpad support. (Backported from master.) * iso7816.h (iso7816_verify_kp): Remove arguments of CHV and CHVLEN. * iso7816.c (iso7816_verify_kp): Call apdu_keypad_verify. Only handle thecase with PININFO. (iso7816_verify): Call apdu_send_simple. * app-openpgp.c (verify_a_chv, verify_chv3): Follow the change of iso7816_verify_kp. * app-nks.c (verify_pin): Likewise. * app-dinsig.c (verify_pin): Likewise. * apdu.c: Include "iso7816.h". (struct reader_table_s): New memeber function keypad_verify. Add fields verify_ioctl and modify_ioctl in pcsc. (CM_IOCTL_GET_FEATURE_REQUEST, FEATURE_VERIFY_PIN_DIRECT) (FEATURE_MODIFY_PIN_DIRECT): New. (pcsc_control): New. (control_pcsc_direct, control_pcsc_wrapped, control_pcsc) (check_pcsc_keypad, pcsc_keypad_verify): New. (ccid_keypad_verify, apdu_keypad_verify): New. (new_reader_slot): Initialize with check_pcsc_keypad, pcsc_keypad_verify, verify_ioctl and modify_ioctl. (open_ct_reader): Initialize keypad_verify with NULL. (open_ccid_reader): Initialize keypad_verify. (open_rapdu_reader): Initialize keypad_verify with NULL. (apdu_open_reader): Initialize pcsc_control. * pcsc-wrapper.c (load_pcsc_driver): Initialize pcsc_control. (handle_control): New. (main): Handle the case 6 of handle_control. diff --git a/scd/apdu.c b/scd/apdu.c index 541dd05..a124d1c 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -61,6 +61,7 @@ #include "apdu.h" #include "ccid-driver.h" +#include "iso7816.h" /* Due to conflicting use of threading libraries we usually can't link @@ -109,6 +110,7 @@ struct reader_table_s { int (*check_keypad)(int, int, int, int, int, int); void (*dump_status_reader)(int); int (*set_progress_cb)(int, gcry_handler_progress_t, void*); + int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *); struct { ccid_driver_t handle; @@ -117,6 +119,8 @@ struct reader_table_s { unsigned long context; unsigned long card; unsigned long protocol; + unsigned long verify_ioctl; + unsigned long modify_ioctl; #ifdef NEED_PCSC_WRAPPER int req_fd; int rsp_fd; @@ -218,6 +222,11 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn); #define PCSC_E_READER_UNAVAILABLE 0x80100017 #define PCSC_W_REMOVED_CARD 0x80100069 +#define CM_IOCTL_GET_FEATURE_REQUEST (0x42000000 + 3400) +#define FEATURE_VERIFY_PIN_DIRECT 0x06 +#define FEATURE_MODIFY_PIN_DIRECT 0x07 + + /* The PC/SC error is defined as a long as per specs. Due to left shifts bit 31 will get sign extended. We use this mask to fix it. */ @@ -286,6 +295,13 @@ long (* DLSTDCALL pcsc_transmit) (unsigned long card, unsigned long *recv_len); long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, unsigned long timeout); +long (* DLSTDCALL pcsc_control) (unsigned long card, + unsigned long control_code, + const void *send_buffer, + unsigned long send_len, + void *recv_buffer, + unsigned long recv_len, + unsigned long *bytes_returned); /* Flag set if PC/SC returned the no-service error. */ static int pcsc_no_service; @@ -297,6 +313,10 @@ static int reset_pcsc_reader (int slot); static int apdu_get_status_internal (int slot, int hang, int no_atr_reset, unsigned int *status, unsigned int *changed); +static int check_pcsc_keypad (int slot, int command, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen); +static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo); @@ -340,9 +360,10 @@ new_reader_slot (void) reader_table[reader].reset_reader = NULL; reader_table[reader].get_status_reader = NULL; reader_table[reader].send_apdu_reader = NULL; - reader_table[reader].check_keypad = NULL; + reader_table[reader].check_keypad = check_pcsc_keypad; reader_table[reader].dump_status_reader = NULL; reader_table[reader].set_progress_cb = NULL; + reader_table[reader].keypad_verify = pcsc_keypad_verify; reader_table[reader].used = 1; reader_table[reader].any_status = 0; @@ -353,6 +374,8 @@ new_reader_slot (void) reader_table[reader].pcsc.rsp_fd = -1; reader_table[reader].pcsc.pid = (pid_t)(-1); #endif + reader_table[reader].pcsc.verify_ioctl = 0; + reader_table[reader].pcsc.modify_ioctl = 0; return reader; } @@ -627,6 +650,7 @@ open_ct_reader (int port) reader_table[reader].send_apdu_reader = ct_send_apdu; reader_table[reader].check_keypad = NULL; reader_table[reader].dump_status_reader = ct_dump_reader_status; + reader_table[reader].keypad_verify = NULL; dump_reader_status (reader); return reader; @@ -1154,6 +1178,150 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, #ifndef NEED_PCSC_WRAPPER static int +control_pcsc_direct (int slot, unsigned long ioctl_code, + const unsigned char *cntlbuf, size_t len, + unsigned char *buffer, size_t *buflen) +{ + long err; + + err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code, + cntlbuf, len, buffer, *buflen, buflen); + if (err) + { + log_error ("pcsc_control failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return pcsc_error_to_sw (err); + } + + return 0; +} +#endif /*!NEED_PCSC_WRAPPER*/ + + +#ifdef NEED_PCSC_WRAPPER +static int +control_pcsc_wrapped (int slot, unsigned long ioctl_code, + const unsigned char *cntlbuf, size_t len, + unsigned char *buffer, size_t *buflen) +{ + long err = PCSC_E_NOT_TRANSACTED; + reader_table_t slotp; + unsigned char msgbuf[9]; + int i, n; + size_t full_len; + + slotp = reader_table + slot; + + msgbuf[0] = 0x06; /* CONTROL command. */ + msgbuf[1] = ((len + 4) >> 24); + msgbuf[2] = ((len + 4) >> 16); + msgbuf[3] = ((len + 4) >> 8); + msgbuf[4] = ((len + 4) ); + msgbuf[5] = (ioctl_code >> 24); + msgbuf[6] = (ioctl_code >> 16); + msgbuf[7] = (ioctl_code >> 8); + msgbuf[8] = (ioctl_code ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 9) + || writen (slotp->pcsc.req_fd, cntlbuf, len)) + { + log_error ("error sending PC/SC CONTROL request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC CONTROL response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16) + | (msgbuf[7] << 8 ) | msgbuf[8]); + if (err) + { + log_error ("pcsc_control failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return pcsc_error_to_sw (err); + } + + full_len = len; + + n = *buflen < len ? *buflen : len; + if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) + { + log_error ("error receiving PC/SC CONTROL response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + *buflen = n; + + full_len -= len; + if (full_len) + { + log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); + err = PCSC_E_INVALID_VALUE; + } + /* We need to read any rest of the response, to keep the + protocol running. */ + while (full_len) + { + unsigned char dummybuf[128]; + + n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf); + if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n) + { + log_error ("error receiving PC/SC CONTROL response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + full_len -= n; + } + + if (!err) + return 0; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return pcsc_error_to_sw (err); +} +#endif /*NEED_PCSC_WRAPPER*/ + + + +/* Do some control with the value of IOCTL_CODE to the card inserted + to SLOT. Input buffer is specified by CNTLBUF of length LEN. + Output buffer is specified by BUFFER of length *BUFLEN, and the + actual output size will be stored at BUFLEN. Returns: A status word. + This routine is used for PIN pad input support. */ +static int +control_pcsc (int slot, unsigned long ioctl_code, + const unsigned char *cntlbuf, size_t len, + unsigned char *buffer, size_t *buflen) +{ +#ifdef NEED_PCSC_WRAPPER + return control_pcsc_wrapped (slot, ioctl_code, cntlbuf, len, buffer, buflen); +#else + return control_pcsc_direct (slot, ioctl_code, cntlbuf, len, buffer, buflen); +#endif +} + + +#ifndef NEED_PCSC_WRAPPER +static int close_pcsc_reader_direct (int slot) { pcsc_release_context (reader_table[slot].pcsc.context); @@ -1793,6 +1961,138 @@ open_pcsc_reader (const char *portstr) } +/* Check whether the reader supports the ISO command code COMMAND + on the keypad. Return 0 on success. */ +static int +check_pcsc_keypad (int slot, int command, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + unsigned char buf[256]; + size_t len = 256; + int sw; + + (void)pin_mode; + (void)pinlen_min; + (void)pinlen_max; + (void)pin_padlen; + + check_again: + if (command == ISO7816_VERIFY) + { + if (reader_table[slot].pcsc.verify_ioctl == (unsigned long)-1) + return SW_NOT_SUPPORTED; + else if (reader_table[slot].pcsc.verify_ioctl != 0) + return 0; /* Success */ + } + else if (command == ISO7816_CHANGE_REFERENCE_DATA) + { + if (reader_table[slot].pcsc.modify_ioctl == (unsigned long)-1) + return SW_NOT_SUPPORTED; + else if (reader_table[slot].pcsc.modify_ioctl != 0) + return 0; /* Success */ + } + else + return SW_NOT_SUPPORTED; + + reader_table[slot].pcsc.verify_ioctl = (unsigned long)-1; + reader_table[slot].pcsc.modify_ioctl = (unsigned long)-1; + + sw = control_pcsc (slot, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, buf, &len); + if (sw) + return SW_NOT_SUPPORTED; + else + { + unsigned char *p = buf; + + while (p < buf + len) + { + unsigned char code = *p++; + + p++; /* Skip length */ + if (code == FEATURE_VERIFY_PIN_DIRECT) + reader_table[slot].pcsc.verify_ioctl + = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + else if (code == FEATURE_MODIFY_PIN_DIRECT) + reader_table[slot].pcsc.modify_ioctl + = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + } + } + + goto check_again; +} + + +#define PIN_VERIFY_STRUCTURE_SIZE 23 +static int +pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo) +{ + int sw; + unsigned char *pin_verify; + unsigned long len = PIN_VERIFY_STRUCTURE_SIZE; + unsigned char result[2]; + size_t resultlen = 2; + + if (!reader_table[slot].atrlen + && (sw = reset_pcsc_reader (slot))) + return sw; + + if (pininfo->mode != 1) + return SW_NOT_SUPPORTED; + + if (pininfo->padlen != 0) + return SW_NOT_SUPPORTED; + + if (!pininfo->minlen) + pininfo->minlen = 1; + if (!pininfo->maxlen) + pininfo->maxlen = 25; + + /* Note that the 25 is the maximum value the SPR532 allows. */ + if (pininfo->minlen < 1 || pininfo->minlen > 25 + || pininfo->maxlen < 1 || pininfo->maxlen > 25 + || pininfo->minlen > pininfo->maxlen) + return SW_HOST_INV_VALUE; + + pin_verify = xtrymalloc (len); + if (!pin_verify) + return SW_HOST_OUT_OF_CORE; + + pin_verify[0] = 0x00; /* bTimerOut */ + pin_verify[1] = 0x00; /* bTimerOut2 */ + pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ + pin_verify[3] = 0x00; /* bmPINBlockString */ + pin_verify[4] = 0x00; /* bmPINLengthFormat */ + pin_verify[5] = pininfo->maxlen; /* wPINMaxExtraDigit */ + pin_verify[6] = pininfo->minlen; /* wPINMaxExtraDigit */ + pin_verify[7] = 0x02; /* bEntryValidationCondition: Validation key pressed */ + if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen) + pin_verify[7] |= 0x01; /* Max size reached. */ + pin_verify[8] = 0xff; /* bNumberMessage: Default */ + pin_verify[9] = 0x09; /* wLangId: 0x0409: US English */ + pin_verify[10] = 0x04; /* wLangId: 0x0409: US English */ + pin_verify[11] = 0x00; /* bMsgIndex */ + pin_verify[12] = 0x00; /* bTeoPrologue[0] */ + pin_verify[13] = 0x00; /* bTeoPrologue[1] */ + pin_verify[14] = 0x00; /* bTeoPrologue[2] */ + pin_verify[15] = 0x04; /* ulDataLength */ + pin_verify[16] = 0x00; /* ulDataLength */ + pin_verify[17] = 0x00; /* ulDataLength */ + pin_verify[18] = 0x00; /* ulDataLength */ + pin_verify[19] = class; /* abData[0] */ + pin_verify[20] = ins; /* abData[1] */ + pin_verify[21] = p0; /* abData[2] */ + pin_verify[22] = p1; /* abData[3] */ + + sw = control_pcsc (slot, reader_table[slot].pcsc.verify_ioctl, + pin_verify, len, result, &resultlen); + xfree (pin_verify); + if (sw || resultlen < 2) + return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE; + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + return sw; +} #ifdef HAVE_LIBUSB /* @@ -1930,6 +2230,35 @@ check_ccid_keypad (int slot, int command, int pin_mode, } +static int +ccid_keypad_verify (int slot, int class, int ins, int p0, int p1, + struct pininfo_s *pininfo) +{ + unsigned char apdu[4]; + int err, sw; + unsigned char result[2]; + size_t resultlen = 2; + + apdu[0] = class; + apdu[1] = ins; + apdu[2] = p0; + apdu[3] = p1; + err = ccid_transceive_secure (reader_table[slot].ccid.handle, + apdu, sizeof apdu, + pininfo->mode, pininfo->minlen, pininfo->maxlen, + pininfo->padlen, + result, 2, &resultlen); + if (err) + return err; + + if (resultlen < 2) + return SW_HOST_INCOMPLETE_CARD_RESPONSE; + + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + return sw; +} + + /* Open the reader and try to read an ATR. */ static int open_ccid_reader (const char *portstr) @@ -1974,6 +2303,7 @@ open_ccid_reader (const char *portstr) reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].dump_status_reader = dump_ccid_reader_status; reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader; + reader_table[slot].keypad_verify = ccid_keypad_verify; /* Our CCID reader code does not support T=0 at all, thus reset the flag. */ reader_table[slot].is_t0 = 0; @@ -2266,6 +2596,7 @@ open_rapdu_reader (int portno, reader_table[slot].send_apdu_reader = my_rapdu_send_apdu; reader_table[slot].check_keypad = NULL; reader_table[slot].dump_status_reader = NULL; + reader_table[slot].keypad_verify = NULL; dump_reader_status (slot); rapdu_msg_release (msg); @@ -2433,6 +2764,7 @@ apdu_open_reader (const char *portstr, int *r_no_service) pcsc_end_transaction = dlsym (handle, "SCardEndTransaction"); pcsc_transmit = dlsym (handle, "SCardTransmit"); pcsc_set_timeout = dlsym (handle, "SCardSetTimeout"); + pcsc_control = dlsym (handle, "SCardControl"); if (!pcsc_establish_context || !pcsc_release_context @@ -2445,12 +2777,13 @@ apdu_open_reader (const char *portstr, int *r_no_service) || !pcsc_begin_transaction || !pcsc_end_transaction || !pcsc_transmit + || !pcsc_control /* || !pcsc_set_timeout */) { /* Note that set_timeout is currently not used and also not available under Windows. */ log_error ("apdu_open_reader: invalid PC/SC driver " - "(%d%d%d%d%d%d%d%d%d%d%d%d)\n", + "(%d%d%d%d%d%d%d%d%d%d%d%d%d)\n", !!pcsc_establish_context, !!pcsc_release_context, !!pcsc_list_readers, @@ -2462,7 +2795,8 @@ apdu_open_reader (const char *portstr, int *r_no_service) !!pcsc_begin_transaction, !!pcsc_end_transaction, !!pcsc_transmit, - !!pcsc_set_timeout ); + !!pcsc_set_timeout, + !!pcsc_control ); dlclose (handle); return -1; } @@ -2877,6 +3211,28 @@ apdu_check_keypad (int slot, int command, int pin_mode, } +int +apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + struct pininfo_s pininfo; + + pininfo.mode = pin_mode; + pininfo.minlen = pinlen_min; + pininfo.maxlen = pinlen_max; + pininfo.padlen = pin_padlen; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if (reader_table[slot].keypad_verify) + return reader_table[slot].keypad_verify (slot, class, ins, p0, p1, + &pininfo); + else + return SW_HOST_NOT_SUPPORTED; +} + + /* Dispatcher for the actual send_apdu function. Note, that this function should be called in locked state. */ static int diff --git a/scd/apdu.h b/scd/apdu.h index d79f8b4..5a48f3a 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -114,6 +114,9 @@ int apdu_get_status (int slot, int hang, unsigned int *status, unsigned int *changed); int apdu_check_keypad (int slot, int command, int pin_mode, int pinlen_min, int pinlen_max, int pin_padlen); +int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, + int pin_mode, int pinlen_min, int pinlen_max, + int pin_padlen); int apdu_send_simple (int slot, int extended_mode, int class, int ins, int p0, int p1, int lc, const char *data); diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 46e9a6a..697cdf6 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -304,7 +304,7 @@ verify_pin (app_t app, gpg_strerror (rc)); return rc; } - rc = iso7816_verify_kp (app->slot, 0x81, "", 0, &pininfo); + rc = iso7816_verify_kp (app->slot, 0x81, &pininfo); /* Dismiss the prompt. */ pincb (pincb_arg, NULL, NULL); } diff --git a/scd/app-nks.c b/scd/app-nks.c index 076b913..b51e1fc 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -802,8 +802,8 @@ verify_pin (app_t app, int pwid, const char *desc, gpg_strerror (rc)); return rc; } - - rc = iso7816_verify_kp (app->slot, pwid, "", 0, &pininfo); + + rc = iso7816_verify_kp (app->slot, pwid, &pininfo); pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ } else diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 8a71caf..28ceeac 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1550,7 +1550,7 @@ verify_a_chv (app_t app, gpg_strerror (rc)); return rc; } - rc = iso7816_verify_kp (app->slot, 0x80+chvno, "", 0, &pininfo); + rc = iso7816_verify_kp (app->slot, 0x80+chvno, &pininfo); /* Dismiss the prompt. */ pincb (pincb_arg, NULL, NULL); @@ -1730,7 +1730,7 @@ verify_chv3 (app_t app, gpg_strerror (rc)); return rc; } - rc = iso7816_verify_kp (app->slot, 0x83, "", 0, &pininfo); + rc = iso7816_verify_kp (app->slot, 0x83, &pininfo); /* Dismiss the prompt. */ pincb (pincb_arg, NULL, NULL); } diff --git a/scd/iso7816.c b/scd/iso7816.c index e3f2c1b..33382f2 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -281,22 +281,16 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo) /* Perform a VERIFY command on SLOT using the card holder verification - vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL - the keypad of the reader will be used. Returns 0 on success. */ + vector CHVNO. With PININFO non-NULL the keypad of the reader will + be used. Returns 0 on success. */ gpg_error_t -iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen, - iso7816_pininfo_t *pininfo) +iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo) { int sw; - if (pininfo && pininfo->mode) - sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv, - pininfo->mode, - pininfo->minlen, - pininfo->maxlen, - pininfo->padlen); - else - sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv); + sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, + pininfo->mode, pininfo->minlen, pininfo->maxlen, + pininfo->padlen); return map_sw (sw); } @@ -305,7 +299,10 @@ iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen, gpg_error_t iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) { - return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL); + int sw; + + sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv); + return map_sw (sw); } /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder diff --git a/scd/iso7816.h b/scd/iso7816.h index 8519712..6af4701 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -63,9 +63,7 @@ gpg_error_t iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo); gpg_error_t iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen); -gpg_error_t iso7816_verify_kp (int slot, - int chvno, const char *chv, size_t chvlen, - iso7816_pininfo_t *pininfo); +gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo); gpg_error_t iso7816_change_reference_data (int slot, int chvno, const char *oldchv, size_t oldchvlen, const char *newchv, size_t newchvlen); diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c index ee974ac..73b25f4 100644 --- a/scd/pcsc-wrapper.c +++ b/scd/pcsc-wrapper.c @@ -178,6 +178,13 @@ long (* pcsc_transmit) (unsigned long card, unsigned long *recv_len); long (* pcsc_set_timeout) (unsigned long context, unsigned long timeout); +long (* pcsc_control) (unsigned long card, + unsigned long control_code, + const void *send_buffer, + unsigned long send_len, + void *recv_buffer, + unsigned long recv_len, + unsigned long *bytes_returned); @@ -335,6 +342,7 @@ load_pcsc_driver (const char *libname) pcsc_end_transaction = dlsym (handle, "SCardEndTransaction"); pcsc_transmit = dlsym (handle, "SCardTransmit"); pcsc_set_timeout = dlsym (handle, "SCardSetTimeout"); + pcsc_control = dlsym (handle, "SCardControl"); if (!pcsc_establish_context || !pcsc_release_context @@ -347,13 +355,14 @@ load_pcsc_driver (const char *libname) || !pcsc_begin_transaction || !pcsc_end_transaction || !pcsc_transmit + || !pcsc_control /* || !pcsc_set_timeout */) { /* Note that set_timeout is currently not used and also not available under Windows. */ fprintf (stderr, "apdu_open_reader: invalid PC/SC driver " - "(%d%d%d%d%d%d%d%d%d%d%d%d)\n", + "(%d%d%d%d%d%d%d%d%d%d%d%d%d)\n", !!pcsc_establish_context, !!pcsc_release_context, !!pcsc_list_readers, @@ -365,7 +374,8 @@ load_pcsc_driver (const char *libname) !!pcsc_begin_transaction, !!pcsc_end_transaction, !!pcsc_transmit, - !!pcsc_set_timeout ); + !!pcsc_set_timeout, + !!pcsc_control ); dlclose (handle); exit (1); } @@ -720,6 +730,38 @@ handle_transmit (unsigned char *argbuf, size_t arglen) } +/* Handle a control request. The argument is expected to be a buffer + which contains CONTROL_CODE (4-byte) and INPUT_BYTES. + */ +static void +handle_control (unsigned char *argbuf, size_t arglen) +{ + long err; + unsigned long ioctl_code; + unsigned long recv_len = 1024; + unsigned char buffer[1024]; + + if (arglen < 4) + bad_request ("CONTROL"); + + ioctl_code = (argbuf[0] << 24) | (argbuf[1] << 16) | (argbuf[2] << 8) | argbuf[3]; + argbuf += 4; + arglen -= 4; + + recv_len = sizeof (buffer); + err = pcsc_control (pcsc_card, ioctl_code, argbuf, arglen, + buffer, recv_len, &recv_len); + if (err) + { + if (verbose) + fprintf (stderr, PGM": pcsc_control failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + request_failed (err); + return; + } + request_succeeded (buffer, recv_len); +} + static void print_version (int with_help) @@ -831,6 +873,10 @@ main (int argc, char **argv) handle_reset (argbuffer, arglen); break; + case 6: + handle_control (argbuffer, arglen); + break; + default: fprintf (stderr, PGM ": invalid request 0x%02X\n", c); exit (1); ----------------------------------------------------------------------- Summary of changes: scd/apdu.c | 497 +++++++++++++++++++++++++++++++++++++++++++++++++++- scd/apdu.h | 6 + scd/app-dinsig.c | 2 +- scd/app-nks.c | 4 +- scd/app-openpgp.c | 133 +++++++++----- scd/app.c | 8 +- scd/ccid-driver.c | 134 +++++++++++--- scd/iso7816.c | 107 ++++------- scd/iso7816.h | 13 +- scd/pcsc-wrapper.c | 50 +++++- 10 files changed, 786 insertions(+), 168 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jun 18 10:14:23 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Mon, 18 Jun 2012 10:14:23 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, updated. gnupg-2.0.19-28-gff40c05 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been updated via ff40c05e8b563471278cb7c92df0310bc5967749 (commit) via 7f3ea446609355c96e90f0b6beb057daa1152643 (commit) from 29b431fcf97a9e615d34a7a40e570e63834b360a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ff40c05e8b563471278cb7c92df0310bc5967749 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 diff --git a/scd/apdu.c b/scd/apdu.c index 07df9fe..a343307 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -367,7 +367,8 @@ unlock_slot (int slot) /* Find an unused reader slot for PORTSTR and put it into the reader - table. Return -1 on error or the index into the reader table. */ + table. Return -1 on error or the index into the reader table. + Acquire slot's lock on successful return. Caller needs to unlock it. */ static int new_reader_slot (void) { @@ -394,6 +395,11 @@ new_reader_slot (void) reader_table[reader].lock_initialized = 1; } #endif /*USE_GNU_PTH*/ + if (lock_slot (reader)) + { + log_error ("error locking mutex: %s\n", strerror (errno)); + return -1; + } reader_table[reader].connect_card = NULL; reader_table[reader].disconnect_card = NULL; reader_table[reader].close_reader = NULL; @@ -675,6 +681,7 @@ open_ct_reader (int port) log_error ("apdu_open_ct_reader failed on port %d: %s\n", port, ct_error_string (rc)); reader_table[reader].used = 0; + unlock_slot (reader); return -1; } @@ -696,6 +703,7 @@ open_ct_reader (int port) reader_table[reader].keypad_modify = NULL; dump_reader_status (reader); + unlock_slot (reader); return reader; } @@ -1701,6 +1709,7 @@ open_pcsc_reader_direct (const char *portstr) log_error ("pcsc_establish_context failed: %s (0x%lx)\n", pcsc_error_string (err), err); reader_table[slot].used = 0; + unlock_slot (slot); if (err == 0x8010001d) pcsc_no_service = 1; return -1; @@ -1717,6 +1726,7 @@ open_pcsc_reader_direct (const char *portstr) log_error ("error allocating memory for reader list\n"); pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; + unlock_slot (slot); return -1 /*SW_HOST_OUT_OF_CORE*/; } err = pcsc_list_readers (reader_table[slot].pcsc.context, @@ -1729,6 +1739,7 @@ open_pcsc_reader_direct (const char *portstr) pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; xfree (list); + unlock_slot (slot); return -1; } @@ -1755,6 +1766,7 @@ open_pcsc_reader_direct (const char *portstr) log_error ("error allocating memory for reader name\n"); pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; + unlock_slot (slot); return -1; } strcpy (reader_table[slot].rdrname, portstr? portstr : list); @@ -1774,6 +1786,7 @@ open_pcsc_reader_direct (const char *portstr) reader_table[slot].dump_status_reader = dump_pcsc_reader_status; dump_reader_status (slot); + unlock_slot (slot); return slot; } #endif /*!NEED_PCSC_WRAPPER */ @@ -1821,6 +1834,7 @@ open_pcsc_reader_wrapped (const char *portstr) { log_error ("error creating a pipe: %s\n", strerror (errno)); slotp->used = 0; + unlock_slot (slot); return -1; } if (pipe (wp) == -1) @@ -1829,6 +1843,7 @@ open_pcsc_reader_wrapped (const char *portstr) close (rp[0]); close (rp[1]); slotp->used = 0; + unlock_slot (slot); return -1; } @@ -1841,6 +1856,7 @@ open_pcsc_reader_wrapped (const char *portstr) close (wp[0]); close (wp[1]); slotp->used = 0; + unlock_slot (slot); return -1; } slotp->pcsc.pid = pid; @@ -1976,6 +1992,7 @@ open_pcsc_reader_wrapped (const char *portstr) pcsc_get_status (slot, &dummy_status); dump_reader_status (slot); + unlock_slot (slot); return slot; command_failed: @@ -1986,6 +2003,7 @@ open_pcsc_reader_wrapped (const char *portstr) kill (slotp->pcsc.pid, SIGTERM); slotp->pcsc.pid = (pid_t)(-1); slotp->used = 0; + unlock_slot (slot); /* There is no way to return SW. */ return -1; @@ -2422,6 +2440,7 @@ open_ccid_reader (const char *portstr) if (err) { slotp->used = 0; + unlock_slot (slot); return -1; } @@ -2456,6 +2475,7 @@ open_ccid_reader (const char *portstr) reader_table[slot].is_t0 = 0; dump_reader_status (slot); + unlock_slot (slot); return slot; } @@ -2694,6 +2714,7 @@ open_rapdu_reader (int portno, if (!slotp->rapdu.handle) { slotp->used = 0; + unlock_slot (slot); return -1; } @@ -2748,12 +2769,14 @@ open_rapdu_reader (int portno, dump_reader_status (slot); rapdu_msg_release (msg); + unlock_slot (slot); return slot; failure: rapdu_msg_release (msg); rapdu_release (slotp->rapdu.handle); slotp->used = 0; + unlock_slot (slot); return -1; } commit 7f3ea446609355c96e90f0b6beb057daa1152643 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. diff --git a/scd/apdu.c b/scd/apdu.c index 0e52909..07df9fe 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -328,6 +328,44 @@ static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, */ +static int +lock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&reader_table[slot].lock, 0, NULL)) + { + log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); + return SW_HOST_LOCKING_FAILED; + } +#endif /*USE_GNU_PTH*/ + return 0; +} + +static int +trylock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&reader_table[slot].lock, TRUE, NULL)) + { + if (errno == EBUSY) + return SW_HOST_BUSY; + log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); + return SW_HOST_LOCKING_FAILED; + } +#endif /*USE_GNU_PTH*/ + return 0; +} + +static void +unlock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_release (&reader_table[slot].lock)) + log_error ("failed to release apdu lock: %s\n", strerror (errno)); +#endif /*USE_GNU_PTH*/ +} + + /* Find an unused reader slot for PORTSTR and put it into the reader table. Return -1 on error or the index into the reader table. */ static int @@ -2728,44 +2766,6 @@ open_rapdu_reader (int portno, */ -static int -lock_slot (int slot) -{ -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&reader_table[slot].lock, 0, NULL)) - { - log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); - return SW_HOST_LOCKING_FAILED; - } -#endif /*USE_GNU_PTH*/ - return 0; -} - -static int -trylock_slot (int slot) -{ -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&reader_table[slot].lock, TRUE, NULL)) - { - if (errno == EBUSY) - return SW_HOST_BUSY; - log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); - return SW_HOST_LOCKING_FAILED; - } -#endif /*USE_GNU_PTH*/ - return 0; -} - -static void -unlock_slot (int slot) -{ -#ifdef USE_GNU_PTH - if (!pth_mutex_release (&reader_table[slot].lock)) - log_error ("failed to release apdu lock: %s\n", strerror (errno)); -#endif /*USE_GNU_PTH*/ -} - - /* Open the reader and return an internal slot number or -1 on error. If PORTSTR is NULL we default to a suitable port (for ctAPI: the first USB reader. For PC/SC the first listed reader). */ ----------------------------------------------------------------------- Summary of changes: scd/apdu.c | 101 ++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 62 insertions(+), 39 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jun 20 14:48:06 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 20 Jun 2012 14:48:06 +0200 Subject: [git] GPG-ERROR - branch, master, updated. libgpg-error-1.10-31-g7878b0d Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Error codes used by GnuPG et al.". The branch, master has been updated via 7878b0d2db1b94be8e9655d847d42309a4a68e2a (commit) via c35dbfdaa2e30e08185e4a468278a29e2c48b500 (commit) from a7eb1bec2b76318bd17d4413d7f44197a241e3bc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7878b0d2db1b94be8e9655d847d42309a4a68e2a Author: Werner Koch Date: Wed Jun 20 13:35:43 2012 +0200 Add more error code documentation -- diff --git a/doc/errorref.txt b/doc/errorref.txt index bbc9001..eafd9d8 100644 --- a/doc/errorref.txt +++ b/doc/errorref.txt @@ -129,7 +129,10 @@ GPG_ERR_NO_VALUE No value - Converting a Distinguised Name to an RFC2253 string failed. -27 GPG_ERR_NOT_FOUND Not found +GPG_ERR_NOT_FOUND Not found + + A search operation did not return a matching value. + GPG_ERR_VALUE_NOT_FOUND Value not found @@ -295,10 +298,22 @@ GPG_ERR_UNSUPPORTED_PROTOCOL Unsupported protocol GPGME: - GPGME_PROTOCOL_xxx not supported. 122 GPG_ERR_BAD_PIN_METHOD Bad PIN method -123 GPG_ERR_CARD_NOT_INITIALIZED Card not initialized + +GPG_ERR_CARD_NOT_INITIALIZED Card not initialized + + SCDAEMON: - A card function is called but the card has not yet + been initialized. This may be due to a conflict with + another card using connection or due to a bug. + 124 GPG_ERR_UNSUPPORTED_OPERATION Unsupported operation 125 GPG_ERR_WRONG_KEY_USAGE Wrong key usage -126 GPG_ERR_NOTHING_FOUND Nothing found + +GPG_ERR_NOTHING_FOUND Nothing found + + Indicates that the operation was not possible because nothing has + been found. For example an update request for non existent data. + + 127 GPG_ERR_WRONG_BLOB_TYPE Wrong blob type GPG_ERR_MISSING_VALUE Missing value commit c35dbfdaa2e30e08185e4a468278a29e2c48b500 Author: Rafa?l Carr? Date: Wed Jun 20 11:49:57 2012 +0200 Use CPPFLAGS when generating mkerrcodes.h * src/Makefile.am (mkerrcodes.h): Use CPPFLAGS. Signed-off-by: Rafa?l Carr? diff --git a/src/Makefile.am b/src/Makefile.am index 518a4c0..a84e3f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -138,7 +138,7 @@ code-to-errno.h: Makefile mkerrnos.awk errnos.in # It is correct to use $(CPP). We want the host's idea of the error codes. mkerrcodes.h: Makefile mkerrcodes.awk $(gpg_extra_headers) $(AWK) -f $(srcdir)/mkerrcodes1.awk $(srcdir)/errnos.in >_$@ - $(CPP) $(extra_cppflags) _$@ | grep GPG_ERR_ | \ + $(CPP) $(CPPFLAGS) $(extra_cppflags) _$@ | grep GPG_ERR_ | \ $(AWK) -f $(srcdir)/mkerrcodes.awk >$@ -rm _$@ ----------------------------------------------------------------------- Summary of changes: doc/errorref.txt | 21 ++++++++++++++++++--- src/Makefile.am | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) hooks/post-receive -- Error codes used by GnuPG et al. http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jun 20 14:52:05 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 20 Jun 2012 14:52:05 +0200 Subject: [git] GPG-ERROR - branch, master, updated. libgpg-error-1.10-32-g09544df Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Error codes used by GnuPG et al.". The branch, master has been updated via 09544df3f087661ff084fc3ff29d9a82d8d33441 (commit) from 7878b0d2db1b94be8e9655d847d42309a4a68e2a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 09544df3f087661ff084fc3ff29d9a82d8d33441 Author: Werner Koch Date: Wed Jun 20 13:39:43 2012 +0200 Add the mailing list to AUTHORS. -- diff --git a/AUTHORS b/AUTHORS index 2035b5d..ce24f90 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ Package: libgpg-error Maintainer: Marcus Brinkmann Bug reports: bug-gnupg at gnupg.org +Mailing list: gnupg-devel at gnupg.org Security related bug reports: security at gnupg.org License (library): LGPLv2.1+ License (tools): GPLv2+ with exception @@ -24,7 +25,7 @@ g10 Code GmbH Jakub Bogusz - TRANSLATION [pl] -Laurentiu Buzdugan +Laurentiu Buzdugan - TRANSLATION [ro] Petr Pisar ----------------------------------------------------------------------- Summary of changes: AUTHORS | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) hooks/post-receive -- Error codes used by GnuPG et al. http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jun 21 12:24:05 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 21 Jun 2012 12:24:05 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-34-g2196728 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 2196728e2252917849c1be94417258076767021b (commit) via 20e423212c9710ee663e12dd0f62580ceb245a6f (commit) via baf0dc7e9c26167ab43ba2adebcf2f1abc9d9b3b (commit) from 39c123b729a472ace039f8536d07f8b9a5f4675a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2196728e2252917849c1be94417258076767021b Author: Werner Koch Date: Thu Jun 21 11:10:39 2012 +0200 Clear AESNI feature flag for x86_64. * src/hwfeatures.c (_gcry_detect_hw_features) [__x86_64__]: Clear AESNI feature flag. diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 396c71b..cf80fe0 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -287,6 +287,9 @@ _gcry_detect_hw_features (unsigned int disabled_features) # ifdef __GNUC__ { detect_x86_64_gnuc (); + /* We don't have AESNI support for 64 bit yet. Thus we should not + announce it. */ + hw_features &= ~HWF_INTEL_AESNI; } # endif #endif commit 20e423212c9710ee663e12dd0f62580ceb245a6f Author: Werner Koch Date: Thu Jun 21 11:09:06 2012 +0200 Beautify last change. * cipher/rijndael.c: Replace C99 feature from last patch. Keep cpp lines short. * random/rndhw.c: Keep cpp lines short. * src/hwfeatures.c (_gcry_detect_hw_features): Make cpp def chain better readable. diff --git a/cipher/rijndael.c b/cipher/rijndael.c index c2e0a77..d9a95cb 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -63,8 +63,10 @@ code. */ #undef USE_PADLOCK #ifdef ENABLE_PADLOCK_SUPPORT -# if ( ( defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 ) || defined(__x86_64__) ) && defined (__GNUC__) -# define USE_PADLOCK 1 +# ifdef __GNUC__ +# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) +# define USE_PADLOCK 1 +# endif # endif #endif /*ENABLE_PADLOCK_SUPPORT*/ @@ -650,6 +652,7 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, unsigned char a[16] __attribute__ ((aligned (16))); unsigned char b[16] __attribute__ ((aligned (16))); unsigned int cword[4] __attribute__ ((aligned (16))); + int blocks; /* The control word fields are: 127:12 11:10 9 8 7 6 5 4 3:0 @@ -663,7 +666,7 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, memcpy (a, ax, 16); - int blocks = 1; /* Init counter for just one block. */ + blocks = 1; /* Init counter for just one block. */ #ifdef __x86_64__ asm volatile ("pushfq\n\t" /* Force key reload. */ diff --git a/random/rndhw.c b/random/rndhw.c index c933cf9..0a5c9fa 100644 --- a/random/rndhw.c +++ b/random/rndhw.c @@ -27,11 +27,14 @@ #undef USE_PADLOCK #ifdef ENABLE_PADLOCK_SUPPORT -# if ( (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) ) && defined (__GNUC__) -# define USE_PADLOCK +# ifdef __GNUC__ +# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) +# define USE_PADLOCK 1 +# endif # endif #endif /*ENABLE_PADLOCK_SUPPORT*/ + /* Keep track on whether the RNG has problems. */ static volatile int rng_failed; diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 73db917..396c71b 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -273,16 +273,22 @@ _gcry_detect_hw_features (unsigned int disabled_features) return; /* Hardware support is not to be evaluated. */ #if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 -#ifdef __GNUC__ - detect_ia32_gnuc (); -#endif +# ifdef __GNUC__ + { + detect_ia32_gnuc (); + } +# endif #elif defined (__i386__) && SIZEOF_UNSIGNED_LONG == 8 -#ifdef __GNUC__ -#endif +# ifdef __GNUC__ + { + } +# endif #elif defined (__x86_64__) -#ifdef __GNUC__ - detect_x86_64_gnuc (); -#endif +# ifdef __GNUC__ + { + detect_x86_64_gnuc (); + } +# endif #endif hw_features &= ~disabled_features; commit baf0dc7e9c26167ab43ba2adebcf2f1abc9d9b3b Author: Rafa?l Carr? Date: Fri Apr 20 13:52:01 2012 -0400 Enable VIA Padlock on x86_64 platforms * cipher/rijndael.c: Duplicate x86 assembly and convert to x86_64. * random/rndhw.c: Likewise. * src/hwfeatures.c: Likewise. -- Changes made to the x86 assembly: - *l -> *q (long -> quad) - e** registers -> r** registers (use widest registers available) - don't mess with ebx GOT register Tested with make check on VIA Nano X2 L4350 Signed-off-by: Rafa?l Carr? diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 2df8ea9..c2e0a77 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -63,7 +63,7 @@ code. */ #undef USE_PADLOCK #ifdef ENABLE_PADLOCK_SUPPORT -# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +# if ( ( defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 ) || defined(__x86_64__) ) && defined (__GNUC__) # define USE_PADLOCK 1 # endif #endif /*ENABLE_PADLOCK_SUPPORT*/ @@ -663,17 +663,28 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, memcpy (a, ax, 16); + int blocks = 1; /* Init counter for just one block. */ +#ifdef __x86_64__ + asm volatile + ("pushfq\n\t" /* Force key reload. */ + "popfq\n\t" + ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */ + : /* No output */ + : "S" (a), "D" (b), "d" (cword), "b" (ctx->padlockkey), "c" (blocks) + : "cc", "memory" + ); +#else asm volatile ("pushfl\n\t" /* Force key reload. */ "popfl\n\t" "xchg %3, %%ebx\n\t" /* Load key. */ - "movl $1, %%ecx\n\t" /* Init counter for just one block. */ - ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */ + ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */ "xchg %3, %%ebx\n" /* Restore GOT register. */ : /* No output */ - : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlockkey) - : "%ecx", "cc", "memory" + : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlockkey), "c" (blocks) + : "cc", "memory" ); +#endif memcpy (bx, b, 16); diff --git a/random/rndhw.c b/random/rndhw.c index 82faab4..c933cf9 100644 --- a/random/rndhw.c +++ b/random/rndhw.c @@ -27,7 +27,7 @@ #undef USE_PADLOCK #ifdef ENABLE_PADLOCK_SUPPORT -# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +# if ( (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__) ) && defined (__GNUC__) # define USE_PADLOCK # endif #endif /*ENABLE_PADLOCK_SUPPORT*/ @@ -55,6 +55,16 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), nbytes = 0; while (nbytes < 64) { +#ifdef __x86_64__ + asm volatile + ("movq %1, %%rdi\n\t" /* Set buffer. */ + "xorq %%rdx, %%rdx\n\t" /* Request up to 8 bytes. */ + ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */ + : "=a" (status) + : "g" (p) + : "%rdx", "%rdi", "cc" + ); +#else asm volatile ("movl %1, %%edi\n\t" /* Set buffer. */ "xorl %%edx, %%edx\n\t" /* Request up to 8 bytes. */ @@ -63,6 +73,7 @@ poll_padlock (void (*add)(const void*, size_t, enum random_origins), : "g" (p) : "%edx", "%edi", "cc" ); +#endif if ((status & (1<<6)) /* RNG still enabled. */ && !(status & (1<<13)) /* von Neumann corrector is enabled. */ && !(status & (1<<14)) /* String filter is disabled. */ diff --git a/src/hwfeatures.c b/src/hwfeatures.c index c356798..73db917 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -40,6 +40,99 @@ _gcry_get_hw_features (void) } +#if defined (__x86_64__) && defined (__GNUC__) +static void +detect_x86_64_gnuc (void) +{ + /* The code here is only useful for the PadLock engine thus we don't + build it if that support has been disabled. */ + char vendor_id[12+1]; + + asm volatile + ("xorl %%eax, %%eax\n\t" /* 0 -> EAX. */ + "cpuid\n\t" /* Get vendor ID. */ + "movl %%ebx, (%0)\n\t" /* EBX,EDX,ECX -> VENDOR_ID. */ + "movl %%edx, 4(%0)\n\t" + "movl %%ecx, 8(%0)\n\t" + : + : "S" (&vendor_id[0]) + : "%eax", "%ecx", "%edx", "cc" + ); + vendor_id[12] = 0; + + if (0) + ; /* Just to make "else if" and ifdef macros look pretty. */ +#ifdef ENABLE_PADLOCK_SUPPORT + else if (!strcmp (vendor_id, "CentaurHauls")) + { + /* This is a VIA CPU. Check what PadLock features we have. */ + asm volatile + ("movl $0xC0000000, %%eax\n\t" /* Check for extended centaur */ + "cpuid\n\t" /* feature flags. */ + "cmpl $0xC0000001, %%eax\n\t" + "jb .Lready%=\n\t" /* EAX < 0xC0000000 => no padlock. */ + + "movl $0xC0000001, %%eax\n\t" /* Ask for the extended */ + "cpuid\n\t" /* feature flags. */ + + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x0C, %%eax\n\t" /* Test bits 2 and 3 to see whether */ + "cmpl $0x0C, %%eax\n\t" /* the RNG exists and is enabled. */ + "jnz .Lno_rng%=\n\t" + "orl $1, %0\n" /* Set our HWF_PADLOCK_RNG bit. */ + + ".Lno_rng%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC0, %%eax\n\t" /* Test bits 6 and 7 to see whether */ + "cmpl $0xC0, %%eax\n\t" /* the ACE exists and is enabled. */ + "jnz .Lno_ace%=\n\t" + "orl $2, %0\n" /* Set our HWF_PADLOCK_AES bit. */ + + ".Lno_ace%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC00, %%eax\n\t" /* Test bits 10, 11 to see whether */ + "cmpl $0xC00, %%eax\n\t" /* the PHE exists and is enabled. */ + "jnz .Lno_phe%=\n\t" + "orl $4, %0\n" /* Set our HWF_PADLOCK_SHA bit. */ + + ".Lno_phe%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x3000, %%eax\n\t" /* Test bits 12, 13 to see whether */ + "cmpl $0x3000, %%eax\n\t" /* MONTMUL exists and is enabled. */ + "jnz .Lready%=\n\t" + "orl $8, %0\n" /* Set our HWF_PADLOCK_MMUL bit. */ + + ".Lready%=:\n" + : "+r" (hw_features) + : + : "%eax", "%edx", "cc" + ); + } +#endif /*ENABLE_PADLOCK_SUPPORT*/ + else if (!strcmp (vendor_id, "GenuineIntel")) + { + /* This is an Intel CPU. */ + asm volatile + ("movl $1, %%eax\n\t" /* Get CPU info and feature flags. */ + "cpuid\n" + "testl $0x02000000, %%ecx\n\t" /* Test bit 25. */ + "jz .Lno_aes%=\n\t" /* No AES support. */ + "orl $256, %0\n" /* Set our HWF_INTEL_AES bit. */ + + ".Lno_aes%=:\n" + : "+r" (hw_features) + : + : "%eax", "%ecx", "%edx", "cc" + ); + } + else if (!strcmp (vendor_id, "AuthenticAMD")) + { + /* This is an AMD CPU. */ + + } +} +#endif /* __x86_64__ && __GNUC__ */ + #if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) static void detect_ia32_gnuc (void) @@ -186,6 +279,10 @@ _gcry_detect_hw_features (unsigned int disabled_features) #elif defined (__i386__) && SIZEOF_UNSIGNED_LONG == 8 #ifdef __GNUC__ #endif +#elif defined (__x86_64__) +#ifdef __GNUC__ + detect_x86_64_gnuc (); +#endif #endif hw_features &= ~disabled_features; ----------------------------------------------------------------------- Summary of changes: cipher/rijndael.c | 26 +++++++++--- random/rndhw.c | 18 +++++++- src/hwfeatures.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 147 insertions(+), 13 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jun 22 05:22:38 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Fri, 22 Jun 2012 05:22:38 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, updated. gnupg-2.0.19-29-ga90f0fc Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been updated via a90f0fca554a679e1c09b0c11ed80311a9358a9d (commit) from ff40c05e8b563471278cb7c92df0310bc5967749 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a90f0fca554a679e1c09b0c11ed80311a9358a9d Author: NIIBE Yutaka Date: Fri Jun 22 10:51:12 2012 +0900 scd: Fix updating slot status. * scd/comman.c (do_reset): Let clear card_removed flag. diff --git a/scd/command.c b/scd/command.c index 5ef6540..227057e 100644 --- a/scd/command.c +++ b/scd/command.c @@ -321,7 +321,7 @@ do_reset (ctrl_t ctrl, int send_reset) break; default: apdu_close_reader (slot); - slot = slot_table[slot].slot = -1; + slot_table[slot].slot = -1; break; } } ----------------------------------------------------------------------- Summary of changes: scd/command.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Sun Jun 24 04:59:26 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Sun, 24 Jun 2012 04:59:26 +0200 Subject: [git] GnuPG - branch, scd-backport-2-0, updated. gnupg-2.0.19-30-gc92a67d Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, scd-backport-2-0 has been updated via c92a67dde7595588254a5202bda95853defbdb4c (commit) from a90f0fca554a679e1c09b0c11ed80311a9358a9d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c92a67dde7595588254a5202bda95853defbdb4c Author: NIIBE Yutaka Date: Sun Jun 24 10:45:49 2012 +0900 scd: handle reader/token removal. * scd/apdu.c (pcsc_error_to_sw): PCSC_E_UNKNOWN_READER means SW_HOST_NO_READER. diff --git a/scd/apdu.c b/scd/apdu.c index a343307..0ce1c51 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -841,6 +841,7 @@ pcsc_error_to_sw (long ec) case PCSC_E_CANCELLED: rc = SW_HOST_ABORTED; break; case PCSC_E_NO_MEMORY: rc = SW_HOST_OUT_OF_CORE; break; case PCSC_E_TIMEOUT: rc = SW_HOST_CARD_IO_ERROR; break; + case PCSC_E_UNKNOWN_READER: rc = SW_HOST_NO_READER; break; case PCSC_E_SHARING_VIOLATION: rc = SW_HOST_LOCKING_FAILED; break; case PCSC_E_NO_SMARTCARD: rc = SW_HOST_NO_CARD; break; case PCSC_W_REMOVED_CARD: rc = SW_HOST_NO_CARD; break; ----------------------------------------------------------------------- Summary of changes: scd/apdu.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jun 25 05:01:37 2012 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Mon, 25 Jun 2012 05:01:37 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-81-gca8eec8 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via ca8eec8e28abb8473d02dbaf8d61cfb1094c5c50 (commit) from 096e7457ec636bcfcf128678660eb2f2e19f113a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ca8eec8e28abb8473d02dbaf8d61cfb1094c5c50 Author: NIIBE Yutaka Date: Sun Jun 24 10:45:49 2012 +0900 scd: handle reader/token removal. * scd/apdu.c (pcsc_error_to_sw): PCSC_E_UNKNOWN_READER means SW_HOST_NO_READER. diff --git a/scd/apdu.c b/scd/apdu.c index 7641e91..bdc37ca 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -818,6 +818,7 @@ pcsc_error_to_sw (long ec) case PCSC_E_CANCELLED: rc = SW_HOST_ABORTED; break; case PCSC_E_NO_MEMORY: rc = SW_HOST_OUT_OF_CORE; break; case PCSC_E_TIMEOUT: rc = SW_HOST_CARD_IO_ERROR; break; + case PCSC_E_UNKNOWN_READER: rc = SW_HOST_NO_READER; break; case PCSC_E_SHARING_VIOLATION: rc = SW_HOST_LOCKING_FAILED; break; case PCSC_E_NO_SMARTCARD: rc = SW_HOST_NO_CARD; break; case PCSC_W_REMOVED_CARD: rc = SW_HOST_NO_CARD; break; ----------------------------------------------------------------------- Summary of changes: scd/apdu.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jun 25 17:40:23 2012 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 25 Jun 2012 17:40:23 +0200 Subject: [git] GnuPG - branch, disallow-v3-keys, created. gnupg-2.1.0beta3-82-g2b32eb1 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, disallow-v3-keys has been created at 2b32eb15aac8cde4144243a67bd4f27f724bc78b (commit) - Log ----------------------------------------------------------------- commit 2b32eb15aac8cde4144243a67bd4f27f724bc78b Author: Werner Koch Date: Mon Jun 25 16:27:04 2012 +0200 gpg: Disallow the use of v3 keys. * g10/gpg.c: Add options --allow-v3-keys and --no-allow-v3-keys. (main): Enable --allow-v3-keys in --pgp2 mode. * g10/options.h (opt): Add field allow_v3_keys. * g10/import.c (delete_v3_subkeys): New. (import_one): Skip v3 keys and delete v3 subkeys. (import_print_stats): Print stats on v3 keys and subkeys. * g10/getkey.c (finish_lookup): Skip v3 keys. -- This is a first take on disabling v3 keys. We may need to add some tweaks to make decryption using an existing v3 key easier. There is no need to disallow decryption. Thanks to Georgi Guninski to put some pressure on us to finally do what PGP 2 folks will probably don?t like. See the discussion on gnupg-devel starting 2012-06-22. diff --git a/NEWS b/NEWS index a8352ca..521ccf9 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ Noteworthy changes in version 2.1.0beta4 (unreleased) * The hash algorithm is now printed for sig records in key listings. + * GPG does not anymore allow the use of the long deprecated v3 keys + (PGP 2 keys). The new option --allow-v3-keys can be used to + exceptionally allow them. + Noteworthy changes in version 2.1.0beta3 (2011-12-20) ----------------------------------------------------- diff --git a/doc/DETAILS b/doc/DETAILS index 59434f1..55f9ce6 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -459,7 +459,7 @@ more arguments in future versions. IMPORT_RES - + Final statistics on import process (this is one long line) FILE_START diff --git a/doc/gpg.texi b/doc/gpg.texi index 420326b..d8e4bcd 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2637,6 +2637,20 @@ Disable all checks on the form of the user ID while generating a new one. This option should only be used in very special environments as it does not ensure the de-facto standard format of user IDs. + at ifset gpgtwoone + at item --allow-v3-keys + at itemx --no-allow-v3-keys + at opindex allow-v3-keys +Allow the use of deprecated v3 keys with @command{gpg}. The default +is not to allow their use. + +Since version 2.1 GnuPG does not anymore allow the import or use of v3 +keys. Those keys have been generated in the past by PGP 2 and exhibit +a couple of flaws. For example they rely on the broken MD5 algorithm. +OpenPGP has long deprecated their use (cf. RFC-4880, section 5.5.2). +This option may be used to exceptionally allow their use. + at end ifset + @item --ignore-time-conflict @opindex ignore-time-conflict GnuPG normally checks that the timestamps associated with keys and diff --git a/g10/getkey.c b/g10/getkey.c index 9294273..348755d 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -2318,6 +2318,12 @@ finish_lookup (GETKEY_CTX ctx) if (DBG_CACHE) log_debug ("\tchecking subkey %08lX\n", (ulong) keyid_from_pk (pk, NULL)); + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (DBG_CACHE) + log_debug ("\tv3 subkey not allowed\n"); + continue; + } if (!pk->flags.valid) { if (DBG_CACHE) @@ -2373,7 +2379,12 @@ finish_lookup (GETKEY_CTX ctx) if (DBG_CACHE && !foundk && !req_prim) log_debug ("\tno suitable subkeys found - trying primary\n"); pk = keyblock->pkt->pkt.public_key; - if (!pk->flags.valid) + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (DBG_CACHE) + log_debug ("\tv3 primary key not allowed\n"); + } + else if (!pk->flags.valid) { if (DBG_CACHE) log_debug ("\tprimary key not valid\n"); diff --git a/g10/gpg.c b/g10/gpg.c index c8dbbfe..74f34f6 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -305,6 +305,8 @@ enum cmd_and_opt_values oNoAllowNonSelfsignedUID, oAllowFreeformUID, oNoAllowFreeformUID, + oAllowV3Keys, + oNoAllowV3Keys, oAllowSecretKeyImport, oEnableSpecialFilenames, oNoLiteral, @@ -682,6 +684,9 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", "@"), ARGPARSE_s_n (oAllowFreeformUID, "allow-freeform-uid", "@"), ARGPARSE_s_n (oNoAllowFreeformUID, "no-allow-freeform-uid", "@"), + ARGPARSE_s_n (oAllowFreeformUID, "allow-freeform-uid", "@"), + ARGPARSE_s_n (oAllowV3Keys, "allow-v3-keys", "@"), + ARGPARSE_s_n (oNoAllowV3Keys, "no-allow-v3-keys", "@"), ARGPARSE_s_n (oNoLiteral, "no-literal", "@"), ARGPARSE_p_u (oSetFilesize, "set-filesize", "@"), ARGPARSE_s_n (oHonorHttpProxy, "honor-http-proxy", "@"), @@ -2805,6 +2810,8 @@ main (int argc, char **argv) case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; + case oAllowV3Keys: opt.allow_v3_keys = 1; break; + case oNoAllowV3Keys: opt.allow_v3_keys = 0; break; case oNoLiteral: opt.no_literal = 1; break; case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oHonorHttpProxy: @@ -3184,6 +3191,7 @@ main (int argc, char **argv) xfree(s2k_digest_string); s2k_digest_string = xstrdup("md5"); opt.compress_algo = COMPRESS_ALGO_ZIP; + opt.allow_v3_keys = 1; } } else if(PGP6) diff --git a/g10/import.c b/g10/import.c index bfe02eb..06a92af 100644 --- a/g10/import.c +++ b/g10/import.c @@ -57,6 +57,8 @@ struct stats_s { ulong not_imported; ulong n_sigs_cleaned; ulong n_uids_cleaned; + ulong skipped_v3_keys; + ulong skipped_v3_subkeys; }; @@ -77,6 +79,7 @@ static int chk_self_sigs( const char *fname, KBNODE keyblock, PKT_public_key *pk, u32 *keyid, int *non_self ); static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid, unsigned int options ); +static int delete_v3_subkeys (kbnode_t keyblock); static int merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, u32 *keyid, int *n_uids, int *n_sigs, int *n_subk ); @@ -330,6 +333,9 @@ import_print_stats (void *hd) if( stats->skipped_new_keys ) log_info(_(" skipped new keys: %lu\n"), stats->skipped_new_keys ); + if( stats->skipped_v3_keys ) + log_info(_(" skipped v3 keys: %lu\n"), + stats->skipped_v3_keys); if( stats->no_user_id ) log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); if( stats->imported || stats->imported_rsa ) { @@ -344,6 +350,9 @@ import_print_stats (void *hd) log_info(_(" new user IDs: %lu\n"), stats->n_uids ); if( stats->n_subk ) log_info(_(" new subkeys: %lu\n"), stats->n_subk ); + if( stats->skipped_v3_subkeys) + log_info(_(" skipped v3 subkeys: %lu\n"), + stats->skipped_v3_subkeys); if( stats->n_sigs ) log_info(_(" new signatures: %lu\n"), stats->n_sigs ); if( stats->n_revoc ) @@ -363,8 +372,10 @@ import_print_stats (void *hd) } if( is_status_enabled() ) { - char buf[14*20]; - sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + char buf[16*20]; + snprintf (buf, sizeof buf, + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu" + " %lu %lu", stats->count, stats->no_user_id, stats->imported, @@ -378,7 +389,9 @@ import_print_stats (void *hd) stats->secret_imported, stats->secret_dups, stats->skipped_new_keys, - stats->not_imported ); + stats->not_imported, + stats->skipped_v3_keys, + stats->skipped_v3_subkeys); write_status_text( STATUS_IMPORT_RES, buf ); } } @@ -771,6 +784,7 @@ import_one (ctrl_t ctrl, int mod_key = 0; int same_key = 0; int non_self = 0; + int count; /* get the key and print some info about it */ node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); @@ -795,6 +809,18 @@ import_one (ctrl_t ctrl, log_printf ("\n"); } + /* We don't allow to import v3 keys unless the --allow-v3-keys + option is active. Note that this checks only the primary key. + v3 subkeys will be removed later. */ + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (opt.verbose) + log_info (_("key %s: v3 keys are not allowed - skipped\n"), + keystr (keyid)); + stats->skipped_new_keys++; + stats->skipped_v3_keys++; + return 0; + } if( !uidnode ) { @@ -855,6 +881,14 @@ import_one (ctrl_t ctrl, return 0; } + if (!opt.allow_v3_keys && (count = delete_v3_subkeys (keyblock))) + { + stats->skipped_v3_subkeys += count; + if (!opt.quiet) + log_info (_("key %s: removed v3 subkeys: %d\n"), + keystr (keyid), count); + } + /* do we have this key already in one of our pubrings ? */ pk_orig = xmalloc_clear( sizeof *pk_orig ); rc = get_pubkey_fast ( pk_orig, keyid ); @@ -2094,6 +2128,37 @@ delete_inv_parts( const char *fname, KBNODE keyblock, } +/* Remove all v3 public subkeys from KEYBLOCK. Returns the number of + * removed subkeys. */ +static int +delete_v3_subkeys (kbnode_t keyblock) +{ + kbnode_t node; + int count = 0; + + for (node = keyblock->next; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && node->pkt->pkt.public_key->version == 3) + { + delete_kbnode (node); + while (node->next && node->next->pkt->pkttype == PKT_SIGNATURE) + { + delete_kbnode (node->next); + node = node->next; + } + count++; + } + } + + /* Because KEYBLOCK is the primary public key, it is never marked + * for deletion and thus commit_keyblock won't change KEYBLOCK. */ + if (count) + commit_kbnode (&keyblock); + return count; +} + + /**************** * It may happen that the imported keyblock has duplicated user IDs. * We check this here and collapse those user IDs together with their diff --git a/g10/options.h b/g10/options.h index e67d0ce..3a9f43c 100644 --- a/g10/options.h +++ b/g10/options.h @@ -170,6 +170,7 @@ struct strlist_t sig_subpackets; int allow_non_selfsigned_uid; int allow_freeform_uid; + int allow_v3_keys; /* Allow the use of v3 keys. */ int no_literal; ulong set_filesize; int fast_list_mode; ----------------------------------------------------------------------- hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org