From e2bd757707136ccf019d3f74744197a8058cb095 Mon Sep 17 00:00:00 2001 From: Kim Kibum Date: Thu, 23 Aug 2012 20:37:47 +0900 Subject: [PATCH] upload source --- COPYING | 340 ++ config.guess | 1517 --------- config.sub | 1760 ----------- configure | 6 +- configure.ac | 2 + debian/changelog | 46 +- debian/control | 4 +- doc/ChangeLog | 444 +++ doc/HACKING | 66 + doc/Makefile.am | 71 + doc/Makefile.in | 745 +++++ doc/README.apichanges | 115 + doc/fips-fsm.eps | 580 ++++ doc/fips-fsm.fig | 199 ++ doc/fips-fsm.pdf | Bin 0 -> 11576 bytes doc/fips-fsm.png | Bin 0 -> 15376 bytes doc/gcrypt.info | 6814 +++++++++++++++++++++++++++++++++++++++++ doc/gcrypt.texi | 5844 +++++++++++++++++++++++++++++++++++ doc/gpl.texi | 397 +++ doc/lgpl.texi | 565 ++++ doc/libgcrypt-modules.eps | 349 +++ doc/libgcrypt-modules.fig | 193 ++ doc/libgcrypt-modules.pdf | Bin 0 -> 6090 bytes doc/libgcrypt-modules.png | Bin 0 -> 6883 bytes doc/mdate-sh | 201 ++ doc/stamp-vti | 4 + doc/texinfo.tex | 7482 +++++++++++++++++++++++++++++++++++++++++++++ doc/version.texi | 4 + packaging/libgcrypt.spec | 1 + src/dumpsexp.c | 613 ++++ src/gcryptrnd.c | 681 +++++ src/getrandom.c | 327 ++ tests/ChangeLog | 757 +++++ tests/Makefile.am | 45 + tests/Makefile.in | 798 +++++ tests/README | 9 + tests/ac-data.c | 208 ++ tests/ac-schemes.c | 347 +++ tests/ac.c | 162 + tests/basic.c | 2182 +++++++++++++ tests/benchmark.c | 1158 +++++++ tests/cavs_driver.pl | 2243 ++++++++++++++ tests/cavs_tests.sh | 135 + tests/fips186-dsa.c | 465 +++ tests/fipsdrv.c | 2526 +++++++++++++++ tests/hmac.c | 171 ++ tests/keygen.c | 311 ++ tests/keygrip.c | 208 ++ tests/mpitests.c | 302 ++ tests/pkbench.c | 514 ++++ tests/prime.c | 122 + tests/pubkey.c | 890 ++++++ tests/random.c | 255 ++ tests/register.c | 187 ++ tests/rsa-16k.key | 18 + tests/t-mpi-bit.c | 354 +++ tests/testapi.c | 112 + tests/tsexp.c | 456 +++ tests/version.c | 58 + 59 files changed, 41073 insertions(+), 3290 deletions(-) create mode 100644 COPYING delete mode 100755 config.guess delete mode 100755 config.sub create mode 100644 doc/ChangeLog create mode 100644 doc/HACKING create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/README.apichanges create mode 100644 doc/fips-fsm.eps create mode 100644 doc/fips-fsm.fig create mode 100644 doc/fips-fsm.pdf create mode 100644 doc/fips-fsm.png create mode 100644 doc/gcrypt.info create mode 100644 doc/gcrypt.texi create mode 100644 doc/gpl.texi create mode 100644 doc/lgpl.texi create mode 100644 doc/libgcrypt-modules.eps create mode 100644 doc/libgcrypt-modules.fig create mode 100644 doc/libgcrypt-modules.pdf create mode 100644 doc/libgcrypt-modules.png create mode 100755 doc/mdate-sh create mode 100644 doc/stamp-vti create mode 100644 doc/texinfo.tex create mode 100644 doc/version.texi create mode 100644 src/dumpsexp.c create mode 100644 src/gcryptrnd.c create mode 100644 src/getrandom.c create mode 100644 tests/ChangeLog create mode 100644 tests/Makefile.am create mode 100644 tests/Makefile.in create mode 100644 tests/README create mode 100644 tests/ac-data.c create mode 100644 tests/ac-schemes.c create mode 100644 tests/ac.c create mode 100644 tests/basic.c create mode 100644 tests/benchmark.c create mode 100755 tests/cavs_driver.pl create mode 100755 tests/cavs_tests.sh create mode 100644 tests/fips186-dsa.c create mode 100644 tests/fipsdrv.c create mode 100644 tests/hmac.c create mode 100644 tests/keygen.c create mode 100644 tests/keygrip.c create mode 100644 tests/mpitests.c create mode 100644 tests/pkbench.c create mode 100644 tests/prime.c create mode 100644 tests/pubkey.c create mode 100644 tests/random.c create mode 100644 tests/register.c create mode 100644 tests/rsa-16k.key create mode 100644 tests/t-mpi-bit.c create mode 100644 tests/testapi.c create mode 100644 tests/tsexp.c create mode 100644 tests/version.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/config.guess b/config.guess deleted file mode 100755 index 40eaed4..0000000 --- a/config.guess +++ /dev/null @@ -1,1517 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-05-11' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-tilera-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config.sub b/config.sub deleted file mode 100755 index 30fdca8..0000000 --- a/config.sub +++ /dev/null @@ -1,1760 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-03-23' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile-* | tilegx-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - # This must be matched before tile*. - tilegx*) - basic_machine=tilegx-unknown - os=-linux-gnu - ;; - tile*) - basic_machine=tile-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/configure b/configure index 3b2b4c4..6caf6f8 100755 --- a/configure +++ b/configure @@ -23314,7 +23314,7 @@ _ACEOF # And create the files. -ac_config_files="$ac_config_files Makefile m4/Makefile mpi/Makefile cipher/Makefile random/Makefile src/Makefile src/gcrypt.h src/libgcrypt-config src/versioninfo.rc" +ac_config_files="$ac_config_files Makefile m4/Makefile mpi/Makefile cipher/Makefile random/Makefile doc/Makefile src/Makefile src/gcrypt.h src/libgcrypt-config src/versioninfo.rc tests/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -24154,10 +24154,12 @@ do "mpi/Makefile") CONFIG_FILES="$CONFIG_FILES mpi/Makefile" ;; "cipher/Makefile") CONFIG_FILES="$CONFIG_FILES cipher/Makefile" ;; "random/Makefile") CONFIG_FILES="$CONFIG_FILES random/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/gcrypt.h") CONFIG_FILES="$CONFIG_FILES src/gcrypt.h" ;; "src/libgcrypt-config") CONFIG_FILES="$CONFIG_FILES src/libgcrypt-config" ;; "src/versioninfo.rc") CONFIG_FILES="$CONFIG_FILES src/versioninfo.rc" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; esac @@ -24918,8 +24920,6 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -#doc/Makefile -#tests/Makefile # Give some feedback echo " diff --git a/configure.ac b/configure.ac index 3fc5d30..87a1815 100644 --- a/configure.ac +++ b/configure.ac @@ -1118,10 +1118,12 @@ m4/Makefile mpi/Makefile cipher/Makefile random/Makefile +doc/Makefile src/Makefile src/gcrypt.h src/libgcrypt-config src/versioninfo.rc +tests/Makefile ]) AC_OUTPUT diff --git a/debian/changelog b/debian/changelog index f993785..06eb091 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,16 +1,46 @@ libgcrypt11 (1.4.4-5slp2+s2) unstable; urgency=low - * Renamed tag - * Git: unmodified/libgcrypt11 + * tag update + * Remove doc and tests from build script + * Git: 165.213.180.234:slp/unmodified/libgcrypt11 * Tag: libgcrypt11_1.4.4-5slp2+s2 - -- Taeksu Shin Thu, 15 Dec 2011 12:29:24 +0900 + -- Dongwook Lee Wed, 7 Sep 2011 15:10:51 +0900 -libgcrypt11 (1.4.4-1tizen) unstable; urgency=low - * Ported to Tizen - * Git: unmodified/libgcrypt11 - * Tag: libgcrypt11_1.4.4-1tizen +libgcrypt11 (1.4.4-5slp2+s1) unstable; urgency=low - -- Taeksu Shin Wed, 07 Dec 2011 11:25:33 +0900 + * Fix for gcc 4.5 compilation + * add ignore file + -- Mike McCormack Fri, 11 Mar 2011 19:06:53 +0900 + +libgcrypt11 (1.4.4-5) unstable; urgency=low + + * remove .git + + -- Youngjae Shin Fri, 20 Nov 2009 14:42:04 +0900 + +libgcrypt11 (1.4.4-4) unstable; urgency=low + + * change debian/rules + + -- Youngjae Shin Mon, 16 Nov 2009 11:27:53 +0900 + +libgcrypt11 (1.4.4-3) unstable; urgency=low + + * Initial Release. + + -- Youngjae Shin Fri, 13 Nov 2009 09:58:26 +0900 + +libgcrypt11 (1.4.4-2) unstable; urgency=low + + * Initial Release. + + -- Youngjae Shin Fri, 13 Nov 2009 09:58:26 +0900 + +libgcrypt11 (1.4.4-1) unstable; urgency=low + + * Initial Release. + + -- Youngjae Shin Fri, 13 Nov 2009 09:58:26 +0900 diff --git a/debian/control b/debian/control index f3baa7e..d0681fe 100644 --- a/debian/control +++ b/debian/control @@ -1,8 +1,8 @@ Source: libgcrypt11 Section: libs Priority: extra -Maintainer: Debian GnuTLS Maintainers , Taeksu Shin , Dongwook Lee -Uploaders: Taeksu Shin , Dongwook Lee +Maintainer: Mike McCormack , Taeksu Shin , Dongwook Lee +X-Original-Maintainer: Debian GnuTLS Maintainers Build-Depends: debhelper (>= 5), autotools-dev, libgpg-error-dev Standards-Version: 3.7.2 diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..027a147 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,444 @@ +2008-12-10 Werner Koch + + * gcrypt.texi (Cryptographic Functions): Explain the domain + parameter for key generation. + +2008-12-05 Werner Koch + + * gcrypt.texi: Updates for pubkey generation. + +2008-10-20 Werner Koch + + * gcrypt.texi (Error handler): Fix description of + gcry_handler_no_mem_t. Reported by Patrick Strateman. desribe + what what the error handler is expected to do. Fixes bug #961. + +2008-09-18 Werner Koch + + * gcrypt.texi (FIPS Mode): Add state transition Error to Error. + * fips-fsm.fig: Ditto. + +2008-09-18 Werner Koch + + * gcrypt.texi: Add a couple of index items. + (FIPS Mode): Reflect recent changes. + (Controlling the library): Describe gcry_fips_mode_active. + +2008-09-16 Werner Koch + + * gcrypt.texi (FIPS Mode): Describe new transitions 18 and 19. + * fips-fsm.fig: Add new transitions. + +2008-09-15 Werner Koch + + * gcrypt.texi: Fold the two FIPS appendices into one. + +2008-09-11 Werner Koch + + * gcrypt.texi (Public-Key Subsystem Architecture): Explain RSA + blinding. + +2008-09-08 Marcus Brinkmann + + * gcrypt.texi: Some typos fixed. + +2008-09-08 Werner Koch + + * gcrypt.texi: Formatting cleanups. + * lgpl.texi (Library Copying): Replace @appendix by @unnumbered. + * gpl.texi (Copying): Ditto. + +2008-08-27 Werner Koch + + * Makefile.am (online): Take care of development versions. + +2008-08-18 Werner Koch + + * gcrypt.texi (Top): Remove the detailmenu. + (Public Key Cryptographi (II)): Move into a section of the PK + interface description. + (Hashing): Move after the encryption chapters. + +2008-08-15 Werner Koch + + * gcrypt.texi (Controlling the library): Remove + GCRYCTL_DUMP_CONFIG because it is not implemented. + (Initializing the library): Describe initialization steps with + regard to secure memory. + + * gcrypt.texi (Working with cipher handles): Adjust for + implementation changes of gcry_cipher_setkey, gcry_cipher_setiv and + gcry_cipher_setctr. + +2008-01-04 Werner Koch + + * gcrypt.texi (Controlling the library): Add remark that the + theoritical attack on a seed file is not feasible under Linux. + +2007-12-11 Werner Koch + + * gcrypt.texi: Various minor corrections as reported by Elie De + Brauer more than a year ago. + +2007-06-15 Werner Koch + + * gcrypt.texi (Controlling the library): Clarified the use of + GCRYCTL_ENABLE_QUICK_RANDOM. + +2007-04-30 Werner Koch + + * HACKING: New. Two items by Marcus. + * README.apichanges: Move from .. to here. + * Makefile.am (EXTRA_DIST): Add new files. + +2007-04-09 Marcus Brinkmann + + * gcrypt.texi: Fix some typos. + +2006-11-05 Moritz Schulte + + * gcrypt.texi (General public-key related Functions): Typo. + +2006-09-19 Werner Koch + + * Makefile.am (online): New target. + +2006-08-29 Werner Koch + + * gcrypt.texi (Available ciphers): Add missing ciphers. + +2006-03-10 Brad Hards (wk, patch 2005-04-25) + + * gcrypt.texi: Document SHA-224 and typo fixes. + +2006-01-18 Brad Hards (wk 2006-03-07) + + * gcrypt.texi (Available cipher modes): Typo fix, add a little + more detail on cipher modes vs cipher algorithms. + +2006-01-08 Moritz Schulte + + * gcrypt.texi: Added documentation for more gcry_control commands. + + * gcrypt.texi: Fixed several typos; thanks to Tommi Vainikainen. + +2005-12-16 Moritz Schulte + + * gcrypt.texi (MPI formats): Fix return types of functions: + gcry_mpi_scan, gcry_mpi_print, gcry_mpi_aprint. + +2005-11-26 Moritz Schulte + + * gcrypt.texi: New chapter: Prime numbers. + +2005-11-12 Moritz Schulte + + * gcrypt.texi (MPI formats): Document that for gcry_mpi_scan and + in the case of GCRYMPI_FMT_HEX, BUFLEN must be zero. + +2005-10-31 Moritz Schulte + + * gcrypt.texi: Added more gcry_control related descriptions. + +2005-10-16 Moritz Schulte + + * gcrypt.texi (Controlling the library): Start documenting the + existing control commands. + +2005-04-11 Moritz Schulte + + * gcrypt.texi (Available hash algorithms): Add entry for Whirlpool. + +2005-03-30 Moritz Schulte + + * gcrypt.texi (Working with IO objects): Document ac io objects; + adjust ac scheme functions, which do now use io objects. + +2005-03-19 Moritz Schulte + + * gcrypt.texi (Working with cipher handles): Clarify CTS mode. + +2005-02-08 Werner Koch + + * gcrypt.texi: Fixed direntry. + +2005-02-13 Moritz Schulte + + * gcrypt.texi (Using cryptographic functions): Document new + encoding and scheme crypto functionality. + +2005-02-03 Moritz Schulte + + * gcrypt.texi: Fixed several typos; thanks to Michele Baldessari. + +2005-01-04 Werner Koch + + * gcrypt.texi: Updated to use @copying. Fixed list of copyright + years; we had real changes in 2004. Fixed some formatting issues. + +2004-08-24 Moritz Schulte + + * gcrypt.texi (Miscellaneous): Document gcry_mpi_randomize. + +2004-08-18 Moritz Schulte + + * gcrypt.texi (Multi Threading): Document + GCRY_THREAD_OPTION_PTH_IMPL, GCRY_THREAD_OPTION_PTHREAD_IMPL. + +2004-05-07 Moritz Schulte + + * gcrypt.texi: Merged several fixes reported by Umberto Salsi. + +2004-04-08 Moritz Schulte + + * gcrypt.texi (Multi Threading): Typo fix. + +2004-03-11 Marcus Brinkmann + + * gcrypt.texi (Multi Threading): Partially document new thread + support. + +2004-02-24 Werner Koch + + * gcrypt.texi (Calculations): Typo fix. + +2004-01-25 Moritz Schulte + + * gcrypt.texi (General cipher functions): Fixed descriptions of + the arguments for GCRYCTL_GET_KEYLEN, GCRYCTL_GET_BLKLEN; reported + by Randy. + +2004-01-14 Moritz Schulte + + * gcrypt.texi (Public Key cryptography II): Adjusted to new + gcry_ac_* API; document flags. + +2003-12-04 Werner Koch + + * Makefile.am (gcrypt_TEXINFOS): Removed fdl.texi. + +2003-12-03 Werner Koch + + * gcrypt.texi: Changed license from FDL to GPL because this is a + reference manual only useful along with actual code. + * fdl.texi: Removed. + + * gcrypt.texi: Minor cleanups + (Working with keys): Clarified generation of RSA's E parameter. + (Multi Threading): Clarified. + +2003-11-11 Werner Koch + + * gcrypt.texi (Working with S-expressions): Added "%b". + +2003-11-04 Werner Koch + + * gcrypt.texi (Retrieving random numbers): Add gcry_create_nonce. + +2003-08-30 Werner Koch + + * gcrypt.texi (Working with hash algorithms): Clarified that HMAC + does not work with all algorithms. + +2003-07-30 Moritz Schulte + + * gcrypt.texi (Available asymmetric algorithms): Mention + GCRY_AC_ELG_E. + +2003-07-28 Moritz Schulte + + * gcrypt.texi (Working with keys): Mention that gcry_pk_testkey + and gcry_ac_key_test only verify private keys. + (Working with keys): Fix typo. + (General public-key related Functions): Fixed some sentences, + thanks to Neil Spring. + +2003-07-27 Werner Koch + + * gcrypt.texi: Adjusted description of gcry_mpi_scan and + gcry_mpi_dump. Add gcry_mpi_dump. + +2003-07-22 Moritz Schulte + + * gcrypt.texi: Added more documentation for the register + mechanism. + +2003-07-18 Werner Koch + + * gcrypt.texi (Misc): Add a warning on the use of opaque values. + +2003-07-14 Moritz Schulte + + * gcrypt.texi (Overview): Mention the non-thread-safe-nature of + functions modifying context stored in handles. + +2003-07-12 Moritz Schulte + + * gcrypt.texi (Available ciphers): Added: TWOFISH128. + (Error Handling): Merged a lot of documentation taken from GPGME. + +2003-07-08 Moritz Schulte + + * gcrypt.texi (Working with sets of data): Documented: + gcry_ac_data_copy. + +2003-07-07 Moritz Schulte + + * gcrypt.texi: Documented module system. + +2003-07-05 Moritz Schulte + + * gcrypt.texi (Working with cipher handles): Small fix by Simon + Josefsson . + +2003-07-02 Moritz Schulte + + * gcrypt.texi: Documented ac interface. + +2003-06-18 Moritz Schulte + + * gcrypt.texi: Small fixes. + +2003-06-16 Moritz Schulte + + * cipher-ref.sgml: Removed file. + * digest-ref.sgml: Likewise. + * misc-ref.sgml: Likewise. + * pubkey-ref.sgml: Likewise. + * reference.sgml: Likewise. + * version.sgml.in: Likewise. + +2003-06-15 Moritz Schulte + + * gcrypt.texi: Documented several parts of the library, merged + some documentation from GPGME's manual, re-structured the whole + manual, added more menus. + +2003-06-14 Moritz Schulte + + * gcrypt.texi (Hash Functions): Adjusteded description of + gcry_md_copy. + +2003-06-12 Moritz Schulte + + * gcrypt.texi (Public Key Functions): Fix example S-Exp, i.e.: + added the number of following digits as prefix to the number of + bits. + (Public Key Functions): Document the general usage of `flags', + including the no-blinding flag. + +2003-06-11 Werner Koch + + * gcrypt.texi (Hash Functions): Document possible values of HD. + +2003-06-09 Moritz Schulte + + * gcrypt.texi (Version Check): Changed description of + gcry_check_version; the user now *must* call the function to + initialize the library. + +2003-06-08 Moritz Schulte + + * gcrypt.texi: Change for libgpg-error. + +2003-05-22 Moritz Schulte + + * gcrypt.texi (Public Key Functions): Fixed typo. + +2003-05-17 Moritz Schulte + + * gcrypt.texi (Public Key Functions): Mention that only the + checking of secret keys is supported currently. + +2003-03-30 Simon Josefsson + + * gcrypt.texi: Add CTR. + +2003-03-22 Simon Josefsson + + * gcrypt.texi: Add CBC-MAC. + +2003-03-04 Moritz Schulte + + * gcrypt.texi (Cipher Functions): Added gcry_cipher_reset. + +2003-01-23 Werner Koch + + * gcrypt.texi (gcry_pk_decrypt): Described use of FLAGS + +2003-01-20 Simon Josefsson + + * gcrypt.texi (Hash Functions): Add CRC. + +2003-01-19 Werner Koch + + * gcrypt.texi: Most functions are now documented. Still need to + fine tune the menu structure, document some utility functions, + mark up indices and references and add examples. + +2002-08-14 Werner Koch + + * gcrypt.texi: Typo fixes. + +2002-05-14 Werner Koch + + * lgpl.texi: New. + * gcrypt.texi: Included lgpl and commented not yet converted text. + +2002-04-16 Werner Koch + + * version.sgml.in, cipher-ref.sgml, digest-ref.sgml, misc-ref.sgml + * pubkey-ref.sgml, reference.sgml: Removed. + * gcrypt.texi: New. Based on the old sgml version. + * gpl.texi, fdl.texi: New. + * Makefile.am: Adjusted for use with texinfo. + +2000-12-21 Werner Koch + + Renamed the gcryptref.sgml files and removed the GnuPG stuff. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch + + * Makefile.am (SUBDIRS): Removed gph from this development series + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch + + * Makefile.am (SUBDIRS): New subdir gph for the manual. + +Thu Jul 22 20:03:03 CEST 1999 Werner Koch + + * gpg.sgml (--always-trust): Added. + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch + + * Makefile.am: Create a dummy man page if docbook-to-man is missing. + +Wed Jun 16 20:16:21 CEST 1999 Werner Koch + + * gpg1.pod: Removed. + * gpg.sgml: New. Replaces the pod file + * Makefile.am: Add rule to make a man file from sgml + +Tue Jun 15 12:21:08 CEST 1999 Werner Koch + + * Makefile.in.in: Use DESTDIR. + +Mon May 31 19:41:10 CEST 1999 Werner Koch + + * gpg.1pod: Enhanced the Bugs section (Michael). + +Wed Feb 10 17:15:39 CET 1999 Werner Koch + + * gpg.1pod: Spelling and grammar corrections (John A. Martin) + * FAQ: Ditto. + * DETAILS: Ditto. + + Copyright 1999, 2000, 2002, 2003, 2008 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/doc/HACKING b/doc/HACKING new file mode 100644 index 0000000..51380b1 --- /dev/null +++ b/doc/HACKING @@ -0,0 +1,66 @@ + Various hacking notes -*- text -*- + ======================= + + +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 + tool in GMP's build process, for example: + + $ m4 -DHAVE_CONFIG_H -D__GMP_WITHIN_GMP -DOPERATION_rshift -DPIC \ + rshift.asm >tmp-rshift.s + + Then tmp-rshift will contain the assembler instructions for the + configured platform. Unfortunately, this way the comments are lost. + For most files I re-inserted some of the comments, but this is + tedious work. + + +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 + in the debugging easily. I found that PARI (pari-gp package in + Debian) has support for elliptic curves. The below commands shows + how they are set up and used with an example. + + ===8<======== + hextodec(s)=local(v=Vec(s),a=10,b=11,c=12,d=13,e=14,f=15,A=10,B=11,C=12,D=13,E=14,F=15,h);if(#setunion(Set(v),Vec("0123456789ABCDEFabcdef"))>22,error);for(i=1,#v,h=shift(h,4)+eval(v[i]));h + + p = hextodec("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + a = hextodec("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC") + b = hextodec("51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00") + + /* Set up y^2 = x^3 + ax + b mod (p). */ + e = ellinit(Mod(1,p)*[0,0,0,a,b]); + + gx = hextodec ("00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66") + gy = hextodec ("011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650") + g = Mod(1,p)*[gx,gy] + + n = hextodec ("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409") + + /* Verify that G is on the curve, and that n is the order. */ + ellisoncurve (e,g) + isprime (n) + ellpow (e,g,n) + + d = hextodec ("018F9573F25059571BDF614529953DE2540497CEDABD04F3AF78813BED7BB163A2FD919EECF822848FCA39EF55E500F8CE861C7D53D371857F7774B79428E887F81B") + + qx = hextodec ("00316AAAD3E905875938F588BD9E8A4785EF9BDB76D62A83A5340F82CB8E800B25619F5C3EA02B7A4FA43D7497C7702F7DFBEAC8E8F92C3CAABD9F84182FDA391B3B") + /* Note: WRONG! (It is apparent that this is the same as X shifted by + 8 bit). */ + qy = hextodec ("0000316AAAD3E905875938F588BD9E8A4785EF9BDB76D62A83A5340F82CB8E800B25619F5C3EA02B7A4FA43D7497C7702F7DFBEAC8E8F92C3CAABD9F84182FDA391B") + q = Mod(1,p)*[qx,qy] + + /* Calculate what Q should be given d. */ + ellpow (e,g,d) + + /* This is not 0 and thus shows that libgcrypt gave Q and d that do + not match. */ + ellpow (e,g,d) - q + ====8<===================== + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..f251064 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,71 @@ +## Process this file with automake to create Makefile.in +# Copyright (C) 2002 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# 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 \ + libgcrypt-modules.eps fips-fsm.eps \ + libgcrypt-modules.png fips-fsm.png \ + libgcrypt-modules.pdf fips-fsm.pdf + +DISTCLEANFILES = gcrypt.cps + +BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \ + libgcrypt-modules.png fips-fsm.png \ + libgcrypt-modules.pdf fips-fsm.pdf + +info_TEXINFOS = gcrypt.texi +gcrypt_TEXINFOS = lgpl.texi gpl.texi libgcrypt-modules.fig fips-fsm.fig + + +.fig.png: + fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.jpg: + fig2dev -L jpg `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.eps: + fig2dev -L eps `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.pdf: + fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@ + + +# Make sure that gcrypt.texi is touched if any other source file has +# been modified. This is required so that the version.texi magic +# updates the release date. +gnupg.texi : $(gcrypt_TEXINFOS) + touch $(srcdir)/gcrypt.texi + +online: gcrypt.html gcrypt.pdf gcrypt.info + set -e; \ + echo "Uploading current manuals to www.gnupg.org ..."; \ + cp libgcrypt-modules.png gcrypt.html/; \ + cp fips-fsm.png gcrypt.html/; \ + user=werner ; dashdevel="" ; \ + if echo "@PACKAGE_VERSION@" | grep -- "-svn" >/dev/null; then \ + dashdevel="-devel" ; \ + cp gcrypt.pdf gcrypt.html/; \ + cp gcrypt.info gcrypt.html/; \ + else \ + rsync -v gcrypt.pdf gcrypt.info \ + $${user}@trithemius.gnupg.org:webspace/manuals/ ; \ + fi ; \ + cd gcrypt.html ; \ + rsync -vr --exclude='.svn' . \ + $${user}@trithemius.gnupg.org:webspace/manuals/gcrypt$${dashdevel}/ + diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..c5bd214 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,745 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2002 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +DIST_COMMON = $(gcrypt_TEXINFOS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/stamp-vti \ + $(srcdir)/version.texi ChangeLog mdate-sh texinfo.tex +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \ + $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +INFO_DEPS = $(srcdir)/gcrypt.info +am__TEXINFO_TEX_DIR = $(srcdir) +DVIS = gcrypt.dvi +PDFS = gcrypt.pdf +PSS = gcrypt.ps +HTMLS = gcrypt.html +TEXINFOS = gcrypt.texi +TEXI2DVI = texi2dvi +TEXI2PDF = $(TEXI2DVI) --pdf --batch +MAKEINFOHTML = $(MAKEINFO) --html +AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) +DVIPS = dvips +am__installdirs = "$(DESTDIR)$(infodir)" +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@ +FFLAGS = @FFLAGS@ +GCRYPT_CIPHERS = @GCRYPT_CIPHERS@ +GCRYPT_DIGESTS = @GCRYPT_DIGESTS@ +GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@ +GCRYPT_RANDOM = @GCRYPT_RANDOM@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@ +LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@ +LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@ +LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@ +LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@ +LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@ +LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@ +LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@ +LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@ +LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MPI_SFLAGS = @MPI_SFLAGS@ +NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTH_CFLAGS = @PTH_CFLAGS@ +PTH_CONFIG = @PTH_CONFIG@ +PTH_LIBS = @PTH_LIBS@ +RANLIB = @RANLIB@ +RC = @RC@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = README.apichanges HACKING \ + libgcrypt-modules.eps fips-fsm.eps \ + libgcrypt-modules.png fips-fsm.png \ + libgcrypt-modules.pdf fips-fsm.pdf + +DISTCLEANFILES = gcrypt.cps +BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \ + libgcrypt-modules.png fips-fsm.png \ + libgcrypt-modules.pdf fips-fsm.pdf + +info_TEXINFOS = gcrypt.texi +gcrypt_TEXINFOS = lgpl.texi gpl.texi libgcrypt-modules.fig fips-fsm.fig +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .dvi .eps .fig .html .info .jpg .pdf .png .ps .texi +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +.texi.info: + restore=: && backupdir="$(am__leading_dot)am$$$$" && \ + am__cwd=`pwd` && $(am__cd) $(srcdir) && \ + rm -rf $$backupdir && mkdir $$backupdir && \ + if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ + for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ + if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ + done; \ + else :; fi && \ + cd "$$am__cwd"; \ + if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $@ $<; \ + then \ + rc=0; \ + $(am__cd) $(srcdir); \ + else \ + rc=$$?; \ + $(am__cd) $(srcdir) && \ + $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ + fi; \ + rm -rf $$backupdir; exit $$rc + +.texi.dvi: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2DVI) $< + +.texi.pdf: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2PDF) $< + +.texi.html: + rm -rf $(@:.html=.htp) + if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) $<; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ + else \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ + exit 1; \ + fi +$(srcdir)/gcrypt.info: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS) +gcrypt.dvi: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS) +gcrypt.pdf: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS) +gcrypt.html: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS) +$(srcdir)/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/stamp-vti +$(srcdir)/stamp-vti: gcrypt.texi $(top_srcdir)/configure + @(dir=.; test -f ./gcrypt.texi || dir=$(srcdir); \ + set `$(SHELL) $(srcdir)/mdate-sh $$dir/gcrypt.texi`; \ + echo "@set UPDATED $$1 $$2 $$3"; \ + echo "@set UPDATED-MONTH $$2 $$3"; \ + echo "@set EDITION $(VERSION)"; \ + echo "@set VERSION $(VERSION)") > vti.tmp + @cmp -s vti.tmp $(srcdir)/version.texi \ + || (echo "Updating $(srcdir)/version.texi"; \ + cp vti.tmp $(srcdir)/version.texi) + -@rm -f vti.tmp + @cp $(srcdir)/version.texi $@ + +mostlyclean-vti: + -rm -f vti.tmp + +maintainer-clean-vti: +@MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi +.dvi.ps: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + $(DVIPS) -o $@ $< + +uninstall-dvi-am: + @$(NORMAL_UNINSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ + rm -f "$(DESTDIR)$(dvidir)/$$f"; \ + done + +uninstall-html-am: + @$(NORMAL_UNINSTALL) + @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ + rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ + done + +uninstall-info-am: + @$(PRE_UNINSTALL) + @if test -d '$(DESTDIR)$(infodir)' && \ + (install-info --version && \ + install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ + if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ + then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ + done; \ + else :; fi + @$(NORMAL_UNINSTALL) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ + (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ + echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ + rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ + else :; fi); \ + done + +uninstall-pdf-am: + @$(NORMAL_UNINSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ + rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ + done + +uninstall-ps-am: + @$(NORMAL_UNINSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ + rm -f "$(DESTDIR)$(psdir)/$$f"; \ + done + +dist-info: $(INFO_DEPS) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + case $$base in \ + $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ + for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ + if test -f $$file; then \ + relfile=`expr "$$file" : "$$d/\(.*\)"`; \ + test -f "$(distdir)/$$relfile" || \ + cp -p $$file "$(distdir)/$$relfile"; \ + else :; fi; \ + done; \ + done + +mostlyclean-aminfo: + -rm -rf gcrypt.aux gcrypt.cp gcrypt.cps gcrypt.fn gcrypt.fns gcrypt.ky \ + gcrypt.kys gcrypt.log gcrypt.pg gcrypt.tmp gcrypt.toc \ + gcrypt.tp gcrypt.vr gcrypt.vrs + +clean-aminfo: + -test -z "gcrypt.dvi gcrypt.pdf gcrypt.ps gcrypt.html" \ + || rm -rf gcrypt.dvi gcrypt.pdf gcrypt.ps gcrypt.html + +maintainer-clean-aminfo: + @list='$(INFO_DEPS)'; for i in $$list; do \ + i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ + echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ + rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ + done +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-info +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(INFO_DEPS) +installdirs: + for dir in "$(DESTDIR)$(infodir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-aminfo clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: $(DVIS) + +html: html-am + +html-am: $(HTMLS) + +info: info-am + +info-am: $(INFO_DEPS) + +install-data-am: install-info-am + +install-dvi: install-dvi-am + +install-dvi-am: $(DVIS) + @$(NORMAL_INSTALL) + test -z "$(dvidir)" || $(MKDIR_P) "$(DESTDIR)$(dvidir)" + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ + done +install-exec-am: + +install-html: install-html-am + +install-html-am: $(HTMLS) + @$(NORMAL_INSTALL) + test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" + @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ + $(am__strip_dir) \ + if test -d "$$d$$p"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ + echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ + else \ + list2="$$list2 $$d$$p"; \ + fi; \ + done; \ + test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ + done; } +install-info: install-info-am + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + test -z "$(infodir)" || $(MKDIR_P) "$(DESTDIR)$(infodir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ + for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ + $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ + if test -f $$ifile; then \ + echo "$$ifile"; \ + else : ; fi; \ + done; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done + @$(POST_INSTALL) + @if (install-info --version && \ + install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ + done; \ + else : ; fi +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: $(PDFS) + @$(NORMAL_INSTALL) + test -z "$(pdfdir)" || $(MKDIR_P) "$(DESTDIR)$(pdfdir)" + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done +install-ps: install-ps-am + +install-ps-am: $(PSS) + @$(NORMAL_INSTALL) + test -z "$(psdir)" || $(MKDIR_P) "$(DESTDIR)$(psdir)" + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-aminfo \ + maintainer-clean-generic maintainer-clean-vti + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-aminfo mostlyclean-generic \ + mostlyclean-libtool mostlyclean-vti + +pdf: pdf-am + +pdf-am: $(PDFS) + +ps: ps-am + +ps-am: $(PSS) + +uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ + uninstall-pdf-am uninstall-ps-am + +.MAKE: all check install install-am install-strip + +.PHONY: all all-am check check-am clean clean-aminfo clean-generic \ + clean-libtool dist-info distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-aminfo \ + maintainer-clean-generic maintainer-clean-vti mostlyclean \ + mostlyclean-aminfo mostlyclean-generic mostlyclean-libtool \ + mostlyclean-vti pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-dvi-am uninstall-html-am uninstall-info-am \ + uninstall-pdf-am uninstall-ps-am + + +.fig.png: + fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.jpg: + fig2dev -L jpg `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.eps: + fig2dev -L eps `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.pdf: + fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@ + +# Make sure that gcrypt.texi is touched if any other source file has +# been modified. This is required so that the version.texi magic +# updates the release date. +gnupg.texi : $(gcrypt_TEXINFOS) + touch $(srcdir)/gcrypt.texi + +online: gcrypt.html gcrypt.pdf gcrypt.info + set -e; \ + echo "Uploading current manuals to www.gnupg.org ..."; \ + cp libgcrypt-modules.png gcrypt.html/; \ + cp fips-fsm.png gcrypt.html/; \ + user=werner ; dashdevel="" ; \ + if echo "@PACKAGE_VERSION@" | grep -- "-svn" >/dev/null; then \ + dashdevel="-devel" ; \ + cp gcrypt.pdf gcrypt.html/; \ + cp gcrypt.info gcrypt.html/; \ + else \ + rsync -v gcrypt.pdf gcrypt.info \ + $${user}@trithemius.gnupg.org:webspace/manuals/ ; \ + fi ; \ + cd gcrypt.html ; \ + rsync -vr --exclude='.svn' . \ + $${user}@trithemius.gnupg.org:webspace/manuals/gcrypt$${dashdevel}/ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/README.apichanges b/doc/README.apichanges new file mode 100644 index 0000000..63b64da --- /dev/null +++ b/doc/README.apichanges @@ -0,0 +1,115 @@ +README.apichanges 2003-07-28 + + NOTE: THESE ARE API CHANGES DONE BEFORE THE FIRST STABLE RELEASE SO + THEY ARE NOT RELEVANT ANYMORE [stable is 1.2.4 right now] + +We decided to change a couple of annoying things in Libgcrypt and to +cleanup the API. The new API better fits into a multi-threaded +environment and is more consistent. One import change is that all +functions return error codes from a set of error codes shared between +GnuPG, GPGME and Libgcrypt. + +This file contains some hints on how to port your application from +libgcrypt <= 1.1.12 to the current API as of 1.1.42. We hope that +there won't be another need for such a major change. + + +* Types + + All types definitions changed to a foo_t scheme; for some time we + will support the old names but you better start to rename them: + + s/GCRY_MPI/gcry_mpi_t/ + s/GcryMPI/gcry_mpi_t/ + s/GCRY_SEXP/gcry_sexp_t/ + s/GcrySexp/gcry_sexp_t/ + s/GCRY_CIPHER_HD/gcry_cipher_hd_t/ + s/GcryCipherHd/gcry_cipher_hd_t/ + s/GCRY_MD_HD/gcry_md_hd_t/ + s/GcryMDHd/gcry_md_hd_t/ + +* Initialization + + For proper initialization of the library, you must call + gcry_check_version() before calling any other function except for + these gcry_control operations: + GCRYCTL_SUSPEND_SECMEM_WARN + GCRYCTL_DISABLE_INTERNAL_LOCKING + GCRYCTL_ANY_INITIALIZATION_P + GCRYCTL_INITIALIZATION_FINISHED_P + + +* Handles + + gcry_cipher_open and gcry_md_open do now return an error code + instead of a NULL handle; the handle is now returned by + asigning it to the first argument. Example on how to change your + code: + + Old: + + hd = gcry_md_open (algo, flags); + if (!hd) + { + fprintf (stderr, "md_open failed: %s\n", gcry_errno (-1)); + .... + + New: + + rc = gcry_md_open (&hd, algo, flags); + if (rc) + { + fprintf (stderr, "md_open failed: %s\n", gcry_strerror (rc)); + .... + + If you are not interested in the error code, you can do it in a + simplified way: + + gcry_md_open (&hd, algo, flags); + if (!hd) + abort (); + + i.e. the function makes sure that HD points to NULL in case of an error. + The required change for gcry_cipher_open is similar. + +* Message Digests + + The order of the arguments to gcry_md_copy has been changed in order + to be more consistent with other functions of this type. This means + that the new message digest handle will be a copy of the message + handle specified by the second argument and stored at the address + pointed to by the first argument. + +* Error codes + + gcry_errno () has been removed because it is hard to use in + multi-threaded environment. You need to save the error code + returned by the functions and use it either numerical or passing it + to gcry_strerror (since gcry_strerror is a wrapper function for + gpg_strerror, the latter function can also be used). + + Instead of using the error codes GCRYERR_*, you have to use the + GPG_ERR_* names. + +* S-expressions + + gcry_sexp_canon_len used to return a `historical' error code in + `errcode', this is not the case anymore; the value returned in + `errcode' is now a standard Libgcrypt (i.e. gpg-error) error code. + +* MPI + + gcry_mpi_scan and gcry_mpi_print need the size of a provided buffer + as input and return the number of bytes actually scanned/printed to + the user. The old API used a single size_t Pointer for both tasks, + the new API distinguishes between the input and the output values. + +* Public Key cryptography + + gcry_pk_decrypt used to return a `simple S-expression part' that + contains a single MPI value. In case the `data' S-expression + contains a `flags' element, the result S-expression is filled with a + complete S-expression of the following format: + + (value PLAINTEXT) + diff --git a/doc/fips-fsm.eps b/doc/fips-fsm.eps new file mode 100644 index 0000000..9de7a84 --- /dev/null +++ b/doc/fips-fsm.eps @@ -0,0 +1,580 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: fips-fsm.fig +%%Creator: fig2dev Version 3.2 Patchlevel 4 +%%CreationDate: Thu Sep 18 19:08:29 2008 +%%For: wk@vigenere (Werner Koch,,,) +%%BoundingBox: 0 0 497 579 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def +/col32 {0.609 0.000 0.000 srgb} bind def +/col33 {0.547 0.547 0.547 srgb} bind def +/col34 {0.547 0.547 0.547 srgb} bind def +/col35 {0.258 0.258 0.258 srgb} bind def +/col36 {0.547 0.547 0.547 srgb} bind def +/col37 {0.258 0.258 0.258 srgb} bind def +/col38 {0.547 0.547 0.547 srgb} bind def +/col39 {0.258 0.258 0.258 srgb} bind def +/col40 {0.547 0.547 0.547 srgb} bind def +/col41 {0.258 0.258 0.258 srgb} bind def +/col42 {0.547 0.547 0.547 srgb} bind def +/col43 {0.258 0.258 0.258 srgb} bind def + +end +save +newpath 0 579 moveto 0 0 lineto 497 0 lineto 497 579 lineto closepath clip newpath +-56.9 596.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/reencdict 12 dict def /ReEncode { reencdict begin +/newcodesandnames exch def /newfontname exch def /basefontname exch def +/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def +basefontdict { exch dup /FID ne { dup /Encoding eq +{ exch dup length array copy newfont 3 1 roll put } +{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall +newfont /FontName newfontname put newcodesandnames aload pop +128 1 255 { newfont /Encoding get exch /.notdef put } for +newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat +newfontname newfont definefont pop end } def +/isovec [ +8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde +8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis +8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron +8#220 /dotlessi 8#230 /oe 8#231 /OE +8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling +8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis +8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot +8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus +8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph +8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine +8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf +8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute +8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring +8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute +8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute +8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve +8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply +8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex +8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave +8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring +8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute +8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute +8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve +8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide +8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex +8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def +/Courier-Oblique /Courier-Oblique-iso isovec ReEncode +/Times-Roman /Times-Roman-iso isovec ReEncode + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06299 0.06299 sc +% +% Fig objects follow +% +% +% here starts figure with depth 50 +% Ellipse +7.500 slw +n 3238 1735 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +3157 1805 m +gs 1 -1 sc (1) col0 sh gr +% Ellipse +n 2408 3749 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +2327 3819 m +gs 1 -1 sc (2) col0 sh gr +% Ellipse +n 1708 5809 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +1627 5879 m +gs 1 -1 sc (3) col0 sh gr +% Ellipse +n 5848 1685 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +5767 1755 m +gs 1 -1 sc (6) col0 sh gr +% Ellipse +n 6128 7899 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +6047 7969 m +gs 1 -1 sc (7) col0 sh gr +% Ellipse +n 7568 4889 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +7487 4959 m +gs 1 -1 sc (8) col0 sh gr +% Ellipse +n 6008 3879 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +5882 3940 m +gs 1 -1 sc (10) col0 sh gr +% Ellipse +n 5418 2659 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +5292 2720 m +gs 1 -1 sc (11) col0 sh gr +% Ellipse +n 4268 3715 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +4142 3776 m +gs 1 -1 sc (12) col0 sh gr +% Ellipse +n 3208 5865 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +3082 5926 m +gs 1 -1 sc (13) col0 sh gr +% Ellipse +n 4178 6765 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +4052 6826 m +gs 1 -1 sc (14) col0 sh gr +% Ellipse +n 4558 7355 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +4432 7416 m +gs 1 -1 sc (15) col0 sh gr +% Ellipse +n 5208 7365 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +5127 7435 m +gs 1 -1 sc (5) col0 sh gr +% Ellipse +n 3708 7715 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +3582 7776 m +gs 1 -1 sc (16) col0 sh gr +% Ellipse +n 3038 7925 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +2957 7995 m +gs 1 -1 sc (4) col0 sh gr +% Ellipse +n 6568 5895 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +6487 5965 m +gs 1 -1 sc (9) col0 sh gr +% Polyline +n 3900 8370 m 3600 8370 3600 9150 300 arcto 4 {pop} repeat + 3600 9450 5670 9450 300 arcto 4 {pop} repeat + 5970 9450 5970 8670 300 arcto 4 {pop} repeat + 5970 8370 3900 8370 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +3870 9000 m +gs 1 -1 sc (Operational) col0 sh gr +% Polyline +n 1215 4335 m 915 4335 915 5145 300 arcto 4 {pop} repeat + 915 5445 2640 5445 300 arcto 4 {pop} repeat + 2940 5445 2940 4635 300 arcto 4 {pop} repeat + 2940 4335 1215 4335 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +1620 4995 m +gs 1 -1 sc (Init) col0 sh gr +% Polyline +n 1230 6345 m 930 6345 930 7155 300 arcto 4 {pop} repeat + 930 7455 2655 7455 300 arcto 4 {pop} repeat + 2955 7455 2955 6645 300 arcto 4 {pop} repeat + 2955 6345 1230 6345 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +1215 7020 m +gs 1 -1 sc (Self-Test) col0 sh gr +% Polyline +n 7050 6360 m 6750 6360 6750 7170 300 arcto 4 {pop} repeat + 6750 7470 8475 7470 300 arcto 4 {pop} repeat + 8775 7470 8775 6660 300 arcto 4 {pop} repeat + 8775 6360 7050 6360 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +7335 7020 m +gs 1 -1 sc (Error) col0 sh gr +% Polyline +n 4125 4335 m 3825 4335 3825 5145 300 arcto 4 {pop} repeat + 3825 5445 5550 5445 300 arcto 4 {pop} repeat + 5850 5445 5850 4635 300 arcto 4 {pop} repeat + 5850 4335 4125 4335 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +3915 4995 m +gs 1 -1 sc (Fatal-Error) col0 sh gr +% Polyline +n 7050 2310 m 6750 2310 6750 3120 300 arcto 4 {pop} repeat + 6750 3420 8475 3420 300 arcto 4 {pop} repeat + 8775 3420 8775 2610 300 arcto 4 {pop} repeat + 8775 2310 7050 2310 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +6930 2970 m +gs 1 -1 sc (Shutdown) col0 sh gr +% Polyline +n 2775 2295 m 2475 2295 2475 3105 300 arcto 4 {pop} repeat + 2475 3405 4200 3405 300 arcto 4 {pop} repeat + 4500 3405 4500 2595 300 arcto 4 {pop} repeat + 4500 2295 2775 2295 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +2655 2970 m +gs 1 -1 sc (Power-On) col0 sh gr +% Polyline +n 2775 285 m 2475 285 2475 1095 300 arcto 4 {pop} repeat + 2475 1395 4200 1395 300 arcto 4 {pop} repeat + 4500 1395 4500 585 300 arcto 4 {pop} repeat + 4500 285 2775 285 300 arcto 4 {pop} repeat + cp gs col0 s gr +/Times-Roman-iso ff 360.00 scf sf +2565 945 m +gs 1 -1 sc (Power-Off) col0 sh gr +% Ellipse +n 4192 6338 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +4066 6399 m +gs 1 -1 sc (17) col0 sh gr +% Ellipse +n 3202 4507 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +3076 4568 m +gs 1 -1 sc (19) col0 sh gr +% Ellipse +n 3181 5161 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +3055 5222 m +gs 1 -1 sc (18) col0 sh gr +% Ellipse +n 7709 7996 142 142 0 360 DrawEllipse gs col0 s gr + +/Courier-Oblique-iso ff 180.00 scf sf +7612 8047 m +gs 1 -1 sc (20) col0 sh gr +% Arc +15.000 slw +1 slc +gs clippath +2899 6648 m 2920 6766 l 3203 6716 l 2957 6699 l 3182 6598 l cp +eoclip +n 4837.5 16740.0 10215.6 -79.2 -100.8 arcn +gs col0 s gr + gr + +% arrowhead +0 slc +n 3182 6598 m 2957 6699 l 3203 6716 l 3182 6598 l cp gs 0.00 setgray ef gr col0 s +% Arc +1 slc +gs clippath +2911 7184 m 2908 7304 l 3195 7313 l 2957 7246 l 3198 7193 l cp +eoclip +n 3026.1 8399.8 1159.2 -1.5 -95.0 arcn +gs col0 s gr + gr + +% arrowhead +0 slc +n 3198 7193 m 2957 7246 l 3195 7313 l 3198 7193 l cp gs 0.00 setgray ef gr col0 s +% Arc +1 slc +gs clippath +6757 6631 m 6772 6512 l 6487 6477 l 6718 6566 l 6472 6596 l cp +eoclip +n 7663.1 -2028.8 8647.1 123.6 96.1 arcn +gs col0 s gr + gr + +% arrowhead +0 slc +n 6472 6596 m 6718 6566 l 6487 6477 l 6472 6596 l cp gs 0.00 setgray ef gr col0 s +% Arc +1 slc +gs clippath +8336 7494 m 8241 7421 l 8066 7650 l 8260 7496 l 8162 7723 l cp +eoclip +n 7717.5 7211.2 619.2 155.3 24.7 arcn +gs col0 s gr + gr + +% arrowhead +0 slc +n 8162 7723 m 8260 7496 l 8066 7650 l 8162 7723 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +3360 2310 m 3480 2310 l 3480 2023 l 3420 2263 l 3360 2023 l cp +eoclip +n 3420 1395 m + 3420 2295 l gs col0 s gr gr + +% arrowhead +0 slc +n 3360 2023 m 3420 2263 l 3480 2023 l 3360 2023 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +4794 4378 m 4860 4278 l 4621 4118 l 4788 4302 l 4555 4218 l cp +eoclip +n 3465 3420 m + 4815 4320 l gs col0 s gr gr + +% arrowhead +0 slc +n 4555 4218 m 4788 4302 l 4621 4118 l 4555 4218 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +1830 6360 m 1950 6360 l 1950 6073 l 1890 6313 l 1830 6073 l cp +eoclip +n 1890 5445 m + 1890 6345 l gs col0 s gr gr + +% arrowhead +0 slc +n 1830 6073 m 1890 6313 l 1950 6073 l 1830 6073 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +3699 8465 m 3790 8386 l 3601 8170 l 3714 8391 l 3511 8249 l cp +eoclip +n 2835 7380 m + 3735 8415 l gs col0 s gr gr + +% arrowhead +0 slc +n 3511 8249 m 3714 8391 l 3601 8170 l 3511 8249 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +4785 5475 m 4665 5475 l 4665 5762 l 4725 5522 l 4785 5762 l cp +eoclip +n 4725 8370 m + 4725 5490 l gs col0 s gr gr + +% arrowhead +0 slc +n 4785 5762 m 4725 5522 l 4665 5762 l 4785 5762 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +7395 3432 m 7287 3380 l 7162 3639 l 7321 3449 l 7270 3691 l cp +eoclip +n 4950 8370 m + 7335 3420 l gs col0 s gr gr + +% arrowhead +0 slc +n 7270 3691 m 7321 3449 l 7162 3639 l 7270 3691 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +6765 6990 m 6765 6870 l 6478 6870 l 6718 6930 l 6478 6990 l cp +eoclip +n 2925 6930 m + 6750 6930 l gs col0 s gr gr + +% arrowhead +0 slc +n 6478 6990 m 6718 6930 l 6478 6870 l 6478 6990 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +3969 5384 m 3880 5303 l 3686 5515 l 3893 5379 l 3774 5596 l cp +eoclip +n 2880 6480 m + 3915 5355 l gs col0 s gr gr + +% arrowhead +0 slc +n 3774 5596 m 3893 5379 l 3686 5515 l 3774 5596 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +6765 2895 m 6765 2775 l 6478 2775 l 6718 2835 l 6478 2895 l cp +eoclip +n 4500 2835 m + 6750 2835 l gs col0 s gr gr + +% arrowhead +0 slc +n 6478 2895 m 6718 2835 l 6478 2775 l 6478 2895 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +7800 3405 m 7680 3405 l 7680 3692 l 7740 3452 l 7800 3692 l cp +eoclip +n 7740 6345 m + 7740 3420 l gs col0 s gr gr + +% arrowhead +0 slc +n 7800 3692 m 7740 3452 l 7680 3692 l 7800 3692 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +1846 4276 m 1908 4379 l 2154 4229 l 1918 4303 l 2092 4127 l cp +eoclip +n 3375 3420 m + 1890 4320 l gs col0 s gr gr + +% arrowhead +0 slc +n 2092 4127 m 1918 4303 l 2154 4229 l 2092 4127 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +6893 3361 m 6808 3276 l 6604 3480 l 6817 3353 l 6689 3565 l cp +eoclip +n 5760 4410 m + 6840 3330 l gs col0 s gr gr + +% arrowhead +0 slc +n 6689 3565 m 6817 3353 l 6604 3480 l 6689 3565 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +4510 794 m 4461 903 l 4724 1020 l 4530 868 l 4773 910 l cp +eoclip +n 7740 2295 m + 4500 855 l gs col0 s gr gr + +% arrowhead +0 slc +n 4773 910 m 4530 868 l 4724 1020 l 4773 910 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +5791 5301 m 5706 5386 l 5910 5590 l 5783 5378 l 5995 5505 l cp +eoclip +n 6840 6435 m + 5760 5355 l gs col0 s gr gr + +% arrowhead +0 slc +n 5995 5505 m 5783 5378 l 5910 5590 l 5995 5505 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +6895 7408 m 6804 7329 l 6615 7545 l 6819 7404 l 6706 7624 l cp +eoclip +n 5895 8460 m + 6840 7380 l gs col0 s gr gr + +% arrowhead +0 slc +n 6706 7624 m 6819 7404 l 6615 7545 l 6706 7624 l cp gs 0.00 setgray ef gr col0 s +% Polyline +1 slc +gs clippath +3840 4740 m 3840 4620 l 3553 4620 l 3793 4680 l 3553 4740 l cp +eoclip +n 2925 4680 m + 3825 4680 l gs col0 s gr gr + +% arrowhead +0 slc +n 3553 4740 m 3793 4680 l 3553 4620 l 3553 4740 l cp gs 0.00 setgray ef gr col0 s +% here ends figure; +$F2psEnd +rs +showpage diff --git a/doc/fips-fsm.fig b/doc/fips-fsm.fig new file mode 100644 index 0000000..a4f0aec --- /dev/null +++ b/doc/fips-fsm.fig @@ -0,0 +1,199 @@ +#FIG 3.2 +Portrait +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +0 32 #9c0000 +0 33 #8c8c8c +0 34 #8c8c8c +0 35 #424242 +0 36 #8c8c8c +0 37 #424242 +0 38 #8c8c8c +0 39 #424242 +0 40 #8c8c8c +0 41 #424242 +0 42 #8c8c8c +0 43 #424242 +6 900 270 8775 9450 +5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 4837.500 16740.000 6750 6705 4725 6525 2925 6705 + 1 1 2.00 120.00 240.00 +5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 3026.138 8399.825 4185 8370 3870 7605 2925 7245 + 1 1 2.00 120.00 240.00 +5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 7663.125 -2028.750 2880 5175 4770 6120 6750 6570 + 1 1 2.00 120.00 240.00 +5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 7717.500 7211.250 7155 7470 7740 7830 8280 7470 + 1 1 2.00 120.00 240.00 +6 3096 1593 3380 1877 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3238 1735 142 142 3238 1735 3103 1690 +4 0 0 50 -1 13 12 0.0000 4 105 105 3157 1805 1\001 +-6 +6 2266 3607 2550 3891 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2408 3749 142 142 2408 3749 2273 3704 +4 0 0 50 -1 13 12 0.0000 4 105 105 2327 3819 2\001 +-6 +6 1566 5667 1850 5951 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1708 5809 142 142 1708 5809 1573 5764 +4 0 0 50 -1 13 12 0.0000 4 105 105 1627 5879 3\001 +-6 +6 5706 1543 5990 1827 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5848 1685 142 142 5848 1685 5713 1640 +4 0 0 50 -1 13 12 0.0000 4 105 105 5767 1755 6\001 +-6 +6 5986 7757 6270 8041 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6128 7899 142 142 6128 7899 5993 7854 +4 0 0 50 -1 13 12 0.0000 4 105 105 6047 7969 7\001 +-6 +6 7426 4747 7710 5031 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 7568 4889 142 142 7568 4889 7433 4844 +4 0 0 50 -1 13 12 0.0000 4 105 105 7487 4959 8\001 +-6 +6 5866 3737 6150 4021 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6008 3879 142 142 6008 3879 5873 3834 +4 0 0 50 -1 13 12 0.0000 4 105 210 5882 3940 10\001 +-6 +6 5276 2517 5560 2801 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5418 2659 142 142 5418 2659 5283 2614 +4 0 0 50 -1 13 12 0.0000 4 105 210 5292 2720 11\001 +-6 +6 4126 3573 4410 3857 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4268 3715 142 142 4268 3715 4133 3670 +4 0 0 50 -1 13 12 0.0000 4 105 210 4142 3776 12\001 +-6 +6 3066 5723 3350 6007 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3208 5865 142 142 3208 5865 3073 5820 +4 0 0 50 -1 13 12 0.0000 4 105 210 3082 5926 13\001 +-6 +6 4036 6623 4320 6907 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4178 6765 142 142 4178 6765 4043 6720 +4 0 0 50 -1 13 12 0.0000 4 105 210 4052 6826 14\001 +-6 +6 4416 7213 4700 7497 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4558 7355 142 142 4558 7355 4423 7310 +4 0 0 50 -1 13 12 0.0000 4 105 210 4432 7416 15\001 +-6 +6 5066 7223 5350 7507 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5208 7365 142 142 5208 7365 5073 7320 +4 0 0 50 -1 13 12 0.0000 4 105 105 5127 7435 5\001 +-6 +6 3566 7573 3850 7857 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3708 7715 142 142 3708 7715 3573 7670 +4 0 0 50 -1 13 12 0.0000 4 105 210 3582 7776 16\001 +-6 +6 2896 7783 3180 8067 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3038 7925 142 142 3038 7925 2903 7880 +4 0 0 50 -1 13 12 0.0000 4 105 105 2957 7995 4\001 +-6 +6 6426 5753 6710 6037 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6568 5895 142 142 6568 5895 6433 5850 +4 0 0 50 -1 13 12 0.0000 4 105 105 6487 5965 9\001 +-6 +6 3600 8370 5985 9450 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 5970 9450 3600 9450 3600 8370 5970 8370 5970 9450 +4 0 0 50 -1 0 24 0.0000 4 330 1725 3870 9000 Operational\001 +-6 +6 900 4320 2970 5445 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 2940 5445 915 5445 915 4335 2940 4335 2940 5445 +4 0 0 50 -1 0 24 0.0000 4 240 510 1620 4995 Init\001 +-6 +6 900 6345 2970 7470 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 2955 7455 930 7455 930 6345 2955 6345 2955 7455 +4 0 0 50 -1 0 24 0.0000 4 255 1335 1215 7020 Self-Test\001 +-6 +6 6750 6345 8775 7470 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 8775 7470 6750 7470 6750 6360 8775 6360 8775 7470 +4 0 0 50 -1 0 24 0.0000 4 240 765 7335 7020 Error\001 +-6 +6 3825 4320 5850 5445 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 5850 5445 3825 5445 3825 4335 5850 4335 5850 5445 +4 0 0 50 -1 0 24 0.0000 4 255 1620 3915 4995 Fatal-Error\001 +-6 +6 6750 2295 8775 3420 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 8775 3420 6750 3420 6750 2310 8775 2310 8775 3420 +4 0 0 50 -1 0 24 0.0000 4 240 1455 6930 2970 Shutdown\001 +-6 +6 2475 2295 4500 3420 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 4500 3405 2475 3405 2475 2295 4500 2295 4500 3405 +4 0 0 50 -1 0 24 0.0000 4 240 1470 2655 2970 Power-On\001 +-6 +6 2475 270 4500 1395 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 20 0 0 5 + 4500 1395 2475 1395 2475 285 4500 285 4500 1395 +4 0 0 50 -1 0 24 0.0000 4 240 1530 2565 945 Power-Off\001 +-6 +6 4050 6196 4334 6480 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4192 6338 142 142 4192 6338 4057 6293 +4 0 0 50 -1 13 12 0.0000 4 105 210 4066 6399 17\001 +-6 +6 3053 4358 3351 4656 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3202 4507 142 142 3202 4507 3067 4462 +4 0 0 50 -1 13 12 0.0000 4 105 210 3076 4568 19\001 +-6 +6 3032 5012 3330 5310 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3181 5161 142 142 3181 5161 3046 5116 +4 0 0 50 -1 13 12 0.0000 4 105 210 3055 5222 18\001 +-6 +6 7560 7847 7858 8145 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 7709 7996 142 142 7709 7996 7574 7951 +4 0 0 50 -1 13 12 0.0000 4 105 210 7612 8047 20\001 +-6 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 3420 1395 3420 2295 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 3465 3420 4815 4320 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 1890 5445 1890 6345 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2835 7380 3735 8415 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4725 8370 4725 5490 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4950 8370 7335 3420 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2925 6930 6750 6930 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2880 6480 3915 5355 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4500 2835 6750 2835 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 7740 6345 7740 3420 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 3375 3420 1890 4320 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 5760 4410 6840 3330 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 7740 2295 4500 855 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 6840 6435 5760 5355 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 5895 8460 6840 7380 +2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 2925 4680 3825 4680 +-6 diff --git a/doc/fips-fsm.pdf b/doc/fips-fsm.pdf new file mode 100644 index 0000000000000000000000000000000000000000..831c2ef85b64c90f55bd3b9d1f0a056ead1bf106 GIT binary patch literal 11576 zcmch72Ut@}x3+W%O?nY9B1$I-5C}zjuc0Ho1qdAydXe5mL7Gwo1VkxPL`0-Wkq!dV zdoNN&5dq~U96iT#zVEyLz5o9_|4#DkJ!@vxta;a3vv=Ov*WvPtd=P#?!1a!;yZHbZ z5Dav)b_7UBfYcGL_Gky7C`O_KQbanV5uQMhqO%nmA&;=D< zV}QAqta0~whRtQ5ZqRL0k^<=f7mz_jKhtn(yI2UnHZS3aW)Rc^ zu;l4*N4AQYYf5DY!-7mpi)C(`zg)TNmV42O-pOz`-emTTIFtp4cFWj?fUMSkDP3f0 z!{_j;+mE2*oxV@syO>I@kU%}(05 zjkwbu>w7)O&fIHJAMP}J(B56=YJ<|60$40SA#I3jdegAgdq>%m;OS{@%cE6Y35R9PkT)zsz{ zHr7EZ+h#)F_aV^sRac~A7kz7X>GjgL2G3L=l5zNw7e0f#D@IA{y+_LJT8zTN<(_=M zh{wYn9uk&~$00;&+WtK98WWC_z`TSJX9A;H3?#n?#>s53e=mnwxCPia-%-!&-z}&0 z_U%;OO~cOERUyc%YA1T{3{IDBwNEQUFJld*E~2*59S)AbVZMPel@(*^h<-T=UQF!% zP(mz$kvlRG&Xw9?#X|9oB>~oIa8=}G*)6?^TQuq~!K_Q24v9}PLgd1Omn;tmqNq&i znmp4&U7HtakeXFYj%c{J)`MJe{Imp*eYFCiL_1}6D_P&TqIb)h0Lx=O9c zBB$#f-a(qg!~sBGkS2d3qOgy;v zYjrc+mqH_XZd?mC*@FWZpGeY|N{FdH-qcyYn5x6YJi34H8F)lapNczxm9?lyLenaX zhAw)+F@upb!3L*gn*1{9lPYqtHLl3dN-t|#jUvNSkRmNs`bR83{YFZTV5Gq%xg>R- z<8ct#l^q)LkG`GXnfX}i7uLI;KIPWbr@clbX2hUJqL*rIN?6kkw_iVj<6CmFg{x(O z(~@+i+*y*EhqpL6r~TZctS{y9Dxm?LOa`l)-H%%(F1)4@v+kVv!&C?LBVg&K3 zJZoK#TQl->)?=>vJaISbkef|!^C(Ml=b?iRdtP?$Z0Y48WKoAmnm}v z-ZNn_1>0D{JB$rZvctYsWrr(8L*xqIQ_AgVVuN5vgY}g#WJ!8tVkqJ@O0wX``)en3 zjDFqTk)o}2akgG@NlOIcISCz4mk61CH`zT>6Dy4rr5!z48Me~jzA79{AR%L;5z|_F z2JW%L_lj_6&r0fV<=d3@?O~AQ^oHLOIH8YF^)iTvo9Wtkmhz~@Vh}1qu#clQX@XEG zmZ#k1rl55^etzb6ve7Xhb=&uB$!{~ug`D|xb})v-E4VpJ>)wkSZbXDP=x?PP!Ax>; zt%!T&>#tp!{TSCLNg*$5_U^)9r)bd|^lCrc%K3qewMA>QWe+=ThOViHb2mB;Z;P3c zlSwgBOiMleweANfms;eNL0@TSK*mP^Z|GHP7}vy4b-A zz^zDRp?Njjmm%hWi^g`oiieDvyS~v6&g{NMOcl4`naxq8Ch2gP$~8{ zACYp;g70UCcADt!g`Mc&yH}U0NY^bXMiq+C*~t0XJ_@ zVVkoi#GYoWJ%-CW;WOA;FB!nCW$>D1cm*38rYf7=DNkD{Zq=^@r!|b89WIR3K5G2_ zv1ZhUe@JMm9IX2>PMhpqL~@>bS%=YzD$?=h>)tK&lP?aHJ37&mk3)H0KlP4$GD#~q zQqC}vH-vG8*q8ETjfRq~a65~s`N@Uo&#qw~S}7-Phv@FmobAk%i?`#Nc?xgbbrvTD zkd{*@-K6Fc{pR5+Biyr7+A`FP=H;Xbm+yrr=mV%-CC0NI89MScf-e(v^7zxrGU{_0?!v|T8b z4Df*a;J#Ay(`WpVi42}TfM_p?BJNkOUyNB6Pj+Rd8-{Ag4NTI0t2T}1jv}&L;ledL zDcqZd9Bk%SROsFN>NegFJL@Nxjj{12N|kUs61ySJ`ItXQ(h<A zP=jYGD7@K={v>OyrOouX9N1r}$~~xT|44&5HiazhpuN^%5}alTyG{x)3bBa-G5Z#O z2Oi&}mn0IcHBqZG-X2+;4XQR7M=AgKPI9 zv788N_2nXyRe{l_DwqEEvgIZLyYIG3jzjR#8l=WvGyn zPu;R%)%VQ~K64FdDobun7G_Ls7c!>@)V%6(2_Ww~In>CxCOY@prDcSpG`$Z;(p^9& zNr8DFjXYHTovKH_INr;~`1_K49Tlm~RWXGQeu$;gR;KZTUPagKm)?B}N=w;SdANrc zeQUO_E6a8d{J5g|+P{uMseDSKtGu8o*{g|SAm49JG9p6$#rumvD~ldsoj1u&Bw!b= zFUaG%wO4(k(bQSE=Wf{s+o6V^^G+&<7;PHYrGm=S_@@#d($&^0d*#;8EC$In zJ{F=++EfwR9exomJ9enq+a>x z)y~;W!Q0w{u> z_FJ8AlMHiy#+NL_ZPQCHI4tR7o<&AHxA+1%WxA>To=Pvj(X z!!o~+q_6yte+{Fr{MKCZ4ri}I_dav-SGz6!*?|cLl-k(k4ERo4PPxfOfO^7>ilnlW zcnJF^<4$S2ew|lZ)2peIz?y+~KJv9=ugrTUmtXa^-sY(hf9$b>a*T@oVDV!r`P#Nx zrXgw5;C>jHYl<;P{$3L9s;y{btfe5IWyD8L znKyzyHKzG0qk0l=^Yn>_L*`8Py8@aF7o&+@I5pJ=Fl8*u)vE$dH^XbA9zdTYXp7nO zrVEv!)&%2Zwhe?N|H9P$6oct%4{dCm>5Xf6=><{y#T8Qn6b8#?ly}3emw7T?bUQtX zSeztm#QZn7K}&71Zuj9^=W-HN10C!riDs@hp+)}wh)HBu=$3cCvh+AzC}p9~WiV}s8oOFFaZ z7^@(1(P0Nsa^tVqF)0$rH=~^vpSw>J=d;=sC_uUck^e>*b43$>*#!|BNHR0L*k%tN zJkV#OOnjv2k(k=y&)kxEG5#t{a5?LTadSrP=Ox9|D_K!JAsz+TNTk7}M~~1qF819Q zwyhkwNfgz2COgh&M-+ZaMG6PsR6l#R)4mDBX%T_cS>>CuXMN){O$#tRlr|@!bA0*I znx%5zsVIo22X=4972KG%&DkBvA{9PAlP6n#QV@`1QmpKGc`2N|dQmJnq35LbaJ=_= z-Ll;q&+QE(=LyES!y-dyuaY7^U+jjBay>jR@(@w{3S-w|(Dm6=aC+q;#;)G9ZxE+Y zTK!e$6wGg$iG~S(pyZm@fqJ z?We3(1?@9G)EJ(7^n>VWMI1T8)%GWOg1N#HE?AlcdlnJ`3j%)1ME)XU^!(frAh?x1 z0;GYkMOw+a`2tPAm}((W5g=4V)C_>B^hCI#fr41N1_07QpxnGXZ4f97kpuU1v(ZJM zO+Xl`2ME$b_@Xh*6@1Z3x@ZiU1B3|u(M8b>(;WgmFJQPGkQ}Cr(TD=1u&L>O%tyMX70p@1MYq%8_)0>GNB126+(G7x3;@za`XfvP zpu%Rqh&Tww{yzyfCkKX!3m4>@LvXNO`Fki~G5Bfy|D{cT*!RCQ$;J|E5)S73uO>l$ zbEK}9H5wbuSWF;tKbghfVf%B!=YjOwr1f?E;M9f;bJx52xf2X5M|`(-ULQ?iHDAHu!_W z99|G&?eP{a$UE=C^4Ut?k898NWJ2#=IJ%fgA7dP3b;4^TMQsoqaS<+5yDA@HZ1bL5 zcerY!aDONQfrIntM=doo9i3ti=@o8t0h`)`hbo}e+n)ic#`p6&dw(P(&TEzEb<>FH zBi25Z~|XRAv1-mE$$yn*ieEOm9|zLqicq4DS5yAT1$E%u)u`!3MC^?5{{*?ww+omamF57 zePPn)fG?$sJN?Ce$sv0RLv5?%jL4U%dJl2T^^A;+mU$&owY*Ah63ks-K5l*R{HpA? z27J7Yn~*2_TvEAGcynM*2_gip@Wt}0LRn1?ENQw9y_tcJ!f=e#%rxZ6y1Zj_tnG7~ zipiWj3`E5GlsH7*-O_nMwG?$@mGzq{J_wAT9{o0c@6I~@q2?C`JVQZFCohuuOXAAX zB&&;VS~ojtY;<;f{TMk35Q_kt)CrttA!SwN&rXc)R+G$sl{gVDSl%7%=JGRjK2`)0 z#BwaNRyPz3;qKv@n}_nOg(YsjH|JkpSmBG9b-!_XREL&M<`vnj)!n^lipWjouv{Zv zmL<_XDXx27vpYq9iN%lHSXviZ({3ed?27lQdUV5C^|@gLpP{^h4v*pPVjzyveAd^# zf!k3nwU@#rrM4JMFEeIS(J4J#iWSz9L!oR8qoW@&okocxouqv$*uBppr~Fb@eCujT zorWyE?{zeGzb4)}lGjl2ctBv(*6ywA<&s)9DAS_rZ1de^uuX{9&8)6)8dtTw{j_4l z(6E;I`t~-P?@B{_Iloc2$OiRSKf=vvs4LE8vfWEAWOtx^WIKoV8*+(mQwdhY$!&xn zR658_b(2Cr9o?}cYjlJia>U3jT)BN%@_@y@({x-u!Bi#DyvbX4eU*LnxV7?RNsn|) zW_ov~mdmtCc)h2Mr*&z7^-bVzj^~gx4eK)H%${4m9))z>L`Lp?$K<6jQ6WdsPJ-xC zMU%?1g0NlHt5ROk#uPr1L9?O)s&{UW5e4C}yRSEFTV3KP5KTC^<#F?He;qzHoM}4( zm8}z*v+PuxXcAE(-`nnLkZVe8IP$1iYF<_BE_z;}*S*ih>#}_qq#zID*ZZGkPNK=S;lN=3UZPIkMMa=7k(R#BP`zi6v znNy>hUE@+NeUqx<>3gjvLn57DV+4nn2^pK4)ISDzz4M>+PJS3i2zXLCiz^(8Am;bT zd~52AOAvSv$6_G4RKs2{!z`xFvA9lwMCQ*2NisvpbQk71ofQ+~Q(xsi?^$Wd*hp_+ zymAHq8$BDeboSq@+rJ(`Ac7*WU-y5=Z<|E_^TqspAL+Nn+{GXOu4~BD1X<1*c0{HN zk#GrjjgK1B#+R4nkJ5+LZK@l!4)-IJ$cC00=e65pjZC%%Mx6_P7~pHLiP#JN~v zb);RZ7ylMBV8Qp?Nv}L7HD5bav zWFQ%)Qf|aZb#0*UUZir$r-{NyJ#hR(sc8SCJL}U*yAqSlG6&-hIde(hQ1nFenYUZE z2Nt{6E(*u%+ln*s8x|k1-4*i_(RX=lU&yLD|(p zY2H*G&vtQ579_c&wc0J~eGUBBwRpyo2 zGWbJE*-P~?4s2oL8uCnOfR@(CjsyTnRGq!8dyC6`-me;Cy|Gg@7L0?!RUF1 zXmsX1Iy{=fG4=u1Zf6`Wuj}MOfJ&yoN8TQ~&-AK;O6F0P&os5wNIlvEZ#=GyHy&)? z{6Qz)gjizY&Q>}TMHBPohMzTFBAO4m@*|c2w)chT^MPzbmWUUE_&ZzQM6H+2>f6L& z0@-iA`xEonm3zoGPxL*3#pGkvDN|Ex)W_W3v zHy=7Ld6P9UjF)}sOq}l`TnfI*0%&W9E5f@tWXaf|M|xMHjFo8h zBC5wSW*PP=S6_+kkeu?aCIlZ(d>d>amc4N^`{U4yryk{%>7Q;(&G*yvH(lwh5rTt0 zF_j8`2(fJHdu0f_PX^C_d&wngI+Dp5XFABm^0EG0gk*@XD9od{6&3>wJ{I4KwsndPf5Ui^jHrI1xczRTgcG4DjZMI}L`jPYLA zWd?~?C<5wm++$YrZl~8{w>_ye^2z-URM*eebNiLP@7R2?NjAQ#BK%|Q@rZ<2T8>te z`je>7QJPzH=84BQ4xW=9+e%!Cci$YS+IaOfQd`8}TN-%lb==Hbtp(Eo}?o5%Ob5rEe5Y7 zIaKGd2O6aJ@c~QUy^q+DKBYV)`tiYU`Q7ZW@0M+n`1}W1gv_6a6 z*Z1;E@Q#y)Min#**(M>)3{jM!cO+QWBgxc|^5{kBU`)$`I=*yCcfw`$ii=$#3j%+h4X7 z&?w;9NWY|akBjqhzissgJ>jeLZ5Kg!7I}0*2ae;3HQYllnoOPEZ$Lj)HIQZ@V0X8k zJ>R97x1>VdGyG^wem9x+=z708eOHZua$lbq4UT<2PTYH>hzZa~jna!sV&N+v#m8!{ zmv{U_*GiEUVwWT);aN8doGz#eKX{oA?tNg~Jj$d&@*3Yma-D_gW2svOLneON>l-M+ zFc!Y@@~cku$!w>I8`Tk~yg_KnGve0!XZrTSg>CH;MHk>z24!YF(zg+G{xiIv zznu{s&q(D8vOgDI7ct7Y_omTcP5zNIZ|n0AP?Fk5BfRfije{nOd1-#1XG6Z0FIHrR zP8S~8oKik#9#~`O?C#dl)z=qY%uK4BgcH^A2LuOiFU)&ER2C{5h>E^m1YHr+Ue{sc zlHya!VNVhch{q>TQk(jcZV6$TRG(yWDq-|~rA^j(Yoh;iWzY1;ty#Ljuahg8Hr~v1E2F-JhLjl0a)3>Ko=20NAw^dc%Cye3^N}BU{#e%fTSxo+ge% ziFVV}X`A`dAY-@LQ`|seBS-e@eu&EUKn2Dp3?Gc0;4EQshgIkW zb#l~`)u9^xY7s+KbS!dA=oklv_Ka38rxjKCFjy}{b^yvpv zM}fGdp|3RQayu{H+6vz?m!=)7d3 zMhj=>Gl>0u7?-na4>3jXs#SACw41=K;MRp|gCG9PN*C8UI80&E&(@5t+d`ooE~Mc;04YM_+U`1I{_tmi49BA#&4%%&le>N z!d;2!P5T)XsrOpun@6g{6>f3hcc8MOO&&AG_V;J^Kv*5`sI8H{f<|6@@X0L2Gr|6< zE?IB$TdDUv7izWe$_-!%oQy-)FLd#VWy>Ui__`Fpf=_P4JG~YLHX_CLTqAYkb*`Eb zjW%SWPnMsK_G`XZXeEven^+a>%$R z&^;7<%2FdcS_Ox-BB!J%(@7vD&_oKxs+zJ^3!r{fFbzK=4Bp~hjVMLUUq z3fkClz?Ty)lz%D_xy_;^F+2I}HFsu3RbF?Zb4B%7fd30!I?y=rIzn6sv9Wk6n~l#B zHeFD>@Sz84IZ@;VWa}Z`+KmPLEPuY=+k5hYdxsc$ZUC&8$M9l>= z(WTY_Qo&W>SlY2$A3RFu%^p>{;{AwZ<$fE!Bw;%+Jd6t1I#|`H?F)zk{vhLX5&!sa z9$tTOY68MS0)IZd{zgH`TA>hF)(a%7DT6t9FnpCK65+|GW$ldg@Ivq*QEnh?y*vVC zI zpa182VK5l@Klov}KUd8ATS!-XjA^bit|;W6<-a}6|3z}0lU_d=r9UxK_yaRNqzeMY zr-R|OT>mXz0{V-1T=Opd_A-QBRTsDTv=EE@0!h#SCd@wUC8EB6JLIEHdlns{D#t1Qdw3WLu z0%`B?vxrSfY#pW}0HlIpk&!ksuJ#!26hpJ>q7g0zKv5x#0&n~C{KIAj0Hk5%`+EtA zLSeGtHwiX-F-$op2<_trLOXaO5Fk6ungFsxdLuw6q%R1C@J6_T&aD8sB3%(6e}tzS z$jueObv|DV-HH$do|B!w)5+Kz_@5y4-=x$plms9mKw(iKpfF7E7fje${)7pJNvq#r z!WRF83DfgG-~<67oxw(z(T@M%zf+cGALLCv(fN(nUJUehMf6_Ohg#7MEyes1^;tgOatsb&p+A; z!T#9}0v5n*Fa4vPs1SA;{99iL7%KWN`b0(k&D>znf1NK3_AfH1fB+^={x$|!SQz%t zalyhO;D2Ku2KB%9#mobH-~Oc!?P-O{Q%}r0&cO3s7L4D3ARRY1%vKe49R-3^TI9S$e(!C~B%cQM7mS z^7gX!ba3~6BErMVry6{B0suS#yposEg?&9(L`<)-S4UZHnEBi{?89@O3H~N|&`Uzv zIx17aQygM~jlz;W&R+iOXW1YXa<{*PW6jg2>V2+@6^O&dm;m-HLMMLlC3<_g~&?aRGz20{Copt33&T7 zq(!)sTiZ@NQ7VV53wt!UgW*C6YmNk}!@DpZzK>PQ2m|P55+(2n`3#Xa^El9z-kfKxX-Qw|} zyFYOL^h3{`pQjbwTd<|STy0BjE<8!17I-=?wCLatXS^%TxM;hInih0{%4tX84A!gy z%6aWY;4>ggMa%1JFKwWE=zmNM86uh3=6JWTAp({r)2}NbtNS&+u6^rsgW6R(Pp;^w z$hTRZ7OvB~H|RF7Gq)=x!n}xhX?Q@fDf5Y8QEG_}K60`$E_iP@K9l~(eEhs%*)V`U z)Ks5$7BJwds+ zcP{Ye&lPJ`o`7ajXme0DuJQ~i9^uM#1@$C9P4W!zkwPc5%yDw{Z2U`i$3QkoyXe7Y zl8XkXl-euirCRFoaqO{oNUZ_^+)pkHlL|OHQg6(!PO>N1LQeM;=2SUbIiguMI|I1> zQnQMyd_G_nmXJO<)6eoY@*PI8qkE_)mCwY@uAq^OCO&%TfXL8+2Ot>~sE5gvY&TrA z`#0`O%Tl7tnLVXXPS8#g9571i*gB496-f0KiDiZOLp}bt?~#)&9I?$o8_B|UMI#;9Bob8sk$j!P%g>pLu0958X-3jQkQG0l~lS+yFBNhDmu1gCKB2CD1k0iONs1wUyIToxQ%1n2k8=n4*{o=0V2h7)LaqkU(<g`(uS zw-CZKtn=MRy}}ssqg7xJ-=Bxb=B1*kMs)aFJP6WWEAH2*Ao3U-g}h?FBup9-?RRo+ zrFfXt9xhq?;*zk-D`tSq^h9VCSZ@F3>!2CI-Nf%mY&E+k$-M6S0&*E?&b80HADHgR z6uKJ{brxuJNAHWd7~}Q(iU+7ao=V^(xh)Q2852G{!p6Ed646DxL={P~;5{)N=v!MqfMC0$JWH3hC^tn^;Y}V1l$X0r!guDgv@~aU2MHAQ7VEw3f;2%VqpRef1SA%c;wYc&;t1fL z*b;(q-~c*Cy6e|**(2@`FpK;(@~Ytgv&d{r!9rH0M4e5I=o;KEY^3+=JEMdaTn)BS zUQMX`6IaR1cTP~iKe{p07XzHgiC%r%bA)Q3#)FWDM^|G((?V!tN`wHge)POF4j3@S z6dYwyN;IRF=92FWc))Y-%?xulZ9?W+08$#!lW`c)%ZRH6eT*nb8a-uQN_214O+ytq z_mmlidcIlmcIBJCk!l@QC)ZHN8%%uQr92|TIF9?CzaIcK9#>mTFp^a}rO-F(?dTp| zT7a|rF&bm>fcdY~QmS<;&qMAspN2||G@<1d|Uth7ex&OZXqaS8h=Ordc=+1jY zD$()0*@>>JCh^8>$ajb=ukZKZ@4nr`D=jU`T(#HX-qE3}e0p$BMJEyZH*g6n2x;jG zO-lclYf(yWB#(dqOp}N*Py+ciDVF_k-h+Tx@!p#9>X#0;UG8t4FftD=^;_RUoz7&! zqMTmrKrNu)CS7%I)$iYf=-K!VG(u|1Yt+SAoGe;Ka@x z;4FJ-D9)&ocbx!ppt>}@0LDEcaZ2)yW>1*^37NMwf!OGrhDd+qx^NZc^G=E|;Mljid-d~9lCb{> zwcp5y{FLRsoKpU!KJCN_18N?Od=$`9uE4$~g@!s_jIp&X=>*V^VSL4Z4cnoPDJpXS zIgFPq!JrZ7&Z9on9iL7D$RmPpUdtbJjH_6oyq^?YdEX+9)DH8mT}39~7i}HpzYxhx zK4PtRv%M!#DgC~KsXQ-HWxkX}wa$?j*w>uyh~`sO>Z^J4ZORl0mgLXMLe@e*j_gS# zZA-WspUGCw?@t@}Bx+AoW zh~+A?5ZA3UU|_;E*=!p(v*>)LD@L*A@DXdzJ+)WbN0*jMz{V^-5FD^s(3ifF5(f=E z4Tj%AvfqtkWy7hMA^>RPK@+sT61m|Kl_HtC& z-GJHthYp?~6XWOAf-Kw<;|;of6DVH`15;+0H%GZ|%N-B9<@in(-LD_J{@0S@GZObr zIXmEf=|b)+S+8X>dNFl-T_>|ay%P56UX4?$YX!l*J=QwxnmuFuuKbwFYYc8E%)2ty z%uA~5qKd$|z&A&~Jk@ol! z#>tcj@HE!*%@6n@3131V29<%%2wzs{fw^MaJvL^rQmeIR8a_AwHTfh@+LfOkq#|=} zo^dU%H8jMYo|0WuAPFECb_Gr|!)iGfw^+DhKFuf>RiLjl&NG)KTHgC2bkDloKh;VT z8+nrjm+^)?S!hYVJ$ZG|$zwb1wr$WswdwQWZZBKlEHr|MOj2m^SCT?uaK&VK>B8;6 zaL!Q6l((&l{}WxTl@ZMqY?W+|5G@Yfs0M7EJ!6M?4AxC?r!p2G6HznsuvKf+Ak%UA zuSoWP$EE*w_!=ILqI)HcjX}S_jts(C1zdp$jP;bER7L+2AAb!agoZxCnE22O>`u-w zJKkzVwkUD7oO1_?X_+wK-3PI)CxPB^yZ<-}1qJ{P&M3J}5(MO@E_X1=S{{xAhBEt% z$e(Y2z&wv~`HdH!y2p?i9O=gPyTuPDZvPxyozb8kr4k$tyJg|3SyTwf+yKm8CnKJCT z2Sv_$wAL|OnhN^;B2l?u0hr4MW$LK^SvUNhb+6a^;)ctc+jIf}IR@uqA)m3gNKx61 zg>>ZaXD(j!A`zwSQiIh}OfWPd^OiM><#zZx#~+G3(ku6g$fNxmX||tZK-x^+R=n>i zGtXY48U@{RlC8GGx!V``#N4pQcC#00LyxApVq^Ox*t`|03=Ajg%Wg_Tgupflu-9Ms z8d&EgPji6*G2cRJHeQbZT;8U-IJ&IzJGdWkOPVIH>iyMrkiT1%wB>Ni6jGR8A_Nv# za6QNA+*gDbWHa0z$8{J7h}4yYyW(hMyrIulE)~0}skojB+D{IdPkI=IbZ(ZvsC+w? zv7{{_0P?Q3bvE47jLJ>IrqQ-L!hZF|vFE;3KlEqE;SV8CS1wqO9}U6i>Z|&RnX5g8 zs?u`(;n*Y|@6pQOMdOCIgiB)2mcqQ=`U?~!MiHUnkp44MyJ{|fi7uI^BdUi27O{ z5po}5so-!_v^S75hty11J z#*7gFePd;|;!Yu&;`U8gNk!yehIog6W^vf8((u)yozeIU|bW%~wgtB?cs>x;ZdUhj5 z_NMZMGlI0EpqWbkyX?!*7Q8Hob^IE>ms40#uEs|E<&Ppx)R8jV@O71;I`{7%{cu-m z>f^_ohxnQD?K8#JmI5cv=3I>q#v!}g%d#z0N43-@}FfZCnt z{NQ${@@TbGPLVr~6{If2BypD#4y-IOaW`VW3MBma*J>!nu5xBocD?mcl;kn43nzEF ztrixAKFG{8dTu~;)porEFU#*N8G1aQX5yr6jH2MNRk^o8Y-Z-vA}enmI&zkH)l_Fv zkV5qw^%M1rhzpytpr?p>qyAsMP0AbSx)57-AF9Klm#8Ua@wss;$VwLEis(I2$Pm^v z|0glSP^5zn|1Etx<4v@^UPuMlm$WpzyvEka>D{ViR`6Lo9(%9cuZwGGwmFXis-uMd zg*hk)uKy9c{jMHMuK4%DLs|t?Lhr&H&Fix-Y;cf_FI;9=aXcnJB0wC3op~m*nH<#N zFlV*9c*^y78-UwbP>YPBy;X*F)ND`K)!r=Ep$Pc9fO4~^P& zqY8PTmMHC5hEPOu-N&7&@us8pK=s#aCEd+}UX8mo2_sRo>3o0A!L1|W0kw3T&m^#1Bu8ITl$h+ z^kcqG${WC$+Ql=>8(+~2i(5?@F=y4LtUSz2#<%x@t9^FLW*g5xRmu^0Ktj`7Yi)F~jr<=s{0ey-D zkIvSnXYtSxH53sQ{vcYp5J&83U~3U^54{B4Lk-VjEieN4GPmIPq^= z%{L)fqx%awDNmY}&;&hmJBQRNLp>C4q@dg>r;T+|Ws?v5Q`Jh|nvq!dp-%rTvGM66 z=+_#-;Ev@^IhXIT<4t;ZHiJ|^1{0-4Rk7SXICN9+Af~iF>P7vM*N|RH#H;;HoOs3(~*SeplipLRw!5r2t&^P<5m)6OuC}+2i#50tj`jPbV@-wzJzG)UQVMoyr zu{u-BhN;ypLM3{ny9a8F-H<%9PCE~MHF}#(TLZ*=835!baKi~xqSw2gi`=T>LCiE{ zn-8QtYp(%1^8G0?R%~$>-b3`=Ua_$vkQpCcDU|Ohp#lWaInnVX;gGTmH`IGEMS)z}nc%5sy_Y?nLGiFbi-B|H9Q7vW0u zizXfV>J~4#qfQ#tI)BuhBi<+ocfq338dt|fF+c7BCO5BIIeVe8*Zp);5BaEY4hNIK zUhnUyWFD4?$`TXu`Z)iR5+KNGHQT=u!5^v65#O|czukE!MG#NeiV0%l*eKw%sw`dr z??P21(!>7Njh0MyHZjZ&uWN1LdQJ(?k}pbplLRXCDR^I6)Qc8mffd&Okccw)CO9W| z4g5A>LBNr;EBwQ^dw>}!^fIopiwESFzyuo$FD1^&m_TxvKDKxK3wwHEXbrZ$jm-8h z{yX>pN;DrLV$wsO+i8f1eEaF4hWGrM&wA5Q`R0iJ@b^b$Zc_RI@T^}B2N}C|bwr}n z#hF@DH@Cs$;QTU>-{EpbYQrQ#BWXsH9?FoCo-#R7WqMN7F+H}-W%V}Q%H8-JMx0fa zKk@_n%%x$3U*&wr!oE?b4`0d(^Woja)@Rm)|#82F6 z)PnpLN1KUc;C*WfWb$`jK!*OWbbe0sp9d>E@+R73Qr(9$L1iHl@#}n!wzZk_5t8Vo0M_Y2j#x?`T>@ zNzd_lM|;zn+>e4I&t+rLPEpLxU1e@jvDA9Sv*p$XTv4wew>OQK`pf1-md)^9kl(sU%;;Y{NZPo8fjH~7SUYYF!m*-evUNQD!^FXX{`nDM&&3gv z4$l0Tg^XrdSnhYC1-UwV7q;qYRV;^3u#3-qhgVI9YTaTYG31)Q9=f%6*89ed&n%=l zT7Ylo8qb)Ath(WmWOaz=FX+6FX@H7*{g+=n+5=h0iOi*y?7fAfM=g=sX(Q_9pKdN! z0wbbzYz)W>LRiQ@(x~k%E01b^3#ymhNG4PcF?;1gtqd{8{>T-EkyM$G z9JpRNcxQ1;GPe%AOEqA+>?suj%pqLD%o(g~#PnN8p-bKiyx?yeYqDiQliP0}CnG%+ zAXzt%)*eoV$mxEw1kck_Aq~f@mZ2Ik3&Nj&I5D=8&hr?7Z6O}kA6_IXPz_}L>i_4K z1SiRVv4fJ=ArK(_5(P_E`?MuPABqq13u1;jtNitCzZ=Q28^_A0`)4Ej#{%P1w7Vw; z@8D!o9X2YWE>nra0T%i9`CH!+7dm8;u^)M!;wT?JFDlClB~9{Wn8Afo!i3Iww-*3- zq|nl~J55)4`{n!)?TI#AS&$#G49flj?X2s&eF9?b4pHNex&}#uA&(qYIb@Y{WoJ7H zniaP$JK{ND%-!Zg?}80$&QAG8qwo|SaPs}JRrTF0=LoD9;PZBUV%_LP9@ZZ!@T@ym zV`oBrLlLXfDkS*bUQy-jo?FY}eSh!seeFK)xnMH^a&?#b>`x_k4UNbwkVorxp2+WW zKN_gH)p@k10?PVJh5k6wM4}Kl1GJ=K!b*G#qGRSWu*L^v%6p?N_zgGPGSoVe!GQW0 zO3E>ww9lsA02>D-`Y3TbE4>Wu#doqhz6=tW&y5~zaP^iGqVYlHXQ)aA&q+H9@6#!( zV;v+&_rScf(5qoHbxmnDNIrwc?I*@)cnP91KcfHZ)}6A(tS;Y`btS% zLAcH_hbQ7Kf7Z~D5tDD%hpZrhK$uo@9zQysSDpi(HS@(L!tBa*0A@3in3 z9NX>}?S6p+zGF-G&#wug5e|RBkzmzbrB)M*Ld>4Tc8+Ulxx;#}9oV$Aj9N-^aVmP)7R)x7z5kWA zhaS%x7tHY@LUXHwZsoA(sd2#A1>;!4o`iiKCrpfYJNB32+Lvr+39Du7@XI6ap)9Q} zVVXJ}iv>*#=8FFXjXLX33Tg^7OSG6O&DMq&)4R)Qp*}_EWja1j z^Y(Xs3AInmuC1D^ak+*w9O41L`gRh%`##51k%VjQKQCDROkJXKnzBP?%uk3jo=jQS)Dko)iC$I&pk|>X)dW`aiZM6ns{-5y&vGVnvLS7$8Z;}JU z)`H05$Tz~Q>mNiVCwO4v4T7BsDGsRu2lUue2TdJV^Ne8z`xpDXqu;oK!cxg%C6&sA zgk?9ZlX|ff%CmEq$+tAwEY|@iA_t*bG~rvyVu}t|`LznctIY1omShmS_-KKJ;DJ6K zwGFlm3C|rCQ?wQhRQT8y0xUVP0NAK(G)5c$O>6kkyONnduz2xFti;=Lyhuy zM|Ovy9^$xM+;_25V)8oldGO=W!X)kfZ2MaYLK5#|Q#{5KiqiHL{IfiVIB$-ue=dYW{dO1!akfMZjsaWr2cf^E``!JOR`Kgt7tTEvp?3UWTbpF+kSIAce zKUe|qlfycer>$36eaxR;`6NV0&uXH zh5bQ-4aHl^ouUP75yB~%l6GLE4vps@PRbROBeaP8@Ihd>K@UcrD(CRM%%SU zUBa&{fa{l;F3qVzj#x{((sNrhX`{tC=u3~*+~Cq zQKdB1q20cggz*S3GDy6IcM`>uKvl2mMx-H+4jav(jiQuR{Ms5`L6Sn_-O}V)OG#5` z)pRFMSU>OZyKeSTtI8R6&zHoE7cJ(o`+NhVy7La|N|~G&LEGQQ*u~EY7b?oW#Pe(Q zrFqrZcg85rbIjCBd|>=zcqMu0c@dH#{E4A3caYvWA#i91A2K|-cTKo_k>4LQxYo(h zsOjyuD<}}53i5+2*C<-rsjsjuwx`BLA^FCa9G2=$Y9q_JBV%hSqvjl&vby!~_v&nu zHi>IJm%*lbsM+0{*@-DjDPEs-Z_zE0DcVP}FTbOm&c9OhB?s+Gn9rOoiHo>gTUDfs zd3En7ov?E6Aq1y;z=;{h?zeBV0RYmaf4BhI@7$XzsTYqX`dUO&()A$g7d%46j(oXu zHs*dM`AD^A-+8`EJJ3=8AmMMD8Rrq1WtMYHJXg6-*QrwpK%m9;y#?wnPgc9$pyb!- zUhI~<)}nn?llI@#=ewcn!%nKlMS&r|G}mt625N)tkzmpF zG9%JVQcRB2IY4K~xL}-iXLqhqoi6)fAa6O_{ZV*LA%$IWRSIu#m?&$Lhdj|Ptg*i&%POc6CCQU&{Tgs2>-Jg%AgMSZq$ZA zcS#wjV4t&s;qGX7=b91c(1)D04ma9)G_0zVyF@_-PUTYJzb*cl;cC-9ae_uhI_$0Gy1^MwRJV>&!ozl>s zm4WdD)Pm2pA~}6LlCQ{GdkO9%fvzHkdlOT{=3%^zt+zQ)Xofvw-ePEyMgdcT;al68 z(Lrc~0@AnX4s}1~^ zTvs*%T2SZ(edchsTdktE3=nuE@6B@+;pfetBy8pQCcV<}GFU-=tg-sSL1_3NGEj!2 z%HZkWi#_($Zu3ZU#?d=M%pW8&EIF;rE`IOc4u}VtuTf`-^^EuLxP$H7E;tcvC@*Id zz6C@)Gedg&SL5F-%hxrMr9t+yPA%&-?@dkBenxqckM|=-`4yJDW;hG#WCh1sS-!9TzW?;Qjo~c$$6=4DN~M?Ioc;! z+8&mTpK1WW-dT2$ooVl7dmlGTatCZxGqbxDS4KR)d01O|)kLpd95tTzt!WX>?#$H9 zTDW<3I+|^;E@kj$J%(*Ki<5&-e^+|X_gT}YjRei*ZUbaidGgW>`4lvl`S!kIx$wlD zD9dqhL=XWVo8I${3M@Xs5wCRmwHMwIUL+NfZrnP+Ci~k(Yi?*4`XY(r`&`~72hrn> z@1V-*itmUK6zgV`_zTTy*qOt2TUQ=yDut zx|gwI?ds7uDWOr=bX(^`KtV+YEgTSS5pb5uEUcmrMSOGeB?`7lR5i;gDDKg&$-HJu ze>-Tpg2wfAQvqKHZ|lyT$hjlxei5i>-}*jd*jbZyB`E0roI9GzukC0#C6rYit5MwU zX|OZ7$23m+=^J9?I_0TqmnC6K;mG0V)F6$R<&Y%4spU5zDOWP(BVflXmaOXxHx;Kp z9nS8zMbmD@=q+r6BO@-GB5H|E-;4s+z){^vf_d$|@u|`RH>!Dcb>EvHgnFJWx zi@*3(OYM7Y(b30_)ho5iWDSacGS8Uw+{4__Dn{Mq#LapZ7&1 zaU(k?cczp=(@xy8C%dwf{n{)mkC`FZj<&Wx`pn_r`(D2XI}R=VuJ}EfK`x3kCUU zWZPg3c7NXSsBVVio;VhQ?|sHYb-NDb`E$eK6RvD73HmQ~bw@**uV>C~Zo5fd7(d;m zeNuO0SehhI_JD?O;~0#;QOi-)=1~QaN@2OW$mSNG4X_x_#Qn-Of5j=8nZA!uG9h!5 z2o?w&Zsj&8pv%FX%n{glV!Gx(LRT2XQdhUplz%r-`?4uE$oUWC>V53Hg+qr%`!3%P zN$A1V2U$y1+OX2Yw~^gF5Z9$Q#mdnKbttMBcZ&wkne^4(0lsAxiCnSoAFcm_7r%9! z257Ao|Av^|_Ad-%7SkV$oUmcfm!0N2PHRVp6m}@>v(RY}FTN1eD=ODkxP38V)iA*9 zkXLVr_*K+m!%74)$T#VkRHeZ4;&asD@ewOq zz^J)*>dUZxz^%*maIY^x>g2>sg(!B;3?8G;v*Gr-^RGSau$)n5FHohYV%YH+tifFi zcDnk*MM?P8!T6-L+B;spncMNKj3RmlO*@cJyDA9&jN9JZ@uBoFtvYjU%3gGF(LrhH zPc};F3}*w=V*9J-HY?$bPfYHSAi1+2fBG_+U|f8)E_m zt#Wiz3yc!!4$PZRqVuMzS|sZ;8R!^)!S#9y@h1T@_Ce{xGwjs;@`}yf0}7CzcHw-m z0ffa1k?*C051BtT2v<*_|^I9$rBM%I)u4N5eAFa4Q zKX_FVJs$p~%wqqp^XA^(o+%?@`1<-XmPzqse9g#3QY}EpSnMqY9JgUV$YwhS{{k0` zAe4({dURemtx8oiTBMyAEo7`05TtaSRaM-`Jmh#Me-LqpLQ%ADYy0C=ulF3kF?Xhq zHmG6ldcD4Y2eDSp9B}r@6u7i^iRWCdsQGC`4V^o0E4YjBJ=NlYzd^Q8A6W!AcBvZm z>uDuV2DC^7rZ4&Ld{=NfmfmW&6QqAXEo}ahSXOwYG>O+?{FIH={at@Tx)@rON9u2x z(e%Q~-Rv}Z*_Ems{XO=uxHwzEh+bB5vfK) znp+hl319PPK*mQ?DWlQr!w`ceEBlE@x$p2G^AXydl={OPY2Hw*l1TwG@6QKEnF@2K=DE_D6H;{{9UpT7#7g$_nSIV@rjBX6B@x_$VKK&nTpnAPT^P ze9u}nd=~F1lF3^zHe|HMDb?W8#r>upk5e$u`*-^`pex_Be(3hj3;wNVphod(lb+p# zTpSV?UgjVF@G%ptY#?#KWW3RBrDW#*dbZ#+Juitqd;M(1S<;cS%er$fhfQzUfGJS3 zqGV-|LRMQ5S)$1F57#OZvG#(zT$pE+zWsQ@Q_&pKAldKN!9XF>(L5J&ds1pen|$qKi>?EQE9 zw`9_!QHGE7&Z<&fe9Riw$6W^6cz9rN@VZ@HlRRpc-|Y)YIa;^4uDkf)uXENj)_6it zGG)C_$mWJ$Xwn;Y+3IQhhZ-ebq);V?L5R!z=XK@YQoEN#G9ak5kG!?5QjWU`eWPdn&*UnmR#cFlJEcw9Vh}Jw|?reOqVQXFN;E& zIxN&UcyWoYuxC~#QN<&%#{RyKU%@yjr>9(kpo zpnyV>S(Ws{^Y?>+eBiEd%2HzrPj!54pg9Q?W^j_hiFf6i3ja$_@dT#15z$hj6+YGF zhXbbhlur9lg0WwXpN$3s=IwjNwhR}l!!d-^Q>Bb7T(~9KLFU@Z$nen*OX@ISCe=0F zPk4@1;jL8NgT3ym5hssTrY{xiA)17){bNWW_ca?$MVpv9uq1p1ljEdSMy|@% z;#cI#?pizy12QjmB$uzuRBKguw=2=BcCS7Fz1&Unx_Erq#=<2>`_?jsZZC`fmnuh* zRc|<-5k}>5ofqmiAWiKeG0&3 z*ncOV{WoDi<&;#5FrZk)O}*A9d93EPMMxYPT2D-mA@y2hI49q3jb`8Y%xQLV7R^;E zI^>{kZVwHdC5qlyt4b<@D#MUn4^t*}2x{2G`IK6~0vOh(F+n&*QE>QzKPqMk zTDtT1^6RS-xwI8&E}l-IGk#r9w0t%*S2CF-+YRb|pCQVLVO_N6`ha}N0se>K{p!`Z z{rQm{squ5vCo5+1Hn!VjXPvu<{$#P8`E`SJ%8IAi$|fJ%`O%{@E+l3QVGP}!hN^X4 zY34}(BUj%W8gqZxIQN3AKbGw2$SIL(e-~z{qf*j$6mOT8?nMjCpNF{V#DNx`NrQhJ zb=KQ`-oGKkv0av$x}cq)`0Mz<2E(qdm^jOA^LBlV!qgNE%S(t%p@Rip+A3T6Sc`ZN z`zZ+)z3bW;FrDN_s^hl_ZpcSn;Y80`P=aoQJR&@czBMm*T40wP?#!^tey?HZ!PFp8 zEy*(nbZ!0FXmki2V*PcOsEeq8D*iaawk4ghsMMDc#!K;kqF5yjy~W~Ueh6iRSpZZ@0U8)u_kX1w z{%hq0_HJ0z0FD1sX&z;f#I5`kE4oHo$x9eD7Mo{`nK0Io3vtYfM} zi$`I=TdGr$m%A2_Fktq334k$XEGv*7hEX40f$5OjwGaveV!xMgeUG73$VOQn?&r!Q z6m~6$2B;tAA63VwW9#R=>x9)>)sGo;T9Jzk9lt)yP2eCmOJ2jV5%D(n%ndz!dY zheEiEy7~|Umq~R7x~WvCV%*_08c=j zyqz6eD|vKJ39fxchaQ9u_|pSA%@cs3pN;_UUqArbeb~|iFn|&@7{IZH_2dl{Q1I{0 rfB%GkYr? + + The name space of Libgcrypt is `gcry_*' for function and type names +and `GCRY*' for other symbols. In addition the same name prefixes with +one prepended underscore are reserved for internal use and should never +be used by an application. Note that Libgcrypt uses libgpg-error, +which uses `gpg_*' as name space for function and type names and +`GPG_*' for other symbols, including all the error codes. + +Certain parts of gcrypt.h may be excluded by defining these macros: + +`GCRYPT_NO_MPI_MACROS' + Do not define the shorthand macros `mpi_*' for `gcry_mpi_*'. + +`GCRYPT_NO_DEPRECATED' + Do not include defintions for deprecated features. This is useful + to make sure that no deprecated features are used. + + +File: gcrypt.info, Node: Building sources, Next: Building sources using Automake, Prev: Header, Up: Preparation + +2.2 Building sources +==================== + +If you want to compile a source file including the `gcrypt.h' header +file, you must make sure that the compiler can find it in the directory +hierarchy. This is accomplished by adding the path to the directory in +which the header file is located to the compilers include file search +path (via the `-I' option). + + However, the path to the include file is determined at the time the +source is configured. To solve this problem, Libgcrypt ships with a +small helper program `libgcrypt-config' that knows the path to the +include file and other configuration options. The options that need to +be added to the compiler invocation at compile time are output by the +`--cflags' option to `libgcrypt-config'. The following example shows +how it can be used at the command line: + + gcc -c foo.c `libgcrypt-config --cflags` + + Adding the output of `libgcrypt-config --cflags' to the compilers +command line will ensure that the compiler can find the Libgcrypt header +file. + + A similar problem occurs when linking the program with the library. +Again, the compiler has to find the library files. For this to work, +the path to the library files has to be added to the library search path +(via the `-L' option). For this, the option `--libs' to +`libgcrypt-config' can be used. For convenience, this option also +outputs all other options that are required to link the program with +the Libgcrypt libraries (in particular, the `-lgcrypt' option). The +example shows how to link `foo.o' with the Libgcrypt library to a +program `foo'. + + gcc -o foo foo.o `libgcrypt-config --libs` + + Of course you can also combine both examples to a single command by +specifying both options to `libgcrypt-config': + + gcc -o foo foo.c `libgcrypt-config --cflags --libs` + + +File: gcrypt.info, Node: Building sources using Automake, Next: Initializing the library, Prev: Building sources, Up: Preparation + +2.3 Building sources using Automake +=================================== + +It is much easier if you use GNU Automake instead of writing your own +Makefiles. If you do that, you do not have to worry about finding and +invoking the `libgcrypt-config' script at all. Libgcrypt provides an +extension to Automake that does all the work for you. + + -- Macro: AM_PATH_LIBGCRYPT ([MINIMUM-VERSION], [ACTION-IF-FOUND], + [ACTION-IF-NOT-FOUND]) + Check whether Libgcrypt (at least version MINIMUM-VERSION, if + given) exists on the host system. If it is found, execute + ACTION-IF-FOUND, otherwise do ACTION-IF-NOT-FOUND, if given. + + Additionally, the function defines `LIBGCRYPT_CFLAGS' to the flags + needed for compilation of the program to find the `gcrypt.h' + header file, and `LIBGCRYPT_LIBS' to the linker flags needed to + link the program to the Libgcrypt library. + + You can use the defined Autoconf variables like this in your +`Makefile.am': + + AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) + LDADD = $(LIBGCRYPT_LIBS) + + +File: gcrypt.info, Node: Initializing the library, Next: Multi-Threading, Prev: Building sources using Automake, Up: Preparation + +2.4 Initializing the library +============================ + +Before the library can be used, it must initialize itself. This is +achieved by invoking the function `gcry_check_version' described below. + + Also, it is often desirable to check that the version of Libgcrypt +used is indeed one which fits all requirements. Even with binary +compatibility, new features may have been introduced, but due to +problem with the dynamic linker an old version may actually be used. +So you may want to check that the version is okay right after program +startup. + + -- Function: const char * gcry_check_version (const char *REQ_VERSION) + The function `gcry_check_version' initializes some subsystems used + by Libgcrypt and must be invoked before any other function in the + library, with the exception of the `GCRYCTL_SET_THREAD_CBS' command + (called via the `gcry_control' function). *Note Multi-Threading::. + + Furthermore, this function returns the version number of the + library. It can also verify that the version number is higher + than a certain required version number REQ_VERSION, if this value + is not a null pointer. + + Libgcrypt uses a concept known as secure memory, which is a region of +memory set aside for storing sensitive data. Because such memory is a +scarce resource, it needs to be setup in advanced to a fixed size. +Further, most operating systems have special requirements on how that +secure memory can be used. For example, it might be required to install +an application as "setuid(root)" to allow allocating such memory. +Libgcrypt requires a sequence of initialization steps to make sure that +this works correctly. The following examples show the necessary steps. + + If you don't have a need for secure memory, for example if your +application does not use secret keys or other confidential data or it +runs in a controlled environment where key material floating around in +memory is not a problem, you should initialize Libgcrypt this way: + + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) + { + fputs ("libgcrypt version mismatch\n", stderr); + exit (2); + } + + /* Disable secure memory. */ + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + If you have to protect your keys or other information in memory +against being swapped out to disk and to enable an automatic overwrite +of used and freed memory, you need to initialize Libgcrypt this way: + + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) + { + fputs ("libgcrypt version mismatch\n", stderr); + exit (2); + } + + /* We don't want to see any warnings, e.g. because we have not yet + parsed program options which might be used to suppress such + warnings. */ + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + + /* ... If required, other initialization goes here. Note that the + process might still be running with increased privileges and that + the secure memory has not been intialized. */ + + /* Allocate a pool of 16k secure memory. This make the secure memory + available and also drops privileges where needed. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + /* It is now okay to let Libgcrypt complain when there was/is + a problem with the secure memory. */ + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + It is important that these initialization steps are not done by a +library but by the actual application. A library using Libgcrypt might +want to check for finished initialization using: + + if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) + { + fputs ("libgcrypt has not been initialized\n", stderr); + abort (); + } + + Instead of terminating the process, the library may instead print a +warning and try to initialize Libgcrypt itself. See also the section on +multi-threading below for more pitfalls. + + +File: gcrypt.info, Node: Multi-Threading, Next: Enabling FIPS mode, Prev: Initializing the library, Up: Preparation + +2.5 Multi-Threading +=================== + +As mentioned earlier, the Libgcrypt library is thread-safe if you +adhere to the following requirements: + + * If your application is multi-threaded, you must set the thread + support callbacks with the `GCRYCTL_SET_THREAD_CBS' command + *before* any other function in the library. + + This is easy enough if you are indeed writing an application using + Libgcrypt. It is rather problematic if you are writing a library + instead. Here are some tips what to do if you are writing a + library: + + If your library requires a certain thread package, just initialize + Libgcrypt to use this thread package. If your library supports + multiple thread packages, but needs to be configured, you will + have to implement a way to determine which thread package the + application wants to use with your library anyway. Then configure + Libgcrypt to use this thread package. + + If your library is fully reentrant without any special support by a + thread package, then you are lucky indeed. Unfortunately, this + does not relieve you from doing either of the two above, or use a + third option. The third option is to let the application + initialize Libgcrypt for you. Then you are not using Libgcrypt + transparently, though. + + As if this was not difficult enough, a conflict may arise if two + libraries try to initialize Libgcrypt independently of each + others, and both such libraries are then linked into the same + application. To make it a bit simpler for you, this will probably + work, but only if both libraries have the same requirement for the + thread package. This is currently only supported for the + non-threaded case, GNU Pth and pthread. Support for more thread + packages is easy to add, so contact us if you require it. + + * The function `gcry_check_version' must be called before any other + function in the library, except the `GCRYCTL_SET_THREAD_CBS' + command (called via the `gcry_control' function), because it + initializes the thread support subsystem in Libgcrypt. To achieve + this in multi-threaded programs, you must synchronize the memory + with respect to other threads that also want to use Libgcrypt. + For this, it is sufficient to call `gcry_check_version' before + creating the other threads using Libgcrypt(1). + + * Just like the function `gpg_strerror', the function + `gcry_strerror' is not thread safe. You have to use + `gpg_strerror_r' instead. + + + Libgcrypt contains convenient macros, which define the necessary +thread callbacks for PThread and for GNU Pth: + +`GCRY_THREAD_OPTION_PTH_IMPL' + This macro defines the following (static) symbols: + `gcry_pth_init', `gcry_pth_mutex_init', `gcry_pth_mutex_destroy', + `gcry_pth_mutex_lock', `gcry_pth_mutex_unlock', `gcry_pth_read', + `gcry_pth_write', `gcry_pth_select', `gcry_pth_waitpid', + `gcry_pth_accept', `gcry_pth_connect', `gcry_threads_pth'. + + After including this macro, `gcry_control()' shall be used with a + command of `GCRYCTL_SET_THREAD_CBS' in order to register the + thread callback structure named "gcry_threads_pth". + +`GCRY_THREAD_OPTION_PTHREAD_IMPL' + This macro defines the following (static) symbols: + `gcry_pthread_mutex_init', `gcry_pthread_mutex_destroy', + `gcry_pthread_mutex_lock', `gcry_pthread_mutex_unlock', + `gcry_threads_pthread'. + + After including this macro, `gcry_control()' shall be used with a + command of `GCRYCTL_SET_THREAD_CBS' in order to register the + thread callback structure named "gcry_threads_pthread". + + Note that these macros need to be terminated with a semicolon. Keep +in mind that these are convenient macros for C programmers; C++ +programmers might have to wrap these macros in an "extern C" body. + + ---------- Footnotes ---------- + + (1) At least this is true for POSIX threads, as `pthread_create' is +a function that synchronizes memory with respects to other threads. +There are many functions which have this property, a complete list can +be found in POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in +the definition of the term "Memory Synchronization". For other thread +packages, more relaxed or more strict rules may apply. + + +File: gcrypt.info, Node: Enabling FIPS mode, Prev: Multi-Threading, Up: Preparation + +2.6 How to enable the FIPS mode +=============================== + +Libgcrypt may be used in a FIPS 140-2 mode. Note, that this does not +necessary mean that Libcgrypt is an appoved FIPS 140-2 module. Check +the NIST database at `http://csrc.nist.gov/groups/STM/cmvp/' to see what +versions of Libgcrypt are approved. + + Because FIPS 140 has certain restrictions on the use of cryptography +which are not always wanted, Libgcrypt needs to be put into FIPS mode +explicitly. Three alternative mechanisms are provided to switch +Libgcrypt into this mode: + + * If the file `/proc/sys/crypto/fips_enabled' exists and contains a + numeric value other than `0', Libgcrypt is put into FIPS mode at + initialization time. Obviously this works only on systems with a + `proc' file system (i.e. GNU/Linux). + + * If the file `/etc/gcrypt/fips_enabled' exists, Libgcrypt is put + into FIPS mode at initialization time. Note that this filename is + hardwired and does not depend on any configuration options. + + * If the application requests FIPS mode using the control command + `GCRYCTL_FORCE_FIPS_MODE'. This must be done prior to any + initialization (i.e. before `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 +`/etc/gcrypt/fips_enabled'. The Enforced FIPS mode helps to detect +applications which don't fulfill all requirements for using Libgcrypt +in FIPS mode (*note FIPS Mode::). + + Once Libgcrypt has been put into FIPS mode, it is not possible to +switch back to standard mode without terminating the process first. If +the logging verbosity level of Libgcrypt has been set to at least 2, +the state transitions and the self-tests are logged. + + +File: gcrypt.info, Node: Generalities, Next: Handler Functions, Prev: Preparation, Up: Top + +3 Generalities +************** + +* Menu: + +* Controlling the library:: Controlling Libgcrypt's behavior. +* Modules:: Description of extension modules. +* Error Handling:: Error codes and such. + + +File: gcrypt.info, Node: Controlling the library, Next: Modules, Up: Generalities + +3.1 Controlling the library +=========================== + + -- Function: gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...) + This function can be used to influence the general behavior of + Libgcrypt in several ways. Depending on CMD, more arguments can + or have to be provided. + + `GCRYCTL_ENABLE_M_GUARD; Arguments: none' + This command enables the built-in memory guard. It must not + be used to activate the memory guard after the memory + management has already been used; therefore it can ONLY be + used at initialization time. Note that the memory guard is + NOT used when the user of the library has set his own memory + management callbacks. + + `GCRYCTL_ENABLE_QUICK_RANDOM; Arguments: none' + This command inhibits the use the very secure random quality + level (`GCRY_VERY_STRONG_RANDOM') and degrades all request + down to `GCRY_STRONG_RANDOM'. In general this is not + recommened. However, for some applications the extra quality + random Libgcrypt tries to create is not justified and this + option may help to get better performace. Please check with + a crypto expert whether this option can be used for your + application. + + This option can only be used at initialization time. + + `GCRYCTL_DUMP_RANDOM_STATS; Arguments: none' + This command dumps randum number generator related statistics + to the library's logging stream. + + `GCRYCTL_DUMP_MEMORY_STATS; Arguments: none' + This command dumps memory managment related statistics to the + library's logging stream. + + `GCRYCTL_DUMP_SECMEM_STATS; Arguments: none' + This command dumps secure memory manamgent related statistics + to the library's logging stream. + + `GCRYCTL_DROP_PRIVS; Arguments: none' + This command disables the use of secure memory and drops the + priviliges of the current process. This command has not much + use; the suggested way to disable secure memory is to use + `GCRYCTL_DISABLE_SECMEM' right after initialization. + + `GCRYCTL_DISABLE_SECMEM; Arguments: none' + This command disables the use of secure memory. If this + command is used in FIPS mode, FIPS mode will be disabled and + the function `gcry_fips_mode_active' returns false. However, + in Enforced FIPS mode this command has no effect at all. + + Many applications do not require secure memory, so they + should disable it right away. This command should be + executed right after `gcry_check_version'. + + `GCRYCTL_INIT_SECMEM; Arguments: int nbytes' + This command is used to allocate a pool of secure memory and + thus enabling the use of secure memory. It also drops all + extra privileges the process has (i.e. if it is run as setuid + (root)). If the argument NBYTES is 0, secure memory will be + disabled. The minimum amount of secure memory allocated is + currently 16384 bytes; you may thus use a value of 1 to + request that default size. + + `GCRYCTL_TERM_SECMEM; Arguments: none' + This command zeroises the secure memory and destroys the + handler. The secure memory pool may not be used anymore + after running this command. If the secure memory pool as + already been destroyed, this command has no effect. + Applications might want to run this command from their exit + handler to make sure that the secure memory gets properly + destroyed. This command is not necessarily thread-safe but + that should not be needed in cleanup code. It may be called + from a signal handler. + + `GCRYCTL_DISABLE_SECMEM_WARN; Arguments: none' + Disable warning messages about problems with the secure memory + subsystem. This command should be run right after + `gcry_check_version'. + + `GCRYCTL_SUSPEND_SECMEM_WARN; Arguments: none' + Postpone warning messages from the secure memory subsystem. + *Note the initialization example: sample-use-suspend-secmem, + on how to use it. + + `GCRYCTL_RESUME_SECMEM_WARN; Arguments: none' + Resume warning messages from the secure memory subsystem. + *Note the initialization example: sample-use-resume-secmem, + on how to use it. + + `GCRYCTL_USE_SECURE_RNDPOOL; Arguments: none' + This command tells the PRNG to store random numbers in secure + memory. This command should be run right after + `gcry_check_version' and not later than the command + GCRYCTL_INIT_SECMEM. Note that in FIPS mode the secure + memory is always used. + + `GCRYCTL_SET_RANDOM_SEED_FILE; Arguments: const char *filename' + This command specifies the file, which is to be used as seed + file for the PRNG. If the seed file is registered prior to + initialization of the PRNG, the seed file's content (if it + exists and seems to be valid) is fed into the PRNG pool. + After the seed file has been registered, the PRNG can be + signalled to write out the PRNG pool's content into the seed + file with the following command. + + `GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none' + Write out the PRNG pool's content into the registered seed + file. + + Multiple instances of the applications sharing the same + random seed file can be started in parallel, in which case + they will read out the same pool and then race for updating + it (the last update overwrites earlier updates). They will + differentiate only by the weak entropy that is added in + read_seed_file based on the PID and clock, and up to 16 bytes + of weak random non-blockingly. The consequence is that the + output of these different instances is correlated to some + extent. In a perfect attack scenario, the attacker can + control (or at least guess) the PID and clock of the + application, and drain the system's entropy pool to reduce + the "up to 16 bytes" above to 0. Then the dependencies of the + inital states of the pools are completely known. Note that + this is not an issue if random of `GCRY_VERY_STRONG_RANDOM' + quality is requested as in this case enough extra entropy + gets mixed. It is also not an issue when using Linux + (rndlinux driver), because this one guarantees to read full + 16 bytes from /dev/urandom and thus there is no way for an + attacker without kernel access to control these 16 bytes. + + `GCRYCTL_SET_VERBOSITY; Arguments: int level' + This command sets the verbosity of the logging. A level of 0 + disables all extra logging whereas positive numbers enable + more verbose logging. The level may be changed at any time + but be aware that no memory synchronization is done so the + effect of this command might not immediately show up in other + threads. This command may even be used prior to + `gcry_check_version'. + + `GCRYCTL_SET_DEBUG_FLAGS; Arguments: unsigned int flags' + Set the debug flag bits as given by the argument. Be aware + that that no memory synchronization is done so the effect of + this command might not immediately show up in other threads. + The debug flags are not considered part of the API and thus + may change without notice. As of now bit 0 enables debugging + of cipher functions and bit 1 debugging of + multi-precision-integers. This command may even be used + prior to `gcry_check_version'. + + `GCRYCTL_CLEAR_DEBUG_FLAGS; Arguments: unsigned int flags' + Set the debug flag bits as given by the argument. Be aware + that that no memory synchronization is done so the effect of + this command might not immediately show up in other threads. + This command may even be used prior to `gcry_check_version'. + + `GCRYCTL_DISABLE_INTERNAL_LOCKING; Arguments: none' + This command does nothing. It exists only for backward + compatibility. + + `GCRYCTL_ANY_INITIALIZATION_P; Arguments: none' + This command returns true if the library has been basically + initialized. Such a basic initialization happens implicitly + with many commands to get certain internal subsystems + running. The common and suggested way to do this basic + intialization is by calling gcry_check_version. + + `GCRYCTL_INITIALIZATION_FINISHED; Arguments: none' + This command tells the libray that the application has + finished the intialization. + + `GCRYCTL_INITIALIZATION_FINISHED_P; Arguments: none' + This command returns true if the command + GCRYCTL_INITIALIZATION_FINISHED has already been run. + + `GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops' + This command registers a thread-callback structure. *Note + Multi-Threading::. + + `GCRYCTL_FAST_POLL; Arguments: none' + Run a fast random poll. + + `GCRYCTL_SET_RNDEGD_SOCKET; Arguments: const char *filename' + This command may be used to override the default name of the + EGD socket to connect to. It may be used only during + initialization as it is not thread safe. Changing the socket + name again is not supported. The function may return an + error if the given filename is too long for a local socket + name. + + EGD is an alternative random gatherer, used only on systems + lacking a proper random device. + + `GCRYCTL_PRINT_CONFIG; Arguments: FILE *stream' + This command dumps information pertaining to the + configuration of the library to the given stream. If NULL is + given for STREAM, the log system is used. This command may + be used before the intialization has been finished but not + before a gcry_version_check. + + `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. + + `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 + the convenience macro below to check whether FIPS mode is + actually active. + + -- Function: int gcry_fips_mode_active (void) + Returns true if the FIPS mode is active. Note that this + is implemented as a macro. + + `GCRYCTL_FORCE_FIPS_MODE; Arguments: none' + 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 application + switch the library into FIPS mode. Note that Libgcrypt will + reject an attempt to switch to fips mode during or after the + intialization. + + `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 success or an error code on failure. + + + + +File: gcrypt.info, Node: Modules, Next: Error Handling, Prev: Controlling the library, Up: Generalities + +3.2 Modules +=========== + +Libgcrypt supports the use of `extension modules', which implement +algorithms in addition to those already built into the library directly. + + -- Data type: gcry_module_t + This data type represents a `module'. + + Functions registering modules provided by the user take a `module +specification structure' as input and return a value of `gcry_module_t' +and an ID that is unique in the modules' category. This ID can be used +to reference the newly registered module. After registering a module +successfully, the new functionality should be able to be used through +the normal functions provided by Libgcrypt until it is unregistered +again. + + +File: gcrypt.info, Node: Error Handling, Prev: Modules, Up: Generalities + +3.3 Error Handling +================== + +Many functions in Libgcrypt can return an error if they fail. For this +reason, the application should always catch the error condition and +take appropriate measures, for example by releasing the resources and +passing the error up to the caller, or by displaying a descriptive +message to the user and cancelling the operation. + + Some error values do not indicate a system error or an error in the +operation, but the result of an operation that failed properly. For +example, if you try to decrypt a tempered message, the decryption will +fail. Another error value actually means that the end of a data buffer +or list has been reached. The following descriptions explain for many +error codes what they mean usually. Some error values have specific +meanings if returned by a certain functions. Such cases are described +in the documentation of those functions. + + Libgcrypt uses the `libgpg-error' library. This allows to share the +error codes with other components of the GnuPG system, and to pass +error values transparently from the crypto engine, or some helper +application of the crypto engine, to the user. This way no information +is lost. As a consequence, Libgcrypt does not use its own identifiers +for error codes, but uses those provided by `libgpg-error'. They +usually start with `GPG_ERR_'. + + However, Libgcrypt does provide aliases for the functions defined in +libgpg-error, which might be preferred for name space consistency. + + Most functions in Libgcrypt return an error code in the case of +failure. For this reason, the application should always catch the +error condition and take appropriate measures, for example by releasing +the resources and passing the error up to the caller, or by displaying +a descriptive message to the user and canceling the operation. + + Some error values do not indicate a system error or an error in the +operation, but the result of an operation that failed properly. + + GnuPG components, including Libgcrypt, use an extra library named +libgpg-error to provide a common error handling scheme. For more +information on libgpg-error, see the according manual. + +* Menu: + +* Error Values:: The error value and what it means. +* Error Sources:: A list of important error sources. +* Error Codes:: A list of important error codes. +* Error Strings:: How to get a descriptive string from a value. + + +File: gcrypt.info, Node: Error Values, Next: Error Sources, Up: Error Handling + +3.3.1 Error Values +------------------ + + -- Data type: gcry_err_code_t + The `gcry_err_code_t' type is an alias for the `libgpg-error' type + `gpg_err_code_t'. The error code indicates the type of an error, + or the reason why an operation failed. + + A list of important error codes can be found in the next section. + + -- Data type: gcry_err_source_t + The `gcry_err_source_t' type is an alias for the `libgpg-error' + type `gpg_err_source_t'. The error source has not a precisely + defined meaning. Sometimes it is the place where the error + happened, sometimes it is the place where an error was encoded + into an error value. Usually the error source will give an + indication to where to look for the problem. This is not always + true, but it is attempted to achieve this goal. + + A list of important error sources can be found in the next section. + + -- Data type: gcry_error_t + The `gcry_error_t' type is an alias for the `libgpg-error' type + `gpg_error_t'. An error value like this has always two + components, an error code and an error source. Both together form + the error value. + + Thus, the error value can not be directly compared against an error + code, but the accessor functions described below must be used. + However, it is guaranteed that only 0 is used to indicate success + (`GPG_ERR_NO_ERROR'), and that in this case all other parts of the + error value are set to 0, too. + + Note that in Libgcrypt, the error source is used purely for + diagnostic purposes. Only the error code should be checked to test + for a certain outcome of a function. The manual only documents the + error code part of an error value. The error source is left + unspecified and might be anything. + + -- Function: gcry_err_code_t gcry_err_code (gcry_error_t ERR) + The static inline function `gcry_err_code' returns the + `gcry_err_code_t' component of the error value ERR. This function + must be used to extract the error code from an error value in + order to compare it with the `GPG_ERR_*' error code macros. + + -- Function: gcry_err_source_t gcry_err_source (gcry_error_t ERR) + The static inline function `gcry_err_source' returns the + `gcry_err_source_t' component of the error value ERR. This + function must be used to extract the error source from an error + value in order to compare it with the `GPG_ERR_SOURCE_*' error + source macros. + + -- Function: gcry_error_t gcry_err_make (gcry_err_source_t SOURCE, + gcry_err_code_t CODE) + The static inline function `gcry_err_make' returns the error value + consisting of the error source SOURCE and the error code CODE. + + This function can be used in callback functions to construct an + error value to return it to the library. + + -- Function: gcry_error_t gcry_error (gcry_err_code_t CODE) + The static inline function `gcry_error' returns the error value + consisting of the default error source and the error code CODE. + + For GCRY applications, the default error source is + `GPG_ERR_SOURCE_USER_1'. You can define `GCRY_ERR_SOURCE_DEFAULT' + before including `gcrypt.h' to change this default. + + This function can be used in callback functions to construct an + error value to return it to the library. + + The `libgpg-error' library provides error codes for all system error +numbers it knows about. If ERR is an unknown error number, the error +code `GPG_ERR_UNKNOWN_ERRNO' is used. The following functions can be +used to construct error values from system errno numbers. + + -- Function: gcry_error_t gcry_err_make_from_errno + (gcry_err_source_t SOURCE, int ERR) + The function `gcry_err_make_from_errno' is like `gcry_err_make', + but it takes a system error like `errno' instead of a + `gcry_err_code_t' error code. + + -- Function: gcry_error_t gcry_error_from_errno (int ERR) + The function `gcry_error_from_errno' is like `gcry_error', but it + takes a system error like `errno' instead of a `gcry_err_code_t' + error code. + + Sometimes you might want to map system error numbers to error codes +directly, or map an error code representing a system error back to the +system error number. The following functions can be used to do that. + + -- Function: gcry_err_code_t gcry_err_code_from_errno (int ERR) + The function `gcry_err_code_from_errno' returns the error code for + the system error ERR. If ERR is not a known system error, the + function returns `GPG_ERR_UNKNOWN_ERRNO'. + + -- Function: int gcry_err_code_to_errno (gcry_err_code_t ERR) + The function `gcry_err_code_to_errno' returns the system error for + the error code ERR. If ERR is not an error code representing a + system error, or if this system error is not defined on this + system, the function returns `0'. + + +File: gcrypt.info, Node: Error Sources, Next: Error Codes, Prev: Error Values, Up: Error Handling + +3.3.2 Error Sources +------------------- + +The library `libgpg-error' defines an error source for every component +of the GnuPG system. The error source part of an error value is not +well defined. As such it is mainly useful to improve the diagnostic +error message for the user. + + If the error code part of an error value is `0', the whole error +value will be `0'. In this case the error source part is of course +`GPG_ERR_SOURCE_UNKNOWN'. + + The list of error sources that might occur in applications using +Libgcrypt is: + +`GPG_ERR_SOURCE_UNKNOWN' + The error source is not known. The value of this error source is + `0'. + +`GPG_ERR_SOURCE_GPGME' + The error source is GPGME itself. + +`GPG_ERR_SOURCE_GPG' + The error source is GnuPG, which is the crypto engine used for the + OpenPGP protocol. + +`GPG_ERR_SOURCE_GPGSM' + The error source is GPGSM, which is the crypto engine used for the + OpenPGP protocol. + +`GPG_ERR_SOURCE_GCRYPT' + The error source is `libgcrypt', which is used by crypto engines + to perform cryptographic operations. + +`GPG_ERR_SOURCE_GPGAGENT' + The error source is `gpg-agent', which is used by crypto engines + to perform operations with the secret key. + +`GPG_ERR_SOURCE_PINENTRY' + The error source is `pinentry', which is used by `gpg-agent' to + query the passphrase to unlock a secret key. + +`GPG_ERR_SOURCE_SCD' + The error source is the SmartCard Daemon, which is used by + `gpg-agent' to delegate operations with the secret key to a + SmartCard. + +`GPG_ERR_SOURCE_KEYBOX' + The error source is `libkbx', a library used by the crypto engines + to manage local keyrings. + +`GPG_ERR_SOURCE_USER_1' + +`GPG_ERR_SOURCE_USER_2' + +`GPG_ERR_SOURCE_USER_3' + +`GPG_ERR_SOURCE_USER_4' + These error sources are not used by any GnuPG component and can be + used by other software. For example, applications using Libgcrypt + can use them to mark error values coming from callback handlers. + Thus `GPG_ERR_SOURCE_USER_1' is the default for errors created + with `gcry_error' and `gcry_error_from_errno', unless you define + `GCRY_ERR_SOURCE_DEFAULT' before including `gcrypt.h'. + + +File: gcrypt.info, Node: Error Codes, Next: Error Strings, Prev: Error Sources, Up: Error Handling + +3.3.3 Error Codes +----------------- + +The library `libgpg-error' defines many error values. The following +list includes the most important error codes. + +`GPG_ERR_EOF' + This value indicates the end of a list, buffer or file. + +`GPG_ERR_NO_ERROR' + This value indicates success. The value of this error code is + `0'. Also, it is guaranteed that an error value made from the + error code `0' will be `0' itself (as a whole). This means that + the error source information is lost for this error code, however, + as this error code indicates that no error occurred, this is + generally not a problem. + +`GPG_ERR_GENERAL' + This value means that something went wrong, but either there is not + enough information about the problem to return a more useful error + value, or there is no separate error value for this type of + problem. + +`GPG_ERR_ENOMEM' + This value means that an out-of-memory condition occurred. + +`GPG_ERR_E...' + System errors are mapped to GPG_ERR_EFOO where FOO is the symbol + for the system error. + +`GPG_ERR_INV_VALUE' + This value means that some user provided data was out of range. + +`GPG_ERR_UNUSABLE_PUBKEY' + This value means that some recipients for a message were invalid. + +`GPG_ERR_UNUSABLE_SECKEY' + This value means that some signers were invalid. + +`GPG_ERR_NO_DATA' + This value means that data was expected where no data was found. + +`GPG_ERR_CONFLICT' + This value means that a conflict of some sort occurred. + +`GPG_ERR_NOT_IMPLEMENTED' + This value indicates that the specific function (or operation) is + not implemented. This error should never happen. It can only + occur if you use certain values or configuration options which do + not work, but for which we think that they should work at some + later time. + +`GPG_ERR_DECRYPT_FAILED' + This value indicates that a decryption operation was unsuccessful. + +`GPG_ERR_WRONG_KEY_USAGE' + This value indicates that a key is not used appropriately. + +`GPG_ERR_NO_SECKEY' + This value indicates that no secret key for the user ID is + available. + +`GPG_ERR_UNSUPPORTED_ALGORITHM' + This value means a verification failed because the cryptographic + algorithm is not supported by the crypto backend. + +`GPG_ERR_BAD_SIGNATURE' + This value means a verification failed because the signature is + bad. + +`GPG_ERR_NO_PUBKEY' + This value means a verification failed because the public key is + not available. + +`GPG_ERR_NOT_OPERATIONAL' + This value means that the library is not yet in state which allows + to use this function. This error code is in particular returned if + Libgcrypt is operated in FIPS mode and the internal state of the + library does not yet or not anymore allow the use of a service. + + This error code is only available with newer libgpg-error + versions, thus you might see "invalid error code" when passing + this to `gpg_strerror'. The numeric value of this error code is + 176. + +`GPG_ERR_USER_1' + +`GPG_ERR_USER_2' + +`...' + +`GPG_ERR_USER_16' + These error codes are not used by any GnuPG component and can be + freely used by other software. Applications using Libgcrypt might + use them to mark specific errors returned by callback handlers if + no suitable error codes (including the system errors) for these + errors exist already. + + +File: gcrypt.info, Node: Error Strings, Prev: Error Codes, Up: Error Handling + +3.3.4 Error Strings +------------------- + + -- Function: const char * gcry_strerror (gcry_error_t ERR) + The function `gcry_strerror' returns a pointer to a statically + allocated string containing a description of the error code + contained in the error value ERR. This string can be used to + output a diagnostic message to the user. + + -- Function: const char * gcry_strsource (gcry_error_t ERR) + The function `gcry_strerror' returns a pointer to a statically + allocated string containing a description of the error source + contained in the error value ERR. This string can be used to + output a diagnostic message to the user. + + The following example illustrates the use of the functions described +above: + + { + gcry_cipher_hd_t handle; + gcry_error_t err = 0; + + err = gcry_cipher_open (&handle, GCRY_CIPHER_AES, + GCRY_CIPHER_MODE_CBC, 0); + if (err) + { + fprintf (stderr, "Failure: %s/%s\n", + gcry_strsource (err), + gcry_strerror (err)); + } + } + + +File: gcrypt.info, Node: Handler Functions, Next: Symmetric cryptography, Prev: Generalities, Up: Top + +4 Handler Functions +******************* + +Libgcrypt makes it possible to install so called `handler functions', +which get called by Libgcrypt in case of certain events. + +* Menu: + +* Progress handler:: Using a progress handler function. +* Allocation handler:: Using special memory allocation functions. +* Error handler:: Using error handler functions. +* Logging handler:: Using a special logging function. + + +File: gcrypt.info, Node: Progress handler, Next: Allocation handler, Up: Handler Functions + +4.1 Progress handler +==================== + +It is often useful to retrieve some feedback while long running +operations are performed. + + -- Data type: gcry_handler_progress_t + Progress handler functions have to be of the type + `gcry_handler_progress_t', which is defined as: + + `void (*gcry_handler_progress_t) (void *, const char *, int, int, + int)' + + The following function may be used to register a handler function for +this purpose. + + -- Function: void gcry_set_progress_handler (gcry_handler_progress_t + CB, void *CB_DATA) + This function installs CB as the `Progress handler' function. It + may be used only during initialization. CB must be defined as + follows: + + void + my_progress_handler (void *CB_DATA, const char *WHAT, + int PRINTCHAR, int CURRENT, int TOTAL) + { + /* Do something. */ + } + + A description of the arguments of the progress handler function + follows. + + CB_DATA + The argument provided in the call to + `gcry_set_progress_handler'. + + WHAT + A string identifying the type of the progress output. The + following values for WHAT are defined: + + `need_entropy' + Not enough entropy is available. TOTAL holds the number + of required bytes. + + `primegen' + Values for PRINTCHAR: + `\n' + Prime generated. + + `!' + Need to refresh the pool of prime numbers. + + `<, >' + Number of bits adjusted. + + `^' + Searching for a generator. + + `.' + Fermat test on 10 candidates failed. + + `:' + Restart with a new random value. + + `+' + Rabin Miller test passed. + + + + +File: gcrypt.info, Node: Allocation handler, Next: Error handler, Prev: Progress handler, Up: Handler Functions + +4.2 Allocation handler +====================== + +It is possible to make Libgcrypt use special memory allocation +functions instead of the built-in ones. + + Memory allocation functions are of the following types: + + -- Data type: gcry_handler_alloc_t + This type is defined as: `void *(*gcry_handler_alloc_t) (size_t + n)'. + + -- Data type: gcry_handler_secure_check_t + This type is defined as: `int *(*gcry_handler_secure_check_t) + (const void *)'. + + -- Data type: gcry_handler_realloc_t + This type is defined as: `void *(*gcry_handler_realloc_t) (void + *p, size_t n)'. + + -- Data type: gcry_handler_free_t + This type is defined as: `void *(*gcry_handler_free_t) (void *)'. + + Special memory allocation functions can be installed with the +following function: + + -- Function: void gcry_set_allocation_handler (gcry_handler_alloc_t + FUNC_ALLOC, gcry_handler_alloc_t FUNC_ALLOC_SECURE, + gcry_handler_secure_check_t FUNC_SECURE_CHECK, + gcry_handler_realloc_t FUNC_REALLOC, gcry_handler_free_t + FUNC_FREE) + Install the provided functions and use them instead of the built-in + functions for doing memory allocation. Using this function is in + general not recommended because the standard Libgcrypt allocation + functions are guaranteed to zeroize memory if needed. + + This function may be used only during initialization and may not be + used in fips mode. + + + +File: gcrypt.info, Node: Error handler, Next: Logging handler, Prev: Allocation handler, Up: Handler Functions + +4.3 Error handler +================= + +The following functions may be used to register handler functions that +are called by Libgcrypt in case certain error conditions occur. They +may and should be registered prior to calling `gcry_check_version'. + + -- Data type: gcry_handler_no_mem_t + This type is defined as: `int (*gcry_handler_no_mem_t) (void *, + size_t, unsigned int)' + + -- Function: void gcry_set_outofcore_handler (gcry_handler_no_mem_t + FUNC_NO_MEM, void *CB_DATA) + This function registers FUNC_NO_MEM as `out-of-core handler', + which means that it will be called in the case of not having enough + memory available. The handler is called with 3 arguments: The + first one is the pointer CB_DATA as set with this function, the + second is the requested memory size and the last being a flag. If + bit 0 of the flag is set, secure memory has been requested. The + handler should either return true to indicate that Libgcrypt + should try again allocating memory or return false to let + Libgcrypt use its default fatal error handler. + + -- Data type: gcry_handler_error_t + This type is defined as: `void (*gcry_handler_error_t) (void *, + int, const char *)' + + -- Function: void gcry_set_fatalerror_handler (gcry_handler_error_t + FUNC_ERROR, void *CB_DATA) + This function registers FUNC_ERROR as `error handler', which means + that it will be called in error conditions. + + +File: gcrypt.info, Node: Logging handler, Prev: Error handler, Up: Handler Functions + +4.4 Logging handler +=================== + + -- Data type: gcry_handler_log_t + This type is defined as: `void (*gcry_handler_log_t) (void *, int, + const char *, va_list)' + + -- Function: void gcry_set_log_handler (gcry_handler_log_t FUNC_LOG, + void *CB_DATA) + This function registers FUNC_LOG as `logging handler', which means + that it will be called in case Libgcrypt wants to log a message. + This function may and should be used prior to calling + `gcry_check_version'. + + +File: gcrypt.info, Node: Symmetric cryptography, Next: Public Key cryptography, Prev: Handler Functions, Up: Top + +5 Symmetric cryptography +************************ + +The cipher functions are used for symmetrical cryptography, i.e. +cryptography using a shared key. The programming model follows an +open/process/close paradigm and is in that similar to other building +blocks provided by Libgcrypt. + +* Menu: + +* Available ciphers:: List of ciphers supported by the library. +* Cipher modules:: How to work with cipher modules. +* Available cipher modes:: List of cipher modes supported by the library. +* Working with cipher handles:: How to perform operations related to cipher handles. +* General cipher functions:: General cipher functions independent of cipher handles. + + +File: gcrypt.info, Node: Available ciphers, Next: Cipher modules, Up: Symmetric cryptography + +5.1 Available ciphers +===================== + +`GCRY_CIPHER_NONE' + This is not a real algorithm but used by some functions as error + return. The value always evaluates to false. + +`GCRY_CIPHER_IDEA' + This is the IDEA algorithm. The constant is provided but there is + currently no implementation for it because the algorithm is + patented. + +`GCRY_CIPHER_3DES' + Triple-DES with 3 Keys as EDE. The key size of this algorithm is + 168 but you have to pass 192 bits because the most significant + bits of each byte are ignored. + +`GCRY_CIPHER_CAST5' + CAST128-5 block cipher algorithm. The key size is 128 bits. + +`GCRY_CIPHER_BLOWFISH' + The blowfish algorithm. The current implementation allows only for + a key size of 128 bits. + +`GCRY_CIPHER_SAFER_SK128' + Reserved and not currently implemented. + +`GCRY_CIPHER_DES_SK' + Reserved and not currently implemented. + +`GCRY_CIPHER_AES' +`GCRY_CIPHER_AES128' +`GCRY_CIPHER_RIJNDAEL' +`GCRY_CIPHER_RIJNDAEL128' + AES (Rijndael) with a 128 bit key. + +`GCRY_CIPHER_AES192' +`GCRY_CIPHER_RIJNDAEL192' + AES (Rijndael) with a 192 bit key. + +`GCRY_CIPHER_AES256' +`GCRY_CIPHER_RIJNDAEL256' + AES (Rijndael) with a 256 bit key. + +`GCRY_CIPHER_TWOFISH' + The Twofish algorithm with a 256 bit key. + +`GCRY_CIPHER_TWOFISH128' + The Twofish algorithm with a 128 bit key. + +`GCRY_CIPHER_ARCFOUR' + An algorithm which is 100% compatible with RSA Inc.'s RC4 + algorithm. Note that this is a stream cipher and must be used + very carefully to avoid a couple of weaknesses. + +`GCRY_CIPHER_DES' + Standard DES with a 56 bit key. You need to pass 64 bit but the + high bits of each byte are ignored. Note, that this is a weak + algorithm which can be broken in reasonable time using a brute + force approach. + +`GCRY_CIPHER_SERPENT128' +`GCRY_CIPHER_SERPENT192' +`GCRY_CIPHER_SERPENT256' + The Serpent cipher from the AES contest. + +`GCRY_CIPHER_RFC2268_40' +`GCRY_CIPHER_RFC2268_128' + Ron's Cipher 2 in the 40 and 128 bit variants. Note, that we + currently only support the 40 bit variant. The identifier for 128 + is reserved for future use. + +`GCRY_CIPHER_SEED' + A 128 bit cipher as described by RFC4269. + +`GCRY_CIPHER_CAMELLIA128' +`GCRY_CIPHER_CAMELLIA192' +`GCRY_CIPHER_CAMELLIA256' + The Camellia cipher by NTT. See + `http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html'. + + + +File: gcrypt.info, Node: Cipher modules, Next: Available cipher modes, Prev: Available ciphers, Up: Symmetric cryptography + +5.2 Cipher modules +================== + +Libgcrypt makes it possible to load additional `cipher modules'; these +ciphers can be used just like the cipher algorithms that are built into +the library directly. For an introduction into extension modules, see +*Note Modules::. + + -- Data type: gcry_cipher_spec_t + This is the `module specification structure' needed for registering + cipher modules, which has to be filled in by the user before it + can be used to register a module. It contains the following + members: + + `const char *name' + The primary name of the algorithm. + + `const char **aliases' + A list of strings that are `aliases' for the algorithm. The + list must be terminated with a NULL element. + + `gcry_cipher_oid_spec_t *oids' + A list of OIDs that are to be associated with the algorithm. + The list's last element must have it's `oid' member set to + NULL. See below for an explanation of this type. + + `size_t blocksize' + The block size of the algorithm, in bytes. + + `size_t keylen' + The length of the key, in bits. + + `size_t contextsize' + The size of the algorithm-specific `context', that should be + allocated for each handle. + + `gcry_cipher_setkey_t setkey' + The function responsible for initializing a handle with a + provided key. See below for a description of this type. + + `gcry_cipher_encrypt_t encrypt' + The function responsible for encrypting a single block. See + below for a description of this type. + + `gcry_cipher_decrypt_t decrypt' + The function responsible for decrypting a single block. See + below for a description of this type. + + `gcry_cipher_stencrypt_t stencrypt' + Like `encrypt', for stream ciphers. See below for a + description of this type. + + `gcry_cipher_stdecrypt_t stdecrypt' + Like `decrypt', for stream ciphers. See below for a + description of this type. + + -- Data type: gcry_cipher_oid_spec_t + This type is used for associating a user-provided algorithm + implementation with certain OIDs. It contains the following + members: + `const char *oid' + Textual representation of the OID. + + `int mode' + Cipher mode for which this OID is valid. + + -- Data type: gcry_cipher_setkey_t + Type for the `setkey' function, defined as: gcry_err_code_t + (*gcry_cipher_setkey_t) (void *c, const unsigned char *key, + unsigned keylen) + + -- Data type: gcry_cipher_encrypt_t + Type for the `encrypt' function, defined as: gcry_err_code_t + (*gcry_cipher_encrypt_t) (void *c, const unsigned char *outbuf, + const unsigned char *inbuf) + + -- Data type: gcry_cipher_decrypt_t + Type for the `decrypt' function, defined as: gcry_err_code_t + (*gcry_cipher_decrypt_t) (void *c, const unsigned char *outbuf, + const unsigned char *inbuf) + + -- Data type: gcry_cipher_stencrypt_t + Type for the `stencrypt' function, defined as: gcry_err_code_t + (*gcry_cipher_stencrypt_t) (void *c, const unsigned char *outbuf, + const unsigned char *, unsigned int n) + + -- Data type: gcry_cipher_stdecrypt_t + Type for the `stdecrypt' function, defined as: gcry_err_code_t + (*gcry_cipher_stdecrypt_t) (void *c, const unsigned char *outbuf, + const unsigned char *, unsigned int n) + + -- Function: gcry_error_t gcry_cipher_register (gcry_cipher_spec_t + *CIPHER, unsigned int *algorithm_id, gcry_module_t *MODULE) + Register a new cipher module whose specification can be found in + CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representing this module is stored in MODULE. + + -- Function: void gcry_cipher_unregister (gcry_module_t MODULE) + Unregister the cipher identified by MODULE, which must have been + registered with gcry_cipher_register. + + -- Function: gcry_error_t gcry_cipher_list (int *LIST, int + *LIST_LENGTH) + Get a list consisting of the IDs of the loaded cipher modules. If + LIST is zero, write the number of loaded cipher modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less cipher modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. + + +File: gcrypt.info, Node: Available cipher modes, Next: Working with cipher handles, Prev: Cipher modules, Up: Symmetric cryptography + +5.3 Available cipher modes +========================== + +`GCRY_CIPHER_MODE_NONE' + No mode specified. This should not be used. The only exception + is that if Libgcrypt is not used in FIPS mode and if any debug + flag has been set, this mode may be used to bypass the actual + encryption. + +`GCRY_CIPHER_MODE_ECB' + Electronic Codebook mode. + +`GCRY_CIPHER_MODE_CFB' + Cipher Feedback mode. The shift size equals the block size of the + cipher (e.g. for AES it is CFB-128). + +`GCRY_CIPHER_MODE_CBC' + Cipher Block Chaining mode. + +`GCRY_CIPHER_MODE_STREAM' + Stream mode, only to be used with stream cipher algorithms. + +`GCRY_CIPHER_MODE_OFB' + Output Feedback mode. + +`GCRY_CIPHER_MODE_CTR' + Counter mode. + + + +File: gcrypt.info, Node: Working with cipher handles, Next: General cipher functions, Prev: Available cipher modes, Up: Symmetric cryptography + +5.4 Working with cipher handles +=============================== + +To use a cipher algorithm, you must first allocate an according handle. +This is to be done using the open function: + + -- Function: gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *HD, int + ALGO, int MODE, unsigned int FLAGS) + This function creates the context handle required for most of the + other cipher functions and returns a handle to it in `hd'. In + case of an error, an according error code is returned. + + The ID of algorithm to use must be specified via ALGO. See *Note + Available ciphers::, for a list of supported ciphers and the + according constants. + + Besides using the constants directly, the function + `gcry_cipher_map_name' may be used to convert the textual name of + an algorithm into the according numeric ID. + + The cipher mode to use must be specified via MODE. See *Note + Available cipher modes::, for a list of supported cipher modes and + the according constants. Note that some modes are incompatible + with some algorithms - in particular, stream mode + (`GCRY_CIPHER_MODE_STREAM') only works with stream ciphers. Any + block cipher mode (`GCRY_CIPHER_MODE_ECB', `GCRY_CIPHER_MODE_CBC', + `GCRY_CIPHER_MODE_CFB', `GCRY_CIPHER_MODE_OFB' or + `GCRY_CIPHER_MODE_CTR') will work with any block cipher algorithm. + + The third argument FLAGS can either be passed as `0' or as the + bit-wise OR of the following constants. + + `GCRY_CIPHER_SECURE' + Make sure that all operations are allocated in secure memory. + This is useful when the key material is highly confidential. + + `GCRY_CIPHER_ENABLE_SYNC' + This flag enables the CFB sync mode, which is a special + feature of Libgcrypt's CFB mode implementation to allow for + OpenPGP's CFB variant. See `gcry_cipher_sync'. + + `GCRY_CIPHER_CBC_CTS' + Enable cipher text stealing (CTS) for the CBC mode. Cannot + be used simultaneous as GCRY_CIPHER_CBC_MAC. CTS mode makes + it possible to transform data of almost arbitrary size (only + limitation is that it must be greater than the algorithm's + block size). + + `GCRY_CIPHER_CBC_MAC' + Compute CBC-MAC keyed checksums. This is the same as CBC + mode, but only output the last block. Cannot be used + simultaneous as GCRY_CIPHER_CBC_CTS. + + Use the following function to release an existing handle: + + -- Function: void gcry_cipher_close (gcry_cipher_hd_t H) + This function releases the context created by `gcry_cipher_open'. + + In order to use a handle for performing cryptographic operations, a +`key' has to be set first: + + -- Function: gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t H, + const void *K, size_t L) + Set the key K used for encryption or decryption in the context + denoted by the handle H. The length L of the key K must match the + required length of the algorithm set for this context or be in the + allowed range for algorithms with variable key size. The function + checks this and returns an error if there is a problem. A caller + should always check for an error. + + + Most crypto modes requires an initialization vector (IV), which +usually is a non-secret random string acting as a kind of salt value. +The CTR mode requires a counter, which is also similar to a salt value. +To set the IV or CTR, use these functions: + + -- Function: gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t H, const + void *K, size_t L) + Set the initialization vector used for encryption or decryption. + The vector is passed as the buffer K of length L and copied to + internal data structures. The function checks that the IV matches + the requirement of the selected algorithm and mode. + + -- Function: gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t H, + const void *C, size_t L) + Set the counter vector used for encryption or decryption. The + counter is passed as the buffer C of length L and copied to + internal data structures. The function checks that the counter + matches the requirement of the selected algorithm (i.e., it must be + the same size as the block size). + + -- Function: gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t H) + Set the given handle's context back to the state it had after the + last call to gcry_cipher_setkey and clear the initialization + vector. + + Note that gcry_cipher_reset is implemented as a macro. + + The actual encryption and decryption is done by using one of the +following functions. They may be used as often as required to process +all the data. + + -- Function: gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t H, + unsigned char *out, size_t OUTSIZE, const unsigned char *IN, + size_t INLEN) + `gcry_cipher_encrypt' is used to encrypt the data. This function + can either work in place or with two buffers. It uses the cipher + context already setup and described by the handle H. There are 2 + ways to use the function: If IN is passed as `NULL' and INLEN is + `0', in-place encryption of the data in OUT or length OUTSIZE + takes place. With IN being not `NULL', INLEN bytes are encrypted + to the buffer OUT which must have at least a size of INLEN. + OUTSIZE must be set to the allocated size of OUT, so that the + function can check that there is sufficient space. Note that + overlapping buffers are not allowed. + + Depending on the selected algorithms and encryption mode, the + length of the buffers must be a multiple of the block size. + + The function returns `0' on success or an error code. + + -- Function: gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t H, + unsigned char *out, size_t OUTSIZE, const unsigned char *IN, + size_t INLEN) + `gcry_cipher_decrypt' is used to decrypt the data. This function + can either work in place or with two buffers. It uses the cipher + context already setup and described by the handle H. There are 2 + ways to use the function: If IN is passed as `NULL' and INLEN is + `0', in-place decryption of the data in OUT or length OUTSIZE + takes place. With IN being not `NULL', INLEN bytes are decrypted + to the buffer OUT which must have at least a size of INLEN. + OUTSIZE must be set to the allocated size of OUT, so that the + function can check that there is sufficient space. Note that + overlapping buffers are not allowed. + + Depending on the selected algorithms and encryption mode, the + length of the buffers must be a multiple of the block size. + + The function returns `0' on success or an error code. + + OpenPGP (as defined in RFC-2440) requires a special sync operation in +some places. The following function is used for this: + + -- Function: gcry_error_t gcry_cipher_sync (gcry_cipher_hd_t H) + Perform the OpenPGP sync operation on context H. Note that this + is a no-op unless the context was created with the flag + `GCRY_CIPHER_ENABLE_SYNC' + + Some of the described functions are implemented as macros utilizing a +catch-all control function. This control function is rarely used +directly but there is nothing which would inhibit it: + + -- Function: gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t H, int + CMD, void *BUFFER, size_t BUFLEN) + `gcry_cipher_ctl' controls various aspects of the cipher module and + specific cipher contexts. Usually some more specialized functions + or macros are used for this purpose. The semantics of the + function and its parameters depends on the the command CMD and the + passed context handle H. Please see the comments in the source + code (`src/global.c') for details. + + -- Function: gcry_error_t gcry_cipher_info (gcry_cipher_hd_t H, int + WHAT, void *BUFFER, size_t *NBYTES) + `gcry_cipher_info' is used to retrieve various information about a + cipher context or the cipher module in general. + + Currently no information is available. + + +File: gcrypt.info, Node: General cipher functions, Prev: Working with cipher handles, Up: Symmetric cryptography + +5.5 General cipher functions +============================ + +To work with the algorithms, several functions are available to map +algorithm names to the internal identifiers, as well as ways to +retrieve information about an algorithm or the current cipher context. + + -- Function: gcry_error_t gcry_cipher_algo_info (int ALGO, int WHAT, + void *BUFFER, size_t *NBYTES) + This function is used to retrieve information on a specific + algorithm. You pass the cipher algorithm ID as ALGO and the type + of information requested as WHAT. The result is either returned as + the return code of the function or copied to the provided BUFFER + whose allocated length must be available in an integer variable + with the address passed in NBYTES. This variable will also + receive the actual used length of the buffer. + + Here is a list of supported codes for WHAT: + + `GCRYCTL_GET_KEYLEN:' + Return the length of the key. If the algorithm supports + multiple key lengths, the maximum supported value is + returned. The length is returned as number of octets (bytes) + and not as number of bits in NBYTES; BUFFER must be zero. + + `GCRYCTL_GET_BLKLEN:' + Return the block length of the algorithm. The length is + returned as a number of octets in NBYTES; BUFFER must be zero. + + `GCRYCTL_TEST_ALGO:' + Returns `0' when the specified algorithm is available for use. + BUFFER and NBYTES must be zero. + + + + -- Function: const char * gcry_cipher_algo_name (int ALGO) + `gcry_cipher_algo_name' returns a string with the name of the + cipher algorithm ALGO. If the algorithm is not known or another + error occurred, the string `"?"' is returned. This function should + not be used to test for the availability of an algorithm. + + -- Function: int gcry_cipher_map_name (const char *NAME) + `gcry_cipher_map_name' returns the algorithm identifier for the + cipher algorithm described by the string NAME. If this algorithm + is not available `0' is returned. + + -- Function: int gcry_cipher_mode_from_oid (const char *STRING) + Return the cipher mode associated with an ASN.1 object identifier. + The object identifier is expected to be in the IETF-style dotted + decimal notation. The function returns `0' for an unknown object + identifier or when no mode is associated with it. + + +File: gcrypt.info, Node: Public Key cryptography, Next: Hashing, Prev: Symmetric cryptography, Up: Top + +6 Public Key cryptography +************************* + +Public key cryptography, also known as asymmetric cryptography, is an +easy way for key management and to provide digital signatures. +Libgcrypt provides two completely different interfaces to public key +cryptography, this chapter explains the one based on S-expressions. + +* Menu: + +* Available algorithms:: Algorithms supported by the library. +* Used S-expressions:: Introduction into the used S-expression. +* Public key modules:: How to work with public key modules. +* Cryptographic Functions:: Functions for performing the cryptographic actions. +* General public-key related Functions:: General functions, not implementing any cryptography. + +* AC Interface:: Alternative interface to public key functions. + + +File: gcrypt.info, Node: Available algorithms, Next: Used S-expressions, Up: Public Key cryptography + +6.1 Available algorithms +======================== + +Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well +as DSA (Digital Signature Algorithm) and Elgamal. The versatile +interface allows to add more algorithms in the future. + + +File: gcrypt.info, Node: Used S-expressions, Next: Public key modules, Prev: Available algorithms, Up: Public Key cryptography + +6.2 Used S-expressions +====================== + +Libgcrypt's API for asymmetric cryptography is based on data structures +called S-expressions (see +`http://people.csail.mit.edu/rivest/sexp.html') and does not work with +contexts as most of the other building blocks of Libgcrypt do. + +The following information are stored in S-expressions: + + keys + + plain text data + + encrypted data + + signatures + + +To describe how Libgcrypt expect keys, we use examples. Note that words +in uppercase indicate parameters whereas lowercase words are literals. + + Note that all MPI (multi-precision-integers) values are expected to +be in `GCRYMPI_FMT_USG' format. An easy way to create S-expressions is +by using `gcry_sexp_build' which allows to pass a string with +printf-like escapes to insert MPI values. + +* Menu: + +* RSA key parameters:: Parameters used with an RSA key. +* DSA key parameters:: Parameters used with a DSA key. +* ECC key parameters:: Parameters used with ECC keys. + + +File: gcrypt.info, Node: RSA key parameters, Next: DSA key parameters, Up: Used S-expressions + +6.2.1 RSA key parameters +------------------------ + +An RSA private key is described by this S-expression: + + (private-key + (rsa + (n N-MPI) + (e E-MPI) + (d D-MPI) + (p P-MPI) + (q Q-MPI) + (u U-MPI))) + +An RSA public key is described by this S-expression: + + (public-key + (rsa + (n N-MPI) + (e E-MPI))) + +N-MPI + RSA public modulus n. + +E-MPI + RSA public exponent e. + +D-MPI + RSA secret exponent d = e^-1 \bmod (p-1)(q-1). + +P-MPI + RSA secret prime p. + +Q-MPI + RSA secret prime q with p < q. + +U-MPI + Multiplicative inverse u = p^-1 \bmod q. + + For signing and decryption the parameters (p, q, u) are optional but +greatly improve the performance. Either all of these optional +parameters must be given or none of them. They are mandatory for +gcry_pk_testkey. + + Note that OpenSSL uses slighly different parameters: q < p and u = +q^-1 \bmod p. To use these parameters you will need to swap the values +and recompute u. Here is example code to do this: + + if (gcry_mpi_cmp (p, q) > 0) + { + gcry_mpi_swap (p, q); + gcry_mpi_invm (u, p, q); + } + + +File: gcrypt.info, Node: DSA key parameters, Next: ECC key parameters, Prev: RSA key parameters, Up: Used S-expressions + +6.2.2 DSA key parameters +------------------------ + +A DSA private key is described by this S-expression: + + (private-key + (dsa + (p P-MPI) + (q Q-MPI) + (g G-MPI) + (y Y-MPI) + (x X-MPI))) + +P-MPI + DSA prime p. + +Q-MPI + DSA group order q (which is a prime divisor of p-1). + +G-MPI + DSA group generator g. + +Y-MPI + DSA public key value y = g^x \bmod p. + +X-MPI + DSA secret exponent x. + + The public key is similar with "private-key" replaced by "public-key" +and no X-MPI. + + +File: gcrypt.info, Node: ECC key parameters, Prev: DSA key parameters, Up: Used S-expressions + +6.2.3 ECC key parameters +------------------------ + +An ECC private key is described by this S-expression: + + (private-key + (ecc + (p P-MPI) + (a A-MPI) + (b B-MPI) + (g G-POINT) + (n N-MPI) + (q Q-POINT) + (d D-MPI))) + +P-MPI + Prime specifying the field GF(p). + +A-MPI +B-MPI + The two coefficients of the Weierstrass equation y^2 = x^3 + ax + b + +G-POINT + Base point g. + +N-MPI + Order of g + +Q-POINT + The point representing the public key Q = dP. + +D-MPI + The private key d + + All point values are encoded in standard format; Libgcrypt does +currently only support uncompressed points, thus the first byte needs to +be `0x04'. + + The public key is similar with "private-key" replaced by "public-key" +and no D-MPI. + + If the domain parameters are well-known, the name of this curve may +be used. For example + + (private-key + (ecc + (curve "NIST P-192") + (q Q-POINT) + (d D-MPI))) + + The `curve' parameter may be given in any case and is used to replace +missing parameters. + +Currently implemented curves are: +`NIST P-192' +`1.2.840.10045.3.1.1' +`prime192v1' +`secp192r1' + The NIST 192 bit curve, its OID, X9.62 and SECP aliases. + +`NIST P-224' +`secp224r1' + The NIST 224 bit curve and its SECP alias. + +`NIST P-256' +`1.2.840.10045.3.1.7' +`prime256v1' +`secp256r1' + The NIST 256 bit curve, its OID, X9.62 and SECP aliases. + +`NIST P-384' +`secp384r1' + The NIST 384 bit curve and its SECP alias. + +`NIST P-521' +`secp521r1' + The NIST 521 bit curve and its SECP alias. + + As usual the OIDs may optionally be prefixed with the string `OID.' +or `oid.'. + + +File: gcrypt.info, Node: Public key modules, Next: Cryptographic Functions, Prev: Used S-expressions, Up: Public Key cryptography + +6.3 Public key modules +====================== + +Libgcrypt makes it possible to load additional `public key modules'; +these public key algorithms can be used just like the algorithms that +are built into the library directly. For an introduction into +extension modules, see *Note Modules::. + + -- Data type: gcry_pk_spec_t + This is the `module specification structure' needed for registering + public key modules, which has to be filled in by the user before it + can be used to register a module. It contains the following + members: + + `const char *name' + The primary name of this algorithm. + + `char **aliases' + A list of strings that are `aliases' for the algorithm. The + list must be terminated with a NULL element. + + `const char *elements_pkey' + String containing the one-letter names of the MPI values + contained in a public key. + + `const char *element_skey' + String containing the one-letter names of the MPI values + contained in a secret key. + + `const char *elements_enc' + String containing the one-letter names of the MPI values that + are the result of an encryption operation using this + algorithm. + + `const char *elements_sig' + String containing the one-letter names of the MPI values that + are the result of a sign operation using this algorithm. + + `const char *elements_grip' + String containing the one-letter names of the MPI values that + are to be included in the `key grip'. + + `int use' + The bitwise-OR of the following flags, depending on the + abilities of the algorithm: + `GCRY_PK_USAGE_SIGN' + The algorithm supports signing and verifying of data. + + `GCRY_PK_USAGE_ENCR' + The algorithm supports the encryption and decryption of + data. + + `gcry_pk_generate_t generate' + The function responsible for generating a new key pair. See + below for a description of this type. + + `gcry_pk_check_secret_key_t check_secret_key' + The function responsible for checking the sanity of a + provided secret key. See below for a description of this + type. + + `gcry_pk_encrypt_t encrypt' + The function responsible for encrypting data. See below for a + description of this type. + + `gcry_pk_decrypt_t decrypt' + The function responsible for decrypting data. See below for a + description of this type. + + `gcry_pk_sign_t sign' + The function responsible for signing data. See below for a + description of this type. + + `gcry_pk_verify_t verify' + The function responsible for verifying that the provided + signature matches the provided data. See below for a + description of this type. + + `gcry_pk_get_nbits_t get_nbits' + The function responsible for returning the number of bits of + a provided key. See below for a description of this type. + + -- Data type: gcry_pk_generate_t + Type for the `generate' function, defined as: gcry_err_code_t + (*gcry_pk_generate_t) (int algo, unsigned int nbits, unsigned long + use_e, gcry_mpi_t *skey, gcry_mpi_t **retfactors) + + -- Data type: gcry_pk_check_secret_key_t + Type for the `check_secret_key' function, defined as: + gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, + gcry_mpi_t *skey) + + -- Data type: gcry_pk_encrypt_t + Type for the `encrypt' function, defined as: gcry_err_code_t + (*gcry_pk_encrypt_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t + data, gcry_mpi_t *pkey, int flags) + + -- Data type: gcry_pk_decrypt_t + Type for the `decrypt' function, defined as: gcry_err_code_t + (*gcry_pk_decrypt_t) (int algo, gcry_mpi_t *result, gcry_mpi_t + *data, gcry_mpi_t *skey, int flags) + + -- Data type: gcry_pk_sign_t + Type for the `sign' function, defined as: gcry_err_code_t + (*gcry_pk_sign_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *skey) + + -- Data type: gcry_pk_verify_t + Type for the `verify' function, defined as: gcry_err_code_t + (*gcry_pk_verify_t) (int algo, gcry_mpi_t hash, gcry_mpi_t *data, + gcry_mpi_t *pkey, int (*cmp) (void *, gcry_mpi_t), void *opaquev) + + -- Data type: gcry_pk_get_nbits_t + Type for the `get_nbits' function, defined as: unsigned + (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey) + + -- Function: gcry_error_t gcry_pk_register (gcry_pk_spec_t *PUBKEY, + unsigned int *algorithm_id, gcry_module_t *MODULE) + Register a new public key module whose specification can be found + in PUBKEY. On success, a new algorithm ID is stored in + ALGORITHM_ID and a pointer representing this module is stored in + MODULE. + + -- Function: void gcry_pk_unregister (gcry_module_t MODULE) + Unregister the public key module identified by MODULE, which must + have been registered with gcry_pk_register. + + -- Function: gcry_error_t gcry_pk_list (int *LIST, int *LIST_LENGTH) + Get a list consisting of the IDs of the loaded pubkey modules. If + LIST is zero, write the number of loaded pubkey modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less pubkey modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. + + +File: gcrypt.info, Node: Cryptographic Functions, Next: General public-key related Functions, Prev: Public key modules, Up: Public Key cryptography + +6.4 Cryptographic Functions +=========================== + +Note that we will in future allow to use keys without p,q and u +specified and may also support other parameters for performance reasons. + +Some functions operating on S-expressions support `flags', that +influence the operation. These flags have to be listed in a +sub-S-expression named `flags'; the following flags are known: + +`pkcs1' + Use PKCS#1 block type 2 padding. + +`no-blinding' + Do not use a technique called `blinding', which is used by default + in order to prevent leaking of secret information. Blinding is + only implemented by RSA, but it might be implemented by other + algorithms in the future as well, when necessary. + +Now that we know the key basics, we can carry on and explain how to +encrypt and decrypt data. In almost all cases the data is a random +session key which is in turn used for the actual encryption of the real +data. There are 2 functions to do this: + + -- Function: gcry_error_t gcry_pk_encrypt (gcry_sexp_t *R_CIPH, + gcry_sexp_t DATA, gcry_sexp_t PKEY) + Obviously a public key must be provided for encryption. It is + expected as an appropriate S-expression (see above) in PKEY. The + data to be encrypted can either be in the simple old format, which + is a very simple S-expression consisting only of one MPI, or it + may be a more complex S-expression which also allows to specify + flags for operation, like e.g. padding rules. + + If you don't want to let Libgcrypt handle the padding, you must + pass an appropriate MPI using this expression for DATA: + + (data + (flags raw) + (value MPI)) + + This has the same semantics as the old style MPI only way. MPI is + the actual data, already padded appropriate for your protocol. + Most systems however use PKCS#1 padding and so you can use this + S-expression for DATA: + + (data + (flags pkcs1) + (value BLOCK)) + + Here, the "flags" list has the "pkcs1" flag which let the function + know that it should provide PKCS#1 block type 2 padding. The + actual data to be encrypted is passed as a string of octets in + BLOCK. The function checks that this data actually can be used + with the given key, does the padding and encrypts it. + + If the function could successfully perform the encryption, the + return value will be 0 and a new S-expression with the encrypted + result is allocated and assigned to the variable at the address of + R_CIPH. The caller is responsible to release this value using + `gcry_sexp_release'. In case of an error, an error code is + returned and R_CIPH will be set to `NULL'. + + The returned S-expression has this format when used with RSA: + + (enc-val + (rsa + (a A-MPI))) + + Where A-MPI is an MPI with the result of the RSA operation. When + using the Elgamal algorithm, the return value will have this + format: + + (enc-val + (elg + (a A-MPI) + (b B-MPI))) + + Where A-MPI and B-MPI are MPIs with the result of the Elgamal + encryption operation. + + -- Function: gcry_error_t gcry_pk_decrypt (gcry_sexp_t *R_PLAIN, + gcry_sexp_t DATA, gcry_sexp_t SKEY) + Obviously a private key must be provided for decryption. It is + expected as an appropriate S-expression (see above) in SKEY. The + data to be decrypted must match the format of the result as + returned by `gcry_pk_encrypt', but should be enlarged with a + `flags' element: + + (enc-val + (flags) + (elg + (a A-MPI) + (b B-MPI))) + + Note that this function currently does not know of any padding + methods and the caller must do any un-padding on his own. + + The function returns 0 on success or an error code. The variable + at the address of R_PLAIN will be set to NULL on error or receive + the decrypted value on success. The format of R_PLAIN is a simple + S-expression part (i.e. not a valid one) with just one MPI if + there was no `flags' element in DATA; if at least an empty `flags' + is passed in DATA, the format is: + + (value PLAINTEXT) + + Another operation commonly performed using public key cryptography is +signing data. In some sense this is even more important than +encryption because digital signatures are an important instrument for +key management. Libgcrypt supports digital signatures using 2 +functions, similar to the encryption functions: + + -- Function: gcry_error_t gcry_pk_sign (gcry_sexp_t *R_SIG, + gcry_sexp_t DATA, gcry_sexp_t SKEY) + This function creates a digital signature for DATA using the + private key SKEY and place it into the variable at the address of + R_SIG. DATA may either be the simple old style S-expression with + just one MPI or a modern and more versatile S-expression which + allows to let Libgcrypt handle padding: + + (data + (flags pkcs1) + (hash HASH-ALGO BLOCK)) + + This example requests to sign the data in BLOCK after applying + PKCS#1 block type 1 style padding. HASH-ALGO is a string with the + hash algorithm to be encoded into the signature, this may be any + hash algorithm name as supported by Libgcrypt. Most likely, this + will be "sha1", "rmd160" or "md5". It is obvious that the length + of BLOCK must match the size of that message digests; the function + checks that this and other constraints are valid. + + If PKCS#1 padding is not required (because the caller does already + provide a padded value), either the old format or better the + following format should be used: + + (data + (flags raw) + (value MPI)) + + Here, the data to be signed is directly given as an MPI. + + The signature is returned as a newly allocated S-expression in + R_SIG using this format for RSA: + + (sig-val + (rsa + (s S-MPI))) + + Where S-MPI is the result of the RSA sign operation. For DSA the + S-expression returned is: + + (sig-val + (dsa + (r R-MPI) + (s S-MPI))) + + Where R-MPI and S-MPI are the result of the DSA sign operation. + For Elgamal signing (which is slow, yields large numbers and + probably is not as secure as the other algorithms), the same + format is used with "elg" replacing "dsa". + +The operation most commonly used is definitely the verification of a +signature. Libgcrypt provides this function: + + -- Function: gcry_error_t gcry_pk_verify (gcry_sexp_t SIG, + gcry_sexp_t DATA, gcry_sexp_t PKEY) + This is used to check whether the signature SIG matches the DATA. + The public key PKEY must be provided to perform this verification. + This function is similar in its parameters to `gcry_pk_sign' with + the exceptions that the public key is used instead of the private + key and that no signature is created but a signature, in a format + as created by `gcry_pk_sign', is passed to the function in SIG. + + The result is 0 for success (i.e. the data matches the signature), + or an error code where the most relevant code is + `GCRYERR_BAD_SIGNATURE' to indicate that the signature does not + match the provided data. + + + +File: gcrypt.info, Node: General public-key related Functions, Next: AC Interface, Prev: Cryptographic Functions, Up: Public Key cryptography + +6.5 General public-key related Functions +======================================== + +A couple of utility functions are available to retrieve the length of +the key, map algorithm identifiers and perform sanity checks: + + -- Function: const char * gcry_pk_algo_name (int ALGO) + Map the public key algorithm id ALGO to a string representation of + the algorithm name. For unknown algorithms this functions returns + the string `"?"'. This function should not be used to test for the + availability of an algorithm. + + -- Function: int gcry_pk_map_name (const char *NAME) + Map the algorithm NAME to a public key algorithm Id. Returns 0 if + the algorithm name is not known. + + -- Function: int gcry_pk_test_algo (int ALGO) + Return 0 if the public key algorithm ALGO is available for use. + Note that this is implemented as a macro. + + -- Function: unsigned int gcry_pk_get_nbits (gcry_sexp_t KEY) + Return what is commonly referred as the key length for the given + public or private in KEY. + + -- Function: unsigned char * gcry_pk_get_keygrip (gcry_sexp_t KEY, + unsigned char *ARRAY) + Return the so called "keygrip" which is the SHA-1 hash of the + public key parameters expressed in a way depended on the + algorithm. ARRAY must either provide space for 20 bytes or be + `NULL'. In the latter case a newly allocated array of that size is + returned. On success a pointer to the newly allocated space or to + ARRAY is returned. `NULL' is returned to indicate an error which + is most likely an unknown algorithm or one where a "keygrip" has + not yet been defined. The function accepts public or secret keys + in KEY. + + -- Function: gcry_error_t gcry_pk_testkey (gcry_sexp_t KEY) + Return zero if the private key KEY is `sane', an error code + otherwise. Note that it is not possible to check the `saneness' + of a public key. + + + -- Function: gcry_error_t gcry_pk_algo_info (int ALGO, int WHAT, + void *BUFFER, size_t *NBYTES) + Depending on the value of WHAT return various information about + the public key algorithm with the id ALGO. Note that the function + returns `-1' on error and the actual error code must be retrieved + using the function `gcry_errno'. The currently defined values for + WHAT are: + + `GCRYCTL_TEST_ALGO:' + Return 0 if the specified algorithm is available for use. + BUFFER must be `NULL', NBYTES may be passed as `NULL' or + point to a variable with the required usage of the algorithm. + This may be 0 for "don't care" or the bit-wise OR of these + flags: + + `GCRY_PK_USAGE_SIGN' + Algorithm is usable for signing. + + `GCRY_PK_USAGE_ENCR' + Algorithm is usable for encryption. + + Unless you need to test for the allowed usage, it is in + general better to use the macro gcry_pk_test_algo instead. + + `GCRYCTL_GET_ALGO_USAGE:' + Return the usage flags for the given algorithm. An invalid + algorithm return 0. Disabled algorithms are ignored here + because we want to know whether the algorithm is at all + capable of a certain usage. + + `GCRYCTL_GET_ALGO_NPKEY' + Return the number of elements the public key for algorithm + ALGO consist of. Return 0 for an unknown algorithm. + + `GCRYCTL_GET_ALGO_NSKEY' + Return the number of elements the private key for algorithm + ALGO consist of. Note that this value is always larger than + that of the public key. Return 0 for an unknown algorithm. + + `GCRYCTL_GET_ALGO_NSIGN' + Return the number of elements a signature created with the + algorithm ALGO consists of. Return 0 for an unknown + algorithm or for an algorithm not capable of creating + signatures. + + `GCRYCTL_GET_ALGO_NENC' + Return the number of elements a encrypted message created + with the algorithm ALGO consists of. Return 0 for an unknown + algorithm or for an algorithm not capable of encryption. + + Please note that parameters not required should be passed as + `NULL'. + + -- Function: gcry_error_t gcry_pk_ctl (int CMD, void *BUFFER, + size_t BUFLEN) + This is a general purpose function to perform certain control + operations. CMD controls what is to be done. The return value is + 0 for success or an error code. Currently supported values for + CMD are: + + `GCRYCTL_DISABLE_ALGO' + Disable the algorithm given as an algorithm id in BUFFER. + BUFFER must point to an `int' variable with the algorithm id + and BUFLEN must have the value `sizeof (int)'. + + +Libgcrypt also provides a function to generate public key pairs: + + -- Function: gcry_error_t gcry_pk_genkey (gcry_sexp_t *R_KEY, + gcry_sexp_t PARMS) + This function create a new public key pair using information given + in the S-expression PARMS and stores the private and the public key + in one new S-expression at the address given by R_KEY. In case of + an error, R_KEY is set to `NULL'. The return code is 0 for + success or an error code otherwise. + + Here is an example for PARMS to create an 2048 bit RSA key: + + (genkey + (rsa + (nbits 4:2048))) + + To create an Elgamal key, substitute "elg" for "rsa" and to create + a DSA key use "dsa". Valid ranges for the key length depend on the + algorithms; all commonly used key lengths are supported. Currently + supported parameters are: + + `nbits' + This is always required to specify the length of the key. + The argument is a string with a number in C-notation. The + value should be a multiple of 8. + + `curve NAME' + For ECC a named curve may be used instead of giving the + number of requested bits. This allows to request a specific + curve to override a default selection Libgcrypt would have + taken if `nbits' has been given. The available names are + listed with the description of the ECC public key parameters. + + `rsa-use-e' + This is only used with RSA to give a hint for the public + exponent. The value will be used as a base to test for a + usable exponent. Some values are special: + + `0' + Use a secure and fast value. This is currently the + number 41. + + `1' + Use a value as required by some crypto policies. This + is currently the number 65537. + + `2' + Reserved + + `> 2' + Use the given value. + + If this parameter is not used, Libgcrypt uses for historic + reasons 65537. + + `qbits' + This is only meanigful for DSA keys. If it is given the DSA + key is generated with a Q parameyer of this size. If it is + not given or zero Q is deduced from NBITS in this way: + `512 <= N <= 1024' + Q = 160 + + `N = 2048' + Q = 224 + + `N = 3072' + Q = 256 + + `N = 7680' + Q = 384 + + `N = 15360' + Q = 512 + Note that in this case only the values for N, as given in the + table, are allowed. When specifying Q all values of N in the + range 512 to 15680 are valid as long as they are multiples of + 8. + + `transient-key' + This is only meaningful for RSA and DSA keys. This is a flag + with no value. If given the RSA or DSA key is created using + a faster and a somewhat less secure random number generator. + This flag may be used for keys which are only used for a + short time and do not require full cryptographic strength. + + `domain' + This is only meaningful for DLP algorithms. If specified + keys are generated with domain parameters taken from this + list. The exact format of this parameter depends on the + actual algorithm. It is currently only implemented for DSA + using this format: + + (genkey + (dsa + (domain + (p P-MPI) + (q Q-MPI) + (g Q-MPI)))) + + `nbits' and `qbits' may not be specified because they are + derived from the domain parameters. + + `derive-parms' + This is currently only implemented for RSA and DSA keys. It + is not allowed to use this together with a `domain' + specification. If given, it is used to derive the keys using + the given parameters. + + If given for an RSA key the X9.31 key generation algorithm is + used even if libgcrypt is not in FIPS mode. If given for a + DSA key, the FIPS 186 algorithm is used even if libgcrypt is + not in FIPS mode. + + (genkey + (rsa + (nbits 4:1024) + (rsa-use-e 1:3) + (derive-parms + (Xp1 #1A1916DDB29B4EB7EB6732E128#) + (Xp2 #192E8AAC41C576C822D93EA433#) + (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D + 769D6D76646C7A792E16EBD89FE6FC5B605A6493 + 39DFC925A86A4C6D150B71B9EEA02D68885F5009 + B98BD984#) + (Xq1 #1A5CF72EE770DE50CB09ACCEA9#) + (Xq2 #134E4CAA16D2350A21D775C404#) + (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D + 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325 + 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34 + 321DE34A#)))) + + (genkey + (dsa + (nbits 4:1024) + (derive-parms + (seed SEED-MPI)))) + + `use-x931' + Force the use of the ANSI X9.31 key generation algorithm + instead of the default algorithm. This flag is only + meaningful for RSA and usually not required. Note that this + algorithm is implicitly used if either `derive-parms' is + given or Libgcrypt is in FIPS mode. + + `use-fips186' + Force the use of the FIPS 186 key generation algorithm + instead of the default algorithm. This flag is only + meaningful for DSA and usually not required. Note that this + algorithm is implicitly used if either `derive-parms' is + given or Libgcrypt is in FIPS mode. As of now FIPS 186-2 is + implemented; after the approval of FIPS 186-3 the code will + be changed to implement 186-3. + + `use-fips186-2' + Force the use of the FIPS 186-2 key generation algorithm + instead of the default algorithm. This algorithm is slighlty + different from FIPS 186-3 and allows only 1024 bit keys. + This flag is only meaningful for DSA and only required for + FIPS testing backward compatibility. + + + The key pair is returned in a format depending on the algorithm. + Both private and public keys are returned in one container and may + be accompanied by some miscellaneous information. + + As an example, here is what the Elgamal key generation returns: + + (key-data + (public-key + (elg + (p P-MPI) + (g G-MPI) + (y Y-MPI))) + (private-key + (elg + (p P-MPI) + (g G-MPI) + (y Y-MPI) + (x X-MPI))) + (misc-key-info + (pm1-factors N1 N2 ... NN)) + + As you can see, some of the information is duplicated, but this + provides an easy way to extract either the public or the private + key. Note that the order of the elements is not defined, e.g. the + private key may be stored before the public key. N1 N2 ... NN is a + list of prime numbers used to composite P-MPI; this is in general + not a very useful information and only available if the key + generation algorithm provides them. + + +File: gcrypt.info, Node: AC Interface, Prev: General public-key related Functions, Up: Public Key cryptography + +6.6 Alternative Public Key Interface +==================================== + +This section documents the alternative interface to asymmetric +cryptography (ac) that is not based on S-expressions, but on native C +data structures. As opposed to the pk interface described in the +former chapter, this one follows an open/use/close paradigm like other +building blocks of the library. + + *This interface has a few known problems; most noteworthy an +inherent tendency to leak memory. It might not be available in +forthcoming versions of Libgcrypt.* + +* Menu: + +* Available asymmetric algorithms:: List of algorithms supported by the library. +* Working with sets of data:: How to work with sets of data. +* Working with IO objects:: How to work with IO objects. +* Working with handles:: How to use handles. +* Working with keys:: How to work with keys. +* Using cryptographic functions:: How to perform cryptographic operations. +* Handle-independent functions:: General functions independent of handles. + + +File: gcrypt.info, Node: Available asymmetric algorithms, Next: Working with sets of data, Up: AC Interface + +6.6.1 Available asymmetric algorithms +------------------------------------- + +Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well +as DSA (Digital Signature Algorithm) and Elgamal. The versatile +interface allows to add more algorithms in the future. + + -- Data type: gcry_ac_id_t + The following constants are defined for this type: + + `GCRY_AC_RSA' + Rivest-Shamir-Adleman + + `GCRY_AC_DSA' + Digital Signature Algorithm + + `GCRY_AC_ELG' + Elgamal + + `GCRY_AC_ELG_E' + Elgamal, encryption only. + + +File: gcrypt.info, Node: Working with sets of data, Next: Working with IO objects, Prev: Available asymmetric algorithms, Up: AC Interface + +6.6.2 Working with sets of data +------------------------------- + +In the context of this interface the term `data set' refers to a list +of `named MPI values' that is used by functions performing +cryptographic operations; a named MPI value is a an MPI value, +associated with a label. + + Such data sets are used for representing keys, since keys simply +consist of a variable amount of numbers. Furthermore some functions +return data sets to the caller that are to be provided to other +functions. + + This section documents the data types, symbols and functions that are +relevant for working with data sets. + + -- Data type: gcry_ac_data_t + A single data set. + + The following flags are supported: + +`GCRY_AC_FLAG_DEALLOC' + Used for storing data in a data set. If given, the data will be + released by the library. Note that whenever one of the ac + functions is about to release objects because of this flag, the + objects are expected to be stored in memory allocated through the + Libgcrypt memory management. In other words: gcry_free() is used + instead of free(). + +`GCRY_AC_FLAG_COPY' + Used for storing/retrieving data in/from a data set. If given, the + library will create copies of the provided/contained data, which + will then be given to the user/associated with the data set. + + -- Function: gcry_error_t gcry_ac_data_new (gcry_ac_data_t *DATA) + Creates a new, empty data set and stores it in DATA. + + -- Function: void gcry_ac_data_destroy (gcry_ac_data_t DATA) + Destroys the data set DATA. + + -- Function: gcry_error_t gcry_ac_data_set (gcry_ac_data_t DATA, + unsigned int FLAGS, char *NAME, gcry_mpi_t MPI) + Add the value MPI to DATA with the label NAME. If FLAGS contains + GCRY_AC_FLAG_COPY, the data set will contain copies of NAME and + MPI. If FLAGS contains GCRY_AC_FLAG_DEALLOC or GCRY_AC_FLAG_COPY, + the values contained in the data set will be deallocated when they + are to be removed from the data set. + + -- Function: gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *DATA_CP, + gcry_ac_data_t DATA) + Create a copy of the data set DATA and store it in DATA_CP. + FIXME: exact semantics undefined. + + -- Function: unsigned int gcry_ac_data_length (gcry_ac_data_t DATA) + Returns the number of named MPI values inside of the data set DATA. + + -- Function: gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t DATA, + unsigned int FLAGS, char *NAME, gcry_mpi_t *MPI) + Store the value labelled with NAME found in DATA in MPI. If FLAGS + contains GCRY_AC_FLAG_COPY, store a copy of the MPI value + contained in the data set. MPI may be NULL (this might be useful + for checking the existence of an MPI with extracting it). + + -- Function: gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t DATA, + unsigned int flags, unsigned int INDEX, const char **NAME, + gcry_mpi_t *MPI) + Stores in NAME and MPI the named MPI value contained in the data + set DATA with the index IDX. If FLAGS contains GCRY_AC_FLAG_COPY, + store copies of the values contained in the data set. NAME or MPI + may be NULL. + + -- Function: void gcry_ac_data_clear (gcry_ac_data_t DATA) + Destroys any values contained in the data set DATA. + + -- Function: gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t DATA, + gcry_sexp_t *SEXP, const char **IDENTIFIERS) + This function converts the data set DATA into a newly created + S-Expression, which is to be stored in SEXP; IDENTIFIERS is a NULL + terminated list of C strings, which specifies the structure of the + S-Expression. + + Example: + + If IDENTIFIERS is a list of pointers to the strings "foo" and + "bar" and if DATA is a data set containing the values "val1 = + 0x01" and "val2 = 0x02", then the resulting S-Expression will look + like this: (foo (bar ((val1 0x01) (val2 0x02))). + + -- Function: gcry_error gcry_ac_data_from_sexp (gcry_ac_data_t *DATA, + gcry_sexp_t SEXP, const char **IDENTIFIERS) + This function converts the S-Expression SEXP into a newly created + data set, which is to be stored in DATA; IDENTIFIERS is a NULL + terminated list of C strings, which specifies the structure of the + S-Expression. If the list of identifiers does not match the + structure of the S-Expression, the function fails. + + +File: gcrypt.info, Node: Working with IO objects, Next: Working with handles, Prev: Working with sets of data, Up: AC Interface + +6.6.3 Working with IO objects +----------------------------- + +Note: IO objects are currently only used in the context of message +encoding/decoding and encryption/signature schemes. + + -- Data type: gcry_ac_io_t + `gcry_ac_io_t' is the type to be used for IO objects. + + IO objects provide an uniform IO layer on top of different underlying +IO mechanisms; either they can be used for providing data to the +library (mode is GCRY_AC_IO_READABLE) or they can be used for +retrieving data from the library (mode is GCRY_AC_IO_WRITABLE). + + IO object need to be initialized by calling on of the following +functions: + + -- Function: void gcry_ac_io_init (gcry_ac_io_t *AC_IO, + gcry_ac_io_mode_t MODE, gcry_ac_io_type_t TYPE, ...); + Initialize AC_IO according to MODE, TYPE and the variable list of + arguments. The list of variable arguments to specify depends on + the given TYPE. + + -- Function: void gcry_ac_io_init_va (gcry_ac_io_t *AC_IO, + gcry_ac_io_mode_t MODE, gcry_ac_io_type_t TYPE, va_list AP); + Initialize AC_IO according to MODE, TYPE and the variable list of + arguments AP. The list of variable arguments to specify depends + on the given TYPE. + + The following types of IO objects exist: + +`GCRY_AC_IO_STRING' + In case of GCRY_AC_IO_READABLE the IO object will provide data + from a memory string. Arguments to specify at initialization time: + `unsigned char *' + Pointer to the beginning of the memory string + + `size_t' + Size of the memory string + In case of GCRY_AC_IO_WRITABLE the object will store retrieved + data in a newly allocated memory string. Arguments to specify at + initialization time: + `unsigned char **' + Pointer to address, at which the pointer to the newly created + memory string is to be stored + + `size_t *' + Pointer to address, at which the size of the newly created + memory string is to be stored + +`GCRY_AC_IO_CALLBACK' + In case of GCRY_AC_IO_READABLE the object will forward read + requests to a provided callback function. Arguments to specify at + initialization time: + `gcry_ac_data_read_cb_t' + Callback function to use + + `void *' + Opaque argument to provide to the callback function + In case of GCRY_AC_IO_WRITABLE the object will forward write + requests to a provided callback function. Arguments to specify at + initialization time: + `gcry_ac_data_write_cb_t' + Callback function to use + + `void *' + Opaque argument to provide to the callback function + + +File: gcrypt.info, Node: Working with handles, Next: Working with keys, Prev: Working with IO objects, Up: AC Interface + +6.6.4 Working with handles +-------------------------- + +In order to use an algorithm, an according handle must be created. +This is done using the following function: + + -- Function: gcry_error_t gcry_ac_open (gcry_ac_handle_t *HANDLE, int + ALGORITHM, int FLAGS) + Creates a new handle for the algorithm ALGORITHM and stores it in + HANDLE. FLAGS is not used currently. + + ALGORITHM must be a valid algorithm ID, see *Note Available + asymmetric algorithms::, for a list of supported algorithms and the + according constants. Besides using the listed constants directly, + the functions `gcry_pk_name_to_id' may be used to convert the + textual name of an algorithm into the according numeric ID. + + -- Function: void gcry_ac_close (gcry_ac_handle_t HANDLE) + Destroys the handle HANDLE. + + +File: gcrypt.info, Node: Working with keys, Next: Using cryptographic functions, Prev: Working with handles, Up: AC Interface + +6.6.5 Working with keys +----------------------- + + -- Data type: gcry_ac_key_type_t + Defined constants: + + `GCRY_AC_KEY_SECRET' + Specifies a secret key. + + `GCRY_AC_KEY_PUBLIC' + Specifies a public key. + + -- Data type: gcry_ac_key_t + This type represents a single `key', either a secret one or a + public one. + + -- Data type: gcry_ac_key_pair_t + This type represents a `key pair' containing a secret and a public + key. + + Key data structures can be created in two different ways; a new key +pair can be generated, resulting in ready-to-use key. Alternatively a +key can be initialized from a given data set. + + -- Function: gcry_error_t gcry_ac_key_init (gcry_ac_key_t *KEY, + gcry_ac_handle_t HANDLE, gcry_ac_key_type_t TYPE, + gcry_ac_data_t DATA) + Creates a new key of type TYPE, consisting of the MPI values + contained in the data set DATA and stores it in KEY. + + -- Function: gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t + HANDLE, unsigned int NBITS, void *KEY_SPEC, + gcry_ac_key_pair_t *KEY_PAIR, gcry_mpi_t **MISC_DATA) + Generates a new key pair via the handle HANDLE of NBITS bits and + stores it in KEY_PAIR. + + In case non-standard settings are wanted, a pointer to a structure + of type `gcry_ac_key_spec__t', matching the selected + algorithm, can be given as KEY_SPEC. MISC_DATA is not used yet. + Such a structure does only exist for RSA. A description of the + members of the supported structures follows. + + `gcry_ac_key_spec_rsa_t' + + `gcry_mpi_t e' + Generate the key pair using a special `e'. The value of + `e' has the following meanings: + `= 0' + Let Libgcrypt decide what exponent should be used. + + `= 1' + Request the use of a "secure" exponent; this is + required by some specification to be 65537. + + `> 2' + Try starting at this value until a working exponent + is found. Note that the current implementation + leaks some information about the private key + because the incrementation used is not randomized. + Thus, this function will be changed in the future + to return a random exponent of the given size. + + Example code: + { + gcry_ac_key_pair_t key_pair; + gcry_ac_key_spec_rsa_t rsa_spec; + + rsa_spec.e = gcry_mpi_new (0); + gcry_mpi_set_ui (rsa_spec.e, 1); + + err = gcry_ac_open (&handle, GCRY_AC_RSA, 0); + assert (! err); + + err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, + &key_pair, NULL); + assert (! err); + } + + -- Function: gcry_ac_key_t gcry_ac_key_pair_extract + (gcry_ac_key_pair_t KEY_PAIR, gcry_ac_key_type_t WHICH) + Returns the key of type WHICH out of the key pair KEY_PAIR. + + -- Function: void gcry_ac_key_destroy (gcry_ac_key_t KEY) + Destroys the key KEY. + + -- Function: void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t + KEY_PAIR) + Destroys the key pair KEY_PAIR. + + -- Function: gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t KEY) + Returns the data set contained in the key KEY. + + -- Function: gcry_error_t gcry_ac_key_test (gcry_ac_handle_t HANDLE, + gcry_ac_key_t KEY) + Verifies that the private key KEY is sane via HANDLE. + + -- Function: gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t + HANDLE, gcry_ac_key_t KEY, unsigned int *NBITS) + Stores the number of bits of the key KEY in NBITS via HANDLE. + + -- Function: gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t + HANDLE, gcry_ac_key_t KEY, unsigned char *KEY_GRIP) + Writes the 20 byte long key grip of the key KEY to KEY_GRIP via + HANDLE. + + +File: gcrypt.info, Node: Using cryptographic functions, Next: Handle-independent functions, Prev: Working with keys, Up: AC Interface + +6.6.6 Using cryptographic functions +----------------------------------- + +The following flags might be relevant: + +`GCRY_AC_FLAG_NO_BLINDING' + Disable any blinding, which might be supported by the chosen + algorithm; blinding is the default. + + There exist two kinds of cryptographic functions available through +the ac interface: primitives, and high-level functions. + + Primitives deal with MPIs (data sets) directly; what they provide is +direct access to the cryptographic operations provided by an algorithm +implementation. + + High-level functions deal with octet strings, according to a +specified "scheme". Schemes make use of "encoding methods", which are +responsible for converting the provided octet strings into MPIs, which +are then forwared to the cryptographic primitives. Since schemes are +to be used for a special purpose in order to achieve a particular +security goal, there exist "encryption schemes" and "signature +schemes". Encoding methods can be used seperately or implicitly +through schemes. + + What follows is a description of the cryptographic primitives. + + -- Function: gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t + HANDLE, unsigned int FLAGS, gcry_ac_key_t KEY, gcry_mpi_t + DATA_PLAIN, gcry_ac_data_t *DATA_ENCRYPTED) + Encrypts the plain text MPI value DATA_PLAIN with the key public + KEY under the control of the flags FLAGS and stores the resulting + data set into DATA_ENCRYPTED. + + -- Function: gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t + HANDLE, unsigned int FLAGS, gcry_ac_key_t KEY, gcry_mpi_t + *DATA_PLAIN, gcry_ac_data_t DATA_ENCRYPTED) + Decrypts the encrypted data contained in the data set + DATA_ENCRYPTED with the secret key KEY under the control of the + flags FLAGS and stores the resulting plain text MPI value in + DATA_PLAIN. + + -- Function: gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t HANDLE, + gcry_ac_key_t KEY, gcry_mpi_t DATA, gcry_ac_data_t + *DATA_SIGNATURE) + Signs the data contained in DATA with the secret key KEY and + stores the resulting signature in the data set DATA_SIGNATURE. + + -- Function: gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t + HANDLE, gcry_ac_key_t KEY, gcry_mpi_t DATA, gcry_ac_data_t + DATA_SIGNATURE) + Verifies that the signature contained in the data set + DATA_SIGNATURE is indeed the result of signing the data contained + in DATA with the secret key belonging to the public key KEY. + + What follows is a description of the high-level functions. + + The type "gcry_ac_em_t" is used for specifying encoding methods; the +following methods are supported: + +`GCRY_AC_EME_PKCS_V1_5' + PKCS-V1_5 Encoding Method for Encryption. Options must be provided + through a pointer to a correctly initialized object of type + gcry_ac_eme_pkcs_v1_5_t. + +`GCRY_AC_EMSA_PKCS_V1_5' + PKCS-V1_5 Encoding Method for Signatures with Appendix. Options + must be provided through a pointer to a correctly initialized + object of type gcry_ac_emsa_pkcs_v1_5_t. + + Option structure types: + +`gcry_ac_eme_pkcs_v1_5_t' + + `gcry_ac_key_t key' + + `gcry_ac_handle_t handle' + +`gcry_ac_emsa_pkcs_v1_5_t' + + `gcry_md_algo_t md' + + `size_t em_n' + + Encoding methods can be used directly through the following +functions: + + -- Function: gcry_error_t gcry_ac_data_encode (gcry_ac_em_t METHOD, + unsigned int FLAGS, void *OPTIONS, unsigned char *M, size_t + M_N, unsigned char **EM, size_t *EM_N) + Encodes the message contained in M of size M_N according to + METHOD, FLAGS and OPTIONS. The newly created encoded message is + stored in EM and EM_N. + + -- Function: gcry_error_t gcry_ac_data_decode (gcry_ac_em_t METHOD, + unsigned int FLAGS, void *OPTIONS, unsigned char *EM, size_t + EM_N, unsigned char **M, size_t *M_N) + Decodes the message contained in EM of size EM_N according to + METHOD, FLAGS and OPTIONS. The newly created decoded message is + stored in M and M_N. + + The type "gcry_ac_scheme_t" is used for specifying schemes; the +following schemes are supported: + +`GCRY_AC_ES_PKCS_V1_5' + PKCS-V1_5 Encryption Scheme. No options can be provided. + +`GCRY_AC_SSA_PKCS_V1_5' + PKCS-V1_5 Signature Scheme (with Appendix). Options can be + provided through a pointer to a correctly initialized object of + type gcry_ac_ssa_pkcs_v1_5_t. + + Option structure types: + +`gcry_ac_ssa_pkcs_v1_5_t' + + `gcry_md_algo_t md' + + The functions implementing schemes: + + -- Function: gcry_error_t gcry_ac_data_encrypt_scheme + (gcry_ac_handle_t HANDLE, gcry_ac_scheme_t SCHEME, unsigned + int FLAGS, void *OPTS, gcry_ac_key_t KEY, gcry_ac_io_t + *IO_MESSAGE, gcry_ac_io_t *IO_CIPHER) + Encrypts the plain text readable from IO_MESSAGE through HANDLE + with the public key KEY according to SCHEME, FLAGS and OPTS. If + OPTS is not NULL, it has to be a pointer to a structure specific + to the chosen scheme (gcry_ac_es_*_t). The encrypted message is + written to IO_CIPHER. + + -- Function: gcry_error_t gcry_ac_data_decrypt_scheme + (gcry_ac_handle_t HANDLE, gcry_ac_scheme_t SCHEME, unsigned + int FLAGS, void *OPTS, gcry_ac_key_t KEY, gcry_ac_io_t + *IO_CIPHER, gcry_ac_io_t *IO_MESSAGE) + Decrypts the cipher text readable from IO_CIPHER through HANDLE + with the secret key KEY according to SCHEME, FLAGS and OPTS. If + OPTS is not NULL, it has to be a pointer to a structure specific + to the chosen scheme (gcry_ac_es_*_t). The decrypted message is + written to IO_MESSAGE. + + -- Function: gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t + HANDLE, gcry_ac_scheme_t SCHEME, unsigned int FLAGS, void + *OPTS, gcry_ac_key_t KEY, gcry_ac_io_t *IO_MESSAGE, + gcry_ac_io_t *IO_SIGNATURE) + Signs the message readable from IO_MESSAGE through HANDLE with the + secret key KEY according to SCHEME, FLAGS and OPTS. If OPTS is + not NULL, it has to be a pointer to a structure specific to the + chosen scheme (gcry_ac_ssa_*_t). The signature is written to + IO_SIGNATURE. + + -- Function: gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t + HANDLE, gcry_ac_scheme_t SCHEME, unsigned int FLAGS, void + *OPTS, gcry_ac_key_t KEY, gcry_ac_io_t *IO_MESSAGE, + gcry_ac_io_t *IO_SIGNATURE) + Verifies through HANDLE that the signature readable from + IO_SIGNATURE is indeed the result of signing the message readable + from IO_MESSAGE with the secret key belonging to the public key + KEY according to SCHEME and OPTS. If OPTS is not NULL, it has to + be an anonymous structure (gcry_ac_ssa_*_t) specific to the chosen + scheme. + + +File: gcrypt.info, Node: Handle-independent functions, Prev: Using cryptographic functions, Up: AC Interface + +6.6.7 Handle-independent functions +---------------------------------- + +These two functions are deprecated; do not use them for new code. + + -- Function: gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t ALGORITHM, + const char **NAME) + Stores the textual representation of the algorithm whose id is + given in ALGORITHM in NAME. Deprecated; use `gcry_pk_algo_name'. + + -- Function: gcry_error_t gcry_ac_name_to_id (const char *NAME, + gcry_ac_id_t *ALGORITHM) + Stores the numeric ID of the algorithm whose textual + representation is contained in NAME in ALGORITHM. Deprecated; use + `gcry_pk_map_name'. + + +File: gcrypt.info, Node: Hashing, Next: Random Numbers, Prev: Public Key cryptography, Up: Top + +7 Hashing +********* + +Libgcrypt provides an easy and consistent to use interface for hashing. +Hashing is buffered and several hash algorithms can be updated at once. +It is possible to compute a MAC using the same routines. The +programming model follows an open/process/close paradigm and is in that +similar to other building blocks provided by Libgcrypt. + + For convenience reasons, a few cyclic redundancy check value +operations are also supported. + +* Menu: + +* Available hash algorithms:: List of hash algorithms supported by the library. +* Hash algorithm modules:: How to work with hash algorithm modules. +* Working with hash algorithms:: List of functions related to hashing. + + +File: gcrypt.info, Node: Available hash algorithms, Next: Hash algorithm modules, Up: Hashing + +7.1 Available hash algorithms +============================= + +`GCRY_MD_NONE' + This is not a real algorithm but used by some functions as an error + return value. This constant is guaranteed to have the value `0'. + +`GCRY_MD_SHA1' + This is the SHA-1 algorithm which yields a message digest of 20 + bytes. + +`GCRY_MD_RMD160' + This is the 160 bit version of the RIPE message digest + (RIPE-MD-160). Like SHA-1 it also yields a digest of 20 bytes. + +`GCRY_MD_MD5' + This is the well known MD5 algorithm, which yields a message + digest of 16 bytes. + +`GCRY_MD_MD4' + This is the MD4 algorithm, which yields a message digest of 16 + bytes. + +`GCRY_MD_MD2' + This is an reserved identifier for MD-2; there is no + implementation yet. + +`GCRY_MD_TIGER' + This is the TIGER/192 algorithm which yields a message digest of + 24 bytes. + +`GCRY_MD_HAVAL' + This is an reserved for the HAVAL algorithm with 5 passes and 160 + bit. It yields a message digest of 20 bytes. Note that there is no + implementation yet available. + +`GCRY_MD_SHA224' + This is the SHA-224 algorithm which yields a message digest of 28 + bytes. See Change Notice 1 for FIPS 180-2 for the specification. + +`GCRY_MD_SHA256' + This is the SHA-256 algorithm which yields a message digest of 32 + bytes. See FIPS 180-2 for the specification. + +`GCRY_MD_SHA384' + This is the SHA-384 algorithm which yields a message digest of 48 + bytes. See FIPS 180-2 for the specification. + +`GCRY_MD_SHA512' + This is the SHA-384 algorithm which yields a message digest of 64 + bytes. See FIPS 180-2 for the specification. + +`GCRY_MD_CRC32' + This is the ISO 3309 and ITU-T V.42 cyclic redundancy check. It + yields an output of 4 bytes. + +`GCRY_MD_CRC32_RFC1510' + This is the above cyclic redundancy check function, as modified by + RFC 1510. It yields an output of 4 bytes. + +`GCRY_MD_CRC24_RFC2440' + This is the OpenPGP cyclic redundancy check function. It yields an + output of 3 bytes. + +`GCRY_MD_WHIRLPOOL' + This is the Whirlpool algorithm which yields a message digest of 64 + bytes. + + + +File: gcrypt.info, Node: Hash algorithm modules, Next: Working with hash algorithms, Prev: Available hash algorithms, Up: Hashing + +7.2 Hash algorithm modules +========================== + +Libgcrypt makes it possible to load additional `message digest +modules'; these digests can be used just like the message digest +algorithms that are built into the library directly. For an +introduction into extension modules, see *Note Modules::. + + -- Data type: gcry_md_spec_t + This is the `module specification structure' needed for registering + message digest modules, which has to be filled in by the user + before it can be used to register a module. It contains the + following members: + + `const char *name' + The primary name of this algorithm. + + `unsigned char *asnoid' + Array of bytes that form the ASN OID. + + `int asnlen' + Length of bytes in `asnoid'. + + `gcry_md_oid_spec_t *oids' + A list of OIDs that are to be associated with the algorithm. + The list's last element must have it's `oid' member set to + NULL. See below for an explanation of this type. See below + for an explanation of this type. + + `int mdlen' + Length of the message digest algorithm. See below for an + explanation of this type. + + `gcry_md_init_t init' + The function responsible for initializing a handle. See + below for an explanation of this type. + + `gcry_md_write_t write' + The function responsible for writing data into a message + digest context. See below for an explanation of this type. + + `gcry_md_final_t final' + The function responsible for `finalizing' a message digest + context. See below for an explanation of this type. + + `gcry_md_read_t read' + The function responsible for reading out a message digest + result. See below for an explanation of this type. + + `size_t contextsize' + The size of the algorithm-specific `context', that should be + allocated for each handle. + + -- Data type: gcry_md_oid_spec_t + This type is used for associating a user-provided algorithm + implementation with certain OIDs. It contains the following + members: + + `const char *oidstring' + Textual representation of the OID. + + -- Data type: gcry_md_init_t + Type for the `init' function, defined as: void (*gcry_md_init_t) + (void *c) + + -- Data type: gcry_md_write_t + Type for the `write' function, defined as: void (*gcry_md_write_t) + (void *c, unsigned char *buf, size_t nbytes) + + -- Data type: gcry_md_final_t + Type for the `final' function, defined as: void (*gcry_md_final_t) + (void *c) + + -- Data type: gcry_md_read_t + Type for the `read' function, defined as: unsigned char + *(*gcry_md_read_t) (void *c) + + -- Function: gcry_error_t gcry_md_register (gcry_md_spec_t *DIGEST, + unsigned int *algorithm_id, gcry_module_t *MODULE) + Register a new digest module whose specification can be found in + DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representing this module is stored in MODULE. + + -- Function: void gcry_md_unregister (gcry_module_t MODULE) + Unregister the digest identified by MODULE, which must have been + registered with gcry_md_register. + + -- Function: gcry_error_t gcry_md_list (int *LIST, int *LIST_LENGTH) + Get a list consisting of the IDs of the loaded message digest + modules. If LIST is zero, write the number of loaded message + digest modules to LIST_LENGTH and return. If LIST is non-zero, + the first *LIST_LENGTH algorithm IDs are stored in LIST, which + must be of according size. In case there are less message digests + modules than *LIST_LENGTH, *LIST_LENGTH is updated to the correct + number. + + +File: gcrypt.info, Node: Working with hash algorithms, Prev: Hash algorithm modules, Up: Hashing + +7.3 Working with hash algorithms +================================ + +To use most of these function it is necessary to create a context; this +is done using: + + -- Function: gcry_error_t gcry_md_open (gcry_md_hd_t *HD, int ALGO, + unsigned int FLAGS) + Create a message digest object for algorithm ALGO. FLAGS may be + given as an bitwise OR of constants described below. ALGO may be + given as `0' if the algorithms to use are later set using + `gcry_md_enable'. HD is guaranteed to either receive a valid + handle or NULL. + + For a list of supported algorithms, see *Note Available hash + algorithms::. + + The flags allowed for MODE are: + + `GCRY_MD_FLAG_SECURE' + Allocate all buffers and the resulting digest in "secure + memory". Use this is the hashed data is highly confidential. + + `GCRY_MD_FLAG_HMAC' + Turn the algorithm into a HMAC message authentication + algorithm. This only works if just one algorithm is enabled + for the handle. Note that the function `gcry_md_setkey' must + be used to set the MAC key. The size of the MAC is equal to + the message digest of the underlying hash algorithm. If you + want CBC message authentication codes based on a cipher, see + *Note Working with cipher handles::. + + + You may use the function `gcry_md_is_enabled' to later check + whether an algorithm has been enabled. + + + If you want to calculate several hash algorithms at the same time, +you have to use the following function right after the `gcry_md_open': + + -- Function: gcry_error_t gcry_md_enable (gcry_md_hd_t H, int ALGO) + Add the message digest algorithm ALGO to the digest object + described by handle H. Duplicated enabling of algorithms is + detected and ignored. + + If the flag `GCRY_MD_FLAG_HMAC' was used, the key for the MAC must +be set using the function: + + -- Function: gcry_error_t gcry_md_setkey (gcry_md_hd_t H, const void + *KEY, size_t KEYLEN) + For use with the HMAC feature, set the MAC key to the value of KEY + of length KEYLEN. There is no restriction on the length of the + key. + + After you are done with the hash calculation, you should release the +resources by using: + + -- Function: void gcry_md_close (gcry_md_hd_t H) + Release all resources of hash context H. H should not be used + after a call to this function. A `NULL' passed as H is ignored. + + + Often you have to do several hash operations using the same +algorithm. To avoid the overhead of creating and releasing context, a +reset function is provided: + + -- Function: void gcry_md_reset (gcry_md_hd_t H) + Reset the current context to its initial state. This is + effectively identical to a close followed by an open and enabling + all currently active algorithms. + + Often it is necessary to start hashing some data and then continue to +hash different data. To avoid hashing the same data several times +(which might not even be possible if the data is received from a pipe), +a snapshot of the current hash context can be taken and turned into a +new context: + + -- Function: gcry_error_t gcry_md_copy (gcry_md_hd_t *HANDLE_DST, + gcry_md_hd_t HANDLE_SRC) + Create a new digest object as an exact copy of the object + described by handle HANDLE_SRC and store it in HANDLE_DST. The + context is not reset and you can continue to hash data using this + context and independently using the original context. + + Now that we have prepared everything to calculate hashes, it is time +to see how it is actually done. There are two ways for this, one to +update the hash with a block of memory and one macro to update the hash +by just one character. Both methods can be used on the same hash +context. + + -- Function: void gcry_md_write (gcry_md_hd_t H, const void *BUFFER, + size_t LENGTH) + Pass LENGTH bytes of the data in BUFFER to the digest object with + handle H to update the digest values. This function should be used + for large blocks of data. + + -- Function: void gcry_md_putc (gcry_md_hd_t H, int C) + Pass the byte in C to the digest object with handle H to update + the digest value. This is an efficient function, implemented as a + macro to buffer the data before an actual update. + + The semantics of the hash functions do not provide for reading out +intermediate message digests because the calculation must be finalized +first. This finalization may for example include the number of bytes +hashed in the message digest or some padding. + + -- Function: void gcry_md_final (gcry_md_hd_t H) + Finalize the message digest calculation. This is not really needed + because `gcry_md_read' does this implicitly. After this has been + done no further updates (by means of `gcry_md_write' or + `gcry_md_putc' are allowed. Only the first call to this function + has an effect. It is implemented as a macro. + + The way to read out the calculated message digest is by using the +function: + + -- Function: unsigned char * gcry_md_read (gcry_md_hd_t H, int ALGO) + `gcry_md_read' returns the message digest after finalizing the + calculation. This function may be used as often as required but + it will always return the same value for one handle. The returned + message digest is allocated within the message context and + therefore valid until the handle is released or reseted (using + `gcry_md_close' or `gcry_md_reset'. ALGO may be given as 0 to + return the only enabled message digest or it may specify one of + the enabled algorithms. The function does return `NULL' if the + requested algorithm has not been enabled. + + Because it is often necessary to get the message digest of one block +of memory, a fast convenience function is available for this task: + + -- Function: void gcry_md_hash_buffer (int ALGO, void *DIGEST, const + void *BUFFER, size_t LENGTH); + `gcry_md_hash_buffer' is a shortcut function to calculate a message + digest of a buffer. This function does not require a context and + immediately returns the message digest of the LENGTH bytes at + BUFFER. DIGEST must be allocated by the caller, large enough to + hold the message digest yielded by the the specified algorithm + ALGO. This required size may be obtained by using the function + `gcry_md_get_algo_dlen'. + + Note that this function will abort the process if an unavailable + algorithm is used. + + Hash algorithms are identified by internal algorithm numbers (see +`gcry_md_open' for a list). However, in most applications they are +used by names, so two functions are available to map between string +representations and hash algorithm identifiers. + + -- Function: const char * gcry_md_algo_name (int ALGO) + Map the digest algorithm id ALGO to a string representation of the + algorithm name. For unknown algorithms this function returns the + string `"?"'. This function should not be used to test for the + availability of an algorithm. + + -- Function: int gcry_md_map_name (const char *NAME) + Map the algorithm with NAME to a digest algorithm identifier. + Returns 0 if the algorithm name is not known. Names representing + ASN.1 object identifiers are recognized if the IETF dotted format + is used and the OID is prefixed with either "`oid.'" or "`OID.'". + For a list of supported OIDs, see the source code at + `cipher/md.c'. This function should not be used to test for the + availability of an algorithm. + + -- Function: gcry_error_t gcry_md_get_asnoid (int ALGO, void *BUFFER, + size_t *LENGTH) + Return an DER encoded ASN.1 OID for the algorithm ALGO in the user + allocated BUFFER. LENGTH must point to variable with the available + size of BUFFER and receives after return the actual size of the + returned OID. The returned error code may be `GPG_ERR_TOO_SHORT' + if the provided buffer is to short to receive the OID; it is + possible to call the function with `NULL' for BUFFER to have it + only return the required size. The function returns 0 on success. + + + To test whether an algorithm is actually available for use, the +following macro should be used: + + -- Function: gcry_error_t gcry_md_test_algo (int ALGO) + The macro returns 0 if the algorithm ALGO is available for use. + + If the length of a message digest is not known, it can be retrieved +using the following function: + + -- Function: unsigned int gcry_md_get_algo_dlen (int ALGO) + Retrieve the length in bytes of the digest yielded by algorithm + ALGO. This is often used prior to `gcry_md_read' to allocate + sufficient memory for the digest. + + In some situations it might be hard to remember the algorithm used +for the ongoing hashing. The following function might be used to get +that information: + + -- Function: int gcry_md_get_algo (gcry_md_hd_t H) + Retrieve the algorithm used with the handle H. Note that this + does not work reliable if more than one algorithm is enabled in H. + + The following macro might also be useful: + + -- Function: int gcry_md_is_secure (gcry_md_hd_t H) + This function returns true when the digest object H is allocated + in "secure memory"; i.e. H was created with the + `GCRY_MD_FLAG_SECURE'. + + -- Function: int gcry_md_is_enabled (gcry_md_hd_t H, int ALGO) + This function returns true when the algorithm ALGO has been + enabled for the digest object H. + + Tracking bugs related to hashing is often a cumbersome task which +requires to add a lot of printf statements into the code. Libgcrypt +provides an easy way to avoid this. The actual data hashed can be +written to files on request. + + -- Function: void gcry_md_debug (gcry_md_hd_t H, const char *SUFFIX) + Enable debugging for the digest object with handle H. This + creates create files named `dbgmd-.' while doing the + actual hashing. SUFFIX is the string part in the filename. The + number is a counter incremented for each new hashing. The data in + the file is the raw data as passed to `gcry_md_write' or + `gcry_md_putc'. If `NULL' is used for SUFFIX, the debugging is + stopped and the file closed. This is only rarely required because + `gcry_md_close' implicitly stops debugging. + + The following two deprecated macros are used for debugging by old +code. They shopuld be replaced by `gcry_md_debug'. + + -- Function: void gcry_md_start_debug (gcry_md_hd_t H, const char + *SUFFIX) + Enable debugging for the digest object with handle H. This + creates create files named `dbgmd-.' while doing the + actual hashing. SUFFIX is the string part in the filename. The + number is a counter incremented for each new hashing. The data in + the file is the raw data as passed to `gcry_md_write' or + `gcry_md_putc'. + + -- Function: void gcry_md_stop_debug (gcry_md_hd_t H, int RESERVED) + Stop debugging on handle H. RESERVED should be specified as 0. + This function is usually not required because `gcry_md_close' does + implicitly stop debugging. + + +File: gcrypt.info, Node: Random Numbers, Next: S-expressions, Prev: Hashing, Up: Top + +8 Random Numbers +**************** + +* Menu: + +* Quality of random numbers:: Libgcrypt uses different quality levels. +* Retrieving random numbers:: How to retrieve random numbers. + + +File: gcrypt.info, Node: Quality of random numbers, Next: Retrieving random numbers, Up: Random Numbers + +8.1 Quality of random numbers +============================= + +Libgcypt offers random numbers of different quality levels: + + -- Data type: gcry_random_level_t + The constants for the random quality levels are of this enum type. + +`GCRY_WEAK_RANDOM' + For all functions, except for `gcry_mpi_randomize', this level maps + to GCRY_STRONG_RANDOM. If you do not want this, consider using + `gcry_create_nonce'. + +`GCRY_STRONG_RANDOM' + Use this level for session keys and similar purposes. + +`GCRY_VERY_STRONG_RANDOM' + Use this level for long term key material. + + +File: gcrypt.info, Node: Retrieving random numbers, Prev: Quality of random numbers, Up: Random Numbers + +8.2 Retrieving random numbers +============================= + + -- Function: void gcry_randomize (unsigned char *BUFFER, size_t + LENGTH, enum gcry_random_level LEVEL) + Fill BUFFER with LENGTH random bytes using a random quality as + defined by LEVEL. + + -- Function: void * gcry_random_bytes (size_t NBYTES, enum + gcry_random_level LEVEL) + Convenience function to allocate a memory block consisting of + NBYTES fresh random bytes using a random quality as defined by + LEVEL. + + -- Function: void * gcry_random_bytes_secure (size_t NBYTES, enum + gcry_random_level LEVEL) + Convenience function to allocate a memory block consisting of + NBYTES fresh random bytes using a random quality as defined by + LEVEL. This function differs from `gcry_random_bytes' in that the + returned buffer is allocated in a "secure" area of the memory. + + -- Function: void gcry_create_nonce (unsigned char *BUFFER, size_t + LENGTH) + Fill BUFFER with LENGTH unpredictable bytes. This is commonly + called a nonce and may also be used for initialization vectors and + padding. This is an extra function nearly independent of the + other random function for 3 reasons: It better protects the + regular random generator's internal state, provides better + performance and does not drain the precious entropy pool. + + + +File: gcrypt.info, Node: S-expressions, Next: MPI library, Prev: Random Numbers, Up: Top + +9 S-expressions +*************** + +S-expressions are used by the public key functions to pass complex data +structures around. These LISP like objects are used by some +cryptographic protocols (cf. RFC-2692) and Libgcrypt provides functions +to parse and construct them. For detailed information, see `Ron +Rivest, code and description of S-expressions, +`http://theory.lcs.mit.edu/~rivest/sexp.html''. + +* Menu: + +* Data types for S-expressions:: Data types related with S-expressions. +* Working with S-expressions:: How to work with S-expressions. + + +File: gcrypt.info, Node: Data types for S-expressions, Next: Working with S-expressions, Up: S-expressions + +9.1 Data types for S-expressions +================================ + + -- Data type: gcry_sexp_t + The `gcry_sexp_t' type describes an object with the Libgcrypt + internal representation of an S-expression. + + +File: gcrypt.info, Node: Working with S-expressions, Prev: Data types for S-expressions, Up: S-expressions + +9.2 Working with S-expressions +============================== + +There are several functions to create an Libgcrypt S-expression object +from its external representation or from a string template. There is +also a function to convert the internal representation back into one of +the external formats: + + -- Function: gcry_error_t gcry_sexp_new (gcry_sexp_t *R_SEXP, + const void *BUFFER, size_t LENGTH, int AUTODETECT) + This is the generic function to create an new S-expression object + from its external representation in BUFFER of LENGTH bytes. On + success the result is stored at the address given by R_SEXP. With + AUTODETECT set to 0, the data in BUFFER is expected to be in + canonized format, with AUTODETECT set to 1 the parses any of the + defined external formats. If BUFFER does not hold a valid + S-expression an error code is returned and R_SEXP set to `NULL'. + Note that the caller is responsible for releasing the newly + allocated S-expression using `gcry_sexp_release'. + + -- Function: gcry_error_t gcry_sexp_create (gcry_sexp_t *R_SEXP, + void *BUFFER, size_t LENGTH, int AUTODETECT, + void (*FREEFNC)(void*)) + This function is identical to `gcry_sexp_new' but has an extra + argument FREEFNC, which, when not set to `NULL', is expected to be + a function to release the BUFFER; most likely the standard `free' + function is used for this argument. This has the effect of + transferring the ownership of BUFFER to the created object in + R_SEXP. The advantage of using this function is that Libgcrypt + might decide to directly use the provided buffer and thus avoid + extra copying. + + -- Function: gcry_error_t gcry_sexp_sscan (gcry_sexp_t *R_SEXP, + size_t *ERROFF, const char *BUFFER, size_t LENGTH) + This is another variant of the above functions. It behaves nearly + identical but provides an ERROFF argument which will receive the + offset into the buffer where the parsing stopped on error. + + -- Function: gcry_error_t gcry_sexp_build (gcry_sexp_t *R_SEXP, + size_t *ERROFF, const char *FORMAT, ...) + This function creates an internal S-expression from the string + template FORMAT and stores it at the address of R_SEXP. If there + is a parsing error, the function returns an appropriate error code + and stores the offset into FORMAT where the parsing stopped in + ERROFF. The function supports a couple of printf-like formatting + characters and expects arguments for some of these escape + sequences right after FORMAT. The following format characters are + defined: + + `%m' + The next argument is expected to be of type `gcry_mpi_t' and + a copy of its value is inserted into the resulting + S-expression. + + `%s' + The next argument is expected to be of type `char *' and that + string is inserted into the resulting S-expression. + + `%d' + The next argument is expected to be of type `int' and its + value is inserted into the resulting S-expression. + + `%b' + The next argument is expected to be of type `int' directly + followed by an argument of type `char *'. This represents a + buffer of given length to be inserted into the resulting + regular expression. + + No other format characters are defined and would return an error. + Note that the format character `%%' does not exists, because a + percent sign is not a valid character in an S-expression. + + -- Function: void gcry_sexp_release (gcry_sexp_t SEXP) + Release the S-expression object SEXP. + +The next 2 functions are used to convert the internal representation +back into a regular external S-expression format and to show the +structure for debugging. + + -- Function: size_t gcry_sexp_sprint (gcry_sexp_t SEXP, int MODE, + char *BUFFER, size_t MAXLENGTH) + Copies the S-expression object SEXP into BUFFER using the format + specified in MODE. MAXLENGTH must be set to the allocated length + of BUFFER. The function returns the actual length of valid bytes + put into BUFFER or 0 if the provided buffer is too short. Passing + `NULL' for BUFFER returns the required length for BUFFER. For + convenience reasons an extra byte with value 0 is appended to the + buffer. + + The following formats are supported: + + `GCRYSEXP_FMT_DEFAULT' + Returns a convenient external S-expression representation. + + `GCRYSEXP_FMT_CANON' + Return the S-expression in canonical format. + + `GCRYSEXP_FMT_BASE64' + Not currently supported. + + `GCRYSEXP_FMT_ADVANCED' + Returns the S-expression in advanced format. + + -- Function: void gcry_sexp_dump (gcry_sexp_t SEXP) + Dumps SEXP in a format suitable for debugging to Libgcrypt's + logging stream. + +Often canonical encoding is used in the external representation. The +following function can be used to check for valid encoding and to learn +the length of the S-expression" + + -- Function: size_t gcry_sexp_canon_len (const unsigned char *BUFFER, + size_t LENGTH, size_t *ERROFF, int *ERRCODE) + Scan the canonical encoded BUFFER with implicit length values and + return the actual length this S-expression uses. For a valid + S-expression it should never return 0. If LENGTH is not 0, the + maximum length to scan is given; this can be used for syntax + checks of data passed from outside. ERRCODE and ERROFF may both be + passed as `NULL'. + + +There are a couple of functions to parse S-expressions and retrieve +elements: + + -- Function: gcry_sexp_t gcry_sexp_find_token (const gcry_sexp_t LIST, + const char *TOKEN, size_t TOKLEN) + Scan the S-expression for a sublist with a type (the car of the + list) matching the string TOKEN. If TOKLEN is not 0, the token is + assumed to be raw memory of this length. The function returns a + newly allocated S-expression consisting of the found sublist or + `NULL' when not found. + + -- Function: int gcry_sexp_length (const gcry_sexp_t LIST) + Return the length of the LIST. For a valid S-expression this + should be at least 1. + + -- Function: gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t LIST, + int NUMBER) + Create and return a new S-expression from the element with index + NUMBER in LIST. Note that the first element has the index 0. If + there is no such element, `NULL' is returned. + + -- Function: gcry_sexp_t gcry_sexp_car (const gcry_sexp_t LIST) + Create and return a new S-expression from the first element in + LIST; this called the "type" and should always exist and be a + string. `NULL' is returned in case of a problem. + + -- Function: gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t LIST) + Create and return a new list form all elements except for the + first one. Note that this function may return an invalid + S-expression because it is not guaranteed, that the type exists + and is a string. However, for parsing a complex S-expression it + might be useful for intermediate lists. Returns `NULL' on error. + + -- Function: const char * gcry_sexp_nth_data (const gcry_sexp_t LIST, + int NUMBER, size_t *DATALEN) + This function is used to get data from a LIST. A pointer to the + actual data with index NUMBER is returned and the length of this + data will be stored to DATALEN. If there is no data at the given + index or the index represents another list, `NULL' is returned. + *Caution:* The returned pointer is valid as long as LIST is not + modified or released. + + Here is an example on how to extract and print the surname (Meier) + from the S-expression `(Name Otto Meier (address Burgplatz 3))': + + size_t len; + const char *name; + + name = gcry_sexp_nth_data (list, 2, &len); + printf ("my name is %.*s\n", (int)len, name); + + -- Function: char * gcry_sexp_nth_string (gcry_sexp_t LIST, int NUMBER) + This function is used to get and convert data from a LIST. The + data is assumed to be a Nul terminated string. The caller must + release this returned value using `gcry_free'. If there is no + data at the given index, the index represents a list or the value + can't be converted to a string, `NULL' is returned. + + -- Function: gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t LIST, + int NUMBER, int MPIFMT) + This function is used to get and convert data from a LIST. This + data is assumed to be an MPI stored in the format described by + MPIFMT and returned as a standard Libgcrypt MPI. The caller must + release this returned value using `gcry_mpi_release'. If there is + no data at the given index, the index represents a list or the + value can't be converted to an MPI, `NULL' is returned. + + +File: gcrypt.info, Node: MPI library, Next: Prime numbers, Prev: S-expressions, Up: Top + +10 MPI library +************** + +* Menu: + +* Data types:: MPI related data types. +* Basic functions:: First steps with MPI numbers. +* MPI formats:: External representation of MPIs. +* Calculations:: Performing MPI calculations. +* Comparisons:: How to compare MPI values. +* Bit manipulations:: How to access single bits of MPI values. +* Miscellaneous:: Miscellaneous MPI functions. + + Public key cryptography is based on mathematics with large numbers. +To implement the public key functions, a library for handling these +large numbers is required. Because of the general usefulness of such a +library, its interface is exposed by Libgcrypt. In the context of +Libgcrypt and in most other applications, these large numbers are +called MPIs (multi-precision-integers). + + +File: gcrypt.info, Node: Data types, Next: Basic functions, Up: MPI library + +10.1 Data types +=============== + + -- Data type: gcry_mpi_t + This type represents an object to hold an MPI. + + +File: gcrypt.info, Node: Basic functions, Next: MPI formats, Prev: Data types, Up: MPI library + +10.2 Basic functions +==================== + +To work with MPIs, storage must be allocated and released for the +numbers. This can be done with one of these functions: + + -- Function: gcry_mpi_t gcry_mpi_new (unsigned int NBITS) + Allocate a new MPI object, initialize it to 0 and initially + allocate enough memory for a number of at least NBITS. This + pre-allocation is only a small performance issue and not actually + necessary because Libgcrypt automatically re-allocates the + required memory. + + -- Function: gcry_mpi_t gcry_mpi_snew (unsigned int NBITS) + This is identical to `gcry_mpi_new' but allocates the MPI in the so + called "secure memory" which in turn will take care that all + derived values will also be stored in this "secure memory". Use + this for highly confidential data like private key parameters. + + -- Function: gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t A) + Create a new MPI as the exact copy of A. + + -- Function: void gcry_mpi_release (gcry_mpi_t A) + Release the MPI A and free all associated resources. Passing + `NULL' is allowed and ignored. When a MPI stored in the "secure + memory" is released, that memory gets wiped out immediately. + +The simplest operations are used to assign a new value to an MPI: + + -- Function: gcry_mpi_t gcry_mpi_set (gcry_mpi_t W, const gcry_mpi_t U) + Assign the value of U to W and return W. If `NULL' is passed for + W, a new MPI is allocated, set to the value of U and returned. + + -- Function: gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t W, unsigned long U) + Assign the value of U to W and return W. If `NULL' is passed for + W, a new MPI is allocated, set to the value of U and returned. + This function takes an `unsigned int' as type for U and thus it is + only possible to set W to small values (usually up to the word + size of the CPU). + + -- Function: void gcry_mpi_swap (gcry_mpi_t A, gcry_mpi_t B) + Swap the values of A and B. + + +File: gcrypt.info, Node: MPI formats, Next: Calculations, Prev: Basic functions, Up: MPI library + +10.3 MPI formats +================ + +The following functions are used to convert between an external +representation of an MPI and the internal one of Libgcrypt. + + -- Function: gcry_error_t gcry_mpi_scan (gcry_mpi_t *R_MPI, + enum gcry_mpi_format FORMAT, const unsigned char *BUFFER, + size_t BUFLEN, size_t *NSCANNED) + Convert the external representation of an integer stored in BUFFER + with a length of BUFLEN into a newly created MPI returned which + will be stored at the address of R_MPI. For certain formats the + length argument is not required and should be passed as `0'. + After a successful operation the variable NSCANNED receives the + number of bytes actually scanned unless NSCANNED was given as + `NULL'. FORMAT describes the format of the MPI as stored in BUFFER: + + `GCRYMPI_FMT_STD' + 2-complement stored without a length header. + + `GCRYMPI_FMT_PGP' + As used by OpenPGP (only defined as unsigned). This is + basically `GCRYMPI_FMT_STD' with a 2 byte big endian length + header. + + `GCRYMPI_FMT_SSH' + As used in the Secure Shell protocol. This is + `GCRYMPI_FMT_STD' with a 4 byte big endian header. + + `GCRYMPI_FMT_HEX' + Stored as a C style string with each byte of the MPI encoded + as 2 hex digits. When using this format, BUFLEN must be zero. + + `GCRYMPI_FMT_USG' + Simple unsigned integer. + + Note that all of the above formats store the integer in big-endian + format (MSB first). + + -- Function: gcry_error_t gcry_mpi_print (enum gcry_mpi_format FORMAT, + unsigned char *BUFFER, size_t BUFLEN, size_t *NWRITTEN, + const gcry_mpi_t A) + Convert the MPI A into an external representation described by + FORMAT (see above) and store it in the provided BUFFER which has a + usable length of at least the BUFLEN bytes. If NWRITTEN is not + NULL, it will receive the number of bytes actually stored in + BUFFER after a successful operation. + + -- Function: gcry_error_t gcry_mpi_aprint + (enum gcry_mpi_format FORMAT, unsigned char **BUFFER, + size_t *NBYTES, const gcry_mpi_t A) + Convert the MPI A into an external representation described by + FORMAT (see above) and store it in a newly allocated buffer which + address will be stored in the variable BUFFER points to. The + number of bytes stored in this buffer will be stored in the + variable NBYTES points to, unless NBYTES is `NULL'. + + -- Function: void gcry_mpi_dump (const gcry_mpi_t A) + Dump the value of A in a format suitable for debugging to + Libgcrypt's logging stream. Note that one leading space but no + trailing space or linefeed will be printed. It is okay to pass + `NULL' for A. + + +File: gcrypt.info, Node: Calculations, Next: Comparisons, Prev: MPI formats, Up: MPI library + +10.4 Calculations +================= + +Basic arithmetic operations: + + -- Function: void gcry_mpi_add (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V) + W = U + V. + + -- Function: void gcry_mpi_add_ui (gcry_mpi_t W, gcry_mpi_t U, + unsigned long V) + W = U + V. Note that V is an unsigned integer. + + -- Function: void gcry_mpi_addm (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V, gcry_mpi_t M) + W = U + V \bmod M. + + -- Function: void gcry_mpi_sub (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V) + W = U - V. + + -- Function: void gcry_mpi_sub_ui (gcry_mpi_t W, gcry_mpi_t U, + unsigned long V) + W = U - V. V is an unsigned integer. + + -- Function: void gcry_mpi_subm (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V, gcry_mpi_t M) + W = U - V \bmod M. + + -- Function: void gcry_mpi_mul (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V) + W = U * V. + + -- Function: void gcry_mpi_mul_ui (gcry_mpi_t W, gcry_mpi_t U, + unsigned long V) + W = U * V. V is an unsigned integer. + + -- Function: void gcry_mpi_mulm (gcry_mpi_t W, gcry_mpi_t U, + gcry_mpi_t V, gcry_mpi_t M) + W = U * V \bmod M. + + -- Function: void gcry_mpi_mul_2exp (gcry_mpi_t W, gcry_mpi_t U, + unsigned long E) + W = U * 2^e. + + -- Function: void gcry_mpi_div (gcry_mpi_t Q, gcry_mpi_t R, + gcry_mpi_t DIVIDEND, gcry_mpi_t DIVISOR, int ROUND) + Q = DIVIDEND / DIVISOR, R = DIVIDEND \bmod DIVISOR. Q and R may + be passed as `NULL'. ROUND should be negative or 0. + + -- Function: void gcry_mpi_mod (gcry_mpi_t R, gcry_mpi_t DIVIDEND, + gcry_mpi_t DIVISOR) + R = DIVIDEND \bmod DIVISOR. + + -- Function: void gcry_mpi_powm (gcry_mpi_t W, const gcry_mpi_t B, + const gcry_mpi_t E, const gcry_mpi_t M) + W = B^e \bmod M. + + -- Function: int gcry_mpi_gcd (gcry_mpi_t G, gcry_mpi_t A, + gcry_mpi_t B) + Set G to the greatest common divisor of A and B. Return true if + the G is 1. + + -- Function: int gcry_mpi_invm (gcry_mpi_t X, gcry_mpi_t A, + gcry_mpi_t M) + Set X to the multiplicative inverse of A \bmod M. Return true if + the inverse exists. + + +File: gcrypt.info, Node: Comparisons, Next: Bit manipulations, Prev: Calculations, Up: MPI library + +10.5 Comparisons +================ + +The next 2 functions are used to compare MPIs: + + -- Function: int gcry_mpi_cmp (const gcry_mpi_t U, const gcry_mpi_t V) + Compare the multi-precision-integers number U and V returning 0 + for equality, a positive value for U > V and a negative for U < V. + + -- Function: int gcry_mpi_cmp_ui (const gcry_mpi_t U, unsigned long V) + Compare the multi-precision-integers number U with the unsigned + integer V returning 0 for equality, a positive value for U > V and + a negative for U < V. + + +File: gcrypt.info, Node: Bit manipulations, Next: Miscellaneous, Prev: Comparisons, Up: MPI library + +10.6 Bit manipulations +====================== + +There are a couple of functions to get information on arbitrary bits in +an MPI and to set or clear them: + + -- Function: unsigned int gcry_mpi_get_nbits (gcry_mpi_t A) + Return the number of bits required to represent A. + + -- Function: int gcry_mpi_test_bit (gcry_mpi_t A, unsigned int N) + Return true if bit number N (counting from 0) is set in A. + + -- Function: void gcry_mpi_set_bit (gcry_mpi_t A, unsigned int N) + Set bit number N in A. + + -- Function: void gcry_mpi_clear_bit (gcry_mpi_t A, unsigned int N) + Clear bit number N in A. + + -- Function: void gcry_mpi_set_highbit (gcry_mpi_t A, unsigned int N) + Set bit number N in A and clear all bits greater than N. + + -- Function: void gcry_mpi_clear_highbit (gcry_mpi_t A, unsigned int N) + Clear bit number N in A and all bits greater than N. + + -- Function: void gcry_mpi_rshift (gcry_mpi_t X, gcry_mpi_t A, + unsigned int N) + Shift the value of A by N bits to the right and store the result + in X. + + -- Function: void gcry_mpi_lshift (gcry_mpi_t X, gcry_mpi_t A, + unsigned int N) + Shift the value of A by N bits to the left and store the result in + X. + + +File: gcrypt.info, Node: Miscellaneous, Prev: Bit manipulations, Up: MPI library + +10.7 Miscellaneous +================== + + -- Function: gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t A, void *P, + unsigned int NBITS) + Store NBITS of the value P points to in A and mark A as an opaque + value (i.e. an value that can't be used for any math calculation + and is only used to store an arbitrary bit pattern in A). + + WARNING: Never use an opaque MPI for actual math operations. The + only valid functions are gcry_mpi_get_opaque and gcry_mpi_release. + Use gcry_mpi_scan to convert a string of arbitrary bytes into an + MPI. + + + -- Function: void * gcry_mpi_get_opaque (gcry_mpi_t A, + unsigned int *NBITS) + Return a pointer to an opaque value stored in A and return its + size in NBITS. Note that the returned pointer is still owned by A + and that the function should never be used for an non-opaque MPI. + + -- Function: void gcry_mpi_set_flag (gcry_mpi_t A, + enum gcry_mpi_flag FLAG) + Set the FLAG for the MPI A. Currently only the flag + `GCRYMPI_FLAG_SECURE' is allowed to convert A into an MPI stored + in "secure memory". + + -- Function: void gcry_mpi_clear_flag (gcry_mpi_t A, + enum gcry_mpi_flag FLAG) + Clear FLAG for the multi-precision-integers A. Note that this + function is currently useless as no flags are allowed. + + -- Function: int gcry_mpi_get_flag (gcry_mpi_t A, + enum gcry_mpi_flag FLAG) + Return true when the FLAG is set for A. + + -- Function: void gcry_mpi_randomize (gcry_mpi_t W, + unsigned int NBITS, enum gcry_random_level LEVEL) + Set the multi-precision-integers W to a random value of NBITS, + using random data quality of level LEVEL. In case NBITS is not a + multiple of a byte, NBITS is rounded up to the next byte boundary. + When using a LEVEL of `GCRY_WEAK_RANDOM' this function makes use of + `gcry_create_nonce'. + + +File: gcrypt.info, Node: Prime numbers, Next: Utilities, Prev: MPI library, Up: Top + +11 Prime numbers +**************** + +* Menu: + +* Generation:: Generation of new prime numbers. +* Checking:: Checking if a given number is prime. + + +File: gcrypt.info, Node: Generation, Next: Checking, Up: Prime numbers + +11.1 Generation +=============== + + -- Function: gcry_error_t gcry_prime_generate (gcry_mpi_t + *PRIME,unsigned int PRIME_BITS, unsigned int FACTOR_BITS, + gcry_mpi_t **FACTORS, gcry_prime_check_func_t CB_FUNC, void + *CB_ARG, gcry_random_level_t RANDOM_LEVEL, unsigned int FLAGS) + Generate a new prime number of PRIME_BITS bits and store it in + PRIME. If FACTOR_BITS is non-zero, one of the prime factors of + (PRIME - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is + non-zero, allocate a new, `NULL'-terminated array holding the + prime factors and store it in FACTORS. FLAGS might be used to + influence the prime number generation process. + + -- Function: gcry_error_t gcry_prime_group_generator (gcry_mpi_t *R_G, + gcry_mpi_t PRIME, gcry_mpi_t *FACTORS, gcry_mpi_t START_G) + Find a generator for PRIME where the factorization of (PRIME-1) is + in the `NULL' terminated array FACTORS. Return the generator as a + newly allocated MPI in R_G. If START_G is not NULL, use this as + the start for the search. + + -- Function: void gcry_prime_release_factors (gcry_mpi_t *FACTORS) + Convenience function to release the FACTORS array. + + +File: gcrypt.info, Node: Checking, Prev: Generation, Up: Prime numbers + +11.2 Checking +============= + + -- Function: gcry_error_t gcry_prime_check (gcry_mpi_t P, unsigned int + FLAGS) + Check wether the number P is prime. Returns zero in case P is + indeed a prime, returns `GPG_ERR_NO_PRIME' in case P is not a + prime and a different error code in case something went horribly + wrong. + + +File: gcrypt.info, Node: Utilities, Next: Architecture, Prev: Prime numbers, Up: Top + +12 Utilities +************ + +* Menu: + +* Memory allocation:: Functions related with memory allocation. + + +File: gcrypt.info, Node: Memory allocation, Up: Utilities + +12.1 Memory allocation +====================== + + -- Function: void * gcry_malloc (size_t N) + This function tries to allocate N bytes of memory. On success it + returns a pointer to the memory area, in an out-of-core condition, + it returns NULL. + + -- Function: void * gcry_malloc_secure (size_t N) + Like `gcry_malloc', but uses secure memory. + + -- Function: void * gcry_calloc (size_t N) + This function tries to allocate N bytes of cleared memory (i.e. + memory that is initialized with zero bytes). On success it + returns a pointer to the memory area, in an out-of-core condition, + it returns NULL. + + -- Function: void * gcry_calloc_secure (size_t N) + Like `gcry_calloc', but uses secure memory. + + -- Function: void * gcry_realloc (void *P, size_t N) + This function tries to resize the memory area pointed to by P to N + bytes. On success it returns a pointer to the new memory area, in + an out-of-core condition, it returns NULL. Depending on whether + the memory pointed to by P is secure memory or not, gcry_realloc + tries to use secure memory as well. + + -- Function: void gcry_free (void *P) + Release the memory area pointed to by P. + + +File: gcrypt.info, Node: Architecture, Next: Self-Tests, Prev: Utilities, Up: Top + +13 Architecture +*************** + +This chapter describes the internal architecture of Libgcrypt. + + Libgcrypt is a function library written in ISO C-90. Any compliant +compiler should be able to build Libgcrypt as long as the target is +either a POSIX platform or compatible to the API used by Windows NT. +Provisions have been take so that the library can be directly used from +C++ applications; however building with a C++ compiler is not supported. + + Building Libgcrypt is done by using the common `./configure && make' +approach. The configure command is included in the source distribution +and as a portable shell script it works on any Unix-alike system. The +result of running the configure script are a C header file +(`config.h'), customized Makefiles, the setup of symbolic links and a +few other things. After that the make tool builds and optionally +installs the library and the documentation. See the files `INSTALL' +and `README' in the source distribution on how to do this. + + Libgcrypt is developed using a Subversion(1) repository. Although +all released versions are tagged in this repository, they should not be +used to build production versions of Libgcrypt. Instead released +tarballs should be used. These tarballs are available from several +places with the master copy at . +Announcements of new releases are posted to the + mailing list(2). + + [image src="libgcrypt-modules.png" alt="Libgcrypt subsystems"] +Figure 13.1: Libgcrypt subsystems + + Libgcrypt consists of several subsystems (*note Figure 13.1: +fig:subsystems.) and all these subsystems provide a public API; this +includes the helper subsystems like the one for S-expressions. The API +style depends on the subsystem; in general an open-use-close approach +is implemented. The open returns a handle to a context used for all +further operations on this handle, several functions may then be used +on this handle and a final close function releases all resources +associated with the handle. + +* Menu: + +* Public-Key Subsystem Architecture:: About public keys. +* Symmetric Encryption Subsystem Architecture:: About standard ciphers. +* Hashing and MACing Subsystem Architecture:: About hashing. +* Multi-Precision-Integer Subsystem Architecture:: About big integers. +* Prime-Number-Generator Subsystem Architecture:: About prime numbers. +* Random-Number Subsystem Architecture:: About random stuff. + + ---------- Footnotes ---------- + + (1) A version control system available for many platforms + + (2) See `http://www.gnupg.org/documentation/mailing-lists.en.html' +for details. + + +File: gcrypt.info, Node: Public-Key Subsystem Architecture, Next: Symmetric Encryption Subsystem Architecture, Up: Architecture + +13.1 Public-Key Architecture +============================ + +Libgcrypt implements two interfaces for public key cryptography: The +standard interface is PK interface using functions in the `gcry_pk_' +name space. The AC interface in an alternative one which is now +deprecated and will not be further described. The AC interface is also +disabled in FIPS mode. + + Because public key cryptography is almost always used to process +small amounts of data (hash values or session keys), the interface is +not implemented using the open-use-close paradigm, but with single +self-contained functions. Due to the wide variety of parameters +required by different algorithms S-expressions, as flexible way to +convey these parameters, are used. There is a set of helper functions +to work with these S-expressions. + + Aside of functions to register new algorithms, map algorithms names +to algorithms identifiers and to lookup properties of a key, the +following main functions are available: + +`gcry_pk_encrypt' + Encrypt data using a public key. + +`gcry_pk_decrypt' + Decrypt data using a private key. + +`gcry_pk_sign' + Sign data using a private key. + +`gcry_pk_verify' + Verify that a signature matches the data. + +`gcry_pk_testkey' + Perform a consistency over a public or private key. + +`gcry_pk_genkey' + Create a new public/private key pair. + + + With the help of the module registration system all these functions +lookup the module implementing the algorithm and pass the actual work +to that module. The parsing of the S-expression input and the +construction of S-expression for the return values is done by the high +level code (`cipher/pubkey.c'). Thus the internal interface between +the algorithm modules and the high level functions passes data in a +custom format. The interface to the modules is published +(`gcrypt-modules.h') so that it can used to register external +implementations of algorithms with Libgcrypt. However, for some +algorithms this module interface is to limited and thus for the +internal modules an extra interface is sometimes used to convey more +information. + + By default Libgcrypt uses a blinding technique for RSA decryption to +mitigate real world timing attacks over a network: Instead of using the +RSA decryption directly, a blinded value y = x r^e \bmod n is decrypted +and the unblinded value x' = y' r^-1 \bmod n returned. The blinding +value r is a random value with the size of the modulus n and generated +with `GCRY_WEAK_RANDOM' random level. + + The algorithm used for RSA and DSA key generation depends on whether +Libgcrypt is operated in standard or in FIPS mode. In standard mode an +algorithm based on the Lim-Lee prime number generator is used. In FIPS +mode RSA keys are generated as specified in ANSI X9.31 (1998) and DSA +keys as specified in FIPS 186-2. + + +File: gcrypt.info, Node: Symmetric Encryption Subsystem Architecture, Next: Hashing and MACing Subsystem Architecture, Prev: Public-Key Subsystem Architecture, Up: Architecture + +13.2 Symmetric Encryption Subsystem Architecture +================================================ + +The interface to work with symmetric encryption algorithms is made up +of functions from the `gcry_cipher_' name space. The implementation +follows the open-use-close paradigm and uses registered algorithm +modules for the actual work. Unless a module implements optimized +cipher mode implementations, the high level code (`cipher/cipher.c') +implements the modes and calls the core algorithm functions to process +each block. + + The most important functions are: + +`gcry_cipher_open' + Create a new instance to encrypt or decrypt using a specified + algorithm and mode. + +`gcry_cipher_close' + Release an instance. + +`gcry_cipher_setkey' + Set a key to be used for encryption or decryption. + +`gcry_cipher_setiv' + Set an initialization vector to be used for encryption or + decryption. + +`gcry_cipher_encrypt' +`gcry_cipher_decrypt' + Encrypt or decrypt data. These functions may be called with + arbitrary amounts of data and as often as needed to encrypt or + decrypt all data. + + + There are also functions to query properties of algorithms or +context, like block length, key length, map names or to enable features +like padding methods. + + +File: gcrypt.info, Node: Hashing and MACing Subsystem Architecture, Next: Multi-Precision-Integer Subsystem Architecture, Prev: Symmetric Encryption Subsystem Architecture, Up: Architecture + +13.3 Hashing and MACing Subsystem Architecture +============================================== + +The interface to work with message digests and CRC algorithms is made +up of functions from the `gcry_md_' name space. The implementation +follows the open-use-close paradigm and uses registered algorithm +modules for the actual work. Although CRC algorithms are not +considered cryptographic hash algorithms, they share enough properties +so that it makes sense to handle them in the same way. It is possible +to use several algorithms at once with one context and thus compute +them all on the same data. + + The most important functions are: + +`gcry_md_open' + Create a new message digest instance and optionally enable one + algorithm. A flag may be used to turn the message digest algorithm + into a HMAC algorithm. + +`gcry_md_enable' + Enable an additional algorithm for the instance. + +`gcry_md_setkey' + Set the key for the MAC. + +`gcry_md_write' + Pass more data for computing the message digest to an instance. + +`gcry_md_putc' + Buffered version of `gcry_md_write' implemented as a macro. + +`gcry_md_read' + Finalize the computation of the message digest or HMAC and return + the result. + +`gcry_md_close' + Release an instance + +`gcry_md_hash_buffer' + Convenience function to directly compute a message digest over a + memory buffer without the need to create an instance first. + + + There are also functions to query properties of algorithms or the +instance, like enabled algorithms, digest length, map algorithm names. +it is also possible to reset an instance or to copy the current state +of an instance at any time. Debug functions to write the hashed data +to files are available as well. + + +File: gcrypt.info, Node: Multi-Precision-Integer Subsystem Architecture, Next: Prime-Number-Generator Subsystem Architecture, Prev: Hashing and MACing Subsystem Architecture, Up: Architecture + +13.4 Multi-Precision-Integer Subsystem Architecture +=================================================== + +The implementation of Libgcrypt's big integer computation code is based +on an old release of GNU Multi-Precision Library (GMP). The decision +not to use the GMP library directly was due to stalled development at +that time and due to security requirements which could not be provided +by the code in GMP. As GMP does, Libgcrypt provides high performance +assembler implementations of low level code for several CPUS to gain +much better performance than with a generic C implementation. + +Major features of Libgcrypt's multi-precision-integer code compared to +GMP are: + + * Avoidance of stack based allocations to allow protection against + swapping out of sensitive data and for easy zeroing of sensitive + intermediate results. + + * Optional use of secure memory and tracking of its use so that + results are also put into secure memory. + + * MPIs are identified by a handle (implemented as a pointer) to give + better control over allocations and to augment them with extra + properties like opaque data. + + * Removal of unnecessary code to reduce complexity. + + * Functions specialized for public key cryptography. + + + +File: gcrypt.info, Node: Prime-Number-Generator Subsystem Architecture, Next: Random-Number Subsystem Architecture, Prev: Multi-Precision-Integer Subsystem Architecture, Up: Architecture + +13.5 Prime-Number-Generator Subsystem Architecture +================================================== + +Libgcrypt provides an interface to its prime number generator. These +functions make use of the internal prime number generator which is +required for the generation for public key key pairs. The plain prime +checking function is exported as well. + + The generation of random prime numbers is based on the Lim and Lee +algorithm to create practically save primes.(1) This algorithm creates +a pool of smaller primes, select a few of them to create candidate +primes of the form 2 * p_0 * p_1 * ... * p_n + 1, tests the candidate +for primality and permutates the pool until a prime has been found. It +is possible to clamp one of the small primes to a certain size to help +DSA style algorithms. Because most of the small primes in the pool are +not used for the resulting prime number, they are saved for later use +(see `save_pool_prime' and `get_pool_prime' in `cipher/primegen.c'). +The prime generator optionally supports the finding of an appropriate +generator. + +The primality test works in three steps: + + 1. The standard sieve algorithm using the primes up to 4999 is used + as a quick first check. + + 2. A Fermat test filters out almost all non-primes. + + 3. A 5 round Rabin-Miller test is finally used. The first round uses + a witness of 2, whereas the next rounds use a random witness. + + + To support the generation of RSA and DSA keys in FIPS mode according +to X9.31 and FIPS 186-2, Libgcrypt implements two additional prime +generation functions: `_gcry_derive_x931_prime' and +`_gcry_generate_fips186_2_prime'. These functions are internal and not +available through the public API. + + ---------- Footnotes ---------- + + (1) Chae Hoon Lim and Pil Joong Lee. A key recovery attack on +discrete log-based shemes using a prime order subgroup. In Burton S. +Kaliski Jr., editor, Advances in Cryptology: Crypto '97, pages +249­-263, Berlin / Heidelberg / New York, 1997. Springer-Verlag. +Described on page 260. + + +File: gcrypt.info, Node: Random-Number Subsystem Architecture, Prev: Prime-Number-Generator Subsystem Architecture, Up: Architecture + +13.6 Random-Number Subsystem Architecture +========================================= + +Libgcrypt provides 3 levels or random quality: The level +`GCRY_VERY_STRONG_RANDOM' usually used for key generation, the level +`GCRY_STRONG_RANDOM' for all other strong random requirements and the +function `gcry_create_nonce' which is used for weaker usages like +nonces. There is also a level `GCRY_WEAK_RANDOM' which in general maps +to `GCRY_STRONG_RANDOM' except when used with the function +`gcry_mpi_randomize', where it randomizes an multi-precision-integer +using the `gcry_create_nonce' function. + +There are two distinct random generators available: + + * The Continuously Seeded Pseudo Random Number Generator (CSPRNG), + which is based on the classic GnuPG derived big pool + implementation. Implemented in `random/random-csprng.c' and used + by default. + + * A FIPS approved ANSI X9.31 PRNG using AES with a 128 bit key. + Implemented in `random/random-fips.c' and used if Libgcrypt is in + FIPS mode. + +Both generators make use of so-called entropy gathering modules: + +rndlinux + Uses the operating system provided `/dev/random' and + `/dev/urandom' devices. + +rndunix + Runs several operating system commands to collect entropy from + sources like virtual machine and process statistics. It is a kind + of poor-man's `/dev/random' implementation. It is not available in + FIPS mode. + +rndegd + Uses the operating system provided Entropy Gathering Daemon (EGD). + The EGD basically uses the same algorithms as rndunix does. + However as a system daemon it keeps on running and thus can serve + several processes requiring entropy input and does not waste + collected entropy if the application does not need all the + collected entropy. It is not available in FIPS mode. + +rndw32 + Targeted for the Microsoft Windows OS. It uses certain properties + of that system and is the only gathering module available for that + OS. + +rndhw + Extra module to collect additional entropy by utilizing a hardware + random number generator. As of now the only supported hardware + RNG is the Padlock engine of VIA (Centaur) CPUs. It is not + available in FIPS mode. + + +* Menu: + +* CSPRNG Description:: Description of the CSPRNG. +* FIPS PRNG Description:: Description of the FIPS X9.31 PRNG. + + +File: gcrypt.info, Node: CSPRNG Description, Next: FIPS PRNG Description, Up: Random-Number Subsystem Architecture + +13.6.1 Description of the CSPRNG +-------------------------------- + +This random number generator is loosely modelled after the one +described in Peter Gutmann's paper: "Software Generation of Practically +Strong Random Numbers".(1) + + A pool of 600 bytes is used and mixed using the core RIPE-MD160 hash +transform function. Several extra features are used to make the robust +against a wide variety of attacks and to protect against failures of +subsystems. The state of the generator may be saved to a file and +initially seed form a file. + + Depending on how Libgcrypt was build the generator is able to select +the best working entropy gathering module. It makes use of the slow +and fast collection methods and requires the pool to initially seeded +form the slow gatherer or a seed file. An entropy estimation is used +to mix in enough data from the gather modules before returning the +actual random output. Process fork detection and protection is +implemented. + + The implementation of the nonce generator (for `gcry_create_nonce') +is a straightforward repeated hash design: A 28 byte buffer is +initially seeded with the PID and the time in seconds in the first 20 +bytes and with 8 bytes of random taken from the `GCRY_STRONG_RANDOM' +generator. Random numbers are then created by hashing all the 28 bytes +with SHA-1 and saving that again in the first 20 bytes. The hash is +also returned as result. + + ---------- Footnotes ---------- + + (1) Also described in chapter 6 of his book "Cryptographic Security +Architecture", New York, 2004, ISBN 0-387-95387-6. + + +File: gcrypt.info, Node: FIPS PRNG Description, Prev: CSPRNG Description, Up: Random-Number Subsystem Architecture + +13.6.2 Description of the FIPS X9.31 PRNG +----------------------------------------- + +The core of this deterministic random number generator is implemented +according to the document "NIST-Recommended Random Number Generator +Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key Triple DES and AES +Algorithms", dated 2005-01-31. This implementation uses the AES +variant. + + The generator is based on contexts to utilize the same core functions +for all random levels as required by the high-level interface. All +random generators return their data in 128 bit blocks. If the caller +requests less bits, the extra bits are not used. The key for each +generator is only set once at the first time a generator context is +used. The seed value is set along with the key and again after 1000 +output blocks. + + On Unix like systems the `GCRY_VERY_STRONG_RANDOM' and +`GCRY_STRONG_RANDOM' generators are keyed and seeded using the rndlinux +module with the `/dev/radnom' device. Thus these generators may block +until the OS kernel has collected enough entropy. When used with +Microsoft Windows the rndw32 module is used instead. + + The generator used for `gcry_create_nonce' is keyed and seeded from +the `GCRY_STRONG_RANDOM' generator. Thus is may also block if the +`GCRY_STRONG_RANDOM' generator has not yet been used before and thus +gets initialized on the first use by `gcry_create_nonce'. This special +treatment is justified by the weaker requirements for a nonce generator +and to save precious kernel entropy for use by the "real" random +generators. + + A self-test facility uses a separate context to check the +functionality of the core X9.31 functions using a known answers test. +During runtime each output block is compared to the previous one to +detect a stucked generator. + + The DT value for the generator is made up of the current time down to +microseconds (if available) and a free running 64 bit counter. When +used with the test context the DT value is taken from the context and +incremented on each use. + + +File: gcrypt.info, Node: Self-Tests, Next: FIPS Mode, Prev: Architecture, Up: Top + +Appendix A Description of the Self-Tests +**************************************** + +In addition to the build time regression test suite, Libgcrypt +implements self-tests to be performed at runtime. Which self-tests are +actually used depends on the mode Libgcrypt is used in. In standard +mode a limited set of self-tests is run at the time an algorithm is +first used. Note that not all algorithms feature a self-test in +standard mode. The `GCRYCTL_SELFTEST' control command may be used to +run all implemented self-tests at any time; this will even run more +tests than those run in FIPS mode. + + If any of the self-tests fails, the library immediately returns an +error code to the caller. If Libgcrypt is in FIPS mode the self-tests +will be performed within the "Self-Test" state and any failure puts the +library into the "Error" state. + +A.1 Power-Up Tests +================== + +Power-up tests are only performed if Libgcrypt is in FIPS mode. + +A.1.1 Symmetric Cipher Algorithm Power-Up Tests +----------------------------------------------- + +The following symmetric encryption algorithm tests are run during +power-up: + +3DES + To test the 3DES 3-key EDE encryption in ECB mode these tests are + run: + 1. A known answer test is run on a 64 bit test vector processed + by 64 rounds of Single-DES block encryption and decryption + using a key changed with each round. + + 2. A known answer test is run on a 64 bit test vector processed + by 16 rounds of 2-key and 3-key Triple-DES block encryption + and decryptions using a key changed with each round. + + 3. 10 known answer tests using 3-key Triple-DES EDE encryption, + comparing the ciphertext to the known value, then running a + decryption and comparing it to the initial plaintext. + (`cipher/des.c:selftest') + +AES-128 + A known answer tests is run using one test vector and one test key + with AES in ECB mode. (`cipher/rijndael.c:selftest_basic_128') + +AES-192 + A known answer tests is run using one test vector and one test key + with AES in ECB mode. (`cipher/rijndael.c:selftest_basic_192') + +AES-256 + A known answer tests is run using one test vector and one test key + with AES in ECB mode. (`cipher/rijndael.c:selftest_basic_256') + +A.1.2 Hash Algorithm Power-Up Tests +----------------------------------- + +The following hash algorithm tests are run during power-up: + +SHA-1 + A known answer test using the string `"abc"' is run. + (`cipher/sha1.c:selftests_sha1') + +SHA-224 + A known answer test using the string `"abc"' is run. + (`cipher/sha256.c:selftests_sha224') + +SHA-256 + A known answer test using the string `"abc"' is run. + (`cipher/sha256.c:selftests_sha256') + +SHA-384 + A known answer test using the string `"abc"' is run. + (`cipher/sha512.c:selftests_sha384') + +SHA-512 + A known answer test using the string `"abc"' is run. + (`cipher/sha512.c:selftests_sha512') + +A.1.3 MAC Algorithm Power-Up Tests +---------------------------------- + +The following MAC algorithm tests are run during power-up: + +HMAC SHA-1 + A known answer test using 9 byte of data and a 64 byte key is run. + (`cipher/hmac-tests.c:selftests_sha1') + +HMAC SHA-224 + A known answer test using 28 byte of data and a 4 byte key is run. + (`cipher/hmac-tests.c:selftests_sha224') + +HMAC SHA-256 + A known answer test using 28 byte of data and a 4 byte key is run. + (`cipher/hmac-tests.c:selftests_sha256') + +HMAC SHA-384 + A known answer test using 28 byte of data and a 4 byte key is run. + (`cipher/hmac-tests.c:selftests_sha384') + +HMAC SHA-512 + A known answer test using 28 byte of data and a 4 byte key is run. + (`cipher/hmac-tests.c:selftests_sha512') + +A.1.4 Random Number Power-Up Test +--------------------------------- + +The DRNG is tested during power-up this way: + + 1. Requesting one block of random using the public interface to check + general working and the duplicated block detection. + + 2. 3 know answer tests using pre-defined keys, seed and initial DT + values. For each test 3 blocks of 16 bytes are requested and + compared to the expected result. The DT value is incremented for + each block. + +A.1.5 Public Key Algorithm Power-Up Tests +----------------------------------------- + +The public key algorithms are tested during power-up: + +RSA + A pre-defined 1024 bit RSA key is used and these tests are run in + turn: + 1. Conversion of S-expression to internal format. + (`cipher/rsa.c:selftests_rsa') + + 2. Private key consistency check. (`cipher/rsa.c:selftests_rsa') + + 3. A pre-defined 20 byte value is signed with PKCS#1 padding for + SHA-1. The result is verified using the public key against + the original data and against modified data. + (`cipher/rsa.c:selftest_sign_1024') + + 4. A 1000 bit random value is encrypted and checked that it does + not match the orginal random value. The encrtypted result is + then decrypted and checked that it macthes the original + random value. (`cipher/rsa.c:selftest_encr_1024') + +DSA + A pre-defined 1024 bit DSA key is used and these tests are run in + turn: + 1. Conversion of S-expression to internal format. + (`cipher/dsa.c:selftests_dsa') + + 2. Private key consistency check. (`cipher/dsa.c:selftests_dsa') + + 3. A pre-defined 20 byte value is signed with PKCS#1 padding for + SHA-1. The result is verified using the public key against + the original data and against modified data. + (`cipher/dsa.c:selftest_sign_1024') + +A.1.6 Integrity Power-Up Tests +------------------------------ + +The integrity of the Libgcrypt is tested during power-up but only if +checking has been enabled at build time. The check works by computing +a HMAC SHA-256 checksum over the file used to load Libgcrypt into +memory. That checksum is compared against a checksum stored in a file +of the same name but with a single dot as a prefix and a suffix of +`.hmac'. + +A.1.7 Critical Functions Power-Up Tests +--------------------------------------- + +The 3DES weak key detection is tested during power-up by calling the +detection function with keys taken from a table listening all weak +keys. The table itself is protected using a SHA-1 hash. +(`cipher/des.c:selftest') + +A.2 Conditional Tests +===================== + +The conditional tests are performed if a certain contidion is met. +This may occur at any time; the library does not necessary enter the +"Self-Test" state to run these tests but will transit to the "Error" +state if a test failed. + +A.2.1 Key-Pair Generation Tests +------------------------------- + +After an asymmetric key-pair has been generated, Libgcrypt runs a +pair-wise consistency tests on the generated key. On failure the +generated key is not used, an error code is returned and, if in FIPS +mode, the library is put into the "Error" state. + +RSA + The test uses a random number 64 bits less the size of the modulus + as plaintext and runs an encryption and decryption operation in + turn. The encrypted value is checked to not match the plaintext + and the result of the decryption is checked to match the plaintext. + + A new random number of the same size is generated, signed and + verified to test the correctness of the signing operation. As a + second signing test, the signature is modified by incrementing its + value and then verified with the expected result that the + verification fails. (`cipher/rsa.c:test_keys') + +DSA + The test uses a random number of the size of the Q parameter to + create a signature and then checks that the signature verifies. + As a second signing test, the data is modified by incrementing its + value and then verified against the signature with the expected + result that the verification fails. (`cipher/dsa.c:test_keys') + +A.2.2 Software Load Tests +------------------------- + +Loading of extra modules into libgcrypt is disabled in FIPS mode and +thus no tests are implemented. (`cipher/cipher.c:gcry_cipher_register', +`cipher/md.c:gcry_md_register', `cipher/md.c:gcry_pk_register') + +A.2.3 Manual Key Entry Tests +---------------------------- + +A manual key entry feature is not implemented in Libgcrypt. + +A.2.4 Continuous RNG Tests +-------------------------- + +The continuous random number test is only used in FIPS mode. The RNG +generates blocks of 128 bit size; the first block generated per context +is saved in the context and another block is generated to be returned +to the caller. Each block is compared against the saved block and then +stored in the context. If a duplicated block is detected an error is +signaled and the libray is put into the "Fatal-Error" state. +(`random/random-fips.c:x931_aes_driver') + +A.3 Application Requested Tests +=============================== + +The application may requests tests at any time by means of the +`GCRYCTL_SELFTEST' control command. Note that using these tests is not +FIPS conform: Although Libgcrypt rejects all application requests for +services while running self-tests, it does not ensure that no other +operations of Libgcrypt are still being executed. Thus, in FIPS mode +an application requesting self-tests needs to power-cycle Libgcrypt +instead. + + When self-tests are requested, Libgcrypt runs all the tests it does +during power-up as well as a few extra checks as described below. + +A.3.1 Symmetric Cipher Algorithm Tests +-------------------------------------- + +The following symmetric encryption algorithm tests are run in addition +to the power-up tests: + +AES-128 + A known answer tests with test vectors taken from NIST SP800-38a + and using the high level functions is run for block modes CFB and + OFB. + + +A.3.2 Hash Algorithm Tests +-------------------------- + +The following hash algorithm tests are run in addition to the power-up +tests: + +SHA-1 +SHA-224 +SHA-256 + 1. A known answer test using a 56 byte string is run. + + 2. A known answer test using a string of one million letters "a" + is run. + (`cipher/sha1.c:selftests_sha1', + `cipher/sha256.c:selftests_sha224', + `cipher/sha256.c:selftests_sha256') + +SHA-384 + +SHA-512 + 1. A known answer test using a 112 byte string is run. + + 2. A known answer test using a string of one million letters "a" + is run. + (`cipher/sha512.c:selftests_sha384', + `cipher/sha512.c:selftests_sha512') + +A.3.3 MAC Algorithm Tests +------------------------- + +The following MAC algorithm tests are run in addition to the power-up +tests: + +HMAC SHA-1 + 1. A known answer test using 9 byte of data and a 20 byte key is + run. + + 2. A known answer test using 9 byte of data and a 100 byte key + is run. + + 3. A known answer test using 9 byte of data and a 49 byte key is + run. + (`cipher/hmac-tests.c:selftests_sha1') + +HMAC SHA-224 +HMAC SHA-256 +HMAC SHA-384 +HMAC SHA-512 + 1. A known answer test using 9 byte of data and a 20 byte key is + run. + + 2. A known answer test using 50 byte of data and a 20 byte key + is run. + + 3. A known answer test using 50 byte of data and a 26 byte key + is run. + + 4. A known answer test using 54 byte of data and a 131 byte key + is run. + + 5. A known answer test using 152 byte of data and a 131 byte key + is run. + (`cipher/hmac-tests.c:selftests_sha224', + `cipher/hmac-tests.c:selftests_sha256', + `cipher/hmac-tests.c:selftests_sha384', + `cipher/hmac-tests.c:selftests_sha512') + + +File: gcrypt.info, Node: FIPS Mode, Next: Library Copying, Prev: Self-Tests, Up: Top + +Appendix B Description of the FIPS Mode +*************************************** + +This appendix gives detailed information pertaining to the FIPS mode. +In particular, the changes to the standard mode and the finite state +machine are described. The self-tests required in this mode are +described in the appendix on self-tests. + +B.1 Restrictions in FIPS Mode +============================= + +If Libgcrypt is used in FIPS mode these restrictions are effective: + + * The cryptographic algorithms are restricted to this list: + + GCRY_CIPHER_3DES + 3 key EDE Triple-DES symmetric encryption. + + GCRY_CIPHER_AES128 + AES 128 bit symmetric encryption. + + GCRY_CIPHER_AES192 + AES 192 bit symmetric encryption. + + GCRY_CIPHER_AES256 + AES 256 bit symmetric encryption. + + GCRY_MD_SHA1 + SHA-1 message digest. + + GCRY_MD_SHA224 + SHA-224 message digest. + + GCRY_MD_SHA256 + SHA-256 message digest. + + GCRY_MD_SHA384 + SHA-384 message digest. + + GCRY_MD_SHA512 + SHA-512 message digest. + + GCRY_MD_SHA1,GCRY_MD_FLAG_HMAC + HMAC using a SHA-1 message digest. + + GCRY_MD_SHA224,GCRY_MD_FLAG_HMAC + HMAC using a SHA-224 message digest. + + GCRY_MD_SHA256,GCRY_MD_FLAG_HMAC + HMAC using a SHA-256 message digest. + + GCRY_MD_SHA384,GCRY_MD_FLAG_HMAC + HMAC using a SHA-384 message digest. + + GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC + HMAC using a SHA-512 message digest. + + GCRY_PK_RSA + RSA encryption and signing. + + GCRY_PK_DSA + DSA signing. + + Note that the CRC algorithms are not considered cryptographic + algorithms and thus are in addition available. + + * RSA key generation refuses to create a key with a keysize of less + than 1024 bits. + + * DSA key generation refuses to create a key with a keysize other + than 1024 bits. + + * The `transient-key' flag for RSA and DSA key generation is ignored. + + * Support for the VIA Padlock engine is disabled. + + * FIPS mode may only be used on systems with a /dev/random device. + Switching into FIPS mode on other systems will fail at runtime. + + * Saving and loading a random seed file is ignored. + + * An X9.31 style random number generator is used in place of the + large-pool-CSPRNG generator. + + * The command `GCRYCTL_ENABLE_QUICK_RANDOM' is ignored. + + * The Alternative Public Key Interface (`gcry_ac_xxx') is not + supported and all API calls return an error. + + * Registration of external modules is not supported. + + * Message digest debugging is disabled. + + * All debug output related to cryptographic data is suppressed. + + * On-the-fly self-tests are not performed, instead self-tests are run + before entering operational state. + + * The function `gcry_set_allocation_handler' may not be used. If it + is used Libgcrypt disables FIPS mode unless Enforced FIPS mode is + enabled, in which case Libgcrypt will enter the error state. + + * The digest algorithm MD5 may not be used. If it is used Libgcrypt + disables FIPS mode unless Enforced FIPS mode is enabled, in which + case Libgcrypt will enter the error state. + + * In Enforced FIPS mode the command `GCRYCTL_DISABLE_SECMEM' is + ignored. In standard FIPS mode it disables FIPS mode. + + * A handler set by `gcry_set_outofcore_handler' is ignored. + + * A handler set by `gcry_set_fatalerror_handler' is ignored. + + + Note that when we speak about disabling FIPS mode, it merely means +that the function `gcry_fips_mode_active' returns false; it does not +mean that any non FIPS algorithms are allowed. + +B.2 FIPS Finite State Machine +============================= + +The FIPS mode of libgcrypt implements a finite state machine (FSM) using +8 states (*note tbl:fips-states::) and checks at runtime that only valid +transitions (*note tbl:fips-state-transitions::) may happen. + + [image src="fips-fsm.png" alt="FIPS FSM Diagram"] +Figure B.1: FIPS mode state diagram + +States used by the FIPS FSM: +Power-Off + Libgcrypt is not runtime linked to another application. This + usually means that the library is not loaded into main memory. + This state is documentation only. + +Power-On + Libgcrypt is loaded into memory and API calls may be made. + Compiler introducted constructor functions may be run. Note that + Libgcrypt does not implement any arbitrary constructor functions + to be called by the operating system + +Init + The Libgcrypt initialization functions are performed and the + library has not yet run any self-test. + +Self-Test + Libgcrypt is performing self-tests. + +Operational + Libgcrypt is in the operational state and all interfaces may be + used. + +Error + Libgrypt is in the error state. When calling any FIPS relevant + interfaces they either return an error (`GPG_ERR_NOT_OPERATIONAL') + or put Libgcrypt into the Fatal-Error state and won't return. + +Fatal-Error + Libgcrypt is in a non-recoverable error state and will + automatically transit into the Shutdown state. + +Shutdown + Libgcrypt is about to be terminated and removed from the memory. + The application may at this point still runing cleanup handlers. + + +Table B.1: FIPS mode states + +The valid state transitions (*note Figure B.1: fig:fips-fsm.) are: +`1' + Power-Off to Power-On is implicitly done by the OS loading + Libgcrypt as a shared library and having it linked to an + application. + +`2' + Power-On to Init is triggered by the application calling the + Libgcrypt intialization function `gcry_check_version'. + +`3' + Init to Self-Test is either triggred by a dedicated API call or + implicit by invoking a libgrypt service conrolled by the FSM. + +`4' + Self-Test to Operational is triggered after all self-tests passed + successfully. + +`5' + Operational to Shutdown is an artifical state without any direct + action in Libgcrypt. When reaching the Shutdown state the library + is deinitialized and can't return to any other state again. + +`6' + Shutdown to Power-off is the process of removing Libgcrypt from the + computer's memory. For obvious reasons the Power-Off state can't + be represented within Libgcrypt and thus this transition is for + documentation only. + +`7' + Operational to Error is triggered if Libgcrypt detected an + application error which can't be returned to the caller but still + allows Libgcrypt to properly run. In the Error state all FIPS + relevant interfaces return an error code. + +`8' + Error to Shutdown is similar to the Operational to Shutdown + transition (5). + +`9' + Error to Fatal-Error is triggred if Libgrypt detects an fatal error + while already being in Error state. + +`10' + Fatal-Error to Shutdown is automatically entered by Libgcrypt + after having reported the error. + +`11' + Power-On to Shutdown is an artifical state to document that + Libgcrypt has not ye been initializaed but the process is about to + terminate. + +`12' + Power-On to Fatal-Error will be triggerd if certain Libgcrypt + functions are used without having reached the Init state. + +`13' + Self-Test to Fatal-Error is triggred by severe errors in Libgcrypt + while running self-tests. + +`14' + Self-Test to Error is triggred by a failed self-test. + +`15' + Operational to Fatal-Error is triggered if Libcrypt encountered a + non-recoverable error. + +`16' + Operational to Self-Test is triggred if the application requested + to run the self-tests again. + +`17' + Error to Self-Test is triggered if the application has requested + to run self-tests to get to get back into operational state after + an error. + +`18' + Init to Error is triggered by errors in the initialization code. + +`19' + Init to Fatal-Error is triggered by non-recoverable errors in the + initialization code. + +`20' + Error to Error is triggered by errors while already in the Error + state. + + +Table B.2: FIPS mode state transitions + +B.3 FIPS Miscellaneous Information +================================== + +Libgcrypt does not do any key management on itself; the application +needs to care about it. Keys which are passed to Libgcrypt should be +allocated in secure memory as available with the functions +`gcry_malloc_secure' and `gcry_calloc_secure'. By calling `gcry_free' +on this memory, the memory and thus the keys are overwritten with zero +bytes before releasing the memory. + + For use with the random number generator, Libgcrypt generates 3 +internal keys which are stored in the encryption contexts used by the +RNG. These keys are stored in secure memory for the lifetime of the +process. Application are required to use `GCRYCTL_TERM_SECMEM' before +process termination. This will zero out the entire secure memory and +thus also the encryption contexts with these keys. + + +File: gcrypt.info, Node: Library Copying, Next: Copying, Prev: FIPS Mode, Up: Top + +GNU Lesser General Public License +********************************* + + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence the + version number 2.1.] + +Preamble +======== + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public Licenses +are intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software--typically libraries--of the Free +Software Foundation and other authors who decide to use it. You can use +it too, but we suggest you first think carefully about whether this +license or the ordinary General Public License is the better strategy to +use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of it +in new free programs; and that you are informed that you can do these +things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know that +what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and is +quite different from the ordinary General Public License. We use this +license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does _Less_ to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of free +software. For example, permission to use the GNU C Library in non-free +programs enables many more people to use the whole GNU operating +system, as well as its variant, the GNU/Linux operating system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run that +program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + 0. This License Agreement applies to any software library or other + program which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under the + terms of this Lesser General Public License (also called "this + License"). Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or + translated straightforwardly into another language. (Hereinafter, + translation is included without limitation in the term + "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, complete source code + means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the library. + + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running a program using the Library is not restricted, and + output from such a program is covered only if its contents + constitute a work based on the Library (independent of the use of + the Library in a tool for writing it). Whether that is true + depends on what the Library does and what the program that uses + the Library does. + + 1. You may copy and distribute verbatim copies of the Library's + complete source code as you receive it, in any medium, provided + that you conspicuously and appropriately publish on each copy an + appropriate copyright notice and disclaimer of warranty; keep + intact all the notices that refer to this License and to the + absence of any warranty; and distribute a copy of this License + along with the Library. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange + for a fee. + + 2. You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a. The modified work must itself be a software library. + + b. You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c. You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d. If a facility in the modified Library refers to a function or + a table of data to be supplied by an application program that + uses the facility, other than as an argument passed when the + facility is invoked, then you must make a good faith effort + to ensure that, in the event an application does not supply + such function or table, the facility still operates, and + performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, the + square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Library, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Library, the distribution of + the whole must be on the terms of this License, whose permissions + for other licensees extend to the entire whole, and thus to each + and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the + Library with the Library (or with a work based on the Library) on + a volume of a storage or distribution medium does not bring the + other work under the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public + License instead of this License to a given copy of the Library. + To do this, you must alter all the notices that refer to this + License, so that they refer to the ordinary GNU General Public + License, version 2, instead of to this License. (If a newer + version than version 2 of the ordinary GNU General Public License + has appeared, then you can specify that version instead if you + wish.) Do not make any other change in these notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to + all subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of + the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or + derivative of it, under Section 2) in object code or executable + form under the terms of Sections 1 and 2 above provided that you + accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange. + + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy + the source code from the same place satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being + compiled or linked with it, is called a "work that uses the + Library". Such a work, in isolation, is not a derivative work of + the Library, and therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a "work that + uses the library". The executable is therefore covered by this + License. Section 6 states terms for distribution of such + executables. + + When a "work that uses the Library" uses material from a header + file that is part of the Library, the object code for the work may + be a derivative work of the Library even though the source code is + not. Whether this is true is especially significant if the work + can be linked without the Library, or if the work is itself a + library. The threshold for this to be true is not precisely + defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a + derivative work. (Executables containing this object code plus + portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or + link a "work that uses the Library" with the Library to produce a + work containing portions of the Library, and distribute that work + under terms of your choice, provided that the terms permit + modification of the work for the customer's own use and reverse + engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are covered + by this License. You must supply a copy of this License. If the + work during execution displays copyright notices, you must include + the copyright notice for the Library among them, as well as a + reference directing the user to the copy of this License. Also, + you must do one of these things: + + a. Accompany the work with the complete corresponding + machine-readable source code for the Library including + whatever changes were used in the work (which must be + distributed under Sections 1 and 2 above); and, if the work + is an executable linked with the Library, with the complete + machine-readable "work that uses the Library", as object code + and/or source code, so that the user can modify the Library + and then relink to produce a modified executable containing + the modified Library. (It is understood that the user who + changes the contents of definitions files in the Library will + not necessarily be able to recompile the application to use + the modified definitions.) + + b. Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run + time a copy of the library already present on the user's + computer system, rather than copying library functions into + the executable, and (2) will operate properly with a modified + version of the library, if the user installs one, as long as + the modified version is interface-compatible with the version + that the work was made with. + + c. Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d. If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the + above specified materials from the same place. + + e. Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special + exception, the materials to be distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of + the operating system on which the executable runs, unless that + component itself accompanies the executable. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you + cannot use both them and the Library together in an executable + that you distribute. + + 7. You may place library facilities that are a work based on the + Library side-by-side in a single library together with other + library facilities not covered by this License, and distribute + such a combined library, provided that the separate distribution + of the work based on the Library and of the other library + facilities is otherwise permitted, and provided that you do these + two things: + + a. Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b. Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same + work. + + 8. You may not copy, modify, sublicense, link with, or distribute the + Library except as expressly provided under this License. Any + attempt otherwise to copy, modify, sublicense, link with, or + distribute the Library is void, and will automatically terminate + your rights under this License. However, parties who have + received copies, or rights, from you under this License will not + have their licenses terminated so long as such parties remain in + full compliance. + + 9. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify + or distribute the Library or its derivative works. These actions + are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any work + based on the Library), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the + Library), the recipient automatically receives a license from the + original licensor to copy, distribute, link with or modify the + Library subject to these terms and conditions. You may not impose + any further restrictions on the recipients' exercise of the rights + granted herein. You are not responsible for enforcing compliance + by third parties with this License. + + 11. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent + issues), conditions are imposed on you (whether by court order, + agreement or otherwise) that contradict the conditions of this + License, they do not excuse you from the conditions of this + License. If you cannot distribute so as to satisfy simultaneously + your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the + Library at all. For example, if a patent license would not permit + royalty-free redistribution of the Library by all those who + receive copies directly or indirectly through you, then the only + way you could satisfy both it and this License would be to refrain + entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply, and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of + any such claims; this section has the sole purpose of protecting + the integrity of the free software distribution system which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Library under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this + License incorporates the limitation as if written in the body of + this License. + + 13. The Free Software Foundation may publish revised and/or new + versions of the Lesser General Public License from time to time. + Such new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Library specifies a version number of this License which applies + to it and "any later version", you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Library + does not specify a license version number, you may choose any + version ever published by the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free + programs whose distribution conditions are incompatible with these, + write to the author to ask for permission. For software which is + copyrighted by the Free Software Foundation, write to the Free + Software Foundation; we sometimes make exceptions for this. Our + decision will be guided by the two goals of preserving the free + status of all derivatives of our free software and of promoting + the sharing and reuse of software generally. + + NO WARRANTY + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE + LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE + QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE + LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY + SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY + MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, + INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU + OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY + OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Libraries +============================================== + +If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of +the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should have +at least the "copyright" line and a pointer to where the full notice is +found. + + ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, + USA. + + Also add information on how to contact you by electronic and paper +mail. + + You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the library + `Frob' (a library for tweaking knobs) written by James Random Hacker. + + SIGNATURE OF TY COON, 1 April 1990 + Ty Coon, President of Vice + + That's all there is to it! + + +File: gcrypt.info, Node: Copying, Next: Figures and Tables, Prev: Library Copying, Up: Top + +GNU General Public License +************************** + + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble +======== + +The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it in +new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, +and (2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + 1. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", + below, refers to any such program or work, and a "work based on + the Program" means either the Program or any derivative work under + copyright law: that is to say, a work containing the Program or a + portion of it, either verbatim or with modifications and/or + translated into another language. (Hereinafter, translation is + included without limitation in the term "modification".) Each + licensee is addressed as "you". + + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based on + the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + + 2. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any + warranty; and give any other recipients of the Program a copy of + this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange + for a fee. + + 3. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a. You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b. You must cause any work that you distribute or publish, that + in whole or in part contains or is derived from the Program + or any part thereof, to be licensed as a whole at no charge + to all third parties under the terms of this License. + + c. If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the + program under these conditions, and telling the user how to + view a copy of this License. (Exception: if the Program + itself is interactive but does not normally print such an + announcement, your work based on the Program is not required + to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Program, the distribution of + the whole must be on the terms of this License, whose permissions + for other licensees extend to the entire whole, and thus to each + and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the + Program with the Program (or with a work based on the Program) on + a volume of a storage or distribution medium does not bring the + other work under the scope of this License. + + 4. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms + of Sections 1 and 2 above provided that you also do one of the + following: + + a. Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Sections 1 and 2 above on a medium customarily used for + software interchange; or, + + b. Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange; or, + + c. Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with + such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed need + not include anything that is normally distributed (in either + source or binary form) with the major components (compiler, + kernel, and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this + License. However, parties who have received copies, or rights, + from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + + 6. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify + or distribute the Program or its derivative works. These actions + are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any work + based on the Program), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + + 7. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program + subject to these terms and conditions. You may not impose any + further restrictions on the recipients' exercise of the rights + granted herein. You are not responsible for enforcing compliance + by third parties to this License. + + 8. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent + issues), conditions are imposed on you (whether by court order, + agreement or otherwise) that contradict the conditions of this + License, they do not excuse you from the conditions of this + License. If you cannot distribute so as to satisfy simultaneously + your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the + Program at all. For example, if a patent license would not permit + royalty-free redistribution of the Program by all those who + receive copies directly or indirectly through you, then the only + way you could satisfy both it and this License would be to refrain + entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of + any such claims; this section has the sole purpose of protecting + the integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. + + 9. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this + License incorporates the limitation as if written in the body of + this License. + + 10. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such + new versions will be similar in spirit to the present version, but + may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies + to it and "any later version", you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Program + does not specify a version number of this License, you may choose + any version ever published by the Free Software Foundation. + + 11. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted + by the Free Software Foundation, write to the Free Software + Foundation; we sometimes make exceptions for this. Our decision + will be guided by the two goals of preserving the free status of + all derivatives of our free software and of promoting the sharing + and reuse of software generally. + + NO WARRANTY + 12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE + LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE + QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY + SERVICING, REPAIR OR CORRECTION. + + 13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY + MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE + LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, + INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR + INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU + OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY + OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Programs +============================================= + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND AN IDEA OF WHAT IT DOES. + Copyright (C) 19YY NAME OF AUTHOR + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + + Also add information on how to contact you by electronic and paper +mail. + + If the program is interactive, make it output a short notice like +this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w'. This is free software, and you are welcome + to redistribute it under certain conditions; type `show c' + for details. + + The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + + You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the program, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright + interest in the program `Gnomovision' + (which makes passes at compilers) written + by James Hacker. + + SIGNATURE OF TY COON, 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Library General Public License instead of this License. + + +File: gcrypt.info, Node: Figures and Tables, Next: Concept Index, Prev: Copying, Up: Top + +List of Figures and Tables +************************** + +* Menu: + +* Figure 13.1: Libgcrypt subsystems: fig:subsystems. +* Figure B.1: FIPS mode state ...: fig:fips-fsm. + +* Menu: + +* Table B.1: FIPS mode states: tbl:fips-states. +* Table B.2: FIPS mode state ...: tbl:fips-state-transitions. + + +File: gcrypt.info, Node: Concept Index, Next: Function and Data Index, Prev: Figures and Tables, Up: Top + +Concept Index +************* + +[index] +* Menu: + +* 3DES: Available ciphers. (line 16) +* Advanced Encryption Standard: Available ciphers. (line 37) +* AES: Available ciphers. (line 37) +* Arcfour: Available ciphers. (line 54) +* Blowfish: Available ciphers. (line 24) +* Camellia: Available ciphers. (line 81) +* CAST5: Available ciphers. (line 21) +* CBC, Cipher Block Chaining mode: Available cipher modes. + (line 20) +* CBC-MAC: Working with cipher handles. + (line 52) +* CFB, Cipher Feedback mode: Available cipher modes. + (line 16) +* cipher text stealing: Working with cipher handles. + (line 45) +* CRC32: Available hash algorithms. + (line 6) +* CTR, Counter mode: Available cipher modes. + (line 29) +* DES: Available ciphers. (line 59) +* DES-EDE: Available ciphers. (line 16) +* Digital Encryption Standard: Available ciphers. (line 16) +* ECB, Electronic Codebook mode: Available cipher modes. + (line 13) +* Enforced FIPS mode: Enabling FIPS mode. (line 30) +* error codes: Error Values. (line 6) +* error codes, list of <1>: Error Codes. (line 6) +* error codes, list of: Error Sources. (line 6) +* error codes, printing of: Error Strings. (line 6) +* error sources: Error Values. (line 6) +* error sources, printing of: Error Strings. (line 6) +* error strings: Error Strings. (line 6) +* error values: Error Values. (line 6) +* error values, printing of: Error Strings. (line 6) +* FIPS 140: Enabling FIPS mode. (line 6) +* FIPS 186 <1>: Public-Key Subsystem Architecture. + (line 63) +* FIPS 186: General public-key related Functions. + (line 256) +* FIPS mode: Enabling FIPS mode. (line 6) +* GPL, GNU General Public License: Copying. (line 6) +* HAVAL: Available hash algorithms. + (line 6) +* HMAC: Working with hash algorithms. + (line 27) +* IDEA: Available ciphers. (line 11) +* LGPL, GNU Lesser General Public License: Library Copying. (line 6) +* MD2, MD4, MD5: Available hash algorithms. + (line 6) +* OFB, Output Feedback mode: Available cipher modes. + (line 26) +* RC2: Available ciphers. (line 71) +* RC4: Available ciphers. (line 54) +* rfc-2268: Available ciphers. (line 71) +* Rijndael: Available ciphers. (line 37) +* RIPE-MD-160: Available hash algorithms. + (line 6) +* Seed (cipher): Available ciphers. (line 76) +* Serpent: Available ciphers. (line 67) +* SHA-1: Available hash algorithms. + (line 6) +* SHA-224, SHA-256, SHA-384, SHA-512: Available hash algorithms. + (line 6) +* sync mode (OpenPGP): Working with cipher handles. + (line 40) +* TIGER: Available hash algorithms. + (line 6) +* Triple-DES: Available ciphers. (line 16) +* Twofish: Available ciphers. (line 48) +* Whirlpool: Available hash algorithms. + (line 6) +* X9.31 <1>: Public-Key Subsystem Architecture. + (line 63) +* X9.31: General public-key related Functions. + (line 249) + + +File: gcrypt.info, Node: Function and Data Index, Prev: Concept Index, Up: Top + +Function and Data Index +*********************** + +[index] +* Menu: + +* AM_PATH_LIBGCRYPT: Building sources using Automake. + (line 13) +* gcry_ac_close: Working with handles. + (line 21) +* gcry_ac_data_clear: Working with sets of data. + (line 75) +* gcry_ac_data_copy: Working with sets of data. + (line 53) +* gcry_ac_data_decode: Using cryptographic functions. + (line 100) +* gcry_ac_data_decrypt: Using cryptographic functions. + (line 40) +* gcry_ac_data_decrypt_scheme: Using cryptographic functions. + (line 137) +* gcry_ac_data_destroy: Working with sets of data. + (line 41) +* gcry_ac_data_encode: Using cryptographic functions. + (line 93) +* gcry_ac_data_encrypt: Using cryptographic functions. + (line 33) +* gcry_ac_data_encrypt_scheme: Using cryptographic functions. + (line 127) +* gcry_ac_data_from_sexp: Working with sets of data. + (line 93) +* gcry_ac_data_get_index: Working with sets of data. + (line 69) +* gcry_ac_data_get_name: Working with sets of data. + (line 61) +* gcry_ac_data_length: Working with sets of data. + (line 57) +* gcry_ac_data_new: Working with sets of data. + (line 38) +* gcry_ac_data_set: Working with sets of data. + (line 45) +* gcry_ac_data_sign: Using cryptographic functions. + (line 48) +* gcry_ac_data_sign_scheme: Using cryptographic functions. + (line 147) +* gcry_ac_data_t: Working with sets of data. + (line 20) +* gcry_ac_data_to_sexp: Working with sets of data. + (line 79) +* gcry_ac_data_verify: Using cryptographic functions. + (line 54) +* gcry_ac_data_verify_scheme: Using cryptographic functions. + (line 157) +* gcry_ac_id_t: Available asymmetric algorithms. + (line 11) +* gcry_ac_id_to_name: Handle-independent functions. + (line 10) +* gcry_ac_io_init: Working with IO objects. + (line 22) +* gcry_ac_io_init_va: Working with IO objects. + (line 28) +* gcry_ac_io_t: Working with IO objects. + (line 10) +* gcry_ac_key_data_get: Working with keys. (line 93) +* gcry_ac_key_destroy: Working with keys. (line 86) +* gcry_ac_key_get_grip: Working with keys. (line 105) +* gcry_ac_key_get_nbits: Working with keys. (line 101) +* gcry_ac_key_init: Working with keys. (line 30) +* gcry_ac_key_pair_destroy: Working with keys. (line 90) +* gcry_ac_key_pair_extract: Working with keys. (line 83) +* gcry_ac_key_pair_generate: Working with keys. (line 36) +* gcry_ac_key_pair_t: Working with keys. (line 20) +* gcry_ac_key_t: Working with keys. (line 16) +* gcry_ac_key_test: Working with keys. (line 97) +* gcry_ac_key_type_t: Working with keys. (line 7) +* gcry_ac_name_to_id: Handle-independent functions. + (line 15) +* gcry_ac_open: Working with handles. + (line 11) +* gcry_calloc: Memory allocation. (line 15) +* gcry_calloc_secure: Memory allocation. (line 21) +* gcry_check_version: Initializing the library. + (line 17) +* gcry_cipher_algo_info: General cipher functions. + (line 12) +* gcry_cipher_algo_name: General cipher functions. + (line 39) +* gcry_cipher_close: Working with cipher handles. + (line 59) +* gcry_cipher_ctl: Working with cipher handles. + (line 157) +* gcry_cipher_decrypt: Working with cipher handles. + (line 127) +* gcry_cipher_decrypt_t: Cipher modules. (line 80) +* gcry_cipher_encrypt: Working with cipher handles. + (line 108) +* gcry_cipher_encrypt_t: Cipher modules. (line 75) +* gcry_cipher_info: Working with cipher handles. + (line 166) +* gcry_cipher_list: Cipher modules. (line 106) +* gcry_cipher_map_name: General cipher functions. + (line 45) +* gcry_cipher_mode_from_oid: General cipher functions. + (line 50) +* gcry_cipher_oid_spec_t: Cipher modules. (line 60) +* gcry_cipher_open: Working with cipher handles. + (line 11) +* gcry_cipher_register: Cipher modules. (line 96) +* gcry_cipher_reset: Working with cipher handles. + (line 95) +* gcry_cipher_setctr: Working with cipher handles. + (line 88) +* gcry_cipher_setiv: Working with cipher handles. + (line 81) +* gcry_cipher_setkey: Working with cipher handles. + (line 66) +* gcry_cipher_setkey_t: Cipher modules. (line 70) +* gcry_cipher_spec_t: Cipher modules. (line 12) +* gcry_cipher_stdecrypt_t: Cipher modules. (line 90) +* gcry_cipher_stencrypt_t: Cipher modules. (line 85) +* gcry_cipher_sync: Working with cipher handles. + (line 147) +* gcry_cipher_unregister: Cipher modules. (line 101) +* gcry_control: Controlling the library. + (line 7) +* gcry_create_nonce: Retrieving random numbers. + (line 26) +* gcry_err_code: Error Values. (line 43) +* gcry_err_code_from_errno: Error Values. (line 95) +* gcry_err_code_t: Error Values. (line 7) +* gcry_err_code_to_errno: Error Values. (line 100) +* gcry_err_make: Error Values. (line 57) +* gcry_err_make_from_errno: Error Values. (line 81) +* gcry_err_source: Error Values. (line 49) +* gcry_err_source_t: Error Values. (line 14) +* gcry_error: Error Values. (line 64) +* gcry_error_from_errno: Error Values. (line 86) +* gcry_error_t: Error Values. (line 25) +* gcry_fips_mode_active: Controlling the library. + (line 221) +* gcry_free: Memory allocation. (line 31) +* gcry_handler_alloc_t: Allocation handler. (line 12) +* gcry_handler_error_t: Error handler. (line 27) +* gcry_handler_free_t: Allocation handler. (line 24) +* gcry_handler_log_t: Logging handler. (line 7) +* gcry_handler_no_mem_t: Error handler. (line 11) +* gcry_handler_progress_t: Progress handler. (line 10) +* gcry_handler_realloc_t: Allocation handler. (line 20) +* gcry_handler_secure_check_t: Allocation handler. (line 16) +* gcry_malloc: Memory allocation. (line 7) +* gcry_malloc_secure: Memory allocation. (line 12) +* gcry_md_algo_name: Working with hash algorithms. + (line 152) +* gcry_md_close: Working with hash algorithms. + (line 61) +* gcry_md_copy: Working with hash algorithms. + (line 82) +* gcry_md_debug: Working with hash algorithms. + (line 216) +* gcry_md_enable: Working with hash algorithms. + (line 44) +* gcry_md_final: Working with hash algorithms. + (line 110) +* gcry_md_final_t: Hash algorithm modules. + (line 73) +* gcry_md_get_algo: Working with hash algorithms. + (line 196) +* gcry_md_get_algo_dlen: Working with hash algorithms. + (line 187) +* gcry_md_get_asnoid: Working with hash algorithms. + (line 168) +* gcry_md_hash_buffer: Working with hash algorithms. + (line 135) +* gcry_md_init_t: Hash algorithm modules. + (line 65) +* gcry_md_is_enabled: Working with hash algorithms. + (line 207) +* gcry_md_is_secure: Working with hash algorithms. + (line 202) +* gcry_md_list: Hash algorithm modules. + (line 91) +* gcry_md_map_name: Working with hash algorithms. + (line 158) +* gcry_md_oid_spec_t: Hash algorithm modules. + (line 57) +* gcry_md_open: Working with hash algorithms. + (line 11) +* gcry_md_putc: Working with hash algorithms. + (line 100) +* gcry_md_read: Working with hash algorithms. + (line 120) +* gcry_md_read_t: Hash algorithm modules. + (line 77) +* gcry_md_register: Hash algorithm modules. + (line 82) +* gcry_md_reset: Working with hash algorithms. + (line 70) +* gcry_md_setkey: Working with hash algorithms. + (line 53) +* gcry_md_spec_t: Hash algorithm modules. + (line 12) +* gcry_md_start_debug: Working with hash algorithms. + (line 230) +* gcry_md_stop_debug: Working with hash algorithms. + (line 238) +* gcry_md_test_algo: Working with hash algorithms. + (line 181) +* gcry_md_unregister: Hash algorithm modules. + (line 87) +* gcry_md_write: Working with hash algorithms. + (line 95) +* gcry_md_write_t: Hash algorithm modules. + (line 69) +* gcry_module_t: Modules. (line 10) +* gcry_mpi_add: Calculations. (line 10) +* gcry_mpi_add_ui: Calculations. (line 14) +* gcry_mpi_addm: Calculations. (line 18) +* gcry_mpi_aprint: MPI formats. (line 54) +* gcry_mpi_clear_bit: Bit manipulations. (line 19) +* gcry_mpi_clear_flag: Miscellaneous. (line 32) +* gcry_mpi_clear_highbit: Bit manipulations. (line 25) +* gcry_mpi_cmp: Comparisons. (line 9) +* gcry_mpi_cmp_ui: Comparisons. (line 13) +* gcry_mpi_copy: Basic functions. (line 23) +* gcry_mpi_div: Calculations. (line 50) +* gcry_mpi_dump: MPI formats. (line 61) +* gcry_mpi_gcd: Calculations. (line 63) +* gcry_mpi_get_flag: Miscellaneous. (line 37) +* gcry_mpi_get_nbits: Bit manipulations. (line 10) +* gcry_mpi_get_opaque: Miscellaneous. (line 20) +* gcry_mpi_invm: Calculations. (line 68) +* gcry_mpi_lshift: Bit manipulations. (line 34) +* gcry_mpi_mod: Calculations. (line 55) +* gcry_mpi_mul: Calculations. (line 34) +* gcry_mpi_mul_2exp: Calculations. (line 46) +* gcry_mpi_mul_ui: Calculations. (line 38) +* gcry_mpi_mulm: Calculations. (line 42) +* gcry_mpi_new: Basic functions. (line 10) +* gcry_mpi_powm: Calculations. (line 59) +* gcry_mpi_print: MPI formats. (line 45) +* gcry_mpi_randomize: Miscellaneous. (line 41) +* gcry_mpi_release: Basic functions. (line 26) +* gcry_mpi_rshift: Bit manipulations. (line 29) +* gcry_mpi_scan: MPI formats. (line 12) +* gcry_mpi_set: Basic functions. (line 33) +* gcry_mpi_set_bit: Bit manipulations. (line 16) +* gcry_mpi_set_flag: Miscellaneous. (line 26) +* gcry_mpi_set_highbit: Bit manipulations. (line 22) +* gcry_mpi_set_opaque: Miscellaneous. (line 8) +* gcry_mpi_set_ui: Basic functions. (line 37) +* gcry_mpi_snew: Basic functions. (line 17) +* gcry_mpi_sub: Calculations. (line 22) +* gcry_mpi_sub_ui: Calculations. (line 26) +* gcry_mpi_subm: Calculations. (line 30) +* gcry_mpi_swap: Basic functions. (line 44) +* gcry_mpi_t: Data types. (line 7) +* gcry_mpi_test_bit: Bit manipulations. (line 13) +* gcry_pk_algo_info: General public-key related Functions. + (line 47) +* gcry_pk_algo_name: General public-key related Functions. + (line 10) +* gcry_pk_check_secret_key_t: Public key modules. (line 91) +* gcry_pk_ctl: General public-key related Functions. + (line 100) +* gcry_pk_decrypt: Cryptographic Functions. + (line 85) +* gcry_pk_decrypt_t: Public key modules. (line 101) +* gcry_pk_encrypt: Cryptographic Functions. + (line 29) +* gcry_pk_encrypt_t: Public key modules. (line 96) +* gcry_pk_generate_t: Public key modules. (line 86) +* gcry_pk_genkey: General public-key related Functions. + (line 115) +* gcry_pk_get_keygrip: General public-key related Functions. + (line 29) +* gcry_pk_get_nbits: General public-key related Functions. + (line 24) +* gcry_pk_get_nbits_t: Public key modules. (line 116) +* gcry_pk_list: Public key modules. (line 131) +* gcry_pk_map_name: General public-key related Functions. + (line 16) +* gcry_pk_register: Public key modules. (line 121) +* gcry_pk_sign: Cryptographic Functions. + (line 117) +* gcry_pk_sign_t: Public key modules. (line 106) +* gcry_pk_spec_t: Public key modules. (line 12) +* gcry_pk_test_algo: General public-key related Functions. + (line 20) +* gcry_pk_testkey: General public-key related Functions. + (line 40) +* gcry_pk_unregister: Public key modules. (line 127) +* gcry_pk_verify: Cryptographic Functions. + (line 170) +* gcry_pk_verify_t: Public key modules. (line 111) +* gcry_prime_check: Checking. (line 8) +* gcry_prime_generate: Generation. (line 10) +* gcry_prime_group_generator: Generation. (line 19) +* gcry_prime_release_factors: Generation. (line 25) +* gcry_random_bytes: Retrieving random numbers. + (line 13) +* gcry_random_bytes_secure: Retrieving random numbers. + (line 19) +* gcry_random_level_t: Quality of random numbers. + (line 9) +* gcry_randomize: Retrieving random numbers. + (line 8) +* gcry_realloc: Memory allocation. (line 24) +* gcry_set_allocation_handler: Allocation handler. (line 34) +* gcry_set_fatalerror_handler: Error handler. (line 32) +* gcry_set_log_handler: Logging handler. (line 12) +* gcry_set_outofcore_handler: Error handler. (line 16) +* gcry_set_progress_handler: Progress handler. (line 21) +* gcry_sexp_build: Working with S-expressions. + (line 43) +* gcry_sexp_canon_len: Working with S-expressions. + (line 116) +* gcry_sexp_car: Working with S-expressions. + (line 146) +* gcry_sexp_cdr: Working with S-expressions. + (line 151) +* gcry_sexp_create: Working with S-expressions. + (line 26) +* gcry_sexp_dump: Working with S-expressions. + (line 107) +* gcry_sexp_find_token: Working with S-expressions. + (line 129) +* gcry_sexp_length: Working with S-expressions. + (line 136) +* gcry_sexp_new: Working with S-expressions. + (line 13) +* gcry_sexp_nth: Working with S-expressions. + (line 141) +* gcry_sexp_nth_data: Working with S-expressions. + (line 159) +* gcry_sexp_nth_mpi: Working with S-expressions. + (line 184) +* gcry_sexp_nth_string: Working with S-expressions. + (line 176) +* gcry_sexp_release: Working with S-expressions. + (line 76) +* gcry_sexp_sprint: Working with S-expressions. + (line 84) +* gcry_sexp_sscan: Working with S-expressions. + (line 37) +* gcry_sexp_t: Data types for S-expressions. + (line 7) +* gcry_strerror: Error Strings. (line 7) +* gcry_strsource: Error Strings. (line 13) + + + +Tag Table: +Node: Top773 +Node: Introduction2990 +Node: Getting Started3362 +Node: Features4243 +Node: Overview5027 +Node: Preparation5658 +Node: Header6515 +Node: Building sources7585 +Node: Building sources using Automake9499 +Node: Initializing the library10681 +Ref: sample-use-suspend-secmem13856 +Ref: sample-use-resume-secmem14476 +Node: Multi-Threading15372 +Ref: Multi-Threading-Footnote-119385 +Node: Enabling FIPS mode19793 +Node: Generalities21659 +Node: Controlling the library21984 +Node: Modules34151 +Node: Error Handling34930 +Node: Error Values37453 +Node: Error Sources42393 +Node: Error Codes44664 +Node: Error Strings48149 +Node: Handler Functions49332 +Node: Progress handler49891 +Node: Allocation handler51887 +Node: Error handler53438 +Node: Logging handler55005 +Node: Symmetric cryptography55597 +Node: Available ciphers56402 +Node: Cipher modules58909 +Node: Available cipher modes63433 +Node: Working with cipher handles64312 +Node: General cipher functions72515 +Node: Public Key cryptography75033 +Node: Available algorithms75948 +Node: Used S-expressions76297 +Node: RSA key parameters77409 +Node: DSA key parameters78684 +Node: ECC key parameters79342 +Node: Public key modules81107 +Node: Cryptographic Functions86691 +Node: General public-key related Functions94178 +Node: AC Interface106467 +Node: Available asymmetric algorithms107602 +Node: Working with sets of data108271 +Node: Working with IO objects112773 +Node: Working with handles115493 +Node: Working with keys116440 +Node: Using cryptographic functions120522 +Node: Handle-independent functions127429 +Node: Hashing128177 +Node: Available hash algorithms128968 +Node: Hash algorithm modules131205 +Node: Working with hash algorithms135053 +Node: Random Numbers146257 +Node: Quality of random numbers146531 +Node: Retrieving random numbers147215 +Node: S-expressions148699 +Node: Data types for S-expressions149341 +Node: Working with S-expressions149665 +Node: MPI library158598 +Node: Data types159556 +Node: Basic functions159750 +Node: MPI formats161818 +Node: Calculations164701 +Node: Comparisons166955 +Node: Bit manipulations167599 +Node: Miscellaneous168914 +Node: Prime numbers170883 +Node: Generation171153 +Node: Checking172437 +Node: Utilities172850 +Node: Memory allocation173043 +Node: Architecture174304 +Ref: fig:subsystems175824 +Ref: Architecture-Footnote-1176909 +Ref: Architecture-Footnote-2176971 +Node: Public-Key Subsystem Architecture177055 +Node: Symmetric Encryption Subsystem Architecture179996 +Node: Hashing and MACing Subsystem Architecture181443 +Node: Multi-Precision-Integer Subsystem Architecture183367 +Node: Prime-Number-Generator Subsystem Architecture184808 +Ref: Prime-Number-Generator Subsystem Architecture-Footnote-1186739 +Node: Random-Number Subsystem Architecture187026 +Node: CSPRNG Description189515 +Ref: CSPRNG Description-Footnote-1191077 +Node: FIPS PRNG Description191200 +Node: Self-Tests193335 +Node: FIPS Mode205019 +Ref: fig:fips-fsm208999 +Ref: tbl:fips-states209101 +Ref: tbl:fips-state-transitions210354 +Node: Library Copying213968 +Node: Copying242086 +Node: Figures and Tables261260 +Node: Concept Index261670 +Node: Function and Data Index267235 + +End Tag Table diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi new file mode 100644 index 0000000..e328994 --- /dev/null +++ b/doc/gcrypt.texi @@ -0,0 +1,5844 @@ +\input texinfo @c -*- Texinfo -*- +@c %**start of header +@setfilename gcrypt.info +@include version.texi +@settitle The Libgcrypt Reference Manual +@c Unify some of the indices. +@syncodeindex tp fn +@syncodeindex pg fn +@c %**end of header +@copying +This manual is for Libgcrypt +(version @value{VERSION}, @value{UPDATED}), +which is GNU's library of cryptographic building blocks. + +Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. The text of the license can be found in the +section entitled ``GNU General Public License''. +@end quotation +@end copying + +@dircategory GNU Libraries +@direntry +* libgcrypt: (gcrypt). Cryptographic function library. +@end direntry + + + +@c +@c Titlepage +@c +@setchapternewpage odd +@titlepage +@title The Libgcrypt Reference Manual +@subtitle Version @value{VERSION} +@subtitle @value{UPDATED} +@author Werner Koch (@email{wk@@gnupg.org}) +@author Moritz Schulte (@email{mo@@g10code.com}) + +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@ifnothtml +@summarycontents +@contents +@page +@end ifnothtml + + +@ifnottex +@node Top +@top The Libgcrypt Library +@insertcopying +@end ifnottex + + +@menu +* Introduction:: What is Libgcrypt. +* Preparation:: What you should do before using the library. +* Generalities:: General library functions and data types. +* Handler Functions:: Working with handler functions. +* Symmetric cryptography:: How to use symmetric cryptography. +* Public Key cryptography:: How to use public key cryptography. +* Hashing:: How to use hash and MAC algorithms. +* Random Numbers:: How to work with random numbers. +* S-expressions:: How to manage S-expressions. +* MPI library:: How to work with multi-precision-integers. +* Prime numbers:: How to use the Prime number related functions. +* Utilities:: Utility functions. +* Architecture:: How Libgcrypt works internally. + +Appendices + +* Self-Tests:: Description of the self-tests. +* FIPS Mode:: Description of the FIPS mode. +* Library Copying:: The GNU Lesser General Public License + says how you can copy and share Libgcrypt. +* Copying:: The GNU General Public License says how you + can copy and share some parts of Libgcrypt. + +Indices + +* Figures and Tables:: Index of figures and tables. +* Concept Index:: Index of concepts and programs. +* Function and Data Index:: Index of functions, variables and data types. + +@end menu + +@ifhtml +@page +@summarycontents +@contents +@end ifhtml + + +@c ********************************************************** +@c ******************* Introduction *********************** +@c ********************************************************** +@node Introduction +@chapter Introduction + +Libgcrypt is a library providing cryptographic building blocks. + +@menu +* Getting Started:: How to use this manual. +* Features:: A glance at Libgcrypt's features. +* Overview:: Overview about the library. +@end menu + +@node Getting Started +@section Getting Started + +This manual documents the Libgcrypt library application programming +interface (API). All functions and data types provided by the library +are explained. + +@noindent +The reader is assumed to possess basic knowledge about applied +cryptography. + +This manual can be used in several ways. If read from the beginning +to the end, it gives a good introduction into the library and how it +can be used in an application. Forward references are included where +necessary. Later on, the manual can be used as a reference manual to +get just the information needed about any particular interface of the +library. Experienced programmers might want to start looking at the +examples at the end of the manual, and then only read up those parts +of the interface which are unclear. + + +@node Features +@section Features + +Libgcrypt might have a couple of advantages over other libraries doing +a similar job. + +@table @asis +@item It's Free Software +Anybody can use, modify, and redistribute it under the terms of the GNU +Lesser General Public License (@pxref{Library Copying}). Note, that +some parts (which are in general not needed by applications) are subject +to the terms of the GNU General Public License (@pxref{Copying}); please +see the README file of the distribution for of list of these parts. + +@item It encapsulates the low level cryptography +Libgcrypt provides a high level interface to cryptographic +building blocks using an extensible and flexible API. + +@end table + +@node Overview +@section Overview + +@noindent +The Libgcrypt library is fully thread-safe, where it makes +sense to be thread-safe. Not thread-safe are some cryptographic +functions that modify a certain context stored in handles. If the +user really intents to use such functions from different threads on +the same handle, he has to take care of the serialization of such +functions himself. If not described otherwise, every function is +thread-safe. + +Libgcrypt depends on the library `libgpg-error', which +contains common error handling related code for GnuPG components. + +@c ********************************************************** +@c ******************* Preparation ************************ +@c ********************************************************** +@node Preparation +@chapter Preparation + +To use Libgcrypt, you have to perform some changes to your +sources and the build system. The necessary changes are small and +explained in the following sections. At the end of this chapter, it +is described how the library is initialized, and how the requirements +of the library are verified. + +@menu +* Header:: What header file you need to include. +* Building sources:: How to build sources using the library. +* Building sources using Automake:: How to build sources with the help of Automake. +* Initializing the library:: How to initialize the library. +* Multi-Threading:: How Libgcrypt can be used in a MT environment. +* Enabling FIPS mode:: How to enable the FIPS mode. +@end menu + + +@node Header +@section Header + +All interfaces (data types and functions) of the library are defined +in the header file @file{gcrypt.h}. You must include this in all source +files using the library, either directly or through some other header +file, like this: + +@example +#include +@end example + +The name space of Libgcrypt is @code{gcry_*} for function +and type names and @code{GCRY*} for other symbols. In addition the +same name prefixes with one prepended underscore are reserved for +internal use and should never be used by an application. Note that +Libgcrypt uses libgpg-error, which uses @code{gpg_*} as +name space for function and type names and @code{GPG_*} for other +symbols, including all the error codes. + +@noindent +Certain parts of gcrypt.h may be excluded by defining these macros: + +@table @code +@item GCRYPT_NO_MPI_MACROS +Do not define the shorthand macros @code{mpi_*} for @code{gcry_mpi_*}. + +@item GCRYPT_NO_DEPRECATED +Do not include defintions for deprecated features. This is useful to +make sure that no deprecated features are used. +@end table + +@node Building sources +@section Building sources + +If you want to compile a source file including the `gcrypt.h' header +file, you must make sure that the compiler can find it in the +directory hierarchy. This is accomplished by adding the path to the +directory in which the header file is located to the compilers include +file search path (via the @option{-I} option). + +However, the path to the include file is determined at the time the +source is configured. To solve this problem, Libgcrypt ships with a small +helper program @command{libgcrypt-config} that knows the path to the +include file and other configuration options. The options that need +to be added to the compiler invocation at compile time are output by +the @option{--cflags} option to @command{libgcrypt-config}. The following +example shows how it can be used at the command line: + +@example +gcc -c foo.c `libgcrypt-config --cflags` +@end example + +Adding the output of @samp{libgcrypt-config --cflags} to the compilers +command line will ensure that the compiler can find the Libgcrypt header +file. + +A similar problem occurs when linking the program with the library. +Again, the compiler has to find the library files. For this to work, +the path to the library files has to be added to the library search path +(via the @option{-L} option). For this, the option @option{--libs} to +@command{libgcrypt-config} can be used. For convenience, this option +also outputs all other options that are required to link the program +with the Libgcrypt libraries (in particular, the @samp{-lgcrypt} +option). The example shows how to link @file{foo.o} with the Libgcrypt +library to a program @command{foo}. + +@example +gcc -o foo foo.o `libgcrypt-config --libs` +@end example + +Of course you can also combine both examples to a single command by +specifying both options to @command{libgcrypt-config}: + +@example +gcc -o foo foo.c `libgcrypt-config --cflags --libs` +@end example + +@node Building sources using Automake +@section Building sources using Automake + +It is much easier if you use GNU Automake instead of writing your own +Makefiles. If you do that, you do not have to worry about finding and +invoking the @command{libgcrypt-config} script at all. +Libgcrypt provides an extension to Automake that does all +the work for you. + +@c A simple macro for optional variables. +@macro ovar{varname} +@r{[}@var{\varname\}@r{]} +@end macro +@defmac AM_PATH_LIBGCRYPT (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found}) +Check whether Libgcrypt (at least version +@var{minimum-version}, if given) exists on the host system. If it is +found, execute @var{action-if-found}, otherwise do +@var{action-if-not-found}, if given. + +Additionally, the function defines @code{LIBGCRYPT_CFLAGS} to the +flags needed for compilation of the program to find the +@file{gcrypt.h} header file, and @code{LIBGCRYPT_LIBS} to the linker +flags needed to link the program to the Libgcrypt library. +@end defmac + +You can use the defined Autoconf variables like this in your +@file{Makefile.am}: + +@example +AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) +LDADD = $(LIBGCRYPT_LIBS) +@end example + +@node Initializing the library +@section Initializing the library + +Before the library can be used, it must initialize itself. This is +achieved by invoking the function @code{gcry_check_version} described +below. + +Also, it is often desirable to check that the version of +Libgcrypt used is indeed one which fits all requirements. +Even with binary compatibility, new features may have been introduced, +but due to problem with the dynamic linker an old version may actually +be used. So you may want to check that the version is okay right +after program startup. + +@deftypefun {const char *} gcry_check_version (const char *@var{req_version}) + +The function @code{gcry_check_version} initializes some subsystems used +by Libgcrypt and must be invoked before any other function in the +library, with the exception of the @code{GCRYCTL_SET_THREAD_CBS} command +(called via the @code{gcry_control} function). +@xref{Multi-Threading}. + +Furthermore, this function returns the version number of the library. +It can also verify that the version number is higher than a certain +required version number @var{req_version}, if this value is not a null +pointer. +@end deftypefun + +Libgcrypt uses a concept known as secure memory, which is a region of +memory set aside for storing sensitive data. Because such memory is a +scarce resource, it needs to be setup in advanced to a fixed size. +Further, most operating systems have special requirements on how that +secure memory can be used. For example, it might be required to install +an application as ``setuid(root)'' to allow allocating such memory. +Libgcrypt requires a sequence of initialization steps to make sure that +this works correctly. The following examples show the necessary steps. + +If you don't have a need for secure memory, for example if your +application does not use secret keys or other confidential data or it +runs in a controlled environment where key material floating around in +memory is not a problem, you should initialize Libgcrypt this way: + +@example + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) + @{ + fputs ("libgcrypt version mismatch\n", stderr); + exit (2); + @} + + /* Disable secure memory. */ + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); +@end example + + +If you have to protect your keys or other information in memory against +being swapped out to disk and to enable an automatic overwrite of used +and freed memory, you need to initialize Libgcrypt this way: + +@example + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) + @{ + fputs ("libgcrypt version mismatch\n", stderr); + exit (2); + @} + +@anchor{sample-use-suspend-secmem} + /* We don't want to see any warnings, e.g. because we have not yet + parsed program options which might be used to suppress such + warnings. */ + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + + /* ... If required, other initialization goes here. Note that the + process might still be running with increased privileges and that + the secure memory has not been intialized. */ + + /* Allocate a pool of 16k secure memory. This make the secure memory + available and also drops privileges where needed. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + +@anchor{sample-use-resume-secmem} + /* It is now okay to let Libgcrypt complain when there was/is + a problem with the secure memory. */ + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); +@end example + +It is important that these initialization steps are not done by a +library but by the actual application. A library using Libgcrypt might +want to check for finished initialization using: + +@example + if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) + @{ + fputs ("libgcrypt has not been initialized\n", stderr); + abort (); + @} +@end example + +Instead of terminating the process, the library may instead print a +warning and try to initialize Libgcrypt itself. See also the section on +multi-threading below for more pitfalls. + + + +@node Multi-Threading +@section Multi-Threading + +As mentioned earlier, the Libgcrypt library is +thread-safe if you adhere to the following requirements: + +@itemize @bullet +@item +If your application is multi-threaded, you must set the thread support +callbacks with the @code{GCRYCTL_SET_THREAD_CBS} command +@strong{before} any other function in the library. + +This is easy enough if you are indeed writing an application using +Libgcrypt. It is rather problematic if you are writing a library +instead. Here are some tips what to do if you are writing a library: + +If your library requires a certain thread package, just initialize +Libgcrypt to use this thread package. If your library supports multiple +thread packages, but needs to be configured, you will have to +implement a way to determine which thread package the application +wants to use with your library anyway. Then configure Libgcrypt to use +this thread package. + +If your library is fully reentrant without any special support by a +thread package, then you are lucky indeed. Unfortunately, this does +not relieve you from doing either of the two above, or use a third +option. The third option is to let the application initialize Libgcrypt +for you. Then you are not using Libgcrypt transparently, though. + +As if this was not difficult enough, a conflict may arise if two +libraries try to initialize Libgcrypt independently of each others, and +both such libraries are then linked into the same application. To +make it a bit simpler for you, this will probably work, but only if +both libraries have the same requirement for the thread package. This +is currently only supported for the non-threaded case, GNU Pth and +pthread. Support for more thread packages is easy to add, so contact +us if you require it. + +@item +The function @code{gcry_check_version} must be called before any other +function in the library, except the @code{GCRYCTL_SET_THREAD_CBS} +command (called via the @code{gcry_control} function), because it +initializes the thread support subsystem in Libgcrypt. To +achieve this in multi-threaded programs, you must synchronize the +memory with respect to other threads that also want to use +Libgcrypt. For this, it is sufficient to call +@code{gcry_check_version} before creating the other threads using +Libgcrypt@footnote{At least this is true for POSIX threads, +as @code{pthread_create} is a function that synchronizes memory with +respects to other threads. There are many functions which have this +property, a complete list can be found in POSIX, IEEE Std 1003.1-2003, +Base Definitions, Issue 6, in the definition of the term ``Memory +Synchronization''. For other thread packages, more relaxed or more +strict rules may apply.}. + +@item +Just like the function @code{gpg_strerror}, the function +@code{gcry_strerror} is not thread safe. You have to use +@code{gpg_strerror_r} instead. + +@end itemize + + +Libgcrypt contains convenient macros, which define the +necessary thread callbacks for PThread and for GNU Pth: + +@table @code +@item GCRY_THREAD_OPTION_PTH_IMPL + +This macro defines the following (static) symbols: +@code{gcry_pth_init}, @code{gcry_pth_mutex_init}, +@code{gcry_pth_mutex_destroy}, @code{gcry_pth_mutex_lock}, +@code{gcry_pth_mutex_unlock}, @code{gcry_pth_read}, +@code{gcry_pth_write}, @code{gcry_pth_select}, +@code{gcry_pth_waitpid}, @code{gcry_pth_accept}, +@code{gcry_pth_connect}, @code{gcry_threads_pth}. + +After including this macro, @code{gcry_control()} shall be used with a +command of @code{GCRYCTL_SET_THREAD_CBS} in order to register the +thread callback structure named ``gcry_threads_pth''. + +@item GCRY_THREAD_OPTION_PTHREAD_IMPL + +This macro defines the following (static) symbols: +@code{gcry_pthread_mutex_init}, @code{gcry_pthread_mutex_destroy}, +@code{gcry_pthread_mutex_lock}, @code{gcry_pthread_mutex_unlock}, +@code{gcry_threads_pthread}. + +After including this macro, @code{gcry_control()} shall be used with a +command of @code{GCRYCTL_SET_THREAD_CBS} in order to register the +thread callback structure named ``gcry_threads_pthread''. +@end table + +Note that these macros need to be terminated with a semicolon. Keep +in mind that these are convenient macros for C programmers; C++ +programmers might have to wrap these macros in an ``extern C'' body. + + +@node Enabling FIPS mode +@section How to enable the FIPS mode +@cindex FIPS mode +@cindex FIPS 140 + +Libgcrypt may be used in a FIPS 140-2 mode. Note, that this does not +necessary mean that Libcgrypt is an appoved FIPS 140-2 module. Check the +NIST database at @url{http://csrc.nist.gov/groups/STM/cmvp/} to see what +versions of Libgcrypt are approved. + +Because FIPS 140 has certain restrictions on the use of cryptography +which are not always wanted, Libgcrypt needs to be put into FIPS mode +explicitly. Three alternative mechanisms are provided to switch +Libgcrypt into this mode: + +@itemize +@item +If the file @file{/proc/sys/crypto/fips_enabled} exists and contains a +numeric value other than @code{0}, Libgcrypt is put into FIPS mode at +initialization time. Obviously this works only on systems with a +@code{proc} file system (i.e. GNU/Linux). + +@item +If the file @file{/etc/gcrypt/fips_enabled} exists, Libgcrypt is put +into FIPS mode at initialization time. Note that this filename is +hardwired and does not depend on any configuration options. + +@item +If the application requests FIPS mode using the control command +@code{GCRYCTL_FORCE_FIPS_MODE}. This must be done prior to any +initialization (i.e. before @code{gcry_check_version}). + +@end itemize + +@cindex Enforced FIPS mode + +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 +@file{/etc/gcrypt/fips_enabled}. 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 +switch back to standard mode without terminating the process first. +If the logging verbosity level of Libgcrypt has been set to at least +2, the state transitions and the self-tests are logged. + + + +@c ********************************************************** +@c ******************* General **************************** +@c ********************************************************** +@node Generalities +@chapter Generalities + +@menu +* Controlling the library:: Controlling Libgcrypt's behavior. +* Modules:: Description of extension modules. +* Error Handling:: Error codes and such. +@end menu + +@node Controlling the library +@section Controlling the library + +@deftypefun gcry_error_t gcry_control (enum gcry_ctl_cmds @var{cmd}, ...) + +This function can be used to influence the general behavior of +Libgcrypt in several ways. Depending on @var{cmd}, more +arguments can or have to be provided. + +@table @code +@item GCRYCTL_ENABLE_M_GUARD; Arguments: none +This command enables the built-in memory guard. It must not be used to +activate the memory guard after the memory management has already been +used; therefore it can ONLY be used at initialization time. Note that +the memory guard is NOT used when the user of the library has set his +own memory management callbacks. + +@item GCRYCTL_ENABLE_QUICK_RANDOM; Arguments: none +This command inhibits the use the very secure random quality level +(@code{GCRY_VERY_STRONG_RANDOM}) and degrades all request down to +@code{GCRY_STRONG_RANDOM}. In general this is not recommened. However, +for some applications the extra quality random Libgcrypt tries to create +is not justified and this option may help to get better performace. +Please check with a crypto expert whether this option can be used for +your application. + +This option can only be used at initialization time. + + +@item GCRYCTL_DUMP_RANDOM_STATS; Arguments: none +This command dumps randum number generator related statistics to the +library's logging stream. + +@item GCRYCTL_DUMP_MEMORY_STATS; Arguments: none +This command dumps memory managment related statistics to the library's +logging stream. + +@item GCRYCTL_DUMP_SECMEM_STATS; Arguments: none +This command dumps secure memory manamgent related statistics to the +library's logging stream. + +@item GCRYCTL_DROP_PRIVS; Arguments: none +This command disables the use of secure memory and drops the priviliges +of the current process. This command has not much use; the suggested way +to disable secure memory is to use @code{GCRYCTL_DISABLE_SECMEM} right +after initialization. + +@item GCRYCTL_DISABLE_SECMEM; Arguments: none +This command disables the use of secure memory. If this command is +used in FIPS mode, FIPS mode will be disabled and the function +@code{gcry_fips_mode_active} returns false. However, in Enforced FIPS +mode this command has no effect at all. + +Many applications do not require secure memory, so they should disable +it right away. This command should be executed right after +@code{gcry_check_version}. + +@item GCRYCTL_INIT_SECMEM; Arguments: int nbytes +This command is used to allocate a pool of secure memory and thus +enabling the use of secure memory. It also drops all extra privileges +the process has (i.e. if it is run as setuid (root)). If the argument +@var{nbytes} is 0, secure memory will be disabled. The minimum amount +of secure memory allocated is currently 16384 bytes; you may thus use a +value of 1 to request that default size. + +@item GCRYCTL_TERM_SECMEM; Arguments: none +This command zeroises the secure memory and destroys the handler. The +secure memory pool may not be used anymore after running this command. +If the secure memory pool as already been destroyed, this command has +no effect. Applications might want to run this command from their +exit handler to make sure that the secure memory gets properly +destroyed. This command is not necessarily thread-safe but that +should not be needed in cleanup code. It may be called from a signal +handler. + +@item GCRYCTL_DISABLE_SECMEM_WARN; Arguments: none +Disable warning messages about problems with the secure memory +subsystem. This command should be run right after +@code{gcry_check_version}. + +@item GCRYCTL_SUSPEND_SECMEM_WARN; Arguments: none +Postpone warning messages from the secure memory subsystem. +@xref{sample-use-suspend-secmem,,the initialization example}, on how to +use it. + +@item GCRYCTL_RESUME_SECMEM_WARN; Arguments: none +Resume warning messages from the secure memory subsystem. +@xref{sample-use-resume-secmem,,the initialization example}, on how to +use it. + +@item GCRYCTL_USE_SECURE_RNDPOOL; Arguments: none +This command tells the PRNG to store random numbers in secure memory. +This command should be run right after @code{gcry_check_version} and not +later than the command GCRYCTL_INIT_SECMEM. Note that in FIPS mode the +secure memory is always used. + +@item GCRYCTL_SET_RANDOM_SEED_FILE; Arguments: const char *filename +This command specifies the file, which is to be used as seed file for +the PRNG. If the seed file is registered prior to initialization of the +PRNG, the seed file's content (if it exists and seems to be valid) is +fed into the PRNG pool. After the seed file has been registered, the +PRNG can be signalled to write out the PRNG pool's content into the seed +file with the following command. + + +@item GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none +Write out the PRNG pool's content into the registered seed file. + +Multiple instances of the applications sharing the same random seed file +can be started in parallel, in which case they will read out the same +pool and then race for updating it (the last update overwrites earlier +updates). They will differentiate only by the weak entropy that is +added in read_seed_file based on the PID and clock, and up to 16 bytes +of weak random non-blockingly. The consequence is that the output of +these different instances is correlated to some extent. In a perfect +attack scenario, the attacker can control (or at least guess) the PID +and clock of the application, and drain the system's entropy pool to +reduce the "up to 16 bytes" above to 0. Then the dependencies of the +inital states of the pools are completely known. Note that this is not +an issue if random of @code{GCRY_VERY_STRONG_RANDOM} quality is +requested as in this case enough extra entropy gets mixed. It is also +not an issue when using Linux (rndlinux driver), because this one +guarantees to read full 16 bytes from /dev/urandom and thus there is no +way for an attacker without kernel access to control these 16 bytes. + +@item GCRYCTL_SET_VERBOSITY; Arguments: int level +This command sets the verbosity of the logging. A level of 0 disables +all extra logging whereas positive numbers enable more verbose logging. +The level may be changed at any time but be aware that no memory +synchronization is done so the effect of this command might not +immediately show up in other threads. This command may even be used +prior to @code{gcry_check_version}. + +@item GCRYCTL_SET_DEBUG_FLAGS; Arguments: unsigned int flags +Set the debug flag bits as given by the argument. Be aware that that no +memory synchronization is done so the effect of this command might not +immediately show up in other threads. The debug flags are not +considered part of the API and thus may change without notice. As of +now bit 0 enables debugging of cipher functions and bit 1 debugging of +multi-precision-integers. This command may even be used prior to +@code{gcry_check_version}. + +@item GCRYCTL_CLEAR_DEBUG_FLAGS; Arguments: unsigned int flags +Set the debug flag bits as given by the argument. Be aware that that no +memory synchronization is done so the effect of this command might not +immediately show up in other threads. This command may even be used +prior to @code{gcry_check_version}. + +@item GCRYCTL_DISABLE_INTERNAL_LOCKING; Arguments: none +This command does nothing. It exists only for backward compatibility. + +@item GCRYCTL_ANY_INITIALIZATION_P; Arguments: none +This command returns true if the library has been basically initialized. +Such a basic initialization happens implicitly with many commands to get +certain internal subsystems running. The common and suggested way to +do this basic intialization is by calling gcry_check_version. + +@item GCRYCTL_INITIALIZATION_FINISHED; Arguments: none +This command tells the libray that the application has finished the +intialization. + +@item GCRYCTL_INITIALIZATION_FINISHED_P; Arguments: none +This command returns true if the command@* +GCRYCTL_INITIALIZATION_FINISHED has already been run. + +@item GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops +This command registers a thread-callback structure. +@xref{Multi-Threading}. + +@item GCRYCTL_FAST_POLL; Arguments: none +Run a fast random poll. + +@item GCRYCTL_SET_RNDEGD_SOCKET; Arguments: const char *filename +This command may be used to override the default name of the EGD socket +to connect to. It may be used only during initialization as it is not +thread safe. Changing the socket name again is not supported. The +function may return an error if the given filename is too long for a +local socket name. + +EGD is an alternative random gatherer, used only on systems lacking a +proper random device. + +@item GCRYCTL_PRINT_CONFIG; Arguments: FILE *stream +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. + +@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. + +@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 +the convenience macro below to check whether FIPS mode is actually +active. + +@deftypefun int gcry_fips_mode_active (void) + +Returns true if the FIPS mode is active. Note that this is +implemented as a macro. +@end deftypefun + + + +@item GCRYCTL_FORCE_FIPS_MODE; Arguments: none +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 +application switch the library into FIPS mode. Note that Libgcrypt will +reject an attempt to switch to 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 +success or an error code on failure. + + +@end table + +@end deftypefun + +@node Modules +@section Modules + +Libgcrypt supports the use of `extension modules', which +implement algorithms in addition to those already built into the library +directly. + +@deftp {Data type} gcry_module_t +This data type represents a `module'. +@end deftp + +Functions registering modules provided by the user take a `module +specification structure' as input and return a value of +@code{gcry_module_t} and an ID that is unique in the modules' +category. This ID can be used to reference the newly registered +module. After registering a module successfully, the new functionality +should be able to be used through the normal functions provided by +Libgcrypt until it is unregistered again. + +@c ********************************************************** +@c ******************* Errors **************************** +@c ********************************************************** +@node Error Handling +@section Error Handling + +Many functions in Libgcrypt can return an error if they +fail. For this reason, the application should always catch the error +condition and take appropriate measures, for example by releasing the +resources and passing the error up to the caller, or by displaying a +descriptive message to the user and cancelling the operation. + +Some error values do not indicate a system error or an error in the +operation, but the result of an operation that failed properly. For +example, if you try to decrypt a tempered message, the decryption will +fail. Another error value actually means that the end of a data +buffer or list has been reached. The following descriptions explain +for many error codes what they mean usually. Some error values have +specific meanings if returned by a certain functions. Such cases are +described in the documentation of those functions. + +Libgcrypt uses the @code{libgpg-error} library. This allows to share +the error codes with other components of the GnuPG system, and to pass +error values transparently from the crypto engine, or some helper +application of the crypto engine, to the user. This way no +information is lost. As a consequence, Libgcrypt does not use its own +identifiers for error codes, but uses those provided by +@code{libgpg-error}. They usually start with @code{GPG_ERR_}. + +However, Libgcrypt does provide aliases for the functions +defined in libgpg-error, which might be preferred for name space +consistency. + + +Most functions in Libgcrypt return an error code in the case +of failure. For this reason, the application should always catch the +error condition and take appropriate measures, for example by +releasing the resources and passing the error up to the caller, or by +displaying a descriptive message to the user and canceling the +operation. + +Some error values do not indicate a system error or an error in the +operation, but the result of an operation that failed properly. + +GnuPG components, including Libgcrypt, use an extra library named +libgpg-error to provide a common error handling scheme. For more +information on libgpg-error, see the according manual. + +@menu +* Error Values:: The error value and what it means. +* Error Sources:: A list of important error sources. +* Error Codes:: A list of important error codes. +* Error Strings:: How to get a descriptive string from a value. +@end menu + + +@node Error Values +@subsection Error Values +@cindex error values +@cindex error codes +@cindex error sources + +@deftp {Data type} {gcry_err_code_t} +The @code{gcry_err_code_t} type is an alias for the +@code{libgpg-error} type @code{gpg_err_code_t}. The error code +indicates the type of an error, or the reason why an operation failed. + +A list of important error codes can be found in the next section. +@end deftp + +@deftp {Data type} {gcry_err_source_t} +The @code{gcry_err_source_t} type is an alias for the +@code{libgpg-error} type @code{gpg_err_source_t}. The error source +has not a precisely defined meaning. Sometimes it is the place where +the error happened, sometimes it is the place where an error was +encoded into an error value. Usually the error source will give an +indication to where to look for the problem. This is not always true, +but it is attempted to achieve this goal. + +A list of important error sources can be found in the next section. +@end deftp + +@deftp {Data type} {gcry_error_t} +The @code{gcry_error_t} type is an alias for the @code{libgpg-error} +type @code{gpg_error_t}. An error value like this has always two +components, an error code and an error source. Both together form the +error value. + +Thus, the error value can not be directly compared against an error +code, but the accessor functions described below must be used. +However, it is guaranteed that only 0 is used to indicate success +(@code{GPG_ERR_NO_ERROR}), and that in this case all other parts of +the error value are set to 0, too. + +Note that in Libgcrypt, the error source is used purely for +diagnostic purposes. Only the error code should be checked to test +for a certain outcome of a function. The manual only documents the +error code part of an error value. The error source is left +unspecified and might be anything. +@end deftp + +@deftypefun {gcry_err_code_t} gcry_err_code (@w{gcry_error_t @var{err}}) +The static inline function @code{gcry_err_code} returns the +@code{gcry_err_code_t} component of the error value @var{err}. This +function must be used to extract the error code from an error value in +order to compare it with the @code{GPG_ERR_*} error code macros. +@end deftypefun + +@deftypefun {gcry_err_source_t} gcry_err_source (@w{gcry_error_t @var{err}}) +The static inline function @code{gcry_err_source} returns the +@code{gcry_err_source_t} component of the error value @var{err}. This +function must be used to extract the error source from an error value in +order to compare it with the @code{GPG_ERR_SOURCE_*} error source macros. +@end deftypefun + +@deftypefun {gcry_error_t} gcry_err_make (@w{gcry_err_source_t @var{source}}, @w{gcry_err_code_t @var{code}}) +The static inline function @code{gcry_err_make} returns the error +value consisting of the error source @var{source} and the error code +@var{code}. + +This function can be used in callback functions to construct an error +value to return it to the library. +@end deftypefun + +@deftypefun {gcry_error_t} gcry_error (@w{gcry_err_code_t @var{code}}) +The static inline function @code{gcry_error} returns the error value +consisting of the default error source and the error code @var{code}. + +For @acronym{GCRY} applications, the default error source is +@code{GPG_ERR_SOURCE_USER_1}. You can define +@code{GCRY_ERR_SOURCE_DEFAULT} before including @file{gcrypt.h} to +change this default. + +This function can be used in callback functions to construct an error +value to return it to the library. +@end deftypefun + +The @code{libgpg-error} library provides error codes for all system +error numbers it knows about. If @var{err} is an unknown error +number, the error code @code{GPG_ERR_UNKNOWN_ERRNO} is used. The +following functions can be used to construct error values from system +errno numbers. + +@deftypefun {gcry_error_t} gcry_err_make_from_errno (@w{gcry_err_source_t @var{source}}, @w{int @var{err}}) +The function @code{gcry_err_make_from_errno} is like +@code{gcry_err_make}, but it takes a system error like @code{errno} +instead of a @code{gcry_err_code_t} error code. +@end deftypefun + +@deftypefun {gcry_error_t} gcry_error_from_errno (@w{int @var{err}}) +The function @code{gcry_error_from_errno} is like @code{gcry_error}, +but it takes a system error like @code{errno} instead of a +@code{gcry_err_code_t} error code. +@end deftypefun + +Sometimes you might want to map system error numbers to error codes +directly, or map an error code representing a system error back to the +system error number. The following functions can be used to do that. + +@deftypefun {gcry_err_code_t} gcry_err_code_from_errno (@w{int @var{err}}) +The function @code{gcry_err_code_from_errno} returns the error code +for the system error @var{err}. If @var{err} is not a known system +error, the function returns @code{GPG_ERR_UNKNOWN_ERRNO}. +@end deftypefun + +@deftypefun {int} gcry_err_code_to_errno (@w{gcry_err_code_t @var{err}}) +The function @code{gcry_err_code_to_errno} returns the system error +for the error code @var{err}. If @var{err} is not an error code +representing a system error, or if this system error is not defined on +this system, the function returns @code{0}. +@end deftypefun + + +@node Error Sources +@subsection Error Sources +@cindex error codes, list of + +The library @code{libgpg-error} defines an error source for every +component of the GnuPG system. The error source part of an error +value is not well defined. As such it is mainly useful to improve the +diagnostic error message for the user. + +If the error code part of an error value is @code{0}, the whole error +value will be @code{0}. In this case the error source part is of +course @code{GPG_ERR_SOURCE_UNKNOWN}. + +The list of error sources that might occur in applications using +@acronym{Libgcrypt} is: + +@table @code +@item GPG_ERR_SOURCE_UNKNOWN +The error source is not known. The value of this error source is +@code{0}. + +@item GPG_ERR_SOURCE_GPGME +The error source is @acronym{GPGME} itself. + +@item GPG_ERR_SOURCE_GPG +The error source is GnuPG, which is the crypto engine used for the +OpenPGP protocol. + +@item GPG_ERR_SOURCE_GPGSM +The error source is GPGSM, which is the crypto engine used for the +OpenPGP protocol. + +@item GPG_ERR_SOURCE_GCRYPT +The error source is @code{libgcrypt}, which is used by crypto engines +to perform cryptographic operations. + +@item GPG_ERR_SOURCE_GPGAGENT +The error source is @command{gpg-agent}, which is used by crypto +engines to perform operations with the secret key. + +@item GPG_ERR_SOURCE_PINENTRY +The error source is @command{pinentry}, which is used by +@command{gpg-agent} to query the passphrase to unlock a secret key. + +@item GPG_ERR_SOURCE_SCD +The error source is the SmartCard Daemon, which is used by +@command{gpg-agent} to delegate operations with the secret key to a +SmartCard. + +@item GPG_ERR_SOURCE_KEYBOX +The error source is @code{libkbx}, a library used by the crypto +engines to manage local keyrings. + +@item GPG_ERR_SOURCE_USER_1 +@item GPG_ERR_SOURCE_USER_2 +@item GPG_ERR_SOURCE_USER_3 +@item GPG_ERR_SOURCE_USER_4 +These error sources are not used by any GnuPG component and can be +used by other software. For example, applications using +Libgcrypt can use them to mark error values coming from callback +handlers. Thus @code{GPG_ERR_SOURCE_USER_1} is the default for errors +created with @code{gcry_error} and @code{gcry_error_from_errno}, +unless you define @code{GCRY_ERR_SOURCE_DEFAULT} before including +@file{gcrypt.h}. +@end table + + +@node Error Codes +@subsection Error Codes +@cindex error codes, list of + +The library @code{libgpg-error} defines many error values. The +following list includes the most important error codes. + +@table @code +@item GPG_ERR_EOF +This value indicates the end of a list, buffer or file. + +@item GPG_ERR_NO_ERROR +This value indicates success. The value of this error code is +@code{0}. Also, it is guaranteed that an error value made from the +error code @code{0} will be @code{0} itself (as a whole). This means +that the error source information is lost for this error code, +however, as this error code indicates that no error occurred, this is +generally not a problem. + +@item GPG_ERR_GENERAL +This value means that something went wrong, but either there is not +enough information about the problem to return a more useful error +value, or there is no separate error value for this type of problem. + +@item GPG_ERR_ENOMEM +This value means that an out-of-memory condition occurred. + +@item GPG_ERR_E... +System errors are mapped to GPG_ERR_EFOO where FOO is the symbol for +the system error. + +@item GPG_ERR_INV_VALUE +This value means that some user provided data was out of range. + +@item GPG_ERR_UNUSABLE_PUBKEY +This value means that some recipients for a message were invalid. + +@item GPG_ERR_UNUSABLE_SECKEY +This value means that some signers were invalid. + +@item GPG_ERR_NO_DATA +This value means that data was expected where no data was found. + +@item GPG_ERR_CONFLICT +This value means that a conflict of some sort occurred. + +@item GPG_ERR_NOT_IMPLEMENTED +This value indicates that the specific function (or operation) is not +implemented. This error should never happen. It can only occur if +you use certain values or configuration options which do not work, +but for which we think that they should work at some later time. + +@item GPG_ERR_DECRYPT_FAILED +This value indicates that a decryption operation was unsuccessful. + +@item GPG_ERR_WRONG_KEY_USAGE +This value indicates that a key is not used appropriately. + +@item GPG_ERR_NO_SECKEY +This value indicates that no secret key for the user ID is available. + +@item GPG_ERR_UNSUPPORTED_ALGORITHM +This value means a verification failed because the cryptographic +algorithm is not supported by the crypto backend. + +@item GPG_ERR_BAD_SIGNATURE +This value means a verification failed because the signature is bad. + +@item GPG_ERR_NO_PUBKEY +This value means a verification failed because the public key is not +available. + +@item GPG_ERR_NOT_OPERATIONAL +This value means that the library is not yet in state which allows to +use this function. This error code is in particular returned if +Libgcrypt is operated in FIPS mode and the internal state of the +library does not yet or not anymore allow the use of a service. + +This error code is only available with newer libgpg-error versions, thus +you might see ``invalid error code'' when passing this to +@code{gpg_strerror}. The numeric value of this error code is 176. + +@item GPG_ERR_USER_1 +@item GPG_ERR_USER_2 +@item ... +@item GPG_ERR_USER_16 +These error codes are not used by any GnuPG component and can be +freely used by other software. Applications using Libgcrypt +might use them to mark specific errors returned by callback handlers +if no suitable error codes (including the system errors) for these +errors exist already. +@end table + + +@node Error Strings +@subsection Error Strings +@cindex error values, printing of +@cindex error codes, printing of +@cindex error sources, printing of +@cindex error strings + +@deftypefun {const char *} gcry_strerror (@w{gcry_error_t @var{err}}) +The function @code{gcry_strerror} returns a pointer to a statically +allocated string containing a description of the error code contained +in the error value @var{err}. This string can be used to output a +diagnostic message to the user. +@end deftypefun + + +@deftypefun {const char *} gcry_strsource (@w{gcry_error_t @var{err}}) +The function @code{gcry_strerror} returns a pointer to a statically +allocated string containing a description of the error source +contained in the error value @var{err}. This string can be used to +output a diagnostic message to the user. +@end deftypefun + +The following example illustrates the use of the functions described +above: + +@example +@{ + gcry_cipher_hd_t handle; + gcry_error_t err = 0; + + err = gcry_cipher_open (&handle, GCRY_CIPHER_AES, + GCRY_CIPHER_MODE_CBC, 0); + if (err) + @{ + fprintf (stderr, "Failure: %s/%s\n", + gcry_strsource (err), + gcry_strerror (err)); + @} +@} +@end example + +@c ********************************************************** +@c ******************* General **************************** +@c ********************************************************** +@node Handler Functions +@chapter Handler Functions + +Libgcrypt makes it possible to install so called `handler functions', +which get called by Libgcrypt in case of certain events. + +@menu +* Progress handler:: Using a progress handler function. +* Allocation handler:: Using special memory allocation functions. +* Error handler:: Using error handler functions. +* Logging handler:: Using a special logging function. +@end menu + +@node Progress handler +@section Progress handler + +It is often useful to retrieve some feedback while long running +operations are performed. + +@deftp {Data type} gcry_handler_progress_t +Progress handler functions have to be of the type +@code{gcry_handler_progress_t}, which is defined as: + +@code{void (*gcry_handler_progress_t) (void *, const char *, int, int, int)} +@end deftp + +The following function may be used to register a handler function for +this purpose. + +@deftypefun void gcry_set_progress_handler (gcry_handler_progress_t @var{cb}, void *@var{cb_data}) + +This function installs @var{cb} as the `Progress handler' function. +It may be used only during initialization. @var{cb} must be defined +as follows: + +@example +void +my_progress_handler (void *@var{cb_data}, const char *@var{what}, + int @var{printchar}, int @var{current}, int @var{total}) +@{ + /* Do something. */ +@} +@end example + +A description of the arguments of the progress handler function follows. + +@table @var +@item cb_data +The argument provided in the call to @code{gcry_set_progress_handler}. +@item what +A string identifying the type of the progress output. The following +values for @var{what} are defined: + +@table @code +@item need_entropy +Not enough entropy is available. @var{total} holds the number of +required bytes. + +@item primegen +Values for @var{printchar}: +@table @code +@item \n +Prime generated. +@item ! +Need to refresh the pool of prime numbers. +@item <, > +Number of bits adjusted. +@item ^ +Searching for a generator. +@item . +Fermat test on 10 candidates failed. +@item : +Restart with a new random value. +@item + +Rabin Miller test passed. +@end table + +@end table + +@end table +@end deftypefun + +@node Allocation handler +@section Allocation handler + +It is possible to make Libgcrypt use special memory +allocation functions instead of the built-in ones. + +Memory allocation functions are of the following types: +@deftp {Data type} gcry_handler_alloc_t +This type is defined as: @code{void *(*gcry_handler_alloc_t) (size_t n)}. +@end deftp +@deftp {Data type} gcry_handler_secure_check_t +This type is defined as: @code{int *(*gcry_handler_secure_check_t) (const void *)}. +@end deftp +@deftp {Data type} gcry_handler_realloc_t +This type is defined as: @code{void *(*gcry_handler_realloc_t) (void *p, size_t n)}. +@end deftp +@deftp {Data type} gcry_handler_free_t +This type is defined as: @code{void *(*gcry_handler_free_t) (void *)}. +@end deftp + +Special memory allocation functions can be installed with the +following function: + +@deftypefun void gcry_set_allocation_handler (gcry_handler_alloc_t @var{func_alloc}, gcry_handler_alloc_t @var{func_alloc_secure}, gcry_handler_secure_check_t @var{func_secure_check}, gcry_handler_realloc_t @var{func_realloc}, gcry_handler_free_t @var{func_free}) +Install the provided functions and use them instead of the built-in +functions for doing memory allocation. Using this function is in +general not recommended because the standard Libgcrypt allocation +functions are guaranteed to zeroize memory if needed. + +This function may be used only during initialization and may not be +used in fips mode. + + +@end deftypefun + +@node Error handler +@section Error handler + +The following functions may be used to register handler functions that +are called by Libgcrypt in case certain error conditions occur. They +may and should be registered prior to calling @code{gcry_check_version}. + +@deftp {Data type} gcry_handler_no_mem_t +This type is defined as: @code{int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int)} +@end deftp +@deftypefun void gcry_set_outofcore_handler (gcry_handler_no_mem_t @var{func_no_mem}, void *@var{cb_data}) +This function registers @var{func_no_mem} as `out-of-core handler', +which means that it will be called in the case of not having enough +memory available. The handler is called with 3 arguments: The first +one is the pointer @var{cb_data} as set with this function, the second +is the requested memory size and the last being a flag. If bit 0 of +the flag is set, secure memory has been requested. The handler should +either return true to indicate that Libgcrypt should try again +allocating memory or return false to let Libgcrypt use its default +fatal error handler. +@end deftypefun + +@deftp {Data type} gcry_handler_error_t +This type is defined as: @code{void (*gcry_handler_error_t) (void *, int, const char *)} +@end deftp + +@deftypefun void gcry_set_fatalerror_handler (gcry_handler_error_t @var{func_error}, void *@var{cb_data}) +This function registers @var{func_error} as `error handler', +which means that it will be called in error conditions. +@end deftypefun + +@node Logging handler +@section Logging handler + +@deftp {Data type} gcry_handler_log_t +This type is defined as: @code{void (*gcry_handler_log_t) (void *, int, const char *, va_list)} +@end deftp + +@deftypefun void gcry_set_log_handler (gcry_handler_log_t @var{func_log}, void *@var{cb_data}) +This function registers @var{func_log} as `logging handler', which means +that it will be called in case Libgcrypt wants to log a message. This +function may and should be used prior to calling +@code{gcry_check_version}. +@end deftypefun + +@c ********************************************************** +@c ******************* Ciphers **************************** +@c ********************************************************** +@c @include cipher-ref.texi +@node Symmetric cryptography +@chapter Symmetric cryptography + +The cipher functions are used for symmetrical cryptography, +i.e. cryptography using a shared key. The programming model follows +an open/process/close paradigm and is in that similar to other +building blocks provided by Libgcrypt. + +@menu +* Available ciphers:: List of ciphers supported by the library. +* Cipher modules:: How to work with cipher modules. +* Available cipher modes:: List of cipher modes supported by the library. +* Working with cipher handles:: How to perform operations related to cipher handles. +* General cipher functions:: General cipher functions independent of cipher handles. +@end menu + +@node Available ciphers +@section Available ciphers + +@table @code +@item GCRY_CIPHER_NONE +This is not a real algorithm but used by some functions as error return. +The value always evaluates to false. + +@item GCRY_CIPHER_IDEA +@cindex IDEA +This is the IDEA algorithm. The constant is provided but there is +currently no implementation for it because the algorithm is patented. + +@item GCRY_CIPHER_3DES +@cindex 3DES +@cindex Triple-DES +@cindex DES-EDE +@cindex Digital Encryption Standard +Triple-DES with 3 Keys as EDE. The key size of this algorithm is 168 but +you have to pass 192 bits because the most significant bits of each byte +are ignored. + +@item GCRY_CIPHER_CAST5 +@cindex CAST5 +CAST128-5 block cipher algorithm. The key size is 128 bits. + +@item GCRY_CIPHER_BLOWFISH +@cindex Blowfish +The blowfish algorithm. The current implementation allows only for a key +size of 128 bits. + +@item GCRY_CIPHER_SAFER_SK128 +Reserved and not currently implemented. + +@item GCRY_CIPHER_DES_SK +Reserved and not currently implemented. + +@item GCRY_CIPHER_AES +@itemx GCRY_CIPHER_AES128 +@itemx GCRY_CIPHER_RIJNDAEL +@itemx GCRY_CIPHER_RIJNDAEL128 +@cindex Rijndael +@cindex AES +@cindex Advanced Encryption Standard +AES (Rijndael) with a 128 bit key. + +@item GCRY_CIPHER_AES192 +@itemx GCRY_CIPHER_RIJNDAEL192 +AES (Rijndael) with a 192 bit key. + +@item GCRY_CIPHER_AES256 +@itemx GCRY_CIPHER_RIJNDAEL256 +AES (Rijndael) with a 256 bit key. + +@item GCRY_CIPHER_TWOFISH +@cindex Twofish +The Twofish algorithm with a 256 bit key. + +@item GCRY_CIPHER_TWOFISH128 +The Twofish algorithm with a 128 bit key. + +@item GCRY_CIPHER_ARCFOUR +@cindex Arcfour +@cindex RC4 +An algorithm which is 100% compatible with RSA Inc.'s RC4 algorithm. +Note that this is a stream cipher and must be used very carefully to +avoid a couple of weaknesses. + +@item GCRY_CIPHER_DES +@cindex DES +Standard DES with a 56 bit key. You need to pass 64 bit but the high +bits of each byte are ignored. Note, that this is a weak algorithm +which can be broken in reasonable time using a brute force approach. + +@item GCRY_CIPHER_SERPENT128 +@itemx GCRY_CIPHER_SERPENT192 +@itemx GCRY_CIPHER_SERPENT256 +@cindex Serpent +The Serpent cipher from the AES contest. + +@item GCRY_CIPHER_RFC2268_40 +@itemx GCRY_CIPHER_RFC2268_128 +@cindex rfc-2268 +@cindex RC2 +Ron's Cipher 2 in the 40 and 128 bit variants. Note, that we currently +only support the 40 bit variant. The identifier for 128 is reserved for +future use. + +@item GCRY_CIPHER_SEED +@cindex Seed (cipher) +A 128 bit cipher as described by RFC4269. + +@item GCRY_CIPHER_CAMELLIA128 +@itemx GCRY_CIPHER_CAMELLIA192 +@itemx GCRY_CIPHER_CAMELLIA256 +@cindex Camellia +The Camellia cipher by NTT. See +@uref{http://info.isl.ntt.co.jp/@/crypt/@/eng/@/camellia/@/specifications.html}. + +@end table + +@node Cipher modules +@section Cipher modules + +Libgcrypt makes it possible to load additional `cipher modules'; these +ciphers can be used just like the cipher algorithms that are built +into the library directly. For an introduction into extension +modules, see @xref{Modules}. + +@deftp {Data type} gcry_cipher_spec_t +This is the `module specification structure' needed for registering +cipher modules, which has to be filled in by the user before it can be +used to register a module. It contains the following members: + +@table @code +@item const char *name +The primary name of the algorithm. +@item const char **aliases +A list of strings that are `aliases' for the algorithm. The list must +be terminated with a NULL element. +@item gcry_cipher_oid_spec_t *oids +A list of OIDs that are to be associated with the algorithm. The +list's last element must have it's `oid' member set to NULL. See +below for an explanation of this type. +@item size_t blocksize +The block size of the algorithm, in bytes. +@item size_t keylen +The length of the key, in bits. +@item size_t contextsize +The size of the algorithm-specific `context', that should be allocated +for each handle. +@item gcry_cipher_setkey_t setkey +The function responsible for initializing a handle with a provided +key. See below for a description of this type. +@item gcry_cipher_encrypt_t encrypt +The function responsible for encrypting a single block. See below for +a description of this type. +@item gcry_cipher_decrypt_t decrypt +The function responsible for decrypting a single block. See below for +a description of this type. +@item gcry_cipher_stencrypt_t stencrypt +Like `encrypt', for stream ciphers. See below for a description of +this type. +@item gcry_cipher_stdecrypt_t stdecrypt +Like `decrypt', for stream ciphers. See below for a description of +this type. +@end table +@end deftp + +@deftp {Data type} gcry_cipher_oid_spec_t +This type is used for associating a user-provided algorithm +implementation with certain OIDs. It contains the following members: +@table @code +@item const char *oid +Textual representation of the OID. +@item int mode +Cipher mode for which this OID is valid. +@end table +@end deftp + +@deftp {Data type} gcry_cipher_setkey_t +Type for the `setkey' function, defined as: gcry_err_code_t +(*gcry_cipher_setkey_t) (void *c, const unsigned char *key, unsigned +keylen) +@end deftp + +@deftp {Data type} gcry_cipher_encrypt_t +Type for the `encrypt' function, defined as: gcry_err_code_t +(*gcry_cipher_encrypt_t) (void *c, const unsigned char *outbuf, const +unsigned char *inbuf) +@end deftp + +@deftp {Data type} gcry_cipher_decrypt_t +Type for the `decrypt' function, defined as: gcry_err_code_t +(*gcry_cipher_decrypt_t) (void *c, const unsigned char *outbuf, const +unsigned char *inbuf) +@end deftp + +@deftp {Data type} gcry_cipher_stencrypt_t +Type for the `stencrypt' function, defined as: gcry_err_code_t +(*gcry_@/cipher_@/stencrypt_@/t) (void *c, const unsigned char *outbuf, const +unsigned char *, unsigned int n) +@end deftp + +@deftp {Data type} gcry_cipher_stdecrypt_t +Type for the `stdecrypt' function, defined as: gcry_err_code_t +(*gcry_@/cipher_@/stdecrypt_@/t) (void *c, const unsigned char *outbuf, const +unsigned char *, unsigned int n) +@end deftp + +@deftypefun gcry_error_t gcry_cipher_register (gcry_cipher_spec_t *@var{cipher}, unsigned int *algorithm_id, gcry_module_t *@var{module}) + +Register a new cipher module whose specification can be found in +@var{cipher}. On success, a new algorithm ID is stored in +@var{algorithm_id} and a pointer representing this module is stored +in @var{module}. +@end deftypefun + +@deftypefun void gcry_cipher_unregister (gcry_module_t @var{module}) +Unregister the cipher identified by @var{module}, which must have been +registered with gcry_cipher_register. +@end deftypefun + +@deftypefun gcry_error_t gcry_cipher_list (int *@var{list}, int *@var{list_length}) +Get a list consisting of the IDs of the loaded cipher modules. If +@var{list} is zero, write the number of loaded cipher modules to +@var{list_length} and return. If @var{list} is non-zero, the first +*@var{list_length} algorithm IDs are stored in @var{list}, which must +be of according size. In case there are less cipher modules than +*@var{list_length}, *@var{list_length} is updated to the correct +number. +@end deftypefun + +@node Available cipher modes +@section Available cipher modes + +@table @code +@item GCRY_CIPHER_MODE_NONE +No mode specified. This should not be used. The only exception is that +if Libgcrypt is not used in FIPS mode and if any debug flag has been +set, this mode may be used to bypass the actual encryption. + +@item GCRY_CIPHER_MODE_ECB +@cindex ECB, Electronic Codebook mode +Electronic Codebook mode. + +@item GCRY_CIPHER_MODE_CFB +@cindex CFB, Cipher Feedback mode +Cipher Feedback mode. The shift size equals the block size of the +cipher (e.g. for AES it is CFB-128). + +@item GCRY_CIPHER_MODE_CBC +@cindex CBC, Cipher Block Chaining mode +Cipher Block Chaining mode. + +@item GCRY_CIPHER_MODE_STREAM +Stream mode, only to be used with stream cipher algorithms. + +@item GCRY_CIPHER_MODE_OFB +@cindex OFB, Output Feedback mode +Output Feedback mode. + +@item GCRY_CIPHER_MODE_CTR +@cindex CTR, Counter mode +Counter mode. + +@end table + +@node Working with cipher handles +@section Working with cipher handles + +To use a cipher algorithm, you must first allocate an according +handle. This is to be done using the open function: + +@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, int @var{algo}, int @var{mode}, unsigned int @var{flags}) + +This function creates the context handle required for most of the +other cipher functions and returns a handle to it in `hd'. In case of +an error, an according error code is returned. + +The ID of algorithm to use must be specified via @var{algo}. See +@xref{Available ciphers}, for a list of supported ciphers and the +according constants. + +Besides using the constants directly, the function +@code{gcry_cipher_map_name} may be used to convert the textual name of +an algorithm into the according numeric ID. + +The cipher mode to use must be specified via @var{mode}. See +@xref{Available cipher modes}, for a list of supported cipher modes +and the according constants. Note that some modes are incompatible +with some algorithms - in particular, stream mode +(@code{GCRY_CIPHER_MODE_STREAM}) only works with stream ciphers. Any +block cipher mode (@code{GCRY_CIPHER_MODE_ECB}, +@code{GCRY_CIPHER_MODE_CBC}, @code{GCRY_CIPHER_MODE_CFB}, +@code{GCRY_CIPHER_MODE_OFB} or @code{GCRY_CIPHER_MODE_CTR}) will work +with any block cipher algorithm. + +The third argument @var{flags} can either be passed as @code{0} or as +the bit-wise OR of the following constants. + +@table @code +@item GCRY_CIPHER_SECURE +Make sure that all operations are allocated in secure memory. This is +useful when the key material is highly confidential. +@item GCRY_CIPHER_ENABLE_SYNC +@cindex sync mode (OpenPGP) +This flag enables the CFB sync mode, which is a special feature of +Libgcrypt's CFB mode implementation to allow for OpenPGP's CFB variant. +See @code{gcry_cipher_sync}. +@item GCRY_CIPHER_CBC_CTS +@cindex cipher text stealing +Enable cipher text stealing (CTS) for the CBC mode. Cannot be used +simultaneous as GCRY_CIPHER_CBC_MAC. CTS mode makes it possible to +transform data of almost arbitrary size (only limitation is that it +must be greater than the algorithm's block size). +@item GCRY_CIPHER_CBC_MAC +@cindex CBC-MAC +Compute CBC-MAC keyed checksums. This is the same as CBC mode, but +only output the last block. Cannot be used simultaneous as +GCRY_CIPHER_CBC_CTS. +@end table +@end deftypefun + +Use the following function to release an existing handle: + +@deftypefun void gcry_cipher_close (gcry_cipher_hd_t @var{h}) + +This function releases the context created by @code{gcry_cipher_open}. +@end deftypefun + +In order to use a handle for performing cryptographic operations, a +`key' has to be set first: + +@deftypefun gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l}) + +Set the key @var{k} used for encryption or decryption in the context +denoted by the handle @var{h}. The length @var{l} of the key @var{k} +must match the required length of the algorithm set for this context or +be in the allowed range for algorithms with variable key size. The +function checks this and returns an error if there is a problem. A +caller should always check for an error. + +@end deftypefun + +Most crypto modes requires an initialization vector (IV), which +usually is a non-secret random string acting as a kind of salt value. +The CTR mode requires a counter, which is also similar to a salt +value. To set the IV or CTR, use these functions: + +@deftypefun gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l}) + +Set the initialization vector used for encryption or decryption. The +vector is passed as the buffer @var{K} of length @var{l} and copied to +internal data structures. The function checks that the IV matches the +requirement of the selected algorithm and mode. +@end deftypefun + +@deftypefun gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t @var{h}, const void *@var{c}, size_t @var{l}) + +Set the counter vector used for encryption or decryption. The counter +is passed as the buffer @var{c} of length @var{l} and copied to +internal data structures. The function checks that the counter +matches the requirement of the selected algorithm (i.e., it must be +the same size as the block size). +@end deftypefun + +@deftypefun gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t @var{h}) + +Set the given handle's context back to the state it had after the last +call to gcry_cipher_setkey and clear the initialization vector. + +Note that gcry_cipher_reset is implemented as a macro. +@end deftypefun + +The actual encryption and decryption is done by using one of the +following functions. They may be used as often as required to process +all the data. + +@deftypefun gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t @var{h}, unsigned char *{out}, size_t @var{outsize}, const unsigned char *@var{in}, size_t @var{inlen}) + +@code{gcry_cipher_encrypt} is used to encrypt the data. This function +can either work in place or with two buffers. It uses the cipher +context already setup and described by the handle @var{h}. There are 2 +ways to use the function: If @var{in} is passed as @code{NULL} and +@var{inlen} is @code{0}, in-place encryption of the data in @var{out} or +length @var{outsize} takes place. With @var{in} being not @code{NULL}, +@var{inlen} bytes are encrypted to the buffer @var{out} which must have +at least a size of @var{inlen}. @var{outsize} must be set to the +allocated size of @var{out}, so that the function can check that there +is sufficient space. Note that overlapping buffers are not allowed. + +Depending on the selected algorithms and encryption mode, the length of +the buffers must be a multiple of the block size. + +The function returns @code{0} on success or an error code. +@end deftypefun + + +@deftypefun gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t @var{h}, unsigned char *{out}, size_t @var{outsize}, const unsigned char *@var{in}, size_t @var{inlen}) + +@code{gcry_cipher_decrypt} is used to decrypt the data. This function +can either work in place or with two buffers. It uses the cipher +context already setup and described by the handle @var{h}. There are 2 +ways to use the function: If @var{in} is passed as @code{NULL} and +@var{inlen} is @code{0}, in-place decryption of the data in @var{out} or +length @var{outsize} takes place. With @var{in} being not @code{NULL}, +@var{inlen} bytes are decrypted to the buffer @var{out} which must have +at least a size of @var{inlen}. @var{outsize} must be set to the +allocated size of @var{out}, so that the function can check that there +is sufficient space. Note that overlapping buffers are not allowed. + +Depending on the selected algorithms and encryption mode, the length of +the buffers must be a multiple of the block size. + +The function returns @code{0} on success or an error code. +@end deftypefun + + +OpenPGP (as defined in RFC-2440) requires a special sync operation in +some places. The following function is used for this: + +@deftypefun gcry_error_t gcry_cipher_sync (gcry_cipher_hd_t @var{h}) + +Perform the OpenPGP sync operation on context @var{h}. Note that this +is a no-op unless the context was created with the flag +@code{GCRY_CIPHER_ENABLE_SYNC} +@end deftypefun + +Some of the described functions are implemented as macros utilizing a +catch-all control function. This control function is rarely used +directly but there is nothing which would inhibit it: + +@deftypefun gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t @var{h}, int @var{cmd}, void *@var{buffer}, size_t @var{buflen}) + +@code{gcry_cipher_ctl} controls various aspects of the cipher module and +specific cipher contexts. Usually some more specialized functions or +macros are used for this purpose. The semantics of the function and its +parameters depends on the the command @var{cmd} and the passed context +handle @var{h}. Please see the comments in the source code +(@code{src/global.c}) for details. +@end deftypefun + +@deftypefun gcry_error_t gcry_cipher_info (gcry_cipher_hd_t @var{h}, int @var{what}, void *@var{buffer}, size_t *@var{nbytes}) + +@code{gcry_cipher_info} is used to retrieve various +information about a cipher context or the cipher module in general. + +Currently no information is available. +@end deftypefun + +@node General cipher functions +@section General cipher functions + +To work with the algorithms, several functions are available to map +algorithm names to the internal identifiers, as well as ways to +retrieve information about an algorithm or the current cipher context. + +@deftypefun gcry_error_t gcry_cipher_algo_info (int @var{algo}, int @var{what}, void *@var{buffer}, size_t *@var{nbytes}) + +This function is used to retrieve information on a specific algorithm. +You pass the cipher algorithm ID as @var{algo} and the type of +information requested as @var{what}. The result is either returned as +the return code of the function or copied to the provided @var{buffer} +whose allocated length must be available in an integer variable with the +address passed in @var{nbytes}. This variable will also receive the +actual used length of the buffer. + +Here is a list of supported codes for @var{what}: + +@c begin constants for gcry_cipher_algo_info +@table @code +@item GCRYCTL_GET_KEYLEN: +Return the length of the key. If the algorithm supports multiple key +lengths, the maximum supported value is returned. The length is +returned as number of octets (bytes) and not as number of bits in +@var{nbytes}; @var{buffer} must be zero. + +@item GCRYCTL_GET_BLKLEN: +Return the block length of the algorithm. The length is returned as a +number of octets in @var{nbytes}; @var{buffer} must be zero. + +@item GCRYCTL_TEST_ALGO: +Returns @code{0} when the specified algorithm is available for use. +@var{buffer} and @var{nbytes} must be zero. + +@end table +@c end constants for gcry_cipher_algo_info + +@end deftypefun +@c end gcry_cipher_algo_info + +@deftypefun {const char *} gcry_cipher_algo_name (int @var{algo}) + +@code{gcry_cipher_algo_name} returns a string with the name of the +cipher algorithm @var{algo}. If the algorithm is not known or another +error occurred, the string @code{"?"} is returned. This function should +not be used to test for the availability of an algorithm. +@end deftypefun + +@deftypefun int gcry_cipher_map_name (const char *@var{name}) + +@code{gcry_cipher_map_name} returns the algorithm identifier for the +cipher algorithm described by the string @var{name}. If this algorithm +is not available @code{0} is returned. +@end deftypefun + +@deftypefun int gcry_cipher_mode_from_oid (const char *@var{string}) + +Return the cipher mode associated with an @acronym{ASN.1} object +identifier. The object identifier is expected to be in the +@acronym{IETF}-style dotted decimal notation. The function returns +@code{0} for an unknown object identifier or when no mode is associated +with it. +@end deftypefun + + +@c ********************************************************** +@c ******************* Public Key ************************* +@c ********************************************************** +@node Public Key cryptography +@chapter Public Key cryptography + +Public key cryptography, also known as asymmetric cryptography, is an +easy way for key management and to provide digital signatures. +Libgcrypt provides two completely different interfaces to +public key cryptography, this chapter explains the one based on +S-expressions. + +@menu +* Available algorithms:: Algorithms supported by the library. +* Used S-expressions:: Introduction into the used S-expression. +* Public key modules:: How to work with public key modules. +* Cryptographic Functions:: Functions for performing the cryptographic actions. +* General public-key related Functions:: General functions, not implementing any cryptography. + +* AC Interface:: Alternative interface to public key functions. +@end menu + +@node Available algorithms +@section Available algorithms + +Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well +as DSA (Digital Signature Algorithm) and Elgamal. The versatile +interface allows to add more algorithms in the future. + +@node Used S-expressions +@section Used S-expressions + +Libgcrypt's API for asymmetric cryptography is based on data structures +called S-expressions (see +@uref{http://people.csail.mit.edu/@/rivest/@/sexp.html}) and does not work +with contexts as most of the other building blocks of Libgcrypt do. + +@noindent +The following information are stored in S-expressions: + +@itemize @asis +@item keys + +@item plain text data + +@item encrypted data + +@item signatures + +@end itemize + +@noindent +To describe how Libgcrypt expect keys, we use examples. Note that +words in +@ifnottex +uppercase +@end ifnottex +@iftex +italics +@end iftex +indicate parameters whereas lowercase words are literals. + +Note that all MPI (multi-precision-integers) values are expected to be in +@code{GCRYMPI_FMT_USG} format. An easy way to create S-expressions is +by using @code{gcry_sexp_build} which allows to pass a string with +printf-like escapes to insert MPI values. + +@menu +* RSA key parameters:: Parameters used with an RSA key. +* DSA key parameters:: Parameters used with a DSA key. +* ECC key parameters:: Parameters used with ECC keys. +@end menu + +@node RSA key parameters +@subsection RSA key parameters + +@noindent +An RSA private key is described by this S-expression: + +@example +(private-key + (rsa + (n @var{n-mpi}) + (e @var{e-mpi}) + (d @var{d-mpi}) + (p @var{p-mpi}) + (q @var{q-mpi}) + (u @var{u-mpi}))) +@end example + +@noindent +An RSA public key is described by this S-expression: + +@example +(public-key + (rsa + (n @var{n-mpi}) + (e @var{e-mpi}))) +@end example + + +@table @var +@item n-mpi +RSA public modulus @math{n}. +@item e-mpi +RSA public exponent @math{e}. +@item d-mpi +RSA secret exponent @math{d = e^{-1} \bmod (p-1)(q-1)}. +@item p-mpi +RSA secret prime @math{p}. +@item q-mpi +RSA secret prime @math{q} with @math{p < q}. +@item u-mpi +Multiplicative inverse @math{u = p^{-1} \bmod q}. +@end table + +For signing and decryption the parameters @math{(p, q, u)} are optional +but greatly improve the performance. Either all of these optional +parameters must be given or none of them. They are mandatory for +gcry_pk_testkey. + +Note that OpenSSL uses slighly different parameters: @math{q < p} and + @math{u = q^{-1} \bmod p}. To use these parameters you will need to +swap the values and recompute @math{u}. Here is example code to do this: + +@example + if (gcry_mpi_cmp (p, q) > 0) + @{ + gcry_mpi_swap (p, q); + gcry_mpi_invm (u, p, q); + @} +@end example + + + + +@node DSA key parameters +@subsection DSA key parameters + +@noindent +A DSA private key is described by this S-expression: + +@example +(private-key + (dsa + (p @var{p-mpi}) + (q @var{q-mpi}) + (g @var{g-mpi}) + (y @var{y-mpi}) + (x @var{x-mpi}))) +@end example + +@table @var +@item p-mpi +DSA prime @math{p}. +@item q-mpi +DSA group order @math{q} (which is a prime divisor of @math{p-1}). +@item g-mpi +DSA group generator @math{g}. +@item y-mpi +DSA public key value @math{y = g^x \bmod p}. +@item x-mpi +DSA secret exponent x. +@end table + +The public key is similar with "private-key" replaced by "public-key" +and no @var{x-mpi}. + + +@node ECC key parameters +@subsection ECC key parameters + +@noindent +An ECC private key is described by this S-expression: + +@example +(private-key + (ecc + (p @var{p-mpi}) + (a @var{a-mpi}) + (b @var{b-mpi}) + (g @var{g-point}) + (n @var{n-mpi}) + (q @var{q-point}) + (d @var{d-mpi}))) +@end example + +@table @var +@item p-mpi +Prime specifying the field @math{GF(p)}. +@item a-mpi +@itemx b-mpi +The two coefficients of the Weierstrass equation @math{y^2 = x^3 + ax + b} +@item g-point +Base point @math{g}. +@item n-mpi +Order of @math{g} +@item q-point +The point representing the public key @math{Q = dP}. +@item d-mpi +The private key @math{d} +@end table + +All point values are encoded in standard format; Libgcrypt does +currently only support uncompressed points, thus the first byte needs to +be @code{0x04}. + +The public key is similar with "private-key" replaced by "public-key" +and no @var{d-mpi}. + +If the domain parameters are well-known, the name of this curve may be +used. For example + +@example +(private-key + (ecc + (curve "NIST P-192") + (q @var{q-point}) + (d @var{d-mpi}))) +@end example + +The @code{curve} parameter may be given in any case and is used to replace +missing parameters. + +@noindent +Currently implemented curves are: +@table @code +@item NIST P-192 +@itemx 1.2.840.10045.3.1.1 +@itemx prime192v1 +@itemx secp192r1 +The NIST 192 bit curve, its OID, X9.62 and SECP aliases. + +@item NIST P-224 +@itemx secp224r1 +The NIST 224 bit curve and its SECP alias. + +@item NIST P-256 +@itemx 1.2.840.10045.3.1.7 +@itemx prime256v1 +@itemx secp256r1 +The NIST 256 bit curve, its OID, X9.62 and SECP aliases. + +@item NIST P-384 +@itemx secp384r1 +The NIST 384 bit curve and its SECP alias. + +@item NIST P-521 +@itemx secp521r1 +The NIST 521 bit curve and its SECP alias. + +@end table +As usual the OIDs may optionally be prefixed with the string @code{OID.} +or @code{oid.}. + + + +@node Public key modules +@section Public key modules + +Libgcrypt makes it possible to load additional `public key +modules'; these public key algorithms can be used just like the +algorithms that are built into the library directly. For an +introduction into extension modules, see @xref{Modules}. + +@deftp {Data type} gcry_pk_spec_t +This is the `module specification structure' needed for registering +public key modules, which has to be filled in by the user before it +can be used to register a module. It contains the following members: + +@table @code +@item const char *name +The primary name of this algorithm. +@item char **aliases +A list of strings that are `aliases' for the algorithm. The list +must be terminated with a NULL element. +@item const char *elements_pkey +String containing the one-letter names of the MPI values contained in +a public key. +@item const char *element_skey +String containing the one-letter names of the MPI values contained in +a secret key. +@item const char *elements_enc +String containing the one-letter names of the MPI values that are the +result of an encryption operation using this algorithm. +@item const char *elements_sig +String containing the one-letter names of the MPI values that are the +result of a sign operation using this algorithm. +@item const char *elements_grip +String containing the one-letter names of the MPI values that are to +be included in the `key grip'. +@item int use +The bitwise-OR of the following flags, depending on the abilities of +the algorithm: +@table @code +@item GCRY_PK_USAGE_SIGN +The algorithm supports signing and verifying of data. +@item GCRY_PK_USAGE_ENCR +The algorithm supports the encryption and decryption of data. +@end table +@item gcry_pk_generate_t generate +The function responsible for generating a new key pair. See below for +a description of this type. +@item gcry_pk_check_secret_key_t check_secret_key +The function responsible for checking the sanity of a provided secret +key. See below for a description of this type. +@item gcry_pk_encrypt_t encrypt +The function responsible for encrypting data. See below for a +description of this type. +@item gcry_pk_decrypt_t decrypt +The function responsible for decrypting data. See below for a +description of this type. +@item gcry_pk_sign_t sign +The function responsible for signing data. See below for a description +of this type. +@item gcry_pk_verify_t verify +The function responsible for verifying that the provided signature +matches the provided data. See below for a description of this type. +@item gcry_pk_get_nbits_t get_nbits +The function responsible for returning the number of bits of a provided +key. See below for a description of this type. +@end table +@end deftp + +@deftp {Data type} gcry_pk_generate_t +Type for the `generate' function, defined as: gcry_err_code_t +(*gcry_pk_generate_t) (int algo, unsigned int nbits, unsigned long +use_e, gcry_mpi_t *skey, gcry_mpi_t **retfactors) +@end deftp + +@deftp {Data type} gcry_pk_check_secret_key_t +Type for the `check_secret_key' function, defined as: gcry_err_code_t +(*gcry_pk_check_secret_key_t) (int algo, gcry_mpi_t *skey) +@end deftp + +@deftp {Data type} gcry_pk_encrypt_t +Type for the `encrypt' function, defined as: gcry_err_code_t +(*gcry_pk_encrypt_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, +gcry_mpi_t *pkey, int flags) +@end deftp + +@deftp {Data type} gcry_pk_decrypt_t +Type for the `decrypt' function, defined as: gcry_err_code_t +(*gcry_pk_decrypt_t) (int algo, gcry_mpi_t *result, gcry_mpi_t *data, +gcry_mpi_t *skey, int flags) +@end deftp + +@deftp {Data type} gcry_pk_sign_t +Type for the `sign' function, defined as: gcry_err_code_t +(*gcry_pk_sign_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, +gcry_mpi_t *skey) +@end deftp + +@deftp {Data type} gcry_pk_verify_t +Type for the `verify' function, defined as: gcry_err_code_t +(*gcry_pk_verify_t) (int algo, gcry_mpi_t hash, gcry_mpi_t *data, +gcry_mpi_t *pkey, int (*cmp) (void *, gcry_mpi_t), void *opaquev) +@end deftp + +@deftp {Data type} gcry_pk_get_nbits_t +Type for the `get_nbits' function, defined as: unsigned +(*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey) +@end deftp + +@deftypefun gcry_error_t gcry_pk_register (gcry_pk_spec_t *@var{pubkey}, unsigned int *algorithm_id, gcry_module_t *@var{module}) + +Register a new public key module whose specification can be found in +@var{pubkey}. On success, a new algorithm ID is stored in +@var{algorithm_id} and a pointer representing this module is stored +in @var{module}. +@end deftypefun + +@deftypefun void gcry_pk_unregister (gcry_module_t @var{module}) +Unregister the public key module identified by @var{module}, which +must have been registered with gcry_pk_register. +@end deftypefun + +@deftypefun gcry_error_t gcry_pk_list (int *@var{list}, int *@var{list_length}) +Get a list consisting of the IDs of the loaded pubkey modules. If +@var{list} is zero, write the number of loaded pubkey modules to +@var{list_length} and return. If @var{list} is non-zero, the first +*@var{list_length} algorithm IDs are stored in @var{list}, which must +be of according size. In case there are less pubkey modules than +*@var{list_length}, *@var{list_length} is updated to the correct +number. +@end deftypefun + +@node Cryptographic Functions +@section Cryptographic Functions + +@noindent +Note that we will in future allow to use keys without p,q and u +specified and may also support other parameters for performance +reasons. + +@noindent + +Some functions operating on S-expressions support `flags', that +influence the operation. These flags have to be listed in a +sub-S-expression named `flags'; the following flags are known: + +@table @code +@item pkcs1 +Use PKCS#1 block type 2 padding. +@item no-blinding +Do not use a technique called `blinding', which is used by default in +order to prevent leaking of secret information. Blinding is only +implemented by RSA, but it might be implemented by other algorithms in +the future as well, when necessary. +@end table + +@noindent +Now that we know the key basics, we can carry on and explain how to +encrypt and decrypt data. In almost all cases the data is a random +session key which is in turn used for the actual encryption of the real +data. There are 2 functions to do this: + +@deftypefun gcry_error_t gcry_pk_encrypt (@w{gcry_sexp_t *@var{r_ciph},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{pkey}}) + +Obviously a public key must be provided for encryption. It is +expected as an appropriate S-expression (see above) in @var{pkey}. +The data to be encrypted can either be in the simple old format, which +is a very simple S-expression consisting only of one MPI, or it may be +a more complex S-expression which also allows to specify flags for +operation, like e.g. padding rules. + +@noindent +If you don't want to let Libgcrypt handle the padding, you must pass an +appropriate MPI using this expression for @var{data}: + +@example +(data + (flags raw) + (value @var{mpi})) +@end example + +@noindent +This has the same semantics as the old style MPI only way. @var{MPI} is +the actual data, already padded appropriate for your protocol. Most +systems however use PKCS#1 padding and so you can use this S-expression +for @var{data}: + +@example +(data + (flags pkcs1) + (value @var{block})) +@end example + +@noindent +Here, the "flags" list has the "pkcs1" flag which let the function know +that it should provide PKCS#1 block type 2 padding. The actual data to +be encrypted is passed as a string of octets in @var{block}. The +function checks that this data actually can be used with the given key, +does the padding and encrypts it. + +If the function could successfully perform the encryption, the return +value will be 0 and a new S-expression with the encrypted result is +allocated and assigned to the variable at the address of @var{r_ciph}. +The caller is responsible to release this value using +@code{gcry_sexp_release}. In case of an error, an error code is +returned and @var{r_ciph} will be set to @code{NULL}. + +@noindent +The returned S-expression has this format when used with RSA: + +@example +(enc-val + (rsa + (a @var{a-mpi}))) +@end example + +@noindent +Where @var{a-mpi} is an MPI with the result of the RSA operation. When +using the Elgamal algorithm, the return value will have this format: + +@example +(enc-val + (elg + (a @var{a-mpi}) + (b @var{b-mpi}))) +@end example + +@noindent +Where @var{a-mpi} and @var{b-mpi} are MPIs with the result of the +Elgamal encryption operation. +@end deftypefun +@c end gcry_pk_encrypt + +@deftypefun gcry_error_t gcry_pk_decrypt (@w{gcry_sexp_t *@var{r_plain},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}}) + +Obviously a private key must be provided for decryption. It is expected +as an appropriate S-expression (see above) in @var{skey}. The data to +be decrypted must match the format of the result as returned by +@code{gcry_pk_encrypt}, but should be enlarged with a @code{flags} +element: + +@example +(enc-val + (flags) + (elg + (a @var{a-mpi}) + (b @var{b-mpi}))) +@end example + +@noindent +Note that this function currently does not know of any padding +methods and the caller must do any un-padding on his own. + +@noindent +The function returns 0 on success or an error code. The variable at the +address of @var{r_plain} will be set to NULL on error or receive the +decrypted value on success. The format of @var{r_plain} is a +simple S-expression part (i.e. not a valid one) with just one MPI if +there was no @code{flags} element in @var{data}; if at least an empty +@code{flags} is passed in @var{data}, the format is: + +@example +(value @var{plaintext}) +@end example +@end deftypefun +@c end gcry_pk_decrypt + + +Another operation commonly performed using public key cryptography is +signing data. In some sense this is even more important than +encryption because digital signatures are an important instrument for +key management. Libgcrypt supports digital signatures using +2 functions, similar to the encryption functions: + +@deftypefun gcry_error_t gcry_pk_sign (@w{gcry_sexp_t *@var{r_sig},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}}) + +This function creates a digital signature for @var{data} using the +private key @var{skey} and place it into the variable at the address of +@var{r_sig}. @var{data} may either be the simple old style S-expression +with just one MPI or a modern and more versatile S-expression which +allows to let Libgcrypt handle padding: + +@example + (data + (flags pkcs1) + (hash @var{hash-algo} @var{block})) +@end example + +@noindent +This example requests to sign the data in @var{block} after applying +PKCS#1 block type 1 style padding. @var{hash-algo} is a string with the +hash algorithm to be encoded into the signature, this may be any hash +algorithm name as supported by Libgcrypt. Most likely, this will be +"sha1", "rmd160" or "md5". It is obvious that the length of @var{block} +must match the size of that message digests; the function checks that +this and other constraints are valid. + +@noindent +If PKCS#1 padding is not required (because the caller does already +provide a padded value), either the old format or better the following +format should be used: + +@example +(data + (flags raw) + (value @var{mpi})) +@end example + +@noindent +Here, the data to be signed is directly given as an @var{MPI}. + +@noindent +The signature is returned as a newly allocated S-expression in +@var{r_sig} using this format for RSA: + +@example +(sig-val + (rsa + (s @var{s-mpi}))) +@end example + +Where @var{s-mpi} is the result of the RSA sign operation. For DSA the +S-expression returned is: + +@example +(sig-val + (dsa + (r @var{r-mpi}) + (s @var{s-mpi}))) +@end example + +Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign +operation. For Elgamal signing (which is slow, yields large numbers +and probably is not as secure as the other algorithms), the same format is +used with "elg" replacing "dsa". +@end deftypefun +@c end gcry_pk_sign + +@noindent +The operation most commonly used is definitely the verification of a +signature. Libgcrypt provides this function: + +@deftypefun gcry_error_t gcry_pk_verify (@w{gcry_sexp_t @var{sig}}, @w{gcry_sexp_t @var{data}}, @w{gcry_sexp_t @var{pkey}}) + +This is used to check whether the signature @var{sig} matches the +@var{data}. The public key @var{pkey} must be provided to perform this +verification. This function is similar in its parameters to +@code{gcry_pk_sign} with the exceptions that the public key is used +instead of the private key and that no signature is created but a +signature, in a format as created by @code{gcry_pk_sign}, is passed to +the function in @var{sig}. + +@noindent +The result is 0 for success (i.e. the data matches the signature), or an +error code where the most relevant code is @code{GCRYERR_BAD_SIGNATURE} +to indicate that the signature does not match the provided data. + +@end deftypefun +@c end gcry_pk_verify + +@node General public-key related Functions +@section General public-key related Functions + +@noindent +A couple of utility functions are available to retrieve the length of +the key, map algorithm identifiers and perform sanity checks: + +@deftypefun {const char *} gcry_pk_algo_name (int @var{algo}) + +Map the public key algorithm id @var{algo} to a string representation of +the algorithm name. For unknown algorithms this functions returns the +string @code{"?"}. This function should not be used to test for the +availability of an algorithm. +@end deftypefun + +@deftypefun int gcry_pk_map_name (const char *@var{name}) + +Map the algorithm @var{name} to a public key algorithm Id. Returns 0 if +the algorithm name is not known. +@end deftypefun + +@deftypefun int gcry_pk_test_algo (int @var{algo}) + +Return 0 if the public key algorithm @var{algo} is available for use. +Note that this is implemented as a macro. +@end deftypefun + + +@deftypefun {unsigned int} gcry_pk_get_nbits (gcry_sexp_t @var{key}) + +Return what is commonly referred as the key length for the given +public or private in @var{key}. +@end deftypefun + +@deftypefun {unsigned char *} gcry_pk_get_keygrip (@w{gcry_sexp_t @var{key}}, @w{unsigned char *@var{array}}) + +Return the so called "keygrip" which is the SHA-1 hash of the public key +parameters expressed in a way depended on the algorithm. @var{array} +must either provide space for 20 bytes or be @code{NULL}. In the latter +case a newly allocated array of that size is returned. On success a +pointer to the newly allocated space or to @var{array} is returned. +@code{NULL} is returned to indicate an error which is most likely an +unknown algorithm or one where a "keygrip" has not yet been defined. +The function accepts public or secret keys in @var{key}. +@end deftypefun + +@deftypefun gcry_error_t gcry_pk_testkey (gcry_sexp_t @var{key}) + +Return zero if the private key @var{key} is `sane', an error code otherwise. +Note that it is not possible to check the `saneness' of a public key. + +@end deftypefun + + +@deftypefun gcry_error_t gcry_pk_algo_info (@w{int @var{algo}}, @w{int @var{what}}, @w{void *@var{buffer}}, @w{size_t *@var{nbytes}}) + +Depending on the value of @var{what} return various information about +the public key algorithm with the id @var{algo}. Note that the +function returns @code{-1} on error and the actual error code must be +retrieved using the function @code{gcry_errno}. The currently defined +values for @var{what} are: + +@table @code +@item GCRYCTL_TEST_ALGO: +Return 0 if the specified algorithm is available for use. +@var{buffer} must be @code{NULL}, @var{nbytes} may be passed as +@code{NULL} or point to a variable with the required usage of the +algorithm. This may be 0 for "don't care" or the bit-wise OR of these +flags: + +@table @code +@item GCRY_PK_USAGE_SIGN +Algorithm is usable for signing. +@item GCRY_PK_USAGE_ENCR +Algorithm is usable for encryption. +@end table + +Unless you need to test for the allowed usage, it is in general better +to use the macro gcry_pk_test_algo instead. + +@item GCRYCTL_GET_ALGO_USAGE: +Return the usage flags for the given algorithm. An invalid algorithm +return 0. Disabled algorithms are ignored here because we +want to know whether the algorithm is at all capable of a certain usage. + +@item GCRYCTL_GET_ALGO_NPKEY +Return the number of elements the public key for algorithm @var{algo} +consist of. Return 0 for an unknown algorithm. + +@item GCRYCTL_GET_ALGO_NSKEY +Return the number of elements the private key for algorithm @var{algo} +consist of. Note that this value is always larger than that of the +public key. Return 0 for an unknown algorithm. + +@item GCRYCTL_GET_ALGO_NSIGN +Return the number of elements a signature created with the algorithm +@var{algo} consists of. Return 0 for an unknown algorithm or for an +algorithm not capable of creating signatures. + +@item GCRYCTL_GET_ALGO_NENC +Return the number of elements a encrypted message created with the algorithm +@var{algo} consists of. Return 0 for an unknown algorithm or for an +algorithm not capable of encryption. +@end table + +@noindent +Please note that parameters not required should be passed as @code{NULL}. +@end deftypefun +@c end gcry_pk_algo_info + + +@deftypefun gcry_error_t gcry_pk_ctl (@w{int @var{cmd}}, @w{void *@var{buffer}}, @w{size_t @var{buflen}}) + +This is a general purpose function to perform certain control +operations. @var{cmd} controls what is to be done. The return value is +0 for success or an error code. Currently supported values for +@var{cmd} are: + +@table @code +@item GCRYCTL_DISABLE_ALGO +Disable the algorithm given as an algorithm id in @var{buffer}. +@var{buffer} must point to an @code{int} variable with the algorithm id +and @var{buflen} must have the value @code{sizeof (int)}. + +@end table +@end deftypefun +@c end gcry_pk_ctl + +@noindent +Libgcrypt also provides a function to generate public key +pairs: + +@deftypefun gcry_error_t gcry_pk_genkey (@w{gcry_sexp_t *@var{r_key}}, @w{gcry_sexp_t @var{parms}}) + +This function create a new public key pair using information given in +the S-expression @var{parms} and stores the private and the public key +in one new S-expression at the address given by @var{r_key}. In case of +an error, @var{r_key} is set to @code{NULL}. The return code is 0 for +success or an error code otherwise. + +@noindent +Here is an example for @var{parms} to create an 2048 bit RSA key: + +@example +(genkey + (rsa + (nbits 4:2048))) +@end example + +@noindent +To create an Elgamal key, substitute "elg" for "rsa" and to create a DSA +key use "dsa". Valid ranges for the key length depend on the +algorithms; all commonly used key lengths are supported. Currently +supported parameters are: + +@table @code +@item nbits +This is always required to specify the length of the key. The argument +is a string with a number in C-notation. The value should be a multiple +of 8. + +@item curve @var{name} +For ECC a named curve may be used instead of giving the number of +requested bits. This allows to request a specific curve to override a +default selection Libgcrypt would have taken if @code{nbits} has been +given. The available names are listed with the description of the ECC +public key parameters. + +@item rsa-use-e +This is only used with RSA to give a hint for the public exponent. The +value will be used as a base to test for a usable exponent. Some values +are special: + +@table @samp +@item 0 +Use a secure and fast value. This is currently the number 41. +@item 1 +Use a value as required by some crypto policies. This is currently +the number 65537. +@item 2 +Reserved +@item > 2 +Use the given value. +@end table + +@noindent +If this parameter is not used, Libgcrypt uses for historic reasons +65537. + +@item qbits +This is only meanigful for DSA keys. If it is given the DSA key is +generated with a Q parameyer of this size. If it is not given or zero +Q is deduced from NBITS in this way: +@table @samp +@item 512 <= N <= 1024 +Q = 160 +@item N = 2048 +Q = 224 +@item N = 3072 +Q = 256 +@item N = 7680 +Q = 384 +@item N = 15360 +Q = 512 +@end table +Note that in this case only the values for N, as given in the table, +are allowed. When specifying Q all values of N in the range 512 to +15680 are valid as long as they are multiples of 8. + +@item transient-key +This is only meaningful for RSA and DSA keys. This is a flag with no +value. If given the RSA or DSA key is created using a faster and a +somewhat less secure random number generator. This flag may be used +for keys which are only used for a short time and do not require full +cryptographic strength. + +@item domain +This is only meaningful for DLP algorithms. If specified keys are +generated with domain parameters taken from this list. The exact +format of this parameter depends on the actual algorithm. It is +currently only implemented for DSA using this format: + +@example +(genkey + (dsa + (domain + (p @var{p-mpi}) + (q @var{q-mpi}) + (g @var{q-mpi})))) +@end example + +@code{nbits} and @code{qbits} may not be specified because they are +derived from the domain parameters. + +@item derive-parms +This is currently only implemented for RSA and DSA keys. It is not +allowed to use this together with a @code{domain} specification. If +given, it is used to derive the keys using the given parameters. + +If given for an RSA key the X9.31 key generation algorithm is used +even if libgcrypt is not in FIPS mode. If given for a DSA key, the +FIPS 186 algorithm is used even if libgcrypt is not in FIPS mode. + +@example +(genkey + (rsa + (nbits 4:1024) + (rsa-use-e 1:3) + (derive-parms + (Xp1 #1A1916DDB29B4EB7EB6732E128#) + (Xp2 #192E8AAC41C576C822D93EA433#) + (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D + 769D6D76646C7A792E16EBD89FE6FC5B605A6493 + 39DFC925A86A4C6D150B71B9EEA02D68885F5009 + B98BD984#) + (Xq1 #1A5CF72EE770DE50CB09ACCEA9#) + (Xq2 #134E4CAA16D2350A21D775C404#) + (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D + 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325 + 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34 + 321DE34A#)))) +@end example + +@example +(genkey + (dsa + (nbits 4:1024) + (derive-parms + (seed @var{seed-mpi})))) +@end example + + +@item use-x931 +@cindex X9.31 +Force the use of the ANSI X9.31 key generation algorithm instead of +the default algorithm. This flag is only meaningful for RSA and +usually not required. Note that this algorithm is implicitly used if +either @code{derive-parms} is given or Libgcrypt is in FIPS mode. + +@item use-fips186 +@cindex FIPS 186 +Force the use of the FIPS 186 key generation algorithm instead of the +default algorithm. This flag is only meaningful for DSA and usually +not required. Note that this algorithm is implicitly used if either +@code{derive-parms} is given or Libgcrypt is in FIPS mode. As of now +FIPS 186-2 is implemented; after the approval of FIPS 186-3 the code +will be changed to implement 186-3. + + +@item use-fips186-2 +Force the use of the FIPS 186-2 key generation algorithm instead of +the default algorithm. This algorithm is slighlty different from +FIPS 186-3 and allows only 1024 bit keys. This flag is only meaningful +for DSA and only required for FIPS testing backward compatibility. + + +@end table +@c end table of parameters + +@noindent +The key pair is returned in a format depending on the algorithm. Both +private and public keys are returned in one container and may be +accompanied by some miscellaneous information. + +@noindent +As an example, here is what the Elgamal key generation returns: + +@example +(key-data + (public-key + (elg + (p @var{p-mpi}) + (g @var{g-mpi}) + (y @var{y-mpi}))) + (private-key + (elg + (p @var{p-mpi}) + (g @var{g-mpi}) + (y @var{y-mpi}) + (x @var{x-mpi}))) + (misc-key-info + (pm1-factors @var{n1 n2 ... nn})) +@end example + +@noindent +As you can see, some of the information is duplicated, but this +provides an easy way to extract either the public or the private key. +Note that the order of the elements is not defined, e.g. the private +key may be stored before the public key. @var{n1 n2 ... nn} is a list +of prime numbers used to composite @var{p-mpi}; this is in general not +a very useful information and only available if the key generation +algorithm provides them. +@end deftypefun +@c end gcry_pk_genkey + +@node AC Interface +@section Alternative Public Key Interface + +This section documents the alternative interface to asymmetric +cryptography (ac) that is not based on S-expressions, but on native C +data structures. As opposed to the pk interface described in the +former chapter, this one follows an open/use/close paradigm like other +building blocks of the library. + +@strong{This interface has a few known problems; most noteworthy an +inherent tendency to leak memory. It might not be available in +forthcoming versions of Libgcrypt.} + + +@menu +* Available asymmetric algorithms:: List of algorithms supported by the library. +* Working with sets of data:: How to work with sets of data. +* Working with IO objects:: How to work with IO objects. +* Working with handles:: How to use handles. +* Working with keys:: How to work with keys. +* Using cryptographic functions:: How to perform cryptographic operations. +* Handle-independent functions:: General functions independent of handles. +@end menu + +@node Available asymmetric algorithms +@subsection Available asymmetric algorithms + +Libgcrypt supports the RSA (Rivest-Shamir-Adleman) +algorithms as well as DSA (Digital Signature Algorithm) and Elgamal. +The versatile interface allows to add more algorithms in the future. + +@deftp {Data type} gcry_ac_id_t + +The following constants are defined for this type: + +@table @code +@item GCRY_AC_RSA +Rivest-Shamir-Adleman +@item GCRY_AC_DSA +Digital Signature Algorithm +@item GCRY_AC_ELG +Elgamal +@item GCRY_AC_ELG_E +Elgamal, encryption only. +@end table +@end deftp + +@node Working with sets of data +@subsection Working with sets of data + +In the context of this interface the term `data set' refers to a list +of `named MPI values' that is used by functions performing +cryptographic operations; a named MPI value is a an MPI value, +associated with a label. + +Such data sets are used for representing keys, since keys simply +consist of a variable amount of numbers. Furthermore some functions +return data sets to the caller that are to be provided to other +functions. + +This section documents the data types, symbols and functions that are +relevant for working with data sets. + +@deftp {Data type} gcry_ac_data_t +A single data set. +@end deftp + +The following flags are supported: + +@table @code +@item GCRY_AC_FLAG_DEALLOC +Used for storing data in a data set. If given, the data will be +released by the library. Note that whenever one of the ac functions +is about to release objects because of this flag, the objects are +expected to be stored in memory allocated through the Libgcrypt memory +management. In other words: gcry_free() is used instead of free(). + +@item GCRY_AC_FLAG_COPY +Used for storing/retrieving data in/from a data set. If given, the +library will create copies of the provided/contained data, which will +then be given to the user/associated with the data set. +@end table + +@deftypefun gcry_error_t gcry_ac_data_new (gcry_ac_data_t *@var{data}) +Creates a new, empty data set and stores it in @var{data}. +@end deftypefun + +@deftypefun void gcry_ac_data_destroy (gcry_ac_data_t @var{data}) +Destroys the data set @var{data}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi}) +Add the value @var{mpi} to @var{data} with the label @var{name}. If +@var{flags} contains GCRY_AC_FLAG_COPY, the data set will contain +copies of @var{name} and @var{mpi}. If @var{flags} contains +GCRY_AC_FLAG_DEALLOC or GCRY_AC_FLAG_COPY, the values +contained in the data set will be deallocated when they are to be +removed from the data set. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *@var{data_cp}, gcry_ac_data_t @var{data}) +Create a copy of the data set @var{data} and store it in +@var{data_cp}. FIXME: exact semantics undefined. +@end deftypefun + +@deftypefun {unsigned int} gcry_ac_data_length (gcry_ac_data_t @var{data}) +Returns the number of named MPI values inside of the data set +@var{data}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi}) +Store the value labelled with @var{name} found in @var{data} in +@var{mpi}. If @var{flags} contains GCRY_AC_FLAG_COPY, store a copy of +the @var{mpi} value contained in the data set. @var{mpi} may be NULL +(this might be useful for checking the existence of an MPI with +extracting it). +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, unsigned int flags, unsigned int @var{index}, const char **@var{name}, gcry_mpi_t *@var{mpi}) +Stores in @var{name} and @var{mpi} the named @var{mpi} value contained +in the data set @var{data} with the index @var{idx}. If @var{flags} +contains GCRY_AC_FLAG_COPY, store copies of the values contained in +the data set. @var{name} or @var{mpi} may be NULL. +@end deftypefun + +@deftypefun void gcry_ac_data_clear (gcry_ac_data_t @var{data}) +Destroys any values contained in the data set @var{data}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t @var{data}, gcry_sexp_t *@var{sexp}, const char **@var{identifiers}) +This function converts the data set @var{data} into a newly created +S-Expression, which is to be stored in @var{sexp}; @var{identifiers} +is a NULL terminated list of C strings, which specifies the structure +of the S-Expression. + +Example: + +If @var{identifiers} is a list of pointers to the strings ``foo'' and +``bar'' and if @var{data} is a data set containing the values ``val1 = +0x01'' and ``val2 = 0x02'', then the resulting S-Expression will look +like this: (foo (bar ((val1 0x01) (val2 0x02))). +@end deftypefun + +@deftypefun gcry_error gcry_ac_data_from_sexp (gcry_ac_data_t *@var{data}, gcry_sexp_t @var{sexp}, const char **@var{identifiers}) +This function converts the S-Expression @var{sexp} into a newly +created data set, which is to be stored in @var{data}; +@var{identifiers} is a NULL terminated list of C strings, which +specifies the structure of the S-Expression. If the list of +identifiers does not match the structure of the S-Expression, the +function fails. +@end deftypefun + +@node Working with IO objects +@subsection Working with IO objects + +Note: IO objects are currently only used in the context of message +encoding/decoding and encryption/signature schemes. + +@deftp {Data type} {gcry_ac_io_t} +@code{gcry_ac_io_t} is the type to be used for IO objects. +@end deftp + +IO objects provide an uniform IO layer on top of different underlying +IO mechanisms; either they can be used for providing data to the +library (mode is GCRY_AC_IO_READABLE) or they can be used for +retrieving data from the library (mode is GCRY_AC_IO_WRITABLE). + +IO object need to be initialized by calling on of the following +functions: + +@deftypefun void gcry_ac_io_init (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, ...); +Initialize @var{ac_io} according to @var{mode}, @var{type} and the +variable list of arguments. The list of variable arguments to specify +depends on the given @var{type}. +@end deftypefun + +@deftypefun void gcry_ac_io_init_va (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, va_list @var{ap}); +Initialize @var{ac_io} according to @var{mode}, @var{type} and the +variable list of arguments @var{ap}. The list of variable arguments +to specify depends on the given @var{type}. +@end deftypefun + +The following types of IO objects exist: + +@table @code +@item GCRY_AC_IO_STRING +In case of GCRY_AC_IO_READABLE the IO object will provide data from a +memory string. Arguments to specify at initialization time: +@table @code +@item unsigned char * +Pointer to the beginning of the memory string +@item size_t +Size of the memory string +@end table +In case of GCRY_AC_IO_WRITABLE the object will store retrieved data in +a newly allocated memory string. Arguments to specify at +initialization time: +@table @code +@item unsigned char ** +Pointer to address, at which the pointer to the newly created memory +string is to be stored +@item size_t * +Pointer to address, at which the size of the newly created memory +string is to be stored +@end table + +@item GCRY_AC_IO_CALLBACK +In case of GCRY_AC_IO_READABLE the object will forward read requests +to a provided callback function. Arguments to specify at +initialization time: +@table @code +@item gcry_ac_data_read_cb_t +Callback function to use +@item void * +Opaque argument to provide to the callback function +@end table +In case of GCRY_AC_IO_WRITABLE the object will forward write requests +to a provided callback function. Arguments to specify at +initialization time: +@table @code +@item gcry_ac_data_write_cb_t +Callback function to use +@item void * +Opaque argument to provide to the callback function +@end table +@end table + +@node Working with handles +@subsection Working with handles + +In order to use an algorithm, an according handle must be created. +This is done using the following function: + +@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, int @var{algorithm}, int @var{flags}) + +Creates a new handle for the algorithm @var{algorithm} and stores it +in @var{handle}. @var{flags} is not used currently. + +@var{algorithm} must be a valid algorithm ID, see @xref{Available +asymmetric algorithms}, for a list of supported algorithms and the +according constants. Besides using the listed constants directly, the +functions @code{gcry_pk_name_to_id} may be used to convert the textual +name of an algorithm into the according numeric ID. +@end deftypefun + +@deftypefun void gcry_ac_close (gcry_ac_handle_t @var{handle}) +Destroys the handle @var{handle}. +@end deftypefun + +@node Working with keys +@subsection Working with keys + +@deftp {Data type} gcry_ac_key_type_t +Defined constants: + +@table @code +@item GCRY_AC_KEY_SECRET +Specifies a secret key. +@item GCRY_AC_KEY_PUBLIC +Specifies a public key. +@end table +@end deftp + +@deftp {Data type} gcry_ac_key_t +This type represents a single `key', either a secret one or a public +one. +@end deftp + +@deftp {Data type} gcry_ac_key_pair_t +This type represents a `key pair' containing a secret and a public key. +@end deftp + +Key data structures can be created in two different ways; a new key +pair can be generated, resulting in ready-to-use key. Alternatively a +key can be initialized from a given data set. + +@deftypefun gcry_error_t gcry_ac_key_init (gcry_ac_key_t *@var{key}, gcry_ac_handle_t @var{handle}, gcry_ac_key_type_t @var{type}, gcry_ac_data_t @var{data}) +Creates a new key of type @var{type}, consisting of the MPI values +contained in the data set @var{data} and stores it in @var{key}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, gcry_mpi_t **@var{misc_data}) + +Generates a new key pair via the handle @var{handle} of @var{NBITS} +bits and stores it in @var{key_pair}. + +In case non-standard settings are wanted, a pointer to a structure of +type @code{gcry_ac_key_spec__t}, matching the selected +algorithm, can be given as @var{key_spec}. @var{misc_data} is not +used yet. Such a structure does only exist for RSA. A description +of the members of the supported structures follows. + +@table @code +@item gcry_ac_key_spec_rsa_t +@table @code +@item gcry_mpi_t e +Generate the key pair using a special @code{e}. The value of @code{e} +has the following meanings: +@table @code +@item = 0 +Let Libgcrypt decide what exponent should be used. +@item = 1 +Request the use of a ``secure'' exponent; this is required by some +specification to be 65537. +@item > 2 +Try starting at this value until a working exponent is found. Note +that the current implementation leaks some information about the +private key because the incrementation used is not randomized. Thus, +this function will be changed in the future to return a random +exponent of the given size. +@end table +@end table +@end table + +Example code: +@example +@{ + gcry_ac_key_pair_t key_pair; + gcry_ac_key_spec_rsa_t rsa_spec; + + rsa_spec.e = gcry_mpi_new (0); + gcry_mpi_set_ui (rsa_spec.e, 1); + + err = gcry_ac_open (&handle, GCRY_AC_RSA, 0); + assert (! err); + + err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, + &key_pair, NULL); + assert (! err); +@} +@end example +@end deftypefun + + +@deftypefun gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t @var{key_pair}, gcry_ac_key_type_t @var{which}) +Returns the key of type @var{which} out of the key pair +@var{key_pair}. +@end deftypefun + +@deftypefun void gcry_ac_key_destroy (gcry_ac_key_t @var{key}) +Destroys the key @var{key}. +@end deftypefun + +@deftypefun void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t @var{key_pair}) +Destroys the key pair @var{key_pair}. +@end deftypefun + +@deftypefun gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t @var{key}) +Returns the data set contained in the key @var{key}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_key_test (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}) +Verifies that the private key @var{key} is sane via @var{handle}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned int *@var{nbits}) +Stores the number of bits of the key @var{key} in @var{nbits} via @var{handle}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned char *@var{key_grip}) +Writes the 20 byte long key grip of the key @var{key} to +@var{key_grip} via @var{handle}. +@end deftypefun + +@node Using cryptographic functions +@subsection Using cryptographic functions + +The following flags might be relevant: + +@table @code +@item GCRY_AC_FLAG_NO_BLINDING +Disable any blinding, which might be supported by the chosen +algorithm; blinding is the default. +@end table + +There exist two kinds of cryptographic functions available through the +ac interface: primitives, and high-level functions. + +Primitives deal with MPIs (data sets) directly; what they provide is +direct access to the cryptographic operations provided by an algorithm +implementation. + +High-level functions deal with octet strings, according to a specified +``scheme''. Schemes make use of ``encoding methods'', which are +responsible for converting the provided octet strings into MPIs, which +are then forwared to the cryptographic primitives. Since schemes are +to be used for a special purpose in order to achieve a particular +security goal, there exist ``encryption schemes'' and ``signature +schemes''. Encoding methods can be used seperately or implicitly +through schemes. + +What follows is a description of the cryptographic primitives. + +@deftypefun gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t @var{handle}, unsigned int @var{flags}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data_plain}, gcry_ac_data_t *@var{data_encrypted}) +Encrypts the plain text MPI value @var{data_plain} with the key public +@var{key} under the control of the flags @var{flags} and stores the +resulting data set into @var{data_encrypted}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t @var{handle}, unsigned int @var{flags}, gcry_ac_key_t @var{key}, gcry_mpi_t *@var{data_plain}, gcry_ac_data_t @var{data_encrypted}) +Decrypts the encrypted data contained in the data set +@var{data_encrypted} with the secret key KEY under the control of the +flags @var{flags} and stores the resulting plain text MPI value in +@var{DATA_PLAIN}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data}, gcry_ac_data_t *@var{data_signature}) +Signs the data contained in @var{data} with the secret key @var{key} +and stores the resulting signature in the data set +@var{data_signature}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data}, gcry_ac_data_t @var{data_signature}) +Verifies that the signature contained in the data set +@var{data_signature} is indeed the result of signing the data +contained in @var{data} with the secret key belonging to the public +key @var{key}. +@end deftypefun + +What follows is a description of the high-level functions. + +The type ``gcry_ac_em_t'' is used for specifying encoding methods; the +following methods are supported: + +@table @code +@item GCRY_AC_EME_PKCS_V1_5 +PKCS-V1_5 Encoding Method for Encryption. Options must be provided +through a pointer to a correctly initialized object of type +gcry_ac_eme_pkcs_v1_5_t. + +@item GCRY_AC_EMSA_PKCS_V1_5 +PKCS-V1_5 Encoding Method for Signatures with Appendix. Options must +be provided through a pointer to a correctly initialized object of +type gcry_ac_emsa_pkcs_v1_5_t. +@end table + +Option structure types: + +@table @code +@item gcry_ac_eme_pkcs_v1_5_t +@table @code +@item gcry_ac_key_t key +@item gcry_ac_handle_t handle +@end table +@item gcry_ac_emsa_pkcs_v1_5_t +@table @code +@item gcry_md_algo_t md +@item size_t em_n +@end table +@end table + +Encoding methods can be used directly through the following functions: + +@deftypefun gcry_error_t gcry_ac_data_encode (gcry_ac_em_t @var{method}, unsigned int @var{flags}, void *@var{options}, unsigned char *@var{m}, size_t @var{m_n}, unsigned char **@var{em}, size_t *@var{em_n}) +Encodes the message contained in @var{m} of size @var{m_n} according +to @var{method}, @var{flags} and @var{options}. The newly created +encoded message is stored in @var{em} and @var{em_n}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_decode (gcry_ac_em_t @var{method}, unsigned int @var{flags}, void *@var{options}, unsigned char *@var{em}, size_t @var{em_n}, unsigned char **@var{m}, size_t *@var{m_n}) +Decodes the message contained in @var{em} of size @var{em_n} according +to @var{method}, @var{flags} and @var{options}. The newly created +decoded message is stored in @var{m} and @var{m_n}. +@end deftypefun + +The type ``gcry_ac_scheme_t'' is used for specifying schemes; the +following schemes are supported: + +@table @code +@item GCRY_AC_ES_PKCS_V1_5 +PKCS-V1_5 Encryption Scheme. No options can be provided. +@item GCRY_AC_SSA_PKCS_V1_5 +PKCS-V1_5 Signature Scheme (with Appendix). Options can be provided +through a pointer to a correctly initialized object of type +gcry_ac_ssa_pkcs_v1_5_t. +@end table + +Option structure types: + +@table @code +@item gcry_ac_ssa_pkcs_v1_5_t +@table @code +@item gcry_md_algo_t md +@end table +@end table + +The functions implementing schemes: + +@deftypefun gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_cipher}) +Encrypts the plain text readable from @var{io_message} through +@var{handle} with the public key @var{key} according to @var{scheme}, +@var{flags} and @var{opts}. If @var{opts} is not NULL, it has to be a +pointer to a structure specific to the chosen scheme (gcry_ac_es_*_t). +The encrypted message is written to @var{io_cipher}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_cipher}, gcry_ac_io_t *@var{io_message}) +Decrypts the cipher text readable from @var{io_cipher} through +@var{handle} with the secret key @var{key} according to @var{scheme}, +@var{flags} and @var{opts}. If @var{opts} is not NULL, it has to be a +pointer to a structure specific to the chosen scheme (gcry_ac_es_*_t). +The decrypted message is written to @var{io_message}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_signature}) +Signs the message readable from @var{io_message} through @var{handle} +with the secret key @var{key} according to @var{scheme}, @var{flags} +and @var{opts}. If @var{opts} is not NULL, it has to be a pointer to +a structure specific to the chosen scheme (gcry_ac_ssa_*_t). The +signature is written to @var{io_signature}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_signature}) +Verifies through @var{handle} that the signature readable from +@var{io_signature} is indeed the result of signing the message +readable from @var{io_message} with the secret key belonging to the +public key @var{key} according to @var{scheme} and @var{opts}. If +@var{opts} is not NULL, it has to be an anonymous structure +(gcry_ac_ssa_*_t) specific to the chosen scheme. +@end deftypefun + +@node Handle-independent functions +@subsection Handle-independent functions + +These two functions are deprecated; do not use them for new code. + +@deftypefun gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t @var{algorithm}, const char **@var{name}) +Stores the textual representation of the algorithm whose id is given +in @var{algorithm} in @var{name}. Deprecated; use @code{gcry_pk_algo_name}. +@end deftypefun + +@deftypefun gcry_error_t gcry_ac_name_to_id (const char *@var{name}, gcry_ac_id_t *@var{algorithm}) +Stores the numeric ID of the algorithm whose textual representation is +contained in @var{name} in @var{algorithm}. Deprecated; use +@code{gcry_pk_map_name}. +@end deftypefun + +@c ********************************************************** +@c ******************* Hash Functions ********************* +@c ********************************************************** +@node Hashing +@chapter Hashing + +Libgcrypt provides an easy and consistent to use interface for hashing. +Hashing is buffered and several hash algorithms can be updated at once. +It is possible to compute a MAC using the same routines. The +programming model follows an open/process/close paradigm and is in that +similar to other building blocks provided by Libgcrypt. + +For convenience reasons, a few cyclic redundancy check value operations +are also supported. + +@menu +* Available hash algorithms:: List of hash algorithms supported by the library. +* Hash algorithm modules:: How to work with hash algorithm modules. +* Working with hash algorithms:: List of functions related to hashing. +@end menu + +@node Available hash algorithms +@section Available hash algorithms + +@c begin table of hash algorithms +@cindex SHA-1 +@cindex SHA-224, SHA-256, SHA-384, SHA-512 +@cindex RIPE-MD-160 +@cindex MD2, MD4, MD5 +@cindex TIGER +@cindex HAVAL +@cindex Whirlpool +@cindex CRC32 +@table @code +@item GCRY_MD_NONE +This is not a real algorithm but used by some functions as an error +return value. This constant is guaranteed to have the value @code{0}. + +@item GCRY_MD_SHA1 +This is the SHA-1 algorithm which yields a message digest of 20 bytes. + +@item GCRY_MD_RMD160 +This is the 160 bit version of the RIPE message digest (RIPE-MD-160). +Like SHA-1 it also yields a digest of 20 bytes. + +@item GCRY_MD_MD5 +This is the well known MD5 algorithm, which yields a message digest of +16 bytes. + +@item GCRY_MD_MD4 +This is the MD4 algorithm, which yields a message digest of 16 bytes. + +@item GCRY_MD_MD2 +This is an reserved identifier for MD-2; there is no implementation yet. + +@item GCRY_MD_TIGER +This is the TIGER/192 algorithm which yields a message digest of 24 bytes. + +@item GCRY_MD_HAVAL +This is an reserved for the HAVAL algorithm with 5 passes and 160 +bit. It yields a message digest of 20 bytes. Note that there is no +implementation yet available. + +@item GCRY_MD_SHA224 +This is the SHA-224 algorithm which yields a message digest of 28 bytes. +See Change Notice 1 for FIPS 180-2 for the specification. + +@item GCRY_MD_SHA256 +This is the SHA-256 algorithm which yields a message digest of 32 bytes. +See FIPS 180-2 for the specification. + +@item GCRY_MD_SHA384 +This is the SHA-384 algorithm which yields a message digest of 48 bytes. +See FIPS 180-2 for the specification. + +@item GCRY_MD_SHA512 +This is the SHA-384 algorithm which yields a message digest of 64 bytes. +See FIPS 180-2 for the specification. + +@item GCRY_MD_CRC32 +This is the ISO 3309 and ITU-T V.42 cyclic redundancy check. It +yields an output of 4 bytes. + +@item GCRY_MD_CRC32_RFC1510 +This is the above cyclic redundancy check function, as modified by RFC +1510. It yields an output of 4 bytes. + +@item GCRY_MD_CRC24_RFC2440 +This is the OpenPGP cyclic redundancy check function. It yields an +output of 3 bytes. + +@item GCRY_MD_WHIRLPOOL +This is the Whirlpool algorithm which yields a message digest of 64 +bytes. + +@end table +@c end table of hash algorithms + +@node Hash algorithm modules +@section Hash algorithm modules + +Libgcrypt makes it possible to load additional `message +digest modules'; these digests can be used just like the message digest +algorithms that are built into the library directly. For an +introduction into extension modules, see @xref{Modules}. + +@deftp {Data type} gcry_md_spec_t +This is the `module specification structure' needed for registering +message digest modules, which has to be filled in by the user before +it can be used to register a module. It contains the following +members: + +@table @code +@item const char *name +The primary name of this algorithm. +@item unsigned char *asnoid +Array of bytes that form the ASN OID. +@item int asnlen +Length of bytes in `asnoid'. +@item gcry_md_oid_spec_t *oids +A list of OIDs that are to be associated with the algorithm. The +list's last element must have it's `oid' member set to NULL. See +below for an explanation of this type. See below for an explanation +of this type. +@item int mdlen +Length of the message digest algorithm. See below for an explanation +of this type. +@item gcry_md_init_t init +The function responsible for initializing a handle. See below for an +explanation of this type. +@item gcry_md_write_t write +The function responsible for writing data into a message digest +context. See below for an explanation of this type. +@item gcry_md_final_t final +The function responsible for `finalizing' a message digest context. +See below for an explanation of this type. +@item gcry_md_read_t read +The function responsible for reading out a message digest result. See +below for an explanation of this type. +@item size_t contextsize +The size of the algorithm-specific `context', that should be +allocated for each handle. +@end table +@end deftp + +@deftp {Data type} gcry_md_oid_spec_t +This type is used for associating a user-provided algorithm +implementation with certain OIDs. It contains the following members: + +@table @code +@item const char *oidstring +Textual representation of the OID. +@end table +@end deftp + +@deftp {Data type} gcry_md_init_t +Type for the `init' function, defined as: void (*gcry_md_init_t) (void +*c) +@end deftp + +@deftp {Data type} gcry_md_write_t +Type for the `write' function, defined as: void (*gcry_md_write_t) +(void *c, unsigned char *buf, size_t nbytes) +@end deftp + +@deftp {Data type} gcry_md_final_t +Type for the `final' function, defined as: void (*gcry_md_final_t) +(void *c) +@end deftp + +@deftp {Data type} gcry_md_read_t +Type for the `read' function, defined as: unsigned char +*(*gcry_md_read_t) (void *c) +@end deftp + +@deftypefun gcry_error_t gcry_md_register (gcry_md_spec_t *@var{digest}, unsigned int *algorithm_id, gcry_module_t *@var{module}) + +Register a new digest module whose specification can be found in +@var{digest}. On success, a new algorithm ID is stored in +@var{algorithm_id} and a pointer representing this module is stored +in @var{module}. +@end deftypefun + +@deftypefun void gcry_md_unregister (gcry_module_t @var{module}) +Unregister the digest identified by @var{module}, which must have been +registered with gcry_md_register. +@end deftypefun + +@deftypefun gcry_error_t gcry_md_list (int *@var{list}, int *@var{list_length}) +Get a list consisting of the IDs of the loaded message digest modules. +If @var{list} is zero, write the number of loaded message digest +modules to @var{list_length} and return. If @var{list} is non-zero, +the first *@var{list_length} algorithm IDs are stored in @var{list}, +which must be of according size. In case there are less message +digests modules than *@var{list_length}, *@var{list_length} is updated +to the correct number. +@end deftypefun + +@node Working with hash algorithms +@section Working with hash algorithms + +To use most of these function it is necessary to create a context; +this is done using: + +@deftypefun gcry_error_t gcry_md_open (gcry_md_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags}) + +Create a message digest object for algorithm @var{algo}. @var{flags} +may be given as an bitwise OR of constants described below. @var{algo} +may be given as @code{0} if the algorithms to use are later set using +@code{gcry_md_enable}. @var{hd} is guaranteed to either receive a valid +handle or NULL. + +For a list of supported algorithms, see @xref{Available hash +algorithms}. + +The flags allowed for @var{mode} are: + +@c begin table of hash flags +@table @code +@item GCRY_MD_FLAG_SECURE +Allocate all buffers and the resulting digest in "secure memory". Use +this is the hashed data is highly confidential. + +@item GCRY_MD_FLAG_HMAC +@cindex HMAC +Turn the algorithm into a HMAC message authentication algorithm. This +only works if just one algorithm is enabled for the handle. Note that +the function @code{gcry_md_setkey} must be used to set the MAC key. +The size of the MAC is equal to the message digest of the underlying +hash algorithm. If you want CBC message authentication codes based on +a cipher, see @xref{Working with cipher handles}. + +@end table +@c begin table of hash flags + +You may use the function @code{gcry_md_is_enabled} to later check +whether an algorithm has been enabled. + +@end deftypefun +@c end function gcry_md_open + +If you want to calculate several hash algorithms at the same time, you +have to use the following function right after the @code{gcry_md_open}: + +@deftypefun gcry_error_t gcry_md_enable (gcry_md_hd_t @var{h}, int @var{algo}) + +Add the message digest algorithm @var{algo} to the digest object +described by handle @var{h}. Duplicated enabling of algorithms is +detected and ignored. +@end deftypefun + +If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must +be set using the function: + +@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen}) + +For use with the HMAC feature, set the MAC key to the value of @var{key} +of length @var{keylen}. There is no restriction on the length of the key. +@end deftypefun + + +After you are done with the hash calculation, you should release the +resources by using: + +@deftypefun void gcry_md_close (gcry_md_hd_t @var{h}) + +Release all resources of hash context @var{h}. @var{h} should not be +used after a call to this function. A @code{NULL} passed as @var{h} is +ignored. + +@end deftypefun + +Often you have to do several hash operations using the same algorithm. +To avoid the overhead of creating and releasing context, a reset function +is provided: + +@deftypefun void gcry_md_reset (gcry_md_hd_t @var{h}) + +Reset the current context to its initial state. This is effectively +identical to a close followed by an open and enabling all currently +active algorithms. +@end deftypefun + + +Often it is necessary to start hashing some data and then continue to +hash different data. To avoid hashing the same data several times (which +might not even be possible if the data is received from a pipe), a +snapshot of the current hash context can be taken and turned into a new +context: + +@deftypefun gcry_error_t gcry_md_copy (gcry_md_hd_t *@var{handle_dst}, gcry_md_hd_t @var{handle_src}) + +Create a new digest object as an exact copy of the object described by +handle @var{handle_src} and store it in @var{handle_dst}. The context +is not reset and you can continue to hash data using this context and +independently using the original context. +@end deftypefun + + +Now that we have prepared everything to calculate hashes, it is time to +see how it is actually done. There are two ways for this, one to +update the hash with a block of memory and one macro to update the hash +by just one character. Both methods can be used on the same hash context. + +@deftypefun void gcry_md_write (gcry_md_hd_t @var{h}, const void *@var{buffer}, size_t @var{length}) + +Pass @var{length} bytes of the data in @var{buffer} to the digest object +with handle @var{h} to update the digest values. This +function should be used for large blocks of data. +@end deftypefun + +@deftypefun void gcry_md_putc (gcry_md_hd_t @var{h}, int @var{c}) + +Pass the byte in @var{c} to the digest object with handle @var{h} to +update the digest value. This is an efficient function, implemented as +a macro to buffer the data before an actual update. +@end deftypefun + +The semantics of the hash functions do not provide for reading out intermediate +message digests because the calculation must be finalized first. This +finalization may for example include the number of bytes hashed in the +message digest or some padding. + +@deftypefun void gcry_md_final (gcry_md_hd_t @var{h}) + +Finalize the message digest calculation. This is not really needed +because @code{gcry_md_read} does this implicitly. After this has been +done no further updates (by means of @code{gcry_md_write} or +@code{gcry_md_putc} are allowed. Only the first call to this function +has an effect. It is implemented as a macro. +@end deftypefun + +The way to read out the calculated message digest is by using the +function: + +@deftypefun {unsigned char *} gcry_md_read (gcry_md_hd_t @var{h}, int @var{algo}) + +@code{gcry_md_read} returns the message digest after finalizing the +calculation. This function may be used as often as required but it will +always return the same value for one handle. The returned message digest +is allocated within the message context and therefore valid until the +handle is released or reseted (using @code{gcry_md_close} or +@code{gcry_md_reset}. @var{algo} may be given as 0 to return the only +enabled message digest or it may specify one of the enabled algorithms. +The function does return @code{NULL} if the requested algorithm has not +been enabled. +@end deftypefun + +Because it is often necessary to get the message digest of one block of +memory, a fast convenience function is available for this task: + +@deftypefun void gcry_md_hash_buffer (int @var{algo}, void *@var{digest}, const void *@var{buffer}, size_t @var{length}); + +@code{gcry_md_hash_buffer} is a shortcut function to calculate a message +digest of a buffer. This function does not require a context and +immediately returns the message digest of the @var{length} bytes at +@var{buffer}. @var{digest} must be allocated by the caller, large +enough to hold the message digest yielded by the the specified algorithm +@var{algo}. This required size may be obtained by using the function +@code{gcry_md_get_algo_dlen}. + +Note that this function will abort the process if an unavailable +algorithm is used. +@end deftypefun + +@c *********************************** +@c ***** MD info functions *********** +@c *********************************** + +Hash algorithms are identified by internal algorithm numbers (see +@code{gcry_md_open} for a list). However, in most applications they are +used by names, so two functions are available to map between string +representations and hash algorithm identifiers. + +@deftypefun {const char *} gcry_md_algo_name (int @var{algo}) + +Map the digest algorithm id @var{algo} to a string representation of the +algorithm name. For unknown algorithms this function returns the +string @code{"?"}. This function should not be used to test for the +availability of an algorithm. +@end deftypefun + +@deftypefun int gcry_md_map_name (const char *@var{name}) + +Map the algorithm with @var{name} to a digest algorithm identifier. +Returns 0 if the algorithm name is not known. Names representing +@acronym{ASN.1} object identifiers are recognized if the @acronym{IETF} +dotted format is used and the OID is prefixed with either "@code{oid.}" +or "@code{OID.}". For a list of supported OIDs, see the source code at +@file{cipher/md.c}. This function should not be used to test for the +availability of an algorithm. +@end deftypefun + +@deftypefun gcry_error_t gcry_md_get_asnoid (int @var{algo}, void *@var{buffer}, size_t *@var{length}) + +Return an DER encoded ASN.1 OID for the algorithm @var{algo} in the +user allocated @var{buffer}. @var{length} must point to variable with +the available size of @var{buffer} and receives after return the +actual size of the returned OID. The returned error code may be +@code{GPG_ERR_TOO_SHORT} if the provided buffer is to short to receive +the OID; it is possible to call the function with @code{NULL} for +@var{buffer} to have it only return the required size. The function +returns 0 on success. + +@end deftypefun + + +To test whether an algorithm is actually available for use, the +following macro should be used: + +@deftypefun gcry_error_t gcry_md_test_algo (int @var{algo}) + +The macro returns 0 if the algorithm @var{algo} is available for use. +@end deftypefun + +If the length of a message digest is not known, it can be retrieved +using the following function: + +@deftypefun {unsigned int} gcry_md_get_algo_dlen (int @var{algo}) + +Retrieve the length in bytes of the digest yielded by algorithm +@var{algo}. This is often used prior to @code{gcry_md_read} to allocate +sufficient memory for the digest. +@end deftypefun + + +In some situations it might be hard to remember the algorithm used for +the ongoing hashing. The following function might be used to get that +information: + +@deftypefun int gcry_md_get_algo (gcry_md_hd_t @var{h}) + +Retrieve the algorithm used with the handle @var{h}. Note that this +does not work reliable if more than one algorithm is enabled in @var{h}. +@end deftypefun + +The following macro might also be useful: + +@deftypefun int gcry_md_is_secure (gcry_md_hd_t @var{h}) + +This function returns true when the digest object @var{h} is allocated +in "secure memory"; i.e. @var{h} was created with the +@code{GCRY_MD_FLAG_SECURE}. +@end deftypefun + +@deftypefun int gcry_md_is_enabled (gcry_md_hd_t @var{h}, int @var{algo}) + +This function returns true when the algorithm @var{algo} has been +enabled for the digest object @var{h}. +@end deftypefun + + + +Tracking bugs related to hashing is often a cumbersome task which +requires to add a lot of printf statements into the code. +Libgcrypt provides an easy way to avoid this. The actual data +hashed can be written to files on request. + +@deftypefun void gcry_md_debug (gcry_md_hd_t @var{h}, const char *@var{suffix}) + +Enable debugging for the digest object with handle @var{h}. This +creates create files named @file{dbgmd-.} while doing the +actual hashing. @var{suffix} is the string part in the filename. The +number is a counter incremented for each new hashing. The data in the +file is the raw data as passed to @code{gcry_md_write} or +@code{gcry_md_putc}. If @code{NULL} is used for @var{suffix}, the +debugging is stopped and the file closed. This is only rarely required +because @code{gcry_md_close} implicitly stops debugging. +@end deftypefun + + +The following two deprecated macros are used for debugging by old code. +They shopuld be replaced by @code{gcry_md_debug}. + +@deftypefun void gcry_md_start_debug (gcry_md_hd_t @var{h}, const char *@var{suffix}) + +Enable debugging for the digest object with handle @var{h}. This +creates create files named @file{dbgmd-.} while doing the +actual hashing. @var{suffix} is the string part in the filename. The +number is a counter incremented for each new hashing. The data in the +file is the raw data as passed to @code{gcry_md_write} or +@code{gcry_md_putc}. +@end deftypefun + + +@deftypefun void gcry_md_stop_debug (gcry_md_hd_t @var{h}, int @var{reserved}) + +Stop debugging on handle @var{h}. @var{reserved} should be specified as +0. This function is usually not required because @code{gcry_md_close} +does implicitly stop debugging. +@end deftypefun + + +@c ********************************************************** +@c ******************* Random ***************************** +@c ********************************************************** +@node Random Numbers +@chapter Random Numbers + +@menu +* Quality of random numbers:: Libgcrypt uses different quality levels. +* Retrieving random numbers:: How to retrieve random numbers. +@end menu + +@node Quality of random numbers +@section Quality of random numbers + +@acronym{Libgcypt} offers random numbers of different quality levels: + +@deftp {Data type} gcry_random_level_t +The constants for the random quality levels are of this enum type. +@end deftp + +@table @code +@item GCRY_WEAK_RANDOM +For all functions, except for @code{gcry_mpi_randomize}, this level maps +to GCRY_STRONG_RANDOM. If you do not want this, consider using +@code{gcry_create_nonce}. +@item GCRY_STRONG_RANDOM +Use this level for session keys and similar purposes. +@item GCRY_VERY_STRONG_RANDOM +Use this level for long term key material. +@end table + +@node Retrieving random numbers +@section Retrieving random numbers + +@deftypefun void gcry_randomize (unsigned char *@var{buffer}, size_t @var{length}, enum gcry_random_level @var{level}) + +Fill @var{buffer} with @var{length} random bytes using a random quality +as defined by @var{level}. +@end deftypefun + +@deftypefun {void *} gcry_random_bytes (size_t @var{nbytes}, enum gcry_random_level @var{level}) + +Convenience function to allocate a memory block consisting of +@var{nbytes} fresh random bytes using a random quality as defined by +@var{level}. +@end deftypefun + +@deftypefun {void *} gcry_random_bytes_secure (size_t @var{nbytes}, enum gcry_random_level @var{level}) + +Convenience function to allocate a memory block consisting of +@var{nbytes} fresh random bytes using a random quality as defined by +@var{level}. This function differs from @code{gcry_random_bytes} in +that the returned buffer is allocated in a ``secure'' area of the +memory. +@end deftypefun + +@deftypefun void gcry_create_nonce (unsigned char *@var{buffer}, size_t @var{length}) + +Fill @var{buffer} with @var{length} unpredictable bytes. This is +commonly called a nonce and may also be used for initialization +vectors and padding. This is an extra function nearly independent of +the other random function for 3 reasons: It better protects the +regular random generator's internal state, provides better performance +and does not drain the precious entropy pool. + +@end deftypefun + + + +@c ********************************************************** +@c ******************* S-Expressions *********************** +@c ********************************************************** +@node S-expressions +@chapter S-expressions + +S-expressions are used by the public key functions to pass complex data +structures around. These LISP like objects are used by some +cryptographic protocols (cf. RFC-2692) and Libgcrypt provides functions +to parse and construct them. For detailed information, see +@cite{Ron Rivest, code and description of S-expressions, +@uref{http://theory.lcs.mit.edu/~rivest/sexp.html}}. + +@menu +* Data types for S-expressions:: Data types related with S-expressions. +* Working with S-expressions:: How to work with S-expressions. +@end menu + +@node Data types for S-expressions +@section Data types for S-expressions + +@deftp {Data type} gcry_sexp_t +The @code{gcry_sexp_t} type describes an object with the Libgcrypt internal +representation of an S-expression. +@end deftp + +@node Working with S-expressions +@section Working with S-expressions + +@noindent +There are several functions to create an Libgcrypt S-expression object +from its external representation or from a string template. There is +also a function to convert the internal representation back into one of +the external formats: + + +@deftypefun gcry_error_t gcry_sexp_new (@w{gcry_sexp_t *@var{r_sexp}}, @w{const void *@var{buffer}}, @w{size_t @var{length}}, @w{int @var{autodetect}}) + +This is the generic function to create an new S-expression object from +its external representation in @var{buffer} of @var{length} bytes. On +success the result is stored at the address given by @var{r_sexp}. +With @var{autodetect} set to 0, the data in @var{buffer} is expected to +be in canonized format, with @var{autodetect} set to 1 the parses any of +the defined external formats. If @var{buffer} does not hold a valid +S-expression an error code is returned and @var{r_sexp} set to +@code{NULL}. +Note that the caller is responsible for releasing the newly allocated +S-expression using @code{gcry_sexp_release}. +@end deftypefun + +@deftypefun gcry_error_t gcry_sexp_create (@w{gcry_sexp_t *@var{r_sexp}}, @w{void *@var{buffer}}, @w{size_t @var{length}}, @w{int @var{autodetect}}, @w{void (*@var{freefnc})(void*)}) + +This function is identical to @code{gcry_sexp_new} but has an extra +argument @var{freefnc}, which, when not set to @code{NULL}, is expected +to be a function to release the @var{buffer}; most likely the standard +@code{free} function is used for this argument. This has the effect of +transferring the ownership of @var{buffer} to the created object in +@var{r_sexp}. The advantage of using this function is that Libgcrypt +might decide to directly use the provided buffer and thus avoid extra +copying. +@end deftypefun + +@deftypefun gcry_error_t gcry_sexp_sscan (@w{gcry_sexp_t *@var{r_sexp}}, @w{size_t *@var{erroff}}, @w{const char *@var{buffer}}, @w{size_t @var{length}}) + +This is another variant of the above functions. It behaves nearly +identical but provides an @var{erroff} argument which will receive the +offset into the buffer where the parsing stopped on error. +@end deftypefun + +@deftypefun gcry_error_t gcry_sexp_build (@w{gcry_sexp_t *@var{r_sexp}}, @w{size_t *@var{erroff}}, @w{const char *@var{format}, ...}) + +This function creates an internal S-expression from the string template +@var{format} and stores it at the address of @var{r_sexp}. If there is a +parsing error, the function returns an appropriate error code and stores +the offset into @var{format} where the parsing stopped in @var{erroff}. +The function supports a couple of printf-like formatting characters and +expects arguments for some of these escape sequences right after +@var{format}. The following format characters are defined: + +@table @samp +@item %m +The next argument is expected to be of type @code{gcry_mpi_t} and a copy of +its value is inserted into the resulting S-expression. +@item %s +The next argument is expected to be of type @code{char *} and that +string is inserted into the resulting S-expression. +@item %d +The next argument is expected to be of type @code{int} and its value is +inserted into the resulting S-expression. +@item %b +The next argument is expected to be of type @code{int} directly +followed by an argument of type @code{char *}. This represents a +buffer of given length to be inserted into the resulting regular +expression. +@end table + +@noindent +No other format characters are defined and would return an error. Note +that the format character @samp{%%} does not exists, because a percent +sign is not a valid character in an S-expression. +@end deftypefun + +@deftypefun void gcry_sexp_release (@w{gcry_sexp_t @var{sexp}}) + +Release the S-expression object @var{sexp}. +@end deftypefun + + +@noindent +The next 2 functions are used to convert the internal representation +back into a regular external S-expression format and to show the +structure for debugging. + +@deftypefun size_t gcry_sexp_sprint (@w{gcry_sexp_t @var{sexp}}, @w{int @var{mode}}, @w{char *@var{buffer}}, @w{size_t @var{maxlength}}) + +Copies the S-expression object @var{sexp} into @var{buffer} using the +format specified in @var{mode}. @var{maxlength} must be set to the +allocated length of @var{buffer}. The function returns the actual +length of valid bytes put into @var{buffer} or 0 if the provided buffer +is too short. Passing @code{NULL} for @var{buffer} returns the required +length for @var{buffer}. For convenience reasons an extra byte with +value 0 is appended to the buffer. + +@noindent +The following formats are supported: + +@table @code +@item GCRYSEXP_FMT_DEFAULT +Returns a convenient external S-expression representation. + +@item GCRYSEXP_FMT_CANON +Return the S-expression in canonical format. + +@item GCRYSEXP_FMT_BASE64 +Not currently supported. + +@item GCRYSEXP_FMT_ADVANCED +Returns the S-expression in advanced format. +@end table +@end deftypefun + +@deftypefun void gcry_sexp_dump (@w{gcry_sexp_t @var{sexp}}) + +Dumps @var{sexp} in a format suitable for debugging to Libgcrypt's +logging stream. +@end deftypefun + +@noindent +Often canonical encoding is used in the external representation. The +following function can be used to check for valid encoding and to learn +the length of the S-expression" + +@deftypefun size_t gcry_sexp_canon_len (@w{const unsigned char *@var{buffer}}, @w{size_t @var{length}}, @w{size_t *@var{erroff}}, @w{int *@var{errcode}}) + +Scan the canonical encoded @var{buffer} with implicit length values and +return the actual length this S-expression uses. For a valid S-expression +it should never return 0. If @var{length} is not 0, the maximum +length to scan is given; this can be used for syntax checks of +data passed from outside. @var{errcode} and @var{erroff} may both be +passed as @code{NULL}. + +@end deftypefun + + +@noindent +There are a couple of functions to parse S-expressions and retrieve +elements: + +@deftypefun gcry_sexp_t gcry_sexp_find_token (@w{const gcry_sexp_t @var{list}}, @w{const char *@var{token}}, @w{size_t @var{toklen}}) + +Scan the S-expression for a sublist with a type (the car of the list) +matching the string @var{token}. If @var{toklen} is not 0, the token is +assumed to be raw memory of this length. The function returns a newly +allocated S-expression consisting of the found sublist or @code{NULL} +when not found. +@end deftypefun + + +@deftypefun int gcry_sexp_length (@w{const gcry_sexp_t @var{list}}) + +Return the length of the @var{list}. For a valid S-expression this +should be at least 1. +@end deftypefun + + +@deftypefun gcry_sexp_t gcry_sexp_nth (@w{const gcry_sexp_t @var{list}}, @w{int @var{number}}) + +Create and return a new S-expression from the element with index @var{number} in +@var{list}. Note that the first element has the index 0. If there is +no such element, @code{NULL} is returned. +@end deftypefun + +@deftypefun gcry_sexp_t gcry_sexp_car (@w{const gcry_sexp_t @var{list}}) + +Create and return a new S-expression from the first element in +@var{list}; this called the "type" and should always exist and be a +string. @code{NULL} is returned in case of a problem. +@end deftypefun + +@deftypefun gcry_sexp_t gcry_sexp_cdr (@w{const gcry_sexp_t @var{list}}) + +Create and return a new list form all elements except for the first one. +Note that this function may return an invalid S-expression because it +is not guaranteed, that the type exists and is a string. However, for +parsing a complex S-expression it might be useful for intermediate +lists. Returns @code{NULL} on error. +@end deftypefun + + +@deftypefun {const char *} gcry_sexp_nth_data (@w{const gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{size_t *@var{datalen}}) + +This function is used to get data from a @var{list}. A pointer to the +actual data with index @var{number} is returned and the length of this +data will be stored to @var{datalen}. If there is no data at the given +index or the index represents another list, @code{NULL} is returned. +@strong{Caution:} The returned pointer is valid as long as @var{list} is +not modified or released. + +@noindent +Here is an example on how to extract and print the surname (Meier) from +the S-expression @samp{(Name Otto Meier (address Burgplatz 3))}: + +@example +size_t len; +const char *name; + +name = gcry_sexp_nth_data (list, 2, &len); +printf ("my name is %.*s\n", (int)len, name); +@end example +@end deftypefun + +@deftypefun {char *} gcry_sexp_nth_string (@w{gcry_sexp_t @var{list}}, @w{int @var{number}}) + +This function is used to get and convert data from a @var{list}. The +data is assumed to be a Nul terminated string. The caller must +release this returned value using @code{gcry_free}. If there is +no data at the given index, the index represents a list or the value +can't be converted to a string, @code{NULL} is returned. +@end deftypefun + +@deftypefun gcry_mpi_t gcry_sexp_nth_mpi (@w{gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{int @var{mpifmt}}) + +This function is used to get and convert data from a @var{list}. This +data is assumed to be an MPI stored in the format described by +@var{mpifmt} and returned as a standard Libgcrypt MPI. The caller must +release this returned value using @code{gcry_mpi_release}. If there is +no data at the given index, the index represents a list or the value +can't be converted to an MPI, @code{NULL} is returned. +@end deftypefun + + +@c ********************************************************** +@c ******************* MPIs ******** *********************** +@c ********************************************************** +@node MPI library +@chapter MPI library + +@menu +* Data types:: MPI related data types. +* Basic functions:: First steps with MPI numbers. +* MPI formats:: External representation of MPIs. +* Calculations:: Performing MPI calculations. +* Comparisons:: How to compare MPI values. +* Bit manipulations:: How to access single bits of MPI values. +* Miscellaneous:: Miscellaneous MPI functions. +@end menu + +Public key cryptography is based on mathematics with large numbers. To +implement the public key functions, a library for handling these large +numbers is required. Because of the general usefulness of such a +library, its interface is exposed by Libgcrypt. +In the context of Libgcrypt and in most other applications, these large +numbers are called MPIs (multi-precision-integers). + +@node Data types +@section Data types + +@deftp {Data type} {gcry_mpi_t} +This type represents an object to hold an MPI. +@end deftp + +@node Basic functions +@section Basic functions + +@noindent +To work with MPIs, storage must be allocated and released for the +numbers. This can be done with one of these functions: + +@deftypefun gcry_mpi_t gcry_mpi_new (@w{unsigned int @var{nbits}}) + +Allocate a new MPI object, initialize it to 0 and initially allocate +enough memory for a number of at least @var{nbits}. This pre-allocation is +only a small performance issue and not actually necessary because +Libgcrypt automatically re-allocates the required memory. +@end deftypefun + +@deftypefun gcry_mpi_t gcry_mpi_snew (@w{unsigned int @var{nbits}}) + +This is identical to @code{gcry_mpi_new} but allocates the MPI in the so +called "secure memory" which in turn will take care that all derived +values will also be stored in this "secure memory". Use this for highly +confidential data like private key parameters. +@end deftypefun + +@deftypefun gcry_mpi_t gcry_mpi_copy (@w{const gcry_mpi_t @var{a}}) + +Create a new MPI as the exact copy of @var{a}. +@end deftypefun + + +@deftypefun void gcry_mpi_release (@w{gcry_mpi_t @var{a}}) + +Release the MPI @var{a} and free all associated resources. Passing +@code{NULL} is allowed and ignored. When a MPI stored in the "secure +memory" is released, that memory gets wiped out immediately. +@end deftypefun + +@noindent +The simplest operations are used to assign a new value to an MPI: + +@deftypefun gcry_mpi_t gcry_mpi_set (@w{gcry_mpi_t @var{w}}, @w{const gcry_mpi_t @var{u}}) + +Assign the value of @var{u} to @var{w} and return @var{w}. If +@code{NULL} is passed for @var{w}, a new MPI is allocated, set to the +value of @var{u} and returned. +@end deftypefun + +@deftypefun gcry_mpi_t gcry_mpi_set_ui (@w{gcry_mpi_t @var{w}}, @w{unsigned long @var{u}}) + +Assign the value of @var{u} to @var{w} and return @var{w}. If +@code{NULL} is passed for @var{w}, a new MPI is allocated, set to the +value of @var{u} and returned. This function takes an @code{unsigned +int} as type for @var{u} and thus it is only possible to set @var{w} to +small values (usually up to the word size of the CPU). +@end deftypefun + +@deftypefun void gcry_mpi_swap (@w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}}) + +Swap the values of @var{a} and @var{b}. +@end deftypefun + +@node MPI formats +@section MPI formats + +@noindent +The following functions are used to convert between an external +representation of an MPI and the internal one of Libgcrypt. + +@deftypefun gcry_error_t gcry_mpi_scan (@w{gcry_mpi_t *@var{r_mpi}}, @w{enum gcry_mpi_format @var{format}}, @w{const unsigned char *@var{buffer}}, @w{size_t @var{buflen}}, @w{size_t *@var{nscanned}}) + +Convert the external representation of an integer stored in @var{buffer} +with a length of @var{buflen} into a newly created MPI returned which +will be stored at the address of @var{r_mpi}. For certain formats the +length argument is not required and should be passed as @code{0}. After a +successful operation the variable @var{nscanned} receives the number of +bytes actually scanned unless @var{nscanned} was given as +@code{NULL}. @var{format} describes the format of the MPI as stored in +@var{buffer}: + +@table @code +@item GCRYMPI_FMT_STD +2-complement stored without a length header. + +@item GCRYMPI_FMT_PGP +As used by OpenPGP (only defined as unsigned). This is basically +@code{GCRYMPI_FMT_STD} with a 2 byte big endian length header. + +@item GCRYMPI_FMT_SSH +As used in the Secure Shell protocol. This is @code{GCRYMPI_FMT_STD} +with a 4 byte big endian header. + +@item GCRYMPI_FMT_HEX +Stored as a C style string with each byte of the MPI encoded as 2 hex +digits. When using this format, @var{buflen} must be zero. + +@item GCRYMPI_FMT_USG +Simple unsigned integer. +@end table + +@noindent +Note that all of the above formats store the integer in big-endian +format (MSB first). +@end deftypefun + + +@deftypefun gcry_error_t gcry_mpi_print (@w{enum gcry_mpi_format @var{format}}, @w{unsigned char *@var{buffer}}, @w{size_t @var{buflen}}, @w{size_t *@var{nwritten}}, @w{const gcry_mpi_t @var{a}}) + +Convert the MPI @var{a} into an external representation described by +@var{format} (see above) and store it in the provided @var{buffer} +which has a usable length of at least the @var{buflen} bytes. If +@var{nwritten} is not NULL, it will receive the number of bytes +actually stored in @var{buffer} after a successful operation. +@end deftypefun + +@deftypefun gcry_error_t gcry_mpi_aprint (@w{enum gcry_mpi_format @var{format}}, @w{unsigned char **@var{buffer}}, @w{size_t *@var{nbytes}}, @w{const gcry_mpi_t @var{a}}) + +Convert the MPI @var{a} into an external representation described by +@var{format} (see above) and store it in a newly allocated buffer which +address will be stored in the variable @var{buffer} points to. The +number of bytes stored in this buffer will be stored in the variable +@var{nbytes} points to, unless @var{nbytes} is @code{NULL}. +@end deftypefun + +@deftypefun void gcry_mpi_dump (@w{const gcry_mpi_t @var{a}}) + +Dump the value of @var{a} in a format suitable for debugging to +Libgcrypt's logging stream. Note that one leading space but no trailing +space or linefeed will be printed. It is okay to pass @code{NULL} for +@var{a}. +@end deftypefun + + +@node Calculations +@section Calculations + +@noindent +Basic arithmetic operations: + +@deftypefun void gcry_mpi_add (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}) + +@math{@var{w} = @var{u} + @var{v}}. +@end deftypefun + + +@deftypefun void gcry_mpi_add_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}}) + +@math{@var{w} = @var{u} + @var{v}}. Note that @var{v} is an unsigned integer. +@end deftypefun + + +@deftypefun void gcry_mpi_addm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}}) + +@math{@var{w} = @var{u} + @var{v} \bmod @var{m}}. +@end deftypefun + +@deftypefun void gcry_mpi_sub (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}) + +@math{@var{w} = @var{u} - @var{v}}. +@end deftypefun + +@deftypefun void gcry_mpi_sub_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}}) + +@math{@var{w} = @var{u} - @var{v}}. @var{v} is an unsigned integer. +@end deftypefun + +@deftypefun void gcry_mpi_subm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}}) + +@math{@var{w} = @var{u} - @var{v} \bmod @var{m}}. +@end deftypefun + +@deftypefun void gcry_mpi_mul (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}) + +@math{@var{w} = @var{u} * @var{v}}. +@end deftypefun + +@deftypefun void gcry_mpi_mul_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}}) + +@math{@var{w} = @var{u} * @var{v}}. @var{v} is an unsigned integer. +@end deftypefun + +@deftypefun void gcry_mpi_mulm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}}) + +@math{@var{w} = @var{u} * @var{v} \bmod @var{m}}. +@end deftypefun + +@deftypefun void gcry_mpi_mul_2exp (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{e}}) + +@c FIXME: I am in need for a real TeX{info} guru: +@c I don't know why TeX can grok @var{e} here. +@math{@var{w} = @var{u} * 2^e}. +@end deftypefun + +@deftypefun void gcry_mpi_div (@w{gcry_mpi_t @var{q}}, @w{gcry_mpi_t @var{r}}, @w{gcry_mpi_t @var{dividend}}, @w{gcry_mpi_t @var{divisor}}, @w{int @var{round}}) + +@math{@var{q} = @var{dividend} / @var{divisor}}, @math{@var{r} = +@var{dividend} \bmod @var{divisor}}. @var{q} and @var{r} may be passed +as @code{NULL}. @var{round} should be negative or 0. +@end deftypefun + +@deftypefun void gcry_mpi_mod (@w{gcry_mpi_t @var{r}}, @w{gcry_mpi_t @var{dividend}}, @w{gcry_mpi_t @var{divisor}}) + +@math{@var{r} = @var{dividend} \bmod @var{divisor}}. +@end deftypefun + +@deftypefun void gcry_mpi_powm (@w{gcry_mpi_t @var{w}}, @w{const gcry_mpi_t @var{b}}, @w{const gcry_mpi_t @var{e}}, @w{const gcry_mpi_t @var{m}}) + +@c I don't know why TeX can grok @var{e} here. +@math{@var{w} = @var{b}^e \bmod @var{m}}. +@end deftypefun + +@deftypefun int gcry_mpi_gcd (@w{gcry_mpi_t @var{g}}, @w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}}) + +Set @var{g} to the greatest common divisor of @var{a} and @var{b}. +Return true if the @var{g} is 1. +@end deftypefun + +@deftypefun int gcry_mpi_invm (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{m}}) + +Set @var{x} to the multiplicative inverse of @math{@var{a} \bmod @var{m}}. +Return true if the inverse exists. +@end deftypefun + + +@node Comparisons +@section Comparisons + +@noindent +The next 2 functions are used to compare MPIs: + + +@deftypefun int gcry_mpi_cmp (@w{const gcry_mpi_t @var{u}}, @w{const gcry_mpi_t @var{v}}) + +Compare the multi-precision-integers number @var{u} and @var{v} +returning 0 for equality, a positive value for @var{u} > @var{v} and a +negative for @var{u} < @var{v}. +@end deftypefun + +@deftypefun int gcry_mpi_cmp_ui (@w{const gcry_mpi_t @var{u}}, @w{unsigned long @var{v}}) + +Compare the multi-precision-integers number @var{u} with the unsigned +integer @var{v} returning 0 for equality, a positive value for @var{u} > +@var{v} and a negative for @var{u} < @var{v}. +@end deftypefun + + +@node Bit manipulations +@section Bit manipulations + +@noindent +There are a couple of functions to get information on arbitrary bits +in an MPI and to set or clear them: + +@deftypefun {unsigned int} gcry_mpi_get_nbits (@w{gcry_mpi_t @var{a}}) + +Return the number of bits required to represent @var{a}. +@end deftypefun + +@deftypefun int gcry_mpi_test_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Return true if bit number @var{n} (counting from 0) is set in @var{a}. +@end deftypefun + +@deftypefun void gcry_mpi_set_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Set bit number @var{n} in @var{a}. +@end deftypefun + +@deftypefun void gcry_mpi_clear_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Clear bit number @var{n} in @var{a}. +@end deftypefun + +@deftypefun void gcry_mpi_set_highbit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Set bit number @var{n} in @var{a} and clear all bits greater than @var{n}. +@end deftypefun + +@deftypefun void gcry_mpi_clear_highbit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Clear bit number @var{n} in @var{a} and all bits greater than @var{n}. +@end deftypefun + +@deftypefun void gcry_mpi_rshift (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Shift the value of @var{a} by @var{n} bits to the right and store the +result in @var{x}. +@end deftypefun + +@deftypefun void gcry_mpi_lshift (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}}) + +Shift the value of @var{a} by @var{n} bits to the left and store the +result in @var{x}. +@end deftypefun + +@node Miscellaneous +@section Miscellaneous + +@deftypefun gcry_mpi_t gcry_mpi_set_opaque (@w{gcry_mpi_t @var{a}}, @w{void *@var{p}}, @w{unsigned int @var{nbits}}) + +Store @var{nbits} of the value @var{p} points to in @var{a} and mark +@var{a} as an opaque value (i.e. an value that can't be used for any +math calculation and is only used to store an arbitrary bit pattern in +@var{a}). + +WARNING: Never use an opaque MPI for actual math operations. The only +valid functions are gcry_mpi_get_opaque and gcry_mpi_release. Use +gcry_mpi_scan to convert a string of arbitrary bytes into an MPI. + +@end deftypefun + +@deftypefun {void *} gcry_mpi_get_opaque (@w{gcry_mpi_t @var{a}}, @w{unsigned int *@var{nbits}}) + +Return a pointer to an opaque value stored in @var{a} and return its +size in @var{nbits}. Note that the returned pointer is still owned by +@var{a} and that the function should never be used for an non-opaque +MPI. +@end deftypefun + +@deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}}) + +Set the @var{flag} for the MPI @var{a}. Currently only the flag +@code{GCRYMPI_FLAG_SECURE} is allowed to convert @var{a} into an MPI +stored in "secure memory". +@end deftypefun + +@deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}}) + +Clear @var{flag} for the multi-precision-integers @var{a}. Note that +this function is currently useless as no flags are allowed. +@end deftypefun + +@deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}}) + +Return true when the @var{flag} is set for @var{a}. +@end deftypefun + +@deftypefun void gcry_mpi_randomize (@w{gcry_mpi_t @var{w}}, @w{unsigned int @var{nbits}}, @w{enum gcry_random_level @var{level}}) + +Set the multi-precision-integers @var{w} to a random value of +@var{nbits}, using random data quality of level @var{level}. In case +@var{nbits} is not a multiple of a byte, @var{nbits} is rounded up to +the next byte boundary. When using a @var{level} of +@code{GCRY_WEAK_RANDOM} this function makes use of +@code{gcry_create_nonce}. +@end deftypefun + +@c ********************************************************** +@c ******************** Prime numbers *********************** +@c ********************************************************** +@node Prime numbers +@chapter Prime numbers + +@menu +* Generation:: Generation of new prime numbers. +* Checking:: Checking if a given number is prime. +@end menu + +@node Generation +@section Generation + +@deftypefun gcry_error_t gcry_prime_generate (gcry_mpi_t *@var{prime},unsigned int @var{prime_bits}, unsigned int @var{factor_bits}, gcry_mpi_t **@var{factors}, gcry_prime_check_func_t @var{cb_func}, void *@var{cb_arg}, gcry_random_level_t @var{random_level}, unsigned int @var{flags}) + +Generate a new prime number of @var{prime_bits} bits and store it in +@var{prime}. If @var{factor_bits} is non-zero, one of the prime factors +of (@var{prime} - 1) / 2 must be @var{factor_bits} bits long. If +@var{factors} is non-zero, allocate a new, @code{NULL}-terminated array +holding the prime factors and store it in @var{factors}. @var{flags} +might be used to influence the prime number generation process. +@end deftypefun + +@deftypefun gcry_error_t gcry_prime_group_generator (gcry_mpi_t *@var{r_g}, gcry_mpi_t @var{prime}, gcry_mpi_t *@var{factors}, gcry_mpi_t @var{start_g}) + +Find a generator for @var{prime} where the factorization of +(@var{prime}-1) is in the @code{NULL} terminated array @var{factors}. +Return the generator as a newly allocated MPI in @var{r_g}. If +@var{start_g} is not NULL, use this as the start for the search. +@end deftypefun + +@deftypefun void gcry_prime_release_factors (gcry_mpi_t *@var{factors}) + +Convenience function to release the @var{factors} array. +@end deftypefun + +@node Checking +@section Checking + +@deftypefun gcry_error_t gcry_prime_check (gcry_mpi_t @var{p}, unsigned int @var{flags}) + +Check wether the number @var{p} is prime. Returns zero in case @var{p} +is indeed a prime, returns @code{GPG_ERR_NO_PRIME} in case @var{p} is +not a prime and a different error code in case something went horribly +wrong. +@end deftypefun + +@c ********************************************************** +@c ******************** Utilities *************************** +@c ********************************************************** +@node Utilities +@chapter Utilities + +@menu +* Memory allocation:: Functions related with memory allocation. +@end menu + +@node Memory allocation +@section Memory allocation + +@deftypefun {void *} gcry_malloc (size_t @var{n}) + +This function tries to allocate @var{n} bytes of memory. On success +it returns a pointer to the memory area, in an out-of-core condition, +it returns NULL. +@end deftypefun + +@deftypefun {void *} gcry_malloc_secure (size_t @var{n}) +Like @code{gcry_malloc}, but uses secure memory. +@end deftypefun + +@deftypefun {void *} gcry_calloc (size_t @var{n}) + +This function tries to allocate @var{n} bytes of cleared memory +(i.e. memory that is initialized with zero bytes). On success it +returns a pointer to the memory area, in an out-of-core condition, it +returns NULL. +@end deftypefun + +@deftypefun {void *} gcry_calloc_secure (size_t @var{n}) +Like @code{gcry_calloc}, but uses secure memory. +@end deftypefun + +@deftypefun {void *} gcry_realloc (void *@var{p}, size_t @var{n}) + +This function tries to resize the memory area pointed to by @var{p} to +@var{n} bytes. On success it returns a pointer to the new memory +area, in an out-of-core condition, it returns NULL. Depending on +whether the memory pointed to by @var{p} is secure memory or not, +gcry_realloc tries to use secure memory as well. +@end deftypefun + +@deftypefun void gcry_free (void *@var{p}) +Release the memory area pointed to by @var{p}. +@end deftypefun + +@c ********************************************************** +@c ***************** Architecure Overview ***************** +@c ********************************************************** +@node Architecture +@chapter Architecture + +This chapter describes the internal architecture of Libgcrypt. + +Libgcrypt is a function library written in ISO C-90. Any compliant +compiler should be able to build Libgcrypt as long as the target is +either a POSIX platform or compatible to the API used by Windows NT. +Provisions have been take so that the library can be directly used from +C++ applications; however building with a C++ compiler is not supported. + +Building Libgcrypt is done by using the common @code{./configure && make} +approach. The configure command is included in the source distribution +and as a portable shell script it works on any Unix-alike system. The +result of running the configure script are a C header file +(@file{config.h}), customized Makefiles, the setup of symbolic links and +a few other things. After that the make tool builds and optionally +installs the library and the documentation. See the files +@file{INSTALL} and @file{README} in the source distribution on how to do +this. + +Libgcrypt is developed using a Subversion@footnote{A version control +system available for many platforms} repository. Although all released +versions are tagged in this repository, they should not be used to build +production versions of Libgcrypt. Instead released tarballs should be +used. These tarballs are available from several places with the master +copy at @indicateurl{ftp://ftp.gnupg.org/gcrypt/libgcrypt/}. +Announcements of new releases are posted to the +@indicateurl{gnupg-announce@@gnupg.org} mailing list@footnote{See +@url{http://www.gnupg.org/documentation/mailing-lists.en.html} for +details.}. + + +@float Figure,fig:subsystems +@caption{Libgcrypt subsystems} +@center @image{libgcrypt-modules, 150mm,,Libgcrypt subsystems} +@end float + +Libgcrypt consists of several subsystems (@pxref{fig:subsystems}) and +all these subsystems provide a public API; this includes the helper +subsystems like the one for S-expressions. The API style depends on the +subsystem; in general an open-use-close approach is implemented. The +open returns a handle to a context used for all further operations on +this handle, several functions may then be used on this handle and a +final close function releases all resources associated with the handle. + +@menu +* Public-Key Subsystem Architecture:: About public keys. +* Symmetric Encryption Subsystem Architecture:: About standard ciphers. +* Hashing and MACing Subsystem Architecture:: About hashing. +* Multi-Precision-Integer Subsystem Architecture:: About big integers. +* Prime-Number-Generator Subsystem Architecture:: About prime numbers. +* Random-Number Subsystem Architecture:: About random stuff. +@c * Helper Subsystems Architecture:: About other stuff. +@end menu + + + +@node Public-Key Subsystem Architecture +@section Public-Key Architecture + +Libgcrypt implements two interfaces for public key cryptography: The +standard interface is PK interface using functions in the +@code{gcry_pk_} name space. The AC interface in an alternative one +which is now deprecated and will not be further described. The AC +interface is also disabled in FIPS mode. + +Because public key cryptography is almost always used to process small +amounts of data (hash values or session keys), the interface is not +implemented using the open-use-close paradigm, but with single +self-contained functions. Due to the wide variety of parameters +required by different algorithms S-expressions, as flexible way to +convey these parameters, are used. There is a set of helper functions +to work with these S-expressions. +@c see @xref{S-expression Subsystem Architecture}. + +Aside of functions to register new algorithms, map algorithms names to +algorithms identifiers and to lookup properties of a key, the +following main functions are available: + +@table @code + +@item gcry_pk_encrypt +Encrypt data using a public key. + +@item gcry_pk_decrypt +Decrypt data using a private key. + +@item gcry_pk_sign +Sign data using a private key. + +@item gcry_pk_verify +Verify that a signature matches the data. + +@item gcry_pk_testkey +Perform a consistency over a public or private key. + +@item gcry_pk_genkey +Create a new public/private key pair. + +@end table + +With the help of the module registration system all these functions +lookup the module implementing the algorithm and pass the actual work +to that module. The parsing of the S-expression input and the +construction of S-expression for the return values is done by the high +level code (@file{cipher/pubkey.c}). Thus the internal interface +between the algorithm modules and the high level functions passes data +in a custom format. The interface to the modules is published +(@file{gcrypt-modules.h}) so that it can used to register external +implementations of algorithms with Libgcrypt. However, for some +algorithms this module interface is to limited and thus for the +internal modules an extra interface is sometimes used to convey more +information. + +By default Libgcrypt uses a blinding technique for RSA decryption to +mitigate real world timing attacks over a network: Instead of using +the RSA decryption directly, a blinded value @math{y = x r^{e} \bmod n} +is decrypted and the unblinded value @math{x' = y' r^{-1} \bmod n} +returned. The blinding value @math{r} is a random value with the size +of the modulus @math{n} and generated with @code{GCRY_WEAK_RANDOM} +random level. + +@cindex X9.31 +@cindex FIPS 186 +The algorithm used for RSA and DSA key generation depends on whether +Libgcrypt is operated in standard or in FIPS mode. In standard mode +an algorithm based on the Lim-Lee prime number generator is used. In +FIPS mode RSA keys are generated as specified in ANSI X9.31 (1998) and +DSA keys as specified in FIPS 186-2. + + + +@node Symmetric Encryption Subsystem Architecture +@section Symmetric Encryption Subsystem Architecture + +The interface to work with symmetric encryption algorithms is made up +of functions from the @code{gcry_cipher_} name space. The +implementation follows the open-use-close paradigm and uses registered +algorithm modules for the actual work. Unless a module implements +optimized cipher mode implementations, the high level code +(@file{cipher/cipher.c}) implements the modes and calls the core +algorithm functions to process each block. + +The most important functions are: + +@table @code + +@item gcry_cipher_open +Create a new instance to encrypt or decrypt using a specified +algorithm and mode. + +@item gcry_cipher_close +Release an instance. + +@item gcry_cipher_setkey +Set a key to be used for encryption or decryption. + +@item gcry_cipher_setiv +Set an initialization vector to be used for encryption or decryption. + +@item gcry_cipher_encrypt +@itemx gcry_cipher_decrypt +Encrypt or decrypt data. These functions may be called with arbitrary +amounts of data and as often as needed to encrypt or decrypt all data. + +@end table + +There are also functions to query properties of algorithms or context, +like block length, key length, map names or to enable features like +padding methods. + + + +@node Hashing and MACing Subsystem Architecture +@section Hashing and MACing Subsystem Architecture + +The interface to work with message digests and CRC algorithms is made +up of functions from the @code{gcry_md_} name space. The +implementation follows the open-use-close paradigm and uses registered +algorithm modules for the actual work. Although CRC algorithms are +not considered cryptographic hash algorithms, they share enough +properties so that it makes sense to handle them in the same way. +It is possible to use several algorithms at once with one context and +thus compute them all on the same data. + +The most important functions are: + +@table @code +@item gcry_md_open +Create a new message digest instance and optionally enable one +algorithm. A flag may be used to turn the message digest algorithm +into a HMAC algorithm. + +@item gcry_md_enable +Enable an additional algorithm for the instance. + +@item gcry_md_setkey +Set the key for the MAC. + +@item gcry_md_write +Pass more data for computing the message digest to an instance. + +@item gcry_md_putc +Buffered version of @code{gcry_md_write} implemented as a macro. + +@item gcry_md_read +Finalize the computation of the message digest or HMAC and return the +result. + +@item gcry_md_close +Release an instance + +@item gcry_md_hash_buffer +Convenience function to directly compute a message digest over a +memory buffer without the need to create an instance first. + +@end table + +There are also functions to query properties of algorithms or the +instance, like enabled algorithms, digest length, map algorithm names. +it is also possible to reset an instance or to copy the current state +of an instance at any time. Debug functions to write the hashed data +to files are available as well. + + + +@node Multi-Precision-Integer Subsystem Architecture +@section Multi-Precision-Integer Subsystem Architecture + +The implementation of Libgcrypt's big integer computation code is +based on an old release of GNU Multi-Precision Library (GMP). The +decision not to use the GMP library directly was due to stalled +development at that time and due to security requirements which could +not be provided by the code in GMP. As GMP does, Libgcrypt provides +high performance assembler implementations of low level code for +several CPUS to gain much better performance than with a generic C +implementation. + +@noindent +Major features of Libgcrypt's multi-precision-integer code compared to +GMP are: + +@itemize +@item +Avoidance of stack based allocations to allow protection against +swapping out of sensitive data and for easy zeroing of sensitive +intermediate results. + +@item +Optional use of secure memory and tracking of its use so that results +are also put into secure memory. + +@item +MPIs are identified by a handle (implemented as a pointer) to give +better control over allocations and to augment them with extra +properties like opaque data. + +@item +Removal of unnecessary code to reduce complexity. + +@item +Functions specialized for public key cryptography. + +@end itemize + + + +@node Prime-Number-Generator Subsystem Architecture +@section Prime-Number-Generator Subsystem Architecture + +Libgcrypt provides an interface to its prime number generator. These +functions make use of the internal prime number generator which is +required for the generation for public key key pairs. The plain prime +checking function is exported as well. + +The generation of random prime numbers is based on the Lim and Lee +algorithm to create practically save primes.@footnote{Chae Hoon Lim +and Pil Joong Lee. A key recovery attack on discrete log-based shemes +using a prime order subgroup. In Burton S. Kaliski Jr., editor, +Advances in Cryptology: Crypto '97, pages 249­-263, Berlin / +Heidelberg / New York, 1997. Springer-Verlag. Described on page 260.} +This algorithm creates a pool of smaller primes, select a few of them +to create candidate primes of the form @math{2 * p_0 * p_1 * ... * p_n ++ 1}, tests the candidate for primality and permutates the pool until +a prime has been found. It is possible to clamp one of the small +primes to a certain size to help DSA style algorithms. Because most +of the small primes in the pool are not used for the resulting prime +number, they are saved for later use (see @code{save_pool_prime} and +@code{get_pool_prime} in @file{cipher/primegen.c}). The prime +generator optionally supports the finding of an appropriate generator. + +@noindent +The primality test works in three steps: + +@enumerate +@item +The standard sieve algorithm using the primes up to 4999 is used as a +quick first check. + +@item +A Fermat test filters out almost all non-primes. + +@item +A 5 round Rabin-Miller test is finally used. The first round uses a +witness of 2, whereas the next rounds use a random witness. + +@end enumerate + +To support the generation of RSA and DSA keys in FIPS mode according +to X9.31 and FIPS 186-2, Libgcrypt implements two additional prime +generation functions: @code{_gcry_derive_x931_prime} and +@code{_gcry_generate_fips186_2_prime}. These functions are internal +and not available through the public API. + + + +@node Random-Number Subsystem Architecture +@section Random-Number Subsystem Architecture + +Libgcrypt provides 3 levels or random quality: The level +@code{GCRY_VERY_STRONG_RANDOM} usually used for key generation, the +level @code{GCRY_STRONG_RANDOM} for all other strong random +requirements and the function @code{gcry_create_nonce} which is used +for weaker usages like nonces. There is also a level +@code{GCRY_WEAK_RANDOM} which in general maps to +@code{GCRY_STRONG_RANDOM} except when used with the function +@code{gcry_mpi_randomize}, where it randomizes an +multi-precision-integer using the @code{gcry_create_nonce} function. + +@noindent +There are two distinct random generators available: + +@itemize +@item +The Continuously Seeded Pseudo Random Number Generator (CSPRNG), which +is based on the classic GnuPG derived big pool implementation. +Implemented in @code{random/random-csprng.c} and used by default. +@item +A FIPS approved ANSI X9.31 PRNG using AES with a 128 bit key. Implemented in +@code{random/random-fips.c} and used if Libgcrypt is in FIPS mode. +@end itemize + +@noindent +Both generators make use of so-called entropy gathering modules: + +@table @asis +@item rndlinux +Uses the operating system provided +@file{/dev/random} and @file{/dev/urandom} devices. + +@item rndunix +Runs several operating system commands to collect entropy from sources +like virtual machine and process statistics. It is a kind of +poor-man's @code{/dev/random} implementation. It is not available in +FIPS mode. + +@item rndegd +Uses the operating system provided Entropy Gathering Daemon (EGD). +The EGD basically uses the same algorithms as rndunix does. However +as a system daemon it keeps on running and thus can serve several +processes requiring entropy input and does not waste collected entropy +if the application does not need all the collected entropy. It is not +available in FIPS mode. + +@item rndw32 +Targeted for the Microsoft Windows OS. It uses certain properties of +that system and is the only gathering module available for that OS. + +@item rndhw +Extra module to collect additional entropy by utilizing a hardware +random number generator. As of now the only supported hardware RNG is +the Padlock engine of VIA (Centaur) CPUs. It is not available in FIPS +mode. + +@end table + + +@menu +* CSPRNG Description:: Description of the CSPRNG. +* FIPS PRNG Description:: Description of the FIPS X9.31 PRNG. +@end menu + + +@node CSPRNG Description +@subsection Description of the CSPRNG + +This random number generator is loosely modelled after the one +described in Peter Gutmann's paper: "Software Generation of +Practically Strong Random Numbers".@footnote{Also described in chapter +6 of his book "Cryptographic Security Architecture", New York, 2004, +ISBN 0-387-95387-6.} + +A pool of 600 bytes is used and mixed using the core RIPE-MD160 hash +transform function. Several extra features are used to make the +robust against a wide variety of attacks and to protect against +failures of subsystems. The state of the generator may be saved to a +file and initially seed form a file. + +Depending on how Libgcrypt was build the generator is able to select +the best working entropy gathering module. It makes use of the slow +and fast collection methods and requires the pool to initially seeded +form the slow gatherer or a seed file. An entropy estimation is used +to mix in enough data from the gather modules before returning the +actual random output. Process fork detection and protection is +implemented. + +@c FIXME: The design and implementaion needs a more verbose description. + +The implementation of the nonce generator (for +@code{gcry_create_nonce}) is a straightforward repeated hash design: A +28 byte buffer is initially seeded with the PID and the time in +seconds in the first 20 bytes and with 8 bytes of random taken from +the @code{GCRY_STRONG_RANDOM} generator. Random numbers are then +created by hashing all the 28 bytes with SHA-1 and saving that again +in the first 20 bytes. The hash is also returned as result. + + +@node FIPS PRNG Description +@subsection Description of the FIPS X9.31 PRNG + +The core of this deterministic random number generator is implemented +according to the document ``NIST-Recommended Random Number Generator +Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key Triple DES and AES +Algorithms'', dated 2005-01-31. This implementation uses the AES +variant. + +The generator is based on contexts to utilize the same core functions +for all random levels as required by the high-level interface. All +random generators return their data in 128 bit blocks. If the caller +requests less bits, the extra bits are not used. The key for each +generator is only set once at the first time a generator context is +used. The seed value is set along with the key and again after 1000 +output blocks. + +On Unix like systems the @code{GCRY_VERY_STRONG_RANDOM} and +@code{GCRY_STRONG_RANDOM} generators are keyed and seeded using the +rndlinux module with the @file{/dev/radnom} device. Thus these +generators may block until the OS kernel has collected enough entropy. +When used with Microsoft Windows the rndw32 module is used instead. + +The generator used for @code{gcry_create_nonce} is keyed and seeded +from the @code{GCRY_STRONG_RANDOM} generator. Thus is may also block +if the @code{GCRY_STRONG_RANDOM} generator has not yet been used +before and thus gets initialized on the first use by +@code{gcry_create_nonce}. This special treatment is justified by the +weaker requirements for a nonce generator and to save precious kernel +entropy for use by the ``real'' random generators. + +A self-test facility uses a separate context to check the +functionality of the core X9.31 functions using a known answers test. +During runtime each output block is compared to the previous one to +detect a stucked generator. + +The DT value for the generator is made up of the current time down to +microseconds (if available) and a free running 64 bit counter. When +used with the test context the DT value is taken from the context and +incremented on each use. + + + +@c @node Helper Subsystems Architecture +@c @section Helper Subsystems Architecture +@c +@c There are a few smaller subsystems which are mainly used internally by +@c Libgcrypt but also available to applications. +@c +@c @menu +@c * S-expression Subsystem Architecture:: Details about the S-expression architecture. +@c * Memory Subsystem Architecture:: Details about the memory allocation architecture. +@c * Miscellaneous Subsystems Architecture:: Details about other subsystems. +@c @end menu +@c +@c @node S-expression Subsystem Architecture +@c @subsection S-expression Subsystem Architecture +@c +@c Libgcrypt provides an interface to S-expression to create and parse +@c them. To use an S-expression with Libgcrypt it needs first be +@c converted into the internal representation used by Libgcrypt (the type +@c @code{gcry_sexp_t}). The conversion functions support a large subset +@c of the S-expression specification and further fature a printf like +@c function to convert a list of big integers or other binary data into +@c an S-expression. +@c +@c Libgcrypt currently implements S-expressions using a tagged linked +@c list. However this is not exposed to an application and may be +@c changed in future releases to reduce overhead when already working +@c with canonically encoded S-expressions. Secure memory is supported by +@c this S-expressions implementation. +@c +@c @node Memory Subsystem Architecture +@c @subsection Memory Subsystem Architecture +@c +@c TBD. +@c +@c +@c @node Miscellaneous Subsystems Architecture +@c @subsection Miscellaneous Subsystems Architecture +@c +@c TBD. +@c +@c + + + +@c ********************************************************** +@c ******************* Appendices ************************* +@c ********************************************************** + +@c ******************************************** +@node Self-Tests +@appendix Description of the Self-Tests + +In addition to the build time regression test suite, Libgcrypt +implements self-tests to be performed at runtime. Which self-tests +are actually used depends on the mode Libgcrypt is used in. In +standard mode a limited set of self-tests is run at the time an +algorithm is first used. Note that not all algorithms feature a +self-test in standard mode. The @code{GCRYCTL_SELFTEST} control +command may be used to run all implemented self-tests at any time; +this will even run more tests than those run in FIPS mode. + +If any of the self-tests fails, the library immediately returns an +error code to the caller. If Libgcrypt is in FIPS mode the self-tests +will be performed within the ``Self-Test'' state and any failure puts +the library into the ``Error'' state. + +@c -------------------------------- +@section Power-Up Tests + +Power-up tests are only performed if Libgcrypt is in FIPS mode. + +@subsection Symmetric Cipher Algorithm Power-Up Tests + +The following symmetric encryption algorithm tests are run during +power-up: + +@table @asis +@item 3DES +To test the 3DES 3-key EDE encryption in ECB mode these tests are +run: +@enumerate +@item +A known answer test is run on a 64 bit test vector processed by 64 +rounds of Single-DES block encryption and decryption using a key +changed with each round. +@item +A known answer test is run on a 64 bit test vector processed by 16 +rounds of 2-key and 3-key Triple-DES block encryption and decryptions +using a key changed with each round. +@item +10 known answer tests using 3-key Triple-DES EDE encryption, comparing +the ciphertext to the known value, then running a decryption and +comparing it to the initial plaintext. +@end enumerate +(@code{cipher/des.c:selftest}) + +@item AES-128 +A known answer tests is run using one test vector and one test +key with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_128}) + +@item AES-192 +A known answer tests is run using one test vector and one test +key with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_192}) + +@item AES-256 +A known answer tests is run using one test vector and one test key +with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_256}) +@end table + +@subsection Hash Algorithm Power-Up Tests + +The following hash algorithm tests are run during power-up: + +@table @asis +@item SHA-1 +A known answer test using the string @code{"abc"} is run. +(@code{cipher/@/sha1.c:@/selftests_sha1}) +@item SHA-224 +A known answer test using the string @code{"abc"} is run. +(@code{cipher/@/sha256.c:@/selftests_sha224}) +@item SHA-256 +A known answer test using the string @code{"abc"} is run. +(@code{cipher/@/sha256.c:@/selftests_sha256}) +@item SHA-384 +A known answer test using the string @code{"abc"} is run. +(@code{cipher/@/sha512.c:@/selftests_sha384}) +@item SHA-512 +A known answer test using the string @code{"abc"} is run. +(@code{cipher/@/sha512.c:@/selftests_sha512}) +@end table + +@subsection MAC Algorithm Power-Up Tests + +The following MAC algorithm tests are run during power-up: + +@table @asis +@item HMAC SHA-1 +A known answer test using 9 byte of data and a 64 byte key is run. +(@code{cipher/hmac-tests.c:selftests_sha1}) +@item HMAC SHA-224 +A known answer test using 28 byte of data and a 4 byte key is run. +(@code{cipher/hmac-tests.c:selftests_sha224}) +@item HMAC SHA-256 +A known answer test using 28 byte of data and a 4 byte key is run. +(@code{cipher/hmac-tests.c:selftests_sha256}) +@item HMAC SHA-384 +A known answer test using 28 byte of data and a 4 byte key is run. +(@code{cipher/hmac-tests.c:selftests_sha384}) +@item HMAC SHA-512 +A known answer test using 28 byte of data and a 4 byte key is run. +(@code{cipher/hmac-tests.c:selftests_sha512}) +@end table + +@subsection Random Number Power-Up Test + +The DRNG is tested during power-up this way: + +@enumerate +@item +Requesting one block of random using the public interface to check +general working and the duplicated block detection. +@item +3 know answer tests using pre-defined keys, seed and initial DT +values. For each test 3 blocks of 16 bytes are requested and compared +to the expected result. The DT value is incremented for each block. +@end enumerate + +@subsection Public Key Algorithm Power-Up Tests + +The public key algorithms are tested during power-up: + +@table @asis +@item RSA +A pre-defined 1024 bit RSA key is used and these tests are run +in turn: +@enumerate +@item +Conversion of S-expression to internal format. +(@code{cipher/@/rsa.c:@/selftests_rsa}) +@item +Private key consistency check. +(@code{cipher/@/rsa.c:@/selftests_rsa}) +@item +A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-1. +The result is verified using the public key against the original data +and against modified data. (@code{cipher/@/rsa.c:@/selftest_sign_1024}) +@item +A 1000 bit random value is encrypted and checked that it does not +match the orginal random value. The encrtypted result is then +decrypted and checked that it macthes the original random value. +(@code{cipher/@/rsa.c:@/selftest_encr_1024}) +@end enumerate + +@item DSA +A pre-defined 1024 bit DSA key is used and these tests are run in turn: +@enumerate +@item +Conversion of S-expression to internal format. +(@code{cipher/@/dsa.c:@/selftests_dsa}) +@item +Private key consistency check. +(@code{cipher/@/dsa.c:@/selftests_dsa}) +@item +A pre-defined 20 byte value is signed with PKCS#1 padding for +SHA-1. The result is verified using the public key against the +original data and against modified data. +(@code{cipher/@/dsa.c:@/selftest_sign_1024}) +@end enumerate +@end table + +@subsection Integrity Power-Up Tests + +The integrity of the Libgcrypt is tested during power-up but only if +checking has been enabled at build time. The check works by computing +a HMAC SHA-256 checksum over the file used to load Libgcrypt into +memory. That checksum is compared against a checksum stored in a file +of the same name but with a single dot as a prefix and a suffix of +@file{.hmac}. + + +@subsection Critical Functions Power-Up Tests + +The 3DES weak key detection is tested during power-up by calling the +detection function with keys taken from a table listening all weak +keys. The table itself is protected using a SHA-1 hash. +(@code{cipher/@/des.c:@/selftest}) + + + +@c -------------------------------- +@section Conditional Tests + +The conditional tests are performed if a certain contidion is met. +This may occur at any time; the library does not necessary enter the +``Self-Test'' state to run these tests but will transit to the +``Error'' state if a test failed. + +@subsection Key-Pair Generation Tests + +After an asymmetric key-pair has been generated, Libgcrypt runs a +pair-wise consistency tests on the generated key. On failure the +generated key is not used, an error code is returned and, if in FIPS +mode, the library is put into the ``Error'' state. + +@table @asis +@item RSA +The test uses a random number 64 bits less the size of the modulus as +plaintext and runs an encryption and decryption operation in turn. The +encrypted value is checked to not match the plaintext and the result +of the decryption is checked to match the plaintext. + +A new random number of the same size is generated, signed and verified +to test the correctness of the signing operation. As a second signing +test, the signature is modified by incrementing its value and then +verified with the expected result that the verification fails. +(@code{cipher/@/rsa.c:@/test_keys}) +@item DSA +The test uses a random number of the size of the Q parameter to create +a signature and then checks that the signature verifies. As a second +signing test, the data is modified by incrementing its value and then +verified against the signature with the expected result that the +verification fails. (@code{cipher/@/dsa.c:@/test_keys}) +@end table + + +@subsection Software Load Tests + +Loading of extra modules into libgcrypt is disabled in FIPS mode and +thus no tests are +implemented. (@code{cipher/@/cipher.c:@/gcry_cipher_register}, +@code{cipher/@/md.c:@/gcry_md_register}, +@code{cipher/@/md.c:@/gcry_pk_register}) + + +@subsection Manual Key Entry Tests + +A manual key entry feature is not implemented in Libgcrypt. + + +@subsection Continuous RNG Tests + +The continuous random number test is only used in FIPS mode. The RNG +generates blocks of 128 bit size; the first block generated per +context is saved in the context and another block is generated to be +returned to the caller. Each block is compared against the saved +block and then stored in the context. If a duplicated block is +detected an error is signaled and the libray is put into the +``Fatal-Error'' state. +(@code{random/@/random-fips.c:@/x931_aes_driver}) + + + +@c -------------------------------- +@section Application Requested Tests + +The application may requests tests at any time by means of the +@code{GCRYCTL_SELFTEST} control command. Note that using these tests +is not FIPS conform: Although Libgcrypt rejects all application +requests for services while running self-tests, it does not ensure +that no other operations of Libgcrypt are still being executed. Thus, +in FIPS mode an application requesting self-tests needs to power-cycle +Libgcrypt instead. + +When self-tests are requested, Libgcrypt runs all the tests it does +during power-up as well as a few extra checks as described below. + +@subsection Symmetric Cipher Algorithm Tests + +The following symmetric encryption algorithm tests are run in addition +to the power-up tests: + +@table @asis +@item AES-128 +A known answer tests with test vectors taken from NIST SP800-38a and +using the high level functions is run for block modes CFB and OFB. + +@end table + +@subsection Hash Algorithm Tests + +The following hash algorithm tests are run in addition to the +power-up tests: + +@table @asis +@item SHA-1 +@itemx SHA-224 +@itemx SHA-256 +@enumerate +@item +A known answer test using a 56 byte string is run. +@item +A known answer test using a string of one million letters "a" is run. +@end enumerate +(@code{cipher/@/sha1.c:@/selftests_sha1}, +@code{cipher/@/sha256.c:@/selftests_sha224}, +@code{cipher/@/sha256.c:@/selftests_sha256}) +@item SHA-384 +@item SHA-512 +@enumerate +@item +A known answer test using a 112 byte string is run. +@item +A known answer test using a string of one million letters "a" is run. +@end enumerate +(@code{cipher/@/sha512.c:@/selftests_sha384}, +@code{cipher/@/sha512.c:@/selftests_sha512}) +@end table + +@subsection MAC Algorithm Tests + +The following MAC algorithm tests are run in addition to the power-up +tests: + +@table @asis +@item HMAC SHA-1 +@enumerate +@item +A known answer test using 9 byte of data and a 20 byte key is run. +@item +A known answer test using 9 byte of data and a 100 byte key is run. +@item +A known answer test using 9 byte of data and a 49 byte key is run. +@end enumerate +(@code{cipher/hmac-tests.c:selftests_sha1}) +@item HMAC SHA-224 +@itemx HMAC SHA-256 +@itemx HMAC SHA-384 +@itemx HMAC SHA-512 +@enumerate +@item +A known answer test using 9 byte of data and a 20 byte key is run. +@item +A known answer test using 50 byte of data and a 20 byte key is run. +@item +A known answer test using 50 byte of data and a 26 byte key is run. +@item +A known answer test using 54 byte of data and a 131 byte key is run. +@item +A known answer test using 152 byte of data and a 131 byte key is run. +@end enumerate +(@code{cipher/@/hmac-tests.c:@/selftests_sha224}, +@code{cipher/@/hmac-tests.c:@/selftests_sha256}, +@code{cipher/@/hmac-tests.c:@/selftests_sha384}, +@code{cipher/@/hmac-tests.c:@/selftests_sha512}) +@end table + + +@c ******************************************** +@node FIPS Mode +@appendix Description of the FIPS Mode + +This appendix gives detailed information pertaining to the FIPS mode. +In particular, the changes to the standard mode and the finite state +machine are described. The self-tests required in this mode are +described in the appendix on self-tests. + +@c ------------------------------- +@section Restrictions in FIPS Mode + +@noindent +If Libgcrypt is used in FIPS mode these restrictions are effective: + +@itemize +@item +The cryptographic algorithms are restricted to this list: + +@table @asis +@item GCRY_CIPHER_3DES +3 key EDE Triple-DES symmetric encryption. +@item GCRY_CIPHER_AES128 +AES 128 bit symmetric encryption. +@item GCRY_CIPHER_AES192 +AES 192 bit symmetric encryption. +@item GCRY_CIPHER_AES256 +AES 256 bit symmetric encryption. +@item GCRY_MD_SHA1 +SHA-1 message digest. +@item GCRY_MD_SHA224 +SHA-224 message digest. +@item GCRY_MD_SHA256 +SHA-256 message digest. +@item GCRY_MD_SHA384 +SHA-384 message digest. +@item GCRY_MD_SHA512 +SHA-512 message digest. +@item GCRY_MD_SHA1,GCRY_MD_FLAG_HMAC +HMAC using a SHA-1 message digest. +@item GCRY_MD_SHA224,GCRY_MD_FLAG_HMAC +HMAC using a SHA-224 message digest. +@item GCRY_MD_SHA256,GCRY_MD_FLAG_HMAC +HMAC using a SHA-256 message digest. +@item GCRY_MD_SHA384,GCRY_MD_FLAG_HMAC +HMAC using a SHA-384 message digest. +@item GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC +HMAC using a SHA-512 message digest. +@item GCRY_PK_RSA +RSA encryption and signing. +@item GCRY_PK_DSA +DSA signing. +@end table + +Note that the CRC algorithms are not considered cryptographic algorithms +and thus are in addition available. + +@item +RSA key generation refuses to create a key with a keysize of +less than 1024 bits. + +@item +DSA key generation refuses to create a key with a keysize other +than 1024 bits. + +@item +The @code{transient-key} flag for RSA and DSA key generation is ignored. + +@item +Support for the VIA Padlock engine is disabled. + +@item +FIPS mode may only be used on systems with a /dev/random device. +Switching into FIPS mode on other systems will fail at runtime. + +@item +Saving and loading a random seed file is ignored. + +@item +An X9.31 style random number generator is used in place of the +large-pool-CSPRNG generator. + +@item +The command @code{GCRYCTL_ENABLE_QUICK_RANDOM} is ignored. + +@item +The Alternative Public Key Interface (@code{gcry_ac_xxx}) is not +supported and all API calls return an error. + +@item +Registration of external modules is not supported. + +@item +Message digest debugging is disabled. + +@item +All debug output related to cryptographic data is suppressed. + +@item +On-the-fly self-tests are not performed, instead self-tests are run +before entering operational state. + +@item +The function @code{gcry_set_allocation_handler} may not be used. If +it is used Libgcrypt disables FIPS mode unless Enforced FIPS mode is +enabled, in which case Libgcrypt will enter the error state. + +@item +The digest algorithm MD5 may not be used. If it is used Libgcrypt +disables FIPS mode unless Enforced FIPS mode is enabled, in which case +Libgcrypt will enter the error state. + +@item +In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is +ignored. In standard FIPS mode it disables FIPS mode. + +@item +A handler set by @code{gcry_set_outofcore_handler} is ignored. +@item +A handler set by @code{gcry_set_fatalerror_handler} is ignored. + +@end itemize + +Note that when we speak about disabling FIPS mode, it merely means +that the function @code{gcry_fips_mode_active} returns false; it does +not mean that any non FIPS algorithms are allowed. + +@c ******************************************** +@section FIPS Finite State Machine + +The FIPS mode of libgcrypt implements a finite state machine (FSM) using +8 states (@pxref{tbl:fips-states}) and checks at runtime that only valid +transitions (@pxref{tbl:fips-state-transitions}) may happen. + +@float Figure,fig:fips-fsm +@caption{FIPS mode state diagram} +@center @image{fips-fsm,150mm,,FIPS FSM Diagram} +@end float + +@float Table,tbl:fips-states +@caption{FIPS mode states} +@noindent +States used by the FIPS FSM: +@table @asis + +@item Power-Off +Libgcrypt is not runtime linked to another application. This usually +means that the library is not loaded into main memory. This state is +documentation only. + +@item Power-On +Libgcrypt is loaded into memory and API calls may be made. Compiler +introducted constructor functions may be run. Note that Libgcrypt does +not implement any arbitrary constructor functions to be called by the +operating system + +@item Init +The Libgcrypt initialization functions are performed and the library has +not yet run any self-test. + +@item Self-Test +Libgcrypt is performing self-tests. + +@item Operational +Libgcrypt is in the operational state and all interfaces may be used. + +@item Error +Libgrypt is in the error state. When calling any FIPS relevant +interfaces they either return an error (@code{GPG_ERR_NOT_OPERATIONAL}) +or put Libgcrypt into the Fatal-Error state and won't return. + +@item Fatal-Error +Libgcrypt is in a non-recoverable error state and +will automatically transit into the Shutdown state. + +@item Shutdown +Libgcrypt is about to be terminated and removed from the memory. The +application may at this point still runing cleanup handlers. + +@end table +@end float + + +@float Table,tbl:fips-state-transitions +@caption{FIPS mode state transitions} +@noindent +The valid state transitions (@pxref{fig:fips-fsm}) are: +@table @code +@item 1 +Power-Off to Power-On is implicitly done by the OS loading Libgcrypt as +a shared library and having it linked to an application. + +@item 2 +Power-On to Init is triggered by the application calling the +Libgcrypt intialization function @code{gcry_check_version}. + +@item 3 +Init to Self-Test is either triggred by a dedicated API call or implicit +by invoking a libgrypt service conrolled by the FSM. + +@item 4 +Self-Test to Operational is triggered after all self-tests passed +successfully. + +@item 5 +Operational to Shutdown is an artifical state without any direct action +in Libgcrypt. When reaching the Shutdown state the library is +deinitialized and can't return to any other state again. + +@item 6 +Shutdown to Power-off is the process of removing Libgcrypt from the +computer's memory. For obvious reasons the Power-Off state can't be +represented within Libgcrypt and thus this transition is for +documentation only. + +@item 7 +Operational to Error is triggered if Libgcrypt detected an application +error which can't be returned to the caller but still allows Libgcrypt +to properly run. In the Error state all FIPS relevant interfaces return +an error code. + +@item 8 +Error to Shutdown is similar to the Operational to Shutdown transition +(5). + +@item 9 +Error to Fatal-Error is triggred if Libgrypt detects an fatal error +while already being in Error state. + +@item 10 +Fatal-Error to Shutdown is automatically entered by Libgcrypt +after having reported the error. + +@item 11 +Power-On to Shutdown is an artifical state to document that Libgcrypt +has not ye been initializaed but the process is about to terminate. + +@item 12 +Power-On to Fatal-Error will be triggerd if certain Libgcrypt functions +are used without having reached the Init state. + +@item 13 +Self-Test to Fatal-Error is triggred by severe errors in Libgcrypt while +running self-tests. + +@item 14 +Self-Test to Error is triggred by a failed self-test. + +@item 15 +Operational to Fatal-Error is triggered if Libcrypt encountered a +non-recoverable error. + +@item 16 +Operational to Self-Test is triggred if the application requested to run +the self-tests again. + +@item 17 +Error to Self-Test is triggered if the application has requested to run +self-tests to get to get back into operational state after an error. + +@item 18 +Init to Error is triggered by errors in the initialization code. + +@item 19 +Init to Fatal-Error is triggered by non-recoverable errors in the +initialization code. + +@item 20 +Error to Error is triggered by errors while already in the Error +state. + + +@end table +@end float + +@c ******************************************** +@section FIPS Miscellaneous Information + +Libgcrypt does not do any key management on itself; the application +needs to care about it. Keys which are passed to Libgcrypt should be +allocated in secure memory as available with the functions +@code{gcry_malloc_secure} and @code{gcry_calloc_secure}. By calling +@code{gcry_free} on this memory, the memory and thus the keys are +overwritten with zero bytes before releasing the memory. + +For use with the random number generator, Libgcrypt generates 3 +internal keys which are stored in the encryption contexts used by the +RNG. These keys are stored in secure memory for the lifetime of the +process. Application are required to use @code{GCRYCTL_TERM_SECMEM} +before process termination. This will zero out the entire secure +memory and thus also the encryption contexts with these keys. + + + +@c ********************************************************** +@c ************* Appendices (license etc.) **************** +@c ********************************************************** +@include lgpl.texi + +@include gpl.texi + +@node Figures and Tables +@unnumbered List of Figures and Tables + +@listoffloats Figure + +@listoffloats Table + +@node Concept Index +@unnumbered Concept Index + +@printindex cp + +@node Function and Data Index +@unnumbered Function and Data Index + +@printindex fn + + + +@bye + +GCRYCTL_SET_RANDOM_DAEMON_SOCKET +GCRYCTL_USE_RANDOM_DAEMON +The random damon is still a bit experimental, thus we do not document +them. Note that they should be used during initialization and that +these functions are not really thread safe. + + + + +@c LocalWords: int HD + + + + diff --git a/doc/gpl.texi b/doc/gpl.texi new file mode 100644 index 0000000..d965561 --- /dev/null +++ b/doc/gpl.texi @@ -0,0 +1,397 @@ +@node Copying +@unnumbered GNU General Public License + +@cindex GPL, GNU General Public License +@center Version 2, June 1991 + +@display +Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc. +59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@heading Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software---to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + +@iftex +@heading TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end iftex +@ifinfo +@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end ifinfo + +@enumerate +@item +This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The ``Program'', below, +refers to any such program or work, and a ``work based on the Program'' +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term ``modification''.) Each licensee is addressed as ``you''. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +@item +You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +@item +You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +@enumerate a +@item +You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +@item +You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. + +@item +If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) +@end enumerate + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +@item +You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +@enumerate a +@item +Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, + +@item +Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, + +@item +Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) +@end enumerate + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +@item +You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +@item +You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +@item +Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +@item +If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +@item +If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +@item +The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and ``any +later version'', you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +@item +If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +@iftex +@heading NO WARRANTY +@end iftex +@ifinfo +@center NO WARRANTY +@end ifinfo + +@item +BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +@item +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. +@end enumerate + +@iftex +@heading END OF TERMS AND CONDITIONS +@end iftex +@ifinfo +@center END OF TERMS AND CONDITIONS +@end ifinfo + +@page +@heading How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +@smallexample +@var{one line to give the program's name and an idea of what it does.} +Copyright (C) 19@var{yy} @var{name of author} + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +@end smallexample + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +@smallexample +Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author} +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details +type `show w'. This is free software, and you are welcome +to redistribute it under certain conditions; type `show c' +for details. +@end smallexample + +The hypothetical commands @samp{show w} and @samp{show c} should show +the appropriate parts of the General Public License. Of course, the +commands you use may be called something other than @samp{show w} and +@samp{show c}; they could even be mouse-clicks or menu items---whatever +suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a ``copyright disclaimer'' for the program, if +necessary. Here is a sample; alter the names: + +@smallexample +@group +Yoyodyne, Inc., hereby disclaims all copyright +interest in the program `Gnomovision' +(which makes passes at compilers) written +by James Hacker. + +@var{signature of Ty Coon}, 1 April 1989 +Ty Coon, President of Vice +@end group +@end smallexample + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/doc/lgpl.texi b/doc/lgpl.texi new file mode 100644 index 0000000..a3f83cb --- /dev/null +++ b/doc/lgpl.texi @@ -0,0 +1,565 @@ +@node Library Copying +@unnumbered GNU Lesser General Public License + +@cindex LGPL, GNU Lesser General Public License +@center Version 2.1, February 1999 + +@display +Copyright @copyright{} 1991, 1999 Free Software Foundation, Inc. +59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts +as the successor of the GNU Library Public License, version 2, hence the +version number 2.1.] +@end display + +@heading Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software---to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software---typically libraries---of the Free +Software Foundation and other authors who decide to use it. You can use +it too, but we suggest you first think carefully about whether this +license or the ordinary General Public License is the better strategy to +use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of it +in new free programs; and that you are informed that you can do these +things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the @dfn{Lesser} General Public License because it +does @emph{Less} to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +``work based on the library'' and a ``work that uses the library''. The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +@iftex +@heading TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end iftex +@ifinfo +@center GNU LESSER GENERAL PUBLIC LICENSE +@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end ifinfo + +@enumerate 0 +@item +This License Agreement applies to any software library or other program +which contains a notice placed by the copyright holder or other +authorized party saying it may be distributed under the terms of this +Lesser General Public License (also called ``this License''). Each +licensee is addressed as ``you''. + + A ``library'' means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The ``Library'', below, refers to any such software library or work +which has been distributed under these terms. A ``work based on the +Library'' means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term ``modification''.) + + ``Source code'' for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + +@item +You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + +@item +You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +@enumerate a +@item +The modified work must itself be a software library. + +@item +You must cause the files modified to carry prominent notices +stating that you changed the files and the date of any change. + +@item +You must cause the whole of the work to be licensed at no +charge to all third parties under the terms of this License. + +@item +If a facility in the modified Library refers to a function or a +table of data to be supplied by an application program that uses +the facility, other than as an argument passed when the facility +is invoked, then you must make a good faith effort to ensure that, +in the event an application does not supply such function or +table, the facility still operates, and performs whatever part of +its purpose remains meaningful. + +(For example, a function in a library to compute square roots has +a purpose that is entirely well-defined independent of the +application. Therefore, Subsection 2d requires that any +application-supplied function or table used by this function must +be optional: if the application does not supply it, the square +root function must still compute square roots.) +@end enumerate + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +@item +You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + +@item +You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + +@item +A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a ``work that uses the Library''. Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a ``work that uses the Library'' with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a ``work that uses the +library''. The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a ``work that uses the Library'' uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + +@item +As an exception to the Sections above, you may also combine or +link a ``work that uses the Library'' with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + +@enumerate a +@item +Accompany the work with the complete corresponding +machine-readable source code for the Library including whatever +changes were used in the work (which must be distributed under +Sections 1 and 2 above); and, if the work is an executable linked +with the Library, with the complete machine-readable ``work that +uses the Library'', as object code and/or source code, so that the +user can modify the Library and then relink to produce a modified +executable containing the modified Library. (It is understood +that the user who changes the contents of definitions files in the +Library will not necessarily be able to recompile the application +to use the modified definitions.) + +@item +Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (1) uses at run time a copy of the +library already present on the user's computer system, rather than +copying library functions into the executable, and (2) will operate +properly with a modified version of the library, if the user installs +one, as long as the modified version is interface-compatible with the +version that the work was made with. + +@item +Accompany the work with a written offer, valid for at +least three years, to give the same user the materials +specified in Subsection 6a, above, for a charge no more +than the cost of performing this distribution. + +@item +If distribution of the work is made by offering access to copy +from a designated place, offer equivalent access to copy the above +specified materials from the same place. + +@item +Verify that the user has already received a copy of these +materials or that you have already sent this user a copy. +@end enumerate + + For an executable, the required form of the ``work that uses the +Library'' must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies the +executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + +@item +You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + +@enumerate a +@item +Accompany the combined library with a copy of the same work +based on the Library, uncombined with any other library +facilities. This must be distributed under the terms of the +Sections above. + +@item +Give prominent notice with the combined library of the fact +that part of it is a work based on the Library, and explaining +where to find the accompanying uncombined form of the same work. +@end enumerate + +@item +You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +@item +You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +@item +Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + +@item +If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +@item +If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + +@item +The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +``any later version'', you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + +@item +If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +@iftex +@heading NO WARRANTY +@end iftex +@ifinfo +@center NO WARRANTY +@end ifinfo + +@item +BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +@item +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. +@end enumerate + +@iftex +@heading END OF TERMS AND CONDITIONS +@end iftex +@ifinfo +@center END OF TERMS AND CONDITIONS +@end ifinfo + +@page +@heading How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +``copyright'' line and a pointer to where the full notice is found. + +@smallexample +@var{one line to give the library's name and an idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at +your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, +USA. +@end smallexample + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a ``copyright disclaimer'' for the library, if +necessary. Here is a sample; alter the names: + +@smallexample +Yoyodyne, Inc., hereby disclaims all copyright interest in the library +`Frob' (a library for tweaking knobs) written by James Random Hacker. + +@var{signature of Ty Coon}, 1 April 1990 +Ty Coon, President of Vice +@end smallexample + +That's all there is to it! diff --git a/doc/libgcrypt-modules.eps b/doc/libgcrypt-modules.eps new file mode 100644 index 0000000..d3d68ad --- /dev/null +++ b/doc/libgcrypt-modules.eps @@ -0,0 +1,349 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: libgcrypt-modules.fig +%%Creator: fig2dev Version 3.2 Patchlevel 4 +%%CreationDate: Tue Aug 19 17:49:04 2008 +%%For: wk@vigenere (Werner Koch,,,) +%%BoundingBox: 0 0 488 300 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def +/col32 {0.555 0.555 0.555 srgb} bind def +/col33 {0.254 0.270 0.254 srgb} bind def +/col34 {0.750 0.750 0.750 srgb} bind def +/col35 {0.500 0.500 0.500 srgb} bind def +/col36 {0.387 0.387 0.387 srgb} bind def +/col37 {0.801 0.801 0.801 srgb} bind def +/col38 {0.422 0.422 0.422 srgb} bind def +/col39 {0.773 0.715 0.590 srgb} bind def +/col40 {0.934 0.969 0.996 srgb} bind def +/col41 {0.859 0.793 0.648 srgb} bind def +/col42 {0.250 0.250 0.250 srgb} bind def +/col43 {0.875 0.875 0.875 srgb} bind def +/col44 {0.555 0.559 0.555 srgb} bind def +/col45 {0.664 0.664 0.664 srgb} bind def +/col46 {0.332 0.332 0.332 srgb} bind def +/col47 {0.840 0.840 0.840 srgb} bind def +/col48 {0.680 0.680 0.680 srgb} bind def +/col49 {0.742 0.742 0.742 srgb} bind def +/col50 {0.316 0.316 0.316 srgb} bind def +/col51 {0.902 0.887 0.902 srgb} bind def +/col52 {0.000 0.000 0.285 srgb} bind def +/col53 {0.473 0.473 0.473 srgb} bind def +/col54 {0.188 0.203 0.188 srgb} bind def +/col55 {0.254 0.254 0.254 srgb} bind def +/col56 {0.777 0.711 0.586 srgb} bind def +/col57 {0.863 0.613 0.574 srgb} bind def +/col58 {0.941 0.922 0.875 srgb} bind def +/col59 {0.762 0.762 0.762 srgb} bind def +/col60 {0.883 0.781 0.656 srgb} bind def +/col61 {0.879 0.879 0.879 srgb} bind def +/col62 {0.820 0.820 0.820 srgb} bind def +/col63 {0.926 0.926 0.926 srgb} bind def +/col64 {0.852 0.477 0.102 srgb} bind def +/col65 {0.941 0.891 0.102 srgb} bind def +/col66 {0.531 0.488 0.758 srgb} bind def +/col67 {0.836 0.836 0.836 srgb} bind def +/col68 {0.547 0.547 0.645 srgb} bind def +/col69 {0.289 0.289 0.289 srgb} bind def +/col70 {0.547 0.418 0.418 srgb} bind def +/col71 {0.352 0.352 0.352 srgb} bind def +/col72 {0.715 0.605 0.449 srgb} bind def +/col73 {0.254 0.574 0.996 srgb} bind def +/col74 {0.746 0.438 0.230 srgb} bind def +/col75 {0.855 0.465 0.000 srgb} bind def +/col76 {0.852 0.719 0.000 srgb} bind def +/col77 {0.000 0.391 0.000 srgb} bind def +/col78 {0.352 0.418 0.230 srgb} bind def +/col79 {0.824 0.824 0.824 srgb} bind def +/col80 {0.555 0.555 0.641 srgb} bind def +/col81 {0.949 0.723 0.363 srgb} bind def +/col82 {0.535 0.598 0.418 srgb} bind def +/col83 {0.391 0.391 0.391 srgb} bind def +/col84 {0.715 0.898 0.996 srgb} bind def +/col85 {0.523 0.750 0.922 srgb} bind def +/col86 {0.738 0.738 0.738 srgb} bind def +/col87 {0.824 0.582 0.320 srgb} bind def +/col88 {0.594 0.820 0.992 srgb} bind def +/col89 {0.547 0.609 0.418 srgb} bind def +/col90 {0.965 0.418 0.000 srgb} bind def +/col91 {0.352 0.418 0.223 srgb} bind def +/col92 {0.547 0.609 0.418 srgb} bind def +/col93 {0.547 0.609 0.480 srgb} bind def +/col94 {0.094 0.289 0.094 srgb} bind def +/col95 {0.676 0.676 0.676 srgb} bind def +/col96 {0.965 0.738 0.352 srgb} bind def +/col97 {0.387 0.418 0.609 srgb} bind def +/col98 {0.965 0.965 0.965 srgb} bind def +/col99 {0.867 0.000 0.000 srgb} bind def +/col100 {0.676 0.676 0.676 srgb} bind def +/col101 {0.965 0.738 0.352 srgb} bind def +/col102 {0.676 0.676 0.676 srgb} bind def +/col103 {0.965 0.738 0.352 srgb} bind def +/col104 {0.387 0.418 0.609 srgb} bind def +/col105 {0.320 0.418 0.160 srgb} bind def +/col106 {0.578 0.578 0.578 srgb} bind def +/col107 {0.000 0.387 0.000 srgb} bind def +/col108 {0.000 0.387 0.289 srgb} bind def +/col109 {0.480 0.516 0.289 srgb} bind def +/col110 {0.902 0.738 0.480 srgb} bind def +/col111 {0.645 0.707 0.773 srgb} bind def +/col112 {0.418 0.418 0.578 srgb} bind def +/col113 {0.516 0.418 0.418 srgb} bind def +/col114 {0.320 0.609 0.289 srgb} bind def +/col115 {0.836 0.902 0.902 srgb} bind def +/col116 {0.320 0.387 0.387 srgb} bind def +/col117 {0.094 0.418 0.289 srgb} bind def +/col118 {0.609 0.645 0.707 srgb} bind def +/col119 {0.996 0.578 0.000 srgb} bind def +/col120 {0.996 0.578 0.000 srgb} bind def +/col121 {0.000 0.387 0.289 srgb} bind def +/col122 {0.480 0.516 0.289 srgb} bind def +/col123 {0.387 0.449 0.480 srgb} bind def +/col124 {0.902 0.738 0.480 srgb} bind def +/col125 {0.867 0.867 0.867 srgb} bind def +/col126 {0.949 0.930 0.824 srgb} bind def +/col127 {0.957 0.680 0.363 srgb} bind def +/col128 {0.582 0.805 0.598 srgb} bind def +/col129 {0.707 0.082 0.488 srgb} bind def +/col130 {0.930 0.930 0.930 srgb} bind def +/col131 {0.516 0.516 0.516 srgb} bind def +/col132 {0.480 0.480 0.480 srgb} bind def +/col133 {0.000 0.352 0.000 srgb} bind def +/col134 {0.902 0.449 0.449 srgb} bind def +/col135 {0.996 0.793 0.191 srgb} bind def +/col136 {0.160 0.473 0.289 srgb} bind def +/col137 {0.867 0.156 0.129 srgb} bind def +/col138 {0.129 0.348 0.773 srgb} bind def +/col139 {0.969 0.969 0.969 srgb} bind def +/col140 {0.898 0.898 0.898 srgb} bind def +/col141 {0.129 0.516 0.352 srgb} bind def +/col142 {0.785 0.785 0.785 srgb} bind def +/col143 {0.871 0.844 0.871 srgb} bind def +/col144 {0.965 0.949 0.965 srgb} bind def + +end +save +newpath 0 300 moveto 0 0 lineto 488 0 lineto 488 300 lineto closepath clip newpath +-32.6 348.9 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/reencdict 12 dict def /ReEncode { reencdict begin +/newcodesandnames exch def /newfontname exch def /basefontname exch def +/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def +basefontdict { exch dup /FID ne { dup /Encoding eq +{ exch dup length array copy newfont 3 1 roll put } +{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall +newfont /FontName newfontname put newcodesandnames aload pop +128 1 255 { newfont /Encoding get exch /.notdef put } for +newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat +newfontname newfont definefont pop end } def +/isovec [ +8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde +8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis +8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron +8#220 /dotlessi 8#230 /oe 8#231 /OE +8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling +8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis +8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot +8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus +8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph +8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine +8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf +8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute +8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring +8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute +8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute +8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve +8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply +8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex +8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave +8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring +8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute +8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute +8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve +8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide +8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex +8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def +/Helvetica /Helvetica-iso isovec ReEncode +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06299 0.06299 sc +% +% Fig objects follow +% +% +% here starts figure with depth 50 +/Helvetica-iso ff 300.00 scf sf +900 1440 m +gs 1 -1 sc (Public-Key) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +900 1815 m +gs 1 -1 sc (Encryption) col0 sh gr +% Polyline +15.000 slw +n 645 810 m 540 810 540 2055 105 arcto 4 {pop} repeat + 540 2160 2685 2160 105 arcto 4 {pop} repeat + 2790 2160 2790 915 105 arcto 4 {pop} repeat + 2790 810 645 810 105 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 300.00 scf sf +630 3420 m +gs 1 -1 sc (Multi-Precision-) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +900 3795 m +gs 1 -1 sc (Integers) col0 sh gr +% Polyline +n 645 2790 m 540 2790 540 4035 105 arcto 4 {pop} repeat + 540 4140 2685 4140 105 arcto 4 {pop} repeat + 2790 4140 2790 2895 105 arcto 4 {pop} repeat + 2790 2790 645 2790 105 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 300.00 scf sf +3420 3420 m +gs 1 -1 sc (Prime-Number) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +3420 3795 m +gs 1 -1 sc (Generator) col0 sh gr +% Polyline +n 3345 2790 m 3240 2790 3240 4035 105 arcto 4 {pop} repeat + 3240 4140 5385 4140 105 arcto 4 {pop} repeat + 5490 4140 5490 2895 105 arcto 4 {pop} repeat + 5490 2790 3345 2790 105 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 300.00 scf sf +6420 3435 m +gs 1 -1 sc (Random) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +6420 3810 m +gs 1 -1 sc (Numbers) col0 sh gr +% Polyline +n 6075 2805 m 5970 2805 5970 4050 105 arcto 4 {pop} repeat + 5970 4155 8115 4155 105 arcto 4 {pop} repeat + 8220 4155 8220 2910 105 arcto 4 {pop} repeat + 8220 2805 6075 2805 105 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 300.00 scf sf +3600 1440 m +gs 1 -1 sc (Symmetric) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +3600 1815 m +gs 1 -1 sc (Encryption) col0 sh gr +% Polyline +n 3345 810 m 3240 810 3240 2055 105 arcto 4 {pop} repeat + 3240 2160 5385 2160 105 arcto 4 {pop} repeat + 5490 2160 5490 915 105 arcto 4 {pop} repeat + 5490 810 3345 810 105 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 300.00 scf sf +6435 1440 m +gs 1 -1 sc (Hashing) col0 sh gr +/Helvetica-iso ff 300.00 scf sf +6435 1815 m +gs 1 -1 sc (MACing) col0 sh gr +% Polyline +n 6090 810 m 5985 810 5985 2055 105 arcto 4 {pop} repeat + 5985 2160 8130 2160 105 arcto 4 {pop} repeat + 8235 2160 8235 915 105 arcto 4 {pop} repeat + 8235 810 6090 810 105 arcto 4 {pop} repeat + cp gs col0 s gr +% Polyline +n 3513 4563 m 3438 4563 3438 5438 75 arcto 4 {pop} repeat + 3438 5513 4947 5513 75 arcto 4 {pop} repeat + 5022 5513 5022 4638 75 arcto 4 {pop} repeat + 5022 4563 3513 4563 75 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 210.00 scf sf +3825 5130 m +gs 1 -1 sc (Memory) col0 sh gr +% Polyline +n 5583 4563 m 5508 4563 5508 5438 75 arcto 4 {pop} repeat + 5508 5513 7017 5513 75 arcto 4 {pop} repeat + 7092 5513 7092 4638 75 arcto 4 {pop} repeat + 7092 4563 5583 4563 75 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 210.00 scf sf +5635 5133 m +gs 1 -1 sc (Miscelleanous) col0 sh gr +% Polyline +n 1443 4567 m 1368 4567 1368 5442 75 arcto 4 {pop} repeat + 1368 5517 2877 5517 75 arcto 4 {pop} repeat + 2952 5517 2952 4642 75 arcto 4 {pop} repeat + 2952 4567 1443 4567 75 arcto 4 {pop} repeat + cp gs col0 s gr +/Helvetica-iso ff 210.00 scf sf +1495 5137 m +gs 1 -1 sc (S-expressions) col0 sh gr +% here ends figure; +$F2psEnd +rs +showpage diff --git a/doc/libgcrypt-modules.fig b/doc/libgcrypt-modules.fig new file mode 100644 index 0000000..ea3d053 --- /dev/null +++ b/doc/libgcrypt-modules.fig @@ -0,0 +1,193 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +0 32 #8e8e8e +0 33 #414541 +0 34 #c0c0c0 +0 35 #808080 +0 36 #636363 +0 37 #cdcdcd +0 38 #6c6c6c +0 39 #c6b797 +0 40 #eff8ff +0 41 #dccba6 +0 42 #404040 +0 43 #e0e0e0 +0 44 #8e8f8e +0 45 #aaaaaa +0 46 #555555 +0 47 #d7d7d7 +0 48 #aeaeae +0 49 #bebebe +0 50 #515151 +0 51 #e7e3e7 +0 52 #000049 +0 53 #797979 +0 54 #303430 +0 55 #414141 +0 56 #c7b696 +0 57 #dd9d93 +0 58 #f1ece0 +0 59 #c3c3c3 +0 60 #e2c8a8 +0 61 #e1e1e1 +0 62 #d2d2d2 +0 63 #ededed +0 64 #da7a1a +0 65 #f1e41a +0 66 #887dc2 +0 67 #d6d6d6 +0 68 #8c8ca5 +0 69 #4a4a4a +0 70 #8c6b6b +0 71 #5a5a5a +0 72 #b79b73 +0 73 #4193ff +0 74 #bf703b +0 75 #db7700 +0 76 #dab800 +0 77 #006400 +0 78 #5a6b3b +0 79 #d3d3d3 +0 80 #8e8ea4 +0 81 #f3b95d +0 82 #89996b +0 83 #646464 +0 84 #b7e6ff +0 85 #86c0ec +0 86 #bdbdbd +0 87 #d39552 +0 88 #98d2fe +0 89 #8c9c6b +0 90 #f76b00 +0 91 #5a6b39 +0 92 #8c9c6b +0 93 #8c9c7b +0 94 #184a18 +0 95 #adadad +0 96 #f7bd5a +0 97 #636b9c +0 98 #f7f7f7 +0 99 #de0000 +0 100 #adadad +0 101 #f7bd5a +0 102 #adadad +0 103 #f7bd5a +0 104 #636b9c +0 105 #526b29 +0 106 #949494 +0 107 #006300 +0 108 #00634a +0 109 #7b844a +0 110 #e7bd7b +0 111 #a5b5c6 +0 112 #6b6b94 +0 113 #846b6b +0 114 #529c4a +0 115 #d6e7e7 +0 116 #526363 +0 117 #186b4a +0 118 #9ca5b5 +0 119 #ff9400 +0 120 #ff9400 +0 121 #00634a +0 122 #7b844a +0 123 #63737b +0 124 #e7bd7b +0 125 #dedede +0 126 #f3eed3 +0 127 #f5ae5d +0 128 #95ce99 +0 129 #b5157d +0 130 #eeeeee +0 131 #848484 +0 132 #7b7b7b +0 133 #005a00 +0 134 #e77373 +0 135 #ffcb31 +0 136 #29794a +0 137 #de2821 +0 138 #2159c6 +0 139 #f8f8f8 +0 140 #e6e6e6 +0 141 #21845a +0 142 #c9c9c9 +0 143 #dfd8df +0 144 #f7f3f7 +6 450 720 8325 5580 +6 450 720 8325 4275 +6 450 720 2880 2250 +6 900 1170 2340 1890 +4 0 0 50 -1 16 20 0.0000 4 300 1410 900 1440 Public-Key\001 +4 0 0 50 -1 16 20 0.0000 4 300 1410 900 1815 Encryption\001 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 2790 2160 2790 810 540 810 540 2160 2790 2160 +-6 +6 525 2775 2805 4155 +6 630 3150 2700 3870 +6 630 3150 2700 3870 +4 0 0 50 -1 16 20 0.0000 4 225 2055 630 3420 Multi-Precision-\001 +4 0 0 50 -1 16 20 0.0000 4 300 1095 900 3795 Integers\001 +-6 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 2790 4140 2790 2790 540 2790 540 4140 2790 4140 +-6 +6 3150 2700 5580 4230 +6 3420 3150 5400 3870 +4 0 0 50 -1 16 20 0.0000 4 225 1965 3420 3420 Prime-Number\001 +4 0 0 50 -1 16 20 0.0000 4 225 1365 3420 3795 Generator\001 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 5490 4140 5490 2790 3240 2790 3240 4140 5490 4140 +-6 +6 5880 2715 8310 4245 +6 6420 3165 7680 3885 +4 0 0 50 -1 16 20 0.0000 4 225 1140 6420 3435 Random\001 +4 0 0 50 -1 16 20 0.0000 4 225 1230 6420 3810 Numbers\001 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 8220 4155 8220 2805 5970 2805 5970 4155 8220 4155 +-6 +6 3150 720 5580 2250 +6 3600 1170 5040 1890 +4 0 0 50 -1 16 20 0.0000 4 300 1425 3600 1440 Symmetric\001 +4 0 0 50 -1 16 20 0.0000 4 300 1410 3600 1815 Encryption\001 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 5490 2160 5490 810 3240 810 3240 2160 5490 2160 +-6 +6 5940 765 8280 2205 +6 6435 1215 7530 1890 +4 0 0 50 -1 16 20 0.0000 4 300 1095 6435 1440 Hashing\001 +4 0 0 50 -1 16 20 0.0000 4 300 1065 6435 1815 MACing\001 +-6 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 8235 2160 8235 810 5985 810 5985 2160 8235 2160 +-6 +-6 +6 1305 4500 7155 5580 +6 3375 4500 5085 5580 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 5022 5513 5022 4563 3438 4563 3438 5513 5022 5513 +4 0 0 50 -1 16 14 0.0000 4 195 780 3825 5130 Memory\001 +-6 +6 5445 4500 7155 5576 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 7092 5513 7092 4563 5508 4563 5508 5513 7092 5513 +4 0 0 50 -1 16 14 0.0000 4 150 1350 5635 5133 Miscelleanous\001 +-6 +6 1305 4504 3015 5580 +2 4 0 2 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 2952 5517 2952 4567 1368 4567 1368 5517 2952 5517 +4 0 0 50 -1 16 14 0.0000 4 195 1350 1495 5137 S-expressions\001 +-6 +-6 +-6 diff --git a/doc/libgcrypt-modules.pdf b/doc/libgcrypt-modules.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d65378e70a3a88480e4a9173e4e3c2a97167960e GIT binary patch literal 6090 zcmbtY2|SeD_m{MolC4mb2a)}m8M7Ek_I)S&HW*_vW|$eGg%TlzNC_!R60#;FMah~H z5mCrip`9^gN6hOk>Ls8Ac{GtO(HW0Gyv2l;~4}^f*aMHprQh!GiU_7H!L7E+p2{o zh~=vOXg$F9U6t)L_MBexg)E+&?NJATLM+l^FCpGse0~Atk2t;KgpZc|o}`Z9S>>Z1 zCpQsLQWgg%aeK~$4=&7^^{0hz(wZ?@6ySW{AQ!aPJkd{H&wFK8Qn#*cp;4`vyHS1K zB)+05Xujx8Ov;<sH+^7~4R_AY4ZffBRXz|L)YmWk<~X*x|K`E)jC)Vjme$ww z$HkQ6GzkXHN(8@etUa8s-)%>-t2-sc@|A;^pEpb7Wm>-lHV<_S^cHeydZ+Rjm)IW5 zd*oGGJLt+Hp*sT4vi=x%#4^3LXR_WaCR0SNWC=F-QgGkcW2ck@+tSaZtn4#+E^#;X zQ)-8b+w1sE%bo~ zf8&gH70E2+5H)Sfk_+UHn3U%da|E<2Ubag4 z&-88>YOGQ{FdJq;^K$A53R6v#tBVBLs#GSob&SU5JPd!=snggd_GN~VYJ4YlZr>F^ zU-#L|3lbMMf7X5N<$Sb{eMej6SiOIDmWYgzz~DUEIF~xpi}sb!_V&z<6mvsYg>mb& z9fs9Om3!9dc5BA*?WfZy6JG^UzL5;+L%i@;NUzV!v)`tdeR3aXv?t&8slBAsn<(qb zcs9hNwy2VESC4CKHy<01>%DA(q;&9+>^Q@Q0`n&|yVigC<70&Q?(`AD9 zgUWq$X5S9;yh{*~x#L%v?_NBjh|dz<7gF}(Y3gxQku}b^LTACZ&arj#5ggq=C6-rh zSn*vW&t0GLzDFNE#PSM>D}BG%ums*2Gr9Y=KYP!|pl`Vu$ejYd7FKo+qPL3^I`SUA z4xCsjY1ScksdKewh!s#;oBRlc8DS>k`SHCyFNKOfjL;ud(Uz(JjF(7+XM4Q3{~)FP$2w+r6{BhbAcv5puTuoHXHP%*M$zMn+P|@eec!7I$R)NzGzA?EyMflGz+&t2 z`>zX(?W?~G(GHjR%U^R;Gg~Nm9d!NS(mUH*sB;4w`O}>~8)R+cvm#H3D)w!8f091# zYS6y(-63MA!J||M_1WH*DURNjXE!IVkna^L3^ZjngqW7}=e6k;RsnKfw40KPpHii& z9@ZT3TiUSuytmeyvL-XXcgHC@Z%=ec|~k3Z&OW8Y@yx>=*v zxc+KX%)%+e?b&D-mJj`RXehQZ4=FyO7~Wc9Y`IGzxjPRy^T19Gj+QL;-@7^Nd!0lo z`Ki-br5DSl@{hV((xh-F{GlyB%Q+|VVz+QvsfX0^6OZ}18In?WOAr{ew7BWAMwcFe z;=Y!7pcXS*F>@62jX)@1U~4q&uS{kc=tBTa@k9b>L~tkJ)u{o1JscWFDJlXAaJVB3 z8l({@3_yXI>tLWcfll?Kxe@447Br<%-7E+Udl1T#0BA`FU_k6z0Sp}r29yZ_1oDT7 zHWd;_{E&wdBd7uOA&qo^nNZDP5NXXUCd-cm3u%Mw0#*&91E2xPoetQ;m}Z;9905p! zA5-OTqKLml*CaLY3_O`i{Hfxv+1IAR{GI=o)u1unn*f?)KudE_&mA(8#0Uh{bpRA| zZt#$XIe=bmnV1>@2++a^fXl;?zm~AN=Cwn@90OxcWB%LduN8vk2n4hze;;S6UK9Rt zsQiAWz(8$3iW`GOrL6h}4g)o*-gpwl9u7l5emBQchy;5%NGa4&Co$-z1eyij+lNd5 z6k(tR=_tV-iN-koJh~8&(SIFLUY-IyEG(K2POf8a#oyzHx$ytarXTkGKTUFTVVblK z`u=GW;y0Tt{9GB#5N7%Wp|N%r|L(TG7QDJ|zb*QZ)fO8I9ljco;n((BH}nd>-OxLp z7!m>u&9gWwvu!t3^K75r%z5fE8*I?F$ckLBt+T5+$=pB`CVFCA-z?8Ywez-ogiUtj zE>%{HUGMXPyTlUSnkkl7{odz42F~Y32rZD-d@qac0_dC@#?s(wk*%c1uM2} z;xO@gcGmmEsp57pur=+&_xthR4U%NdB!*X(wRfhbUP#I~RMno6>h5>+jD&68jP=I$ zp2L228Az?P^!Ur!mg3^#`(k9HEOHZ$NL%ORb|8_@>4{Tnd-R=!)4w}?DS=BHCB&s= zN1KsK6StbH){&4Af;`_H?ta}pTRZ&ybJx0(hc9m44!q0; zo=I*ZyLKUJTa`Ty@YV$=lqPeu9`;aq`}h$Y->NNQLIzw?KpWxJfo>l7Dw*Tjo>wC z4o9C)w-L)S7+9a63bXYIaf(z33io_cJ~n>2=_L@yKXJufdN%P}372bOZ)HIDx#|o{ z)Ch;A<>lZw=ce5~boV!AmZuMM3NKYul?;tHaG1K&uS`UzaNq(Oc9U{^139Z-O-h&g zKledq_CH(C(Ra{(zi>HruXbY-wcn=cYXQkGp(Ve?wA#Y}pbmQSD2dIY&c2_26tHhA z`$Em@C0mNOzMG~uFx0e_I;6|mRI*OIH8gUrYM>HXFIw)|?tchAbPwxaTRPC|dbBf8 zUZluykbF04Yq`t48!aK6wvQD3cy7RTCtQk25f9=!@%$O(mAVn|{9+duk@jud!$ynQ zjK8YU(*@4GwO|cwKO(^{QJa)Junyd&9Cm?gYEC9OPtsOinc`?H!F`dVrFu+DP;KLL z8HqgCy%D6$bvl<^DxK{5HyQQkO;t6+e2R_48h7z0xRDRjTO+yb+GlDsH5c`Cg}H0D zhUE{~Gjd0d3*MiX*MSwCHQrM(WFm2%U2u^KJDh>qJWTo(ZJ^Cxk?IqP*L)B_2oDLcDqkA8193^r&v3SKh&Kz_YgsD zc)ytORQD&*rhBvvAfHD>3OX$)yvd5ElbB-1xuB3SJ&-*EsF4g2~_DlNu0%tYsW3$s+4phz! zpOUC4(@;bOOloruJ;AE;Pw6ahPFP2?j~XZlVWRffUJEwe%Ka&Z<@>}A#&Tma*!IHO zNfjG-sisrcqeZW!=yCH9>70+iP{s1-ljUXKloL9qFAX{>Y){T!-xXNV>2&rh%GPGf zJ=QDu@~0<7C)_*;OS8}M99bz!?HBEZ)kDuQIfat@t)GUap}9^Cp<6h zNF{#~e9>|n-_e-(J#=3Szg1XjjCE>H*L*Lb^IVOR@3pk21E!y@OyYXUUuPFDnj!UN zI!>IoHd}0e<+qsr^5N9uuLB{5rbIQKWuu{jJ8lUufM+M zmHoZoPb`WfX|Qjp7Z0GjgJ=EbEaNuziIxs$1t$vV>nLvSao|<5b+~X$IcM=uS&Vaq zT$AGzIj=K$aJNF|rR=eMmyyoGlS zh{GgAd>mNLIhOOWKgs$@ zyhCQ+&5r(Bx>A;Kty4*~-87d_Mzzi6QvQUV+G}?v^)XY4*NqCn6CXpX6J9N~-CAEL zrZV!Rqyq+U;)sn|ov2}T|64ci>1?Hs_tyJsV7)pNTI*+{Sfs)+bhI{s^BuL^=*fQmbQj_&S@`@lbfZ%0-R<6m->c8Cx^J)%#KbH zdm;65xkTly@1NiCE{(ui!qbJ6&Dvs>Uh6)d%XjTmd;Yd;*e{G&)Z~@YG*GtPEK1mWeq7wd<`S#@gA3&N zt>#I6OZV5SJ#Kt@2%~sZA^`46_n5ld(!IatyC}}k_)Ktcb&#~w@nLS0u{{l#z|b4C zF6#L_`$G-txhouJuF4g9#|(U=1(VC<9A)lai=4fZnq($8;J(2TYunRvW8PyjjRXj@ zu(Q>D4l{{V9v_MRst3C<@*qZl?Ssusq{I7}@U|J2q5WE4D>S3;v)yw6*=xn~OK-sh zzi{Qo-f%T~d$b|tHJ$eUzy#_Pewjmd=2*hNTq}QGzoC0F;wL6qy`rz(f7S7H0u#)D z>c(o&Bcn?o`x6)>H@qB)P6e4GngqHVjpW0i(f|Y#MVYVOOIL^1fCY5xhc2l!Izz(~ zPXpkfA%3liKq5eEk~_nbZVzLM{x6^ZVjQi=ygS4H4;nBSCfvdznILYhja6LjBcbwI7-njmG@=!GE=XwUDdx!2#x*se6qZ#(cv81ttZOV_NWo0!cFU ztO8Xn3RHR{QHTIy6?TDtg9g8Wus^WhnjFa7-=9jLy`ZR3=%l~;nj{Yo0)&Ji=xYx{ zp+RpF#gFdzn_A|A*8+tJM*a~GtKC&>`5%Kv9RlAF_Lf5;AU|V}02YOCWFi?N9YDcA zHM$!UhC@UMLF0XN2_&NDT9+Ah%rT}U4Ag^wFUd`fLWGbX1QIP61aB(k-KqHU}x`W1`#*g)ZJ|I*b0JT6GNCfGiCuk1pfDDiX zT7bHsAE*bCK|E*x27un6tJLZeA>2w(09Fy&Z@`xsL~Fi*iU#g}ZUma7j;SG_<4L76 ze*9$sMR_|Uk`vmqZQDA z2e3v%pwJN5XFdSsCk>54LqYR*8bSdFIqM%ZEDriF{)2`=L6x0<&``KPX-L!`^TOc> zDAoN#7K!|W4~@Y5!H2>yOC0}@MJxV`eTYA4I24q9{w|9`<+A!F(5w!pgENa6@Z|qG6z6CiU$>7M%ZdCiO#^&7^^#i#$b^!ad9mZZP@<+k9x>7 literal 0 HcmV?d00001 diff --git a/doc/libgcrypt-modules.png b/doc/libgcrypt-modules.png new file mode 100644 index 0000000000000000000000000000000000000000..dd194e2dd4801dadc79ddfb35e5349a6e0fbcc6e GIT binary patch literal 6883 zcmeHLXHXN`who}6RF7U!Kv4ulN{E6G=|~YnM^Gey5oyK{Kstt^9tD-61_&ZeMFNNf zC529q2%ZoEQUig2krI&->4cIz&dmGq-rP5H%bPdzew-hB_MW}h?3uM@ed}B6d+h9J zBPA{`4gdh8AQ!DJ0RX~^0DzFg9^svvX4i$Goo#REMUQX*K+@sQCDhYd;ka{oG{X97 zglkAZM6^$sKfuP>{uYB_d0gbohe9-mZRgb!Lxxup%;|F8qk=Ox^Xw^So`lyQsyKDXG_) z`X;qNq~e&m`-_K*l_;R_NU}#XyMWbQm)kp4gj@E+TQufq(XHrml$v%nJB-oqHcm*((7*JWL=y*aZ77>WXxY* zk`hT@KuR^%?MDRN4=jm@+wLL6Ua2fh$ywXAG4Emr4!q)B`^REt0vX1UV}{L@`ny)$ z>ufmJPSB(E(-=TEoqM?>zD>S3A^It^WPGB1^)u=NUqpO+i%A+c%%<1(+VK048k>_Z z5wuz8^|`jt*mPBVu?5mtiIf`6+gizq)K$=`)GS;XI6V<#h>s0_^XtgylC9~89M8Wc z1G7K3+x{eHHcRB=aF%a{Ukj@ULs`)uIxsTQS><3Bi!V8iqZI*RlSFKMwFkH&PJ$|M z2u3cs5Eh98qx9(0V3e8*#4h&Z*b#KXrJ`pZH+71-^bqCmRV}x1M~RXWoa$Jt)=|%R zw?XgxxnM&nG%SAtnMLeSKQ@vo7)|Bli0zd8F&EzR(0pGt-e#fh@U)JcVhtmV-v=r= zS!sHAs16mV8{j#p4g#rQq1?klCa{gCuY{@5r_8uWsvS>NCwKc#ollR+>!t`OC&} z4bh`mJSS;l<53U`o3wn#q4iEp=N<9N#CA?4d;oX#7y&qa>Bpxt!1cR2lxu`X^iY!^Fr+7rr}t|QK~X<>FIemB_8UY$r9TC!92v}D$Z+86vY?wLb&p>HJ8sb_nqP$ z&_d8u4xJim2~-W~inE4`r9yj{+X=fBRgl+i0>6Wtl4t^4ajpi7E(W&%2iE7x^b`*k z_Cusy2S(=#TqM4dMJ}uGltUmp@C$F5Ln`tSTetaVU~FA34(Wqb9!KZor&l_a*krgC z=bGg=^19ENGo7^sp5wV>tEN@oDg+3JG{`xa>r#;RM83|)wY5}LpwOI4-nZqk>pE9^ z;2KqvN?Jnsq!HMurLHdp+jZVx!4mxI6=^TiTOLM7@w!c`o3Cgba2r>M9^^x3YV`7_ zKnnUOF@zXq4DLx?I1X1vwg8I?Ve1pJwtjEC3N#|$-RP^5tDwUk0B6G#P49Y(U0H8F zp$1V9ugLFO{9E0L6R3JUq<<^12$Rxj4Y8QuT)-#{<%I!_KalRoMxyn-=6>y!Iaag$ z(;D^;q_pGFGTWUjAwijaoJx_en^D9)+52(khh*4YLhSFQvM`d0o(D9c@#&Tht;8T( zq4xV=DTcsSJN9{cdnsp9IC-t7QQwv(b>5JaGGTd?dqi;MBJ*?>Pa-QrrxBCk!)oBU zS0K2=3Bjc@KZ)_9otpgnT1(l8-rWO=+O~>^IS>ULX=b5iI)#?nKJvmKBc!6lR-_2y zAJaaZ-Lc4{E3StpcMZTU-d2NCgdWbtP&2->&mc7+Niby4%qyDe=2LD?V$IpA9<2MC z6={5{*6{#jJtb)83yS>Fi;G%tODWp|!!nPq;>nUlai{#ZQhK2ZWNl>YUE7NaKW|SL zodW-e>+7*ST>6CYS~U5Xb=mpCB1{}WUR)*`t>1@by`PEe6K>xA7m9n`Br49}TPNZ9 zn{7GYjlflbvm+A#xd1dltRY-upY0?AjK4)D{J6Jjb@op?o}T%BqFV1wKJUld2u=a* za_`q1*eRmugTrn1=&SLEhc{3b>d1}IaHeq+>;`cBoV~K)+`T6e;RWJ_1UPe?joJd7 z^99CHbTHU+FIQt`%u^IYdW)TV_eV}FWD391RWud-UozGIp6mYUA3h{vKvI-Y!R>vM zo7lw{f*nS^rm;PlJ0z#M%62|$3<*gSF^x#u+j zAmdEg&`q?E1PK32tp5)qF9{{h*no~rn*Dd8N-RVFc?5_NRxp3GpK zuF$)m5tA}g1(p>*ADCal5k|&;&iEY`J>)}&N;;=}*|NxyrgKJ_TP>r_Wj*MpBR)ZLgbaRF@Nr0(#nrH(niH_JeQ zx8%D2y9GIZvc6H3(ZcT1@s3C4G(!4ehW-<|dYwk5N&~^yF*XHTTKFX8+AGxEg|M19 z-lE7&Z^*5zUAONftcv=(LL$`(Yxqp9@N;FOTJMspW3R|?OJ8?RruT$dTasoo+MvTR zVbM9XFl1(iff~&VqV1)V&>n=3tQRJb>=#|yCU|90CnuT%A=;;D9~&Vn0WKyDB9X;$ zHo1uYqEf_-o``^&?g6|)36F6xbRcXgZm-%H_aZrIs;VJT@uIpgs%RNmM zk@fSLraiHFbGLJJxscZlXmOW>R^+I+=T7h>QT1r|u6eK51j4RPEpC+@SG@i@ReOT- zo#JWavNqf3EcN9>fIHR!)^{JQ(VJQLxC}SZwJ^M{2R;iuH@N1?hVKr5px^eO@1oMkpYO3r#HvuR~7Mb zFXWsqrhs)ds>f&4GcuAO)ah64s+=+zr)%8pKI&2U?i*PT)?c7`Yo+m%(S+FK+N_y{ z-^RGrwTc&rJN_a?zg->Pxae!xm_~}zB-{JsqCL*xqu*pcSU1czHGLMhJ=C=cMSv&3 z$K>a$H08F6H)weLOzm*Vd%caFlumE(L*#nm*o0-j5a-SiK{Ih*&6jesknALK8mM5T zZ+T@p$TRF-uq4@5lT#M~_bYa&41P3gLd}qq(kjgJ8n`>8L#;q|S~`NWh8R;mm2;&e zL}=>l66~E!=)*?W-8^@3vHM@J=5M0hWXL*u|8a}{p`0&I?gS})^T?@mZQxzJYuB%H zYkD2QT&I4nuKjAqI5|Oyu-rG6r$)?_-O%4GD|QJJ+M_~Ld`$=~oP4_59@f3f92~qc zHNG%lw>bPZ&@Al(PpY4q_LMu%`eSiWoV@wcB3DnDN0UYsk-P%JjV50^H645b_iC3h zAK?yw`p342MEYd*&I|yVzY(siIy__yU5tuj4?C2lE@lk3jA~oKsm9OZp@WErl$qrT4TxObrY>!-KE~u`IOCfY{S5*&hpK{ zrYJqPn9&Ji5T<4b3uzGA2{Tuz`8FQ>Iy=K>oN#t9Fm*3%PoHVjA@9f%ux(KThoQCxOf#*~>e0nP^9Q z;dGxx@Hsr6`id}3p~Ec`G23W%rC>o~33*39v00)0Y7#F;3${Gp0>Q%v$h%U zNB$n!rtET{ic(P5u5sq<2CqbJ?1xRvXIBn#z+$h5ff6EpV7m7vTuzzs{S)IG|G@fi zQB3~rC4;|JWn3GzCq`HLcdSQ?YJHCRIiEBC_2R?zd~+p4E3NAqs`%kPP!~#{`fO=_ zR;up;oGr~%kI6b|mlCD%pm*?y5~34fIp7BudKK_*=?j17+TUlxYY64EB*mF;7+NB2 zNBdP>BExwvZQ2r&juLm<+|nWDL?eQLJzYxFtVRA5&iimjS46x1~KY$$TE z0`0sS@1M_LKNt-9e220e9gvy-eD>7boXOE)yTCTMIFO$&p8KtkZYvioNo5*&?N}+db%?#8| zJI*rjyNUaNPh%FQfi79|X1IRHA$Qc!vFUKtTB+0kw&B;Yo4W(5mmy5OcmgJw>ge-$ ztKl}Aee~;gR^+9SHK?hk%+f5YWfAi&$d!iry`EIt;DC-hQ=3026f}PZ|0&q-q2ApA zo6Lq%Ouc7Q4e2{Gfw95l;l4-KaeG-Fs9Sr6KE#Md=RBeLU!XFUK$su{vr9bw8dwBT zxUf}Rhuz$Ay2aIH>?@H^SF)0ta}yiA0v(*pSHn~Go~g;0*139zfsETzQre7mq5TFu za98r*7Tx|kC}^ndgueWwJs#oL6sk_z(GW%b+DgB>!>b6*5-hKR717SkdCU%@s+QXDYJL?lydeeoiqepI>AdK0Bfa5i`X-X~JICRV^xLDRa~Mq5 zjL~j2ll{?3MzduzZhuH4s^L=Ip*whX6o|xGr`C9Up8vEXssbR^j#fB}>-Qi3U(2$) z`u|gw?f^HR6I}^_Atw?5Ab*qv+!zox?|=dxc}M`xAcT$w q00E!h@4owj2-t`J>+!E3{FMoR!QuZ;P4GtB@6K+4ql*4(E&UIuonzzx literal 0 HcmV?d00001 diff --git a/doc/mdate-sh b/doc/mdate-sh new file mode 100755 index 0000000..cd916c0 --- /dev/null +++ b/doc/mdate-sh @@ -0,0 +1,201 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. + +scriptversion=2005-06-29.22 + +# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005 Free Software +# Foundation, Inc. +# written by Ulrich Drepper , June 1995 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No file. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: mdate-sh [--help] [--version] FILE + +Pretty-print the modification time of FILE. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "mdate-sh $scriptversion" + exit $? + ;; +esac + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +# GNU ls changes its time format in response to the TIME_STYLE +# variable. Since we cannot assume `unset' works, revert this +# variable to its documented default. +if test "${TIME_STYLE+set}" = set; then + TIME_STYLE=posix-long-iso + export TIME_STYLE +fi + +save_arg1=$1 + +# Find out how to get the extended ls output of a file or directory. +if ls -L /dev/null 1>/dev/null 2>&1; then + ls_command='ls -L -l -d' +else + ls_command='ls -l -d' +fi + +# A `ls -l' line looks as follows on OS/2. +# drwxrwx--- 0 Aug 11 2001 foo +# This differs from Unix, which adds ownership information. +# drwxrwx--- 2 root root 4096 Aug 11 2001 foo +# +# To find the date, we split the line on spaces and iterate on words +# until we find a month. This cannot work with files whose owner is a +# user named `Jan', or `Feb', etc. However, it's unlikely that `/' +# will be owned by a user whose name is a month. So we first look at +# the extended ls output of the root directory to decide how many +# words should be skipped to get the date. + +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +set x`ls -l -d /` + +# Find which argument is the month. +month= +command= +until test $month +do + shift + # Add another shift to the command. + command="$command shift;" + case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; + esac +done + +# Get the extended ls output of the file or directory. +set dummy x`eval "$ls_command \"\$save_arg1\""` + +# Remove all preceding arguments +eval $command + +# Because of the dummy argument above, month is in $2. +# +# On a POSIX system, we should have +# +# $# = 5 +# $1 = file size +# $2 = month +# $3 = day +# $4 = year or time +# $5 = filename +# +# On Darwin 7.7.0 and 7.6.0, we have +# +# $# = 4 +# $1 = day +# $2 = month +# $3 = year or time +# $4 = filename + +# Get the month. +case $2 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; +esac + +case $3 in + ???*) day=$1;; + *) day=$3; shift;; +esac + +# Here we have to deal with the problem that the ls output gives either +# the time of day or the year. +case $3 in + *:*) set `date`; eval year=\$$# + case $2 in + Jan) nummonthtod=1;; + Feb) nummonthtod=2;; + Mar) nummonthtod=3;; + Apr) nummonthtod=4;; + May) nummonthtod=5;; + Jun) nummonthtod=6;; + Jul) nummonthtod=7;; + Aug) nummonthtod=8;; + Sep) nummonthtod=9;; + Oct) nummonthtod=10;; + Nov) nummonthtod=11;; + Dec) nummonthtod=12;; + esac + # For the first six month of the year the time notation can also + # be used for files modified in the last year. + if (expr $nummonth \> $nummonthtod) > /dev/null; + then + year=`expr $year - 1` + fi;; + *) year=$3;; +esac + +# The result. +echo $day $month $year + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/doc/stamp-vti b/doc/stamp-vti new file mode 100644 index 0000000..cde5683 --- /dev/null +++ b/doc/stamp-vti @@ -0,0 +1,4 @@ +@set UPDATED 22 January 2009 +@set UPDATED-MONTH January 2009 +@set EDITION 1.4.4 +@set VERSION 1.4.4 diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..8083622 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,7482 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2006-10-04.17} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free +% Software Foundation, Inc. +% +% This texinfo.tex file is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License as +% published by the Free Software Foundation; either version 2, or (at +% your option) any later version. +% +% This texinfo.tex file is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the implied warranty +% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +% Boston, MA 02110-1301, USA. +% +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. (This has been our intent since Texinfo was invented.) +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org). +% The texinfo.tex in any given distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. + + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\message{Basics,} +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexfootnote=\footnote +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexinsert=\insert +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{l.\the\inputlineno:\space} +\fi + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi + +% Since the category of space is not known, we have to be careful. +\chardef\spacecat = 10 +\def\spaceisspace{\catcode`\ =\spacecat} + +% sometimes characters are active, so we need control sequences. +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dashChar = `\- +\chardef\dotChar = `\. +\chardef\exclamChar= `\! +\chardef\lquoteChar= `\` +\chardef\questChar = `\? +\chardef\rquoteChar= `\' +\chardef\semiChar = `\; +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} + +% Hyphenation fixes. +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines16 +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + % We don't want .vr (or whatever) entries like this: + % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} + % "\acronym" won't work when it's read back in; + % it needs to be + % {\code {{\tt \backslashcurfont }acronym} + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingyyy.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 24pt + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \indexdummies + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\argtorun{#2}% + \begingroup + \obeylines + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. +} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + \argremovecomment #1\comment\ArgTerm% + }% +} + +% First remove any @comment, then any @c comment. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} + +% Each occurence of `\^^M' or `\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, e.g., +% @end itemize @c foo +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. +% +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm +} + +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \argtorun. +% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. +% +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} + +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +% +% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my +% favourite TeX trick. --kasal, 16nov03 + +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} + +% Several utility definitions with active space: +{ + \obeyspaces + \gdef\obeyedspace{ } + + % Make each space character in the input produce a normal interword + % space in the output. Don't allow a line break at this space, as this + % is used only in environments like @example, where each line of input + % should produce a line of output anyway. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % If an index command is used in an @example environment, any spaces + % therein should become regular spaces in the raw index file, not the + % expansion of \tie (\leavevmode \penalty \@M \ ). + \gdef\unsepspaces{\let =\space} +} + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +% Define the framework for environments in texinfo.tex. It's used like this: +% +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as enviroments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At runtime, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp + \else + \badenverr + \fi +} + +% Evironment mismatch, #1 expected: +\def\badenverr{% + \errhelp = \EMsimple + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + out of any environment% + \else + in environment \expandafter\string#1% + \fi +} + +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv +% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi +} + +\newhelp\EMsimple{Press RETURN to continue.} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux/toc files. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% + \kern-.15em + \TeX +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=\endofsentencespacefactor\space} + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=\endofsentencespacefactor\space} + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% + \fi\fi +} + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\envdef\group{% + \ifnum\catcode`\^^M=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + \startsavinginserts + % + \setbox\groupbox = \vtop\bgroup + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% The \vtop produces a box with normal height and large depth; thus, TeX puts +% \baselineskip glue before it, and (when the next line of text is done) +% \lineskip glue after it. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \box\groupbox + \prevdepth = \dimen1 + \checkinserts +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +% Old definition--didn't work. +%\parseargdef\need{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\parseargdef\need{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break (and is undocumented). + +\let\br = \par + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} + +% This defn is used inside nofill environments such as @example. +\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount + \leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack + \def\thisfile{#1}% + {% + \makevalueexpandable + \def\temp{\input #1 }% + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \catcode`-=\other +} + +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\parseargdef\center{% + \ifhmode + \let\next\centerH + \else + \let\next\centerV + \fi + \next{\hfil \ignorespaces#1\unskip \hfil}% +} +\def\centerH#1{% + {% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break + }% +} +\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} + +% @sp n outputs n lines of vertical space + +\parseargdef\sp{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\parseargdef\paragraphindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\parseargdef\exampleindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indent at such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. +% We switch the definition of this back and forth according to WORD. +% By default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\def\insertword{insert} +% +\parseargdef\firstparagraphindent{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \restorefirstparagraphindent + \indent + }% + \gdef\noindent{% + \restorefirstparagraphindent + \noindent + }% + \global\everypar = {% + \kern -\parindent + \restorefirstparagraphindent + }% +} + +\gdef\restorefirstparagraphindent{% + \global \let \indent = \ptexindent + \global \let \noindent = \ptexnoindent + \global \everypar = {}% +} + + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{$\ptexbullet$} +\def\minus{$-$} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in the cm +% typewriter fonts as three actual period characters; on the other hand, +% in other typewriter fonts three periods are wider than 1.5em. So do +% whichever is larger. +% +\def\dots{% + \leavevmode + \setbox0=\hbox{...}% get width of three periods + \ifdim\wd0 > 1.5em + \dimen0 = \wd0 + \else + \dimen0 = 1.5em + \fi + \hbox to \dimen0{% + \hskip 0pt plus.25fil + .\hskip 0pt plus1fil + .\hskip 0pt plus1fil + .\hskip 0pt plus.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @comma{} is so commas can be inserted into text without messing up +% Texinfo's parsing. +% +\let\comma = , + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi % \openindices needs to do some work in any case. + \openindices + \let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + \openin 1 texinfo.cnf + \ifeof 1 \else \input texinfo.cnf \fi + \closein 1 + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as \undefined, +% borrowed from ifpdf.sty. +\ifx\pdfoutput\undefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html +% (and related messages, the final outcome is that it is up to the TeX +% user to double the backslashes and otherwise make the string valid, so +% that's what we do). + +% double active backslashes. +% +{\catcode`\@=0 \catcode`\\=\active + @gdef@activebackslashdouble{% + @catcode`@\=@active + @let\=@doublebackslash} +} + +% To handle parens, we must adopt a different approach, since parens are +% not active characters. hyperref.dtx (which has the same problem as +% us) handles it with this amazing macro to replace tokens. I've +% tinkered with it a little for texinfo, but it's definitely from there. +% +% #1 is the tokens to replace. +% #2 is the replacement. +% #3 is the control sequence with the string. +% +\def\HyPsdSubst#1#2#3{% + \def\HyPsdReplace##1#1##2\END{% + ##1% + \ifx\\##2\\% + \else + #2% + \HyReturnAfterFi{% + \HyPsdReplace##2\END + }% + \fi + }% + \xdef#3{\expandafter\HyPsdReplace#3#1\END}% +} +\long\def\HyReturnAfterFi#1\fi{\fi#1} + +% #1 is a control sequence in which to do the replacements. +\def\backslashparens#1{% + \xdef#1{#1}% redefine it as its expansion; the definition is simply + % \lastnode when called from \setref -> \pdfmkdest. + \HyPsdSubst{(}{\realbackslash(}{#1}% + \HyPsdSubst{)}{\realbackslash)}{#1}% +} + +\ifpdf + \input pdfcolor + \pdfcatalog{/PageMode /UseOutlines}% + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifdim \wd0 >0pt width \imagewidth \fi + \ifdim \wd2 >0pt height \imageheight \fi + \ifnum\pdftexversion<13 + #1.pdf% + \else + {#1.pdf}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \atdummies + \activebackslashdouble + \def\pdfdestname{#1}% + \backslashparens\pdfdestname + \pdfdest name{\pdfdestname} xyz% + }}% + % + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1}% + % + \let\linkcolor = \Blue % was Cyan, but that seems light? + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by 1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + % + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worth the trouble, since most documents are normally structured. + \def\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty + \def\pdfoutlinedest{#4}% + \else + % Doubled backslashes in the name. + {\activebackslashdouble \xdef\pdfoutlinedest{#3}% + \backslashparens\pdfoutlinedest}% + \fi + % + % Also double the backslashes in the display string. + {\activebackslashdouble \xdef\pdfoutlinetext{#1}% + \backslashparens\pdfoutlinetext}% + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% + } + % + \def\pdfmakeoutlines{% + \begingroup + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \def\thissubsecnum{0}% + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% + \readdatafile{toc}% + % + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. + % + % xx to do this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Right + % now, I guess we'll just let the pdf reader have its way. + \indexnofonts + \setupdatafile + \catcode`\\=\active \otherbackslash + \input \jobname.toc + \endgroup + } + % + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \linkcolor #1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\else + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput + + +\message{fonts,} + +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname ten#1\endcsname % change the current font +} + +% Select #1 fonts with the current style. +% +\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +% Definitions for a main text size of 11pt. This is the default in +% Texinfo. +% +\def\definetextfontsizexi{ +% Text fonts (11.2pt, magstep1). +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1} +\setfont\deftt\ttshape{10}{\magstep1} +\setfont\defttsl\ttslshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter (and unnumbered) fonts (17.28pt). +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% Subsection fonts (13.15pt). +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1315} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 + +% Reduced fonts for @acro in text (10pt). +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000} +\setfont\reducedtt\ttshape{10}{1000} +\setfont\reducedbf\bfshape{10}{1000} +\setfont\reducedit\itshape{10}{1000} +\setfont\reducedsl\slshape{10}{1000} +\setfont\reducedsf\sfshape{10}{1000} +\setfont\reducedsc\scshape{10}{1000} +\setfont\reducedttsl\ttslshape{10}{1000} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 + +% reset the current fonts +\textfonts +\rm +} % end of 11pt text font size definitions + + +% Definitions to make the main text be 10pt Computer Modern, with +% section, chapter, etc., sizes following suit. This is for the GNU +% Press printing of the Emacs 22 manual. Maybe other manuals in the +% future. Used with @smallbook, which sets the leading to 12pt. +% +\def\definetextfontsizex{% +% Text fonts (10pt). +\def\textnominalsize{10pt} +\edef\mainmagstep{1000} +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstephalf} +\setfont\deftt\ttshape{10}{\magstephalf} +\setfont\defttsl\ttslshape{10}{\magstephalf} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter fonts (14.4pt). +\def\chapnominalsize{14pt} +\setfont\chaprm\rmbshape{12}{\magstep1} +\setfont\chapit\itbshape{10}{\magstep2} +\setfont\chapsl\slbshape{10}{\magstep2} +\setfont\chaptt\ttbshape{12}{\magstep1} +\setfont\chapttsl\ttslshape{10}{\magstep2} +\setfont\chapsf\sfbshape{12}{\magstep1} +\let\chapbf\chaprm +\setfont\chapsc\scbshape{10}{\magstep2} +\font\chapi=cmmi12 scaled \magstep1 +\font\chapsy=cmsy10 scaled \magstep2 + +% Section fonts (12pt). +\def\secnominalsize{12pt} +\setfont\secrm\rmbshape{12}{1000} +\setfont\secit\itbshape{10}{\magstep1} +\setfont\secsl\slbshape{10}{\magstep1} +\setfont\sectt\ttbshape{12}{1000} +\setfont\secttsl\ttslshape{10}{\magstep1} +\setfont\secsf\sfbshape{12}{1000} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep1} +\font\seci=cmmi12 +\font\secsy=cmsy10 scaled \magstep1 + +% Subsection fonts (10pt). +\def\ssecnominalsize{10pt} +\setfont\ssecrm\rmbshape{10}{1000} +\setfont\ssecit\itbshape{10}{1000} +\setfont\ssecsl\slbshape{10}{1000} +\setfont\ssectt\ttbshape{10}{1000} +\setfont\ssecttsl\ttslshape{10}{1000} +\setfont\ssecsf\sfbshape{10}{1000} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1000} +\font\sseci=cmmi10 +\font\ssecsy=cmsy10 + +% Reduced fonts for @acro in text (9pt). +\def\reducednominalsize{9pt} +\setfont\reducedrm\rmshape{9}{1000} +\setfont\reducedtt\ttshape{9}{1000} +\setfont\reducedbf\bfshape{10}{900} +\setfont\reducedit\itshape{9}{1000} +\setfont\reducedsl\slshape{9}{1000} +\setfont\reducedsf\sfshape{9}{1000} +\setfont\reducedsc\scshape{10}{900} +\setfont\reducedttsl\ttslshape{10}{900} +\font\reducedi=cmmi9 +\font\reducedsy=cmsy9 + +% reduce space between paragraphs +\divide\parskip by 2 + +% reset the current fonts +\textfonts +\rm +} % end of 10pt text font size definitions + + +% We provide the user-level command +% @fonttextsize 10 +% (or 11) to redefine the text font size. pt is assumed. +% +\def\xword{10} +\def\xiword{11} +% +\parseargdef\fonttextsize{% + \def\textsizearg{#1}% + \wlog{doing @fonttextsize \textsizearg}% + % + % Set \globaldefs so that documents can use this inside @tex, since + % makeinfo 4.8 does not support it, but we need it nonetheless. + % + \begingroup \globaldefs=1 + \ifx\textsizearg\xword \definetextfontsizex + \else \ifx\textsizearg\xiword \definetextfontsizexi + \else + \errhelp=\EMsimple + \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} + \fi\fi + \endgroup +} + + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this because \STYLE needs to also set the +% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire +% \tenSTYLE to set the current font. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used in +% the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \let\tenttsl=\textttsl + \def\curfontsize{text}% + \def\lsize{reduced}\def\lllsize{smaller}% + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \def\curfontsize{title}% + \def\lsize{chap}\def\lllsize{subsec}% + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \let\tenttsl=\chapttsl + \def\curfontsize{chap}% + \def\lsize{sec}\def\lllsize{text}% + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \let\tenttsl=\secttsl + \def\curfontsize{sec}% + \def\lsize{subsec}\def\lllsize{reduced}% + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \let\tenttsl=\ssecttsl + \def\curfontsize{ssec}% + \def\lsize{text}\def\lllsize{small}% + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts +\def\reducedfonts{% + \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl + \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc + \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy + \let\tenttsl=\reducedttsl + \def\curfontsize{reduced}% + \def\lsize{small}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \def\curfontsize{small}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \def\curfontsize{smaller}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \scriptfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish the USA used A4 paper. +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\definetextfontsizexi + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000} +\setfont\shortconttt\ttshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else + \ptexslash\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally uses \ttsl. +% @var is set to this for defun arguments. +\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\slanted=\smartslanted +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic + +% @b, explicit bold. +\def\b#1{{\bf #1}} +\let\strong=\b + +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\plainfrenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends + } +\catcode`@=\other +\def\endofsentencespacefactor{3000}% default + +\def\t#1{% + {\tt \rawbackslash \plainfrenchspacing #1}% + \null +} +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \plainfrenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in @code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active + % + \global\def\code{\begingroup + \catcode\rquoteChar=\active \catcode\lquoteChar=\active + \let'\codequoteright \let`\codequoteleft + % + \catcode\dashChar=\active \catcode\underChar=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\realdash + \let_\realunder + \fi + \codex + } +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is undesirable in +% some manuals, especially if they don't have long identifiers in +% general. @allowcodebreaks provides a way to control this. +% +\newif\ifallowcodebreaks \allowcodebreakstrue + +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse + \else + \errhelp = \EMsimple + \errmessage{Unknown @allowcodebreaks option `\txiarg'}% + \fi\fi +} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\txiarg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\txiarg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle option `\txiarg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. +\let\indicateurl=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\selectfonts\lsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\plainfrenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% +\def\pounds{{\it\$}} + +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + \hfil\crcr\Orb}}% + }$% +} + +% @textdegree - the normal degrees sign. +% +\def\textdegree{$^\circ$} + +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\undefined +\def\Orb{\mathhexbox20D} +\fi + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \let\page = \oldpage + \page + \null + }% +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Macros to be used within @titlepage: + +\let\subtitlerm=\tenrm +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt} + +\parseargdef\title{% + \checkenv\titlepage + \leftline{\titlefonts\rm #1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\authorfont \leftline{#1}}% + \fi +} + + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make TeX use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + + +\def\evenheading{\parsearg\evenheadingxxx} +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -12pt + \global\advance\vsize by -12pt +} + +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{% +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg{\gdef\thistitle}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @ftable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemindicate{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted would + % cause the example and the item to crash together. So we use this + % bizarre value of 10001 as a signal to \aboveenvbreak to insert + % \parskip glue after all. Section titles are handled this way also. + % + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} + +% @table, @ftable, @vtable. +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% +} +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley +} +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\envdef\itemize{\parsearg\doitemize} + +\def\doitemize#1{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + \def\itemcontents{#1}% + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + \let\item=\itemizeitem +} + +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + \vadjust{\penalty 1200}}% not good to break after first line of item. + \flushcr +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call \doitemize, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \doitemize{#1.}\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. +% Assignments have to be global since we are inside the implicit group +% of an alignment entry. Note that \everycr resets \everytab. +\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% +% +% A \tab used to include \hskip1sp. But then the space in a template +% line is not enough. That is bad. So let's go back to just `&' until +% we encounter the problem it was intended to solve again. +% --karl, nathan@acm.org, 20apr99. +\def\tab{\checkenv\multitable &\the\everytab}% + +% @multitable ... @end multitable definitions: +% +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% + \vskip\parskip + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + % + \everycr = {% + \noalign{% + \global\everytab={}% + \global\colcount=0 % Reset the column counter. + % Check for saved footnotes, etc. + \checkinserts + % Keeps underfull box messages off when table breaks over pages. + %\filbreak + % Maybe so, but it also creates really weird page breaks when the + % table breaks over pages. Wouldn't \vfil be better? Wait until the + % problem manifests itself, so it can be fixed for real --karl. + }% + }% + % + \parsearg\domultitable +} +\def\domultitable#1{% + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively + % marking characters. + \noindent\ignorespaces##\unskip\multistrut + }\cr +} +\def\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse +} + +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +\fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{conditionals,} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} +\def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% Ignore text until a line `@end #1', keeping track of nested conditionals. +% +% A count to remember the depth of nesting. +\newcount\doignorecount + +\def\doignore#1{\begingroup + % Scan in ``verbatim'' mode: + \obeylines + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \spaceisspace + % + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. + % + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next +} + +% Finish off ignored text. +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} + + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. +% +\parseargdef\set{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% +} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} + +% @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} +{ + \catcode`\- = \active \catcode`\_ = \active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... + \catcode`\-=\other \catcode`\_=\other + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\realdash \let_\normalunderscore + } +} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we call \makevalueexpandable in \indexdummies). +% The command has to be fully expandable (if the variable is set), since +% the result winds up in the index file. This means that if the +% variable's value contains other Texinfo commands, it's almost certain +% it will fail (although perhaps we could fix that with sufficient work +% to do a one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +% To get special treatment of `@end ifset,' call \makeond and the redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next +} +\def\ifsetfail{\doignore{ifset}} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \escapechar = `\\ % use backslash in output files. + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % I don't entirely understand this, but when an index entry is + % generated from a macro call, the \endinput which \scanmacro inserts + % causes processing to be prematurely terminated. This is, + % apparently, because \indexsorttmp is fully expanded, and \endinput + % is an expandable command. The redefinition below makes \endinput + % disappear altogether for that purpose -- although logging shows that + % processing continues to some further point. On the other hand, it + % seems \endinput does not hurt in the printed index arg, since that + % is still getting written without apparent harm. + % + % Sample source (mac-idx3.tex, reported by Graham Percival to + % help-texinfo, 22may06): + % @macro funindex {WORD} + % @findex xyz + % @end macro + % ... + % @funindex commtest + % + % The above is not enough to reproduce the bug, but it gives the flavor. + % + % Sample whatsit resulting: + % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} + % + % So: + \let\endinput = \empty + % + % Do the redefinitions. + \commondummies +} + +% For the aux and toc files, @ is the escape character. So we want to +% redefine everything using @ as the escape character (instead of +% \realbackslash, still used for index files). When everything uses @, +% this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % Do the redefinitions. + \commondummies + \otherbackslash +} + +% Called from \indexdummies and \atdummies. +% +\def\commondummies{% + % + % \definedummyword defines \#1 as \string\#1\space, thus effectively + % preventing its expansion. This is used only for control% words, + % not control letters, because the \space would be incorrect for + % control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword ##1{\def##1{\string##1\space}}% + \def\definedummyletter##1{\def##1{\string##1}}% + \let\definedummyaccent\definedummyletter + % + \commondummiesnofonts + % + \definedummyletter\_% + % + % Non-English letters. + \definedummyword\AA + \definedummyword\AE + \definedummyword\L + \definedummyword\OE + \definedummyword\O + \definedummyword\aa + \definedummyword\ae + \definedummyword\l + \definedummyword\oe + \definedummyword\o + \definedummyword\ss + \definedummyword\exclamdown + \definedummyword\questiondown + \definedummyword\ordf + \definedummyword\ordm + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt + % + \definedummyword\LaTeX + \definedummyword\TeX + % + % Assorted special characters. + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\expansion + \definedummyword\minus + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\result + \definedummyword\textdegree + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + % + \normalturnoffactive + % + % Handle some cases of @value -- where it does not contain any + % (non-fully-expandable) commands. + \makevalueexpandable +} + +% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% +\def\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter\!% + \definedummyaccent\"% + \definedummyaccent\'% + \definedummyletter\*% + \definedummyaccent\,% + \definedummyletter\.% + \definedummyletter\/% + \definedummyletter\:% + \definedummyaccent\=% + \definedummyletter\?% + \definedummyaccent\^% + \definedummyaccent\`% + \definedummyaccent\~% + \definedummyword\u + \definedummyword\v + \definedummyword\H + \definedummyword\dotaccent + \definedummyword\ringaccent + \definedummyword\tieaccent + \definedummyword\ubaraccent + \definedummyword\udotaccent + \definedummyword\dotless + % + % Texinfo font commands. + \definedummyword\b + \definedummyword\i + \definedummyword\r + \definedummyword\sc + \definedummyword\t + % + % Commands that take arguments. + \definedummyword\acronym + \definedummyword\cite + \definedummyword\code + \definedummyword\command + \definedummyword\dfn + \definedummyword\emph + \definedummyword\env + \definedummyword\file + \definedummyword\kbd + \definedummyword\key + \definedummyword\math + \definedummyword\option + \definedummyword\pxref + \definedummyword\ref + \definedummyword\samp + \definedummyword\strong + \definedummyword\tie + \definedummyword\uref + \definedummyword\url + \definedummyword\var + \definedummyword\verb + \definedummyword\w + \definedummyword\xref +} + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexnofonts{% + % Accent commands should become @asis. + \def\definedummyaccent##1{\let##1\asis}% + % We can just ignore other control letters. + \def\definedummyletter##1{\let##1\empty}% + % Hopefully, all control words can become @asis. + \let\definedummyword\definedummyaccent + % + \commondummiesnofonts + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + % Non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + \def\ordf{a}% + \def\ordm{o}% + % + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. + % (The following {} will end up in the sort string, but that's ok.) + \def\bullet{bullet}% + \def\comma{,}% + \def\copyright{copyright}% + \def\registeredsymbol{R}% + \def\dots{...}% + \def\enddots{...}% + \def\equiv{==}% + \def\error{error}% + \def\euro{euro}% + \def\expansion{==>}% + \def\minus{-}% + \def\pounds{pounds}% + \def\point{.}% + \def\print{-|}% + \def\result{=>}% + \def\textdegree{degrees}% + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% Most index entries go through here, but \dosubind is the general case. +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{\dosubind{#1}{#2}{}} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% empty if called from \doind, as we usually are (the main exception +% is with most defuns, which call us directly). +% +\def\dosubind#1#2#3{% + \iflinks + {% + % Store the main index entry text (including the third arg). + \toks0 = {#2}% + % If third arg is present, precede it with a space. + \def\thirdarg{#3}% + \ifx\thirdarg\empty \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + \edef\writeto{\csname#1indfile\endcsname}% + % + \ifvmode + \dosubindsanitize + \else + \dosubindwrite + \fi + }% + \fi +} + +% Write the entry in \toks0 to the index file: +% +\def\dosubindwrite{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% + \fi + % + % Remember, we are within a group. + \indexdummies % Must do this here, since \bf, etc expand at this stage + \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\writeto{% + \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% + }% + \temp +} + +% Take care of unwanted page breaks: +% +% If a skip is the last thing on the list now, preserve it +% by backing up by \lastskip, doing the \write, then inserting +% the skip again. Otherwise, the whatsit generated by the +% \write will make \lastskip zero. The result is that sequences +% like this: +% @end defun +% @tindex whatever +% @defun ... +% will have extra space inserted, because the \medbreak in the +% start of the @defun won't see the skip inserted by the @end of +% the previous defun. +% +% But don't do any of this if we're not in vertical mode. We +% don't want to do a \vskip and prematurely end a paragraph. +% +% Avoid page breaks due to these extra skips, too. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +% ..., ready, GO: +% +\def\dosubindsanitize{% + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \skip0 = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \count255 = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\skip0 glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\skip0 + \fi + % + \dosubindwrite + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\count255>9999 \penalty\count255 \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\skip0 + \fi +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\parseargdef\printindex{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\backslashcurfont}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \nobreak + \vskip 0pt plus 3\baselineskip + \penalty 0 + \vskip 0pt plus -3\baselineskip + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + % Do our best not to break after the initial. + \nobreak + \vskip .33\baselineskip plus .1\baselineskip +}} + +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +% A straightforward implementation would start like this: +% \def\entry#1#2{... +% But this frozes the catcodes in the argument, and can cause problems to +% @code, which sets - active. This problem was fixed by a kludge--- +% ``-'' was active throughout whole index, but this isn't really right. +% +% The right solution is to prevent \entry from swallowing the whole text. +% --kasal, 21nov03 +\def\entry{% + \begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing + % columns. + \vskip 0pt plus1pt + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\doentry{% + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. +} +\def\finishentry#1{% + % #1 is the page number. + % + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#1}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd + \ % + \else + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#1.% + \ \the\toksA + \else + \ #1% + \fi + \fi + \par + \endgroup +} + +% Like plain.tex's \dotfill, except uses up at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +% \unnumberedno is an oxymoron, of course. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% +% \def\appendixletter{\char\the\appendixno} +% We do the following ugly conditional instead of the above simple +% construct for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +% +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +% However, they are not reliable, because we don't use marks. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achive this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unmlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 + \else + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi + \fi + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unmlevel + \chardef\unmlevel = \absseclevel + \fi + \else + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unmlevel + \def\headtype{U}% + \else + \chardef\unmlevel = 3 + \fi + \fi + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi + \else + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi + \fi + \suppressfirstparagraphindent +} + +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + \message{\putwordChapter\space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + \def\appendixnum{\putwordAppendix\space \appendixletter}% + \message{\appendixnum}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the to achieve this: TeX expands \the only once, + % simply yielding the contents of . (We also do this for + % the toc entries.) + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% + % + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\parseargdef\centerchap{% + % Well, we could do the following in a group, but that would break + % an assumption that \chapmacro is called at the outermost level. + % Thus we are safer this way: --kasal, 24feb04 + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax +} + +% @top is like @unnumbered. +\let\top\unnumbered + +% Sections. +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% +} + +\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% +} +\let\appendixsec\appendixsection + +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% +} + +% Subsections. +\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% +} + +% Subsubsections. +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +} + +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% + \bigskip \par\penalty 200\relax + \suppressfirstparagraphindent +} + +% @heading, @subheading, @subsubheading. +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{% +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +% Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yomitfromtockeyword{Yomitfromtoc} +\def\Yappendixkeyword{Yappendix} +% +\def\chapmacro#1#2#3{% + \pchapsepmacro + {% + \chapfonts \rm + % + % Have to define \thissection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \gdef\thischapternum{}% + \gdef\thischapter{#1}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \gdef\thischapternum{}% + \gdef\thischapter{}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + \xdef\thischapternum{\appendixletter}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. And we don't + % use \thissection because that changes with each section. + % + \xdef\thischapter{\putwordAppendix{} \appendixletter: + \noexpand\thischaptername}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \xdef\thischapternum{\the\chapno}% + \xdef\thischapter{\putwordChapter{} \the\chapno: + \noexpand\thischaptername}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt +} + + +% I don't think this chapter style is supported any more, so I'm not +% updating it with the new noderef stuff. We'll see. --karl, 11aug03. +% +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} +% +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} +\def\CHAPFopen{% + \global\let\chapmacro=\chfopen + \global\let\centerchapmacro=\centerchfopen} + + +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} + +% Subsection titles. +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} + +% Subsubsection titles. +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} + + +% Print any size, any type, section title. +% +% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is +% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the +% section number. +% +\def\sectionheading#1#2#3#4{% + {% + % Switch to the right set of fonts. + \csname #2fonts\endcsname \rm + % + % Insert space above the heading. + \csname #2headingbreak\endcsname + % + % Only insert the space after the number if we have a section number. + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\thissection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \thissection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\thissection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\thissection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chapmacro. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chapmacro. + \donoderef{#3}% + % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % + % Output the actual section heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% + }% + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. + \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) + \vskip-\parskip + % + % This is purely so the last item on the list is a known \penalty > + % 10000. This is so \startdefun can avoid allowing breakpoints after + % section headings. Otherwise, it would insert a valid breakpoint between: + % + % @section sec-whatever + % @deffn def-whatever + \penalty 10001 +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. +% +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. +% +\newif\iftocfileopened +\def\omitkeyword{omit}% +% +\def\writetocentry#1#2#3{% + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% + \fi + \fi + % + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one on every page because the title pages are numbered + % 1 and 2 (the page numbers aren't printed), and so are the first + % two pages of the document. Thus, we'd have two destinations named + % `1', and two named `2'. + \ifpdf \global\pdfmakepagedesttrue \fi +} + + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \jobname.toc +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Prepare to read what we've written to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \def\thischapter{}% + \chapmacro{#1}{Yomitfromtoc}{}% + % + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \readtocfile + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \readtocfile + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% +} + +% Appendices, in the main contents. +% Need the word Appendix, and a fixed-size box. +% +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} +% +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} + +% Unnumbered chapters. +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} + +% Sections. +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} + +% And subsubsections. +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} + +% This parameter controls the indentation of the various levels. +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\envdef\tex{% + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + \let\frenchspacing=\plainfrenchspacing + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +} +% There is no need to define \Etex. + +% Define @lisp ... @end lisp. +% @lisp environment forms a group so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty<10000 \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\envdef\cartouche{% + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt % we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing = t% + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of \def\group. +} +\def\Ecartouche{% + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \checkinserts +} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \let\exdent=\nofillexdent +} + +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp +% +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \smallexamplefonts \rm + \fi +} + +% We often define two environments, @foo and @smallfoo. +% Let's do it by one command: +\def\makedispenv #1#2{ + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak +} + +% Define two synonyms: +\def\maketwodispenvs #1#2#3{ + \makedispenv{#1}{#3} + \makedispenv{#2}{#3} +} + +% @lisp: indented, narrowed, typewriter font; @example: same as @lisp. +% +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +% +\maketwodispenvs {lisp}{example}{% + \nonfillstart + \tt\quoteexpand + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} +% @display/@smalldisplay: same as @lisp except keep current font. +% +\makedispenv {display}{% + \nonfillstart + \gobble +} + +% @format/@smallformat: same as @display except don't narrow margins. +% +\makedispenv{format}{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} + +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} +\let\Eflushleft = \afterenvbreak + +% @flushright. +% +\envdef\flushright{% + \let\nonarrowing = t% + \nonfillstart + \advance\leftskip by 0pt plus 1fill + \gobble +} +\let\Eflushright = \afterenvbreak + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. +% +\envdef\quotation{% + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\undefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{...} +% If we want to allow any as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=\other}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} + +% Allow an option to not replace quotes with a regular directed right +% quote/apostrophe (char 0x27), but instead use the undirected quote +% from cmtt (char 0x0d). The undirected quote is ugly, so don't make it +% the default, but it works for pasting with more pdf viewers (at least +% evince), the lilypond developers report. xpdf does work with the +% regular 0x27. +% +\def\codequoteright{% + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else + \char'15 + \fi +} +% +% and a similar option for the left quote char vs. a grave accent. +% Modern fonts display ASCII 0x60 as a grave accent, so some people like +% the code environments to do likewise. +% +\def\codequoteleft{% + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + `% + \else + \char'22 + \fi +} +% +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } + \catcode`\'=\active + \gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}% + % + \catcode`\`=\active + \gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}% + % + \gdef\quoteexpand{\rquoteexpand \lquoteexpand}% +\endgroup + +% start the verbatim environment. +\def\setupverbatim{% + \let\nonarrowing = t% + \nonfillstart + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + \quoteexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'#1'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. +\endgroup +% +\envdef\verbatim{% + \setupverbatim\doverbatim +} +\let\Everbatim = \afterenvbreak + + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} +% +\def\doverbatiminclude#1{% + {% + \makevalueexpandable + \setupverbatim + \input #1 + \afterenvbreak + }% +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\copyingtext + \endgroup +} + +\message{defuns,} +% @defun etc. + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt + +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak + \else + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \defargscommonending, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + \ifnum\lastpenalty=10002 \penalty2000 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint + \fi + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% + % + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% +} +\def\gobbledefun#1\startdefun{} + +% \printdefunline \deffnheader{text} +% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup +} + +\def\Edefun{\endgraf\medbreak} + +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remainnig is to define \deffnheader. +% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp +} + +% \domakedefun \deffn \deffnx \deffnheader +% +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. +% +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% +} + +%%% Untyped functions: + +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} + +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} + +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deffngeneral {subind}category name args +% +\def\deffngeneral#1#2 #3 #4\endheader{% + % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +} + +%%% Typed functions: + +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} + +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} + +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Typed variables: + +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} + +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} + +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } + +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Untyped variables: + +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } + +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} + +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } + +%%% Type: +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% +} + +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} + +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. +% +% We are followed by (but not passed) the arguments, if any. +% +\def\defname#1#2#3{% + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % How we'll format the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % (plain.tex says that \dimen1 should be used only as global.) + \parshape 2 0in \dimen0 \defargsindent \dimen2 + % + % Put the type name to the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% return value type + \ifx\temp\empty\else \tclose{\temp} \fi + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \tenrm + % + \boldbrax + % arguments will be output next, if any. +} + +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. +% +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. Let's try @var for that. + \let\var=\ttslanted + #1% + \sl\hyphenchar\font=45 +} + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& + + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} +} + +\newcount\parencount + +% If we encounter &foo, then turn on ()-hacking afterwards +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} + +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi +} +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi +} +\def\bfafterword#1 {#1 \bf} + +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword +} +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 +} + +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 +} + +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi +} +\def\badparencount{% + \errmessage{Unbalanced parentheses in @def}% + \global\parencount=0 +} +\def\badbrackcount{% + \errmessage{Unbalanced square braces in @def}% + \global\brackcount=0 +} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } +\fi + +\def\scanmacro#1{% + \begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % ... and \example + \spaceisspace + % + % Append \endinput to make sure that TeX does not see the ending newline. + % I've verified that it is necessary both for e-TeX and for ordinary TeX + % --kasal, 29nov03 + \scantokens{#1\endinput}% + \endgroup +} + +\def\scanexp#1{% + \edef\temp{\noexpand\scanmacro{#1}}% + \temp +} + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? + +% List of all defined macros in the form +% \definedummyword\macro1\definedummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\definedummyword#1}% + \xdef\macrolist{\the\toks0}% +} + +% Utility routines. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% +\def\cslet#1#2{% + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\scanctxt{% + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\@=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\~=\other +} + +\def\scanargctxt{% + \scanctxt + \catcode`\\=\other + \catcode`\^^M=\other +} + +\def\macrobodyctxt{% + \scanctxt + \catcode`\{=\other + \catcode`\}=\other + \catcode`\^^M=\other + \usembodybackslash +} + +\def\macroargctxt{% + \scanctxt + \catcode`\\=\other +} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + \addtomacrolist{\the\macname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\parseargdef\unmacro{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\definedummyword\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx #1\relax + % remove this + \else + \noexpand\definedummyword \noexpand#1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \macnamexxx} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\parseargusing\obeyspaces\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} + + +\message{cross references,} + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} + +\let\nwnode=\node +\let\lastnode=\empty + +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty + \fi +} + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \thissection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. +% +\def\setref#1#2{% + \pdfmkdest{#1}% + \iflinks + {% + \atdummies % preserve commands, but don't expand them + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\thissection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \writexrdef{pg}{\folio}% will be written later, during \shipout + }% + \fi +} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printedrefname{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual\unskip}% + \setbox0=\hbox{\printedrefname\unskip}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printedrefname{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printedrefname{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printedrefname{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printedrefname{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % Make link in pdf output. + \ifpdf + \leavevmode + \getfilename{#4}% + {\turnoffactive + % See comments at \activebackslashdouble. + {\activebackslashdouble \xdef\pdfxrefdest{#1}% + \backslashparens\pdfxrefdest}% + % + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{\pdfxrefdest}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{\pdfmkpgn{\pdfxrefdest}}% + \fi + }% + \linkcolor + \fi + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". We distinguish them by the + % LABEL-title being set to a magic string. + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd0 = 0pt + \refx{#1-snt}{}% + \else + \printedrefname + \fi + % + % if the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd1 > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via a macro so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi + \fi + \endlink +\endgroup} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since square brackets don't work well in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% Things referred to by \setref. +% +\def\Ynothing{} +\def\Yomitfromtoc{} +\def\Ynumbered{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +\def\Yappendix{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname XR#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. Usually it's +% just a \def (we prepend XR to the control sequence name to avoid +% collisions). But if this is a float type, we have more work to do. +% +\def\xrdef#1#2{% + \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR#1\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% + \fi +} + +% Read the last existing aux file, if any. No error if none exists. +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readdatafile{aux}% + \global\havexrefstrue + \fi + \closein 1 +} + +\def\setupdatafile{% + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % This is to support \ in node names and titles, since the \ + % characters end up in a \csname. It's easier than + % leaving it active and making its active definition an actual \ + % character. What I don't understand is why it works in the *value* + % of the xrdef. Seems like it should be a catcode12 \, and that + % should not typeset properly. But it works, so I'm moving on for + % now. --karl, 15jan04. + \catcode`\\=\other + % + % Make the characters 128-255 be printing characters. + {% + \count1=128 + \def\loop{% + \catcode\count1=\other + \advance\count1 by 1 + \ifnum \count1<256 \loop \fi + }% + }% + % + % @ is our escape character in .aux files, and we need braces. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 +\endgroup} + +\message{insertions,} +% including footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\gdef\dofootnote{% + \insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarily, if a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is finished. +% And the same can be done for other insert classes. --kasal, 16nov03. + +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi +} + +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. +% +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +\closein 1 +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \egroup \bigbreak \fi % space after the image +\endgroup} + + +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \thissection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\thissection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \atdummies + % + % since we read the caption text in the macro world, where ^^M + % is turned into a normal character, we have to scan it back, so + % we don't write the literal three characters "^^M" into the aux file. + \scanexp{% + \xdef\noexpand\gtemp{% + \ifx\thisshortcaption\empty + \thiscaption + \else + \thisshortcaption + \fi + }% + }% + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + % place the captured inserts + % + % BEWARE: when the floats start floating, we have to issue warning + % whenever an insert appears inside a float which could possibly + % float. --kasal, 26may04 + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \thissection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup + \fi +} + +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\parseargdef\documentlanguage{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \input txi-#1.tex + \fi + \closein 1 + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}% + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.25 trim size. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {\voffset}{.25in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .4cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{51\baselineskip}{160mm} + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1 + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +\let\realunder=_ +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} + +\catcode`\@=0 + +% \backslashcurfont outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\backslashcurfont=`\\ +\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work + +% \realbackslash is an actual character `\' with catcode other, and +% \doublebackslash is two of them (for the pdf outlines). +{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} + +% In texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active +@def@normalbackslash{{@tt@backslashcurfont}} +% On startup, @fixbackslash assigns: +% @let \ = @normalbackslash + +% \rawbackslash defines an active \ to do \backslashcurfont. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +@gdef@rawbackslash{@let\=@backslashcurfont} +@gdef@otherbackslash{@let\=@realbackslash} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. +% +@def@normalturnoffactive{% + @let\=@normalbackslash + @let"=@normaldoublequote + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix + @unsepspaces +} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\' in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also turn back on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: + +@c vim:sw=2: + +@ignore + arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 +@end ignore diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 0000000..cde5683 --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,4 @@ +@set UPDATED 22 January 2009 +@set UPDATED-MONTH January 2009 +@set EDITION 1.4.4 +@set VERSION 1.4.4 diff --git a/packaging/libgcrypt.spec b/packaging/libgcrypt.spec index 4881062..46f30fa 100644 --- a/packaging/libgcrypt.spec +++ b/packaging/libgcrypt.spec @@ -1,3 +1,4 @@ +#sbs-git:slp/unmodified/libgcrypt11 libgcrypt 1.4.4 a8637cda42f30ffa3200f43cc02b9bc607008661 Name: libgcrypt Version: 1.4.4 Release: 5 diff --git a/src/dumpsexp.c b/src/dumpsexp.c new file mode 100644 index 0000000..8f5c0d3 --- /dev/null +++ b/src/dumpsexp.c @@ -0,0 +1,613 @@ +/* dumpsexp.c - Dump S-expressions. + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * Getrandom is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * Getrandom is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PGM "dumpsexp" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to .\n" + + +static int verbose; /* Verbose mode. */ +static int decimal; /* Print addresses in decimal. */ +static int assume_hex; /* Assume input is hexencoded. */ + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2007 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] [file]\n" + "Debug tool for S-expressions\n" + "\n" + " --decimal Print offsets using decimal notation\n" + " --assume-hex Assume input is a hex dump\n" + " --verbose Show what we are doing\n" + " --version Print version of the program and exit\n" + " --help Display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') +#define digit_p(a) ((a) >= '0' && (a) <= '9') +#define octdigit_p(a) ((a) >= '0' && (a) <= '7') +#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \ + || ((a) >= 'a' && (a) <= 'z')) +#define hexdigit_p(a) (digit_p (a) \ + || ((a) >= 'A' && (a) <= 'F') \ + || ((a) >= 'a' && (a) <= 'f')) +#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \ + (a) <= 'F'? ((a)-'A'+10):((a)-'a'+10)) + + +/* Return true if P points to a byte containing a whitespace according + to the S-expressions definition. */ +static inline int +whitespace_p (int c) +{ + switch (c) + { + case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; + default: return 0; + } +} + +static void +logit (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + va_end (arg_ptr); +} + +/* The raw data buffer and its current length */ +static unsigned char databuffer[16]; +static int databufferlen; +/* The number of bytes in databuffer which should be skipped at a flush. */ +static int skipdatabufferlen; +/* The number of raw bytes printed on the last line. */ +static int nbytesprinted; +/* The file offset of the current data buffer . */ +static unsigned long databufferoffset; + + + +static int +my_getc (FILE *fp) +{ + int c1, c2; + + if (!assume_hex) + return getc (fp); + + while ( (c1=getc (fp)) != EOF && space_p (c1) ) + ; + if (c1 == EOF) + return EOF; + + if (!hexdigit_p (c1)) + { + logit ("non hex-digit encountered\n"); + return EOF; + } + + while ( (c2=getc (fp)) != EOF && space_p (c2) ) + ; + if (c2 == EOF) + { + logit ("error reading second hex nibble\n"); + return EOF; + } + if (!hexdigit_p (c2)) + { + logit ("second hex nibble is not a hex-digit\n"); + return EOF; + } + return xtoi_1 (c1) * 16 + xtoi_1 (c2); +} + + + + + +/* Flush the raw data buffer. */ +static void +flushdatabuffer (void) +{ + int i; + + if (!databufferlen) + return; + nbytesprinted = 0; + if (decimal) + printf ("%08lu ", databufferoffset); + else + printf ("%08lx ", databufferoffset); + for (i=0; i < databufferlen; i++) + { + if (i == 8) + putchar (' '); + if (i < skipdatabufferlen) + fputs (" ", stdout); + else + { + printf (" %02x", databuffer[i]); + databufferoffset++; + } + nbytesprinted++; + } + for (; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + fputs (" ", stdout); + } + fputs (" |", stdout); + for (i=0; i < databufferlen; i++) + { + if (i < skipdatabufferlen) + putchar (' '); + else if (databuffer[i] >= ' ' && databuffer[i] <= '~' + && databuffer[i] != '|') + putchar (databuffer[i]); + else + putchar ('.'); + } + putchar ('|'); + putchar ('\n'); + databufferlen = 0; + skipdatabufferlen = 0; +} + + +/* Add C to the raw data buffer and flush as needed. */ +static void +addrawdata (int c) +{ + if ( databufferlen >= sizeof databuffer ) + flushdatabuffer (); + databuffer[databufferlen++] = c; +} + + +static void +printcursor (int both) +{ + int i; + + flushdatabuffer (); + printf ("%8s ", ""); + for (i=0; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + if (i+1 == nbytesprinted) + { + fputs (" ^ ", stdout); + if (!both) + break; + } + else + fputs (" ", stdout); + } + if (both) + { + fputs (" ", stdout); + for (i=0; i < nbytesprinted-1; i++) + putchar (' '); + putchar ('^'); + } + databufferlen = skipdatabufferlen = nbytesprinted; +} + +static void +printerr (const char *text) +{ + printcursor (1); + printf ("\n Error: %s\n", text); +} + +static void +printctl (const char *text) +{ + if (verbose) + { + printcursor (0); + printf ("%s\n", text); + } +} + +static void +printchr (int c) +{ + (void)c; +} + +static void +printhex (int c) +{ + (void)c; +} + + + + + + +static int +parse_and_print (FILE *fp) +{ + static const char tokenchars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-./_:*+="; + int c; + int level = 0; + int tokenc = 0; + int hexcount = 0; + int disphint = 0; + unsigned long datalen = 0; + char quote_buf[10]; + int quote_idx = 0; + enum + { + INIT_STATE = 0, IN_NUMBER, PRE_DATA, IN_DATA, IN_STRING, + IN_ESCAPE, IN_OCT_ESC, IN_HEX_ESC, + CR_ESC, LF_ESC, IN_HEXFMT, IN_BASE64 + } + state = INIT_STATE; + + + while ((c = my_getc (fp)) != EOF ) + { + addrawdata (c); + switch (state) + { + case INIT_STATE: + if (tokenc) + { + if (strchr (tokenchars, c)) + { + printchr (c); + continue; + } + tokenc = 0; + } + parse_init_state: + if (c == '(') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("open"); + level++; + } + else if (c == ')') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("close"); + level--; + } + else if (c == '\"') + { + state = IN_STRING; + printctl ("beginstring"); + } + else if (c == '#') + { + state = IN_HEXFMT; + hexcount = 0; + printctl ("beginhex"); + } + else if (c == '|') + { + state = IN_BASE64; + printctl ("beginbase64"); + } + else if (c == '[') + { + if (disphint) + printerr ("nested display hint"); + disphint = c; + } + else if (c == ']') + { + if (!disphint) + printerr ("no open display hint"); + disphint = 0; + } + else if (c >= '0' && c <= '9') + { + if (c == '0') + printerr ("zero prefixed length"); + state = IN_NUMBER; + datalen = (c - '0'); + } + else if (strchr (tokenchars, c)) + { + printchr (c); + tokenc = c; + } + else if (whitespace_p (c)) + ; + else if (c == '{') + { + printerr ("rescanning is not supported"); + } + else if (c == '&' || c == '\\') + { + printerr ("reserved punctuation detected"); + } + else + { + printerr ("bad character detected"); + } + break; + + case IN_NUMBER: + if (digit_p (c)) + { + unsigned long tmp = datalen * 10 + (c - '0'); + if (tmp < datalen) + { + printerr ("overflow in data length"); + state = INIT_STATE; + datalen = 0; + } + else + datalen = tmp; + } + else if (c == ':') + { + if (!datalen) + { + printerr ("no data length"); + state = INIT_STATE; + } + else + state = PRE_DATA; + } + else if (c == '\"' || c == '#' || c == '|' ) + { + /* We ignore the optional length and divert to the init + state parser code. */ + goto parse_init_state; + } + else + printerr ("invalid length specification"); + break; + + case PRE_DATA: + state = IN_DATA; + printctl ("begindata"); + case IN_DATA: + if (datalen) + { + printhex (c); + datalen--; + } + if (!datalen) + { + state = INIT_STATE; + printctl ("enddata"); + } + break; + + case IN_STRING: + if (c == '\"') + { + printctl ("endstring"); + state = INIT_STATE; + } + else if (c == '\\') + state = IN_ESCAPE; + else + printchr (c); + break; + + case IN_ESCAPE: + switch (c) + { + case 'b': case 't': case 'v': case 'n': case 'f': + case 'r': case '"': case '\'': case '\\': + printhex (c); + state = IN_STRING; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + state = IN_OCT_ESC; + quote_idx = 0; + quote_buf[quote_idx++] = c; + break; + + case 'x': + state = IN_HEX_ESC; + quote_idx = 0; + break; + + case '\r': + state = CR_ESC; + break; + + case '\n': + state = LF_ESC; + break; + + default: + printerr ("invalid escape sequence"); + state = IN_STRING; + break; + } + + case IN_OCT_ESC: + state = IN_STRING; + break; + case IN_HEX_ESC: + state = IN_STRING; + break; + case CR_ESC: + state = IN_STRING; + break; + case LF_ESC: + state = IN_STRING; + break; + + case IN_HEXFMT: + if (hexdigit_p (c)) + { + printchr (c); + hexcount++; + } + else if (c == '#') + { + if ((hexcount & 1)) + printerr ("odd number of hex digits"); + printctl ("endhex"); + state = INIT_STATE; + } + else if (!whitespace_p (c)) + printerr ("bad hex character"); + break; + + case IN_BASE64: + if (c == '|') + { + printctl ("endbase64"); + state = INIT_STATE; + } + else + printchr (c); + break; + + default: + logit ("invalid state %d detected", state); + exit (1); + } + } + flushdatabuffer (); + if (ferror (fp)) + { + logit ("error reading input: %s\n", strerror (errno)); + return -1; + } + return 0; +} + + + +int +main (int argc, char **argv) +{ + int rc; + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--verbose")) + { + argc--; argv++; + verbose = 1; + } + else if (!strcmp (*argv, "--decimal")) + { + argc--; argv++; + decimal = 1; + } + else if (!strcmp (*argv, "--assume-hex")) + { + argc--; argv++; + assume_hex = 1; + } + else + print_usage (); + } + + if (!argc) + { + rc = parse_and_print (stdin); + } + else + { + for (; argc; argc--) + { + FILE *fp = fopen (*argv, "rb"); + if (!fp) + { + logit ("can't open `%s': %s\n", *argv, strerror (errno)); + rc = 1; + } + else + { + if ( parse_and_print (fp) ) + rc = 1; + fclose (fp); + } + } + } + + + return !rc; +} + diff --git a/src/gcryptrnd.c b/src/gcryptrnd.c new file mode 100644 index 0000000..e15feca --- /dev/null +++ b/src/gcryptrnd.c @@ -0,0 +1,681 @@ +/* gcryptrnd.c - Libgcrypt Random Number Daemon + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * Gcryptend is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * Gcryptrnd is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* We require vsyslog pth + We need to test for: setrlimit + + We should also prioritize requests. This is best done by putting + the requests into queues and have a main thread processing these + queues. + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PGM "gcryptrnd" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to .\n" + +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; + + +/* Flag set to true if we have been daemonized. */ +static int running_detached; +/* Flag indicating that a shutdown has been requested. */ +static int shutdown_pending; +/* Counter for active connections. */ +static int active_connections; + + + +/* Local prototypes. */ +static void serve (int listen_fd); + + + + + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + + +/* Error printing utility. PRIORITY should be one of syslog's + priority levels. This fucntions prints to the stderro or syslog + depending on whether we are already daemonized. */ +static void +logit (int priority, const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + if (running_detached) + { + vsyslog (priority, format, arg_ptr); + } + else + { + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + } + va_end (arg_ptr); +} + +/* Callback used by libgcrypt for logging. */ +static void +my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) +{ + (void)dummy; + + /* Map the log levels. */ + switch (level) + { + case GCRY_LOG_CONT: level = LOG_INFO /* FIXME */; break; + case GCRY_LOG_INFO: level = LOG_INFO; break; + case GCRY_LOG_WARN: level = LOG_WARNING; break; + case GCRY_LOG_ERROR:level = LOG_ERR; break; + case GCRY_LOG_FATAL:level = LOG_CRIT; break; + case GCRY_LOG_BUG: level = LOG_CRIT; break; + case GCRY_LOG_DEBUG:level = LOG_DEBUG; break; + default: level = LOG_ERR; break; + } + if (running_detached) + { + vsyslog (level, format, arg_ptr); + } + else + { + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + if (!*format || format[strlen (format)-1] != '\n') + putc ('\n', stderr); + } +} + + +/* The cleanup handler - used to wipe out the secure memory. */ +static void +cleanup (void) +{ + gcry_control (GCRYCTL_TERM_SECMEM ); +} + + +/* Make us a daemon and open the syslog. */ +static void +daemonize (void) +{ + int i; + pid_t pid; + + fflush (NULL); + + pid = fork (); + if (pid == (pid_t)-1) + { + logit (LOG_CRIT, "fork failed: %s", strerror (errno)); + exit (1); + } + if (pid) + exit (0); + + if (setsid() == -1) + { + logit (LOG_CRIT, "setsid() failed: %s", strerror(errno)); + exit (1); + } + + signal (SIGHUP, SIG_IGN); + + pid = fork (); + if (pid == (pid_t)-1) + { + logit (LOG_CRIT, PGM ": second fork failed: %s", strerror (errno)); + exit (1); + } + if (pid) + exit (0); /* First child exits. */ + + running_detached = 1; + + if (chdir("/")) + { + logit (LOG_CRIT, "chdir(\"/\") failed: %s", strerror (errno)); + exit (1); + } + umask (0); + + for (i=0; i <= 2; i++) + close (i); + + openlog (PGM, LOG_PID, LOG_DAEMON); +} + + +static void +disable_core_dumps (void) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit limit; + + if (getrlimit (RLIMIT_CORE, &limit)) + limit.rlim_max = 0; + limit.rlim_cur = 0; + if( !setrlimit (RLIMIT_CORE, &limit) ) + return 0; + if (errno != EINVAL && errno != ENOSYS) + logit (LOG_ERR, "can't disable core dumps: %s\n", strerror (errno)); +#endif /* HAVE_SETRLIMIT */ +} + + + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2006 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] [SOCKETNAME]\n" + "Start Libgcrypt's random number daemon listening" + " on socket SOCKETNAME\n" + "SOCKETNAME defaults to XXX\n" + "\n" + " --no-detach do not deatach from the console\n" + " --version print version of the program and exit\n" + " --help display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] [SOCKETNAME]\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +int +main (int argc, char **argv) +{ + int no_detach = 0; + gpg_error_t err; + struct sockaddr_un *srvr_addr; + socklen_t addrlen; + int fd; + int rc; + const char *socketname = "/var/run/libgcrypt/S.gcryptrnd"; + + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--no-detach")) + { + no_detach = 1; + argc--; argv++; + } + else + print_usage (); + } + + if (argc == 1) + socketname = argv[0]; + else if (argc > 1) + print_usage (); + + if (!no_detach) + daemonize (); + + signal (SIGPIPE, SIG_IGN); + + logit (LOG_NOTICE, "started version " VERSION ); + + /* Libgcrypt requires us to register the threading model before we + do anything else with it. Note that this also calls pth_init. We + do the initialization while already running as a daemon to avoid + overhead with double initialization of Libgcrypt. */ + err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + if (err) + { + logit (LOG_CRIT, "can't register GNU Pth with Libgcrypt: %s", + gpg_strerror (err)); + exit (1); + } + + /* Check that the libgcrypt version is sufficient. */ + if (!gcry_check_version (VERSION) ) + { + logit (LOG_CRIT, "libgcrypt is too old (need %s, have %s)", + VERSION, gcry_check_version (NULL) ); + exit (1); + } + + /* Register the logging callback and tell Libcgrypt to put the + random pool into secure memory. */ + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + /* Obviously we don't want to allow any core dumps. */ + disable_core_dumps (); + + /* Initialize the secure memory stuff which will also drop any extra + privileges we have. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + /* Register a cleanup handler. */ + atexit (cleanup); + + /* Create and listen on the socket. */ + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + logit (LOG_CRIT, "can't create socket: %s", strerror (errno)); + exit (1); + } + srvr_addr = gcry_xmalloc (sizeof *srvr_addr); + memset (srvr_addr, 0, sizeof *srvr_addr); + srvr_addr->sun_family = AF_UNIX; + if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path)) + { + logit (LOG_CRIT, "socket name `%s' too long", socketname); + exit (1); + } + strcpy (srvr_addr->sun_path, socketname); + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr->sun_path) + 1); + rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen); + if (rc == -1 && errno == EADDRINUSE) + { + remove (socketname); + rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen); + } + if (rc == -1) + { + logit (LOG_CRIT, "error binding socket to `%s': %s", + srvr_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + logit (LOG_CRIT, "listen() failed: %s", strerror (errno)); + close (fd); + exit (1); + } + + logit (LOG_INFO, "listening on socket `%s', fd=%d", + srvr_addr->sun_path, fd); + + serve (fd); + close (fd); + + logit (LOG_NOTICE, "stopped version " VERSION ); + return 0; +} + + +/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on + success or another value on write error. */ +static int +writen (int fd, const void *buffer, size_t length) +{ + while (length) + { + ssize_t n = pth_write (fd, buffer, length); + if (n < 0) + { + logit (LOG_ERR, "connection %d: write error: %s", + fd, strerror (errno)); + return -1; /* write error */ + } + length -= n; + buffer = (const char*)buffer + n; + } + return 0; /* Okay */ +} + + +/* Send an error response back. Returns 0 on success. */ +static int +send_error (int fd, int errcode) +{ + unsigned char buf[2]; + + buf[0] = errcode; + buf[1] = 0; + return writen (fd, buf, 2 ); +} + +/* Send a pong response back. Returns 0 on success or another value + on write error. */ +static int +send_pong (int fd) +{ + return writen (fd, "\x00\x04pong", 6); +} + +/* Send a nonce of size LENGTH back. Return 0 on success. */ +static int +send_nonce (int fd, int length) +{ + unsigned char buf[2+255]; + int rc; + + assert (length >= 0 && length <= 255); + buf[0] = 0; + buf[1] = length; + gcry_create_nonce (buf+2, length); + rc = writen (fd, buf, 2+length ); + wipememory (buf+2, length); + return rc; +} + +/* Send a random of size LENGTH with quality LEVEL back. Return 0 on + success. */ +static int +send_random (int fd, int length, int level) +{ + unsigned char buf[2+255]; + int rc; + + assert (length >= 0 && length <= 255); + assert (level == GCRY_STRONG_RANDOM || level == GCRY_VERY_STRONG_RANDOM); + buf[0] = 0; + buf[1] = length; + /* Note that we don't bother putting the random stuff into secure + memory because this daemon is anyway intended to be run under + root and it is questionable whether the kernel buffers etc. are + equally well protected. */ + gcry_randomize (buf+2, length, level); + rc = writen (fd, buf, 2+length ); + wipememory (buf+2, length); + return rc; +} + +/* Main processing loop for a connection. + + A request is made up of: + + 1 byte Total length of request; must be 3 + 1 byte Command + 0 = Ping + 10 = GetNonce + 11 = GetStrongRandom + 12 = GetVeryStrongRandom + (all other values are reserved) + 1 byte Number of requested bytes. + This is ignored for command Ping. + + A response is made up of: + + 1 byte Error Code + 0 = Everything is fine + 1 = Bad Command + 0xff = Other error. + (For a bad request the connection will simply be closed) + 1 byte Length of data + n byte data + + The requests are read as long as the connection is open. + + + */ +static void +connection_loop (int fd) +{ + unsigned char request[3]; + unsigned char *p; + int nleft, n; + int rc; + + for (;;) + { + for (nleft=3, p=request; nleft > 0; ) + { + n = pth_read (fd, p, nleft); + if (!n && p == request) + return; /* Client terminated connection. */ + if (n <= 0) + { + logit (LOG_ERR, "connection %d: read error: %s", + fd, n? strerror (errno) : "Unexpected EOF"); + return; + } + p += n; + nleft -= n; + } + if (request[0] != 3) + { + logit (LOG_ERR, "connection %d: invalid length (%d) of request", + fd, request[0]); + return; + } + + switch (request[1]) + { + case 0: /* Ping */ + rc = send_pong (fd); + break; + case 10: /* GetNonce */ + rc = send_nonce (fd, request[2]); + break; + case 11: /* GetStrongRandom */ + rc = send_random (fd, request[2], GCRY_STRONG_RANDOM); + break; + case 12: /* GetVeryStrongRandom */ + rc = send_random (fd, request[2], GCRY_VERY_STRONG_RANDOM); + break; + + default: /* Invalid command */ + rc = send_error (fd, 1); + break; + } + if (rc) + break; /* A write error occured while sending the response. */ + } +} + + + +/* Entry point for a connection's thread. */ +static void * +connection_thread (void *arg) +{ + int fd = (int)arg; + + active_connections++; + logit (LOG_INFO, "connection handler for fd %d started", fd); + + connection_loop (fd); + + close (fd); + logit (LOG_INFO, "connection handler for fd %d terminated", fd); + active_connections--; + + return NULL; +} + + +/* This signal handler is called from the main loop between acepting + connections. It is called on the regular stack, thus no special + caution needs to be taken. It returns true to indicate that the + process should terminate. */ +static int +handle_signal (int signo) +{ + switch (signo) + { + case SIGHUP: + logit (LOG_NOTICE, "SIGHUP received - re-reading configuration"); + break; + + case SIGUSR1: + logit (LOG_NOTICE, "SIGUSR1 received - no action defined"); + break; + + case SIGUSR2: + logit (LOG_NOTICE, "SIGUSR2 received - no action defined"); + break; + + case SIGTERM: + if (!shutdown_pending) + logit (LOG_NOTICE, "SIGTERM received - shutting down ..."); + else + logit (LOG_NOTICE, "SIGTERM received - still %d active connections", + active_connections); + shutdown_pending++; + if (shutdown_pending > 2) + { + logit (LOG_NOTICE, "shutdown forced"); + return 1; + } + break; + + case SIGINT: + logit (LOG_NOTICE, "SIGINT received - immediate shutdown"); + return 1; + + default: + logit (LOG_NOTICE, "signal %d received - no action defined\n", signo); + } + return 0; +} + + + +/* Main server loop. This is called with the FD of the listening + socket. */ +static void +serve (int listen_fd) +{ + pth_attr_t tattr; + pth_event_t ev; + sigset_t sigs; + int signo; + struct sockaddr_un paddr; + socklen_t plen = sizeof (paddr); + int fd; + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "connection"); + + sigemptyset (&sigs); + sigaddset (&sigs, SIGHUP); + sigaddset (&sigs, SIGUSR1); + sigaddset (&sigs, SIGUSR2); + sigaddset (&sigs, SIGINT); + sigaddset (&sigs, SIGTERM); + ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + + for (;;) + { + if (shutdown_pending) + { + if (!active_connections) + break; /* Ready. */ + + /* Do not accept anymore connections but wait for existing + connections to terminate. */ + signo = 0; + pth_wait (ev); + if (pth_event_occurred (ev) && signo) + if (handle_signal (signo)) + break; /* Stop the loop. */ + continue; + } + + gcry_fast_random_poll (); + fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { + if (pth_event_occurred (ev)) + { + if (handle_signal (signo)) + break; /* Stop the loop. */ + continue; + } + logit (LOG_WARNING, "accept failed: %s - waiting 1s\n", + strerror (errno)); + gcry_fast_random_poll (); + pth_sleep (1); + continue; + } + + if (!pth_spawn (tattr, connection_thread, (void*)fd)) + { + logit (LOG_ERR, "error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } + + pth_event_free (ev, PTH_FREE_ALL); +} + diff --git a/src/getrandom.c b/src/getrandom.c new file mode 100644 index 0000000..f4c9b4b --- /dev/null +++ b/src/getrandom.c @@ -0,0 +1,327 @@ +/* getrandom.c - Libgcrypt Random Number client + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * Getrandom is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * Getrandom is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PGM "getrandom" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to .\n" + + +static void +logit (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + va_end (arg_ptr); +} + + +/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on + success or another value on write error. */ +static int +writen (int fd, const void *buffer, size_t length) +{ + while (length) + { + ssize_t n; + + do + n = write (fd, buffer, length); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("write error: %s", strerror (errno)); + return -1; /* write error */ + } + length -= n; + buffer = (const char *)buffer + n; + } + return 0; /* Okay */ +} + + + + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2006 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] NBYTES\n" + "Connect to libgcrypt's random number daemon and " + "return random numbers" + "\n" + " --nonce Return weak random suitable for a nonce\n" + " --very-strong Return very strong random\n" + " --ping Send a ping\n" + " --socket NAME Name of sockket to connect to\n" + " --hex Return result as a hex dump\n" + " --verbose Show what we are doing\n" + " --version Print version of the program and exit\n" + " --help Display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +int +main (int argc, char **argv) +{ + struct sockaddr_un *srvr_addr; + socklen_t addrlen; + int fd; + int rc; + unsigned char buffer[300]; + int nleft, nread; + const char *socketname = "/var/run/libgcrypt/S.gcryptrnd"; + int do_ping = 0; + int get_nonce = 0; + int get_very_strong = 0; + int req_nbytes, nbytes, n; + int verbose = 0; + int fail = 0; + int do_hex = 0; + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--socket") && argc > 1 ) + { + argc--; argv++; + socketname = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--nonce")) + { + argc--; argv++; + get_nonce = 1; + } + else if (!strcmp (*argv, "--very-strong")) + { + argc--; argv++; + get_very_strong = 1; + } + else if (!strcmp (*argv, "--ping")) + { + argc--; argv++; + do_ping = 1; + } + else if (!strcmp (*argv, "--hex")) + { + argc--; argv++; + do_hex = 1; + } + else if (!strcmp (*argv, "--verbose")) + { + argc--; argv++; + verbose = 1; + } + else + print_usage (); + } + + + if (!argc && do_ping) + ; /* This is allowed. */ + else if (argc != 1) + print_usage (); + req_nbytes = argc? atoi (*argv) : 0; + + if (req_nbytes < 0) + print_usage (); + + /* Create a socket. */ + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + logit ("can't create socket: %s", strerror (errno)); + exit (1); + } + srvr_addr = malloc (sizeof *srvr_addr); + if (!srvr_addr) + { + logit ("malloc failed: %s", strerror (errno)); + exit (1); + } + memset (srvr_addr, 0, sizeof *srvr_addr); + srvr_addr->sun_family = AF_UNIX; + if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path)) + { + logit ("socket name `%s' too long", socketname); + exit (1); + } + strcpy (srvr_addr->sun_path, socketname); + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr->sun_path) + 1); + rc = connect (fd, (struct sockaddr*) srvr_addr, addrlen); + if (rc == -1) + { + logit ("error connecting socket `%s': %s", + srvr_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + do + { + nbytes = req_nbytes > 255? 255 : req_nbytes; + req_nbytes -= nbytes; + + buffer[0] = 3; + if (do_ping) + buffer[1] = 0; + else if (get_nonce) + buffer[1] = 10; + else if (get_very_strong) + buffer[1] = 12; + else + buffer[1] = 11; + buffer[2] = nbytes; + if (writen (fd, buffer, 3)) + fail = 1; + else + { + for (nleft=2, nread=0; nleft > 0; ) + { + do + n = read (fd, buffer+nread, nleft); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("read error: %s", strerror (errno)); + exit (1); + } + nleft -= n; + nread += n; + if (nread && buffer[0]) + { + logit ("server returned error code %d", buffer[0]); + exit (1); + } + } + if (verbose) + logit ("received response with %d bytes of data", buffer[1]); + if (buffer[1] < nbytes) + { + logit ("warning: server returned less bytes than requested"); + fail = 1; + } + else if (buffer[1] > nbytes && !do_ping) + { + logit ("warning: server returned more bytes than requested"); + fail = 1; + } + nbytes = buffer[1]; + if (nbytes > sizeof buffer) + { + logit ("buffer too short to receive data"); + exit (1); + } + + for (nleft=nbytes, nread=0; nleft > 0; ) + { + do + n = read (fd, buffer+nread, nleft); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("read error: %s", strerror (errno)); + exit (1); + } + nleft -= n; + nread += n; + } + + if (do_hex) + { + for (n=0; n < nbytes; n++) + { + if (!n) + ; + else if (!(n % 16)) + putchar ('\n'); + else + putchar (' '); + printf ("%02X", buffer[n]); + } + if (nbytes) + putchar ('\n'); + } + else + { + if (fwrite (buffer, nbytes, 1, stdout) != 1) + { + logit ("error writing to stdout: %s", strerror (errno)); + fail = 1; + } + } + } + } + while (!fail && req_nbytes); + + close (fd); + free (srvr_addr); + return fail? 1 : 0; +} + diff --git a/tests/ChangeLog b/tests/ChangeLog new file mode 100644 index 0000000..8122d23 --- /dev/null +++ b/tests/ChangeLog @@ -0,0 +1,757 @@ +2009-01-22 Werner Koch + + * cavs_tests.sh: Pass option -D to driver if required. + + * fipsdrv.c (run_dsa_sign): Use hash of the data. + (dsa_gen_with_seed): New. + (run_dsa_pqg_gen): Add args SEED and SEEDLEN and use them. + (main): Optically take a seed for dsa-pgq-gen. + (standalone_mode): New. + (main): Add option --standalone. + (print_dsa_domain_parameters): Implement standalone mode. + +2009-01-21 Werner Koch + + * fipsdrv.c (run_dsa_verify): Use gcry_mpi_scan again. + (run_rsa_derive): Also print N. + + * fipsdrv.c (run_dsa_verify): Use hash of the data. + + * pubkey.c (get_dsa_key_fips186_with_seed_new): New. + (check_run): Call it. + +2008-12-11 Werner Koch + + * fipsdrv.c (run_rsa_derive): New. + (main): Add mode rsa-derive. + +2008-12-10 Werner Koch + + * basic.c (main): Check for error after running self-test in + non-fips mode. + + * pubkey.c (get_dsa_key_with_domain_new): New. + (get_dsa_key_fips186_with_domain_new): New. + (check_run): Call them. + +2008-12-08 Werner Koch + + * fipsdrv.c [W32]: Include fcntl.h. + +2008-12-05 Werner Koch + + * pubkey.c (get_dsa_key_new): Add arg transient_key. + (check_run): Use it. + +2008-12-03 Werner Koch + + * fipsdrv.c (run_dsa_pqg_gen): Facor code out into .. + (print_dsa_domain_parameters, dsa_gen): .. these two new functions. + (print_sexp, read_sexp_from_file): New. + (run_dsa_sign): New. + (run_dsa_verify): New. + +2008-12-02 Werner Koch + + * fipsdrv.c: All standalone build. + + * mpitests.c (mpi_powm): New. + +2008-11-28 Werner Koch + + * fips186-dsa.c: New. + + * fipsdrv.c (print_mpi_line, print_data_line): New. + (run_dsa_pqg_gen): New. + (usage): Add mode dsa-pqg-gen. + +2008-11-25 Werner Koch + + * pubkey.c (get_dsa_key_new): New. + +2008-11-24 Werner Koch + + * tsexp.c (basic): Add test for format character S. + + * pubkey.c (check_x931_derived_key): New. + (get_keys_x931_new): New. + (check_run): Check X9.31 generated RSA key. + +2008-11-07 Werner Koch + + * fipsdrv.c (run_cipher_mct_loop, get_current_iv): New. + (read_textline, read_hexline, skip_to_empty_line): New. + (main): New option --mct-server. + * cavs_driver.pl: Update from upstream and adjust to new fipsdrv. + +2008-11-05 Werner Koch + + * fipsdrv.c (run_encrypt_decrypt): Disable weak key detection. + +2008-10-31 Werner Koch + + * fipsdrv.c (run_rsa_sign): Buffer needs to be larger for SHA512. + +2008-10-27 Werner Koch + + * fipsdrv.c (run_encrypt_decrypt): Make IV_BUFFER optional. + (main): Ditto. + * cavs_driver.pl: Remove the --no-fips flags. + (libgcrypt_encdec($$$$$)): Make IV optional. + (libgcrypt_state_cipher($$$$$)): Ditto. + +2008-10-24 Werner Koch + + * benchmark.c (md_bench): Do not test MD5 in fips mode. + * basic.c (check_digests, check_hmac): Ditto. + +2008-10-06 Werner Koch + + * cavs_driver.pl: New version from upstream. + (libgcrypt_rsa_verify($$$$)): Pass pkcs1. + (libgcrypt_rsa_sign($$$)): Pass pkcs1 and hash algo. + + * fipsdrv.c (run_rsa_sign): Hash data in pkcs1 mode. + (run_rsa_verify): Ditto. + (read_key_file): Rename to read_private_key_file. Factor public + key code out to.. + (read_public_key_file): .. new. + +2008-10-02 Werner Koch + + * fipsdrv.c (print_buffer): Add base64 printing code. + (base64_decode, read_key_file, parse_tag, read_sig_file): New. + (run_rsa_gen, run_rsa_sign): New. + (main): Add modes rsa-gen, rsa-sign and rsa-verify. + + +2008-09-29 Werner Koch + + * fipsdrv.c: Merge code from fipsrngdrv.c + * fipsrngdrv.c: Remove. + +2008-09-26 Werner Koch + + * Makefile.am: Distribute cavs_driver.pl. + * cavs_tests.sh: New. + * fipsdrv.c: New. + +2008-09-18 Werner Koch + + * benchmark.c (main): Do not disable secure memory in FIPS mode. + +2008-09-18 Werner Koch + + * basic.c (main): Do not disable secure memory in FIPS mode. + +2008-09-16 Werner Koch + + * fipsrngdrv.c (main): Bail out on write error. Implement verbose + option. + (main): Use flag to disable dup block checks. + +2008-09-15 Werner Koch + + * fipsrngdrv.c: New. + +2008-09-09 Werner Koch + + * basic.c (main): New option --selftest. + +2008-08-29 Werner Koch + + * keygrip.c: Update to also check ECDSA. + +2008-08-28 Werner Koch + + * rsa-16k.key: New sample key. + +2008-08-27 Werner Koch + + * pkbench.c (read_file): New. + (process_key_pair_file): Replace mmap by read_file. + (main): Add a --fips option. + * Makefile.am (EXTRA_DIST): Remove. + (EXTRA_PROGRAMS): Add pkbench. + + * basic.c (main): Extended FIPS self-test test. + +2008-08-26 Werner Koch + + * basic.c (get_keys_new): Use transient-key flag. + * benchmark.c (main): First check options then do the libgcrypt + initialization. + (rsa_bench): Use transient-key flag if not in fips mode. + +2008-08-20 Werner Koch + + * t-mpi-bit.c (test_lshift): New. + (mpi2bitstr_nlz, lshiftbitstring): New. + (main): Run test. + +2008-08-18 Werner Koch + + * basic.c (main): Add option --fips. + +2008-08-15 Werner Koch + + * register.c (main): Check for fips mode. + (check_run): Take care of fips mode. + + * basic.c (check_cbc_mac_cipher, check_ciphers, check_digests) + (check_hmac, check_pubkey): Do not test unavalaible algorithms in + fips mode. + (main): Check for fips mode. + +2008-04-22 Werner Koch + + * basic.c (check_one_cipher): Also check in-place encryption. + +2008-03-17 Werner Koch + + * benchmark.c (main): Add option --cipher-repetition. + (cipher_bench): Use it. + +2008-03-12 Werner Koch + + * benchmark.c (rsa_bench): Add arg NO_BLINDING. + (main): Add option --no-blinding. + +2007-12-05 Werner Koch + + * pubkey.c (sample_private_key_1_1,sample_private_key_1_2): New. + (get_keys_sample): Add arg SECRET_VARIANT. + (check_run): Check all variants. Also check gcry_pk_testkey. + (check_keys_crypt): Add DECRYPT_FAIL_CODE. + (check_keys): Ditto. + +2007-11-30 Werner Koch + + * benchmark.c (main): Add optione --verbose and reworked the + option parsing. + (random_bench): Dump random stats. + +2007-10-31 Werner Koch + + * benchmark.c (start_timer, stop_timer, elapsed_time) [W32]: Fixed. + +2007-06-20 Werner Koch + + * benchmark.c (rsa_bench): New. + (main): New command "rsa". + +2007-05-03 Werner Koch + + * Makefile.am (EXTRA_DIST): Do not build pkbench.c + +2007-05-02 David Shaw + + * basic.c (check_ciphers): Add Camellia. + +2007-04-30 David Shaw + + * basic.c (check_ciphers): #if out ciphers we don't have. Add + test for GCRY_CIPHER_RFC2268_40. + +2007-04-30 Werner Koch + + * version.c: New. + * Makefile.am (TESTS): Add version. + +2007-04-30 Marcus Brinkmann + + * benchmark.c (ecc_bench): Release KEY_SPEC. + +2007-04-28 Marcus Brinkmann + + * ac-data.c (check_run): Don't give redundant GCRY_AC_FLAG_DEALLOC + in addition to GCRY_AC_FLAG_COPY. Don't release LABEL1 or MPI0, + as those are donated to libgcrypt, but do release MPI0 and MPI2. + +2007-04-12 Marcus Brinkmann + + * ac-schemes.c (scheme_spec): Revert last change. + + * ac-schemes.c (scheme_spec): Remove const qualifier from member M. + (es_check): Remove const qualifier from C and M2. + +2007-03-28 Werner Koch + + * pkbench.c (generate_key): Support named curves. + + * benchmark.c (dsa_bench): New args ITERATIONS and PRINT_HEADER. + (main): Call dsa and ecc benchs. + (show_sexp): New. + + * Makefile.am (TESTS): Move pkbench to EXTRA_PROGRAMS. + +2007-03-22 Werner Koch + + * benchmark.c (die): New. + (ecc_bench): New. + + * pkbench.c (main): Reworked to provide proper option handling. + +2007-03-13 Werner Koch + + * mpitests.c: Reformatted to GNU standards. + (main): Add options --verbose and --debug for future use. + +2007-03-13 Werner Dittmann (wk) + + * mpitests.c: New. + +2007-02-23 Werner Koch + + * Makefile.am (TEST): Run benchmark as last. + + * ac-data.c (check_sexp_conversion): Print label only in verbose + mode. + + * pubkey.c (main): Run test just 2 times instead of 10. + (get_elg_key_new): New. + (check_run): Also run tests with Elgamal keys. + (check_keys): New arg NBITS_DATA. + (get_elg_key_new): Use only 400 for the 512 bit Elgamal test. + + * random.c: New. + +2007-02-22 Werner Koch + + * basic.c (check_pubkey_sign): Also try signing using an OID. + + * Makefile.am (TESTS) [W32]: Removed pkbench for now. + * pkbench.c (benchmark): Fixed for W32. + +2007-02-21 Werner Koch + + * hmac.c (check_one_mac): Make pointer args const. + * basic.c (check_one_md): Ditto. + (check_one_hmac): Ditto. + + * keygen.c (progress_cb): Filter out line feeds. + * basic.c (progress_handler): Ditto. + +2006-12-18 Werner Koch + + * Makefile.am (AM_CFLAGS, AM_CPPFLAGS): Splitted and merged with + Moritz' changes. + (INCLUDES): Removed. + + * keygen.c (progress_handler): New. + (main): Use it in verbose mode. + +2006-11-05 Moritz Schulte + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-17 Werner Koch + + * keygen.c (check_rsa_keys): Also create an 1536 bit DSA key. + +2006-08-03 Werner Koch + + * t-mpi-bit.c: New. + +2006-07-06 Werner Koch + + * benchmark.c (main): New option --use-random-daemon. New command + strongrandom. + (random_bench): New arg VERY_STRONG. + +2006-03-14 Werner Koch + + * benchmark.c (main): Allow for seed file argument to random bench. + + * basic.c (main): Use progress handler only in verbose mode. + (main): Speed up test key generation. + * ac-data.c (check_sexp_conversion, check_run): Take care of VERBOSE. + * ac.c (main): Ditto. + * pubkey.c (main): Ditto. + * pkbench.c (main): Ditto. + * keygen.c (main): Ditto. + (check_rsa_keys): Print key only in verbose mode. + +2006-03-10 Brad Hards (wk, patch 2006-02-18) + + * basic.c (check_one_hmac, check_hmac): New. + +2006-03-07 Werner Koch + + * benchmark.c (cipher_bench): Add OFB mode. + +2006-01-18 Brad Hards (wk 2006-03-07) + + * basic.c: Added test cases for OFB and CFB modes. Fixed some + compiler warnings for signedness. + +2005-11-12 Moritz Schulte + + * ac-data.c: Added way more test cases. + +2005-09-15 Moritz Schulte + + * Makefile.am (TESTS): Added keygrip. + * keygrip.c: New. + +2005-09-19 Werner Koch + + * benchmark.c (dsa_bench): New. + +2005-08-19 Werner Koch + + * hmac.c (main): Added all FIPS tests. + +2005-08-18 Werner Koch + + * hmac.c: New. + +2005-04-22 Moritz Schulte + + * tsexp.c: Include in case HAVE_CONFIG_H is defined; + thanks to Albert Chin. + * testapi.c: Likewise. + * register.c: Likewise. + * pubkey.c: Likewise. + * prime.c: Likewise. + * pkbench.c: Likewise. + * keygen.c: Likewise. + * benchmark.c: Likewise. + * basic.c: Likewise. + * ac-schemes.c: Likewise. + * ac-data.c: Likewise. + * ac.c: Likewise. + +2005-04-16 Moritz Schulte + + * ac-data.c (check_run): Include new test. + +2005-04-11 Moritz Schulte + + * basic.c (check_digests): Add tests for Whirlpool. + +2005-03-30 Moritz Schulte + + * ac-schemes.c: New file. + * ac-data.c: New file. + * Makefile.am (TESTS): Added ac-schemes and ac-data. + +2004-09-15 Moritz Schulte + + * pkbench.c: Include . + +2004-08-24 Moritz Schulte + + * pkbench.c (context_init): Improve generation of test data. + +2004-08-23 Moritz Schulte + + * Makefile.am (TESTS): Added: pkbench. + * pkbench.c: New file. + +2004-02-25 Werner Koch + + * Makefile.am (TEST): Add benchmark. + + * benchmark.c (md_bench, cipher_bench): Allow NULL arg to to run + tests for all algorithms. + (main): Run all tests by default. + +2004-02-03 Werner Koch + + * tsexp.c (basic): New pass to check secure memory switching. + +2004-01-12 Moritz Schulte + + * ac.c (check_one): Adjust to new ac API. + +2003-11-22 Werner Koch + + * pubkey.c (check_keys_crypt): Fixed my last patch. + +2003-11-11 Werner Koch + + * tsexp.c (basic): Add pass structure and a test for the %b + format. + +2003-11-04 Werner Koch + + * Makefile.am (noinst_PROGRAMS): Use this so that test programs + get always build. + + * keygen.c (check_nonce): New. + (main): Add a basic check for the nocen function. + +2003-10-31 Werner Koch + + * basic.c (check_aes128_cbc_cts_cipher): Make it a prototype + + * ac.c (check_run): Comment unused variable. + +2003-10-10 Werner Koch + + * prime.c (check_primes): Generate a generator and avoid printing + unless in verbose mode. + +2003-10-07 Werner Koch + + * tsexp.c (check_sscan): New. + +2003-09-04 Werner Koch + + * pubkey.c (check_keys_crypt): Fix for compatibility mode. + +2003-09-02 Moritz Schulte + + * Makefile.am (TESTS): Added: prime. + + * prime.c: New file. + +2003-08-27 Moritz Schulte + + * basic.c (check_ciphers): Added: Serpent. + Write braces around flags. + +2003-08-04 Moritz Schulte + + * benchmark.c (do_powm): Adjust for new gcry_mpi_scan interface. + +2003-07-23 Moritz Schulte + + * ac.c (key_copy): New function... + (check_one): ... use it. + +2003-07-22 Moritz Schulte + + * basic.c (check_ciphers): Use gcry_cipher_map_name. + +2003-07-18 Moritz Schulte + + * ac.c (check_run): Renamed to ... + (check_one): ... this, changed calling interface. + (check_run): New function. + + * register.c: Adjust gcry_cipher_spec_t structure. + +2003-07-14 Moritz Schulte + + * register.c: Adjust cipher specification structure. + + * benchmark.c: New file. + * testapi.c: New file. + + * Makefile.am (EXTRA_PROGRAMS): Set to: benchmark testapi. + (check_PROGRAMS): Set to: $(TESTS). + +2003-07-12 Moritz Schulte + + * ac.c, basic.c, keygen.c, register.c, sexp.c, tsexp.c: Used + gcry_err* wrappers for libgpg symbols. + + * basic.c (check_ciphers): Added: GCRY_CIPHER_TWOFISH128. + +2003-07-08 Moritz Schulte + + * Makefile.am (LIBS): Remove: -lpthread. + + * basic.c (check_one_cipher): Fix variable initialization. Thanks + to Simon Joseffson . + +2003-07-07 Moritz Schulte + + * Makefile.am (TESTS): Added: register. + +2003-07-05 Moritz Schulte + + * register.c (check_run): Adjusted for new gcry_cipher_register API. + +2003-07-02 Moritz Schulte + + * Makefile.am (TESTS): Added: ac. + * ac.c: New file. + +2003-06-18 Werner Koch + + * basic.c (check_cbc_mac_cipher): Adjusted for new API of get_blklen + and get_keylen. + (check_ctr_cipher): Ditto. + (check_one_cipher): Ditto. + (check_one_md): Adjusted for new API of gcry_md_copy. + +2003-06-18 Moritz Schulte + + * register.c: Replace old type GcryModule with newer one: + gcry_module_t. + Adjusted for new API. + + * Makefile.am (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + +2003-06-15 Moritz Schulte + + * basic.c (get_keys_new): New function. + (do_check_one_pubkey): New function ... + (check_one_pubkey): ... use it. + (progress_handler): New function. + (main): Use gcry_set_progress_handler. + +2003-06-14 Moritz Schulte + + * basic.c: Replaced calls to gcry_strerror with calls to + gpg_strerror. + (check_one_md): Adjust for new gcry_md_copy API. + + * tsexp.c: Likewise. + * keygen.c: Likewise. + +2003-06-12 Moritz Schulte + + * basic.c: Changed here and there, reorganized pubkey checks, + added DSA and ELG keys. + +2003-06-09 Moritz Schulte + + * basic.c, keygen.c, pubkey.c, register.c, tsexp.c: Changed to use + new API. + +2003-06-01 Moritz Schulte + + * tsexp.c (canon_len): Adjust for new gcry_sexp_canon_len API. + +2003-05-26 Moritz Schulte + + * basic.c (verify_one_signature): Adjust for libgpg-error. + (check_pubkey_sign): Likewise. + (check_pubkey): Likewise. + * basic.c (check_pubkey_sign): Likewise. + * tsexp.c (canon_len): Likewise. + (back_and_forth_one): Likewise. + +2003-04-27 Moritz Schulte + + * pubkey.c: Changed the sample private key to contain the + identifier `openpgp-rsa' instead of `rsa'. + + * basic.c (check_digests): Enabled/fixed some tests for TIGER. + +2003-04-17 Moritz Schulte + + * Makefile.am (TESTS): Removed `register' for now. + +2003-04-17 Moritz Schulte + + * basic.c (check_digests): Include checks for SHA512 and SHA384. + +2003-04-16 Moritz Schulte + + * basic.c (check_one_md): Also test md_copy. + +2003-04-07 Moritz Schulte + + * Makefile.am (TESTS): Added register. + + * register.c: New file. + +2003-03-30 Simon Josefsson + + * basic.c (check_one_cipher): New. Test CTR. + (main): Call it. + (check_ciphers): Check CTR mode. + +2003-03-26 Moritz Schulte + + * Makefile.am (TESTS): Added pubkey. + + * pubkey.c: New file. + +2003-03-22 Simon Josefsson + + * basic.c (check_cbc_mac_cipher): New. + (main): Use it. + +2003-03-19 Werner Koch + + * keygen.c (check_rsa_keys): Don't expect an exponent when asking + for e=0. + (check_generated_rsa_key): Just print exponent if EXPECTED_E is 0. + +2003-03-02 Moritz Schulte + + * basic.c (check_one_cipher): Use gcry_cipher_reset() instead of + gcry_cipher_close(), gcry_cipher_open and gcry_cipher_setkey(). + +2003-01-23 Werner Koch + + * keygen.c: New. + +2003-01-20 Simon Josefsson + + * basic.c (check_digests): Add CRC. + (check_one_md): Print computed and expected values on error. + +2003-01-20 Werner Koch + + * basic.c (check_one_md): Kludge to check a one million "a". + (check_digests): Add checks for SHA-256. + +2003-01-20 Werner Koch + + * basic.c (check_pubkey): Check the keygrip for the sample key. + +2003-01-15 Werner Koch + + * basic.c (verify_one_signature,check_pubkey_sign) + (check_pubkey): New. + (main): Check public key functions. Add a --debug option. + +2002-11-23 Werner Koch + + * basic.c (check_digests): Add another test for MD4. By Simon + Josefsson. + +2002-11-10 Simon Josefsson + + * basic.c (check_aes128_cbc_cts_cipher): New function. + (check_one_cipher): Add flags parameter. + (check_ciphers): Support flags parameter. + (main): Check CTS. + +2002-11-10 Werner Koch + + * basic.c (check_one_md): New. By Simon Josefsson. + (check_digests): New tests for MD4. By Simon. + +2002-08-26 Werner Koch + + * basic.c (check_ciphers): Check simple DES. + +2002-05-16 Werner Koch + + * tsexp.c (back_and_forth): Very minimal test of the new functions. + +2002-05-14 Werner Koch + + Changed license of all files to the LGPL. + +2002-05-02 Werner Koch + + * basic.c: Add option --verbose. + +2002-01-11 Werner Koch + + * tsexp.c (canon_len): Fixed tests. + +2001-12-18 Werner Koch + + * tsexp.c: New. + + + Copyright 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..4cfddf3 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,45 @@ +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +## Process this file with automake to produce Makefile.in + +TESTS = version t-mpi-bit prime register ac ac-schemes ac-data basic \ + mpitests tsexp keygen pubkey hmac keygrip fips186-dsa + + +# random.c uses fork() thus a test for W32 does not make any sense. +if !HAVE_W32_SYSTEM +TESTS += random +endif + +# The last test to run. +TESTS += benchmark + + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) +AM_LDFLAGS = $(GPG_ERROR_LIBS) + +LDADD = ../src/libgcrypt.la $(DL_LIBS) + +EXTRA_PROGRAMS = testapi pkbench +noinst_PROGRAMS = $(TESTS) fipsdrv + +EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..4a18327 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,798 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = version$(EXEEXT) t-mpi-bit$(EXEEXT) prime$(EXEEXT) \ + register$(EXEEXT) ac$(EXEEXT) ac-schemes$(EXEEXT) \ + ac-data$(EXEEXT) basic$(EXEEXT) mpitests$(EXEEXT) \ + tsexp$(EXEEXT) keygen$(EXEEXT) pubkey$(EXEEXT) hmac$(EXEEXT) \ + keygrip$(EXEEXT) fips186-dsa$(EXEEXT) $(am__EXEEXT_1) \ + benchmark$(EXEEXT) + +# random.c uses fork() thus a test for W32 does not make any sense. +@HAVE_W32_SYSTEM_FALSE@am__append_1 = random +EXTRA_PROGRAMS = testapi$(EXEEXT) pkbench$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_2) fipsdrv$(EXEEXT) +subdir = tests +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + ChangeLog +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \ + $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_W32_SYSTEM_FALSE@am__EXEEXT_1 = random$(EXEEXT) +am__EXEEXT_2 = version$(EXEEXT) t-mpi-bit$(EXEEXT) prime$(EXEEXT) \ + register$(EXEEXT) ac$(EXEEXT) ac-schemes$(EXEEXT) \ + ac-data$(EXEEXT) basic$(EXEEXT) mpitests$(EXEEXT) \ + tsexp$(EXEEXT) keygen$(EXEEXT) pubkey$(EXEEXT) hmac$(EXEEXT) \ + keygrip$(EXEEXT) fips186-dsa$(EXEEXT) $(am__EXEEXT_1) \ + benchmark$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +ac_SOURCES = ac.c +ac_OBJECTS = ac.$(OBJEXT) +ac_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +ac_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +ac_data_SOURCES = ac-data.c +ac_data_OBJECTS = ac-data.$(OBJEXT) +ac_data_LDADD = $(LDADD) +ac_data_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +ac_schemes_SOURCES = ac-schemes.c +ac_schemes_OBJECTS = ac-schemes.$(OBJEXT) +ac_schemes_LDADD = $(LDADD) +ac_schemes_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +basic_SOURCES = basic.c +basic_OBJECTS = basic.$(OBJEXT) +basic_LDADD = $(LDADD) +basic_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +benchmark_SOURCES = benchmark.c +benchmark_OBJECTS = benchmark.$(OBJEXT) +benchmark_LDADD = $(LDADD) +benchmark_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +fips186_dsa_SOURCES = fips186-dsa.c +fips186_dsa_OBJECTS = fips186-dsa.$(OBJEXT) +fips186_dsa_LDADD = $(LDADD) +fips186_dsa_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +fipsdrv_SOURCES = fipsdrv.c +fipsdrv_OBJECTS = fipsdrv.$(OBJEXT) +fipsdrv_LDADD = $(LDADD) +fipsdrv_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +hmac_SOURCES = hmac.c +hmac_OBJECTS = hmac.$(OBJEXT) +hmac_LDADD = $(LDADD) +hmac_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +keygen_SOURCES = keygen.c +keygen_OBJECTS = keygen.$(OBJEXT) +keygen_LDADD = $(LDADD) +keygen_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +keygrip_SOURCES = keygrip.c +keygrip_OBJECTS = keygrip.$(OBJEXT) +keygrip_LDADD = $(LDADD) +keygrip_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +mpitests_SOURCES = mpitests.c +mpitests_OBJECTS = mpitests.$(OBJEXT) +mpitests_LDADD = $(LDADD) +mpitests_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +pkbench_SOURCES = pkbench.c +pkbench_OBJECTS = pkbench.$(OBJEXT) +pkbench_LDADD = $(LDADD) +pkbench_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +prime_SOURCES = prime.c +prime_OBJECTS = prime.$(OBJEXT) +prime_LDADD = $(LDADD) +prime_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +pubkey_SOURCES = pubkey.c +pubkey_OBJECTS = pubkey.$(OBJEXT) +pubkey_LDADD = $(LDADD) +pubkey_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +random_SOURCES = random.c +random_OBJECTS = random.$(OBJEXT) +random_LDADD = $(LDADD) +random_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +register_SOURCES = register.c +register_OBJECTS = register.$(OBJEXT) +register_LDADD = $(LDADD) +register_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +t_mpi_bit_SOURCES = t-mpi-bit.c +t_mpi_bit_OBJECTS = t-mpi-bit.$(OBJEXT) +t_mpi_bit_LDADD = $(LDADD) +t_mpi_bit_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +testapi_SOURCES = testapi.c +testapi_OBJECTS = testapi.$(OBJEXT) +testapi_LDADD = $(LDADD) +testapi_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +tsexp_SOURCES = tsexp.c +tsexp_OBJECTS = tsexp.$(OBJEXT) +tsexp_LDADD = $(LDADD) +tsexp_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +version_SOURCES = version.c +version_OBJECTS = version.$(OBJEXT) +version_LDADD = $(LDADD) +version_DEPENDENCIES = ../src/libgcrypt.la $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = ac.c ac-data.c ac-schemes.c basic.c benchmark.c \ + fips186-dsa.c fipsdrv.c hmac.c keygen.c keygrip.c mpitests.c \ + pkbench.c prime.c pubkey.c random.c register.c t-mpi-bit.c \ + testapi.c tsexp.c version.c +DIST_SOURCES = ac.c ac-data.c ac-schemes.c basic.c benchmark.c \ + fips186-dsa.c fipsdrv.c hmac.c keygen.c keygrip.c mpitests.c \ + pkbench.c prime.c pubkey.c random.c register.c t-mpi-bit.c \ + testapi.c tsexp.c version.c +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@ +FFLAGS = @FFLAGS@ +GCRYPT_CIPHERS = @GCRYPT_CIPHERS@ +GCRYPT_DIGESTS = @GCRYPT_DIGESTS@ +GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@ +GCRYPT_RANDOM = @GCRYPT_RANDOM@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@ +LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@ +LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@ +LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@ +LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@ +LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@ +LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@ +LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@ +LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@ +LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MPI_SFLAGS = @MPI_SFLAGS@ +NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTH_CFLAGS = @PTH_CFLAGS@ +PTH_CONFIG = @PTH_CONFIG@ +PTH_LIBS = @PTH_LIBS@ +RANLIB = @RANLIB@ +RC = @RC@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) +AM_LDFLAGS = $(GPG_ERROR_LIBS) +LDADD = ../src/libgcrypt.la $(DL_LIBS) +EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +ac$(EXEEXT): $(ac_OBJECTS) $(ac_DEPENDENCIES) + @rm -f ac$(EXEEXT) + $(LINK) $(ac_OBJECTS) $(ac_LDADD) $(LIBS) +ac-data$(EXEEXT): $(ac_data_OBJECTS) $(ac_data_DEPENDENCIES) + @rm -f ac-data$(EXEEXT) + $(LINK) $(ac_data_OBJECTS) $(ac_data_LDADD) $(LIBS) +ac-schemes$(EXEEXT): $(ac_schemes_OBJECTS) $(ac_schemes_DEPENDENCIES) + @rm -f ac-schemes$(EXEEXT) + $(LINK) $(ac_schemes_OBJECTS) $(ac_schemes_LDADD) $(LIBS) +basic$(EXEEXT): $(basic_OBJECTS) $(basic_DEPENDENCIES) + @rm -f basic$(EXEEXT) + $(LINK) $(basic_OBJECTS) $(basic_LDADD) $(LIBS) +benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES) + @rm -f benchmark$(EXEEXT) + $(LINK) $(benchmark_OBJECTS) $(benchmark_LDADD) $(LIBS) +fips186-dsa$(EXEEXT): $(fips186_dsa_OBJECTS) $(fips186_dsa_DEPENDENCIES) + @rm -f fips186-dsa$(EXEEXT) + $(LINK) $(fips186_dsa_OBJECTS) $(fips186_dsa_LDADD) $(LIBS) +fipsdrv$(EXEEXT): $(fipsdrv_OBJECTS) $(fipsdrv_DEPENDENCIES) + @rm -f fipsdrv$(EXEEXT) + $(LINK) $(fipsdrv_OBJECTS) $(fipsdrv_LDADD) $(LIBS) +hmac$(EXEEXT): $(hmac_OBJECTS) $(hmac_DEPENDENCIES) + @rm -f hmac$(EXEEXT) + $(LINK) $(hmac_OBJECTS) $(hmac_LDADD) $(LIBS) +keygen$(EXEEXT): $(keygen_OBJECTS) $(keygen_DEPENDENCIES) + @rm -f keygen$(EXEEXT) + $(LINK) $(keygen_OBJECTS) $(keygen_LDADD) $(LIBS) +keygrip$(EXEEXT): $(keygrip_OBJECTS) $(keygrip_DEPENDENCIES) + @rm -f keygrip$(EXEEXT) + $(LINK) $(keygrip_OBJECTS) $(keygrip_LDADD) $(LIBS) +mpitests$(EXEEXT): $(mpitests_OBJECTS) $(mpitests_DEPENDENCIES) + @rm -f mpitests$(EXEEXT) + $(LINK) $(mpitests_OBJECTS) $(mpitests_LDADD) $(LIBS) +pkbench$(EXEEXT): $(pkbench_OBJECTS) $(pkbench_DEPENDENCIES) + @rm -f pkbench$(EXEEXT) + $(LINK) $(pkbench_OBJECTS) $(pkbench_LDADD) $(LIBS) +prime$(EXEEXT): $(prime_OBJECTS) $(prime_DEPENDENCIES) + @rm -f prime$(EXEEXT) + $(LINK) $(prime_OBJECTS) $(prime_LDADD) $(LIBS) +pubkey$(EXEEXT): $(pubkey_OBJECTS) $(pubkey_DEPENDENCIES) + @rm -f pubkey$(EXEEXT) + $(LINK) $(pubkey_OBJECTS) $(pubkey_LDADD) $(LIBS) +random$(EXEEXT): $(random_OBJECTS) $(random_DEPENDENCIES) + @rm -f random$(EXEEXT) + $(LINK) $(random_OBJECTS) $(random_LDADD) $(LIBS) +register$(EXEEXT): $(register_OBJECTS) $(register_DEPENDENCIES) + @rm -f register$(EXEEXT) + $(LINK) $(register_OBJECTS) $(register_LDADD) $(LIBS) +t-mpi-bit$(EXEEXT): $(t_mpi_bit_OBJECTS) $(t_mpi_bit_DEPENDENCIES) + @rm -f t-mpi-bit$(EXEEXT) + $(LINK) $(t_mpi_bit_OBJECTS) $(t_mpi_bit_LDADD) $(LIBS) +testapi$(EXEEXT): $(testapi_OBJECTS) $(testapi_DEPENDENCIES) + @rm -f testapi$(EXEEXT) + $(LINK) $(testapi_OBJECTS) $(testapi_LDADD) $(LIBS) +tsexp$(EXEEXT): $(tsexp_OBJECTS) $(tsexp_DEPENDENCIES) + @rm -f tsexp$(EXEEXT) + $(LINK) $(tsexp_OBJECTS) $(tsexp_LDADD) $(LIBS) +version$(EXEEXT): $(version_OBJECTS) $(version_DEPENDENCIES) + @rm -f version$(EXEEXT) + $(LINK) $(version_OBJECTS) $(version_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac-data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac-schemes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fips186-dsa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fipsdrv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygrip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpitests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkbench.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/register.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-mpi-bit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testapi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsexp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..5326890 --- /dev/null +++ b/tests/README @@ -0,0 +1,9 @@ +Some notes about the tests. + +rsa-16k.key - A 16384 bit RSA key (public and privat), created 2008-08-28. + It took 91 minutes to create it on a 1500Mhz Pentium M. + pkpench showed these results: + encrypt: 80 ms + decrypt: 14370 ms + sign: 14110 ms + verify: 30 ms diff --git a/tests/ac-data.c b/tests/ac-data.c new file mode 100644 index 0000000..e97b4f4 --- /dev/null +++ b/tests/ac-data.c @@ -0,0 +1,208 @@ +/* ac-data.c - Public key encryption/decryption tests + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#define assert_err(err) \ + do \ + if (err) \ + { \ + fprintf (stderr, "Error occured at line %i: %s\n", \ + __LINE__, gcry_strerror (err)); \ + exit (1); \ + } \ + while (0) + +#include "../src/gcrypt.h" + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +static void +check_sexp_conversion (gcry_ac_data_t data, const char **identifiers) +{ + gcry_ac_data_t data2; + gcry_error_t err; + gcry_sexp_t sexp; + unsigned int i; + const char *label1, *label2; + gcry_mpi_t mpi1, mpi2; + size_t length1, length2; + + err = gcry_ac_data_to_sexp (data, &sexp, identifiers); + assert_err (err); + if (verbose) + gcry_sexp_dump (sexp); + err = gcry_ac_data_from_sexp (&data2, sexp, identifiers); + assert_err (err); + + length1 = gcry_ac_data_length (data); + length2 = gcry_ac_data_length (data2); + assert (length1 == length2); + + for (i = 0; i < length1; i++) + { + err = gcry_ac_data_get_index (data, 0, i, &label1, &mpi1); + assert_err (err); + err = gcry_ac_data_get_index (data2, 0, i, &label2, &mpi2); + assert_err (err); + if (verbose) + { + fprintf (stderr, "Label1=`%s'\n", label1); + fprintf (stderr, "Label2=`%s'\n", label2); + } + assert (! strcmp (label1, label2)); + assert (! gcry_mpi_cmp (mpi1, mpi2)); + } + + gcry_ac_data_destroy (data2); + gcry_sexp_release (sexp); +} + +void +check_run (void) +{ + const char *identifiers[] = { "foo", + "bar", + "baz", + "hello", + "somemoretexthere", + "blahblahblah", + NULL }; + const char *identifiers_null[] = { NULL }; + gcry_ac_data_t data; + gcry_error_t err; + const char *label0; + const char *label1; + gcry_mpi_t mpi0; + gcry_mpi_t mpi1; + gcry_mpi_t mpi2; + + /* Initialize values. */ + + label0 = "thisisreallylonglabelbutsincethereisnolimitationonthelengthoflabelsitshouldworkjustfine"; + mpi0 = gcry_mpi_new (0); + assert (mpi0); + gcry_mpi_set_ui (mpi0, 123456); + + err = gcry_ac_data_new (&data); + assert_err (err); + + check_sexp_conversion (data, identifiers); + check_sexp_conversion (data, identifiers_null); + check_sexp_conversion (data, NULL); + + err = gcry_ac_data_set (data, 0, label0, mpi0); + assert_err (err); + err = gcry_ac_data_get_index (data, 0, 0, &label1, &mpi1); + assert_err (err); + assert (label0 == label1); + assert (mpi0 == mpi1); + check_sexp_conversion (data, identifiers); + check_sexp_conversion (data, identifiers_null); + check_sexp_conversion (data, NULL); + + if (verbose) + printf ("data-set-test-0 succeeded\n"); + + gcry_ac_data_clear (data); + + err = gcry_ac_data_set (data, GCRY_AC_FLAG_COPY, label0, mpi0); + assert_err (err); + + err = gcry_ac_data_set (data, GCRY_AC_FLAG_COPY, "foo", mpi0); + assert_err (err); + err = gcry_ac_data_set (data, GCRY_AC_FLAG_COPY, "foo", mpi0); + assert_err (err); + err = gcry_ac_data_set (data, GCRY_AC_FLAG_COPY, "bar", mpi0); + assert_err (err); + err = gcry_ac_data_set (data, GCRY_AC_FLAG_COPY, "blah1", mpi0); + assert_err (err); + check_sexp_conversion (data, identifiers); + check_sexp_conversion (data, identifiers_null); + check_sexp_conversion (data, NULL); + + err = gcry_ac_data_get_name (data, 0, label0, &mpi1); + assert_err (err); + assert (mpi0 != mpi1); + err = gcry_ac_data_get_name (data, GCRY_AC_FLAG_COPY, label0, &mpi2); + assert_err (err); + assert (mpi0 != mpi1); + assert (mpi1 != mpi2); + err = gcry_ac_data_get_index (data, 0, 0, &label1, &mpi1); + assert_err (err); + gcry_mpi_release (mpi0); + gcry_mpi_release (mpi2); + + if (verbose) + printf ("data-set-test-1 succeeded\n"); + + gcry_ac_data_clear (data); + assert (! gcry_ac_data_length (data)); + check_sexp_conversion (data, identifiers); + check_sexp_conversion (data, identifiers_null); + check_sexp_conversion (data, NULL); + + if (verbose) + printf ("data-set-test-2 succeeded\n"); + + gcry_ac_data_destroy (data); + + +} + +int +main (int argc, char **argv) +{ + int debug = 0; + int i = 1; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + + for (; i > 0; i--) + check_run (); + + return 0; +} diff --git a/tests/ac-schemes.c b/tests/ac-schemes.c new file mode 100644 index 0000000..dcef0bf --- /dev/null +++ b/tests/ac-schemes.c @@ -0,0 +1,347 @@ +/* ac-schemes.c - Tests for ES/SSA + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static unsigned int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +typedef struct scheme_spec +{ + unsigned int idx; + gcry_ac_scheme_t scheme; + unsigned int flags; + const char *m; + size_t m_n; +} scheme_spec_t; + +#define SCHEME_SPEC_FLAG_GET_OPTS (1 << 0) + +#define FILL(idx, scheme, flags, m) \ + { idx, GCRY_AC_##scheme, flags, m, sizeof (m) } + +scheme_spec_t es_specs[] = + { + FILL (0, ES_PKCS_V1_5, 0, "foobar"), + FILL (1, ES_PKCS_V1_5, 0, "") + }; + +scheme_spec_t ssa_specs[] = + { + FILL (0, SSA_PKCS_V1_5, SCHEME_SPEC_FLAG_GET_OPTS, "foobar") + }; + +#undef FILL + +gcry_err_code_t +scheme_get_opts (scheme_spec_t specs, void **opts) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + void *opts_new = NULL; + + switch (specs.scheme) + { + case GCRY_AC_SSA_PKCS_V1_5: + { + gcry_ac_ssa_pkcs_v1_5_t *opts_pkcs_v1_5 = NULL; + + opts_new = gcry_malloc (sizeof (gcry_ac_ssa_pkcs_v1_5_t)); + if (! opts_new) + err = gpg_err_code_from_errno (ENOMEM); + else + { + opts_pkcs_v1_5 = (gcry_ac_ssa_pkcs_v1_5_t *) opts_new; + + switch (specs.idx) + { + case 0: + opts_pkcs_v1_5->md = GCRY_MD_SHA1; + break; + case 1: + opts_pkcs_v1_5->md = GCRY_MD_MD5; + break; + } + } + } + case GCRY_AC_ES_PKCS_V1_5: + break; + } + + if (! err) + *opts = opts_new; + + return err; +} + +gcry_error_t +es_check (gcry_ac_handle_t handle, scheme_spec_t spec, + gcry_ac_key_t key_public, gcry_ac_key_t key_secret) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + char *c = NULL; + char *m2 = NULL; + size_t c_n = 0; + size_t m2_n = 0; + void *opts = NULL; + gcry_ac_io_t io_m; + gcry_ac_io_t io_c; + gcry_ac_io_t io_m2; + + if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS) + err = scheme_get_opts (spec, &opts); + if (! err) + { + c = NULL; + m2 = NULL; + + gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, spec.m, spec.m_n); + gcry_ac_io_init (&io_c, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &c, &c_n); + + err = gcry_ac_data_encrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0, opts, key_public, + &io_m, &io_c); + if (! err) + { + gcry_ac_io_init (&io_c, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, c, c_n); + gcry_ac_io_init (&io_m2, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &m2, &m2_n); + + err = gcry_ac_data_decrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0, + opts, key_secret, &io_c, &io_m2); + } + if (! err) + assert ((spec.m_n == m2_n) && (! strncmp (spec.m, m2, spec.m_n))); + + if (c) + gcry_free (c); + if (m2) + gcry_free (m2); + } + + if (opts) + gcry_free (opts); + + return err; +} + +gcry_error_t +ssa_check (gcry_ac_handle_t handle, scheme_spec_t spec, + gcry_ac_key_t key_public, gcry_ac_key_t key_secret) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + unsigned char *s = NULL; + size_t s_n = 0; + void *opts = NULL; + gcry_ac_io_t io_m; + gcry_ac_io_t io_s; + + if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS) + err = scheme_get_opts (spec, &opts); + if (! err) + { + gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, spec.m, spec.m_n); + gcry_ac_io_init (&io_s, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &s, &s_n); + + err = gcry_ac_data_sign_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_secret, + &io_m, &io_s); + if (! err) + { + gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, spec.m, spec.m_n); + gcry_ac_io_init (&io_s, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, s, s_n); + err = gcry_ac_data_verify_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_public, + &io_m, &io_s); + } + assert (! err); + + if (s) + gcry_free (s); + } + + if (opts) + gcry_free (opts); + + return err; +} + +void +es_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + unsigned int i = 0; + + for (i = 0; (i < (sizeof (es_specs) / sizeof (*es_specs))) && (! err); i++) + err = es_check (handle, es_specs[i], key_public, key_secret); + + assert (! err); +} + +void +ssa_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + unsigned int i = 0; + + for (i = 0; (i < (sizeof (ssa_specs) / sizeof (*ssa_specs))) && (! err); i++) + err = ssa_check (handle, ssa_specs[i], key_public, key_secret); + + assert (! err); +} + +#define KEY_TYPE_PUBLIC (1 << 0) +#define KEY_TYPE_SECRET (1 << 1) + +typedef struct key_spec +{ + const char *name; + unsigned int flags; + const char *mpi_string; +} key_spec_t; + +key_spec_t key_specs[] = + { + { "n", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET, + "e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251" }, + { "e", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET, + "010001" }, + { "d", KEY_TYPE_SECRET, + "046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781" }, + { "p", KEY_TYPE_SECRET, + "00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" + "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1" }, + { "q", KEY_TYPE_SECRET, + "00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" + "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361" }, + { "u", KEY_TYPE_SECRET, + "304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" + "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b" }, + { NULL }, + }; + +gcry_error_t +key_init (gcry_ac_key_type_t type, gcry_ac_key_t *key) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_ac_data_t key_data = NULL; + gcry_ac_key_t key_new = NULL; + gcry_mpi_t mpi = NULL; + unsigned int i = 0; + + err = gcry_ac_data_new (&key_data); + for (i = 0; key_specs[i].name && (! err); i++) + { + if (((type == GCRY_AC_KEY_PUBLIC) && (key_specs[i].flags & KEY_TYPE_PUBLIC)) + || ((type == GCRY_AC_KEY_SECRET) && (key_specs[i].flags & KEY_TYPE_SECRET))) + { + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, key_specs[i].mpi_string, 0, NULL); + if (! err) + { + gcry_ac_data_set (key_data, GCRY_AC_FLAG_COPY | GCRY_AC_FLAG_DEALLOC, + key_specs[i].name, mpi); + gcry_mpi_release (mpi); + } + } + } + if (! err) + err = gcry_ac_key_init (&key_new, NULL, type, key_data); + + if (key_data) + gcry_ac_data_destroy (key_data); + + if (! err) + *key = key_new; + + return err; +} + +static void +check_run (void) +{ + gcry_ac_handle_t handle = NULL; + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_ac_key_t key_public = NULL, key_secret = NULL; + + err = key_init (GCRY_AC_KEY_PUBLIC, &key_public); + if (! err) + err = key_init (GCRY_AC_KEY_SECRET, &key_secret); + + if (! err) + err = gcry_ac_open (&handle, GCRY_AC_RSA, 0); + if (! err) + { + es_checks (handle, key_public, key_secret); + ssa_checks (handle, key_public, key_secret); + } + + assert (! err); +} + +int +main (int argc, char **argv) +{ + unsigned int debug = 0; + + if ((argc > 1) && (! strcmp (argv[1], "--verbose"))) + verbose = 1; + else if ((argc > 1) && (! strcmp (argv[1], "--debug"))) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (! gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + + check_run (); + + return 0; +} diff --git a/tests/ac.c b/tests/ac.c new file mode 100644 index 0000000..d734360 --- /dev/null +++ b/tests/ac.c @@ -0,0 +1,162 @@ +/* pubkey.c - Public key encryption/decryption tests + * Copyright (C) 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +void +key_copy (gcry_ac_handle_t handle, + gcry_ac_key_type_t type, + gcry_ac_key_t *key_cp, gcry_ac_key_t key) +{ + gcry_error_t err = 0; + + err = gcry_ac_key_init (key_cp, handle, type, + gcry_ac_key_data_get (key)); + + assert (! err); +} + +void +check_one (gcry_mpi_t x) +{ + gcry_ac_handle_t handle; + gcry_ac_key_pair_t key_pair; + gcry_ac_key_t key_sec, key_sec_cp, key_pub, key_pub_cp; + gcry_error_t err = 0; + gcry_mpi_t x2; + gcry_ac_data_t data, data2; + gcry_ac_key_spec_rsa_t rsa_spec; + + rsa_spec.e = gcry_mpi_new (0); + gcry_mpi_set_ui (rsa_spec.e, 1); + + err = gcry_ac_open (&handle, GCRY_AC_RSA, 0); + assert (! err); + + err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, &key_pair, NULL); + assert (! err); + + key_sec = gcry_ac_key_pair_extract (key_pair, GCRY_AC_KEY_SECRET); + key_copy (handle, GCRY_AC_KEY_SECRET, &key_sec_cp, key_sec); + + key_pub = gcry_ac_key_pair_extract (key_pair, GCRY_AC_KEY_PUBLIC); + key_copy (handle, GCRY_AC_KEY_PUBLIC, &key_pub_cp, key_pub); + + err = gcry_ac_data_encrypt (handle, GCRY_AC_FLAG_NO_BLINDING, key_pub_cp, x, &data); + assert (! err); + + err = gcry_ac_data_decrypt (handle, GCRY_AC_FLAG_NO_BLINDING, key_sec_cp, &x2, data); + assert (! err); + + assert (! gcry_mpi_cmp (x, x2)); + + gcry_ac_data_destroy (data); + + err = gcry_ac_data_sign (handle, key_sec, x, &data); + assert (! err); + err = gcry_ac_data_copy (&data2, data); + assert (! err); + gcry_ac_data_destroy (data); + err = gcry_ac_data_copy (&data, data2); + assert (! err); + gcry_ac_data_destroy (data2); + + err = gcry_ac_data_verify (handle, key_pub, x, data); + assert (! err); + + gcry_ac_data_destroy (data); + + err = gcry_ac_data_sign (handle, key_sec, x, &data); + assert (! err); + { + const char *label; + gcry_mpi_t y; + + err = gcry_ac_data_get_index (data, 0, 0, &label, &y); + assert (! err); + gcry_mpi_add_ui (y, y, 1); + + err = gcry_ac_data_verify (handle, key_pub, x, data); + assert (gcry_err_code (err) == GPG_ERR_BAD_SIGNATURE); + } + + gcry_ac_close (handle); +} + +void +check_run (void) +{ + /*const char *s = "All Hail Discordia."; -- not used */ + unsigned int a = 0x4223; + gcry_mpi_t x; + + x = gcry_mpi_new (0); + gcry_mpi_set_ui (x, a); + check_one (x); + gcry_mpi_release (x); +} + +int +main (int argc, char **argv) +{ + int debug = 0; + int i = 1; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + for (; i > 0; i--) + check_run (); + + return 0; +} diff --git a/tests/basic.c b/tests/basic.c new file mode 100644 index 0000000..53305dd --- /dev/null +++ b/tests/basic.c @@ -0,0 +1,2182 @@ +/* basic.c - basic regression tests + * Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +typedef struct test_spec_pubkey_key +{ + const char *secret; + const char *public; + const char *grip; +} +test_spec_pubkey_key_t; + +typedef struct test_spec_pubkey +{ + int id; + int flags; + test_spec_pubkey_key_t key; +} +test_spec_pubkey_t; + +#define FLAG_CRYPT (1 << 0) +#define FLAG_SIGN (1 << 1) +#define FLAG_GRIP (1 << 2) + +static int verbose; +static int error_count; +static int in_fips_mode; + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +#define MAX_DATA_LEN 100 + +void +progress_handler (void *cb_data, const char *what, int printchar, + int current, int total) +{ + (void)cb_data; + (void)what; + (void)current; + (void)total; + + if (printchar == '\n') + fputs ( "", stdout); + else + putchar (printchar); + fflush (stdout); +} + +static void +check_cbc_mac_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + unsigned char plaintext[MAX_DATA_LEN]; + size_t plaintextlen; + char mac[MAX_DATA_LEN]; + } + tv[] = + { + { GCRY_CIPHER_AES, + "chicken teriyaki", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", + 0, "\x23\x8f\x6d\xc7\x53\x6a\x62\x97\x11\xc4\xa5\x16\x43\xea\xb0\xb6" }, + { GCRY_CIPHER_3DES, + "abcdefghABCDEFGH01234567", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", + 0, "\x5c\x11\xf0\x01\x47\xbd\x3d\x3a" }, + { GCRY_CIPHER_DES, + "abcdefgh", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", + 0, "\xfa\x4b\xdf\x9d\xfa\xab\x01\x70" } + }; + gcry_cipher_hd_t hd; + unsigned char out[MAX_DATA_LEN]; + int i, blklen, keylen; + gcry_error_t err = 0; + + if (verbose) + fprintf (stderr, "Starting CBC MAC checks.\n"); + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + + err = gcry_cipher_open (&hd, + tv[i].algo, + GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC); + if (!hd) + { + fail ("cbc-mac algo %d, grcy_open_cipher failed: %s\n", + tv[i].algo, gpg_strerror (err)); + return; + } + + blklen = gcry_cipher_get_algo_blklen(tv[i].algo); + if (!blklen) + { + fail ("cbc-mac algo %d, gcry_cipher_get_algo_blklen failed\n", + tv[i].algo); + gcry_cipher_close (hd); + return; + } + + keylen = gcry_cipher_get_algo_keylen (tv[i].algo); + if (!keylen) + { + fail ("cbc-mac algo %d, gcry_cipher_get_algo_keylen failed\n", + tv[i].algo); + return; + } + + err = gcry_cipher_setkey (hd, tv[i].key, keylen); + if (err) + { + fail ("cbc-mac algo %d, gcry_cipher_setkey failed: %s\n", + tv[i].algo, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + err = gcry_cipher_setiv (hd, NULL, 0); + if (err) + { + fail ("cbc-mac algo %d, gcry_cipher_setiv failed: %s\n", + tv[i].algo, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (verbose) + fprintf (stderr, " checking CBC MAC for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo); + err = gcry_cipher_encrypt (hd, + out, blklen, + tv[i].plaintext, + tv[i].plaintextlen ? + tv[i].plaintextlen : + strlen ((char*)tv[i].plaintext)); + if (err) + { + fail ("cbc-mac algo %d, gcry_cipher_encrypt failed: %s\n", + tv[i].algo, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + +#if 0 + { + int j; + for (j = 0; j < gcry_cipher_get_algo_blklen (tv[i].algo); j++) + printf ("\\x%02x", out[j] & 0xFF); + printf ("\n"); + } +#endif + + if (memcmp (tv[i].mac, out, blklen)) + fail ("cbc-mac algo %d, encrypt mismatch entry %d\n", tv[i].algo, i); + + gcry_cipher_close (hd); + } + if (verbose) + fprintf (stderr, "Completed CBC MAC checks.\n"); +} + +static void +check_aes128_cbc_cts_cipher (void) +{ + char key[128 / 8] = "chicken teriyaki"; + unsigned char plaintext[] = + "I would like the General Gau's Chicken, please, and wonton soup."; + struct tv + { + unsigned char out[MAX_DATA_LEN]; + int inlen; + } tv[] = + { + { "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" + "\x97", + 17 }, + { "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5", + 31 }, + { "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", + 32 }, + { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5", + 47 }, + { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", + 48 }, + { "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", + 64 }, + }; + gcry_cipher_hd_t hd; + unsigned char out[MAX_DATA_LEN]; + int i; + gcry_error_t err = 0; + + if (verbose) + fprintf (stderr, "Starting AES128 CBC CTS checks.\n"); + err = gcry_cipher_open (&hd, + GCRY_CIPHER_AES, + GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); + if (err) + { + fail ("aes-cbc-cts, grcy_open_cipher failed: %s\n", gpg_strerror (err)); + return; + } + + err = gcry_cipher_setkey (hd, key, 128 / 8); + if (err) + { + fail ("aes-cbc-cts, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + err = gcry_cipher_setiv (hd, NULL, 0); + if (err) + { + fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (verbose) + fprintf (stderr, " checking encryption for length %i\n", tv[i].inlen); + err = gcry_cipher_encrypt (hd, out, MAX_DATA_LEN, + plaintext, tv[i].inlen); + if (err) + { + fail ("aes-cbc-cts, gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("aes-cbc-cts, encrypt mismatch entry %d\n", i); + + err = gcry_cipher_setiv (hd, NULL, 0); + if (err) + { + fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + if (verbose) + fprintf (stderr, " checking decryption for length %i\n", tv[i].inlen); + err = gcry_cipher_decrypt (hd, out, tv[i].inlen, NULL, 0); + if (err) + { + fail ("aes-cbc-cts, gcry_cipher_decrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (memcmp (plaintext, out, tv[i].inlen)) + fail ("aes-cbc-cts, decrypt mismatch entry %d\n", i); + } + + gcry_cipher_close (hd); + if (verbose) + fprintf (stderr, "Completed AES128 CBC CTS checks.\n"); +} + +static void +check_ctr_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char ctr[MAX_DATA_LEN]; + struct data + { + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + } + data[MAX_DATA_LEN]; + } tv[] = + { + /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ + { GCRY_CIPHER_AES, + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd\xff" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1\x79\x21\x70\xa0\xf3\x00\x9c\xee" }, + } + }, + { GCRY_CIPHER_AES192, + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b" + "\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\x1a\xbc\x93\x24\x17\x52\x1c\xa2\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x09\x03\x39\xec\x0a\xa6\xfa\xef\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70\xd1\xbd\x1d\x66\x56\x20\xab\xf7" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x4f\x78\xa7\xf6\xd2\x98\x09\x58\x5a\x97\xda\xec\x58\xc6\xb0\x50" }, + } + }, + { GCRY_CIPHER_AES256, + "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\x60\x1e\xc3\x13\x77\x57\x89\xa5\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a\xca\x84\xe9\x90\xca\xca\xf5\xc5" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c\xe8\x70\x17\xba\x2d\x84\x98\x8d" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6\x13\xc2\xdd\x08\x45\x79\x41\xa6" } + } + } + }; + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + int i, j, keylen, blklen; + gcry_error_t err = 0; + + if (verbose) + fprintf (stderr, "Starting CTR cipher checks.\n"); + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); + if (err) + { + fail ("aes-ctr, grcy_open_cipher failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("aes-ctr, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("aes-ctr, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + blklen = gcry_cipher_get_algo_blklen(tv[i].algo); + if (!blklen) + { + fail ("aes-ctr, gcry_cipher_get_algo_blklen failed\n"); + return; + } + + err = gcry_cipher_setctr (hde, tv[i].ctr, blklen); + if (!err) + err = gcry_cipher_setctr (hdd, tv[i].ctr, blklen); + if (err) + { + fail ("aes-ctr, gcry_cipher_setctr failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (verbose) + fprintf (stderr, " checking CTR mode for for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo); + for (j = 0; tv[i].data[j].inlen; j++) + { + err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, + tv[i].data[j].plaintext, + tv[i].data[j].inlen == -1 ? + strlen ((char*)tv[i].data[j].plaintext) : + tv[i].data[j].inlen); + if (err) + { + fail ("aes-ctr, gcry_cipher_encrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen)) + fail ("aes-ctr, encrypt mismatch entry %d:%d\n", i, j); + + err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0); + if (err) + { + fail ("aes-ctr, gcry_cipher_decrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen)) + fail ("aes-ctr, decrypt mismatch entry %d:%d\n", i, j); + } + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } + if (verbose) + fprintf (stderr, "Completed CTR cipher checks.\n"); +} + +static void +check_cfb_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char iv[MAX_DATA_LEN]; + struct data + { + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + } + data[MAX_DATA_LEN]; + } tv[] = + { + /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ + { GCRY_CIPHER_AES, + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\xc8\xa6\x45\x37\xa0\xb3\xa9\x3f\xcd\xe3\xcd\xad\x9f\x1c\xe5\x8b"}, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x26\x75\x1f\x67\xa3\xcb\xb1\x40\xb1\x80\x8c\xf1\x87\xa4\xf4\xdf" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\xc0\x4b\x05\x35\x7c\x5d\x1c\x0e\xea\xc4\xc6\x6f\x9f\xf7\xf2\xe6" }, + } + }, + { GCRY_CIPHER_AES192, + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b" + "\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab\x34\xc2\x59\x09\xc9\x9a\x41\x74" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x67\xce\x7f\x7f\x81\x17\x36\x21\x96\x1a\x2b\x70\x17\x1d\x3d\x7a" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x2e\x1e\x8a\x1d\xd5\x9b\x88\xb1\xc8\xe6\x0f\xed\x1e\xfa\xc4\xc9" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\xc0\x5f\x9f\x9c\xa9\x83\x4f\xa0\x42\xae\x8f\xba\x58\x4b\x09\xff" }, + } + }, + { GCRY_CIPHER_AES256, + "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\xdc\x7e\x84\xbf\xda\x79\x16\x4b\x7e\xcd\x84\x86\x98\x5d\x38\x60" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x39\xff\xed\x14\x3b\x28\xb1\xc8\x32\x11\x3c\x63\x31\xe5\x40\x7b" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\xdf\x10\x13\x24\x15\xe5\x4b\x92\xa1\x3e\xd0\xa8\x26\x7a\xe2\xf9" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x75\xa3\x85\x74\x1a\xb9\xce\xf8\x20\x31\x62\x3d\x55\xb1\xe4\x71" } + } + } + }; + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + int i, j, keylen, blklen; + gcry_error_t err = 0; + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CFB, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CFB, 0); + if (err) + { + fail ("aes-cfb, grcy_open_cipher failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("aes-cfb, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("aes-cfb, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + blklen = gcry_cipher_get_algo_blklen(tv[i].algo); + if (!blklen) + { + fail ("aes-cfb, gcry_cipher_get_algo_blklen failed\n"); + return; + } + + err = gcry_cipher_setiv (hde, tv[i].iv, blklen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, blklen); + if (err) + { + fail ("aes-cfb, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + for (j = 0; tv[i].data[j].inlen; j++) + { + err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, + tv[i].data[j].plaintext, + tv[i].data[j].inlen); + if (err) + { + fail ("aes-cfb, gcry_cipher_encrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen)) { + fail ("aes-cfb, encrypt mismatch entry %d:%d\n", i, j); + } + err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0); + if (err) + { + fail ("aes-cfb, gcry_cipher_decrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen)) + fail ("aes-cfb, decrypt mismatch entry %d:%d\n", i, j); + } + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } +} + +static void +check_ofb_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char iv[MAX_DATA_LEN]; + struct data + { + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + } + data[MAX_DATA_LEN]; + } tv[] = + { + /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ + { GCRY_CIPHER_AES, + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x77\x89\x50\x8d\x16\x91\x8f\x03\xf5\x3c\x52\xda\xc5\x4e\xd8\x25"}, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x97\x40\x05\x1e\x9c\x5f\xec\xf6\x43\x44\xf7\xa8\x22\x60\xed\xcc" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x30\x4c\x65\x28\xf6\x59\xc7\x78\x66\xa5\x10\xd9\xc1\xd6\xae\x5e" }, + } + }, + { GCRY_CIPHER_AES192, + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b" + "\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab\x34\xc2\x59\x09\xc9\x9a\x41\x74" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\xfc\xc2\x8b\x8d\x4c\x63\x83\x7c\x09\xe8\x17\x00\xc1\x10\x04\x01" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x8d\x9a\x9a\xea\xc0\xf6\x59\x6f\x55\x9c\x6d\x4d\xaf\x59\xa5\xf2" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x6d\x9f\x20\x08\x57\xca\x6c\x3e\x9c\xac\x52\x4b\xd9\xac\xc9\x2a" }, + } + }, + { GCRY_CIPHER_AES256, + "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + 16, + "\xdc\x7e\x84\xbf\xda\x79\x16\x4b\x7e\xcd\x84\x86\x98\x5d\x38\x60" }, + { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", + 16, + "\x4f\xeb\xdc\x67\x40\xd2\x0b\x3a\xc8\x8f\x6a\xd8\x2a\x4f\xb0\x8d" }, + { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", + 16, + "\x71\xab\x47\xa0\x86\xe8\x6e\xed\xf3\x9d\x1c\x5b\xba\x97\xc4\x08" }, + { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + 16, + "\x01\x26\x14\x1d\x67\xf3\x7b\xe8\x53\x8f\x5a\x8b\xe7\x40\xe4\x84" } + } + } + }; + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + int i, j, keylen, blklen; + gcry_error_t err = 0; + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_OFB, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_OFB, 0); + if (err) + { + fail ("aes-ofb, grcy_open_cipher failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("aes-ofb, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("aes-ofb, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + blklen = gcry_cipher_get_algo_blklen(tv[i].algo); + if (!blklen) + { + fail ("aes-ofb, gcry_cipher_get_algo_blklen failed\n"); + return; + } + + err = gcry_cipher_setiv (hde, tv[i].iv, blklen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, blklen); + if (err) + { + fail ("aes-ofb, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + for (j = 0; tv[i].data[j].inlen; j++) + { + err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, + tv[i].data[j].plaintext, + tv[i].data[j].inlen); + if (err) + { + fail ("aes-ofb, gcry_cipher_encrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen)) + fail ("aes-ofb, encrypt mismatch entry %d:%d\n", i, j); + + err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0); + if (err) + { + fail ("aes-ofb, gcry_cipher_decrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen)) + fail ("aes-ofb, decrypt mismatch entry %d:%d\n", i, j); + } + + err = gcry_cipher_reset(hde); + if (!err) + err = gcry_cipher_reset(hdd); + if (err) + { + fail ("aes-ofb, gcry_cipher_reset (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* gcry_cipher_reset clears the IV */ + err = gcry_cipher_setiv (hde, tv[i].iv, blklen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, blklen); + if (err) + { + fail ("aes-ofb, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* this time we encrypt and decrypt one byte at a time */ + for (j = 0; tv[i].data[j].inlen; j++) + { + int byteNum; + for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum) + { + err = gcry_cipher_encrypt (hde, out+byteNum, 1, + (tv[i].data[j].plaintext) + byteNum, + 1); + if (err) + { + fail ("aes-ofb, gcry_cipher_encrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen)) + fail ("aes-ofb, encrypt mismatch entry %d:%d\n", i, j); + + for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum) + { + err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0); + if (err) + { + fail ("aes-ofb, gcry_cipher_decrypt (%d, %d) failed: %s\n", + i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen)) + fail ("aes-ofb, decrypt mismatch entry %d:%d\n", i, j); + } + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } +} + +static void +check_one_cipher (int algo, int mode, int flags) +{ + gcry_cipher_hd_t hd; + char key[32]; + unsigned char plain[16], in[16], out[16]; + int keylen; + gcry_error_t err = 0; + + memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF", 32); + memcpy (plain, "foobar42FOOBAR17", 16); + + keylen = gcry_cipher_get_algo_keylen (algo); + if (!keylen) + { + fail ("algo %d, mode %d, gcry_cipher_get_algo_keylen failed\n", + algo, mode); + return; + } + + if (keylen < 40 / 8 || keylen > 32) + { + fail ("algo %d, mode %d, keylength problem (%d)\n", algo, mode, keylen); + return; + } + + err = gcry_cipher_open (&hd, algo, mode, flags); + if (err) + { + fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n", + algo, mode, gpg_strerror (err)); + return; + } + + err = gcry_cipher_setkey (hd, key, keylen); + if (err) + { + fail ("algo %d, mode %d, gcry_cipher_setkey failed: %s\n", + algo, mode, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + err = gcry_cipher_encrypt (hd, out, 16, plain, 16); + if (err) + { + fail ("algo %d, mode %d, gcry_cipher_encrypt failed: %s\n", + algo, mode, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + gcry_cipher_reset (hd); + + err = gcry_cipher_decrypt (hd, in, 16, out, 16); + if (err) + { + fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n", + algo, mode, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (memcmp (plain, in, 16)) + fail ("algo %d, mode %d, encrypt-decrypt mismatch\n", algo, mode); + + /* Again, using in-place encryption. */ + gcry_cipher_reset (hd); + + memcpy (out, plain, 16); + err = gcry_cipher_encrypt (hd, out, 16, NULL, 0); + if (err) + { + fail ("algo %d, mode %d, in-place, gcry_cipher_encrypt failed: %s\n", + algo, mode, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + gcry_cipher_reset (hd); + + err = gcry_cipher_decrypt (hd, out, 16, NULL, 0); + if (err) + { + fail ("algo %d, mode %d, in-place, gcry_cipher_decrypt failed: %s\n", + algo, mode, gpg_strerror (err)); + gcry_cipher_close (hd); + return; + } + + if (memcmp (plain, out, 16)) + fail ("algo %d, mode %d, in-place, encrypt-decrypt mismatch\n",algo, mode); + + + gcry_cipher_close (hd); + +} + + +static void +check_ciphers (void) +{ + static int algos[] = { +#if USE_BLOWFISH + GCRY_CIPHER_BLOWFISH, +#endif +#if USE_DES + GCRY_CIPHER_DES, + GCRY_CIPHER_3DES, +#endif +#if USE_CAST5 + GCRY_CIPHER_CAST5, +#endif +#if USE_AES + GCRY_CIPHER_AES, + GCRY_CIPHER_AES192, + GCRY_CIPHER_AES256, +#endif +#if USE_TWOFISH + GCRY_CIPHER_TWOFISH, + GCRY_CIPHER_TWOFISH128, +#endif +#if USE_SERPENT + GCRY_CIPHER_SERPENT128, + GCRY_CIPHER_SERPENT192, + GCRY_CIPHER_SERPENT256, +#endif +#if USE_RFC2268 + GCRY_CIPHER_RFC2268_40, +#endif +#if USE_SEED + GCRY_CIPHER_SEED, +#endif +#if USE_CAMELLIA + GCRY_CIPHER_CAMELLIA128, + GCRY_CIPHER_CAMELLIA192, + GCRY_CIPHER_CAMELLIA256, +#endif + 0 + }; + static int algos2[] = { +#if USE_ARCFOUR + GCRY_CIPHER_ARCFOUR, +#endif + 0 + }; + int i; + + if (verbose) + fprintf (stderr, "Starting Cipher checks.\n"); + for (i = 0; algos[i]; i++) + { + if (gcry_cipher_test_algo (algos[i]) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i]); + continue; + } + if (verbose) + fprintf (stderr, " checking %s [%i]\n", + gcry_cipher_algo_name (algos[i]), + gcry_cipher_map_name (gcry_cipher_algo_name (algos[i]))); + + check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_OFB, 0); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0); + } + + for (i = 0; algos2[i]; i++) + { + if (gcry_cipher_test_algo (algos[i]) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i]); + continue; + } + if (verbose) + fprintf (stderr, " checking `%s'\n", + gcry_cipher_algo_name (algos2[i])); + + check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0); + } + /* we have now run all cipher's selftests */ + + if (verbose) + fprintf (stderr, "Completed Cipher checks.\n"); + + /* TODO: add some extra encryption to test the higher level functions */ +} + + + +static void +check_one_md (int algo, const char *data, int len, const char *expect) +{ + gcry_md_hd_t hd, hd2; + unsigned char *p; + int mdlen; + int i; + gcry_error_t err = 0; + + err = gcry_md_open (&hd, algo, 0); + if (err) + { + fail ("algo %d, grcy_md_open failed: %s\n", algo, gpg_strerror (err)); + return; + } + + mdlen = gcry_md_get_algo_dlen (algo); + if (mdlen < 1 || mdlen > 500) + { + fail ("algo %d, grcy_md_get_algo_dlen failed: %d\n", algo, mdlen); + return; + } + + if (*data == '!' && !data[1]) + { /* hash one million times a "a" */ + char aaa[1000]; + + /* Write in odd size chunks so that we test the buffering. */ + memset (aaa, 'a', 1000); + for (i = 0; i < 1000; i++) + gcry_md_write (hd, aaa, 1000); + } + else + gcry_md_write (hd, data, len); + + err = gcry_md_copy (&hd2, hd); + if (err) + { + fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err)); + } + + gcry_md_close (hd); + + p = gcry_md_read (hd2, algo); + + if (memcmp (p, expect, mdlen)) + { + printf ("computed: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", p[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("algo %d, digest mismatch\n", algo); + } + + gcry_md_close (hd2); +} + + +static void +check_digests (void) +{ + static struct algos + { + int md; + const char *data; + const char *expect; + } algos[] = + { + { GCRY_MD_MD4, "", + "\x31\xD6\xCF\xE0\xD1\x6A\xE9\x31\xB7\x3C\x59\xD7\xE0\xC0\x89\xC0" }, + { GCRY_MD_MD4, "a", + "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24" }, + { GCRY_MD_MD4, "message digest", + "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b" }, + { GCRY_MD_MD5, "", + "\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\x09\x98\xEC\xF8\x42\x7E" }, + { GCRY_MD_MD5, "a", + "\x0C\xC1\x75\xB9\xC0\xF1\xB6\xA8\x31\xC3\x99\xE2\x69\x77\x26\x61" }, + { GCRY_MD_MD5, "abc", + "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72" }, + { GCRY_MD_MD5, "message digest", + "\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0" }, + { GCRY_MD_SHA1, "abc", + "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" + "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" }, + { GCRY_MD_SHA1, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE" + "\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1" }, + { GCRY_MD_SHA1, "!" /* kludge for "a"*1000000 */ , + "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" + "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" }, + /* From RFC3874 */ + { GCRY_MD_SHA224, "abc", + "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3" + "\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7" }, + { GCRY_MD_SHA224, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50" + "\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25" }, + { GCRY_MD_SHA224, "!", + "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" + "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" }, + { GCRY_MD_SHA256, "abc", + "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" + "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" }, + { GCRY_MD_SHA256, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" + "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" }, + { GCRY_MD_SHA256, "!", + "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" + "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" }, + { GCRY_MD_SHA384, "abc", + "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" + "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed" + "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7" }, + { GCRY_MD_SHA512, "abc", + "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" + "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" + "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD" + "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F" }, + { GCRY_MD_RMD160, "", + "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" + "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" }, + { GCRY_MD_RMD160, "a", + "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae" + "\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe" }, + { GCRY_MD_RMD160, "abc", + "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04" + "\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc" }, + { GCRY_MD_RMD160, "message digest", + "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8" + "\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" }, + { GCRY_MD_CRC32, "", "\x00\x00\x00\x00" }, + { GCRY_MD_CRC32, "foo", "\x8c\x73\x65\x21" }, + { GCRY_MD_CRC32_RFC1510, "", "\x00\x00\x00\x00" }, + { GCRY_MD_CRC32_RFC1510, "foo", "\x73\x32\xbc\x33" }, + { GCRY_MD_CRC32_RFC1510, "test0123456789", "\xb8\x3e\x88\xd6" }, + { GCRY_MD_CRC32_RFC1510, "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", + "\xe3\x41\x80\xf7" }, +#if 0 + { GCRY_MD_CRC32_RFC1510, "\x80\x00", "\x3b\x83\x98\x4b" }, + { GCRY_MD_CRC32_RFC1510, "\x00\x08", "\x0e\xdb\x88\x32" }, + { GCRY_MD_CRC32_RFC1510, "\x00\x80", "\xed\xb8\x83\x20" }, +#endif + { GCRY_MD_CRC32_RFC1510, "\x80", "\xed\xb8\x83\x20" }, +#if 0 + { GCRY_MD_CRC32_RFC1510, "\x80\x00\x00\x00", "\xed\x59\xb6\x3b" }, + { GCRY_MD_CRC32_RFC1510, "\x00\x00\x00\x01", "\x77\x07\x30\x96" }, +#endif + { GCRY_MD_CRC24_RFC2440, "", "\xb7\x04\xce" }, + { GCRY_MD_CRC24_RFC2440, "foo", "\x4f\xc2\x55" }, + { GCRY_MD_TIGER, "", + "\x24\xF0\x13\x0C\x63\xAC\x93\x32\x16\x16\x6E\x76" + "\xB1\xBB\x92\x5F\xF3\x73\xDE\x2D\x49\x58\x4E\x7A" }, + { GCRY_MD_TIGER, "abc", + "\xF2\x58\xC1\xE8\x84\x14\xAB\x2A\x52\x7A\xB5\x41" + "\xFF\xC5\xB8\xBF\x93\x5F\x7B\x95\x1C\x13\x29\x51" }, + { GCRY_MD_TIGER, "Tiger", + "\x9F\x00\xF5\x99\x07\x23\x00\xDD\x27\x6A\xBB\x38" + "\xC8\xEB\x6D\xEC\x37\x79\x0C\x11\x6F\x9D\x2B\xDF" }, + { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg" + "hijklmnopqrstuvwxyz0123456789+-", + "\x87\xFB\x2A\x90\x83\x85\x1C\xF7\x47\x0D\x2C\xF8" + "\x10\xE6\xDF\x9E\xB5\x86\x44\x50\x34\xA5\xA3\x86" }, + { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdef" + "ghijklmnopqrstuvwxyz+0123456789", + "\x46\x7D\xB8\x08\x63\xEB\xCE\x48\x8D\xF1\xCD\x12" + "\x61\x65\x5D\xE9\x57\x89\x65\x65\x97\x5F\x91\x97" }, + { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham", + "\x0C\x41\x0A\x04\x29\x68\x86\x8A\x16\x71\xDA\x5A" + "\x3F\xD2\x9A\x72\x5E\xC1\xE4\x57\xD3\xCD\xB3\x03" }, + { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham, proceedings of Fa" + "st Software Encryption 3, Cambridge.", + "\xEB\xF5\x91\xD5\xAF\xA6\x55\xCE\x7F\x22\x89\x4F" + "\xF8\x7F\x54\xAC\x89\xC8\x11\xB6\xB0\xDA\x31\x93" }, + { GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham, proceedings of Fa" + "st Software Encryption 3, Cambridge, 1996.", + "\x3D\x9A\xEB\x03\xD1\xBD\x1A\x63\x57\xB2\x77\x4D" + "\xFD\x6D\x5B\x24\xDD\x68\x15\x1D\x50\x39\x74\xFC" }, + { GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh" + "ijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRS" + "TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + "\x00\xB8\x3E\xB4\xE5\x34\x40\xC5\x76\xAC\x6A\xAE" + "\xE0\xA7\x48\x58\x25\xFD\x15\xE7\x0A\x59\xFF\xE4" }, + { GCRY_MD_WHIRLPOOL, "", + "\x19\xFA\x61\xD7\x55\x22\xA4\x66\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" + "\xC5\x30\x23\x21\x30\xD4\x07\xF8\x9A\xFE\xE0\x96\x49\x97\xF7\xA7" + "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB\xCF\x88\xE3\xE0\x3C\x4F\x07\x57" + "\xEA\x89\x64\xE5\x9B\x63\xD9\x37\x08\xB1\x38\xCC\x42\xA6\x6E\xB3" }, + { GCRY_MD_WHIRLPOOL, "a", + "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F\x11\xA6\x72\x06\x53\x1F\xB7\xD7" + "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" + "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" + "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, + { GCRY_MD_WHIRLPOOL, "a", + "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F\x11\xA6\x72\x06\x53\x1F\xB7\xD7" + "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" + "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" + "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, + { GCRY_MD_WHIRLPOOL, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B\xF1\x1F\x00\xED\x9A\xBA\x26\x90" + "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E" + "\x08\xEB\xA2\x66\x29\x12\x9D\x8F\xB7\xCB\x57\x21\x1B\x92\x81\xA6" + "\x55\x17\xCC\x87\x9D\x7B\x96\x21\x42\xC6\x5F\x5A\x7A\xF0\x14\x67" }, + { GCRY_MD_WHIRLPOOL, + "!", + "\x0C\x99\x00\x5B\xEB\x57\xEF\xF5\x0A\x7C\xF0\x05\x56\x0D\xDF\x5D" + "\x29\x05\x7F\xD8\x6B\x20\xBF\xD6\x2D\xEC\xA0\xF1\xCC\xEA\x4A\xF5" + "\x1F\xC1\x54\x90\xED\xDC\x47\xAF\x32\xBB\x2B\x66\xC3\x4F\xF9\xAD" + "\x8C\x60\x08\xAD\x67\x7F\x77\x12\x69\x53\xB2\x26\xE4\xED\x8B\x01" }, + { 0 }, + }; + int i; + + if (verbose) + fprintf (stderr, "Starting hash checks.\n"); + + for (i = 0; algos[i].md; i++) + { + if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5) + && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i].md); + continue; + } + if (verbose) + fprintf (stderr, " checking %s [%i] for length %zi\n", + gcry_md_algo_name (algos[i].md), + algos[i].md, + !strcmp (algos[i].data, "!")? + 1000000 : strlen(algos[i].data)); + + check_one_md (algos[i].md, algos[i].data, strlen (algos[i].data), + algos[i].expect); + } + + if (verbose) + fprintf (stderr, "Completed hash checks.\n"); +} + +static void +check_one_hmac (int algo, const char *data, int datalen, + const char *key, int keylen, const char *expect) +{ + gcry_md_hd_t hd, hd2; + unsigned char *p; + int mdlen; + int i; + gcry_error_t err = 0; + + err = gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC); + if (err) + { + fail ("algo %d, grcy_md_open failed: %s\n", algo, gpg_strerror (err)); + return; + } + + mdlen = gcry_md_get_algo_dlen (algo); + if (mdlen < 1 || mdlen > 500) + { + fail ("algo %d, grcy_md_get_algo_dlen failed: %d\n", algo, mdlen); + return; + } + + gcry_md_setkey( hd, key, keylen ); + + gcry_md_write (hd, data, datalen); + + err = gcry_md_copy (&hd2, hd); + if (err) + { + fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err)); + } + + gcry_md_close (hd); + + p = gcry_md_read (hd2, algo); + if (!p) + fail("algo %d, hmac gcry_md_read failed\n", algo); + + if (memcmp (p, expect, mdlen)) + { + printf ("computed: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", p[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("algo %d, digest mismatch\n", algo); + } + + gcry_md_close (hd2); +} + +static void +check_hmac (void) +{ + static struct algos + { + int md; + const char *data; + const char *key; + const char *expect; + } algos[] = + { + { GCRY_MD_MD5, "what do ya want for nothing?", "Jefe", + "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" }, + { GCRY_MD_MD5, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" }, + { GCRY_MD_MD5, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", + "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" }, + { GCRY_MD_MD5, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" }, + { GCRY_MD_MD5, "Test With Truncation", + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" }, + { GCRY_MD_MD5, "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa", + "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" }, + { GCRY_MD_MD5, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa", + "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", }, + { GCRY_MD_SHA256, "what do ya want for nothing?", "Jefe", + "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a" + "\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" }, + { GCRY_MD_SHA256, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88" + "\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" }, + { GCRY_MD_SHA256, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA", + "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7" + "\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" }, + { GCRY_MD_SHA256, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08" + "\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" }, + { GCRY_MD_SHA256, + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f" + "\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" }, + { GCRY_MD_SHA256, + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44" + "\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" }, + { GCRY_MD_SHA224, "what do ya want for nothing?", "Jefe", + "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" }, + { GCRY_MD_SHA224, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47" + "\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" }, + { GCRY_MD_SHA224, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA", + "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64" + "\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" }, + { GCRY_MD_SHA224, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62" + "\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" }, + { GCRY_MD_SHA224, + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" + "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" }, + { GCRY_MD_SHA224, + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" + "\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" }, + { GCRY_MD_SHA384, "what do ya want for nothing?", "Jefe", + "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" }, + { GCRY_MD_SHA384, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15" + "\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea" + "\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" }, + { GCRY_MD_SHA384, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA", + "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f" + "\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b" + "\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" }, + { GCRY_MD_SHA384, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7" + "\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e" + "\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" }, + { GCRY_MD_SHA384, + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" + "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" + "\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" }, + { GCRY_MD_SHA384, + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" + "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5" + "\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" }, + { GCRY_MD_SHA512, "what do ya want for nothing?", "Jefe", + "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" }, + { GCRY_MD_SHA512, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0" + "\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" + "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" + "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" }, + { GCRY_MD_SHA512, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA", + "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9" + "\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39" + "\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07" + "\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" }, + { GCRY_MD_SHA512, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7" + "\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb" + "\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63" + "\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" }, + { GCRY_MD_SHA512, + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4" + "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52" + "\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" + "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" }, + { GCRY_MD_SHA512, + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd" + "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" + "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" + "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + { 0 }, + }; + int i; + + if (verbose) + fprintf (stderr, "Starting hashed MAC checks.\n"); + + for (i = 0; algos[i].md; i++) + { + if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5) + && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i].md); + continue; + } + if (verbose) + fprintf (stderr, + " checking %s [%i] for %zi byte key and %zi byte data\n", + gcry_md_algo_name (algos[i].md), + algos[i].md, + strlen(algos[i].key), strlen(algos[i].data)); + + check_one_hmac (algos[i].md, algos[i].data, strlen (algos[i].data), + algos[i].key, strlen(algos[i].key), + algos[i].expect); + } + + if (verbose) + fprintf (stderr, "Completed hashed MAC checks.\n"); + } + +/* Check that the signature SIG matches the hash HASH. PKEY is the + public key used for the verification. BADHASH is a hasvalue which + should; result in a bad signature status. */ +static void +verify_one_signature (gcry_sexp_t pkey, gcry_sexp_t hash, + gcry_sexp_t badhash, gcry_sexp_t sig) +{ + gcry_error_t rc; + + rc = gcry_pk_verify (sig, hash, pkey); + if (rc) + fail ("gcry_pk_verify failed: %s\n", gpg_strerror (rc)); + rc = gcry_pk_verify (sig, badhash, pkey); + if (gcry_err_code (rc) != GPG_ERR_BAD_SIGNATURE) + fail ("gcry_pk_verify failed to detect a bad signature: %s\n", + gpg_strerror (rc)); +} + + +/* Test the public key sign function using the private ket SKEY. PKEY + is used for verification. */ +static void +check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey) +{ + gcry_error_t rc; + gcry_sexp_t sig, badhash, hash; + int dataidx; + static const char baddata[] = + "(data\n (flags pkcs1)\n" + " (hash sha1 #11223344556677889900AABBCCDDEEFF10203041#))\n"; + static struct + { + const char *data; + int expected_rc; + } datas[] = + { + { "(data\n (flags pkcs1)\n" + " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n", + 0 }, + /* This test is to see whether hash algorithms not hard wired in + pubkey.c are detected: */ + { "(data\n (flags pkcs1)\n" + " (hash oid.1.3.14.3.2.29 " + " #11223344556677889900AABBCCDDEEFF10203040#))\n", + 0 }, + { "(data\n (flags )\n" + " (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n", + GPG_ERR_CONFLICT }, + { "(data\n (flags pkcs1)\n" + " (hash foo #11223344556677889900AABBCCDDEEFF10203040#))\n", + GPG_ERR_DIGEST_ALGO }, + { "(data\n (flags )\n" " (value #11223344556677889900AA#))\n", + 0 }, + { "(data\n (flags )\n" " (value #0090223344556677889900AA#))\n", + 0 }, + { "(data\n (flags raw)\n" " (value #11223344556677889900AA#))\n", + 0 }, + { "(data\n (flags pkcs1)\n" + " (value #11223344556677889900AA#))\n", + GPG_ERR_CONFLICT }, + { "(data\n (flags raw foo)\n" + " (value #11223344556677889900AA#))\n", + GPG_ERR_INV_FLAG }, + { NULL } + }; + + (void)n; + + rc = gcry_sexp_sscan (&badhash, NULL, baddata, strlen (baddata)); + if (rc) + die ("converting data failed: %s\n", gpg_strerror (rc)); + + for (dataidx = 0; datas[dataidx].data; dataidx++) + { + if (verbose) + fprintf (stderr, " signature test %d\n", dataidx); + + rc = gcry_sexp_sscan (&hash, NULL, datas[dataidx].data, + strlen (datas[dataidx].data)); + if (rc) + die ("converting data failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_sign (&sig, hash, skey); + if (gcry_err_code (rc) != datas[dataidx].expected_rc) + fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc)); + + if (!rc) + verify_one_signature (pkey, hash, badhash, sig); + + gcry_sexp_release (sig); + sig = NULL; + gcry_sexp_release (hash); + hash = NULL; + } + + gcry_sexp_release (badhash); +} + +static void +check_pubkey_grip (int n, const unsigned char *grip, + gcry_sexp_t skey, gcry_sexp_t pkey) +{ + unsigned char sgrip[20], pgrip[20]; + + if (!gcry_pk_get_keygrip (skey, sgrip)) + die ("get keygrip for private RSA key failed\n"); + if (!gcry_pk_get_keygrip (pkey, pgrip)) + die ("[%i] get keygrip for public RSA key failed\n", n); + if (memcmp (sgrip, pgrip, 20)) + fail ("[%i] keygrips don't match\n", n); + if (memcmp (sgrip, grip, 20)) + fail ("wrong keygrip for RSA key\n"); +} + +static void +do_check_one_pubkey (int n, gcry_sexp_t skey, gcry_sexp_t pkey, + const unsigned char *grip, int flags) +{ + if (flags & FLAG_SIGN) + check_pubkey_sign (n, skey, pkey); + if (grip && (flags & FLAG_GRIP)) + check_pubkey_grip (n, grip, skey, pkey); +} + +static void +check_one_pubkey (int n, test_spec_pubkey_t spec) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_sexp_t skey, pkey; + + err = gcry_sexp_sscan (&skey, NULL, spec.key.secret, + strlen (spec.key.secret)); + if (!err) + err = gcry_sexp_sscan (&pkey, NULL, spec.key.public, + strlen (spec.key.public)); + if (err) + die ("converting sample key failed: %s\n", gpg_strerror (err)); + + do_check_one_pubkey (n, skey, pkey, + (const unsigned char*)spec.key.grip, spec.flags); + + gcry_sexp_release (skey); + gcry_sexp_release (pkey); +} + +static void +get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + if (verbose) + fprintf (stderr, " generating RSA key:"); + rc = gcry_sexp_new (&key_spec, + in_fips_mode ? "(genkey (rsa (nbits 4:1024)))" + : "(genkey (rsa (nbits 4:1024)(transient-key)))", + 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating RSA key: %s\n", gpg_strerror (rc)); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (! pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (! sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + +static void +check_one_pubkey_new (int n) +{ + gcry_sexp_t skey, pkey; + + get_keys_new (&pkey, &skey); + do_check_one_pubkey (n, skey, pkey, NULL, FLAG_SIGN | FLAG_CRYPT); +} + +/* Run all tests for the public key functions. */ +static void +check_pubkey (void) +{ + test_spec_pubkey_t pubkeys[] = + { + { + GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN, + + { "(private-key\n" + " (rsa\n" + " (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + " 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + " ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + " 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" + " (e #010001#)\n" + " (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + " 7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + " C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + " C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" + " (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" + " fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" + " (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" + " 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n" + " (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" + " ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))\n", + + "(public-key\n" + " (rsa\n" + " (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + " 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + " ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + " 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" + " (e #010001#)))\n", + + "\x32\x10\x0c\x27\x17\x3e\xf6\xe9\xc4\xe9" + "\xa2\x5d\x3d\x69\xf8\x6d\x37\xa4\xf9\x39"} + }, + { + GCRY_PK_DSA, FLAG_SIGN, + + { "(private-key\n" + " (DSA\n" + " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" + " 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" + " CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" + " 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)\n" + " (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)\n" + " (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" + " AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" + " B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" + " 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)\n" + " (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" + " A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" + " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" + " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)\n" + " (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))\n", + + "(public-key\n" + " (DSA\n" + " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" + " 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" + " CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" + " 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)\n" + " (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)\n" + " (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" + " AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" + " B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" + " 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)\n" + " (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" + " A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" + " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" + " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))\n", + + "\xc6\x39\x83\x1a\x43\xe5\x05\x5d\xc6\xd8" + "\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" } + }, + { + GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT, + + { "(private-key\n" + " (ELG\n" + " (p #00B93B93386375F06C2D38560F3B9C6D6D7B7506B20C1773F73F8DE56E6CD65D" + " F48DFAAA1E93F57A2789B168362A0F787320499F0B2461D3A4268757A7B27517" + " B7D203654A0CD484DEC6AF60C85FEB84AAC382EAF2047061FE5DAB81A20A0797" + " 6E87359889BAE3B3600ED718BE61D4FC993CC8098A703DD0DC942E965E8F18D2A7#)\n" + " (g #05#)\n" + " (y #72DAB3E83C9F7DD9A931FDECDC6522C0D36A6F0A0FEC955C5AC3C09175BBFF2B" + " E588DB593DC2E420201BEB3AC17536918417C497AC0F8657855380C1FCF11C5B" + " D20DB4BEE9BDF916648DE6D6E419FA446C513AAB81C30CB7B34D6007637BE675" + " 56CE6473E9F9EE9B9FADD275D001563336F2186F424DEC6199A0F758F6A00FF4#)\n" + " (x #03C28900087B38DABF4A0AB98ACEA39BB674D6557096C01D72E31C16BDD32214#)))\n", + + "(public-key\n" + " (ELG\n" + " (p #00B93B93386375F06C2D38560F3B9C6D6D7B7506B20C1773F73F8DE56E6CD65D" + " F48DFAAA1E93F57A2789B168362A0F787320499F0B2461D3A4268757A7B27517" + " B7D203654A0CD484DEC6AF60C85FEB84AAC382EAF2047061FE5DAB81A20A0797" + " 6E87359889BAE3B3600ED718BE61D4FC993CC8098A703DD0DC942E965E8F18D2A7#)\n" + " (g #05#)\n" + " (y #72DAB3E83C9F7DD9A931FDECDC6522C0D36A6F0A0FEC955C5AC3C09175BBFF2B" + " E588DB593DC2E420201BEB3AC17536918417C497AC0F8657855380C1FCF11C5B" + " D20DB4BEE9BDF916648DE6D6E419FA446C513AAB81C30CB7B34D6007637BE675" + " 56CE6473E9F9EE9B9FADD275D001563336F2186F424DEC6199A0F758F6A00FF4#)))\n", + + "\xa7\x99\x61\xeb\x88\x83\xd2\xf4\x05\xc8" + "\x4f\xba\x06\xf8\x78\x09\xbc\x1e\x20\xe5" } + }, + }; + int i; + if (verbose) + fprintf (stderr, "Starting public key checks.\n"); + for (i = 0; i < sizeof (pubkeys) / sizeof (*pubkeys); i++) + if (pubkeys[i].id) + { + if (gcry_pk_test_algo (pubkeys[i].id) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + pubkeys[i].id); + continue; + } + check_one_pubkey (i, pubkeys[i]); + } + if (verbose) + fprintf (stderr, "Completed public key checks.\n"); + + if (verbose) + fprintf (stderr, "Starting additional public key checks.\n"); + for (i = 0; i < sizeof (pubkeys) / sizeof (*pubkeys); i++) + if (pubkeys[i].id) + { + if (gcry_pk_test_algo (pubkeys[i].id) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + pubkeys[i].id); + continue; + } + check_one_pubkey_new (i); + } + if (verbose) + fprintf (stderr, "Completed additional public key checks.\n"); + +} + +int +main (int argc, char **argv) +{ + gpg_error_t err; + int last_argc = -1; + int debug = 0; + int use_fips = 0; + int selftest_only = 0; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--fips")) + { + use_fips = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--selftest")) + { + selftest_only = 1; + verbose += 2; + argc--; argv++; + } + } + + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + + if (use_fips) + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + if ( gcry_fips_mode_active () ) + in_fips_mode = 1; + + if (!in_fips_mode) + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + if (verbose) + gcry_set_progress_handler (progress_handler, NULL); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + if (!selftest_only) + { + check_ciphers (); + check_aes128_cbc_cts_cipher (); + check_cbc_mac_cipher (); + check_ctr_cipher (); + check_cfb_cipher (); + check_ofb_cipher (); + check_digests (); + check_hmac (); + check_pubkey (); + } + + + if (in_fips_mode && !selftest_only) + { + /* If we are in fips mode do some more tests. */ + gcry_md_hd_t md; + + /* First trigger a self-test. */ + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) + fail ("not in operational state after self-test\n"); + + /* Get us into the error state. */ + err = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (err) + fail ("failed to open SHA-1 hash context: %s\n", gpg_strerror (err)); + else + { + err = gcry_md_enable (md, GCRY_MD_SHA256); + if (err) + fail ("failed to add SHA-256 hash context: %s\n", + gpg_strerror (err)); + else + { + /* gcry_md_get_algo is only defined for a context with + just one digest algorithm. With our setup it should + put the oibrary intoerror state. */ + fputs ("Note: Two lines with error messages follow " + "- this is expected\n", stderr); + gcry_md_get_algo (md); + gcry_md_close (md); + if (gcry_control (GCRYCTL_OPERATIONAL_P, 0)) + fail ("expected error state but still in operational state\n"); + else + { + /* Now run a self-test and to get back into + operational state. */ + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) + fail ("did not reach operational after error " + "and self-test\n"); + } + } + } + + } + else + { + /* If in standard mode, run selftests. */ + if (gcry_control (GCRYCTL_SELFTEST, 0)) + fail ("running self-test failed\n"); + } + + if (verbose) + fprintf (stderr, "\nAll tests completed. Errors: %i\n", error_count); + + if (in_fips_mode && !gcry_fips_mode_active ()) + fprintf (stderr, "FIPS mode is not anymore active\n"); + + return error_count ? 1 : 0; +} diff --git a/tests/benchmark.c b/tests/benchmark.c new file mode 100644 index 0000000..8f8f04c --- /dev/null +++ b/tests/benchmark.c @@ -0,0 +1,1158 @@ +/* benchmark.c - for libgcrypt + * Copyright (C) 2002, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +#ifdef _GCRYPT_IN_LIBGCRYPT +# include "../src/gcrypt.h" +#else +# include +#endif + + +#define PGM "benchmark" + +static int verbose; + +/* Do encryption tests with large buffers. */ +static int large_buffers; + +/* Number of cipher repetitions. */ +static int cipher_repetitions; + +/* Whether fips mode was active at startup. */ +static int in_fips_mode; + + +static const char sample_private_dsa_key_1024[] = +"(private-key\n" +" (dsa\n" +" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685" + "03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A" + "853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF" + "C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n" +" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n" +" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622" + "B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312" + "FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3" + "85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n" +" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4" + "ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6" + "66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155" + "D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n" +" (x #4186F8A58C5DF46C5BCFC7006BEEBF05E93C0CA7#)\n" +"))\n"; + +static const char sample_public_dsa_key_1024[] = +"(public-key\n" +" (dsa\n" +" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685" + "03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A" + "853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF" + "C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n" +" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n" +" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622" + "B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312" + "FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3" + "85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n" +" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4" + "ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6" + "66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155" + "D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n" +"))\n"; + + +static const char sample_private_dsa_key_2048[] = +"(private-key\n" +" (dsa\n" +" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365" + "A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C" + "308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150" + "C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970" + "71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405" + "D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179" + "0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4" + "2F9C9F315ED409171EC35CA04CC06B275577B3#)\n" +" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n" +" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78" + "98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3" + "5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F" + "B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508" + "4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F" + "0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44" + "2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3" + "6EE4425A553AF8885FEA15A88135BE133520#)\n" +" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C" + "2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB" + "4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79" + "328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F" + "8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3" + "E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923" + "79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7" + "14A264330AECCB24DE2A1107847B23490897#)\n" +" (x #477BD14676E22563C5ABA68025CEBA2A48D485F5B2D4AD4C0EBBD6D0#)\n" +"))\n"; + + +static const char sample_public_dsa_key_2048[] = +"(public-key\n" +" (dsa\n" +" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365" + "A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C" + "308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150" + "C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970" + "71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405" + "D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179" + "0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4" + "2F9C9F315ED409171EC35CA04CC06B275577B3#)\n" +" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n" +" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78" + "98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3" + "5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F" + "B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508" + "4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F" + "0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44" + "2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3" + "6EE4425A553AF8885FEA15A88135BE133520#)\n" +" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C" + "2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB" + "4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79" + "328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F" + "8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3" + "E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923" + "79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7" + "14A264330AECCB24DE2A1107847B23490897#)\n" +"))\n"; + + +static const char sample_private_dsa_key_3072[] = +"(private-key\n" +" (dsa\n" +" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938" + "877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5" + "62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83" + "B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988" + "AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46" + "0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2" + "AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902" + "D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60" + "B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E" + "95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7" + "62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33" + "8015353D3778B02B892AF7#)\n" +" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n" +" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4" + "DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474" + "7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98" + "9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC" + "134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C" + "7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89" + "F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB" + "120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6" + "374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0" + "21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F" + "D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC" + "4997AF9EB55C6660B01A#)\n" +" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE" + "4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053" + "A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492" + "8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15" + "DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71" + "CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997" + "437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026" + "73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B" + "FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD" + "F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765" + "3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561" + "2703D518D8D49FF0EBE6#)\n" +" (x #00A9FFFC88E67D6F7B810E291C050BAFEA7FC4A75E8D2F16CFED3416FD77607232#)\n" +"))\n"; + +static const char sample_public_dsa_key_3072[] = +"(public-key\n" +" (dsa\n" +" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938" + "877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5" + "62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83" + "B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988" + "AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46" + "0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2" + "AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902" + "D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60" + "B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E" + "95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7" + "62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33" + "8015353D3778B02B892AF7#)\n" +" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n" +" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4" + "DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474" + "7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98" + "9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC" + "134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C" + "7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89" + "F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB" + "120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6" + "374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0" + "21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F" + "D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC" + "4997AF9EB55C6660B01A#)\n" +" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE" + "4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053" + "A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492" + "8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15" + "DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71" + "CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997" + "437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026" + "73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B" + "FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD" + "F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765" + "3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561" + "2703D518D8D49FF0EBE6#)\n" +"))\n"; + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) +#define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\ + exit(2);} while(0) + + +/* Helper for the start and stop timer. */ +#ifdef _WIN32 +struct { + FILETIME creation_time, exit_time, kernel_time, user_time; +} started_at, stopped_at; +#else +static clock_t started_at, stopped_at; +#endif + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + putchar ('\n'); + fputs ( PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +static void +show_sexp (const char *prefix, gcry_sexp_t a) +{ + char *buf; + size_t size; + + fputs (prefix, stderr); + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = malloc (size); + if (!buf) + die ("out of core\n"); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); +} + + +static void +start_timer (void) +{ +#ifdef _WIN32 + GetProcessTimes (GetCurrentProcess (), + &started_at.creation_time, &started_at.exit_time, + &started_at.kernel_time, &started_at.user_time); + stopped_at = started_at; +#else + struct tms tmp; + + times (&tmp); + started_at = stopped_at = tmp.tms_utime; +#endif +} + +static void +stop_timer (void) +{ +#ifdef _WIN32 + GetProcessTimes (GetCurrentProcess (), + &stopped_at.creation_time, &stopped_at.exit_time, + &stopped_at.kernel_time, &stopped_at.user_time); +#else + struct tms tmp; + + times (&tmp); + stopped_at = tmp.tms_utime; +#endif +} + +static const char * +elapsed_time (void) +{ + static char buf[50]; +#if _WIN32 + unsigned long long t1, t2, t; + + t1 = (((unsigned long long)started_at.kernel_time.dwHighDateTime << 32) + + started_at.kernel_time.dwLowDateTime); + t1 += (((unsigned long long)started_at.user_time.dwHighDateTime << 32) + + started_at.user_time.dwLowDateTime); + t2 = (((unsigned long long)stopped_at.kernel_time.dwHighDateTime << 32) + + stopped_at.kernel_time.dwLowDateTime); + t2 += (((unsigned long long)stopped_at.user_time.dwHighDateTime << 32) + + stopped_at.user_time.dwLowDateTime); + t = (t2 - t1)/10000; + snprintf (buf, sizeof buf, "%5.0fms", (double)t ); +#else + snprintf (buf, sizeof buf, "%5.0fms", + (((double) (stopped_at - started_at))/CLOCKS_PER_SEC)*10000000); +#endif + return buf; +} + + +static void +random_bench (int very_strong) +{ + char buf[128]; + int i; + + printf ("%-10s", "random"); + + if (!very_strong) + { + start_timer (); + for (i=0; i < 100; i++) + gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM); + stop_timer (); + printf (" %s", elapsed_time ()); + } + + start_timer (); + for (i=0; i < 100; i++) + gcry_randomize (buf, 8, + very_strong? GCRY_VERY_STRONG_RANDOM:GCRY_STRONG_RANDOM); + stop_timer (); + printf (" %s", elapsed_time ()); + + putchar ('\n'); + if (verbose) + gcry_control (GCRYCTL_DUMP_RANDOM_STATS); +} + + + +static void +md_bench ( const char *algoname ) +{ + int algo; + gcry_md_hd_t hd; + int i; + char buf[1000]; + gcry_error_t err = GPG_ERR_NO_ERROR; + + if (!algoname) + { + for (i=1; i < 400; i++) + if (in_fips_mode && i == GCRY_MD_MD5) + ; /* Don't use MD5 in fips mode. */ + else if ( !gcry_md_test_algo (i) ) + md_bench (gcry_md_algo_name (i)); + return; + } + + algo = gcry_md_map_name (algoname); + if (!algo) + { + fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); + exit (1); + } + + err = gcry_md_open (&hd, algo, 0); + if (err) + { + fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); + exit (1); + } + + for (i=0; i < sizeof buf; i++) + buf[i] = i; + + printf ("%-12s", gcry_md_algo_name (algo)); + + start_timer (); + for (i=0; i < 1000; i++) + gcry_md_write (hd, buf, sizeof buf); + gcry_md_final (hd); + stop_timer (); + printf (" %s", elapsed_time ()); + + gcry_md_reset (hd); + start_timer (); + for (i=0; i < 10000; i++) + gcry_md_write (hd, buf, sizeof buf/10); + gcry_md_final (hd); + stop_timer (); + printf (" %s", elapsed_time ()); + + gcry_md_reset (hd); + start_timer (); + for (i=0; i < 1000000; i++) + gcry_md_write (hd, "", 1); + gcry_md_final (hd); + stop_timer (); + printf (" %s", elapsed_time ()); + + gcry_md_close (hd); + putchar ('\n'); +} + +static void +cipher_bench ( const char *algoname ) +{ + static int header_printed; + int algo; + gcry_cipher_hd_t hd; + int i; + int keylen, blklen; + char key[128]; + char *outbuf, *buf; + size_t allocated_buflen, buflen; + int repetitions; + static struct { int mode; const char *name; int blocked; } modes[] = { + { GCRY_CIPHER_MODE_ECB, "ECB", 1 }, + { GCRY_CIPHER_MODE_CBC, "CBC", 1 }, + { GCRY_CIPHER_MODE_CFB, "CFB", 0 }, + { GCRY_CIPHER_MODE_OFB, "OFB", 0 }, + { GCRY_CIPHER_MODE_CTR, "CTR", 0 }, + { GCRY_CIPHER_MODE_STREAM, "STREAM", 0 }, + {0} + }; + int modeidx; + gcry_error_t err = GPG_ERR_NO_ERROR; + + + if (!algoname) + { + for (i=1; i < 400; i++) + if ( !gcry_cipher_test_algo (i) ) + cipher_bench (gcry_cipher_algo_name (i)); + return; + } + + if (large_buffers) + { + allocated_buflen = 1024 * 100; + repetitions = 10; + } + else + { + allocated_buflen = 1024; + repetitions = 1000; + } + repetitions *= cipher_repetitions; + + buf = gcry_xmalloc (allocated_buflen); + outbuf = gcry_xmalloc (allocated_buflen); + + if (!header_printed) + { + if (cipher_repetitions != 1) + printf ("Running each test %d times.\n", cipher_repetitions); + printf ("%-12s", ""); + for (modeidx=0; modes[modeidx].mode; modeidx++) + printf (" %-15s", modes[modeidx].name ); + putchar ('\n'); + printf ("%-12s", ""); + for (modeidx=0; modes[modeidx].mode; modeidx++) + printf (" ---------------" ); + putchar ('\n'); + header_printed = 1; + } + + algo = gcry_cipher_map_name (algoname); + if (!algo) + { + fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); + exit (1); + } + + keylen = gcry_cipher_get_algo_keylen (algo); + if (!keylen) + { + fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", + algoname); + exit (1); + } + if ( keylen > sizeof key ) + { + fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", + algo, keylen ); + exit (1); + } + for (i=0; i < keylen; i++) + key[i] = i + (clock () & 0xff); + + blklen = gcry_cipher_get_algo_blklen (algo); + if (!blklen) + { + fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", + algoname); + exit (1); + } + + printf ("%-12s", gcry_cipher_algo_name (algo)); + fflush (stdout); + + for (modeidx=0; modes[modeidx].mode; modeidx++) + { + if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM) + | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM)) + { + printf (" " ); + continue; + } + + for (i=0; i < sizeof buf; i++) + buf[i] = i; + + err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); + if (err) + { + fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); + exit (1); + } + + err = gcry_cipher_setkey (hd, key, keylen); + if (err) + { + fprintf (stderr, "gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + buflen = allocated_buflen; + if (modes[modeidx].blocked) + buflen = (buflen / blklen) * blklen; + + start_timer (); + for (i=err=0; !err && i < repetitions; i++) + err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen); + stop_timer (); + + printf (" %s", elapsed_time ()); + fflush (stdout); + gcry_cipher_close (hd); + if (err) + { + fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err) ); + exit (1); + } + + err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); + if (err) + { + fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); + exit (1); + } + + err = gcry_cipher_setkey (hd, key, keylen); + if (err) + { + fprintf (stderr, "gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + start_timer (); + for (i=err=0; !err && i < repetitions; i++) + err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + gcry_cipher_close (hd); + if (err) + { + fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", + gpg_strerror (err) ); + exit (1); + } + } + + putchar ('\n'); + gcry_free (buf); + gcry_free (outbuf); +} + + + +static void +rsa_bench (int iterations, int print_header, int no_blinding) +{ + gpg_error_t err; + int p_sizes[] = { 1024, 2048, 3072, 4096 }; + int testno; + + if (print_header) + printf ("Algorithm generate %4d*sign %4d*verify\n" + "------------------------------------------------\n", + iterations, iterations ); + for (testno=0; testno < DIM (p_sizes); testno++) + { + gcry_sexp_t key_spec, key_pair, pub_key, sec_key; + gcry_mpi_t x; + gcry_sexp_t data; + gcry_sexp_t sig = NULL; + int count; + + printf ("RSA %3d bit ", p_sizes[testno]); + fflush (stdout); + + err = gcry_sexp_build (&key_spec, NULL, + gcry_fips_mode_active () + ? "(genkey (RSA (nbits %d)))" + : "(genkey (RSA (nbits %d)(transient-key)))", + p_sizes[testno]); + if (err) + die ("creating S-expression failed: %s\n", gcry_strerror (err)); + + start_timer (); + err = gcry_pk_genkey (&key_pair, key_spec); + if (err) + die ("creating %d bit RSA key failed: %s\n", + p_sizes[testno], gcry_strerror (err)); + + pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); + if (! pub_key) + die ("public part missing in key\n"); + sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); + if (! sec_key) + die ("private part missing in key\n"); + gcry_sexp_release (key_pair); + gcry_sexp_release (key_spec); + + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + x = gcry_mpi_new (p_sizes[testno]); + gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); + err = gcry_sexp_build (&data, NULL, + "(data (flags raw) (value %m))", x); + gcry_mpi_release (x); + if (err) + die ("converting data failed: %s\n", gcry_strerror (err)); + + start_timer (); + for (count=0; count < iterations; count++) + { + gcry_sexp_release (sig); + err = gcry_pk_sign (&sig, data, sec_key); + if (err) + die ("signing failed (%d): %s\n", count, gpg_strerror (err)); + } + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + start_timer (); + for (count=0; count < iterations; count++) + { + err = gcry_pk_verify (sig, data, pub_key); + if (err) + { + putchar ('\n'); + show_sexp ("seckey:\n", sec_key); + show_sexp ("data:\n", data); + show_sexp ("sig:\n", sig); + die ("verify failed (%d): %s\n", count, gpg_strerror (err)); + } + } + stop_timer (); + printf (" %s", elapsed_time ()); + + if (no_blinding) + { + fflush (stdout); + x = gcry_mpi_new (p_sizes[testno]); + gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); + err = gcry_sexp_build (&data, NULL, + "(data (flags no-blinding) (value %m))", x); + gcry_mpi_release (x); + if (err) + die ("converting data failed: %s\n", gcry_strerror (err)); + + start_timer (); + for (count=0; count < iterations; count++) + { + gcry_sexp_release (sig); + err = gcry_pk_sign (&sig, data, sec_key); + if (err) + die ("signing failed (%d): %s\n", count, gpg_strerror (err)); + } + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + } + + putchar ('\n'); + fflush (stdout); + + gcry_sexp_release (sig); + gcry_sexp_release (data); + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +} + + + +static void +dsa_bench (int iterations, int print_header) +{ + gpg_error_t err; + gcry_sexp_t pub_key[3], sec_key[3]; + int p_sizes[3] = { 1024, 2048, 3072 }; + int q_sizes[3] = { 160, 224, 256 }; + gcry_sexp_t data; + gcry_sexp_t sig; + int i, j; + + err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024, + strlen (sample_public_dsa_key_1024)); + if (!err) + err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024, + strlen (sample_private_dsa_key_1024)); + if (!err) + err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048, + strlen (sample_public_dsa_key_2048)); + if (!err) + err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048, + strlen (sample_private_dsa_key_2048)); + if (!err) + err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072, + strlen (sample_public_dsa_key_3072)); + if (!err) + err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072, + strlen (sample_private_dsa_key_3072)); + if (err) + { + fprintf (stderr, PGM ": converting sample keys failed: %s\n", + gcry_strerror (err)); + exit (1); + } + + if (print_header) + printf ("Algorithm generate %4d*sign %4d*verify\n" + "------------------------------------------------\n", + iterations, iterations ); + for (i=0; i < DIM (q_sizes); i++) + { + gcry_mpi_t x; + + x = gcry_mpi_new (q_sizes[i]); + gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM); + err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); + gcry_mpi_release (x); + if (err) + { + fprintf (stderr, PGM ": converting data failed: %s\n", + gcry_strerror (err)); + exit (1); + } + + printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]); + fflush (stdout); + + start_timer (); + for (j=0; j < iterations; j++) + { + err = gcry_pk_sign (&sig, data, sec_key[i]); + if (err) + { + putchar ('\n'); + fprintf (stderr, PGM ": signing failed: %s\n", + gpg_strerror (err)); + exit (1); + } + } + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + start_timer (); + for (j=0; j < iterations; j++) + { + err = gcry_pk_verify (sig, data, pub_key[i]); + if (err) + { + putchar ('\n'); + fprintf (stderr, PGM ": verify failed: %s\n", + gpg_strerror (err)); + exit (1); + } + } + stop_timer (); + printf (" %s\n", elapsed_time ()); + fflush (stdout); + + gcry_sexp_release (sig); + gcry_sexp_release (data); + } + + + for (i=0; i < DIM (q_sizes); i++) + { + gcry_sexp_release (sec_key[i]); + gcry_sexp_release (pub_key[i]); + } +} + + +static void +ecc_bench (int iterations, int print_header) +{ +#if USE_ECC + gpg_error_t err; + int p_sizes[] = { 192, 224, 256, 384, 521 }; + int testno; + + if (print_header) + printf ("Algorithm generate %4d*sign %4d*verify\n" + "------------------------------------------------\n", + iterations, iterations ); + for (testno=0; testno < DIM (p_sizes); testno++) + { + gcry_sexp_t key_spec, key_pair, pub_key, sec_key; + gcry_mpi_t x; + gcry_sexp_t data; + gcry_sexp_t sig = NULL; + int count; + + printf ("ECDSA %3d bit ", p_sizes[testno]); + fflush (stdout); + + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (ECDSA (nbits %d)))", p_sizes[testno]); + if (err) + die ("creating S-expression failed: %s\n", gcry_strerror (err)); + + start_timer (); + err = gcry_pk_genkey (&key_pair, key_spec); + if (err) + die ("creating %d bit ECC key failed: %s\n", + p_sizes[testno], gcry_strerror (err)); + + pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); + if (! pub_key) + die ("public part missing in key\n"); + sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); + if (! sec_key) + die ("private part missing in key\n"); + gcry_sexp_release (key_pair); + gcry_sexp_release (key_spec); + + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + x = gcry_mpi_new (p_sizes[testno]); + gcry_mpi_randomize (x, p_sizes[testno], GCRY_WEAK_RANDOM); + err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); + gcry_mpi_release (x); + if (err) + die ("converting data failed: %s\n", gcry_strerror (err)); + + start_timer (); + for (count=0; count < iterations; count++) + { + gcry_sexp_release (sig); + err = gcry_pk_sign (&sig, data, sec_key); + if (err) + die ("signing failed: %s\n", gpg_strerror (err)); + } + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + start_timer (); + for (count=0; count < iterations; count++) + { + err = gcry_pk_verify (sig, data, pub_key); + if (err) + { + putchar ('\n'); + show_sexp ("seckey:\n", sec_key); + show_sexp ("data:\n", data); + show_sexp ("sig:\n", sig); + die ("verify failed: %s\n", gpg_strerror (err)); + } + } + stop_timer (); + printf (" %s\n", elapsed_time ()); + fflush (stdout); + + gcry_sexp_release (sig); + gcry_sexp_release (data); + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +#endif /*USE_ECC*/ +} + + + +static void +do_powm ( const char *n_str, const char *e_str, const char *m_str) +{ + gcry_mpi_t e, n, msg, cip; + gcry_error_t err; + int i; + + err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0); + if (err) BUG (); + err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0); + if (err) BUG (); + err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0); + if (err) BUG (); + + cip = gcry_mpi_new (0); + + start_timer (); + for (i=0; i < 1000; i++) + gcry_mpi_powm (cip, msg, e, n); + stop_timer (); + printf (" %s", elapsed_time ()); fflush (stdout); +/* { */ +/* char *buf; */ + +/* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */ +/* BUG (); */ +/* printf ("result: %s\n", buf); */ +/* gcry_free (buf); */ +/* } */ + gcry_mpi_release (cip); + gcry_mpi_release (msg); + gcry_mpi_release (n); + gcry_mpi_release (e); +} + + +static void +mpi_bench (void) +{ + printf ("%-10s", "powm"); fflush (stdout); + + do_powm ( +"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E4", + "29", +"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8" + ); + do_powm ( + "20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716", + "29", + "B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847" + ); + do_powm ( + "20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA4071620A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716", + "29", + "B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847" + ); + + putchar ('\n'); + + +} + + +int +main( int argc, char **argv ) +{ + int last_argc = -1; + int no_blinding = 0; + int use_random_daemon = 0; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: benchmark " + "[md|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--use-random-daemon")) + { + use_random_daemon = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--no-blinding")) + { + no_blinding = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--large-buffers")) + { + large_buffers = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--cipher-repetition")) + { + argc--; argv++; + if (argc) + { + cipher_repetitions = atoi(*argv); + argc--; argv++; + } + } + else if (!strcmp (*argv, "--fips")) + { + argc--; argv++; + /* This command needs to be called before gcry_check_version. */ + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + } + } + + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + + if (!gcry_check_version (GCRYPT_VERSION)) + { + fprintf (stderr, PGM ": version mismatch\n"); + exit (1); + } + + if (gcry_fips_mode_active ()) + in_fips_mode = 1; + else + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + if (use_random_daemon) + gcry_control (GCRYCTL_USE_RANDOM_DAEMON, 1); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + + if (cipher_repetitions < 1) + cipher_repetitions = 1; + + if ( !argc ) + { + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + md_bench (NULL); + putchar ('\n'); + cipher_bench (NULL); + putchar ('\n'); + rsa_bench (100, 1, no_blinding); + dsa_bench (100, 0); + ecc_bench (100, 0); + putchar ('\n'); + mpi_bench (); + putchar ('\n'); + random_bench (0); + } + else if ( !strcmp (*argv, "random") || !strcmp (*argv, "strongrandom")) + { + if (argc == 1) + random_bench ((**argv == 's')); + else if (argc == 2) + { + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]); + random_bench ((**argv == 's')); + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); + } + else + fputs ("usage: benchmark [strong]random [seedfile]\n", stdout); + } + else if ( !strcmp (*argv, "md")) + { + if (argc == 1) + md_bench (NULL); + else + for (argc--, argv++; argc; argc--, argv++) + md_bench ( *argv ); + } + else if ( !strcmp (*argv, "cipher")) + { + if (argc == 1) + cipher_bench (NULL); + else + for (argc--, argv++; argc; argc--, argv++) + cipher_bench ( *argv ); + } + else if ( !strcmp (*argv, "mpi")) + { + mpi_bench (); + } + else if ( !strcmp (*argv, "rsa")) + { + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + rsa_bench (100, 1, no_blinding); + } + else if ( !strcmp (*argv, "dsa")) + { + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + dsa_bench (100, 1); + } + else if ( !strcmp (*argv, "ecc")) + { + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + ecc_bench (100, 1); + } + else + { + fprintf (stderr, PGM ": bad arguments\n"); + return 1; + } + + + if (in_fips_mode && !gcry_fips_mode_active ()) + fprintf (stderr, PGM ": FIPS mode is not anymore active\n"); + + return 0; +} + diff --git a/tests/cavs_driver.pl b/tests/cavs_driver.pl new file mode 100755 index 0000000..7111f0f --- /dev/null +++ b/tests/cavs_driver.pl @@ -0,0 +1,2243 @@ +#!/usr/bin/env perl +# +# $Id: cavs_driver.pl 1497 2009-01-22 14:01:29Z smueller $ +# +# CAVS test driver (based on the OpenSSL driver) +# Written by: Stephan Müller +# Copyright (c) atsec information security corporation +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# NO WARRANTY +# +# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +# REPAIR OR CORRECTION. +# +# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGES. +# +# +# test execution instruction: +# 1. get the request files from the lab +# 2. call each request file from 1. with this program: +# $0 .rep +# 3. send the resulting file .rsp to the lab +# +# +# Test should be easily adoptable to other implementations +# See the first functions for this task +# +# Following tests are covered (others may also be covered +# but have not been tested) +# +# AES +# [CBC|CFB128|ECB|OFB]GFSbox[128|192|256] +# [CBC|CFB128|ECB|OFB]MCT[128|192|256] +# [CBC|CFB128|ECB|OFB]VarKey[128|192|256] +# [CBC|CFB128|ECB|OFB]KeySbox[128|192|256] +# [CBC|CFB128|ECB|OFB]MMT[128|192|256] +# [CBC|CFB128|ECB|OFB]VarTxt[128|192|256] +# +# RSA +# SigGen[15|RSA] +# SigVer15 +# (SigVerRSA is not applicable for OpenSSL as X9.31 padding +# is not done through openssl dgst) +# KeyGen RSA X9.31 +# +# SHA +# SHA[1|224|256|384|512]ShortMsg +# SHA[1|224|256|384|512]LongMsg +# SHA[1|224|256|384|512]Monte +# +# HMAC (SHA - caveat: we only support hash output equal to the block size of +# of the hash - we do not support truncation of the hash; to support +# that, we first need to decipher the HMAC.req file - see hmac_kat() ) +# HMAC +# +# TDES +# T[CBC|CFB??|ECB|OFB]Monte[1|2|3] +# T[CBC|CFB??|ECB|OFB]permop +# T[CBC|CFB??|ECB|OFB]MMT[1|2|3] +# T[CBC|CFB??|ECB|OFB]subtab +# T[CBC|CFB??|ECB|OFB]varkey +# T[CBC|CFB??|ECB|OFB]invperm +# T[CBC|CFB??|ECB|OFB]vartext +# +# ANSI X9.31 RNG +# ANSI931_AES128MCT +# ANSI931_AES128VST +# +# DSA +# PQGGen +# SigGen +# SigVer +# +# RC4 (atsec developed tests) +# RC4KeyBD +# RC4MCT +# RC4PltBD +# RC4REGT +# + +use strict; +use warnings; +use IPC::Open2; +use Getopt::Std; +use MIME::Base64; + +# Contains the command line options +my %opt; + +################################################################# +##### Central interface functions to the external ciphers ####### +################################################################# +# Only these interface routines should be changed in case of +# porting to a new cipher library +# +# For porting to a new library, create implementation of these functions +# and then add pointers to the respective implementation of each +# function to the given variables. + +# common encryption/decryption routine +# $1 key in hex form (please note for 3DES: even when ede3 for three +# independent ciphers is given with the cipher specification, we hand in +# either one key for k1 = k2 = k3, two keys which are concatinated for +# k1 = k3, k2 independent, or three keys which are concatinated for +# k1, k2, k3 independent) +# $2 iv in hex form +# $3 cipher - the cipher string is defined as specified in the openssl +# enc(1ssl) specification for the option "-ciphername" +# (e.g. aes-128-cbc or des-ede3-cbc) +# $4 encrypt=1/decrypt=0 +# $5 de/encrypted data in hex form +# return en/decrypted data in hex form +my $encdec; + +# +# Derive an RSA key from the given X9.31 parameters. +# $1: modulus size +# $2: E in hex form +# $3: Xp1 in hex form +# $4: Xp2 in hex form +# $5: Xp in hex form +# $6: Xq1 in hex form +# $7: Xq2 in hex form +# $8: Xq in hex form +# return: string with the calculated values in hex format, where each value +# is separated from the previous with a \n in the following order: +# P\n +# Q\n +# N\n +# D\n +my $rsa_derive; + +# Sign a message with RSA +# $1: data to be signed in hex form +# $2: Hash algo +# $3: Key file in PEM format with the private key +# return: digest in hex format +my $rsa_sign; + +# Verify a message with RSA +# $1: data to be verified in hex form +# $2: hash algo +# $3: file holding the public RSA key in PEM format +# $4: file holding the signature in binary form +# return: 1 == verified / 0 == not verified +my $rsa_verify; + +# generate a new private RSA key with the following properties: +# exponent is 65537 +# PEM format +# $1 key size in bit +# $2 keyfile name +# return: nothing, but file created +my $gen_rsakey; + +# Creating a hash +# $1: Plaintext in hex form +# $2: hash type in the form documented in openssl's dgst(1ssl) - e.g. +# sha1, sha224, sha256, sha384, sha512 +# return: hash in hex form +my $hash; + +# supplying the call to the external cipher implementation +# that is being used to keep STDIN and STDOUT open +# to maintain the state of the block chaining +# $1: cipher +# $2: 1=encryption, 0=decryption +# $3: buffersize needed for openssl +# $4: encryption key in binary form +# $5: IV in binary form +# return: command line to execute the application +my $state_cipher; +# the only difference of the DES version is that it implements the inner loop +# of the TDES tests +my $state_cipher_des; + +# supplying the call to the external cipher implementation +# that is being used to keep STDIN and STDOUT open +# to maintain the state of the RNG with its seed +# +# input holds seed values +# $1: cipher key in hex format +# $2: DT value in hex format +# $3: V value in hex format +# +# return: command line to execute the application +# +# the application is expected to deliver random values on STDOUT - the script +# reads 128 bits repeatedly where the state of the RNG must be retained +# between the reads. The output of the RNG on STDOUT is assumed to be binary. +my $state_rng; + +# Generate an HMAC based on SHAx +# $1: Key to be used for the HMAC in hex format +# $2: length of the hash to be calculated in bits +# $3: Message for which the HMAC shall be calculated in hex format +# $4: hash type (1 - SHA1, 224 - SHA224, and so on) +# return: calculated HMAC in hex format +my $hmac; + +# +# Generate the P, Q, G, Seed, counter, h (value used to generate g) values +# for DSA +# $1: modulus size +# return: string with the calculated values in hex format, where each value +# is separated from the previous with a \n in the following order: +# P\n +# Q\n +# G\n +# Seed\n +# counter\n +# h +my $dsa_pqggen; + +# +# Generate an DSA public key from the provided parameters: +# $1: Name of file to create +# $2: P in hex form +# $3: Q in hex form +# $4: G in hex form +# $5: Y in hex form +my $dsa_genpubkey; + +# Verify a message with DSA +# $1: data to be verified in hex form +# $2: file holding the public DSA key in PEM format +# $3: R value of the signature +# $4: S value of the signature +# return: 1 == verified / 0 == not verified +my $dsa_verify; + +# generate a new DSA key with the following properties: +# PEM format +# $1 keyfile name +# return: file created, hash with keys of P, Q, G in hex format +my $gen_dsakey; + +# Sign a message with DSA +# $1: data to be signed in hex form +# $2: Key file in PEM format with the private key +# return: hash of digest information in hex format with Y, R, S as keys +my $dsa_sign; + +################################################################ +##### OpenSSL interface functions +################################################################ +sub openssl_encdec($$$$$) { + my $key=shift; + my $iv=shift; + my $cipher=shift; + my $enc = (shift) ? "-e" : "-d"; + my $data=shift; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "-iv $iv" if ($iv); + + $data=hex2bin($data); + my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc $iv"; + $program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given + $data=pipe_through_program($data,$program); + return bin2hex($data); +} + +sub openssl_rsa_sign($$$) { + my $data = shift; + my $cipher = shift; + my $keyfile = shift; + + $data=hex2bin($data); + die "ARCFOUR not available for RSA" if $opt{'R'}; + $data=pipe_through_program($data, + "openssl dgst -$cipher -binary -sign $keyfile"); + return bin2hex($data); +} + +sub openssl_rsa_verify($$$$) { + my $data = shift; + my $cipher = shift; + my $keyfile = shift; + my $sigfile = shift; + + $data = hex2bin($data); + die "ARCFOUR not available for RSA" if $opt{'R'}; + $data = pipe_through_program($data, + "openssl dgst -$cipher -binary -verify $keyfile -signature $sigfile"); + + # Parse through the OpenSSL output information + return ($data =~ /OK/); +} + +sub openssl_gen_rsakey($$) { + my $keylen = shift; + my $file = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; + # generating of a key with exponent 0x10001 + my @args = ("openssl", "genrsa", "-F4", "-out", "$file", "$keylen"); + system(@args) == 0 + or die "system @args failed: $?"; + die "system @args failed: file $file not created" if (! -f $file); +} + +sub openssl_hash($$) { + my $pt = shift; + my $cipher = shift; + + die "ARCFOUR not available for hashes" if $opt{'R'}; + my $hash = hex2bin($pt); + #bin2hex not needed as the '-hex' already converts it + return pipe_through_program($hash, "openssl dgst -$cipher -hex"); +} + +sub openssl_state_cipher($$$$$) { + my $cipher = shift; + my $encdec = shift; + my $bufsize = shift; + my $key = shift; + my $iv = shift; + + my $enc = $encdec ? "-e": "-d"; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "-iv ".bin2hex($iv) if ($iv); + + my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." $iv"; + #for ARCFOUR, no IV must be given + $out = "rc4 -k " . bin2hex($key) if $opt{'R'}; + return $out; +} + +###### End of OpenSSL interface implementation ############ + +########################################################### +###### libgcrypt implementation +########################################################### +sub libgcrypt_encdec($$$$$) { + my $key=shift; + my $iv=shift; + my $cipher=shift; + my $enc = (shift) ? "encrypt" : "decrypt"; + my $data=shift; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "--iv $iv" if ($iv); + + my $program="fipsdrv --key $key $iv --algo $cipher $enc"; + + return pipe_through_program($data,$program); + +} + +sub libgcrypt_rsa_derive($$$$$$$$) { + my $n = shift; + my $e = shift; + my $xp1 = shift; + my $xp2 = shift; + my $xp = shift; + my $xq1 = shift; + my $xq2 = shift; + my $xq = shift; + my $sexp; + my @tmp; + + $n = sprintf ("%u", $n); + $e = sprintf ("%u", hex($e)); + $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")" + . "(rsa-use-e " . sprintf ("%u:%s", length($e), $e) . ")" + . "(derive-parms" + . "(Xp1 #$xp1#)" + . "(Xp2 #$xp2#)" + . "(Xp #$xp#)" + . "(Xq1 #$xq1#)" + . "(Xq2 #$xq2#)" + . "(Xq #$xq#))))\n"; + + return pipe_through_program($sexp, "fipsdrv rsa-derive"); +} + + +sub libgcrypt_rsa_sign($$$) { + my $data = shift; + my $hashalgo = shift; + my $keyfile = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; + + return pipe_through_program($data, + "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign"); +} + +sub libgcrypt_rsa_verify($$$$) { + my $data = shift; + my $hashalgo = shift; + my $keyfile = shift; + my $sigfile = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; + $data = pipe_through_program($data, + "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify"); + + # Parse through the output information + return ($data =~ /GOOD signature/); +} + +sub libgcrypt_gen_rsakey($$) { + my $keylen = shift; + my $file = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; + my @args = ("fipsdrv --keysize $keylen rsa-gen > $file"); + system(@args) == 0 + or die "system @args failed: $?"; + die "system @args failed: file $file not created" if (! -f $file); +} + +sub libgcrypt_hash($$) { + my $pt = shift; + my $hashalgo = shift; + + my $program = "fipsdrv --algo $hashalgo digest"; + die "ARCFOUR not available for hashes" if $opt{'R'}; + + return pipe_through_program($pt, $program); +} + +sub libgcrypt_state_cipher($$$$$) { + my $cipher = shift; + my $enc = (shift) ? "encrypt": "decrypt"; + my $bufsize = shift; + my $key = shift; + my $iv = shift; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "--iv ".bin2hex($iv) if ($iv); + + my $program="fipsdrv --binary --key ".bin2hex($key)." $iv --algo '$cipher' --chunk '$bufsize' $enc"; + + return $program; +} + +sub libgcrypt_state_cipher_des($$$$$) { + my $cipher = shift; + my $enc = (shift) ? "encrypt": "decrypt"; + my $bufsize = shift; + my $key = shift; + my $iv = shift; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "--iv ".bin2hex($iv) if ($iv); + + my $program="fipsdrv --algo '$cipher' --mct-server $enc"; + + return $program; +} + +sub libgcrypt_state_rng($$$) { + my $key = shift; + my $dt = shift; + my $v = shift; + + return "fipsdrv --binary --loop --key $key --iv $v --dt $dt random"; +} + +sub libgcrypt_hmac($$$$) { + my $key = shift; + my $maclen = shift; + my $msg = shift; + my $hashtype = shift; + + my $program = "fipsdrv --key $key --algo $hashtype hmac-sha"; + return pipe_through_program($msg, $program); +} + +sub libgcrypt_dsa_pqggen($) { + my $mod = shift; + + my $program = "fipsdrv --keysize $mod dsa-pqg-gen"; + return pipe_through_program("", $program); +} + +sub libgcrypt_gen_dsakey($) { + my $file = shift; + + my $program = "fipsdrv --keysize 1024 --key $file dsa-gen"; + my $tmp; + my %ret; + + die "ARCFOUR not available for DSA" if $opt{'R'}; + + $tmp = pipe_through_program("", $program); + die "dsa key gen failed: file $file not created" if (! -f $file); + + @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp); + return %ret; +} + +sub libgcrypt_dsa_genpubkey($$$$$) { + my $filename = shift; + my $p = shift; + my $q = shift; + my $g = shift; + my $y = shift; + + my $sexp; + + $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))"; + + open(FH, ">", $filename) or die; + print FH $sexp; + close FH; +} + +sub libgcrypt_dsa_sign($$) { + my $data = shift; + my $keyfile = shift; + my $tmp; + my %ret; + + die "ARCFOUR not available for DSA" if $opt{'R'}; + + $tmp = pipe_through_program($data, "fipsdrv --key $keyfile dsa-sign"); + @ret{'Y', 'R', 'S'} = split(/\n/, $tmp); + return %ret; +} + +sub libgcrypt_dsa_verify($$$$) { + my $data = shift; + my $keyfile = shift; + my $r = shift; + my $s = shift; + + my $ret; + + die "ARCFOUR not available for DSA" if $opt{'R'}; + + my $sigfile = "$keyfile.sig"; + open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?"; + print FH "(sig-val(dsa(r #$r#)(s #$s#)))"; + close FH; + + $ret = pipe_through_program($data, + "fipsdrv --key $keyfile --signature $sigfile dsa-verify"); + unlink ($sigfile); + # Parse through the output information + return ($ret =~ /GOOD signature/); +} + +######### End of libgcrypt implementation ################ + +################################################################ +###### Vendor1 interface functions +################################################################ + +sub vendor1_encdec($$$$$) { + my $key=shift; + my $iv=shift; + my $cipher=shift; + my $enc = (shift) ? "encrypt" : "decrypt"; + my $data=shift; + + $data=hex2bin($data); + my $program = "./aes $enc $key"; + $data=pipe_through_program($data,$program); + return bin2hex($data); +} + +sub vendor1_state_cipher($$$$$) { + my $cipher = shift; + my $encdec = shift; + my $bufsize = shift; + my $key = shift; + my $iv = shift; + + $key = bin2hex($key); + my $enc = $encdec ? "encrypt": "decrypt"; + my $out = "./aes $enc $key $bufsize"; + return $out; +} + +##### No other interface functions below this point ###### +########################################################## + +########################################################## +# General helper routines + +# Executing a program by feeding STDIN and retrieving +# STDOUT +# $1: data string to be piped to the app on STDIN +# rest: program and args +# returns: STDOUT of program as string +sub pipe_through_program($@) { + my $in = shift; + my @args = @_; + + my ($CO, $CI); + my $pid = open2($CO, $CI, @args); + + my $out = ""; + my $len = length($in); + my $first = 1; + while (1) { + my $rin = ""; + my $win = ""; + # Output of prog is FD that we read + vec($rin,fileno($CO),1) = 1; + # Input of prog is FD that we write + # check for $first is needed because we can have NULL input + # that is to be written to the app + if ( $len > 0 || $first) { + (vec($win,fileno($CI),1) = 1); + $first=0; + } + # Let us wait for 100ms + my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1); + if ( $wout ) { + my $written = syswrite($CI, $in, $len); + die "broken pipe" if !defined $written; + $len -= $written; + substr($in, 0, $written) = ""; + if ($len <= 0) { + close $CI or die "broken pipe: $!"; + } + } + if ( $rout ) { + my $tmp_out = ""; + my $bytes_read = sysread($CO, $tmp_out, 4096); + $out .= $tmp_out; + last if ($bytes_read == 0); + } + } + close $CO or die "broken pipe: $!"; + waitpid $pid, 0; + + return $out; +} + +# +# convert ASCII hex to binary input +# $1 ASCII hex +# return binary representation +sub hex2bin($) { + my $in = shift; + my $len = length($in); + $len = 0 if ($in eq "00"); + return pack("H$len", "$in"); +} + +# +# convert binary input to ASCII hex +# $1 binary value +# return ASCII hex representation +sub bin2hex($) { + my $in = shift; + my $len = length($in)*2; + return unpack("H$len", "$in"); +} + +# $1: binary byte (character) +# returns: binary byte with odd parity using low bit as parity bit +sub odd_par($) { + my $in = ord(shift); + my $odd_count=0; + for(my $i=1; $i<8; $i++) { + $odd_count++ if ($in & (1<<$i)); + } + + my $out = $in; + if ($odd_count & 1) { # check if parity is already odd + $out &= ~1; # clear the low bit + } else { + $out |= 1; # set the low bit + } + + return chr($out); +} + +# DES keys uses only the 7 high bits of a byte, the 8th low bit +# is the parity bit +# as the new key is calculated from oldkey XOR cipher in the MCT test, +# the parity is not really checked and needs to be set to match +# expectation (OpenSSL does not really care, but the FIPS +# test result is expected that the key has the appropriate parity) +# $1: arbitrary binary string +# returns: string with odd parity set in low bit of each byte +sub fix_key_parity($) { + my $in = shift; + my $out = ""; + for (my $i = 0; $i < length($in); $i++) { + $out .= odd_par(substr($in, $i, 1)); + } + + return $out; +} + +#################################################### +# DER/PEM utility functions +# Cf. http://www.columbia.edu/~ariel/ssleay/layman.html + +# Convert unsigned integer to base256 bigint bytes +# $1 integer +# returns base256 octet string +sub int_base256_unsigned($) { + my $n = shift; + + my $out = chr($n & 255); + while ($n>>=8) { + $out = chr($n & 255) . $out; + } + + return $out; +} + +# Convert signed integer to base256 bigint bytes +# $1 integer +# returns base256 octet string +sub int_base256_signed($) { + my $n = shift; + my $negative = ($n < 0); + + if ($negative) { + $n = -$n-1; + } + + my $out = int_base256_unsigned($n); + + if (ord(substr($out, 0, 1)) & 128) { + # it's supposed to be positive but has sign bit set, + # add a leading zero + $out = chr(0) . $out; + } + + if ($negative) { + my $neg = chr(255) x length($out); + $out ^= $neg; + } + + return $out; +} + +# Length header for specified DER object length +# $1 length as integer +# return octet encoding for length +sub der_len($) { + my $len = shift; + + if ($len <= 127) { + return chr($len); + } else { + my $blen = int_base256_unsigned($len); + + return chr(128 | length($blen)) . $blen; + } +} + +# Prepend length header to object +# $1 object as octet sequence +# return length header for object followed by object as octets +sub der_len_obj($) { + my $x = shift; + + return der_len(length($x)) . $x; +} + +# DER sequence +# $* objects +# returns DER sequence consisting of the objects passed as arguments +sub der_seq { + my $seq = join("", @_); + return chr(0x30) . der_len_obj($seq); +} + +# DER bitstring +# $1 input octets (must be full octets, fractional octets not supported) +# returns input encapsulated as bitstring +sub der_bitstring($) { + my $x = shift; + + $x = chr(0) . $x; + + return chr(0x03) . der_len_obj($x); +} + +# base-128-encoded integer, used for object numbers. +# $1 integer +# returns octet sequence +sub der_base128($) { + my $n = shift; + + my $out = chr($n & 127); + + while ($n>>=7) { + $out = chr(128 | ($n & 127)) . $out; + } + + return $out; +} + +# Generating the PEM certificate string +# (base-64-encoded DER string) +# $1 DER string +# returns octet sequence +sub pem_cert($) { + my $n = shift; + + my $out = "-----BEGIN PUBLIC KEY-----\n"; + $out .= encode_base64($n); + $out .= "-----END PUBLIC KEY-----\n"; + + return $out; +} + +# DER object identifier +# $* sequence of id numbers +# returns octets +sub der_objectid { + my $v1 = shift; + my $v2 = shift; + + my $out = chr(40*$v1 + $v2) . join("", map { der_base128($_) } @_); + + return chr(0x06) . der_len_obj($out); +} + +# DER signed integer +# $1 number as octet string (base 256 representation, high byte first) +# returns number in DER integer encoding +sub der_bigint($) { + my $x = shift; + + return chr(0x02) . der_len_obj($x); +} + +# DER positive integer with leading zeroes stripped +# $1 number as octet string (base 256 representation, high byte first) +# returns number in DER integer encoding +sub der_pos_bigint($) { + my $x = shift; + + # strip leading zero digits + $x =~ s/^[\0]+//; + + # need to prepend a zero if high bit set, since it would otherwise be + # interpreted as a negative number. Also needed for number 0. + if (!length($x) || ord(substr($x, 0, 1)) >= 128) { + $x = chr(0) . $x; + } + + return der_bigint($x); +} + +# $1 number as signed integer +# returns number as signed DER integer encoding +sub der_int($) { + my $n = shift; + + return der_bigint(int_base256_signed($n)); +} + +# the NULL object constant +sub der_null() { + return chr(0x05) . chr(0x00); +} + +# Unit test helper +# $1 calculated result +# $2 expected result +# no return value, dies if results differ, showing caller's line number +sub der_test($$) { + my $actual = bin2hex(shift); + my $expected = shift; + + my @caller = caller; + $actual eq $expected or die "Error:line $caller[2]:assertion failed: " + ."$actual != $expected\n"; +} + +# Unit testing for the DER encoding functions +# Examples from http://www.columbia.edu/~ariel/ssleay/layman.html +# No input, no output. Dies if unit tests fail. +sub der_unit_test { + ## uncomment these if you want to test the test framework + #print STDERR "Unit test running\n"; + #der_test chr(0), "42"; + + der_test der_null, "0500"; + + # length bytes + der_test der_len(1), "01"; + der_test der_len(127), "7f"; + der_test der_len(128), "8180"; + der_test der_len(256), "820100"; + der_test der_len(65536), "83010000"; + + # bigint + der_test der_bigint(chr(0)), "020100"; + der_test der_bigint(chr(128)), "020180"; # -128 + der_test der_pos_bigint(chr(128)), "02020080"; # +128 + der_test der_pos_bigint(chr(0).chr(0).chr(1)), "020101"; + der_test der_pos_bigint(chr(0)), "020100"; + + # integers (tests base256 conversion) + der_test der_int( 0), "020100"; + der_test der_int( 127), "02017f"; + der_test der_int( 128), "02020080"; + der_test der_int( 256), "02020100"; + der_test der_int( -1), "0201ff"; + der_test der_int( -128), "020180"; + der_test der_int( -129), "0202ff7f"; + der_test der_int(-65536), "0203ff0000"; + der_test der_int(-65537), "0203feffff"; + + # object encoding, "RSA Security" + der_test der_base128(840), "8648"; + der_test der_objectid(1, 2, 840, 113549), "06062a864886f70d"; + + # Combinations + der_test der_bitstring("ABCD"), "03050041424344"; + der_test der_bitstring(der_null), "0303000500"; + der_test der_seq(der_int(0), der_null), "30050201000500"; + + # The big picture + der_test der_seq(der_seq(der_objectid(1, 2, 840, 113549), der_null), + der_bitstring(der_seq(der_pos_bigint(chr(5)), + der_pos_bigint(chr(3))))), + "3017300a06062a864886f70d05000309003006020105020103"; +} + +#################################################### +# OpenSSL missing functionality workarounds + +## Format of an RSA public key: +# 0:d=0 hl=3 l= 159 cons: SEQUENCE +# 3:d=1 hl=2 l= 13 cons: SEQUENCE +# 5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption +# 16:d=2 hl=2 l= 0 prim: NULL +# 18:d=1 hl=3 l= 141 prim: BIT STRING +# [ sequence: INTEGER (n), INTEGER (e) ] + +# generate RSA pub key in PEM format +# $1: filename where PEM key is to be stored +# $2: n of the RSA key in hex +# $3: e of the RSA key in hex +# return: nothing, but file created +sub gen_pubrsakey($$$) { + my $filename=shift; + my $n = shift; + my $e = shift; + + # make sure the DER encoder works ;-) + der_unit_test(); + + # generate DER encoding of the public key + + my $rsaEncryption = der_objectid(1, 2, 840, 113549, 1, 1, 1); + + my $der = der_seq(der_seq($rsaEncryption, der_null), + der_bitstring(der_seq(der_pos_bigint(hex2bin($n)), + der_pos_bigint(hex2bin($e))))); + + open(FH, ">", $filename) or die; + print FH pem_cert($der); + close FH; + +} + +# generate RSA pub key in PEM format +# +# This implementation uses "openssl asn1parse -genconf" which was added +# in openssl 0.9.8. It is not available in older openssl versions. +# +# $1: filename where PEM key is to be stored +# $2: n of the RSA key in hex +# $3: e of the RSA key in hex +# return: nothing, but file created +sub gen_pubrsakey_using_openssl($$$) { + my $filename=shift; + my $n = shift; + my $e = shift; + + my $asn1 = "asn1=SEQUENCE:pubkeyinfo + +[pubkeyinfo] +algorithm=SEQUENCE:rsa_alg +pubkey=BITWRAP,SEQUENCE:rsapubkey + +[rsa_alg] +algorithm=OID:rsaEncryption +parameter=NULL + +[rsapubkey] +n=INTEGER:0x$n + +e=INTEGER:0x$e"; + + open(FH, ">$filename.cnf") or die "Cannot create file $filename.cnf: $?"; + print FH $asn1; + close FH; + my @args = ("openssl", "asn1parse", "-genconf", "$filename.cnf", "-noout", "-out", "$filename.der"); + system(@args) == 0 or die "system @args failed: $?"; + @args = ("openssl", "rsa", "-inform", "DER", "-in", "$filename.der", + "-outform", "PEM", "-pubin", "-pubout", "-out", "$filename"); + system(@args) == 0 or die "system @args failed: $?"; + die "RSA PEM formatted key file $filename was not created" + if (! -f $filename); + + unlink("$filename.cnf"); + unlink("$filename.der"); +} + +############################################ +# Test cases + +# This is the Known Answer Test +# $1: the string that we have to put in front of the key +# when printing the key +# $2: crypto key1 in hex form +# $3: crypto key2 in hex form (TDES, undef otherwise) +# $4: crypto key3 in hex form (TDES, undef otherwise) +# $5: IV in hex form +# $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form +# $7: cipher +# $8: encrypt=1/decrypt=0 +# return: string formatted as expected by CAVS +sub kat($$$$$$$$) { + my $keytype = shift; + my $key1 = shift; + my $key2 = shift; + my $key3 = shift; + my $iv = shift; + my $pt = shift; + my $cipher = shift; + my $enc = shift; + + my $out = ""; + + $out .= "$keytype = $key1\n"; + + # this is the concardination of the keys for 3DES + if (defined($key2)) { + $out .= "KEY2 = $key2\n"; + $key1 = $key1 . $key2; + } + if (defined($key3)) { + $out .= "KEY3 = $key3\n"; + $key1= $key1 . $key3; + } + + $out .= "IV = $iv\n" if (defined($iv) && $iv ne ""); + if ($enc) { + $out .= "PLAINTEXT = $pt\n"; + $out .= "CIPHERTEXT = " . &$encdec($key1, $iv, $cipher, 1, $pt) . "\n"; + } else { + $out .= "CIPHERTEXT = $pt\n"; + $out .= "PLAINTEXT = " . &$encdec($key1, $iv, $cipher, 0, $pt) . "\n"; + } + + return $out; +} + +# This is the Known Answer Test for Hashes +# $1: Plaintext in hex form +# $2: hash +# $3: hash length (undef if not applicable) +# return: string formatted as expected by CAVS +sub hash_kat($$$) { + my $pt = shift; + my $cipher = shift; + my $len = shift; + + my $out = ""; + $out .= "Len = $len\n" if (defined($len)); + $out .= "Msg = $pt\n"; + + $pt = "" if(!$len); + $out .= "MD = " . &$hash($pt, $cipher) . "\n"; + return $out; +} + +# Known Answer Test for HMAC hash +# $1: key length in bytes +# $2: MAC length in bytes +# $3: key for HMAC in hex form +# $4: message to be hashed +# return: string formatted as expected by CAVS +sub hmac_kat($$$$) { + my $klen = shift; + my $tlen = shift; + my $key = shift; + my $msg = shift; + + # XXX this is a hack - we need to decipher the HMAC REQ files in a more + # sane way + # + # This is a conversion table from the expected hash output size + # to the assumed hash type - we only define here the block size of + # the underlying hashes and do not allow any truncation + my %hashtype = ( + 20 => 1, + 28 => 224, + 32 => 256, + 48 => 384, + 64 => 512 + ); + + die "Hash output size $tlen is not supported!" + if(!defined($hashtype{$tlen})); + + my $out = ""; + $out .= "Klen = $klen\n"; + $out .= "Tlen = $tlen\n"; + $out .= "Key = $key\n"; + $out .= "Msg = $msg\n"; + $out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n"; + + return $out; +} + + +# Cipher Monte Carlo Testing +# $1: the string that we have to put in front of the key +# when printing the key +# $2: crypto key1 in hex form +# $3: crypto key2 in hex form (TDES, undef otherwise) +# $4: crypto key3 in hex form (TDES, undef otherwise) +# $5: IV in hex form +# $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form +# $7: cipher +# $8: encrypt=1/decrypt=0 +# return: string formatted as expected by CAVS +sub crypto_mct($$$$$$$$) { + my $keytype = shift; + my $key1 = hex2bin(shift); + my $key2 = shift; + my $key3 = shift; + my $iv = hex2bin(shift); + my $source_data = hex2bin(shift); + my $cipher = shift; + my $enc = shift; + + my $out = ""; + + $key2 = hex2bin($key2) if (defined($key2)); + $key3 = hex2bin($key3) if (defined($key3)); + my $bufsize = length($source_data); + + # for AES: outer loop 0-99, inner 0-999 based on FIPS compliance tests + # for RC4: outer loop 0-99, inner 0-999 based on atsec compliance tests + # for DES: outer loop 0-399, inner 0-9999 based on FIPS compliance tests + my $ciph = substr($cipher,0,3); + my $oloop=100; + my $iloop=1000; + if ($ciph =~ /des/) {$oloop=400;$iloop=10000;} + + for (my $i=0; $i<$oloop; ++$i) { + $out .= "COUNT = $i\n"; + if (defined($key2)) { + $out .= "$keytype = ". bin2hex($key1). "\n"; + $out .= "KEY2 = ". bin2hex($key2). "\n"; + $key1 = $key1 . $key2; + } else { + $out .= "$keytype = ". bin2hex($key1). "\n"; + } + if(defined($key3)) { + $out .= "KEY3 = ". bin2hex($key3). "\n"; + $key1 = $key1 . $key3; + } + my $keylen = length($key1); + + $out .= "IV = ". bin2hex($iv) . "\n" + if (defined($iv) && $iv ne ""); + + if ($enc) { + $out .= "PLAINTEXT = ". bin2hex($source_data). "\n"; + } else { + $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n"; + } + my ($CO, $CI); + my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv); + $cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/); + my $pid = open2($CO, $CI, $cipher_imp); + + my $calc_data = $iv; # CT[j] + my $old_calc_data; # CT[j-1] + my $old_old_calc_data; # CT[j-2] + my $next_source; + + # TDES inner loop implements logic within driver + if ($cipher =~ /des/) { + # Need to provide a dummy IV in case of ECB mode. + my $iv_arg = (defined($iv) && $iv ne "") + ? bin2hex($iv) + : "00"x(length($source_data)); + print $CI "1\n" + .$iloop."\n" + .bin2hex($key1)."\n" + .$iv_arg."\n" + .bin2hex($source_data)."\n\n" or die; + chomp(my $line = <$CO>); + $calc_data = hex2bin($line); + chomp($line = <$CO>); + $old_calc_data = hex2bin($line); + chomp($line = <$CO>); + $old_old_calc_data = hex2bin($line); + chomp($line = <$CO>); + $iv = hex2bin($line) if (defined($iv) && $iv ne ""); + chomp($line = <$CO>); + $next_source = hex2bin($line); + # Skip over empty line. + $line = <$CO>; + } else { + for (my $j = 0; $j < $iloop; ++$j) { + $old_old_calc_data = $old_calc_data; + $old_calc_data = $calc_data; + + #print STDERR "source_data=", bin2hex($source_data), "\n"; + syswrite $CI, $source_data or die $!; + my $len = sysread $CO, $calc_data, $bufsize; + + #print STDERR "len=$len, bufsize=$bufsize\n"; + die if $len ne $bufsize; + #print STDERR "calc_data=", bin2hex($calc_data), "\n"; + + if ( (!$enc && $ciph =~ /des/) || + $ciph =~ /rc4/ || + $cipher =~ /ecb/ ) { + #TDES in decryption mode, RC4 and ECB mode + #have a special rule + $source_data = $calc_data; + } else { + $source_data = $old_calc_data; + } + } + } + close $CO; + close $CI; + waitpid $pid, 0; + + if ($enc) { + $out .= "CIPHERTEXT = ". bin2hex($calc_data). "\n\n"; + } else { + $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n"; + } + + if ( $ciph =~ /aes/ ) { + $key1 ^= substr($old_calc_data . $calc_data, -$keylen); + #print STDERR bin2hex($key1)."\n"; + } elsif ( $ciph =~ /des/ ) { + die "Wrong keylen $keylen" if ($keylen != 24); + + # $nkey needed as $key holds the concatenation of the + # old key atm + my $nkey = fix_key_parity(substr($key1,0,8) ^ $calc_data); + #print STDERR "KEY1 = ". bin2hex($nkey)."\n"; + if (substr($key1,0,8) ne substr($key1,8,8)) { + #print STDERR "KEY2 recalc: KEY1==KEY3, KEY2 indep. or all KEYs are indep.\n"; + $key2 = fix_key_parity((substr($key1,8,8) ^ $old_calc_data)); + } else { + #print STDERR "KEY2 recalc: KEY1==KEY2==KEY3\n"; + $key2 = fix_key_parity((substr($key1,8,8) ^ $calc_data)); + } + #print STDERR "KEY2 = ". bin2hex($key2)."\n"; + if ( substr($key1,0,8) eq substr($key1,16)) { + #print STDERR "KEY3 recalc: KEY1==KEY2==KEY3 or KEY1==KEY3, KEY2 indep.\n"; + $key3 = fix_key_parity((substr($key1,16) ^ $calc_data)); + } else { + #print STDERR "KEY3 recalc: all KEYs are independent\n"; + $key3 = fix_key_parity((substr($key1,16) ^ $old_old_calc_data)); + } + #print STDERR "KEY3 = ". bin2hex($key3)."\n"; + + # reset the first key - concardination happens at + # beginning of loop + $key1=$nkey; + } elsif ($ciph =~ /rc4/ ) { + $key1 ^= substr($calc_data, 0, 16); + #print STDERR bin2hex($key1)."\n"; + } else { + die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing"; + } + + if ($cipher =~ /des-ede3-ofb/) { + $source_data = $source_data ^ $next_source; + } elsif (!$enc && $cipher =~ /des-ede3-cfb/) { + #TDES decryption CFB has a special rule + $source_data = $next_source; + } elsif ( $ciph =~ /rc4/ || $cipher eq "des-ede3" || $cipher =~ /ecb/) { + #No resetting of IV as the IV is all zero set initially (i.e. no IV) + $source_data = $calc_data; + } elsif (! $enc && $ciph =~ /des/ ) { + #TDES in decryption mode has a special rule + $iv = $old_calc_data; + $source_data = $calc_data; + } else { + $iv = $calc_data; + $source_data = $old_calc_data; + } + } + + return $out; +} + +# Hash Monte Carlo Testing +# $1: Plaintext in hex form +# $2: hash +# return: string formatted as expected by CAVS +sub hash_mct($$) { + my $pt = shift; + my $cipher = shift; + + my $out = ""; + + $out .= "Seed = $pt\n\n"; + + for (my $j=0; $j<100; ++$j) { + $out .= "COUNT = $j\n"; + my $md0=$pt; + my $md1=$pt; + my $md2=$pt; + for (my $i=0; $i<1000; ++$i) { + #print STDERR "outer loop $j; inner loop $i\n"; + my $mi= $md0 . $md1 . $md2; + $md0=$md1; + $md1=$md2; + $md2 = &$hash($mi, $cipher); + $md2 =~ s/\n//; + } + $out .= "MD = $md2\n\n"; + $pt=$md2; + } + + return $out; +} + +# RSA SigGen test +# $1: Message to be signed in hex form +# $2: Hash algorithm +# $3: file name with RSA key in PEM form +# return: string formatted as expected by CAVS +sub rsa_siggen($$$) { + my $data = shift; + my $cipher = shift; + my $keyfile = shift; + + my $out = ""; + + $out .= "SHAAlg = $cipher\n"; + $out .= "Msg = $data\n"; + $out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n"; + + return $out; +} + +# RSA SigVer test +# $1: Message to be verified in hex form +# $2: Hash algoritm +# $3: Signature of message in hex form +# $4: n of the RSA key in hex in hex form +# $5: e of the RSA key in hex in hex form +# return: string formatted as expected by CAVS +sub rsa_sigver($$$$$) { + my $data = shift; + my $cipher = shift; + my $signature = shift; + my $n = shift; + my $e = shift; + + my $out = ""; + + $out .= "SHAAlg = $cipher\n"; + $out .= "e = $e\n"; + $out .= "Msg = $data\n"; + $out .= "S = $signature\n"; + + # XXX maybe a secure temp file name is better here + # but since it is not run on a security sensitive + # system, I hope that this is fine + my $keyfile = "rsa_sigver.tmp.$$"; + gen_pubrsakey($keyfile, $n, $e); + + my $sigfile = "$keyfile.sig"; + open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?"; + print FH hex2bin($signature); + close FH; + + $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n"); + + unlink($keyfile); + unlink($sigfile); + + return $out; +} + +# RSA X9.31 key generation test +# $1 modulus size +# $2 e +# $3 xp1 +# $4 xp2 +# $5 Xp +# $6 xq1 +# $7 xq2 +# $8 Xq +# return: string formatted as expected by CAVS +sub rsa_keygen($$$$$$$$) { + my $modulus = shift; + my $e = shift; + my $xp1 = shift; + my $xp2 = shift; + my $Xp = shift; + my $xq1 = shift; + my $xq2 = shift; + my $Xq = shift; + + my $out = ""; + + my $ret = &$rsa_derive($modulus, $e, $xp1, $xp2, $Xp, $xq1, $xq2, $Xq); + + my ($P, $Q, $N, $D) = split(/\n/, $ret); + + $out .= "e = $e\n"; + $out .= "xp1 = $xp1\n"; + $out .= "xp2 = $xp2\n"; + $out .= "Xp = $Xp\n"; + $out .= "p = $P\n"; + $out .= "xq1 = $xq1\n"; + $out .= "xq2 = $xq2\n"; + $out .= "Xq = $Xq\n"; + $out .= "q = $Q\n"; + $out .= "n = $N\n"; + $out .= "d = $D\n\n"; + + return $out; + +} + +# X9.31 RNG test +# $1 key for the AES cipher +# $2 DT value +# $3 V value +# $4 type ("VST", "MCT") +# return: string formatted as expected by CAVS +sub rngx931($$$$) { + my $key=shift; + my $dt=shift; + my $v=shift; + my $type=shift; + + my $out = "Key = $key\n"; + $out .= "DT = $dt\n"; + $out .= "V = $v\n"; + + my $count = 1; + $count = 10000 if ($type eq "MCT"); + + my $rnd_val = ""; + + # we read 16 bytes from RNG + my $bufsize = 16; + + my ($CO, $CI); + my $rng_imp = &$state_rng($key, $dt, $v); + my $pid = open2($CO, $CI, $rng_imp); + for (my $i = 0; $i < $count; ++$i) { + my $len = sysread $CO, $rnd_val, $bufsize; + #print STDERR "len=$len, bufsize=$bufsize\n"; + die "len=$len != bufsize=$bufsize" if $len ne $bufsize; + #print STDERR "calc_data=", bin2hex($rnd_val), "\n"; + } + close $CO; + close $CI; + waitpid $pid, 0; + + $out .= "R = " . bin2hex($rnd_val) . "\n\n"; + + return $out; +} + +# DSA PQGGen test +# $1 modulus size +# $2 number of rounds to perform the test +# return: string formatted as expected by CAVS +sub dsa_pqggen_driver($$) { + my $mod = shift; + my $rounds = shift; + + my $out = ""; + for(my $i=0; $i<$rounds; $i++) { + my $ret = &$dsa_pqggen($mod); + my ($P, $Q, $G, $Seed, $c, $H) = split(/\n/, $ret); + die "Return value does not contain all expected values of P, Q, G, Seed, c, H for dsa_pqggen" + if (!defined($P) || !defined($Q) || !defined($G) || + !defined($Seed) || !defined($c) || !defined($H)); + + # now change the counter to decimal as CAVS wants decimal + # counter value although all other is HEX + $c = hex($c); + + $out .= "P = $P\n"; + $out .= "Q = $Q\n"; + $out .= "G = $G\n"; + $out .= "Seed = $Seed\n"; + $out .= "c = $c\n"; + $out .= "H = $H\n\n"; + } + + return $out; +} + + +# DSA SigGen test +# $1: Message to be signed in hex form +# $2: file name with DSA key in PEM form +# return: string formatted as expected by CAVS +sub dsa_siggen($$) { + my $data = shift; + my $keyfile = shift; + + my $out = ""; + + my %ret = &$dsa_sign($data, $keyfile); + + $out .= "Msg = $data\n"; + $out .= "Y = " . $ret{'Y'} . "\n"; + $out .= "R = " . $ret{'R'} . "\n"; + $out .= "S = " . $ret{'S'} . "\n"; + + return $out; +} + + +# DSA signature verification +# $1 modulus +# $2 P +# $3 Q +# $4 G +# $5 Y - public key +# $6 r +# $7 s +# $8 message to be verified +# return: string formatted as expected by CAVS +sub dsa_sigver($$$$$$$$) { + my $modulus = shift; + my $p = shift; + my $q = shift; + my $g = shift; + my $y = shift; + my $r = shift; + my $s = shift; + my $msg = shift; + + my $out = ""; + + #PQG are already printed - do not print them here + + $out .= "Msg = $msg\n"; + $out .= "Y = $y\n"; + $out .= "R = $r\n"; + $out .= "S = $s\n"; + + # XXX maybe a secure temp file name is better here + # but since it is not run on a security sensitive + # system, I hope that this is fine + my $keyfile = "dsa_sigver.tmp.$$"; + &$dsa_genpubkey($keyfile, $p, $q, $g, $y); + + $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n"); + + unlink($keyfile); + + return $out; +} + +############################################################## +# Parser of input file and generator of result file +# + +sub usage() { + + print STDERR "Usage: +$0 [-R] [-D] [-I name] + +-R execution of ARCFOUR instead of OpenSSL +-I NAME Use interface style NAME: + openssl OpenSSL (default) + libgcrypt Libgcrypt +-D SigGen and SigVer are executed with DSA + Please note that the DSA CAVS vectors do not allow distinguishing + them from the RSA vectors. As the RSA test is the default, you have + to supply this option to apply the DSA logic"; +} + +# Parser of CAVS test vector file +# $1: Test vector file +# $2: Output file for test results +# return: nothing +sub parse($$) { + my $infile = shift; + my $outfile = shift; + + my $out = ""; + + # this is my cipher/hash type + my $cipher = ""; + + # Test type + # 1 - cipher known answer test + # 2 - cipher Monte Carlo test + # 3 - hash known answer test + # 4 - hash Monte Carlo test + # 5 - RSA signature generation + # 6 - RSA signature verification + my $tt = 0; + + # Variables for tests + my $keytype = ""; # we can have "KEY", "KEYs", "KEY1" + my $key1 = ""; + my $key2 = undef; #undef needed for allowing + my $key3 = undef; #the use of them as input variables + my $pt = ""; + my $enc = 1; + my $iv = ""; + my $len = undef; #see key2|3 + my $n = ""; + my $e = ""; + my $signature = ""; + my $rsa_keyfile = ""; + my $dsa_keyfile = ""; + my $dt = ""; + my $v = ""; + my $klen = ""; + my $tlen = ""; + my $modulus = ""; + my $capital_n = 0; + my $capital_p = ""; + my $capital_q = ""; + my $capital_g = ""; + my $capital_y = ""; + my $capital_r = ""; + my $xp1 = ""; + my $xp2 = ""; + my $Xp = ""; + my $xq1 = ""; + my $xq2 = ""; + my $Xq = ""; + + my $mode = ""; + + open(IN, "<$infile"); + while() { + + my $line = $_; + chomp($line); + $line =~ s/\r//; + + my $keylen = ""; + + # Mode and type check + # consider the following parsed line + # '# AESVS MCT test data for CBC' + # '# TDES Multi block Message Test for CBC' + # '# INVERSE PERMUTATION - KAT for CBC' + # '# SUBSTITUTION TABLE - KAT for CBC' + # '# TDES Monte Carlo (Modes) Test for CBC' + # '# "SHA-1 Monte" information for "IBMRHEL5"' + # '# "SigVer PKCS#1 Ver 1.5" information for "IBMRHEL5"' + # '# "SigGen PKCS#1 Ver 1.5" information for "IBMRHEL5"' + # '#RC4VS MCT test data' + + # avoid false positives from user specified 'for "PRODUCT"' strings + my $tmpline = $line; + $tmpline =~ s/ for ".*"//; + + ##### Extract cipher + # XXX there may be more - to be added + if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA)/) { + if ($tmpline =~ /CBC/) { $mode="cbc"; } + elsif ($tmpline =~ /ECB/) { $mode="ecb"; } + elsif ($tmpline =~ /OFB/) { $mode="ofb"; } + elsif ($tmpline =~ /CFB/) { $mode="cfb"; } + #we do not need mode as the cipher is already clear + elsif ($tmpline =~ /SHA-1/) { $cipher="sha1"; } + elsif ($tmpline =~ /SHA-224/) { $cipher="sha224"; } + elsif ($tmpline =~ /SHA-256/) { $cipher="sha256"; } + elsif ($tmpline =~ /SHA-384/) { $cipher="sha384"; } + elsif ($tmpline =~ /SHA-512/) { $cipher="sha512"; } + #we do not need mode as the cipher is already clear + elsif ($tmpline =~ /RC4VS/) { $cipher="rc4"; } + elsif ($tmpline =~ /SigGen|SigVer/) { + die "Error: X9.31 is not supported" + if ($tmpline =~ /X9/); + $cipher="sha1"; #place holder - might be overwritten later + } + + if ($tmpline =~ /^#.*AESVS/) { + # AES cipher (part of it) + $cipher="aes"; + } + if ($tmpline =~ /^#.*(TDES|KAT)/) { + # TDES cipher (full definition) + # the FIPS-140 test generator tool does not produce + # machine readable output! + if ($mode eq "cbc") { $cipher="des-ede3-cbc"; } + if ($mode eq "ecb") { $cipher="des-ede3"; } + if ($mode eq "ofb") { $cipher="des-ede3-ofb"; } + if ($mode eq "cfb") { $cipher="des-ede3-cfb"; } + } + + # check for RNG + if ($tmpline =~ /ANSI X9\.31/) { + # change the tmpline to add the type of the + # test which is ONLY visible from the file + # name :-( + if ($infile =~ /MCT\.req/) { + $tmpline .= " MCT"; + } elsif ($infile =~ /VST\.req/) { + $tmpline .= " VST"; + } else { + die "Unexpected cipher type with $infile"; + } + } + + if ($tt == 0) { + ##### Identify the test type + if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) { + $tt = 13; + die "Interface function rsa_derive for RSA key generation not defined for tested library" + if (!defined($rsa_derive)); + } elsif ($tmpline =~ /SigVer/ && $opt{'D'} ) { + $tt = 12; + die "Interface function dsa_verify or dsa_genpubkey for DSA verification not defined for tested library" + if (!defined($dsa_verify) || !defined($dsa_genpubkey)); + } elsif ($tmpline =~ /SigGen/ && $opt{'D'}) { + $tt = 11; + die "Interface function dsa_sign or gen_dsakey for DSA sign not defined for tested library" + if (!defined($dsa_sign) || !defined($gen_rsakey)); + } elsif ($tmpline =~ /PQGGen/) { + $tt = 10; + die "Interface function for DSA PQGGen testing not defined for tested library" + if (!defined($dsa_pqggen)); + } elsif ($tmpline =~ /Hash sizes tested/) { + $tt = 9; + die "Interface function hmac for HMAC testing not defined for tested library" + if (!defined($hmac)); + } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) { + $tt = 8; + die "Interface function state_rng for RNG MCT not defined for tested library" + if (!defined($state_rng)); + } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) { + $tt = 7; + die "Interface function state_rng for RNG KAT not defined for tested library" + if (!defined($state_rng)); + } elsif ($tmpline =~ /SigVer/ ) { + $tt = 6; + die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library" + if (!defined($rsa_verify) || !defined($gen_rsakey)); + } elsif ($tmpline =~ /SigGen/ ) { + $tt = 5; + die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library" + if (!defined($rsa_sign) || !defined($gen_rsakey)); + } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher =~ /^sha/) { + $tt = 4; + die "Interface function hash for Hashing not defined for tested library" + if (!defined($hash)); + } elsif ($tmpline =~ /Monte|MCT|Carlo/) { + $tt = 2; + die "Interface function state_cipher for Stateful Cipher operation defined for tested library" + if (!defined($state_cipher) || !defined($state_cipher_des)); + } elsif ($cipher =~ /^sha/) { + $tt = 3; + die "Interface function hash for Hashing not defined for tested library" + if (!defined($hash)); + } else { + $tt = 1; + die "Interface function encdec for Encryption/Decryption not defined for tested library" + if (!defined($encdec)); + } + } + } + + # This is needed as ARCFOUR does not operate with an IV + $iv = "00000000000000000000000000000000" if ($cipher eq "rc4" + && $iv eq "" ); + + # we are now looking for the string + # '# Key Length : 256' + # found in AES + if ($tmpline =~ /^# Key Length.*?(128|192|256)/) { + if ($cipher eq "aes") { + $cipher="$cipher-$1-$mode"; + } else { + die "Error: Key length $1 given for cipher $cipher which is unexpected"; + } + } + + # Get the test data + if ($line =~ /^(KEY|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG + die "KEY seen twice - input file crap" if ($key1 ne ""); + $keytype=$1; + $key1=$2; + $key1 =~ s/\s//g; #replace potential white spaces + } + elsif ($line =~ /^(KEYs)\s*=\s*(.*)/) { # found in ciphers and RNG + die "KEY seen twice - input file crap" if ($key1 ne ""); + $keytype=$1; + $key1=$2; + $key1 =~ s/\s//g; #replace potential white spaces + $key2 = $key1; + $key3 = $key1; + } + elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES + die "First key not set, but got already second key - input file crap" if ($key1 eq ""); + die "KEY2 seen twice - input file crap" if (defined($key2)); + $key2=$1; + $key2 =~ s/\s//g; #replace potential white spaces + } + elsif ($line =~ /^KEY3\s*=\s*(.*)/) { # found in TDES + die "Second key not set, but got already third key - input file crap" if ($key2 eq ""); + die "KEY3 seen twice - input file crap" if (defined($key3)); + $key3=$1; + $key3 =~ s/\s//g; #replace potential white spaces + } + elsif ($line =~ /^IV\s*=\s*(.*)/) { # found in ciphers + die "IV seen twice - input file crap" if ($iv ne ""); + $iv=$1; + $iv =~ s/\s//g; #replace potential white spaces + } + elsif ($line =~ /^PLAINTEXT\s*=\s*(.*)/) { # found in ciphers + if ( $1 !~ /\?/ ) { #only use it if there is valid hex data + die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne ""); + $pt=$1; + $pt =~ s/\s//g; #replace potential white spaces + $enc=1; + } + } + elsif ($line =~ /^CIPHERTEXT\s*=\s*(.*)/) { # found in ciphers + if ( $1 !~ /\?/ ) { #only use it if there is valid hex data + die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne ""); + $pt=$1; + $pt =~ s/\s//g; #replace potential white spaces + $enc=0; + } + } + elsif ($line =~ /^Len\s*=\s*(.*)/) { # found in hashs + $len=$1; + } + elsif ($line =~ /^(Msg|Seed)\s*=\s*(.*)/) { # found in hashs + die "Msg/Seed seen twice - input file crap" if ($pt ne ""); + $pt=$2; + } + elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests + $modulus = $1; + $out .= $line . "\n\n"; # print it + # generate the private key with given bit length now + # as we have the required key length in bit + if ($tt == 11) { + $dsa_keyfile = "dsa_siggen.tmp.$$"; + my %pqg = &$gen_dsakey($dsa_keyfile); + $out .= "P = " . $pqg{'P'} . "\n"; + $out .= "Q = " . $pqg{'Q'} . "\n"; + $out .= "G = " . $pqg{'G'} . "\n"; + } elsif ( $tt == 5 ) { + # XXX maybe a secure temp file name is better here + # but since it is not run on a security sensitive + # system, I hope that this is fine + $rsa_keyfile = "rsa_siggen.tmp.$$"; + &$gen_rsakey($modulus, $rsa_keyfile); + my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile"); + $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/; + $out .= "n = $modulus\n"; + $out .= "\ne = 10001\n" + } + } + elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests + $cipher=$1; + } + elsif($line =~ /^n\s*=\s*(.*)/) { # found in RSA requests + $out .= $line . "\n"; + $n=$1; + } + elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests + $e=$1; + } + elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests + die "S seen twice - input file crap" if ($signature ne ""); + $signature=$1; + } + elsif ($line =~ /^DT\s*=\s*(.*)/) { # X9.31 RNG requests + die "DT seen twice - check input file" + if ($dt ne ""); + $dt=$1; + } + elsif ($line =~ /^V\s*=\s*(.*)/) { # X9.31 RNG requests + die "V seen twice - check input file" + if ($v ne ""); + $v=$1; + } + elsif ($line =~ /^Klen\s*=\s*(.*)/) { # HMAC requests + die "Klen seen twice - check input file" + if ($klen ne ""); + $klen=$1; + } + elsif ($line =~ /^Tlen\s*=\s*(.*)/) { # HMAC RNG requests + die "Tlen seen twice - check input file" + if ($tlen ne ""); + $tlen=$1; + } + elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA PQGGen + die "N seen twice - check input file" + if ($capital_n); + $capital_n = $1; + } + elsif ($line =~ /^P\s*=\s*(.*)/) { #DSA SigVer + die "P seen twice - check input file" + if ($capital_p); + $capital_p = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^Q\s*=\s*(.*)/) { #DSA SigVer + die "Q seen twice - check input file" + if ($capital_q); + $capital_q = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^G\s*=\s*(.*)/) { #DSA SigVer + die "G seen twice - check input file" + if ($capital_g); + $capital_g = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^Y\s*=\s*(.*)/) { #DSA SigVer + die "Y seen twice - check input file" + if ($capital_y); + $capital_y = $1; + } + elsif ($line =~ /^R\s*=\s*(.*)/) { #DSA SigVer + die "R seen twice - check input file" + if ($capital_r); + $capital_r = $1; + } + elsif ($line =~ /^xp1\s*=\s*(.*)/) { #RSA key gen + die "xp1 seen twice - check input file" + if ($xp1); + $xp1 = $1; + } + elsif ($line =~ /^xp2\s*=\s*(.*)/) { #RSA key gen + die "xp2 seen twice - check input file" + if ($xp2); + $xp2 = $1; + } + elsif ($line =~ /^Xp\s*=\s*(.*)/) { #RSA key gen + die "Xp seen twice - check input file" + if ($Xp); + $Xp = $1; + } + elsif ($line =~ /^xq1\s*=\s*(.*)/) { #RSA key gen + die "xq1 seen twice - check input file" + if ($xq1); + $xq1 = $1; + } + elsif ($line =~ /^xq2\s*=\s*(.*)/) { #RSA key gen + die "xq2 seen twice - check input file" + if ($xq2); + $xq2 = $1; + } + elsif ($line =~ /^Xq\s*=\s*(.*)/) { #RSA key gen + die "Xq seen twice - check input file" + if ($Xq); + $Xq = $1; + } + else { + $out .= $line . "\n"; + } + + # call tests if all input data is there + if ($tt == 1) { + if ($key1 ne "" && $pt ne "" && $cipher ne "") { + $out .= kat($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc); + $keytype = ""; + $key1 = ""; + $key2 = undef; + $key3 = undef; + $iv = ""; + $pt = ""; + } + } + elsif ($tt == 2) { + if ($key1 ne "" && $pt ne "" && $cipher ne "") { + $out .= crypto_mct($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc); + $keytype = ""; + $key1 = ""; + $key2 = undef; + $key3 = undef; + $iv = ""; + $pt = ""; + } + } + elsif ($tt == 3) { + if ($pt ne "" && $cipher ne "") { + $out .= hash_kat($pt, $cipher, $len); + $pt = ""; + $len = undef; + } + } + elsif ($tt == 4) { + if ($pt ne "" && $cipher ne "") { + $out .= hash_mct($pt, $cipher); + $pt = ""; + } + } + elsif ($tt == 5) { + if ($pt ne "" && $cipher ne "" && $rsa_keyfile ne "") { + $out .= rsa_siggen($pt, $cipher, $rsa_keyfile); + $pt = ""; + } + } + elsif ($tt == 6) { + if ($pt ne "" && $cipher ne "" && $signature ne "" && $n ne "" && $e ne "") { + $out .= rsa_sigver($pt, $cipher, $signature, $n, $e); + $pt = ""; + $signature = ""; + } + } + elsif ($tt == 7 ) { + if ($key1 ne "" && $dt ne "" && $v ne "") { + $out .= rngx931($key1, $dt, $v, "VST"); + $key1 = ""; + $dt = ""; + $v = ""; + } + } + elsif ($tt == 8 ) { + if ($key1 ne "" && $dt ne "" && $v ne "") { + $out .= rngx931($key1, $dt, $v, "MCT"); + $key1 = ""; + $dt = ""; + $v = ""; + } + } + elsif ($tt == 9) { + if ($klen ne "" && $tlen ne "" && $key1 ne "" && $pt ne "") { + $out .= hmac_kat($klen, $tlen, $key1, $pt); + $key1 = ""; + $tlen = ""; + $klen = ""; + $pt = ""; + } + } + elsif ($tt == 10) { + if ($modulus ne "" && $capital_n > 0) { + $out .= dsa_pqggen_driver($modulus, $capital_n); + #$mod is not resetted + $capital_n = 0; + } + } + elsif ($tt == 11) { + if ($pt ne "" && $dsa_keyfile ne "") { + $out .= dsa_siggen($pt, $dsa_keyfile); + $pt = ""; + } + } + elsif ($tt == 12) { + if ($modulus ne "" && + $capital_p ne "" && + $capital_q ne "" && + $capital_g ne "" && + $capital_y ne "" && + $capital_r ne "" && + $signature ne "" && + $pt ne "") { + $out .= dsa_sigver($modulus, + $capital_p, + $capital_q, + $capital_g, + $capital_y, + $capital_r, + $signature, + $pt); + + # We do not clear the domain values PQG and + # the modulus value as they + # are specified only once in a file + # and we do not need to print them as they + # are already printed above + $capital_y = ""; + $capital_r = ""; + $signature = ""; + $pt = ""; + } + } + elsif ($tt == 13) { + if($modulus ne "" && + $e ne "" && + $xp1 ne "" && + $xp2 ne "" && + $Xp ne "" && + $xq1 ne "" && + $xq2 ne "" && + $Xq ne "") { + $out .= rsa_keygen($modulus, + $e, + $xp1, + $xp2, + $Xp, + $xq1, + $xq2, + $Xq); + $e = ""; + $xp1 = ""; + $xp2 = ""; + $Xp = ""; + $xq1 = ""; + $xq2 = ""; + $Xq = ""; + } + } + elsif ($tt > 0) { + die "Test case $tt not defined"; + } + } + + close IN; + $out =~ s/\n/\r\n/g; # make it a dos file + open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?"; + print OUT $out; + close OUT; + +} + +# Signalhandler +sub cleanup() { + unlink("rsa_siggen.tmp.$$"); + unlink("rsa_sigver.tmp.$$"); + unlink("rsa_sigver.tmp.$$.sig"); + unlink("rsa_sigver.tmp.$$.der"); + unlink("rsa_sigver.tmp.$$.cnf"); + unlink("dsa_siggen.tmp.$$"); + unlink("dsa_sigver.tmp.$$"); + unlink("dsa_sigver.tmp.$$.sig"); + exit; +} + +############################################################ +# +# let us pretend to be C :-) +sub main() { + + usage() unless @ARGV; + + getopts("DRI:", \%opt) or die "bad option"; + + ##### Set library + + if ( ! defined $opt{'I'} || $opt{'I'} eq 'openssl' ) { + print STDERR "Using OpenSSL interface functions\n"; + $encdec = \&openssl_encdec; + $rsa_sign = \&openssl_rsa_sign; + $rsa_verify = \&openssl_rsa_verify; + $gen_rsakey = \&openssl_gen_rsakey; + $hash = \&openssl_hash; + $state_cipher = \&openssl_state_cipher; + } elsif ( $opt{'I'} eq 'libgcrypt' ) { + print STDERR "Using libgcrypt interface functions\n"; + $encdec = \&libgcrypt_encdec; + $rsa_sign = \&libgcrypt_rsa_sign; + $rsa_verify = \&libgcrypt_rsa_verify; + $gen_rsakey = \&libgcrypt_gen_rsakey; + $rsa_derive = \&libgcrypt_rsa_derive; + $hash = \&libgcrypt_hash; + $state_cipher = \&libgcrypt_state_cipher; + $state_cipher_des = \&libgcrypt_state_cipher_des; + $state_rng = \&libgcrypt_state_rng; + $hmac = \&libgcrypt_hmac; + $dsa_pqggen = \&libgcrypt_dsa_pqggen; + $gen_dsakey = \&libgcrypt_gen_dsakey; + $dsa_sign = \&libgcrypt_dsa_sign; + $dsa_verify = \&libgcrypt_dsa_verify; + $dsa_genpubkey = \&libgcrypt_dsa_genpubkey; + } else { + die "Invalid interface option given"; + } + + my $infile=$ARGV[0]; + die "Error: Test vector file $infile not found" if (! -f $infile); + + my $outfile = $infile; + # let us add .rsp regardless whether we could strip .req + $outfile =~ s/\.req$//; + if ($opt{'R'}) { + $outfile .= ".rc4"; + } else { + $outfile .= ".rsp"; + } + if (-f $outfile) { + die "Output file $outfile could not be removed: $?" + unless unlink($outfile); + } + print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n"; + + #Signal handler + $SIG{HUP} = \&cleanup; + $SIG{INT} = \&cleanup; + $SIG{QUIT} = \&cleanup; + $SIG{TERM} = \&cleanup; + + # Do the job + parse($infile, $outfile); + + cleanup(); + +} + +########################################### +# Call it +main(); +1; diff --git a/tests/cavs_tests.sh b/tests/cavs_tests.sh new file mode 100755 index 0000000..b9aa621 --- /dev/null +++ b/tests/cavs_tests.sh @@ -0,0 +1,135 @@ +#!/bin/sh +# Run FIPS CAVS tests +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Instructions: +# +# 1. Cd to the libgcrypt/tests directory +# +# 2. Unpack the test vector tarball into subdirectory named "cavs". +# An example directory layout after unpacking might be: +# libgcrypt/tests/cavs/AES/req/CBCGFSbox128.req +# libgcrypt/tests/cavs/AES/req/CFB128MCT128.req +# +# Note that below the "cavs" directory there should only be one +# directory part named "req". Further avoid directory part +# names "resp". +# +# 3. Run this script from the libgcrypt/tests directory: +# ./cavs_tests.sh +# +# 4. Send the result file cavs/CAVS_results-*.zip to the testing lab. +# + +# Stop script if something unexpected happens. +set -e + +# A global flag to keep track of errors. +errors_seen_file="$(pwd)/.#cavs_test.errors_seen.tmp" +[ -f "$errors_seen_file" ] && rm "$errors_seen_file" +continue_mode=no +[ "$1" = "--continue" ] && continue_mode=yes + + +# Function to run one test. +# The argument is the request file name. +function run_one_test () { + local reqfile="$1" + local rspfile + local tmprspfile + local respdir + local dflag="" + + tmprspfile=$(echo "$reqfile" | sed 's,.req$,.rsp,') + rspfile=$(echo "$tmprspfile" | sed 's,/req/,/resp/,' ) + respdir=$(dirname "$rspfile") + [ -f "$tmprspfile" ] && rm "$tmprspfile" + [ -d "$respdir" ] || mkdir "$respdir" + [ -f "$rspfile" ] && rm "$rspfile" + + if echo "$reqfile" | grep '/DSA/req/' >/dev/null 2>/dev/null; then + dflag="-D" + fi + + if ./cavs_driver.pl -I libgcrypt $dflag "$reqfile"; then + if [ -f "$tmprspfile" ]; then + mv "$tmprspfile" "$rspfile" + else + echo "failed test: $reqfile" >&2 + : >"$errors_seen_file" + fi + else + echo "failed test: $reqfile rc=$?" >&2 + : >"$errors_seen_file" + fi +} + + + +# Save date and system architecure to construct the output archive name +DATE=$(date +%Y%m%d) +ARCH=$(arch || echo unknown) +result_file="CAVS_results-$ARCH-$DATE.zip" + +for f in fipsdrv cavs_driver.pl; do + if [ ! -f "./$f" ]; then + echo "required program \"$f\" missing in current directory" >&2 + exit 2 + fi +done +if [ ! -d cavs ]; then + echo "required directory \"cavs\" missing below current directory" >&2 + exit 2 +fi +if [ ! zip -h >/dev/null 2>&1 ]; then + echo "required program \"zip\" is not installed on this system" >&2 + exit 2 +fi + +# Set the PATH to this directory so that the perl script is able to +# find the test drivers. +PATH=.:$PATH + +# Check whether there are any stale response files +find cavs -type f -name "*.rsp" | ( while read f ; do + echo "Stale response file: $f" >&2 + any=yes +done +if [ "$any" = "yes" ]; then + echo "Stale response files found" >&2 + if [ "$continue_mode" != "yes" ]; then + echo "use option --continue if that is not a problem" >&2 + exit 1 + fi +fi +) || exit 1 + + +# Find all test files and run the tests. +find cavs -type f -name "*.req" | while read f ; do + echo "Running test file $f" >&2 + run_one_test "$f" + if [ -f "$errors_seen_file" ]; then + break; + fi +done + +if [ -f "$errors_seen_file" ]; then + rm "$errors_seen_file" + echo "Error encountered - not packing up response file" >&2 + exit 1 +fi + +echo "Packing up all response files" >&2 +cd cavs +find . -type f -name "*rsp" -print | zip -@ "$result_file" + +echo "Result file is: cavs/$result_file" >&2 diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c new file mode 100644 index 0000000..cdb507b --- /dev/null +++ b/tests/fips186-dsa.c @@ -0,0 +1,465 @@ +/* fips186-dsa.c - FIPS 186 DSA tests + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include + +#ifdef _GCRYPT_IN_LIBGCRYPT +# include "../src/gcrypt.h" +#else +# include +#endif + + +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + +static int verbose; +static int error_count; + +static void +info (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +static void +show_sexp (const char *prefix, gcry_sexp_t a) +{ + char *buf; + size_t size; + + if (prefix) + fputs (prefix, stderr); + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = gcry_xmalloc (size); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); + gcry_free (buf); +} + +static gcry_mpi_t +mpi_from_string (const char *string) +{ + gpg_error_t err; + gcry_mpi_t a; + + err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, string, 0, NULL); + if (err) + die ("error converting string to mpi: %s\n", gpg_strerror (err)); + return a; +} + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +data_from_hex (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = gcry_xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + die ("error parsing hex string `%s'\n", string); + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + + +static void +extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected) +{ + gcry_sexp_t l1; + gcry_mpi_t a, b; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + b = mpi_from_string (expected); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( gcry_mpi_cmp (a, b) ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_mpi_release (b); + gcry_mpi_release (a); + gcry_sexp_release (l1); +} + + +static void +extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) +{ + gcry_sexp_t l1; + const void *a; + size_t alen; + void *b; + size_t blen; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_data (l1, 1, &alen); + b = data_from_hex (expected, &blen); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( alen != blen || memcmp (a, b, alen) ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_free (b); + gcry_sexp_release (l1); +} + +static void +extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected) +{ + gcry_sexp_t l1; + char *a; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_string (l1, 1); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( strtoul (a, NULL, 10) != expected ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_free (a); + gcry_sexp_release (l1); +} + + +static void +check_dsa_gen_186_2 (void) +{ + static struct { + int nbits; + const char *p, *q, *g; + const char *seed; + int counter; + const char *h; + } tbl[] = { + /* These tests are from FIPS 186-2, B.3.1. */ + { + 1024, + "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" + "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" + "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" + "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69", + "9c916d121de9a03f71fb21bc2e1c0d116f065a4f", + "8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" + "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" + "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" + "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44", + "0cb1990c1fd3626055d7a0096f8fa99807399871", + 98, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002" + }, + { + 1024, + "f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f" + "8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb" + "0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be" + "3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9", + "f8751166cf4f6f3b07c081fd2a9071f23ca1988d", + "1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62" + "4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a" + "665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c" + "4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33", + "34b3520d45d240a8861b82c8b61ffa16e67b5cce", + 622, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7" + "b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4" + "55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc" + "1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad", + "d32b29f065c1394a30490b6fcbf812a32a8634ab", + "06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1" + "ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714" + "c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231" + "80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2", + "b6ec750da2f824cb42c5f7e28c81350d97f75125", + 185, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b" + "ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f" + "d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b" + "c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5", + "de822c03445b77cec4ad3a6fb0ca39ff97059ddf", + "65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371" + "681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b" + "848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69" + "1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748", + "cd2221dd73815a75224e9fde7faf52829b81ac7a", + 62, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803" + "ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891" + "354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9" + "8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227", + "c6d786643d2acfc6b8d576863fda8cfbfbd5e03f", + "2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d" + "af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d" + "5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb" + "e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb", + "73483e697599871af983a281e3afa22e0ed86b68", + 272, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + + /* These tests are generated by the OpenSSL FIPS version. */ + { + 1024, + "A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C" + "A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255" + "EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033" + "11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9", + "C643946CEA8748E12D430C48DB038F9165814389", + "59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16" + "892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC" + "B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7" + "44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225", + "02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd", + 50, + "02" + }, + { + 1024, + "9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987" + "6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3" + "D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450" + "04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5", + "AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7", + "74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701" + "95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E" + "039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A" + "C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498", + "6481a12a50384888ee84b61024f7c9c685d6ac96", + 289, + "02" + }, + { + 1024, + + "B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828" + "1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63" + "5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503" + "B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF", + "EA649C04911FAB5A41440287A517EF752A40354B", + "88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162" + "01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194" + "93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C" + "858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696", + "5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a", + 626, + "02" + }, + { + 1024, + "F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C" + "F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D" + "5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977" + "CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD", + "A40D9EE456AED4C8A653FDB47B6629C0B843FE8F", + "DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE" + "700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614" + "F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7" + "2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67", + "8a9a57706f69f4f566252cdf6d5cbfdf2020150b", + 397, + "02" + }, + { + 1024, + "D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068" + "29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934" + "96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A" + "093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B", + "D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5", + "468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC" + "58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5" + "7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159" + "928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839", + "30b3599944a914a330a3f49d11ec88f555422aef", + 678, + "02" + } + }; + gpg_error_t err; + int tno; + gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; + gcry_sexp_t l1; + + for (tno = 0; tno < DIM (tbl); tno++) + { + if (verbose) + info ("generating FIPS 186-2 test key %d\n", tno); + + { + void *data; + size_t datalen; + + data = data_from_hex (tbl[tno].seed, &datalen); + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (dsa (nbits %d)(use-fips186-2)" + "(derive-parms(seed %b))))", + tbl[tno].nbits, (int)datalen, data); + gcry_free (data); + } + if (err) + die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); + + err = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (err) + { + fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); + continue; + } + + if (verbose > 1) + show_sexp ("generated key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + fail ("public part missing in key %d\n", tno); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + fail ("private part missing in key %d\n", tno); + + l1 = gcry_sexp_find_token (key, "misc-key-info", 0); + if (!l1) + fail ("misc_key_info part missing in key %d\n", tno); + seed_values = gcry_sexp_find_token (l1, "seed-values", 0); + if (!seed_values) + fail ("seed-values part missing in key %d\n", tno); + gcry_sexp_release (l1); + + extract_cmp_mpi (sec_key, "p", tbl[tno].p); + extract_cmp_mpi (sec_key, "q", tbl[tno].q); + extract_cmp_mpi (sec_key, "g", tbl[tno].g); + + extract_cmp_data (seed_values, "seed", tbl[tno].seed); + extract_cmp_int (seed_values, "counter", tbl[tno].counter); + extract_cmp_mpi (seed_values, "h", tbl[tno].h); + + gcry_sexp_release (seed_values); + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + gcry_sexp_release (key); + } +} + + + +int +main (int argc, char **argv) +{ + int debug = 0; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + { + verbose = 2; + debug = 1; + } + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version ("1.4.4")) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + + check_dsa_gen_186_2 (); + + + return error_count ? 1 : 0; +} diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c new file mode 100644 index 0000000..f80e30c --- /dev/null +++ b/tests/fipsdrv.c @@ -0,0 +1,2526 @@ +/* fipsdrv.c - A driver to help with FIPS CAVS tests. + Copyright (C) 2008 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +# include /* We need setmode(). */ +#else +# include +#endif +#include +#include + +#ifdef _GCRYPT_IN_LIBGCRYPT +# include "../src/gcrypt.h" +#else +# include +# define PACKAGE_BUGREPORT "devnull@example.org" +# define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]" +#endif + + +#define PGM "fipsdrv" + +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + +#define PRIV_CTL_INIT_EXTRNG_TEST 58 +#define PRIV_CTL_RUN_EXTRNG_TEST 59 +#define PRIV_CTL_DEINIT_EXTRNG_TEST 60 +#define PRIV_CTL_DISABLE_WEAK_KEY 61 +#define PRIV_CTL_GET_INPUT_VECTOR 62 + + +/* Verbose mode flag. */ +static int verbose; + +/* Binary input flag. */ +static int binary_input; + +/* Binary output flag. */ +static int binary_output; + +/* Base64 output flag. */ +static int base64_output; + +/* We need to know whether we are in loop_mode. */ +static int loop_mode; + +/* If true some functions are modified to print the output in the CAVS + response file format. */ +static int standalone_mode; + + +/* ASN.1 classes. */ +enum +{ + UNIVERSAL = 0, + APPLICATION = 1, + ASNCONTEXT = 2, + PRIVATE = 3 +}; + + +/* ASN.1 tags. */ +enum +{ + TAG_NONE = 0, + TAG_BOOLEAN = 1, + TAG_INTEGER = 2, + TAG_BIT_STRING = 3, + TAG_OCTET_STRING = 4, + TAG_NULL = 5, + TAG_OBJECT_ID = 6, + TAG_OBJECT_DESCRIPTOR = 7, + TAG_EXTERNAL = 8, + TAG_REAL = 9, + TAG_ENUMERATED = 10, + TAG_EMBEDDED_PDV = 11, + TAG_UTF8_STRING = 12, + TAG_REALTIVE_OID = 13, + TAG_SEQUENCE = 16, + TAG_SET = 17, + TAG_NUMERIC_STRING = 18, + TAG_PRINTABLE_STRING = 19, + TAG_TELETEX_STRING = 20, + TAG_VIDEOTEX_STRING = 21, + TAG_IA5_STRING = 22, + TAG_UTC_TIME = 23, + TAG_GENERALIZED_TIME = 24, + TAG_GRAPHIC_STRING = 25, + TAG_VISIBLE_STRING = 26, + TAG_GENERAL_STRING = 27, + TAG_UNIVERSAL_STRING = 28, + TAG_CHARACTER_STRING = 29, + TAG_BMP_STRING = 30 +}; + +/* ASN.1 Parser object. */ +struct tag_info +{ + int class; /* Object class. */ + unsigned long tag; /* The tag of the object. */ + unsigned long length; /* Length of the values. */ + int nhdr; /* Length of the header (TL). */ + unsigned int ndef:1; /* The object has an indefinite length. */ + unsigned int cons:1; /* This is a constructed object. */ +}; + + + +/* Print a error message and exit the process with an error code. */ +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + + +static void +showhex (const char *prefix, const void *buffer, size_t length) +{ + const unsigned char *p = buffer; + + if (prefix) + fprintf (stderr, PGM ": %s: ", prefix); + while (length-- ) + fprintf (stderr, "%02X", *p++); + if (prefix) + putc ('\n', stderr); +} + +/* static void */ +/* show_sexp (const char *prefix, gcry_sexp_t a) */ +/* { */ +/* char *buf; */ +/* size_t size; */ + +/* if (prefix) */ +/* fputs (prefix, stderr); */ +/* size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); */ +/* buf = gcry_xmalloc (size); */ + +/* gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); */ +/* fprintf (stderr, "%.*s", (int)size, buf); */ +/* gcry_free (buf); */ +/* } */ + + +/* Convert STRING consisting of hex characters into its binary + representation and store that at BUFFER. BUFFER needs to be of + LENGTH bytes. The function checks that the STRING will convert + exactly to LENGTH bytes. The string is delimited by either end of + string or a white space character. The function returns -1 on + error or the length of the parsed string. */ +static int +hex2bin (const char *string, void *buffer, size_t length) +{ + int i; + const char *s = string; + + for (i=0; i < length; ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + return -1; /* Invalid hex digits. */ + ((unsigned char*)buffer)[i++] = xtoi_2 (s); + s += 2; + } + if (*s && (!my_isascii (*s) || !isspace (*s)) ) + return -1; /* Not followed by Nul or white space. */ + if (i != length) + return -1; /* Not of expected length. */ + if (*s) + s++; /* Skip the delimiter. */ + return s - string; +} + + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +hex2buffer (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = gcry_xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + return NULL; /* Invalid hex digits. */ + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + + +static char * +read_textline (FILE *fp) +{ + char line[256]; + char *p; + int any = 0; + + /* Read line but skip over initial empty lines. */ + do + { + do + { + if (!fgets (line, sizeof line, fp)) + { + if (feof (fp)) + return NULL; + die ("error reading input line: %s\n", strerror (errno)); + } + p = strchr (line, '\n'); + if (p) + *p = 0; + p = line + (*line? (strlen (line)-1):0); + for ( ;p > line; p--) + if (my_isascii (*p) && isspace (*p)) + *p = 0; + } + while (!any && !*line); + any = 1; + } + while (*line == '#'); /* Always skip comment lines. */ + if (verbose > 1) + fprintf (stderr, PGM ": received line: %s\n", line); + return gcry_xstrdup (line); +} + +static char * +read_hexline (FILE *fp, size_t *retlen) +{ + char *line, *p; + + line = read_textline (fp); + if (!line) + return NULL; + p = hex2buffer (line, retlen); + if (!p) + die ("error decoding hex string on input\n"); + gcry_free (line); + return p; +} + +static void +skip_to_empty_line (FILE *fp) +{ + char line[256]; + char *p; + + do + { + if (!fgets (line, sizeof line, fp)) + { + if (feof (fp)) + return; + die ("error reading input line: %s\n", strerror (errno)); + } + p = strchr (line, '\n'); + if (p) + *p =0; + } + while (*line); +} + + + +/* Read a file from stream FP into a newly allocated buffer and return + that buffer. The valid length of the buffer is stored at R_LENGTH. + Returns NULL on failure. If decode is set, the file is assumed to + be hex encoded and the decoded content is returned. */ +static void * +read_file (FILE *fp, int decode, size_t *r_length) +{ + char *buffer; + size_t buflen; + size_t nread, bufsize = 0; + + *r_length = 0; +#define NCHUNK 8192 +#ifdef HAVE_DOSISH_SYSTEM + setmode (fileno(fp), O_BINARY); +#endif + buffer = NULL; + buflen = 0; + do + { + bufsize += NCHUNK; + if (!buffer) + buffer = gcry_xmalloc (bufsize); + else + buffer = gcry_xrealloc (buffer, bufsize); + + nread = fread (buffer + buflen, 1, NCHUNK, fp); + if (nread < NCHUNK && ferror (fp)) + { + gcry_free (buffer); + return NULL; + } + buflen += nread; + } + while (nread == NCHUNK); +#undef NCHUNK + if (decode) + { + const char *s; + char *p; + + for (s=buffer,p=buffer,nread=0; nread+1 < buflen; s += 2, nread +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + { + gcry_free (buffer); + return NULL; /* Invalid hex digits. */ + } + *(unsigned char*)p++ = xtoi_2 (s); + } + if (nread != buflen) + { + gcry_free (buffer); + return NULL; /* Odd number of hex digits. */ + } + buflen = p - buffer; + } + + *r_length = buflen; + return buffer; +} + +/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Returns + the new length of the buffer. Dies on error. */ +static size_t +base64_decode (char *buffer, size_t length) +{ + static unsigned char const asctobin[128] = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + int idx = 0; + unsigned char val = 0; + int c = 0; + char *d, *s; + int lfseen = 1; + + /* Find BEGIN line. */ + for (s=buffer; length; length--, s++) + { + if (lfseen && *s == '-' && length > 11 && !memcmp (s, "-----BEGIN ", 11)) + { + for (; length && *s != '\n'; length--, s++) + ; + break; + } + lfseen = (*s == '\n'); + } + + /* Decode until pad character or END line. */ + for (d=buffer; length; length--, s++) + { + if (lfseen && *s == '-' && length > 9 && !memcmp (s, "-----END ", 9)) + break; + if ((lfseen = (*s == '\n')) || *s == ' ' || *s == '\r' || *s == '\t') + continue; + if (*s == '=') + { + /* Pad character: stop */ + if (idx == 1) + *d++ = val; + break; + } + + if ( (*s & 0x80) || (c = asctobin[*(unsigned char *)s]) == 0xff) + die ("invalid base64 character %02X at pos %d detected\n", + *(unsigned char*)s, (int)(s-buffer)); + + switch (idx) + { + case 0: + val = c << 2; + break; + case 1: + val |= (c>>4)&3; + *d++ = val; + val = (c<<4)&0xf0; + break; + case 2: + val |= (c>>2)&15; + *d++ = val; + val = (c<<6)&0xc0; + break; + case 3: + val |= c&0x3f; + *d++ = val; + break; + } + idx = (idx+1) % 4; + } + + return d - buffer; +} + + +/* Parse the buffer at the address BUFFER which consists of the number + of octets as stored at BUFLEN. Return the tag and the length part + from the TLV triplet. Update BUFFER and BUFLEN on success. Checks + that the encoded length does not exhaust the length of the provided + buffer. */ +static int +parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti) +{ + int c; + unsigned long tag; + const unsigned char *buf = *buffer; + size_t length = *buflen; + + ti->length = 0; + ti->ndef = 0; + ti->nhdr = 0; + + /* Get the tag */ + if (!length) + return -1; /* Premature EOF. */ + c = *buf++; length--; + ti->nhdr++; + + ti->class = (c & 0xc0) >> 6; + ti->cons = !!(c & 0x20); + tag = (c & 0x1f); + + if (tag == 0x1f) + { + tag = 0; + do + { + tag <<= 7; + if (!length) + return -1; /* Premature EOF. */ + c = *buf++; length--; + ti->nhdr++; + tag |= (c & 0x7f); + } + while ( (c & 0x80) ); + } + ti->tag = tag; + + /* Get the length */ + if (!length) + return -1; /* Premature EOF. */ + c = *buf++; length--; + ti->nhdr++; + + if ( !(c & 0x80) ) + ti->length = c; + else if (c == 0x80) + ti->ndef = 1; + else if (c == 0xff) + return -1; /* Forbidden length value. */ + else + { + unsigned long len = 0; + int count = c & 0x7f; + + for (; count; count--) + { + len <<= 8; + if (!length) + return -1; /* Premature EOF. */ + c = *buf++; length--; + ti->nhdr++; + len |= (c & 0xff); + } + ti->length = len; + } + + if (ti->class == UNIVERSAL && !ti->tag) + ti->length = 0; + + if (ti->length > length) + return -1; /* Data larger than buffer. */ + + *buffer = buf; + *buflen = length; + return 0; +} + + +/* Read the file FNAME assuming it is a PEM encoded private key file + and return an S-expression. With SHOW set, the key parameters are + printed. */ +static gcry_sexp_t +read_private_key_file (const char *fname, int show) +{ + gcry_error_t err; + FILE *fp; + char *buffer; + size_t buflen; + const unsigned char *der; + size_t derlen; + struct tag_info ti; + gcry_mpi_t keyparms[8]; + int n_keyparms = 8; + int idx; + gcry_sexp_t s_key; + + fp = fopen (fname, binary_input?"rb":"r"); + if (!fp) + die ("can't open `%s': %s\n", fname, strerror (errno)); + buffer = read_file (fp, 0, &buflen); + if (!buffer) + die ("error reading `%s'\n", fname); + fclose (fp); + + buflen = base64_decode (buffer, buflen); + + /* Parse the ASN.1 structure. */ + der = (const unsigned char*)buffer; + derlen = buflen; + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef) + goto bad_asn1; + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef) + goto bad_asn1; + if (ti.length != 1 || *der) + goto bad_asn1; /* The value of the first integer is no 0. */ + der += ti.length; derlen -= ti.length; + + for (idx=0; idx < n_keyparms; idx++) + { + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef) + goto bad_asn1; + if (show) + { + char prefix[2]; + + prefix[0] = idx < 8? "nedpq12u"[idx] : '?'; + prefix[1] = 0; + showhex (prefix, der, ti.length); + } + err = gcry_mpi_scan (keyparms+idx, GCRYMPI_FMT_USG, der, ti.length,NULL); + if (err) + die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err)); + der += ti.length; derlen -= ti.length; + } + if (idx != n_keyparms) + die ("not enough RSA key parameters\n"); + + gcry_free (buffer); + + /* Convert from OpenSSL parameter ordering to the OpenPGP order. */ + /* First check that p < q; if not swap p and q and recompute u. */ + if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0) + { + gcry_mpi_swap (keyparms[3], keyparms[4]); + gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]); + } + + /* Build the S-expression. */ + err = gcry_sexp_build (&s_key, NULL, + "(private-key(rsa(n%m)(e%m)" + /**/ "(d%m)(p%m)(q%m)(u%m)))", + keyparms[0], keyparms[1], keyparms[2], + keyparms[3], keyparms[4], keyparms[7] ); + if (err) + die ("error building S-expression: %s\n", gpg_strerror (err)); + + for (idx=0; idx < n_keyparms; idx++) + gcry_mpi_release (keyparms[idx]); + + return s_key; + + bad_asn1: + die ("invalid ASN.1 structure in `%s'\n", fname); + return NULL; /*NOTREACHED*/ +} + + +/* Read the file FNAME assuming it is a PEM encoded public key file + and return an S-expression. With SHOW set, the key parameters are + printed. */ +static gcry_sexp_t +read_public_key_file (const char *fname, int show) +{ + gcry_error_t err; + FILE *fp; + char *buffer; + size_t buflen; + const unsigned char *der; + size_t derlen; + struct tag_info ti; + gcry_mpi_t keyparms[2]; + int n_keyparms = 2; + int idx; + gcry_sexp_t s_key; + + fp = fopen (fname, binary_input?"rb":"r"); + if (!fp) + die ("can't open `%s': %s\n", fname, strerror (errno)); + buffer = read_file (fp, 0, &buflen); + if (!buffer) + die ("error reading `%s'\n", fname); + fclose (fp); + + buflen = base64_decode (buffer, buflen); + + /* Parse the ASN.1 structure. */ + der = (const unsigned char*)buffer; + derlen = buflen; + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef) + goto bad_asn1; + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef) + goto bad_asn1; + /* We skip the description of the key parameters and assume it is RSA. */ + der += ti.length; derlen -= ti.length; + + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_BIT_STRING || ti.class || ti.cons || ti.ndef) + goto bad_asn1; + if (ti.length < 1 || *der) + goto bad_asn1; /* The number of unused bits needs to be 0. */ + der += 1; derlen -= 1; + + /* Parse the BIT string. */ + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef) + goto bad_asn1; + + for (idx=0; idx < n_keyparms; idx++) + { + if ( parse_tag (&der, &derlen, &ti) + || ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef) + goto bad_asn1; + if (show) + { + char prefix[2]; + + prefix[0] = idx < 2? "ne"[idx] : '?'; + prefix[1] = 0; + showhex (prefix, der, ti.length); + } + err = gcry_mpi_scan (keyparms+idx, GCRYMPI_FMT_USG, der, ti.length,NULL); + if (err) + die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err)); + der += ti.length; derlen -= ti.length; + } + if (idx != n_keyparms) + die ("not enough RSA key parameters\n"); + + gcry_free (buffer); + + /* Build the S-expression. */ + err = gcry_sexp_build (&s_key, NULL, + "(public-key(rsa(n%m)(e%m)))", + keyparms[0], keyparms[1] ); + if (err) + die ("error building S-expression: %s\n", gpg_strerror (err)); + + for (idx=0; idx < n_keyparms; idx++) + gcry_mpi_release (keyparms[idx]); + + return s_key; + + bad_asn1: + die ("invalid ASN.1 structure in `%s'\n", fname); + return NULL; /*NOTREACHED*/ +} + + + +/* Read the file FNAME assuming it is a binary signature result and + return an an S-expression suitable for gcry_pk_verify. */ +static gcry_sexp_t +read_sig_file (const char *fname) +{ + gcry_error_t err; + FILE *fp; + char *buffer; + size_t buflen; + gcry_mpi_t tmpmpi; + gcry_sexp_t s_sig; + + fp = fopen (fname, "rb"); + if (!fp) + die ("can't open `%s': %s\n", fname, strerror (errno)); + buffer = read_file (fp, 0, &buflen); + if (!buffer) + die ("error reading `%s'\n", fname); + fclose (fp); + + err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, buffer, buflen, NULL); + if (!err) + err = gcry_sexp_build (&s_sig, NULL, + "(sig-val(rsa(s %m)))", tmpmpi); + if (err) + die ("error building S-expression: %s\n", gpg_strerror (err)); + gcry_mpi_release (tmpmpi); + gcry_free (buffer); + + return s_sig; +} + + +/* Read an S-expression from FNAME. */ +static gcry_sexp_t +read_sexp_from_file (const char *fname) +{ + gcry_error_t err; + FILE *fp; + char *buffer; + size_t buflen; + gcry_sexp_t sexp; + + fp = fopen (fname, "rb"); + if (!fp) + die ("can't open `%s': %s\n", fname, strerror (errno)); + buffer = read_file (fp, 0, &buflen); + if (!buffer) + die ("error reading `%s'\n", fname); + fclose (fp); + if (!buflen) + die ("error: file `%s' is empty\n", fname); + + err = gcry_sexp_create (&sexp, buffer, buflen, 1, gcry_free); + if (err) + die ("error parsing `%s': %s\n", fname, gpg_strerror (err)); + + return sexp; +} + + +static void +print_buffer (const void *buffer, size_t length) +{ + int writerr = 0; + + if (base64_output) + { + static const unsigned char bintoasc[64+1] = + ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"); + const unsigned char *p; + unsigned char inbuf[4]; + char outbuf[4]; + int idx, quads; + + idx = quads = 0; + for (p = buffer; length; p++, length--) + { + inbuf[idx++] = *p; + if (idx > 2) + { + outbuf[0] = bintoasc[(*inbuf>>2)&077]; + outbuf[1] = bintoasc[(((*inbuf<<4)&060) + |((inbuf[1] >> 4)&017))&077]; + outbuf[2] = bintoasc[(((inbuf[1]<<2)&074) + |((inbuf[2]>>6)&03))&077]; + outbuf[3] = bintoasc[inbuf[2]&077]; + if (fwrite (outbuf, 4, 1, stdout) != 1) + writerr = 1; + idx = 0; + if (++quads >= (64/4)) + { + if (fwrite ("\n", 1, 1, stdout) != 1) + writerr = 1; + quads = 0; + } + } + } + if (idx) + { + outbuf[0] = bintoasc[(*inbuf>>2)&077]; + if (idx == 1) + { + outbuf[1] = bintoasc[((*inbuf<<4)&060)&077]; + outbuf[2] = outbuf[3] = '='; + } + else + { + outbuf[1] = bintoasc[(((*inbuf<<4)&060) + |((inbuf[1]>>4)&017))&077]; + outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077]; + outbuf[3] = '='; + } + if (fwrite (outbuf, 4, 1, stdout) != 1) + writerr = 1; + quads++; + } + if (quads && fwrite ("\n", 1, 1, stdout) != 1) + writerr = 1; + } + else if (binary_output) + { + if (fwrite (buffer, length, 1, stdout) != 1) + writerr++; + } + else + { + const unsigned char *p = buffer; + + if (verbose > 1) + showhex ("sent line", buffer, length); + while (length-- && !ferror (stdout) ) + printf ("%02X", *p++); + if (ferror (stdout)) + writerr++; + } + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + { +#ifndef HAVE_W32_SYSTEM + if (loop_mode && errno == EPIPE) + loop_mode = 0; + else +#endif + die ("writing output failed: %s\n", strerror (errno)); + } +} + + +/* Print an MPI on a line. */ +static void +print_mpi_line (gcry_mpi_t a, int no_lz) +{ + unsigned char *buf, *p; + gcry_error_t err; + int writerr = 0; + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a); + if (err) + die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err)); + + p = buf; + if (no_lz && p[0] == '0' && p[1] == '0' && p[2]) + p += 2; + + printf ("%s\n", p); + if (ferror (stdout)) + writerr++; + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + die ("writing output failed: %s\n", strerror (errno)); + gcry_free (buf); +} + + +/* Print some data on hex format on a line. */ +static void +print_data_line (const void *data, size_t datalen) +{ + const unsigned char *p = data; + int writerr = 0; + + while (data && datalen-- && !ferror (stdout) ) + printf ("%02X", *p++); + putchar ('\n'); + if (ferror (stdout)) + writerr++; + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + die ("writing output failed: %s\n", strerror (errno)); +} + +/* Print the S-expression A to the stream FP. */ +static void +print_sexp (gcry_sexp_t a, FILE *fp) +{ + char *buf; + size_t size; + + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = gcry_xmalloc (size); + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + if (fwrite (buf, size, 1, fp) != 1) + die ("error writing to stream: %s\n", strerror (errno)); + gcry_free (buf); +} + + + + +static gcry_error_t +init_external_rng_test (void **r_context, + unsigned int flags, + const void *key, size_t keylen, + const void *seed, size_t seedlen, + const void *dt, size_t dtlen) +{ + return gcry_control (PRIV_CTL_INIT_EXTRNG_TEST, + r_context, flags, + key, keylen, + seed, seedlen, + dt, dtlen); +} + +static gcry_error_t +run_external_rng_test (void *context, void *buffer, size_t buflen) +{ + return gcry_control (PRIV_CTL_RUN_EXTRNG_TEST, context, buffer, buflen); +} + +static void +deinit_external_rng_test (void *context) +{ + gcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context); +} + + +/* Given an OpenSSL cipher name NAME, return the Libgcrypt algirithm + identified and store the libgcrypt mode at R_MODE. Returns 0 on + error. */ +static int +map_openssl_cipher_name (const char *name, int *r_mode) +{ + static struct { + const char *name; + int algo; + int mode; + } table[] = + { + { "bf-cbc", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC }, + { "bf", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC }, + { "bf-cfb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB }, + { "bf-ecb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB }, + { "bf-ofb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB }, + + { "cast-cbc", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC }, + { "cast", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC }, + { "cast5-cbc", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC }, + { "cast5-cfb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CFB }, + { "cast5-ecb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_ECB }, + { "cast5-ofb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_OFB }, + + { "des-cbc", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC }, + { "des", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC }, + { "des-cfb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB }, + { "des-ofb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_OFB }, + { "des-ecb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB }, + + { "des-ede3-cbc", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC }, + { "des-ede3", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB }, + { "des3", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC }, + { "des-ede3-cfb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CFB }, + { "des-ede3-ofb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_OFB }, + + { "rc4", GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM }, + + { "aes-128-cbc", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC }, + { "aes-128", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC }, + { "aes-128-cfb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB }, + { "aes-128-ecb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB }, + { "aes-128-ofb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_OFB }, + + { "aes-192-cbc", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC }, + { "aes-192", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC }, + { "aes-192-cfb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB }, + { "aes-192-ecb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB }, + { "aes-192-ofb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB }, + + { "aes-256-cbc", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC }, + { "aes-256", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC }, + { "aes-256-cfb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB }, + { "aes-256-ecb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB }, + { "aes-256-ofb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB }, + + { NULL, 0 , 0 } + }; + int idx; + + for (idx=0; table[idx].name; idx++) + if (!strcmp (name, table[idx].name)) + { + *r_mode = table[idx].mode; + return table[idx].algo; + } + *r_mode = 0; + return 0; +} + + + +/* Run an encrypt or decryption operations. If DATA is NULL the + function reads its input in chunks of size DATALEN from fp and + processes it and writes it out until EOF. */ +static void +run_encrypt_decrypt (int encrypt_mode, + int cipher_algo, int cipher_mode, + const void *iv_buffer, size_t iv_buflen, + const void *key_buffer, size_t key_buflen, + const void *data, size_t datalen, FILE *fp) +{ + gpg_error_t err; + gcry_cipher_hd_t hd; + void *outbuf; + size_t outbuflen; + void *inbuf; + size_t inbuflen; + size_t blocklen; + + err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0); + if (err) + die ("gcry_cipher_open failed for algo %d, mode %d: %s\n", + cipher_algo, cipher_mode, gpg_strerror (err)); + + blocklen = gcry_cipher_get_algo_blklen (cipher_algo); + assert (blocklen); + + gcry_cipher_ctl (hd, PRIV_CTL_DISABLE_WEAK_KEY, NULL, 0); + + err = gcry_cipher_setkey (hd, key_buffer, key_buflen); + if (err) + die ("gcry_cipher_setkey failed with keylen %u: %s\n", + (unsigned int)key_buflen, gpg_strerror (err)); + + if (iv_buffer) + { + err = gcry_cipher_setiv (hd, iv_buffer, iv_buflen); + if (err) + die ("gcry_cipher_setiv failed with ivlen %u: %s\n", + (unsigned int)iv_buflen, gpg_strerror (err)); + } + + inbuf = data? NULL : gcry_xmalloc (datalen); + outbuflen = datalen; + outbuf = gcry_xmalloc (outbuflen < blocklen? blocklen:outbuflen); + + do + { + if (inbuf) + { + int nread = fread (inbuf, 1, datalen, fp); + if (nread < (int)datalen && ferror (fp)) + die ("error reading input\n"); + data = inbuf; + inbuflen = nread; + } + else + inbuflen = datalen; + + if (encrypt_mode) + err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen); + else + err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen); + if (err) + die ("gcry_cipher_%scrypt failed: %s\n", + encrypt_mode? "en":"de", gpg_strerror (err)); + + print_buffer (outbuf, outbuflen); + } + while (inbuf); + + gcry_cipher_close (hd); + gcry_free (outbuf); + gcry_free (inbuf); +} + + +static void +get_current_iv (gcry_cipher_hd_t hd, void *buffer, size_t buflen) +{ + unsigned char tmp[17]; + + if (gcry_cipher_ctl (hd, PRIV_CTL_GET_INPUT_VECTOR, tmp, sizeof tmp)) + die ("error getting current input vector\n"); + if (buflen > *tmp) + die ("buffer too short to store the current input vector\n"); + memcpy (buffer, tmp+1, *tmp); +} + +/* Run the inner loop of the CAVS monte carlo test. */ +static void +run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode, + const void *iv_buffer, size_t iv_buflen, + const void *key_buffer, size_t key_buflen, + const void *data, size_t datalen, int iterations) +{ + gpg_error_t err; + gcry_cipher_hd_t hd; + size_t blocklen; + int count; + char input[16]; + char output[16]; + char last_output[16]; + char last_last_output[16]; + char last_iv[16]; + + + err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0); + if (err) + die ("gcry_cipher_open failed for algo %d, mode %d: %s\n", + cipher_algo, cipher_mode, gpg_strerror (err)); + + blocklen = gcry_cipher_get_algo_blklen (cipher_algo); + if (!blocklen || blocklen > sizeof output) + die ("invalid block length %d\n", blocklen); + + + gcry_cipher_ctl (hd, PRIV_CTL_DISABLE_WEAK_KEY, NULL, 0); + + err = gcry_cipher_setkey (hd, key_buffer, key_buflen); + if (err) + die ("gcry_cipher_setkey failed with keylen %u: %s\n", + (unsigned int)key_buflen, gpg_strerror (err)); + + if (iv_buffer) + { + err = gcry_cipher_setiv (hd, iv_buffer, iv_buflen); + if (err) + die ("gcry_cipher_setiv failed with ivlen %u: %s\n", + (unsigned int)iv_buflen, gpg_strerror (err)); + } + + if (datalen != blocklen) + die ("length of input (%u) does not match block length (%u)\n", + (unsigned int)datalen, (unsigned int)blocklen); + memcpy (input, data, datalen); + memset (output, 0, sizeof output); + for (count=0; count < iterations; count++) + { + memcpy (last_last_output, last_output, sizeof last_output); + memcpy (last_output, output, sizeof output); + + get_current_iv (hd, last_iv, blocklen); + + if (encrypt_mode) + err = gcry_cipher_encrypt (hd, output, blocklen, input, blocklen); + else + err = gcry_cipher_decrypt (hd, output, blocklen, input, blocklen); + if (err) + die ("gcry_cipher_%scrypt failed: %s\n", + encrypt_mode? "en":"de", gpg_strerror (err)); + + + if (encrypt_mode && (cipher_mode == GCRY_CIPHER_MODE_CFB + || cipher_mode == GCRY_CIPHER_MODE_CBC)) + memcpy (input, last_iv, blocklen); + else if (cipher_mode == GCRY_CIPHER_MODE_OFB) + memcpy (input, last_iv, blocklen); + else if (!encrypt_mode && cipher_mode == GCRY_CIPHER_MODE_CFB) + { + /* Reconstruct the output vector. */ + int i; + for (i=0; i < blocklen; i++) + input[i] ^= output[i]; + } + else + memcpy (input, output, blocklen); + } + + print_buffer (output, blocklen); + putchar ('\n'); + print_buffer (last_output, blocklen); + putchar ('\n'); + print_buffer (last_last_output, blocklen); + putchar ('\n'); + get_current_iv (hd, last_iv, blocklen); + print_buffer (last_iv, blocklen); /* Last output vector. */ + putchar ('\n'); + print_buffer (input, blocklen); /* Next input text. */ + putchar ('\n'); + if (verbose > 1) + showhex ("sent line", "", 0); + putchar ('\n'); + fflush (stdout); + + gcry_cipher_close (hd); +} + + + +/* Run a digest operation. */ +static void +run_digest (int digest_algo, const void *data, size_t datalen) +{ + gpg_error_t err; + gcry_md_hd_t hd; + const unsigned char *digest; + unsigned int digestlen; + + err = gcry_md_open (&hd, digest_algo, 0); + if (err) + die ("gcry_md_open failed for algo %d: %s\n", + digest_algo, gpg_strerror (err)); + + gcry_md_write (hd, data, datalen); + digest = gcry_md_read (hd, digest_algo); + digestlen = gcry_md_get_algo_dlen (digest_algo); + print_buffer (digest, digestlen); + gcry_md_close (hd); +} + + +/* Run a HMAC operation. */ +static void +run_hmac (int digest_algo, const void *key, size_t keylen, + const void *data, size_t datalen) +{ + gpg_error_t err; + gcry_md_hd_t hd; + const unsigned char *digest; + unsigned int digestlen; + + err = gcry_md_open (&hd, digest_algo, GCRY_MD_FLAG_HMAC); + if (err) + die ("gcry_md_open failed for HMAC algo %d: %s\n", + digest_algo, gpg_strerror (err)); + + gcry_md_setkey (hd, key, keylen); + if (err) + die ("gcry_md_setkey failed for HMAC algo %d: %s\n", + digest_algo, gpg_strerror (err)); + + gcry_md_write (hd, data, datalen); + digest = gcry_md_read (hd, digest_algo); + digestlen = gcry_md_get_algo_dlen (digest_algo); + print_buffer (digest, digestlen); + gcry_md_close (hd); +} + + + +/* Derive an RSA key using the S-expression in (DATA,DATALEN). This + S-expression is used directly as input to gcry_pk_genkey. The + result is printed to stdout with one parameter per line in hex + format and in this order: p, q, n, d. */ +static void +run_rsa_derive (const void *data, size_t datalen) +{ + gpg_error_t err; + gcry_sexp_t s_keyspec, s_key, s_top, l1; + gcry_mpi_t mpi; + const char *parmlist; + int idx; + + if (!datalen) + err = gpg_error (GPG_ERR_NO_DATA); + else + err = gcry_sexp_new (&s_keyspec, data, datalen, 1); + if (err) + die ("gcry_sexp_new failed for RSA key derive: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&s_key, s_keyspec); + if (err) + die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (s_keyspec); + + /* P and Q might have been swapped but we need to to return them in + the proper order. Build the parameter list accordingly. */ + parmlist = "pqnd"; + s_top = gcry_sexp_find_token (s_key, "misc-key-info", 0); + if (s_top) + { + l1 = gcry_sexp_find_token (s_top, "p-q-swapped", 0); + if (l1) + parmlist = "qpnd"; + gcry_sexp_release (l1); + gcry_sexp_release (s_top); + } + + /* Parse and print the parameters. */ + l1 = gcry_sexp_find_token (s_key, "private-key", 0); + s_top = gcry_sexp_find_token (l1, "rsa", 0); + gcry_sexp_release (l1); + if (!s_top) + die ("private-key part not found in result\n"); + + for (idx=0; parmlist[idx]; idx++) + { + l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1); + mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + if (!mpi) + die ("parameter %c missing in private-key\n", parmlist[idx]); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + } + + gcry_sexp_release (s_top); + gcry_sexp_release (s_key); +} + + + +static size_t +compute_tag_length (size_t n) +{ + int needed = 0; + + if (n < 128) + needed += 2; /* Tag and one length byte. */ + else if (n < 256) + needed += 3; /* Tag, number of length bytes, 1 length byte. */ + else if (n < 65536) + needed += 4; /* Tag, number of length bytes, 2 length bytes. */ + else + die ("DER object too long to encode\n"); + + return needed; +} + +static unsigned char * +store_tag_length (unsigned char *p, int tag, size_t n) +{ + if (tag == TAG_SEQUENCE) + tag |= 0x20; /* constructed */ + + *p++ = tag; + if (n < 128) + *p++ = n; + else if (n < 256) + { + *p++ = 0x81; + *p++ = n; + } + else if (n < 65536) + { + *p++ = 0x82; + *p++ = n >> 8; + *p++ = n; + } + + return p; +} + + +/* Generate an RSA key of size KEYSIZE using the public exponent + PUBEXP and print it to stdout in the OpenSSL format. The format + is: + + SEQUENCE { + INTEGER (0) -- Unknown constant. + INTEGER -- n + INTEGER -- e + INTEGER -- d + INTEGER -- p + INTEGER -- q (with p < q) + INTEGER -- dmp1 = d mod (p-1) + INTEGER -- dmq1 = d mod (q-1) + INTEGER -- u = p^{-1} mod q + } + +*/ +static void +run_rsa_gen (int keysize, int pubexp) +{ + gpg_error_t err; + gcry_sexp_t keyspec, key, l1; + const char keyelems[] = "nedpq..u"; + gcry_mpi_t keyparms[8]; + size_t keyparmslen[8]; + int idx; + size_t derlen, needed, n; + unsigned char *derbuf, *der; + + err = gcry_sexp_build (&keyspec, NULL, + "(genkey (rsa (nbits %d)(rsa-use-e %d)))", + keysize, pubexp); + if (err) + die ("gcry_sexp_build failed for RSA key generation: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&key, keyspec); + if (err) + die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (keyspec); + + l1 = gcry_sexp_find_token (key, "private-key", 0); + if (!l1) + die ("private key not found in genkey result\n"); + gcry_sexp_release (key); + key = l1; + + l1 = gcry_sexp_find_token (key, "rsa", 0); + if (!l1) + die ("returned private key not formed as expected\n"); + gcry_sexp_release (key); + key = l1; + + /* Extract the parameters from the S-expression and store them in a + well defined order in KEYPARMS. */ + for (idx=0; idx < DIM(keyparms); idx++) + { + if (keyelems[idx] == '.') + { + keyparms[idx] = gcry_mpi_new (0); + continue; + } + l1 = gcry_sexp_find_token (key, keyelems+idx, 1); + if (!l1) + die ("no %c parameter in returned private key\n", keyelems[idx]); + keyparms[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + if (!keyparms[idx]) + die ("no value for %c parameter in returned private key\n", + keyelems[idx]); + gcry_sexp_release (l1); + } + + gcry_sexp_release (key); + + /* Check that p < q; if not swap p and q and recompute u. */ + if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0) + { + gcry_mpi_swap (keyparms[3], keyparms[4]); + gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]); + } + + /* Compute the additional parameters. */ + gcry_mpi_sub_ui (keyparms[5], keyparms[3], 1); + gcry_mpi_mod (keyparms[5], keyparms[2], keyparms[5]); + gcry_mpi_sub_ui (keyparms[6], keyparms[4], 1); + gcry_mpi_mod (keyparms[6], keyparms[2], keyparms[6]); + + /* Compute the length of the DER encoding. */ + needed = compute_tag_length (1) + 1; + for (idx=0; idx < DIM(keyparms); idx++) + { + err = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, keyparms[idx]); + if (err) + die ("error formatting parameter: %s\n", gpg_strerror (err)); + keyparmslen[idx] = n; + needed += compute_tag_length (n) + n; + } + + /* Store the key parameters. */ + derlen = compute_tag_length (needed) + needed; + der = derbuf = gcry_xmalloc (derlen); + + der = store_tag_length (der, TAG_SEQUENCE, needed); + der = store_tag_length (der, TAG_INTEGER, 1); + *der++ = 0; + for (idx=0; idx < DIM(keyparms); idx++) + { + der = store_tag_length (der, TAG_INTEGER, keyparmslen[idx]); + err = gcry_mpi_print (GCRYMPI_FMT_STD, der, + keyparmslen[idx], NULL, keyparms[idx]); + if (err) + die ("error formatting parameter: %s\n", gpg_strerror (err)); + der += keyparmslen[idx]; + } + + /* Print the stuff. */ + for (idx=0; idx < DIM(keyparms); idx++) + gcry_mpi_release (keyparms[idx]); + + assert (der - derbuf == derlen); + + if (base64_output) + puts ("-----BEGIN RSA PRIVATE KEY-----"); + print_buffer (derbuf, derlen); + if (base64_output) + puts ("-----END RSA PRIVATE KEY-----"); + + gcry_free (derbuf); +} + + + +/* Sign DATA of length DATALEN using the key taken from the PEM + encoded KEYFILE and the hash algorithm HASHALGO. */ +static void +run_rsa_sign (const void *data, size_t datalen, + int hashalgo, int pkcs1, const char *keyfile) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig, s_tmp; + gcry_mpi_t sig_mpi = NULL; + unsigned char *outbuf; + size_t outlen; + +/* showhex ("D", data, datalen); */ + if (pkcs1) + { + unsigned char hash[64]; + unsigned int hashsize; + + hashsize = gcry_md_get_algo_dlen (hashalgo); + if (!hashsize || hashsize > sizeof hash) + die ("digest too long for buffer or unknown hash algorithm\n"); + gcry_md_hash_buffer (hashalgo, hash, data, datalen); + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pkcs1)(hash %s %b))", + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } + else + { + gcry_mpi_t tmp; + + err = gcry_mpi_scan (&tmp, GCRYMPI_FMT_USG, data, datalen,NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", tmp); + gcry_mpi_release (tmp); + } + } + if (err) + die ("gcry_sexp_build failed for RSA data input: %s\n", + gpg_strerror (err)); + + s_key = read_private_key_file (keyfile, 0); + + err = gcry_pk_sign (&s_sig, s_data, s_key); + if (err) + { + gcry_sexp_release (read_private_key_file (keyfile, 1)); + die ("gcry_pk_signed failed (datalen=%d,keyfile=%s): %s\n", + (int)datalen, keyfile, gpg_strerror (err)); + } + gcry_sexp_release (s_key); + gcry_sexp_release (s_data); + + s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); + if (s_tmp) + { + gcry_sexp_release (s_sig); + s_sig = s_tmp; + s_tmp = gcry_sexp_find_token (s_sig, "rsa", 0); + if (s_tmp) + { + gcry_sexp_release (s_sig); + s_sig = s_tmp; + s_tmp = gcry_sexp_find_token (s_sig, "s", 0); + if (s_tmp) + { + gcry_sexp_release (s_sig); + s_sig = s_tmp; + sig_mpi = gcry_sexp_nth_mpi (s_sig, 1, GCRYMPI_FMT_USG); + } + } + } + gcry_sexp_release (s_sig); + + if (!sig_mpi) + die ("no value in returned S-expression\n"); + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &outbuf, &outlen, sig_mpi); + if (err) + die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err)); + gcry_mpi_release (sig_mpi); + + print_buffer (outbuf, outlen); + gcry_free (outbuf); +} + + + +/* Verify DATA of length DATALEN using the public key taken from the + PEM encoded KEYFILE and the hash algorithm HASHALGO against the + binary signature in SIGFILE. */ +static void +run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1, + const char *keyfile, const char *sigfile) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig; + + if (pkcs1) + { + unsigned char hash[64]; + unsigned int hashsize; + + hashsize = gcry_md_get_algo_dlen (hashalgo); + if (!hashsize || hashsize > sizeof hash) + die ("digest too long for buffer or unknown hash algorithm\n"); + gcry_md_hash_buffer (hashalgo, hash, data, datalen); + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pkcs1)(hash %s %b))", + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } + else + { + gcry_mpi_t tmp; + + err = gcry_mpi_scan (&tmp, GCRYMPI_FMT_USG, data, datalen,NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", tmp); + gcry_mpi_release (tmp); + } + } + if (err) + die ("gcry_sexp_build failed for RSA data input: %s\n", + gpg_strerror (err)); + + s_key = read_public_key_file (keyfile, 0); + + s_sig = read_sig_file (sigfile); + + err = gcry_pk_verify (s_sig, s_data, s_key); + if (!err) + puts ("GOOD signature"); + else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE) + puts ("BAD signature"); + else + printf ("ERROR (%s)\n", gpg_strerror (err)); + + gcry_sexp_release (s_sig); + gcry_sexp_release (s_key); + gcry_sexp_release (s_data); +} + + + +/* Generate a DSA key of size KEYSIZE and return the complete + S-expression. */ +static gcry_sexp_t +dsa_gen (int keysize) +{ + gpg_error_t err; + gcry_sexp_t keyspec, key; + + err = gcry_sexp_build (&keyspec, NULL, + "(genkey (dsa (nbits %d)(use-fips186-2)))", + keysize); + if (err) + die ("gcry_sexp_build failed for DSA key generation: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&key, keyspec); + if (err) + die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (keyspec); + + return key; +} + + +/* Generate a DSA key of size KEYSIZE and return the complete + S-expression. */ +static gcry_sexp_t +dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen) +{ + gpg_error_t err; + gcry_sexp_t keyspec, key; + + err = gcry_sexp_build (&keyspec, NULL, + "(genkey" + " (dsa" + " (nbits %d)" + " (use-fips186-2)" + " (derive-parms" + " (seed %b))))", + keysize, (int)seedlen, seed); + if (err) + die ("gcry_sexp_build failed for DSA key generation: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&key, keyspec); + if (err) + die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (keyspec); + + return key; +} + + +/* Print the domain parameter as well as the derive information. KEY + is the complete key as returned by dsa_gen. We print to stdout + with one parameter per line in hex format using this order: p, q, + g, seed, counter, h. */ +static void +print_dsa_domain_parameters (gcry_sexp_t key) +{ + gcry_sexp_t l1, l2; + gcry_mpi_t mpi; + int idx; + const void *data; + size_t datalen; + char *string; + + l1 = gcry_sexp_find_token (key, "public-key", 0); + if (!l1) + die ("public key not found in genkey result\n"); + + l2 = gcry_sexp_find_token (l1, "dsa", 0); + if (!l2) + die ("returned public key not formed as expected\n"); + gcry_sexp_release (l1); + l1 = l2; + + /* Extract the parameters from the S-expression and print them to stdout. */ + for (idx=0; "pqg"[idx]; idx++) + { + l2 = gcry_sexp_find_token (l1, "pqg"+idx, 1); + if (!l2) + die ("no %c parameter in returned public key\n", "pqg"[idx]); + mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!mpi) + die ("no value for %c parameter in returned public key\n","pqg"[idx]); + gcry_sexp_release (l2); + if (standalone_mode) + printf ("%c = ", "PQG"[idx]); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + } + gcry_sexp_release (l1); + + /* Extract the seed values. */ + l1 = gcry_sexp_find_token (key, "misc-key-info", 0); + if (!l1) + die ("misc-key-info not found in genkey result\n"); + + l2 = gcry_sexp_find_token (l1, "seed-values", 0); + if (!l2) + die ("no seed-values in returned key\n"); + gcry_sexp_release (l1); + l1 = l2; + + l2 = gcry_sexp_find_token (l1, "seed", 0); + if (!l2) + die ("no seed value in returned key\n"); + data = gcry_sexp_nth_data (l2, 1, &datalen); + if (!data) + die ("no seed value in returned key\n"); + if (standalone_mode) + printf ("Seed = "); + print_data_line (data, datalen); + gcry_sexp_release (l2); + + l2 = gcry_sexp_find_token (l1, "counter", 0); + if (!l2) + die ("no counter value in returned key\n"); + string = gcry_sexp_nth_string (l2, 1); + if (!string) + die ("no counter value in returned key\n"); + if (standalone_mode) + printf ("c = %ld\n", strtoul (string, NULL, 10)); + else + printf ("%lX\n", strtoul (string, NULL, 10)); + gcry_free (string); + gcry_sexp_release (l2); + + l2 = gcry_sexp_find_token (l1, "h", 0); + if (!l2) + die ("no n value in returned key\n"); + mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!mpi) + die ("no h value in returned key\n"); + if (standalone_mode) + printf ("H = "); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + gcry_sexp_release (l2); + + gcry_sexp_release (l1); +} + + +/* Generate DSA domain parameters for a modulus size of KEYSIZE. The + result is printed to stdout with one parameter per line in hex + format and in this order: p, q, g, seed, counter, h. If SEED is + not NULL this seed value will be used for the generation. */ +static void +run_dsa_pqg_gen (int keysize, const void *seed, size_t seedlen) +{ + gcry_sexp_t key; + + if (seed) + key = dsa_gen_with_seed (keysize, seed, seedlen); + else + key = dsa_gen (keysize); + print_dsa_domain_parameters (key); + gcry_sexp_release (key); +} + + +/* Generate a DSA key of size of KEYSIZE and write the private key to + FILENAME. Also write the parameters to stdout in the same way as + run_dsa_pqg_gen. */ +static void +run_dsa_gen (int keysize, const char *filename) +{ + gcry_sexp_t key, private_key; + FILE *fp; + + key = dsa_gen (keysize); + private_key = gcry_sexp_find_token (key, "private-key", 0); + if (!private_key) + die ("private key not found in genkey result\n"); + print_dsa_domain_parameters (key); + + fp = fopen (filename, "wb"); + if (!fp) + die ("can't create `%s': %s\n", filename, strerror (errno)); + print_sexp (private_key, fp); + fclose (fp); + + gcry_sexp_release (private_key); + gcry_sexp_release (key); +} + + + +/* Sign DATA of length DATALEN using the key taken from the S-expression + encoded KEYFILE. */ +static void +run_dsa_sign (const void *data, size_t datalen, const char *keyfile) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig, s_tmp, s_tmp2; + char hash[20]; + gcry_mpi_t tmpmpi; + + gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen); + err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", tmpmpi); + gcry_mpi_release (tmpmpi); + } + if (err) + die ("gcry_sexp_build failed for DSA data input: %s\n", + gpg_strerror (err)); + + s_key = read_sexp_from_file (keyfile); + + err = gcry_pk_sign (&s_sig, s_data, s_key); + if (err) + { + gcry_sexp_release (read_private_key_file (keyfile, 1)); + die ("gcry_pk_signed failed (datalen=%d,keyfile=%s): %s\n", + (int)datalen, keyfile, gpg_strerror (err)); + } + gcry_sexp_release (s_data); + + /* We need to return the Y parameter first. */ + s_tmp = gcry_sexp_find_token (s_key, "private-key", 0); + if (!s_tmp) + die ("private key part not found in provided key\n"); + + s_tmp2 = gcry_sexp_find_token (s_tmp, "dsa", 0); + if (!s_tmp2) + die ("private key part is not a DSA key\n"); + gcry_sexp_release (s_tmp); + + s_tmp = gcry_sexp_find_token (s_tmp2, "y", 0); + tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); + if (!tmpmpi) + die ("no y parameter in DSA key\n"); + print_mpi_line (tmpmpi, 1); + gcry_mpi_release (tmpmpi); + gcry_sexp_release (s_tmp); + + gcry_sexp_release (s_key); + + + /* Now return the actual signature. */ + s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); + if (!s_tmp) + die ("no sig-val element in returned S-expression\n"); + + gcry_sexp_release (s_sig); + s_sig = s_tmp; + s_tmp = gcry_sexp_find_token (s_sig, "dsa", 0); + if (!s_tmp) + die ("no dsa element in returned S-expression\n"); + + gcry_sexp_release (s_sig); + s_sig = s_tmp; + + s_tmp = gcry_sexp_find_token (s_sig, "r", 0); + tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); + if (!tmpmpi) + die ("no r parameter in returned S-expression\n"); + print_mpi_line (tmpmpi, 1); + gcry_mpi_release (tmpmpi); + gcry_sexp_release (s_tmp); + + s_tmp = gcry_sexp_find_token (s_sig, "s", 0); + tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); + if (!tmpmpi) + die ("no s parameter in returned S-expression\n"); + print_mpi_line (tmpmpi, 1); + gcry_mpi_release (tmpmpi); + gcry_sexp_release (s_tmp); + + gcry_sexp_release (s_sig); +} + + + +/* Verify DATA of length DATALEN using the public key taken from the + S-expression in KEYFILE against the S-expression formatted + signature in SIGFILE. */ +static void +run_dsa_verify (const void *data, size_t datalen, + const char *keyfile, const char *sigfile) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig; + char hash[20]; + gcry_mpi_t tmpmpi; + + gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen); + /* Note that we can't simply use %b with HASH to build the + S-expression, because that might yield a negative value. */ + err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", tmpmpi); + gcry_mpi_release (tmpmpi); + } + if (err) + die ("gcry_sexp_build failed for DSA data input: %s\n", + gpg_strerror (err)); + + s_key = read_sexp_from_file (keyfile); + s_sig = read_sexp_from_file (sigfile); + + err = gcry_pk_verify (s_sig, s_data, s_key); + if (!err) + puts ("GOOD signature"); + else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE) + puts ("BAD signature"); + else + printf ("ERROR (%s)\n", gpg_strerror (err)); + + gcry_sexp_release (s_sig); + gcry_sexp_release (s_key); + gcry_sexp_release (s_data); +} + + + + +static void +usage (int show_help) +{ + if (!show_help) + { + fputs ("usage: " PGM + " [OPTION] [FILE] (try --help for more information)\n", stderr); + exit (2); + } + fputs + ("Usage: " PGM " [OPTIONS] MODE [FILE]\n" + "Run a crypto operation using hex encoded input and output.\n" + "MODE:\n" + " encrypt, decrypt, digest, random, hmac-sha,\n" + " rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n" + "OPTIONS:\n" + " --verbose Print additional information\n" + " --binary Input and output is in binary form\n" + " --no-fips Do not force FIPS mode\n" + " --key KEY Use the hex encoded KEY\n" + " --iv IV Use the hex encoded IV\n" + " --dt DT Use the hex encoded DT for the RNG\n" + " --algo NAME Use algorithm NAME\n" + " --keysize N Use a keysize of N bits\n" + " --signature NAME Take signature from file NAME\n" + " --chunk N Read in chunks of N bytes (implies --binary)\n" + " --pkcs1 Use PKCS#1 encoding\n" + " --mct-server Run a monte carlo test server\n" + " --loop Enable random loop mode\n" + " --progress Print pogress indicators\n" + " --help Print this text\n" + "With no FILE, or when FILE is -, read standard input.\n" + "Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout); + exit (0); +} + +int +main (int argc, char **argv) +{ + int last_argc = -1; + gpg_error_t err; + int no_fips = 0; + int progress = 0; + int use_pkcs1 = 0; + const char *mode_string; + const char *key_string = NULL; + const char *iv_string = NULL; + const char *dt_string = NULL; + const char *algo_string = NULL; + const char *keysize_string = NULL; + const char *signature_string = NULL; + FILE *input; + void *data; + size_t datalen; + size_t chunksize = 0; + int mct_server = 0; + + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + usage (1); + } + else if (!strcmp (*argv, "--version")) + { + fputs (PGM " (Libgcrypt) " PACKAGE_VERSION "\n", stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--binary")) + { + binary_input = binary_output = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--no-fips")) + { + no_fips++; + argc--; argv++; + } + else if (!strcmp (*argv, "--loop")) + { + loop_mode = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--progress")) + { + progress = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--key")) + { + argc--; argv++; + if (!argc) + usage (0); + key_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--iv")) + { + argc--; argv++; + if (!argc) + usage (0); + iv_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--dt")) + { + argc--; argv++; + if (!argc) + usage (0); + dt_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--algo")) + { + argc--; argv++; + if (!argc) + usage (0); + algo_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--keysize")) + { + argc--; argv++; + if (!argc) + usage (0); + keysize_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--signature")) + { + argc--; argv++; + if (!argc) + usage (0); + signature_string = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--chunk")) + { + argc--; argv++; + if (!argc) + usage (0); + chunksize = atoi (*argv); + binary_input = binary_output = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--pkcs1")) + { + use_pkcs1 = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--mct-server")) + { + mct_server = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--standalone")) + { + standalone_mode = 1; + argc--; argv++; + } + } + + if (!argc || argc > 2) + usage (0); + mode_string = *argv; + + if (!strcmp (mode_string, "rsa-derive")) + binary_input = 1; + + if (argc == 2 && strcmp (argv[1], "-")) + { + input = fopen (argv[1], binary_input? "rb":"r"); + if (!input) + die ("can't open `%s': %s\n", argv[1], strerror (errno)); + } + else + input = stdin; + +#ifndef HAVE_W32_SYSTEM + if (loop_mode) + signal (SIGPIPE, SIG_IGN); +#endif + + if (verbose) + fprintf (stderr, PGM ": started (mode=%s)\n", mode_string); + + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + if (!no_fips) + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_check_version ("1.4.3")) + die ("Libgcrypt is not sufficient enough\n"); + if (verbose) + fprintf (stderr, PGM ": using Libgcrypt %s\n", gcry_check_version (NULL)); + if (no_fips) + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + /* Most operations need some input data. */ + if (!chunksize + && !mct_server + && strcmp (mode_string, "random") + && strcmp (mode_string, "rsa-gen") + && strcmp (mode_string, "dsa-gen") ) + { + data = read_file (input, !binary_input, &datalen); + if (!data) + die ("error reading%s input\n", binary_input?"":" and decoding"); + if (verbose) + fprintf (stderr, PGM ": %u bytes of input data\n", + (unsigned int)datalen); + } + else + { + data = NULL; + datalen = 0; + } + + + if (!strcmp (mode_string, "encrypt") || !strcmp (mode_string, "decrypt")) + { + int cipher_algo, cipher_mode; + void *iv_buffer = NULL; + void *key_buffer = NULL; + size_t iv_buflen, key_buflen; + + if (!algo_string) + die ("option --algo is required in this mode\n"); + cipher_algo = map_openssl_cipher_name (algo_string, &cipher_mode); + if (!cipher_algo) + die ("cipher algorithm `%s' is not supported\n", algo_string); + if (mct_server) + { + int iterations; + + for (;;) + { + gcry_free (key_buffer); key_buffer = NULL; + gcry_free (iv_buffer); iv_buffer = NULL; + gcry_free (data); data = NULL; + if (!(key_buffer = read_textline (input))) + { + if (feof (input)) + break; + die ("no version info in input\n"); + } + if (atoi (key_buffer) != 1) + die ("unsupported input version %s\n", key_buffer); + gcry_free (key_buffer); + if (!(key_buffer = read_textline (input))) + die ("no iteration count in input\n"); + iterations = atoi (key_buffer); + gcry_free (key_buffer); + if (!(key_buffer = read_hexline (input, &key_buflen))) + die ("no key in input\n"); + if (!(iv_buffer = read_hexline (input, &iv_buflen))) + die ("no IV in input\n"); + if (!(data = read_hexline (input, &datalen))) + die ("no data in input\n"); + skip_to_empty_line (input); + + run_cipher_mct_loop ((*mode_string == 'e'), + cipher_algo, cipher_mode, + iv_buffer, iv_buflen, + key_buffer, key_buflen, + data, datalen, iterations); + } + } + else + { + if (cipher_mode != GCRY_CIPHER_MODE_ECB) + { + if (!iv_string) + die ("option --iv is required in this mode\n"); + iv_buffer = hex2buffer (iv_string, &iv_buflen); + if (!iv_buffer) + die ("invalid value for IV\n"); + } + else + { + iv_buffer = NULL; + iv_buflen = 0; + } + if (!key_string) + die ("option --key is required in this mode\n"); + key_buffer = hex2buffer (key_string, &key_buflen); + if (!key_buffer) + die ("invalid value for KEY\n"); + + run_encrypt_decrypt ((*mode_string == 'e'), + cipher_algo, cipher_mode, + iv_buffer, iv_buflen, + key_buffer, key_buflen, + data, data? datalen:chunksize, input); + } + gcry_free (key_buffer); + gcry_free (iv_buffer); + } + else if (!strcmp (mode_string, "digest")) + { + int algo; + + if (!algo_string) + die ("option --algo is required in this mode\n"); + algo = gcry_md_map_name (algo_string); + if (!algo) + die ("digest algorithm `%s' is not supported\n", algo_string); + if (!data) + die ("no data available (do not use --chunk)\n"); + + run_digest (algo, data, datalen); + } + else if (!strcmp (mode_string, "random")) + { + void *context; + unsigned char key[16]; + unsigned char seed[16]; + unsigned char dt[16]; + unsigned char buffer[16]; + size_t count = 0; + + if (hex2bin (key_string, key, 16) < 0 ) + die ("value for --key are not 32 hex digits\n"); + if (hex2bin (iv_string, seed, 16) < 0 ) + die ("value for --iv are not 32 hex digits\n"); + if (hex2bin (dt_string, dt, 16) < 0 ) + die ("value for --dt are not 32 hex digits\n"); + + /* The flag value 1 disables the dup check, so that the RNG + returns all generated data. */ + err = init_external_rng_test (&context, 1, key, 16, seed, 16, dt, 16); + if (err) + die ("init external RNG test failed: %s\n", gpg_strerror (err)); + + do + { + err = run_external_rng_test (context, buffer, sizeof buffer); + if (err) + die ("running external RNG test failed: %s\n", gpg_strerror (err)); + print_buffer (buffer, sizeof buffer); + if (progress) + { + if (!(++count % 1000)) + fprintf (stderr, PGM ": %lu random bytes so far\n", + (unsigned long int)count * sizeof buffer); + } + } + while (loop_mode); + + if (progress) + fprintf (stderr, PGM ": %lu random bytes\n", + (unsigned long int)count * sizeof buffer); + + deinit_external_rng_test (context); + } + else if (!strcmp (mode_string, "hmac-sha")) + { + int algo; + void *key_buffer; + size_t key_buflen; + + if (!data) + die ("no data available (do not use --chunk)\n"); + if (!algo_string) + die ("option --algo is required in this mode\n"); + switch (atoi (algo_string)) + { + case 1: algo = GCRY_MD_SHA1; break; + case 224: algo = GCRY_MD_SHA224; break; + case 256: algo = GCRY_MD_SHA256; break; + case 384: algo = GCRY_MD_SHA384; break; + case 512: algo = GCRY_MD_SHA512; break; + default: algo = 0; break; + } + if (!algo) + die ("no digest algorithm found for hmac type `%s'\n", algo_string); + if (!key_string) + die ("option --key is required in this mode\n"); + key_buffer = hex2buffer (key_string, &key_buflen); + if (!key_buffer) + die ("invalid value for KEY\n"); + + run_hmac (algo, key_buffer, key_buflen, data, datalen); + + gcry_free (key_buffer); + } + else if (!strcmp (mode_string, "rsa-derive")) + { + if (!data) + die ("no data available (do not use --chunk)\n"); + run_rsa_derive (data, datalen); + } + else if (!strcmp (mode_string, "rsa-gen")) + { + int keysize; + + if (!binary_output) + base64_output = 1; + + keysize = keysize_string? atoi (keysize_string) : 0; + if (keysize < 128 || keysize > 16384) + die ("invalid keysize specified; needs to be 128 .. 16384\n"); + run_rsa_gen (keysize, 65537); + } + else if (!strcmp (mode_string, "rsa-sign")) + { + int algo; + + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!algo_string) + die ("option --algo is required in this mode\n"); + algo = gcry_md_map_name (algo_string); + if (!algo) + die ("digest algorithm `%s' is not supported\n", algo_string); + if (!data) + die ("no data available (do not use --chunk)\n"); + + run_rsa_sign (data, datalen, algo, use_pkcs1, key_string); + + } + else if (!strcmp (mode_string, "rsa-verify")) + { + int algo; + + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!algo_string) + die ("option --algo is required in this mode\n"); + algo = gcry_md_map_name (algo_string); + if (!algo) + die ("digest algorithm `%s' is not supported\n", algo_string); + if (!data) + die ("no data available (do not use --chunk)\n"); + if (!signature_string) + die ("option --signature is required in this mode\n"); + if (access (signature_string, R_OK)) + die ("option --signature needs to specify an existing file\n"); + + run_rsa_verify (data, datalen, algo, use_pkcs1, key_string, + signature_string); + + } + else if (!strcmp (mode_string, "dsa-pqg-gen")) + { + int keysize; + + keysize = keysize_string? atoi (keysize_string) : 0; + if (keysize < 1024 || keysize > 3072) + die ("invalid keysize specified; needs to be 1024 .. 3072\n"); + run_dsa_pqg_gen (keysize, datalen? data:NULL, datalen); + } + else if (!strcmp (mode_string, "dsa-gen")) + { + int keysize; + + keysize = keysize_string? atoi (keysize_string) : 0; + if (keysize < 1024 || keysize > 3072) + die ("invalid keysize specified; needs to be 1024 .. 3072\n"); + if (!key_string) + die ("option --key is required in this mode\n"); + run_dsa_gen (keysize, key_string); + } + else if (!strcmp (mode_string, "dsa-sign")) + { + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!data) + die ("no data available (do not use --chunk)\n"); + + run_dsa_sign (data, datalen, key_string); + } + else if (!strcmp (mode_string, "dsa-verify")) + { + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!data) + die ("no data available (do not use --chunk)\n"); + if (!signature_string) + die ("option --signature is required in this mode\n"); + if (access (signature_string, R_OK)) + die ("option --signature needs to specify an existing file\n"); + + run_dsa_verify (data, datalen, key_string, signature_string); + } + else + usage (0); + + gcry_free (data); + + /* Because Libgcrypt does not enforce FIPS mode in all cases we let + the process die if Libgcrypt is not anymore in FIPS mode after + the actual operation. */ + if (!no_fips && !gcry_fips_mode_active ()) + die ("FIPS mode is not anymore active\n"); + + if (verbose) + fputs (PGM ": ready\n", stderr); + + return 0; +} + diff --git a/tests/hmac.c b/tests/hmac.c new file mode 100644 index 0000000..9d87dbb --- /dev/null +++ b/tests/hmac.c @@ -0,0 +1,171 @@ +/* hmac.c - HMAC regression tests + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; +static int error_count; + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + + + +static void +check_one_mac (int algo, + const void *key, size_t keylen, + const void *data, size_t datalen, + const char *expect) +{ + gcry_md_hd_t hd; + unsigned char *p; + int mdlen; + int i; + gcry_error_t err = 0; + + err = gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC); + if (err) + { + fail ("algo %d, grcy_md_open failed: %s\n", algo, gpg_strerror (err)); + return; + } + + mdlen = gcry_md_get_algo_dlen (algo); + if (mdlen < 1 || mdlen > 500) + { + fail ("algo %d, grcy_md_get_algo_dlen failed: %d\n", algo, mdlen); + return; + } + + err = gcry_md_setkey (hd, key, keylen); + if (err) + { + fail ("algo %d, grcy_md_setkey failed: %s\n", algo, gpg_strerror (err)); + return; + } + + gcry_md_write (hd, data, datalen); + + p = gcry_md_read (hd, 0); + + if (memcmp (p, expect, mdlen)) + { + printf ("computed: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", p[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < mdlen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("algo %d, MAC does not match\n", algo); + } + + gcry_md_close (hd); +} + +static void +check_hmac (void) +{ + unsigned char key[128]; + int i, j; + + if (verbose) + fprintf (stderr, "checking FIPS-198a, A.1\n"); + for (i=0; i < 64; i++) + key[i] = i; + check_one_mac (GCRY_MD_SHA1, key, 64, "Sample #1", 9, + "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12" + "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a"); + + if (verbose) + fprintf (stderr, "checking FIPS-198a, A.2\n"); + for (i=0, j=0x30; i < 20; i++) + key[i] = j++; + check_one_mac (GCRY_MD_SHA1, key, 20, "Sample #2", 9, + "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82" + "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24"); + + if (verbose) + fprintf (stderr, "checking FIPS-198a, A.3\n"); + for (i=0, j=0x50; i < 100; i++) + key[i] = j++; + check_one_mac (GCRY_MD_SHA1, key, 100, "Sample #3", 9, + "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0" + "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa"); + + if (verbose) + fprintf (stderr, "checking FIPS-198a, A.4\n"); + for (i=0, j=0x70; i < 49; i++) + key[i] = j++; + check_one_mac (GCRY_MD_SHA1, key, 49, "Sample #4", 9, + "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42" + "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26"); + +} + +int +main (int argc, char **argv) +{ + int debug = 0; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + check_hmac (); + + return error_count ? 1 : 0; +} diff --git a/tests/keygen.c b/tests/keygen.c new file mode 100644 index 0000000..f5d5610 --- /dev/null +++ b/tests/keygen.c @@ -0,0 +1,311 @@ +/* keygen.c - key generation regression tests + * Copyright (C) 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include "../src/gcrypt.h" + + + +static int verbose; +static int debug; +static int error_count; + +static void +fail ( const char *format, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + error_count++; +} + +static void +die ( const char *format, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + + +static void +print_mpi (const char *text, gcry_mpi_t a) +{ + char *buf; + void *bufaddr = &buf; + gcry_error_t rc; + + rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); + if (rc) + fprintf (stderr, "%s=[error printing number: %s]\n", + text, gpg_strerror (rc)); + else + { + fprintf (stderr, "%s=0x%s\n", text, buf); + gcry_free (buf); + } +} + + +static void +check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e) +{ + gcry_sexp_t skey, pkey, list; + + pkey = gcry_sexp_find_token (key, "public-key", 0); + if (!pkey) + fail ("public part missing in return value\n"); + else + { + gcry_mpi_t e = NULL; + + list = gcry_sexp_find_token (pkey, "e", 0); + if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) ) + fail ("public exponent not found\n"); + else if (!expected_e) + { + if (verbose) + print_mpi ("e", e); + } + else if ( gcry_mpi_cmp_ui (e, expected_e)) + { + print_mpi ("e", e); + fail ("public exponent is not %lu\n", expected_e); + } + gcry_sexp_release (list); + gcry_mpi_release (e); + gcry_sexp_release (pkey); + } + + skey = gcry_sexp_find_token (key, "private-key", 0); + if (!skey) + fail ("private part missing in return value\n"); + else + { + int rc = gcry_pk_testkey (skey); + if (rc) + fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (skey); + } + + } + +static void +check_rsa_keys (void) +{ + gcry_sexp_t keyparm, key; + int rc; + int i; + + /* Check that DSA generation works and that it can grok the qbits + argument. */ + if (verbose) + fprintf (stderr, "creating 5 1024 bit DSA keys\n"); + for (i=0; i < 5; i++) + { + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (dsa\n" + " (nbits 4:1024)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating DSA key: %s\n", gpg_strerror (rc)); + gcry_sexp_release (key); + if (verbose) + fprintf (stderr, " done\n"); + } + + if (verbose) + fprintf (stderr, "creating 1536 bit DSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (dsa\n" + " (nbits 4:1536)\n" + " (qbits 3:224)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating DSA key: %s\n", gpg_strerror (rc)); + if (debug) + { + char buffer[20000]; + gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, buffer, sizeof buffer); + if (verbose) + printf ("=============================\n%s\n" + "=============================\n", buffer); + } + gcry_sexp_release (key); + + if (verbose) + fprintf (stderr, "creating 1024 bit RSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (rsa\n" + " (nbits 4:1024)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating RSA key: %s\n", gpg_strerror (rc)); + + check_generated_rsa_key (key, 65537); + gcry_sexp_release (key); + + + if (verbose) + fprintf (stderr, "creating 512 bit RSA key with e=257\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (rsa\n" + " (nbits 3:512)\n" + " (rsa-use-e 3:257)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating RSA key: %s\n", gpg_strerror (rc)); + + check_generated_rsa_key (key, 257); + gcry_sexp_release (key); + + if (verbose) + fprintf (stderr, "creating 512 bit RSA key with default e\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (rsa\n" + " (nbits 3:512)\n" + " (rsa-use-e 1:0)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating RSA key: %s\n", gpg_strerror (rc)); + + check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ + gcry_sexp_release (key); + +} + + +static void +check_nonce (void) +{ + char a[32], b[32]; + int i,j; + int oops=0; + + if (verbose) + fprintf (stderr, "checking gcry_create_nonce\n"); + + gcry_create_nonce (a, sizeof a); + for (i=0; i < 10; i++) + { + gcry_create_nonce (b, sizeof b); + if (!memcmp (a, b, sizeof a)) + die ("identical nounce found\n"); + } + for (i=0; i < 10; i++) + { + gcry_create_nonce (a, sizeof a); + if (!memcmp (a, b, sizeof a)) + die ("identical nounce found\n"); + } + + again: + for (i=1,j=0; i < sizeof a; i++) + if (a[0] == a[i]) + j++; + if (j+1 == sizeof (a)) + { + if (oops) + die ("impossible nonce found\n"); + oops++; + gcry_create_nonce (a, sizeof a); + goto again; + } +} + + +static void +progress_cb (void *cb_data, const char *what, int printchar, + int current, int total) +{ + (void)cb_data; + (void)what; + (void)current; + (void)total; + + if (printchar == '\n') + fputs ( "", stdout); + else + putchar (printchar); + fflush (stdout); +} + + +int +main (int argc, char **argv) +{ + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + if (verbose) + gcry_set_progress_handler ( progress_cb, NULL ); + + check_rsa_keys (); + check_nonce (); + + return error_count? 1:0; +} + diff --git a/tests/keygrip.c b/tests/keygrip.c new file mode 100644 index 0000000..e1908ba --- /dev/null +++ b/tests/keygrip.c @@ -0,0 +1,208 @@ +/* keygrip.c - verifies that keygrips are calculated as expected + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; + + + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +static void +print_hex (const char *text, const void *buf, size_t n) +{ + const unsigned char *p = buf; + + fputs (text, stdout); + for (; n; n--, p++) + printf ("%02X", *p); + putchar ('\n'); +} + + + + +static struct +{ + int algo; + const char *key; + const unsigned char grip[20]; +} key_grips[] = + { + { + GCRY_PK_RSA, + "(private-key" + " (rsa" + " (n #00B6B509596A9ECABC939212F891E656A626BA07DA8521A9CAD4C08E640C04052FBB87F424EF1A0275A48A9299AC9DB69ABE3D0124E6C756B1F7DFB9B842D6251AEA6EE85390495CADA73D671537FCE5850A932F32BAB60AB1AC1F852C1F83C625E7A7D70CDA9EF16D5C8E47739D77DF59261ABE8454807FF441E143FBD37F8545#)" + " (e #010001#)" + " (d #077AD3DE284245F4806A1B82B79E616FBDE821C82D691A65665E57B5FAD3F34E67F401E7BD2E28699E89D9C496CF821945AE83AC7A1231176A196BA6027E77D85789055D50404A7A2A95B1512F91F190BBAEF730ED550D227D512F89C0CDB31AC06FA9A19503DDF6B66D0B42B9691BFD6140EC1720FFC48AE00C34796DC899E5#)" + " (p #00D586C78E5F1B4BF2E7CD7A04CA091911706F19788B93E44EE20AAF462E8363E98A72253ED845CCBF2481BB351E8557C85BCFFF0DABDBFF8E26A79A0938096F27#)" + " (q #00DB0CDF60F26F2A296C88D6BF9F8E5BE45C0DDD713C96CC73EBCB48B061740943F21D2A93D6E42A7211E7F02A95DCED6C390A67AD21ECF739AE8A0CA46FF2EBB3#)" + " (u #33149195F16912DB20A48D020DBC3B9E3881B39D722BF79378F6340F43148A6E9FC5F53E2853B7387BA4443BA53A52FCA8173DE6E85B42F9783D4A7817D0680B#)))", + "\x32\xCF\xFA\x85\xB1\x79\x1F\xBB\x26\x14\xE9\x1A\xFD\xF3\xAF\xE3\x32\x08\x2E\x25" + }, + { + GCRY_PK_DSA, + " (public-key" + " (dsa" + " (p #0084E4C626E16005770BD9509ABF7354492E85B8C0060EFAAAEC617F725B592FAA59DF5460575F41022776A9718CE62EDD542AB73C7720869EBDBC834D174ADCD7136827DF51E2613545A25CA573BC502A61B809000B6E35F5EB7FD6F18C35678C23EA1C3638FB9CFDBA2800EE1B62F41A4479DE824F2834666FBF8DC5B53C2617#)" + " (q #00B0E6F710051002A9F425D98A677B18E0E5B038AB#)" + " (g #44370CEE0FE8609994183DBFEBA7EEA97D466838BCF65EFF506E35616DA93FA4E572A2F08886B74977BC00CA8CD3DBEA7AEB7DB8CBB180E6975E0D2CA76E023E6DE9F8CCD8826EBA2F72B8516532F6001DEFFAE76AA5E59E0FA33DBA3999B4E92D1703098CDEDCC416CF008801964084CDE1980132B2B78CB4CE9C15A559528B#)" + " (y #3D5DD14AFA2BF24A791E285B90232213D0E3BA74AB1109E768AED19639A322F84BB7D959E2BA92EF73DE4C7F381AA9F4053CFA3CD4527EF9043E304E5B95ED0A3A5A9D590AA641C13DB2B6E32B9B964A6A2C730DD3EA7C8E13F7A140AFF1A91CE375E9B9B960384779DC4EA180FA1F827C52288F366C0770A220F50D6D8FD6F6#)))", + "\x04\xA3\x4F\xA0\x2B\x03\x94\xD7\x32\xAD\xD5\x9B\x50\xAF\xDB\x5D\x57\x22\xA6\x10" + + }, + { + GCRY_PK_DSA, + "(private-key" + " (dsa" + " (p #0084E4C626E16005770BD9509ABF7354492E85B8C0060EFAAAEC617F725B592FAA59DF5460575F41022776A9718CE62EDD542AB73C7720869EBDBC834D174ADCD7136827DF51E2613545A25CA573BC502A61B809000B6E35F5EB7FD6F18C35678C23EA1C3638FB9CFDBA2800EE1B62F41A4479DE824F2834666FBF8DC5B53C2617#)" + " (q #00B0E6F710051002A9F425D98A677B18E0E5B038AB#)" + " (g #44370CEE0FE8609994183DBFEBA7EEA97D466838BCF65EFF506E35616DA93FA4E572A2F08886B74977BC00CA8CD3DBEA7AEB7DB8CBB180E6975E0D2CA76E023E6DE9F8CCD8826EBA2F72B8516532F6001DEFFAE76AA5E59E0FA33DBA3999B4E92D1703098CDEDCC416CF008801964084CDE1980132B2B78CB4CE9C15A559528B#)" + " (y #3D5DD14AFA2BF24A791E285B90232213D0E3BA74AB1109E768AED19639A322F84BB7D959E2BA92EF73DE4C7F381AA9F4053CFA3CD4527EF9043E304E5B95ED0A3A5A9D590AA641C13DB2B6E32B9B964A6A2C730DD3EA7C8E13F7A140AFF1A91CE375E9B9B960384779DC4EA180FA1F827C52288F366C0770A220F50D6D8FD6F6#)" + " (x #0087F9E91BFBCC1163DE71ED86D557708E32F8ADDE#)))", + "\x04\xA3\x4F\xA0\x2B\x03\x94\xD7\x32\xAD\xD5\x9B\x50\xAF\xDB\x5D\x57\x22\xA6\x10" + }, + { + GCRY_PK_ECDSA, + "(public-key" + " (ecdsa" + " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)" + " (a #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC#)" + " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)" + " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)" + " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)" + " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))", + "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6" + }, + { + GCRY_PK_ECDSA, + "(public-key" + " (ecdsa" + " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)" + " (curve \"NIST P-256\")" + " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)" + " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)" + " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)" + " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))", + "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6" + }, + { + GCRY_PK_ECDSA, + "(public-key" + " (ecdsa" + " (curve secp256r1)" + " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))", + "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6" + } + + }; + +static void +check (void) +{ + unsigned char buf[20]; + unsigned char *ret; + gcry_error_t err; + gcry_sexp_t sexp; + unsigned int i; + + for (i = 0; i < (sizeof (key_grips) / sizeof (*key_grips)); i++) + { + if (gcry_pk_test_algo (key_grips[i].algo)) + { + if (verbose) + fprintf (stderr, "algo %d not available; test skipped\n", + key_grips[i].algo); + continue; + } + err = gcry_sexp_sscan (&sexp, NULL, key_grips[i].key, + strlen (key_grips[i].key)); + if (err) + die ("scanning data %d failed: %s\n", i, gpg_strerror (err)); + ret = gcry_pk_get_keygrip (sexp, buf); + if (!ret) + die ("gcry_pk_get_keygrip failed for %d\n", i); + + if ( memcmp (key_grips[i].grip, buf, sizeof (buf)) ) + { + print_hex ("keygrip: ", buf, sizeof buf); + die ("keygrip for %d does not match\n", i); + } + + gcry_sexp_release (sexp); + } +} + + + +static void +progress_handler (void *cb_data, const char *what, int printchar, + int current, int total) +{ + (void)cb_data; + (void)what; + (void)current; + (void)total; + + putchar (printchar); +} + +int +main (int argc, char **argv) +{ + int debug = 0; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_set_progress_handler (progress_handler, NULL); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + check (); + + return 0; +} diff --git a/tests/mpitests.c b/tests/mpitests.c new file mode 100644 index 0000000..3ccfae0 --- /dev/null +++ b/tests/mpitests.c @@ -0,0 +1,302 @@ +/* mpitests.c - basic mpi tests + * Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#ifdef _GCRYPT_IN_LIBGCRYPT +# include "../src/gcrypt.h" +#else +# include +#endif + +static int verbose; +static int debug; + + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + + + +/* Set up some test patterns */ + +/* 48 bytes with value 1: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ +unsigned char ones[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +/* 48 bytes with value 2: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ +unsigned char twos[] = { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 +}; + +/* 48 bytes with value 3: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ +unsigned char threes[] = { + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 +}; + +/* 48 bytes with value 0x80: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ +unsigned char eighties[] = { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +}; + +/* 48 bytes with value 0xff: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ +unsigned char manyff[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + + + +static int +test_add (void) +{ + gcry_mpi_t one; + gcry_mpi_t two; + gcry_mpi_t ff; + gcry_mpi_t result; + unsigned char* pc; + + gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); + gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); + gcry_mpi_scan(&ff, GCRYMPI_FMT_USG, manyff, sizeof(manyff), NULL); + result = gcry_mpi_new(0); + + gcry_mpi_add(result, one, two); + gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); + if (verbose) + printf("Result of one plus two:\n%s\n", pc); + gcry_free(pc); + + gcry_mpi_add(result, ff, one); + gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); + if (verbose) + printf("Result of ff plus one:\n%s\n", pc); + gcry_free(pc); + + gcry_mpi_release(one); + gcry_mpi_release(two); + gcry_mpi_release(ff); + gcry_mpi_release(result); + return 1; +} + + +static int +test_sub (void) +{ + gcry_mpi_t one; + gcry_mpi_t two; + gcry_mpi_t result; + unsigned char* pc; + + gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); + gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); + result = gcry_mpi_new(0); + gcry_mpi_sub(result, two, one); + + gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); + if (verbose) + printf("Result of two minus one:\n%s\n", pc); + gcry_free(pc); + + gcry_mpi_release(one); + gcry_mpi_release(two); + gcry_mpi_release(result); + return 1; +} + + +static int +test_mul (void) +{ + gcry_mpi_t two; + gcry_mpi_t three; + gcry_mpi_t result; + unsigned char* pc; + + gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); + gcry_mpi_scan(&three, GCRYMPI_FMT_USG, threes, sizeof(threes), NULL); + result = gcry_mpi_new(0); + gcry_mpi_mul(result, two, three); + + gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); + if (verbose) + printf("Result of two mul three:\n%s\n", pc); + gcry_free(pc); + + gcry_mpi_release(two); + gcry_mpi_release(three); + gcry_mpi_release(result); + return 1; +} + + +/* What we test here is that we don't overwrite our args and that + using thne same mpi for several args works. */ +static int +test_powm (void) +{ + int b_int = 17; + int e_int = 3; + int m_int = 19; + gcry_mpi_t base = gcry_mpi_set_ui (NULL, b_int); + gcry_mpi_t exp = gcry_mpi_set_ui (NULL, e_int); + gcry_mpi_t mod = gcry_mpi_set_ui (NULL, m_int); + gcry_mpi_t res = gcry_mpi_new (0); + + gcry_mpi_powm (res, base, exp, mod); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (exp, e_int)) + die ("test_powm_ui failed for exp at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (mod, m_int)) + die ("test_powm failed for mod at %d\n", __LINE__); + + /* Check using base for the result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui (exp, e_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (base, base, exp, mod); + if (gcry_mpi_cmp (res, base)) + die ("test_powm failed at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (exp, e_int)) + die ("test_powm_ui failed for exp at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (mod, m_int)) + die ("test_powm failed for mod at %d\n", __LINE__); + + /* Check using exp for the result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui (exp, e_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (exp, base, exp, mod); + if (gcry_mpi_cmp (res, exp)) + die ("test_powm failed at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (mod, m_int)) + die ("test_powm failed for mod at %d\n", __LINE__); + + /* Check using mod for the result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui (exp, e_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (mod, base, exp, mod); + if (gcry_mpi_cmp (res, mod)) + die ("test_powm failed at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (exp, e_int)) + die ("test_powm_ui failed for exp at %d\n", __LINE__); + + /* Now check base ^ base mod mod. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (res, base, base, mod); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (mod, m_int)) + die ("test_powm failed for mod at %d\n", __LINE__); + + /* Check base ^ base mod mod with base as result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (base, base, base, mod); + if (gcry_mpi_cmp (res, base)) + die ("test_powm failed at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (mod, m_int)) + die ("test_powm failed for mod at %d\n", __LINE__); + + /* Check base ^ base mod mod with mod as result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_set_ui(mod, m_int); + gcry_mpi_powm (mod, base, base, mod); + if (gcry_mpi_cmp (res, mod)) + die ("test_powm failed at %d\n", __LINE__); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + + /* Now check base ^ base mod base. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_powm (res, base, base, base); + if (gcry_mpi_cmp_ui (base, b_int)) + die ("test_powm failed for base at %d\n", __LINE__); + + /* Check base ^ base mod base with base as result. */ + gcry_mpi_set_ui (base, b_int); + gcry_mpi_powm (base, base, base, base); + if (gcry_mpi_cmp (res, base)) + die ("test_powm failed at %d\n", __LINE__); + + /* Fixme: We should add the rest of the cases of course. */ + + + + return 1; +} + + +int +main (int argc, char* argv[]) +{ + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + { + fputs ("version mismatch\n", stderr); + exit (1); + } + gcry_control(GCRYCTL_DISABLE_SECMEM); + + test_add (); + test_sub (); + test_mul (); + test_powm (); + + return 0; +} + diff --git a/tests/pkbench.c b/tests/pkbench.c new file mode 100644 index 0000000..67b94dc --- /dev/null +++ b/tests/pkbench.c @@ -0,0 +1,514 @@ +/* pkbench.c - Pubkey menchmarking + * Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +# include +#endif /*HAVE_W32_SYSTEM*/ +#include +#include +#include +#include + +#define PGM "pkbench" + + +static int verbose; +static int debug; +static int error_count; + + +typedef struct context +{ + gcry_sexp_t key_secret; + gcry_sexp_t key_public; + gcry_sexp_t data; + gcry_sexp_t data_encrypted; + gcry_sexp_t data_signed; +} *context_t; + +typedef int (*work_t) (context_t context, unsigned int final); + + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fputs ( PGM ": ", stderr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + putchar ('\n'); + fputs ( PGM ": ", stderr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +static void +show_sexp (const char *prefix, gcry_sexp_t a) +{ + char *buf; + size_t size; + + fputs (prefix, stderr); + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = gcry_xmalloc (size); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); + gcry_free (buf); +} + + +static void * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + struct stat st; + char *buf; + size_t buflen; + + fp = fopen (fname, "rb"); + if (!fp) + { + fail ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + fail ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = gcry_xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + fail ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + gcry_free (buf); + return NULL; + } + fclose (fp); + + if (r_length) + *r_length = buflen; + return buf; +} + + + +static void +benchmark (work_t worker, context_t context) +{ + clock_t timer_start, timer_stop; + unsigned int loop = 10; + unsigned int i = 0; + struct tms timer; + int ret = 0; + +#ifdef HAVE_W32_SYSTEM + timer_start = clock (); +#else + times (&timer); + timer_start = timer.tms_utime; +#endif + for (i = 0; i < loop; i++) + { + ret = (*worker) (context, (i + 1) == loop); + if (! ret) + break; + } +#ifdef HAVE_W32_SYSTEM + timer_stop = clock (); +#else + times (&timer); + timer_stop = timer.tms_utime; +#endif + + if (ret) + printf ("%.0f ms\n", + (((double) ((timer_stop - timer_start) / loop)) / CLOCKS_PER_SEC) + * 10000000); + else + printf ("[skipped]\n"); +} + +static int +work_encrypt (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_sexp_t data_encrypted = NULL; + int ret = 1; + + err = gcry_pk_encrypt (&data_encrypted, + context->data, context->key_public); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + { + err = GPG_ERR_NO_ERROR; + ret = 0; + } + else + { + assert (! err); + + if (final) + context->data_encrypted = data_encrypted; + else + gcry_sexp_release (data_encrypted); + } + + return ret; +} + +static int +work_decrypt (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + int ret = 1; + + if (! context->data_encrypted) + ret = 0; + else + { + gcry_sexp_t data_decrypted = NULL; + + err = gcry_pk_decrypt (&data_decrypted, + context->data_encrypted, + context->key_secret); + assert (! err); + if (final) + { + gcry_sexp_release (context->data_encrypted); + context->data_encrypted = NULL; + } + gcry_sexp_release (data_decrypted); + } + + return ret; +} + +static int +work_sign (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_sexp_t data_signed = NULL; + int ret = 1; + + err = gcry_pk_sign (&data_signed, + context->data, context->key_secret); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + { + err = GPG_ERR_NO_ERROR; + ret = 0; + } + else if (err) + { + fail ("pk_sign failed: %s\n", gpg_strerror (err)); + ret = 0; + } + else + { + if (final) + context->data_signed = data_signed; + else + gcry_sexp_release (data_signed); + } + + return ret; +} + +static int +work_verify (context_t context, unsigned int final) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + int ret = 1; + + if (!context->data_signed) + return 0; + + err = gcry_pk_verify (context->data_signed, + context->data, + context->key_public); + if (err) + { + show_sexp ("data_signed:\n", context->data_signed); + show_sexp ("data:\n", context->data); + fail ("pk_verify failed: %s\n", gpg_strerror (err)); + ret = 0; + } + else if (final) + { + gcry_sexp_release (context->data_signed); + context->data_signed = NULL; + } + + return ret; +} + +static void +process_key_pair (context_t context) +{ + struct + { + work_t worker; + const char *identifier; + } worker_functions[] = { { work_encrypt, "encrypt" }, + { work_decrypt, "decrypt" }, + { work_sign, "sign" }, + { work_verify, "verify" } }; + unsigned int i = 0; + + for (i = 0; i < (sizeof (worker_functions) / sizeof (*worker_functions)); i++) + { + printf ("%s: ", worker_functions[i].identifier); + benchmark (worker_functions[i].worker, context); + } +} + +static void +context_init (context_t context, gcry_sexp_t key_secret, gcry_sexp_t key_public) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + unsigned int key_size = 0; + gcry_mpi_t data = NULL; + gcry_sexp_t data_sexp = NULL; + + key_size = gcry_pk_get_nbits (key_secret); + assert (key_size); + + data = gcry_mpi_new (key_size); + assert (data); + + gcry_mpi_randomize (data, key_size, GCRY_STRONG_RANDOM); + gcry_mpi_clear_bit (data, key_size - 1); + err = gcry_sexp_build (&data_sexp, NULL, + "(data (flags raw) (value %m))", + data); + assert (! err); + gcry_mpi_release (data); + + context->key_secret = key_secret; + context->key_public = key_public; + context->data = data_sexp; + context->data_encrypted = NULL; + context->data_signed = NULL; +} + +static void +context_destroy (context_t context) +{ + gcry_sexp_release (context->key_secret); + gcry_sexp_release (context->key_public); + gcry_sexp_release (context->data); +} + +static void +process_key_pair_file (const char *key_pair_file) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + void *key_pair_buffer = NULL; + gcry_sexp_t key_pair_sexp = NULL; + gcry_sexp_t key_secret_sexp = NULL; + gcry_sexp_t key_public_sexp = NULL; + struct context context = { NULL }; + size_t file_length; + + key_pair_buffer = read_file (key_pair_file, &file_length); + if (!key_pair_buffer) + die ("failed to open `%s'\n", key_pair_file); + + err = gcry_sexp_sscan (&key_pair_sexp, NULL, + key_pair_buffer, file_length); + if (err) + die ("gcry_sexp_sscan failed\n"); + + key_secret_sexp = gcry_sexp_find_token (key_pair_sexp, "private-key", 0); + assert (key_secret_sexp); + key_public_sexp = gcry_sexp_find_token (key_pair_sexp, "public-key", 0); + assert (key_public_sexp); + + gcry_sexp_release (key_pair_sexp); + + context_init (&context, key_secret_sexp, key_public_sexp); + + printf ("Key file: %s\n", key_pair_file); + process_key_pair (&context); + printf ("\n"); + + context_destroy (&context); + gcry_free (key_pair_buffer); +} + + +static void +generate_key (const char *algorithm, const char *key_size) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + size_t key_pair_buffer_size = 0; + char *key_pair_buffer = NULL; + gcry_sexp_t key_spec = NULL; + gcry_sexp_t key_pair = NULL; + + if (isdigit ((unsigned int)*key_size)) + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (%s (nbits %s)))", + algorithm, key_size); + else + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (%s (curve %s)))", + algorithm, key_size); + if (err) + die ("sexp_build failed: %s\n", gpg_strerror (err)); + + err = gcry_pk_genkey (&key_pair, key_spec); + if (err) + { + show_sexp ("request:\n", key_spec); + die ("pk_genkey failed: %s\n", gpg_strerror (err)); + } + + key_pair_buffer_size = gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED, + NULL, 0); + key_pair_buffer = gcry_xmalloc (key_pair_buffer_size); + + gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED, + key_pair_buffer, key_pair_buffer_size); + + printf ("%.*s", (int)key_pair_buffer_size, key_pair_buffer); + gcry_free (key_pair_buffer); +} + + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int genkey_mode = 0; + int fips_mode = 0; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + puts ("Usage: " PGM " [OPTIONS] [FILES]\n" + "Various public key tests:\n\n" + " Default is to process all given key files\n\n" + " --genkey ALGONAME SIZE Generate a public key\n" + "\n" + " --verbose enable extra informational output\n" + " --debug enable additional debug output\n" + " --help display this help and exit\n\n"); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--genkey")) + { + genkey_mode = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--fips")) + { + fips_mode = 1; + argc--; argv++; + } + } + + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + + if (fips_mode) + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + + gcry_control (GCRYCTL_DISABLE_SECMEM); + if (!gcry_check_version (GCRYPT_VERSION)) + { + fprintf (stderr, PGM ": version mismatch\n"); + exit (1); + } + + if (genkey_mode) + { + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + } + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + + if (genkey_mode && argc == 2) + { + generate_key (argv[0], argv[1]); + } + else if (!genkey_mode && argc) + { + int i; + + for (i = 0; i < argc; i++) + process_key_pair_file (argv[i]); + } + else + { + fprintf (stderr, "usage: " PGM + " [OPTIONS] [FILES] (try --help for more information)\n"); + exit (1); + } + + return error_count ? 1 : 0; +} diff --git a/tests/prime.c b/tests/prime.c new file mode 100644 index 0000000..12bcc89 --- /dev/null +++ b/tests/prime.c @@ -0,0 +1,122 @@ +/* prime.c - part of the Libgcrypt test suite. + Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +static void +check_primes (void) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + gcry_mpi_t *factors = NULL; + gcry_mpi_t prime = NULL; + gcry_mpi_t g; + unsigned int i = 0; + struct prime_spec + { + unsigned int prime_bits; + unsigned int factor_bits; + unsigned int flags; + } prime_specs[] = + { + { 1024, 100, GCRY_PRIME_FLAG_SPECIAL_FACTOR }, + { 128, 0, 0 }, + { 0 }, + }; + + for (i = 0; prime_specs[i].prime_bits; i++) + { + err = gcry_prime_generate (&prime, + prime_specs[i].prime_bits, + prime_specs[i].factor_bits, + &factors, + NULL, NULL, + GCRY_WEAK_RANDOM, + prime_specs[i].flags); + assert (! err); + if (verbose) + { + fprintf (stderr, "test %d: p = ", i); + gcry_mpi_dump (prime); + putc ('\n', stderr); + } + + err = gcry_prime_check (prime, 0); + assert (! err); + + err = gcry_prime_group_generator (&g, prime, factors, NULL); + assert (!err); + gcry_prime_release_factors (factors); factors = NULL; + + if (verbose) + { + fprintf (stderr, " %d: g = ", i); + gcry_mpi_dump (g); + putc ('\n', stderr); + } + gcry_mpi_release (g); + + + gcry_mpi_add_ui (prime, prime, 1); + err = gcry_prime_check (prime, 0); + assert (err); + } +} + +int +main (int argc, char **argv) +{ + int debug = 0; + + if ((argc > 1) && (! strcmp (argv[1], "--verbose"))) + verbose = 1; + else if ((argc > 1) && (! strcmp (argv[1], "--debug"))) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (! gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + + check_primes (); + + return 0; +} diff --git a/tests/pubkey.c b/tests/pubkey.c new file mode 100644 index 0000000..e5ec464 --- /dev/null +++ b/tests/pubkey.c @@ -0,0 +1,890 @@ +/* pubkey.c - Public key encryption/decryption tests + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + + +#include "../src/gcrypt.h" + +/* Sample RSA keys, taken from basic.c. */ + +static const char sample_private_key_1[] = +"(private-key\n" +" (openpgp-rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" + "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" +" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" + "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n" +" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" + "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n" +" )\n" +")\n"; + +/* The same key as above but without p, q and u to test the non CRT case. */ +static const char sample_private_key_1_1[] = +"(private-key\n" +" (openpgp-rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +" )\n" +")\n"; + +/* The same key as above but just without q to test the non CRT case. This + should fail. */ +static const char sample_private_key_1_2[] = +"(private-key\n" +" (openpgp-rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" + "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" +" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" + "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n" +" )\n" +")\n"; + +static const char sample_public_key_1[] = +"(public-key\n" +" (rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" )\n" +")\n"; + + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +static void +show_sexp (const char *prefix, gcry_sexp_t a) +{ + char *buf; + size_t size; + + if (prefix) + fputs (prefix, stderr); + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = gcry_xmalloc (size); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); + gcry_free (buf); +} + + +static void +check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey, + gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code) +{ + gcry_sexp_t plain1, cipher, l; + gcry_mpi_t x0, x1; + int rc; + int have_flags; + + /* Extract data from plaintext. */ + l = gcry_sexp_find_token (plain0, "value", 0); + x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + + /* Encrypt data. */ + rc = gcry_pk_encrypt (&cipher, plain0, pkey); + if (rc) + die ("encryption failed: %s\n", gcry_strerror (rc)); + + l = gcry_sexp_find_token (cipher, "flags", 0); + have_flags = !!l; + gcry_sexp_release (l); + + /* Decrypt data. */ + rc = gcry_pk_decrypt (&plain1, cipher, skey); + gcry_sexp_release (cipher); + if (rc) + { + if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code) + return; /* This is the expected failure code. */ + die ("decryption failed: %s\n", gcry_strerror (rc)); + } + + /* Extract decrypted data. Note that for compatibility reasons, the + output of gcry_pk_decrypt depends on whether a flags lists (even + if empty) occurs in its input data. Because we passed the output + of encrypt directly to decrypt, such a flag value won't be there + as of today. We check it anyway. */ + l = gcry_sexp_find_token (plain1, "value", 0); + if (l) + { + if (!have_flags) + die ("compatibility mode of pk_decrypt broken\n"); + gcry_sexp_release (plain1); + x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l); + } + else + { + if (have_flags) + die ("compatibility mode of pk_decrypt broken\n"); + x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG); + gcry_sexp_release (plain1); + } + + /* Compare. */ + if (gcry_mpi_cmp (x0, x1)) + die ("data corrupted\n"); +} + +static void +check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data, + gpg_err_code_t decrypt_fail_code) +{ + gcry_sexp_t plain; + gcry_mpi_t x; + int rc; + + /* Create plain text. */ + x = gcry_mpi_new (nbits_data); + gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); + + rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x); + if (rc) + die ("converting data for encryption failed: %s\n", + gcry_strerror (rc)); + + check_keys_crypt (pkey, skey, plain, decrypt_fail_code); + gcry_sexp_release (plain); + gcry_mpi_release (x); + + /* Create plain text. */ + x = gcry_mpi_new (nbits_data); + gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); + + rc = gcry_sexp_build (&plain, NULL, + "(data (flags raw no-blinding) (value %m))", x); + if (rc) + die ("converting data for encryption failed: %s\n", + gcry_strerror (rc)); + + check_keys_crypt (pkey, skey, plain, decrypt_fail_code); + gcry_sexp_release (plain); +} + +static void +get_keys_sample (gcry_sexp_t *pkey, gcry_sexp_t *skey, int secret_variant) +{ + gcry_sexp_t pub_key, sec_key; + int rc; + static const char *secret; + + + switch (secret_variant) + { + case 0: secret = sample_private_key_1; break; + case 1: secret = sample_private_key_1_1; break; + case 2: secret = sample_private_key_1_2; break; + default: die ("BUG\n"); + } + + rc = gcry_sexp_sscan (&pub_key, NULL, sample_public_key_1, + strlen (sample_public_key_1)); + if (!rc) + rc = gcry_sexp_sscan (&sec_key, NULL, secret, strlen (secret)); + if (rc) + die ("converting sample keys failed: %s\n", gcry_strerror (rc)); + + *pkey = pub_key; + *skey = sec_key; +} + +static void +get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new (&key_spec, + "(genkey (rsa (nbits 4:1024)))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating RSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated RSA key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (! pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (! sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new (&key_spec, + "(genkey (rsa (nbits 4:1024)(use-x931)))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating RSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated RSA (X9.31) key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new + (&key_spec, + (fixed_x + ? "(genkey (elg (nbits 4:1024)(xvalue my.not-so-secret.key)))" + : "(genkey (elg (nbits 3:512)))"), + 0, 1); + + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating Elgamal key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated ELG key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new (&key_spec, + transient_key + ? "(genkey (dsa (nbits 4:1024)(transient-key)))" + : "(genkey (dsa (nbits 4:1024)))", + 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated DSA key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new + (&key_spec, "(genkey (dsa (nbits 4:1024)(use-fips186)))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated DSA key (fips 186):\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new + (&key_spec, + "(genkey (dsa (transient-key)(domain" + "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" + "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" + "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" + "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)" + "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)" + "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" + "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" + "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" + "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)" + ")))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated DSA key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + +static void +get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new + (&key_spec, + "(genkey (dsa (transient-key)(use-fips186)(domain" + "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" + "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" + "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" + "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)" + "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)" + "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" + "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" + "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" + "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)" + ")))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated DSA key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) +{ + gcry_sexp_t key_spec, key, pub_key, sec_key; + int rc; + + rc = gcry_sexp_new + (&key_spec, + "(genkey" + " (dsa" + " (nbits 4:1024)" + " (use-fips186)" + " (transient-key)" + " (derive-parms" + " (seed #0cb1990c1fd3626055d7a0096f8fa99807399871#))))", + 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + + if (verbose > 1) + show_sexp ("generated DSA key (fips 186 with seed):\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key\n"); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key\n"); + + gcry_sexp_release (key); + *pkey = pub_key; + *skey = sec_key; +} + + +static void +check_run (void) +{ + gpg_error_t err; + gcry_sexp_t pkey, skey; + int variant; + + for (variant=0; variant < 3; variant++) + { + if (verbose) + fprintf (stderr, "Checking sample key (%d).\n", variant); + get_keys_sample (&pkey, &skey, variant); + /* Check gcry_pk_testkey which requires all elements. */ + err = gcry_pk_testkey (skey); + if ((variant == 0 && err) + || (variant > 0 && gpg_err_code (err) != GPG_ERR_NO_OBJ)) + die ("gcry_pk_testkey failed: %s\n", gpg_strerror (err)); + /* Run the usual check but expect an error from variant 2. */ + check_keys (pkey, skey, 800, variant == 2? GPG_ERR_NO_OBJ : 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } + + if (verbose) + fprintf (stderr, "Checking generated RSA key.\n"); + get_keys_new (&pkey, &skey); + check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Checking generated RSA key (X9.31).\n"); + get_keys_x931_new (&pkey, &skey); + check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Checking generated Elgamal key.\n"); + get_elg_key_new (&pkey, &skey, 0); + check_keys (pkey, skey, 400, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Checking passphrase generated Elgamal key.\n"); + get_elg_key_new (&pkey, &skey, 1); + check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Generating DSA key.\n"); + get_dsa_key_new (&pkey, &skey, 0); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (!gcry_fips_mode_active ()) + { + if (verbose) + fprintf (stderr, "Generating transient DSA key.\n"); + get_dsa_key_new (&pkey, &skey, 1); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } + + if (verbose) + fprintf (stderr, "Generating DSA key (FIPS 186).\n"); + get_dsa_key_fips186_new (&pkey, &skey); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Generating DSA key with given domain.\n"); + get_dsa_key_with_domain_new (&pkey, &skey); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Generating DSA key with given domain (FIPS 186).\n"); + get_dsa_key_fips186_with_domain_new (&pkey, &skey); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n"); + get_dsa_key_fips186_with_seed_new (&pkey, &skey); + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); +} + + + +static gcry_mpi_t +key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name) +{ + gcry_sexp_t l1, l2; + gcry_mpi_t result; + + l1 = gcry_sexp_find_token (sexp, topname, 0); + if (!l1) + return NULL; + + l2 = gcry_sexp_find_token (l1, name, 0); + if (!l2) + { + gcry_sexp_release (l1); + return NULL; + } + + result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + gcry_sexp_release (l1); + return result; +} + + +static void +check_x931_derived_key (int what) +{ + static struct { + const char *param; + const char *expected_d; + } testtable[] = { + { /* First example from X9.31 (D.1.1). */ + "(genkey\n" + " (rsa\n" + " (nbits 4:1024)\n" + " (rsa-use-e 1:3)\n" + " (derive-parms\n" + " (Xp1 #1A1916DDB29B4EB7EB6732E128#)\n" + " (Xp2 #192E8AAC41C576C822D93EA433#)\n" + " (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D\n" + " 769D6D76646C7A792E16EBD89FE6FC5B605A6493\n" + " 39DFC925A86A4C6D150B71B9EEA02D68885F5009\n" + " B98BD984#)\n" + " (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)\n" + " (Xq2 #134E4CAA16D2350A21D775C404#)\n" + " (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D\n" + " 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325\n" + " 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34\n" + " 321DE34A#))))\n", + "1CCDA20BCFFB8D517EE9666866621B11822C7950D55F4BB5BEE37989A7D173" + "12E326718BE0D79546EAAE87A56623B919B1715FFBD7F16028FC4007741961" + "C88C5D7B4DAAAC8D36A98C9EFBB26C8A4A0E6BC15B358E528A1AC9D0F042BE" + "B93BCA16B541B33F80C933A3B769285C462ED5677BFE89DF07BED5C127FD13" + "241D3C4B" + }, + + { /* Second example from X9.31 (D.2.1). */ + "(genkey\n" + " (rsa\n" + " (nbits 4:1536)\n" + " (rsa-use-e 1:3)\n" + " (derive-parms\n" + " (Xp1 #18272558B61316348297EACA74#)\n" + " (Xp2 #1E970E8C6C97CEF91F05B0FA80#)\n" + " (Xp #F7E943C7EF2169E930DCF23FE389EF7507EE8265\n" + " 0D42F4A0D3A3CEFABE367999BB30EE680B2FE064\n" + " 60F707F46005F8AA7CBFCDDC4814BBE7F0F8BC09\n" + " 318C8E51A48D134296E40D0BBDD282DCCBDDEE1D\n" + " EC86F0B1C96EAFF5CDA70F9AEB6EE31E#)\n" + " (Xq1 #11FDDA6E8128DC1629F75192BA#)\n" + " (Xq2 #18AB178ECA907D72472F65E480#)\n" + " (Xq #C47560011412D6E13E3E7D007B5C05DBF5FF0D0F\n" + " CFF1FA2070D16C7ABA93EDFB35D8700567E5913D\n" + " B734E3FBD15862EBC59FA0425DFA131E549136E8\n" + " E52397A8ABE4705EC4877D4F82C4AAC651B33DA6\n" + " EA14B9D5F2A263DC65626E4D6CEAC767#))))\n", + "1FB56069985F18C4519694FB71055721A01F14422DC901C35B03A64D4A5BD1" + "259D573305F5B056AC931B82EDB084E39A0FD1D1A86CC5B147A264F7EF4EB2" + "0ED1E7FAAE5CAE4C30D5328B7F74C3CAA72C88B70DED8EDE207B8629DA2383" + "B78C3CE1CA3F9F218D78C938B35763AF2A8714664CC57F5CECE2413841F5E9" + "EDEC43B728E25A41BF3E1EF8D9EEE163286C9F8BF0F219D3B322C3E4B0389C" + "2E8BB28DC04C47DA2BF38823731266D2CF6CC3FC181738157624EF051874D0" + "BBCCB9F65C83" + /* Note that this example in X9.31 gives this value for D: + + "7ED581A6617C6311465A53EDC4155C86807C5108B724070D6C0E9935296F44" + "96755CCC17D6C15AB24C6E0BB6C2138E683F4746A1B316C51E8993DFBD3AC8" + "3B479FEAB972B930C354CA2DFDD30F2A9CB222DC37B63B7881EE18A7688E0E" + "DE30F38728FE7C8635E324E2CD5D8EBCAA1C51993315FD73B38904E107D7A7" + "B7B10EDCA3896906FCF87BE367BB858CA1B27E2FC3C8674ECC8B0F92C0E270" + "BA2ECA3701311F68AFCE208DCC499B4B3DB30FF0605CE055D893BC1461D342" + "EF32E7D9720B" + + This is a bug in X9.31, obviously introduced by using + + d = e^{-1} mod (p-1)(q-1) + + instead of using the universal exponent as required by 4.1.3: + + d = e^{-1} mod lcm(p-1,q-1) + + The examples in X9.31 seem to be pretty buggy, see + cipher/primegen.c for another bug. Not only that I had to + spend 100 USD for the 66 pages of the document, it also took + me several hours to figure out that the bugs are in the + document and not in my code. + */ + }, + + { /* First example from NIST RSAVS (B.1.1). */ + "(genkey\n" + " (rsa\n" + " (nbits 4:1024)\n" + " (rsa-use-e 1:3)\n" + " (derive-parms\n" + " (Xp1 #1ed3d6368e101dab9124c92ac8#)\n" + " (Xp2 #16e5457b8844967ce83cab8c11#)\n" + " (Xp #b79f2c2493b4b76f329903d7555b7f5f06aaa5ea\n" + " ab262da1dcda8194720672a4e02229a0c71f60ae\n" + " c4f0d2ed8d49ef583ca7d5eeea907c10801c302a\n" + " cab44595#)\n" + " (Xq1 #1a5d9e3fa34fb479bedea412f6#)\n" + " (Xq2 #1f9cca85f185341516d92e82fd#)\n" + " (Xq #c8387fd38fa33ddcea6a9de1b2d55410663502db\n" + " c225655a9310cceac9f4cf1bce653ec916d45788\n" + " f8113c46bc0fa42bf5e8d0c41120c1612e2ea8bb\n" + " 2f389eda#))))\n", + "17ef7ad4fd96011b62d76dfb2261b4b3270ca8e07bc501be954f8719ef586b" + "f237e8f693dd16c23e7adecc40279dc6877c62ab541df5849883a5254fccfd" + "4072a657b7f4663953930346febd6bbd82f9a499038402cbf97fd5f068083a" + "c81ad0335c4aab0da19cfebe060a1bac7482738efafea078e21df785e56ea0" + "dc7e8feb" + }, + + { /* Second example from NIST RSAVS (B.1.1). */ + "(genkey\n" + " (rsa\n" + " (nbits 4:1536)\n" + " (rsa-use-e 1:3)\n" + " (derive-parms\n" + " (Xp1 #1e64c1af460dff8842c22b64d0#)\n" + " (Xp2 #1e948edcedba84039c81f2ac0c#)\n" + " (Xp #c8c67df894c882045ede26a9008ab09ea0672077\n" + " d7bc71d412511cd93981ddde8f91b967da404056\n" + " c39f105f7f239abdaff92923859920f6299e82b9\n" + " 5bd5b8c959948f4a034d81613d6235a3953b49ce\n" + " 26974eb7bb1f14843841281b363b9cdb#)\n" + " (Xq1 #1f3df0f017ddd05611a97b6adb#)\n" + " (Xq2 #143edd7b22d828913abf24ca4d#)\n" + " (Xq #f15147d0e7c04a1e3f37adde802cdc610999bf7a\n" + " b0088434aaeda0c0ab3910b14d2ce56cb66bffd9\n" + " 7552195fae8b061077e03920814d8b9cfb5a3958\n" + " b3a82c2a7fc97e55db543948d3396289245336ec\n" + " 9e3cb308cc655aebd766340da8921383#))))\n", + "1f8b19f3f5f2ac9fc599f110cad403dcd9bdf5f7f00fb2790e78e820398184" + "1f3fb3dd230fb223d898f45719d9b2d3525587ff2b8bcc7425e40550a5b536" + "1c8e9c1d26e83fbd9c33c64029c0e878b829d55def12912b73d94fd758c461" + "0f473e230c41b5e4c86e27c5a5029d82c811c88525d0269b95bd2ff272994a" + "dbd80f2c2ecf69065feb8abd8b445b9c6d306b1585d7d3d7576d49842bc7e2" + "8b4a2f88f4a47e71c3edd35fdf83f547ea5c2b532975c551ed5268f748b2c4" + "2ccf8a84835b" + } + }; + gpg_error_t err; + gcry_sexp_t key_spec, key, pub_key, sec_key; + gcry_mpi_t d_expected, d_have; + + if (what < 0 && what >= sizeof testtable) + die ("invalid WHAT value\n"); + + err = gcry_sexp_new (&key_spec, testtable[what].param, 0, 1); + if (err) + die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err)); + + err = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (err) + die ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err)); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + die ("public part missing in key [%d]\n", what); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + die ("private part missing in key [%d]\n", what); + + err = gcry_mpi_scan + (&d_expected, GCRYMPI_FMT_HEX, testtable[what].expected_d, 0, NULL); + if (err) + die ("error converting string [%d]\n", what); + + if (verbose > 1) + show_sexp ("generated key:\n", key); + + d_have = key_param_from_sexp (sec_key, "rsa", "d"); + if (!d_have) + die ("parameter d not found in RSA secret key [%d]\n", what); + if (gcry_mpi_cmp (d_expected, d_have)) + { + show_sexp (NULL, sec_key); + die ("parameter d does match expected value [%d]\n", what); + } + gcry_mpi_release (d_expected); + gcry_mpi_release (d_have); + + gcry_sexp_release (key); + gcry_sexp_release (pub_key); + gcry_sexp_release (sec_key); +} + + + + +int +main (int argc, char **argv) +{ + int debug = 0; + int i; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + { + verbose = 2; + debug = 1; + } + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + for (i=0; i < 2; i++) + check_run (); + + for (i=0; i < 4; i++) + check_x931_derived_key (i); + + return 0; +} diff --git a/tests/random.c b/tests/random.c new file mode 100644 index 0000000..502a375 --- /dev/null +++ b/tests/random.c @@ -0,0 +1,255 @@ +/* random.c - part of the Libgcrypt test suite. + Copyright (C) 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + + +static void +print_hex (const char *text, const void *buf, size_t n) +{ + const unsigned char *p = buf; + + fputs (text, stdout); + for (; n; n--, p++) + printf ("%02X", *p); + putchar ('\n'); +} + + +static int +writen (int fd, const void *buf, size_t nbytes) +{ + size_t nleft = nbytes; + int nwritten; + + while (nleft > 0) + { + nwritten = write (fd, buf, nleft); + if (nwritten < 0) + { + if (errno == EINTR) + nwritten = 0; + else + return -1; + } + nleft -= nwritten; + buf = (const char*)buf + nwritten; + } + + return 0; +} + +static int +readn (int fd, void *buf, size_t buflen, size_t *ret_nread) +{ + size_t nleft = buflen; + int nread; + char *p; + + p = buf; + while ( nleft > 0 ) + { + nread = read ( fd, buf, nleft ); + if (nread < 0) + { + if (nread == EINTR) + nread = 0; + else + return -1; + } + else if (!nread) + break; /* EOF */ + nleft -= nread; + buf = (char*)buf + nread; + } + if (ret_nread) + *ret_nread = buflen - nleft; + return 0; +} + + + +/* Check that forking won't return the same random. */ +static void +check_forking (void) +{ + pid_t pid; + int rp[2]; + int i, status; + size_t nread; + char tmp1[16], tmp1c[16], tmp1p[16]; + + /* We better make sure that the RNG has been initialzied. */ + gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM); + if (verbose) + print_hex ("initial random: ", tmp1, sizeof tmp1); + + if (pipe (rp) == -1) + die ("pipe failed: %s\n", strerror (errno)); + + pid = fork (); + if (pid == (pid_t)(-1)) + die ("fork failed: %s\n", strerror (errno)); + if (!pid) + { + gcry_randomize (tmp1c, sizeof tmp1c, GCRY_STRONG_RANDOM); + if (writen (rp[1], tmp1c, sizeof tmp1c)) + die ("write failed: %s\n", strerror (errno)); + if (verbose) + { + print_hex (" child random: ", tmp1c, sizeof tmp1c); + fflush (stdout); + } + _exit (0); + } + gcry_randomize (tmp1p, sizeof tmp1p, GCRY_STRONG_RANDOM); + if (verbose) + print_hex (" parent random: ", tmp1p, sizeof tmp1p); + + close (rp[1]); + if (readn (rp[0], tmp1c, sizeof tmp1c, &nread)) + die ("read failed: %s\n", strerror (errno)); + if (nread != sizeof tmp1c) + die ("read too short\n"); + + while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; + if (i != (pid_t)(-1) + && WIFEXITED (status) && !WEXITSTATUS (status)) + ; + else + die ("child failed\n"); + + if (!memcmp (tmp1p, tmp1c, sizeof tmp1c)) + die ("parent and child got the same random number\n"); +} + + + +/* Check that forking won't return the same nonce. */ +static void +check_nonce_forking (void) +{ + pid_t pid; + int rp[2]; + int i, status; + size_t nread; + char nonce1[10], nonce1c[10], nonce1p[10]; + + /* We won't get the same nonce back if we never initialized the + nonce subsystem, thus we get one nonce here and forget about + it. */ + gcry_create_nonce (nonce1, sizeof nonce1); + if (verbose) + print_hex ("initial nonce: ", nonce1, sizeof nonce1); + + if (pipe (rp) == -1) + die ("pipe failed: %s\n", strerror (errno)); + + pid = fork (); + if (pid == (pid_t)(-1)) + die ("fork failed: %s\n", strerror (errno)); + if (!pid) + { + gcry_create_nonce (nonce1c, sizeof nonce1c); + if (writen (rp[1], nonce1c, sizeof nonce1c)) + die ("write failed: %s\n", strerror (errno)); + if (verbose) + { + print_hex (" child nonce: ", nonce1c, sizeof nonce1c); + fflush (stdout); + } + _exit (0); + } + gcry_create_nonce (nonce1p, sizeof nonce1p); + if (verbose) + print_hex (" parent nonce: ", nonce1p, sizeof nonce1p); + + close (rp[1]); + if (readn (rp[0], nonce1c, sizeof nonce1c, &nread)) + die ("read failed: %s\n", strerror (errno)); + if (nread != sizeof nonce1c) + die ("read too short\n"); + + while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; + if (i != (pid_t)(-1) + && WIFEXITED (status) && !WEXITSTATUS (status)) + ; + else + die ("child failed\n"); + + if (!memcmp (nonce1p, nonce1c, sizeof nonce1c)) + die ("parent and child got the same nonce\n"); +} + + + + + + +int +main (int argc, char **argv) +{ + int debug = 0; + + if ((argc > 1) && (! strcmp (argv[1], "--verbose"))) + verbose = 1; + else if ((argc > 1) && (! strcmp (argv[1], "--debug"))) + verbose = debug = 1; + + signal (SIGPIPE, SIG_IGN); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + + check_forking (); + check_nonce_forking (); + + return 0; +} diff --git a/tests/register.c b/tests/register.c new file mode 100644 index 0000000..df90fe0 --- /dev/null +++ b/tests/register.c @@ -0,0 +1,187 @@ +/* register.c - Test for registering of additional cipher modules. + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +static int verbose; +static int in_fips_mode; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +gcry_err_code_t +foo_setkey (void *c, const unsigned char *key, unsigned keylen) +{ + (void)c; + (void)key; + (void)keylen; + + return 0; +} + +#define FOO_BLOCKSIZE 16 + +void +foo_encrypt (void *c, unsigned char *outbuf, const unsigned char *inbuf) +{ + int i; + + (void)c; + + for (i = 0; i < FOO_BLOCKSIZE; i++) + outbuf[i] = inbuf[i] ^ 0x42; +} + +void +foo_decrypt (void *c, unsigned char *outbuf, const unsigned char *inbuf) +{ + int i; + + (void)c; + + for (i = 0; i < FOO_BLOCKSIZE; i++) + outbuf[i] = inbuf[i] ^ 0x42; +} + +gcry_cipher_spec_t cipher_spec_foo = + { + "FOO", NULL, NULL, 16, 0, 0, + foo_setkey, foo_encrypt, foo_decrypt, + NULL, NULL, + }; + +int +check_list (int algorithm) +{ + gcry_error_t err = GPG_ERR_NO_ERROR; + int *list, list_length; + int i, ret = 0; + + err = gcry_cipher_list (NULL, &list_length); + assert (! err); + list = malloc (sizeof (int) * list_length); + assert (list); + err = gcry_cipher_list (list, &list_length); + + for (i = 0; i < list_length && (! ret); i++) + if (list[i] == algorithm) + ret = 1; + + return ret; +} + +void +check_run (void) +{ + int err, algorithm; + gcry_cipher_hd_t h; + char plain[16] = "Heil Discordia!"; + char encrypted[16], decrypted[16]; + gcry_module_t module; + int ret; + + err = gcry_cipher_register (&cipher_spec_foo, &algorithm, &module); + if (in_fips_mode) + { + if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) + die ("register cipher failed in fips mode: %s\n", gpg_strerror (err)); + return; + } + else + { + if (err) + die ("register cipher failed: %s\n", gpg_strerror (err)); + } + + err = gcry_cipher_open (&h, algorithm, GCRY_CIPHER_MODE_CBC, 0); + if (err) + die ("gcry_cipher_open failed: %s\n", gpg_strerror (err)); + + err = gcry_cipher_encrypt (h, + (unsigned char *) encrypted, sizeof (encrypted), + (unsigned char *) plain, sizeof (plain)); + assert (! err); + assert (memcmp ((void *) plain, (void *) encrypted, sizeof (plain))); + + err = gcry_cipher_reset (h); + assert (! err); + + err = gcry_cipher_decrypt (h, + (unsigned char *) decrypted, sizeof (decrypted), + (unsigned char *) encrypted, sizeof (encrypted)); + assert (! err); + assert (! memcmp ((void *) plain, (void *) decrypted, sizeof (plain))); + + ret = check_list (algorithm); + assert (ret); + + gcry_cipher_close (h); + + gcry_cipher_unregister (module); + + ret = check_list (algorithm); + assert (! ret); +} + +int +main (int argc, char **argv) +{ + int debug = 0; + int i = 1; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + + if ( gcry_control (GCRYCTL_FIPS_MODE_P, 0) ) + in_fips_mode = 1; + + for (; i > 0; i--) + check_run (); + + /* In fips mode we let the Makefile skip this test because a PASS + would not make much sense with all egistering disabled. */ + return in_fips_mode? 77:0; +} diff --git a/tests/rsa-16k.key b/tests/rsa-16k.key new file mode 100644 index 0000000..017915a --- /dev/null +++ b/tests/rsa-16k.key @@ -0,0 +1,18 @@ +(key-data + (public-key + (rsa + (n #00D6007A7AD47BB8D6B356E4F24DFAEE3A722FEE77F7E9547F866CB369C233E6CB3916D416973E3157B4DC1837E6D4C907D1063855735EAA857176A7DA3CA9F378FF7AE9EF227C193965F106F35DB2A833D2760CF9F2D041938CD310D9CE38EDD179C33EBC4963A02221D8000FDBF4BEB592CAB1ED1EEEC9D6916F27263C76DE70184F5399DE3B3862227346B1B3FBA306174D08BEC3675E2593CFD42159655B0BE1A2B69C2BA9F4F03B8C6BA505F6BFDFC6163D74F42A6D4908284D6879CECCF6512F9225612E3030ACF3663DFB77B41AFFCFC70BC11B224E14B397D25AC15E4E342B34B363056EA76CB0265DBD41F733C7FDE98B7C2340289E338CD31F993ABFACA6E83B54BCB50DD1DD11165C188C80EBDA190A11B6D8982CDA1B6B9D1631AA3EACC93040237831A52D15826A0D3E92C833D0234975C92A7236F902FA6703C89C7779765020C11F714B4C9D33B76CD466DC2BE9A102488B0635F31E6FBB9282E5139D32623E10ED9C295DA3B39F68227218EDF8C6FE9372F174AE1DE5BBE7B0AF09A869CAEDBEFE05458BFD43CF32F10F5C345A2E3D588C8C16B4DA8B44FA9539C679B81133A35498696F5D866E3B6A89811AEA7BFD1BF690EC329D87989CDADA7EAB106785D2D6661BD400D76C113E28F13FD883027E1CAC848B13750C7CCD530273C165BDFDA93E6F72897E97F003308704B95801F223EE89160786B1DE440BA9C1F371CBA37E5B09650CDB3AA1ABAA237AD15B89DCD03390A28308643E219490BEC83403F6A09B94F81D7BB391C121FC9028A6908E5B287AC79209B905B33724B1869A679CB347BF192D80D2D66CF1DAEFEBBF22CEDB8CEC010D6F8D86CD055ED71425DA72DF1C07A573E6F070235C378DAB5404ED004B4946CCDA4786ACBBF379A47CC36A049C50651CA4B1CEF03EE87DB6D2484C3D10AF71798A6AD1E20780814F79348D45BD1004880D2DEDEBD152694C80B9F93DF32F5930911DB379B4CBB9230CFC5FC126B9B77F074B9C82BDB4F12471B3FE92079525FD276293B63B978B55E039024EE688180D7C7C6C094B754AB9B652AC31812F2F7E45EF2B6D4478D7C6E5C8F3CB0A4D04A3E693D1DD4D8F894E910D9A999DDABE0427A1AB0C715C5A695A69140B20B9DA1195E6C9536B5DF24B4D45ED24D0F2C276E3CF48066EFB977C2B7096B02EB52309D916BD432347D72799BF9D76A03D54DE211460017C0E268BC9E23B415ABF46EB8B939B5A413EBD3F20E95F704E1F2CDCDF974A8743923DBC6D8363DC8948BE85EF1D368CD3EABDBE5B82648D2F676EB310D7B77465D3A14B86050463E43AC745F3781E7A6F582BD7B8AB22BC4EEECD2CB155E6E0B2604843E3906D47EBDA2C10B6D8BFCBB5722CE5394EB50721E90EFD28C63A62269C8C14593D69076D0F198D2BDCCB6D753CB81C4BED56A90E2DDBFFC0B9076C65F973B5EA3242E71E3CBBFE0976CFE22475F56726058D2D0CE3BD52AA940A0F559DD055BE9A6F50846902E02B70DB4FF5BED33762E10409D25ABDACF661BD9BA2A22212E02893A1625CA44850887B4B3A00D0AF63645E2EC42333035062090E8E7E63037C692FBA0B3FC7F3686FC2831F4DE2D4D82CF6FD6321D6621C8227715E3772EE8805911AA9E67083C511F17863C4D6F2C29E19CF329200024E539A7C5BF1A9D601AFF8DB7CFD75C6532488469E44BAC7266A3C127720E640328F9970B75509E292CCEC0B55A1F729456CB2804BE50451185F8CDA313C7D4DF6C1C67D6C411025A2BFFF06C5062470F97B17E75B4F81CD1FEC777465D684849809B4281B690D2A8FE5C4FA87DB00328630FC31BFDDA4641B29CB434147806A614E450E3E2B50317E3B4EE6262A2D4D0A8FE7530CEDFBCB5016C4D6E61C34E61AFA324871A9C75F9BC6BF6C92B95910C9D0FE049AEEF2E96E4C9E69E1FCE1F6CC687D533668F55367E2695197BE392A7FE66C4F88C0B1A9DEC6DFF682675855979DEA2A5644748DD882CE1F0D8FDA8530617BAA130AD9C16ABF8D76B5853104AD2E0C54C9639C3F6E1343AC94139621245EE8E12CA4366A6EC752BD9D1A0948CCC3626CEDB882BA4638115BBF55444DD4544EEC561F0E762C9989A9306D4749ABD47C31F40AD3F735FEEE6E1FDCEB626073CD5F76730B348103B041B9EEB941EFA61581DD9278802A2934C33FF0668C25CEF2546C44263A68919ECBB540B4A18E1867EA15C9F7A2853F55EFBB01C3D27D28579E030D0A771B754680FCD46B56EBD3431C24F202A343E20294076E56A09FA5F6C3E844DAF5BDCFBFF55CCC3FDDDB060FBC680BA520153098E57FC7741D77DFA8932F9028D8E0E66600974A41DAC5BBA4690407AC36EC206655ADCECC8AA0471601F67C3DF48B830585FA15C52061C4FF958453B1E75626120CDC0ADCE44743027FA4C59C1931E90726CD2BE240D0DC6D61CDE5165350D86FFF17260A823C0AE3467A597D774A67BE843951975E17BC1CB69DC8A0C7BFF799FB8FD2BDB37853D2EB28C9B7B8A2212FC73FDF2F21FF3FBCD798533FC4867739E48BA061B174BAC224064F3E867A1CF52E091FDD36871955FBEA90CD3D23B1BF0039930E0636080E6A36206ED5DD1CE4546EC0B0802BBEE2869DCCAEA01B8FC3A6392820180AA4D99AB67C57E8FD0874E7C54BBC7B9A2AA4D1EA4ADC1A2802DF908AF74F915AF98EEEBF822AC958CD0D9AF5A754AB2F4790225F18864A94734E526BDE497FF21F3392472D4F0E3B7E2EE97DDCA15060BF35A05E2593418809D3C9738C328EB4D44F35E6C913069096B0742809F55F01D06D40EB0476C34950FDAEF9BD2CC1F7653B4BCF1AA304963530C8F0C39697EAD32ADF464E3CAC931D33992B357A3A231FB978A56C3592A61411A5428C3549A991D811#) + (e #010001#) + ) + ) + (private-key + (rsa + (n #00D6007A7AD47BB8D6B356E4F24DFAEE3A722FEE77F7E9547F866CB369C233E6CB3916D416973E3157B4DC1837E6D4C907D1063855735EAA857176A7DA3CA9F378FF7AE9EF227C193965F106F35DB2A833D2760CF9F2D041938CD310D9CE38EDD179C33EBC4963A02221D8000FDBF4BEB592CAB1ED1EEEC9D6916F27263C76DE70184F5399DE3B3862227346B1B3FBA306174D08BEC3675E2593CFD42159655B0BE1A2B69C2BA9F4F03B8C6BA505F6BFDFC6163D74F42A6D4908284D6879CECCF6512F9225612E3030ACF3663DFB77B41AFFCFC70BC11B224E14B397D25AC15E4E342B34B363056EA76CB0265DBD41F733C7FDE98B7C2340289E338CD31F993ABFACA6E83B54BCB50DD1DD11165C188C80EBDA190A11B6D8982CDA1B6B9D1631AA3EACC93040237831A52D15826A0D3E92C833D0234975C92A7236F902FA6703C89C7779765020C11F714B4C9D33B76CD466DC2BE9A102488B0635F31E6FBB9282E5139D32623E10ED9C295DA3B39F68227218EDF8C6FE9372F174AE1DE5BBE7B0AF09A869CAEDBEFE05458BFD43CF32F10F5C345A2E3D588C8C16B4DA8B44FA9539C679B81133A35498696F5D866E3B6A89811AEA7BFD1BF690EC329D87989CDADA7EAB106785D2D6661BD400D76C113E28F13FD883027E1CAC848B13750C7CCD530273C165BDFDA93E6F72897E97F003308704B95801F223EE89160786B1DE440BA9C1F371CBA37E5B09650CDB3AA1ABAA237AD15B89DCD03390A28308643E219490BEC83403F6A09B94F81D7BB391C121FC9028A6908E5B287AC79209B905B33724B1869A679CB347BF192D80D2D66CF1DAEFEBBF22CEDB8CEC010D6F8D86CD055ED71425DA72DF1C07A573E6F070235C378DAB5404ED004B4946CCDA4786ACBBF379A47CC36A049C50651CA4B1CEF03EE87DB6D2484C3D10AF71798A6AD1E20780814F79348D45BD1004880D2DEDEBD152694C80B9F93DF32F5930911DB379B4CBB9230CFC5FC126B9B77F074B9C82BDB4F12471B3FE92079525FD276293B63B978B55E039024EE688180D7C7C6C094B754AB9B652AC31812F2F7E45EF2B6D4478D7C6E5C8F3CB0A4D04A3E693D1DD4D8F894E910D9A999DDABE0427A1AB0C715C5A695A69140B20B9DA1195E6C9536B5DF24B4D45ED24D0F2C276E3CF48066EFB977C2B7096B02EB52309D916BD432347D72799BF9D76A03D54DE211460017C0E268BC9E23B415ABF46EB8B939B5A413EBD3F20E95F704E1F2CDCDF974A8743923DBC6D8363DC8948BE85EF1D368CD3EABDBE5B82648D2F676EB310D7B77465D3A14B86050463E43AC745F3781E7A6F582BD7B8AB22BC4EEECD2CB155E6E0B2604843E3906D47EBDA2C10B6D8BFCBB5722CE5394EB50721E90EFD28C63A62269C8C14593D69076D0F198D2BDCCB6D753CB81C4BED56A90E2DDBFFC0B9076C65F973B5EA3242E71E3CBBFE0976CFE22475F56726058D2D0CE3BD52AA940A0F559DD055BE9A6F50846902E02B70DB4FF5BED33762E10409D25ABDACF661BD9BA2A22212E02893A1625CA44850887B4B3A00D0AF63645E2EC42333035062090E8E7E63037C692FBA0B3FC7F3686FC2831F4DE2D4D82CF6FD6321D6621C8227715E3772EE8805911AA9E67083C511F17863C4D6F2C29E19CF329200024E539A7C5BF1A9D601AFF8DB7CFD75C6532488469E44BAC7266A3C127720E640328F9970B75509E292CCEC0B55A1F729456CB2804BE50451185F8CDA313C7D4DF6C1C67D6C411025A2BFFF06C5062470F97B17E75B4F81CD1FEC777465D684849809B4281B690D2A8FE5C4FA87DB00328630FC31BFDDA4641B29CB434147806A614E450E3E2B50317E3B4EE6262A2D4D0A8FE7530CEDFBCB5016C4D6E61C34E61AFA324871A9C75F9BC6BF6C92B95910C9D0FE049AEEF2E96E4C9E69E1FCE1F6CC687D533668F55367E2695197BE392A7FE66C4F88C0B1A9DEC6DFF682675855979DEA2A5644748DD882CE1F0D8FDA8530617BAA130AD9C16ABF8D76B5853104AD2E0C54C9639C3F6E1343AC94139621245EE8E12CA4366A6EC752BD9D1A0948CCC3626CEDB882BA4638115BBF55444DD4544EEC561F0E762C9989A9306D4749ABD47C31F40AD3F735FEEE6E1FDCEB626073CD5F76730B348103B041B9EEB941EFA61581DD9278802A2934C33FF0668C25CEF2546C44263A68919ECBB540B4A18E1867EA15C9F7A2853F55EFBB01C3D27D28579E030D0A771B754680FCD46B56EBD3431C24F202A343E20294076E56A09FA5F6C3E844DAF5BDCFBFF55CCC3FDDDB060FBC680BA520153098E57FC7741D77DFA8932F9028D8E0E66600974A41DAC5BBA4690407AC36EC206655ADCECC8AA0471601F67C3DF48B830585FA15C52061C4FF958453B1E75626120CDC0ADCE44743027FA4C59C1931E90726CD2BE240D0DC6D61CDE5165350D86FFF17260A823C0AE3467A597D774A67BE843951975E17BC1CB69DC8A0C7BFF799FB8FD2BDB37853D2EB28C9B7B8A2212FC73FDF2F21FF3FBCD798533FC4867739E48BA061B174BAC224064F3E867A1CF52E091FDD36871955FBEA90CD3D23B1BF0039930E0636080E6A36206ED5DD1CE4546EC0B0802BBEE2869DCCAEA01B8FC3A6392820180AA4D99AB67C57E8FD0874E7C54BBC7B9A2AA4D1EA4ADC1A2802DF908AF74F915AF98EEEBF822AC958CD0D9AF5A754AB2F4790225F18864A94734E526BDE497FF21F3392472D4F0E3B7E2EE97DDCA15060BF35A05E2593418809D3C9738C328EB4D44F35E6C913069096B0742809F55F01D06D40EB0476C34950FDAEF9BD2CC1F7653B4BCF1AA304963530C8F0C39697EAD32ADF464E3CAC931D33992B357A3A231FB978A56C3592A61411A5428C3549A991D811#) + (e #010001#) + (d #0125A7ED14E014111AE2BD8FD81A69B0BDED886DBE477D9CC08C6B07F1F82BD5BD73797FF9FFFB0D2542BE97FD1DCE9FE30F516F117DB449B513C85EF779DC91DD57B6B2E1BDD077A1EBE148486C2ADC8FEAC7FE1BD40BDD45E6833B26FB75388D05293177EE12678B197B42EFD59A38985B4BB471A3761E41F1BA8AB3A2AFA5A241B999096B8A9809BC7C5DBB3BDF476049AE7671A47213C9922B7E4C1A5545BA92C555100DB00AB77254C8E1DFC283F3EDE901819B611CD5E551133D14E8FD18840F6331D29E2EED47118E7094C1E36E53DA2AA90133856A351367224B51F80C184A5C3C4CDA5CC822126B3DF696AE96BFB8B836FA56E4E8D7D8A545E5F668F23203AC6968BE0A8A0C3BEEAC0AC9CFAE994B8EA5E293A5B9817D49B89761528595BB99D83C2B1AA4054FA2FF1D1D4F8ADBC3E863D8F4BD8C76C38E057D81740FB4FB12BC3CF80AB510223934FE8D3FD461D17E9B4EA07380A7E5202DD93A40B1F2E6C2048160949A247AC9A3F962A4E2F4EE809F00C76AF8DA4737D1398E6A95BE4637C949A33492C9691B254EB239EA7B1EC0E2D4261A27183F90577F04B356FD10FDB5E23A4471068952930EAFF4EDC757ACE25781DBA807A0C153FEDDCCB55A08B774AB44AD2CC75BD319D4822BFC6AF24C9F837C72D1A615109882906ADC2B2C679630A6FAE363144B77A134F2856DF1D8E9A77AAEC08A72FD67C122BD280D591A6C4045D0497362FB91C8C38C00A457A0BBE8D625210E4BF55FC4041FBE0A1515B70EA98C4F4284B3C96C15DD21C8CC15305DB5BFA2C21EB9520C9ACD823F5E7ABCDA3993D89A7B561C101FEC08A8AE6621245CAA1406D7536FBC6E835692D2B1BB540B8F2B2EAB7A1406B2FE83873CDEDFB0A0E717A037CD3A6322AE0B6F5E36187646866A0D406F7F54007FEC9711311BCE87FC6B4F44C5D1F7BEDD2DED081F1439F38312FA27CB65665B1595F88713378797AB624C728CA6632653EC8E762A76E3E597AAD4C3C3FE41648AEB07FCB8BFE9C70A1818E4F1B19124BECD320E4CDA6A9FD02B0A422114B5DE31376549C3B5FE1A896F8FCB256B814BD100FFBF5359510D8FD243DB014DBCFA3036C857A41DCBAE29ECE25012AF0B88827A1B3F3FA6E75EDF1790B0CCD794D0E733315743EF50FA18E5E1A93DC5D1EB28F555C0A8541B729954EA1865C6FDBE810D153CB50C024E8E7A59D324C22B626A30F4AAA0FA46EDCA4CC42F4B2D033B147DA54A67D103633A88EBFFF0EFFB61AA98DD2B057700FAC0986A9FB27C2CC29EE30B699DE063C76A1E2863D13951C35C5ABD357555781D2A5E68B0BFACF2E11747006E0810DD0CF97D585318A3B0DF7A67465EC3761004AA9B7C141B4E5444D9EB649BBD94F983FCFAEC982D994C7A620DE2D8AEE012BFD22AA9322F3DD3BD5CE90C17660D18F8CB679B02BDABC0D4D0F876B0DD6D258E08DC50B35544A4BDBE5F75604493D5FDF98B7FB812475C7B7122DDEC512322E1855C31105397AF284B7C2B4DC315D2E8D5017BBD2400885D5EB6C321B5093EF98A14EB4C29DC2B7DF9565D9E23A2BE6A2E334CE3485A8677E463DD86F49E3B56D2974F7D930FFDD60BA54AB49AE9DCDC588A4FC7AFCDB89A7713C51FA97BFA8868EE207C3C0032FDB302E45DFA0DFD8A2DE4D50A959A424626CC92CE74F8A2627C3B20406D714BB64825FBAE1B44A2F7569E32A8CBB41DBA3D9115691B07C3951A2D1394BF06BB0690B710D438CCC4E5B92B0CF302109A60C836E3AB40E4D3579C2E1C77F432C62925A751D92A564440A563B3C373D9A46FFCB0EB478962450C11192FDE187718F9AEDFF61DFE39AE98714B1DD49C356593F23F2BADE0E753B25BDCB3D618E3CDC5C5D8F37974A449E6E2D21B46FA90435F399AFF98988DEA9048B8031E1AE2E4B2B7C3FBB7CA775B6058500DB8852FF7358251CBF12A3CA233719760D251939A29778D7B4BDE15B5244B8AB47555C18925222331443DD6B227282A101443F14851734796FF4E323B66ED8304E594973EDBCA57B9413BB83574673623CB9BA282F92FBE49BFC7D6D18644C1741DAFEE86B58A174AA1B576F2599CAA8F15C9AC513CCC3778EAB81D6EF90557E73E207E96BC2D83BD3FED3717B0E8E527AE27BD05B28962280099AD1AF8C8D0B0E668EDC73AB3BD7E21C9C9134BFBC837BBC8E68FE8DF48365491371D378CB768A24A956F0D625D47EDBBAB051E4B4EE5D59574A4F2C4371D491ED182CD945DDAF11EB17382A58F2AFB6B79DE3EA1636C67449340F77A1CF14DFEDCB42B18BFFB866DD007B9A606C7BAEA70F9C5EAC98CBB52ECE5932F2925ACEAAE412E6114090CB54145A751E430EF1CA3A418C4D76EA7D797FF882401FD21984F4FBC347C4BFBB5B2B946B65F4FE0C7B9E5E16CBC1B6612325A0C83A8740D5D885C443EB8D02289BFC72E3BD2925E599B863F117C8A32E81F4B6F2C0C5D8CEA6E75C03E564E3F8D1663B5F3D21D844B6F80FB982484809303019670115FF5CC5FF6681E1C9B9AB01EA719AECAB7A4C4F1044017449741C726A4D1D97D0FB0D390F37DE0F838038270AEDD5E058113252D4F8E91B1377FD24F528EEDF58AE575327BE17F4A9D68E24B39DDF1187C8ABCEB1A84AB6BAB0735F3756E512641E62D3B51DF0316D065949379DD06C07606A82126A129A2A70F91EF54096CFCBC3447B49D5DD5F7DC7AA9F3E86E8ECD581F51731DF726194CD3143CC1E608AE882EA8848CDFD9F3FF6282AC6D722C2D5F51F2652724FEB601E02E1F078E32B36892ED9E2DE0A637836A005B01CEFDADF90534049565E8B965224B3E7EFF5707F3DEB6BFDB8D8045549168CD1C81910E584978A555DE877CFBDCB8D7388D3081F9DD8067198562521FEE99C57E3401#) + (p #00E6BBCBEBFCA813CED7907F5FA73C4C2D3532AF7A7650C4A88563DF805D54D0CEA528347A60F703C8FFE91997505F8C238383E03C53DFD347D0E385A5CFFE4E2A944DD45ACBC481D54D7B22F4C59A2BFC8C686E527B907AD9C5ECE870D102550D8D4A02B404DAE7023CC8F0436DE5F50A7CE1F4E741147F676B5DC9437CB47727B93155AE5C1EBE236E9F436D723FF770104305A1460C21BE9361582CB107CAF036F0600BCC6D78DE73C1F44C25F377B9A65349E9B73C446E5C6281DCB68EC65AF684AB39F6C84CF96E4CD909B61FA2D8BBB69A7994B78865FFEACD3838F851C944039C2422B75AE4F9C2A1702B005641EB41CE9FB042757E86F6E9651428EBA4D908D60A99AD61E5D09E7A05C7E59A9615DE965200CFB75A228B1D5DB8D2C040A65D940D5516C9FC5069B94D2F1903EF6B07F70ECF3E8D720F74139A4647D79131835CF7F15EA839350A00BD9D733359503497BCE39A2497CACCAD41B0AE7A36E6F01FECA1B0B062F9C3232BD6F6734C97DB2EE7DE050370087210F8161B07237E712E29E0BA6B2B661EC22DAD0509D50EF75255D40B954D2B3694C30E5982EB2D15B72A8709BC4F9B6FEFC4E6F01FF04D128311209B4C4353AF43BDE58D631DB7E047D7B469CDE4A9176415F6F7B60BC129E0BA8363D77140DA0FC685DB76FCB968C8C58657DB86FC908E7D11F41D907CA367C17AD3EF81280721FD40E6AEDC118538AFE109B8FA818502982578BB2EAE3ACC3028EF79C4CAB575CC8473E05FF5D911186058BCA7F5269FAA66CBB68CE47EE0748F2A8E52EEB8475030D34E54C365572BA282226730ADA3BEF16D582A409F15AB89188F1737F7CA82EE0D96BD2B3A2153CDF6EE27FD04F4AEF4AA3FC6EB02E92EC21359864507EAD3E09D3117EEDD61AF34265412C362EE01B26B925BC74A2679A1C112C653AE88FD124220742A05DDCB1CDE7DF2342669FDF76E1C3F9BF8FE13633ADF33050FA491FA708A918ECA787FF074E90F9A0AA216ACB1160D22BE7A9817DEF5FA2E27FC906ACF5B5774A5DB069A66F5F1752D7521E1CE49F8888218BA24C97A92C287DAB8B08B4433EC1DDEB5C7A3D96956EBCC46A2DE2B95CACA91BECBCB15DCA20D13C977F50F6DC0D705DB78B597581F850E20E0EEB6EA9A7A9D2708A650A3CD0748EE1DDAEA559C80D2A00F2DBD29C3EF58C13CB0B84AFA30C508BC8AD71A4FC3E14690F16B52943013D7BB09F5627D7D1343DAED88198D5ADA23E0B94484E06A827FE49227540110ECEC9E354F87E27496B7FF5ED31521817C8B5B182129EE0C521C85A996BF5EAF1F87583BDFE69386EDCE63337252F58D37AEC742702D97F3B97CE0FD06EE60EE4380C2E48D7AAD49E26F76CE981237ADB617B0BB6D59DAE31B6335866E7F9670F8A25D9BC44D7C32602BA3D58002BD53473E3F781249AB17C1C78C496611#) + (q #00ED6FA36442A240865581B5C398C93F55AFD5386A801AF1D8BF8A9FF8AB9C578F97DA02AFC44180AB581A1E10A4D65B7D1E9C0B04D57FB1FD13B7ECF1AD7C0296F1F5D52C3223CB117E6C6BED1FDA701A7A4079FBD35B180D2295B216FEAB284F85594EDDDC179C9AAE6E6CA545D2FBCA308B0961B21A1B4A4E9DE27CF8D6922FC902C35313B05F0FFB5CC667E64E0706D5210D3919074B384CA5968359CBA5F4BCA096323AD48E2CDE9D25F08E2EF945A1DD46457F48B4BF8EBEC2DC3737CC09E333E30F17A3ACD19567A5C5D200E7A4303A97A893F0884ED3CD976B41C2BCEEF04D9FCE4F30218CC9AAE26FFC5749B10011B805ADA9C4857B691A7A820F2564DF5979F570F8D524DDE268F702891E9CCDBD9F821C2ECF27F60C795E743AC67CADB07D22D3A7BD322DA9C3E7A35AC6A35333F871FE6DE0162BA2A1F9565E411ADD424FF0727B2280BAFDDF522C272D3A2910EFE27F5590F8E0F6C38BEA1895A0893755F44BDF41FECF3BF3BA27C6D6F036A1AA70736DE71465FA78EA46F34341E05DE7AB37A5074B4E99E0BAB54D658629503E1242ACAFDE08721058F208D3F62FAE742D158CAE521994514CF0BEC580F075046319FBFC8E971F0FF5EED9E2AB7D194CD21ECCCB2E54D239AA3B0254F4AB1641E6E8E1512FF1D1ED579205F1807898828CFA24B80D230FA6C52C6A92348E1A069C239F7B6F2E7CC995BD3CD1B413FC86C626FE962C7EC3CF19FA193B3A732AF17E51E6B57CC263DE82A5C45CB9E37C2BAB44E88E5792FBBC40748F86134D221BF775E2BF57F98A884FCBA494718661A3FF73AAE04A6F5CDFB6F143D680D09BA4CCD6C6F186E92569B8F67A35B5796B9F2ED404F11C54ED290D7D7836501473F06D8A623D53AB586B644F3F5BDF8B0B670CA696A23B7B52319C91D2CA27FCDF421030CEA8A6B079FEC2E467BE0427AFCEA12648F3E12F09745166D20D3D1CD6965EABA2732469C077B3C4E44D3503D882937DA5139076144FAEAB75083BF4E16725BB9625A99DE92F6F226DE343F73E974577F8D6F5B57CFBEB60763627240A28C90A73BC7A9E47D74CBABB6486988C983A5A3DC91A4D8E353AE6C608499D21391E32D8EF3A030925959B52C1BC03F17AAE2FEE4E28B2B51889EC2A5FE587C60139C9CF29AF46555B089B54B5EF0BB3B92BCC0EA0E6E94F944FE8E9741DDA902F185E0D16876A10351AD22FE6ABD4378AD74A13CD2BD9696F0B59A069CD6582F92458A89B15648E833614598D6FDABAC026791CDB3FA87873CA86E3DF7187C9230AFFB1089EF83B8CB54856ADC234D07DF479514A8F47EC9903930E47F9E93AE1F96D7358F4208E19CCED8AEC063AFE8A31E39C921F7D7867D57E8F68B1494793E6DCD06F3DC68809BD455DBB44076D6AB64586E0A09A42CEBA2829A5F81BDEA5EDB23DC251D69C373D2E275201#) + (u #00EA2CBBEFBFFBD4BD3850584AEA315F88ED892F7398E5C4ECD17F8E4588B073DA32AC708DADC0E55417553FB4DC25130F42A9A04E435C63E1091744232D53FF98ABA450E3B91AF512631E28BF453BE4FCB9713112F890F368523FE175B0909385F0B404B3E6370FA6DB33490DC216CE3DE548FDDF68C81FE49BB9683C30FA6D1DE8B019A94683E508B720F2EDA20133325FD4644620D086182F1E8283215D2BCBBC1B302DEA714CE1E59FE8E996489018078F8CCDDAEF086EFDF82BA45DF424E539ABC9D61ABEC14346275AA9256031514AAC59FF40C7D1B4363AC7C74E8CC3854C9E57F6913C2CFC599E9DBB446D553482C9B531563A7CADD562D64151B3961FB52A0D542406D491F8090EBB737C388016F95918313C0EC987F701F2A25AE3F0CEF2B9F3460A9E48AEE382F01CB09B0A9372104FAC2EE692BB2B14E6FE376A29891687E157C40F09FB3283402E4D319C9791E7A06025C542B4411EEA71890D22E34E8038B3002AC7FB75A50ED29AAEAFF36588950A06A8D2139B0420673DCB37087E8196A034D0A5C78A824BCD0A74BBD7E08B04B8F08F473C09F6350508CEB476DEE1E41D0CF960CA3E87AE8489811577F7D49CB1EF885453F7087B8126FB99028B5771EC9E159040109102DEE175DAFA038EE7B62B96797E56E6361C37DFC42398020114765E28C3F3B4B6A4C33A86A995A0D5647068B7147552F4E6130866527D4833949E9F9204406F096735F33BFD1BB57734E15D0B4035A37CCA7C897C18162B12951A684F586F1B7FF041A85B7F44FAC125A80AC782AD3F4D7EC52C318EEA52CFA6AF09EBA50813B5BAC8367B1FF80A99DB8BDEC3E3842455A06D22DA99F0BE5B52330D1D5C0CCACB3661D703BE1D96E7832A159C8858E08CC23101FBC0DE783D3209A80A3ED4EBCF57661B01D84EBCFBE70A0EC921588B8CD9B9BF21918D86C3C97B0F6BBF4037E80C99A349A1A2B78F337CC4029415FF0DB54AC9A3A1DF7E07482DC9F04E638C9D5BBAAD32A627F2EF1DC3E17AEC365E416C703C449AA40104DEC358202F7F78CCF77115ADAD567CDAE6B4B2C81DA4FBE6A97BBF2A704389911E4A5B39C3C1F187101E53B3DF7A0CE05C4B7956F4ED31DD225B46036C5344B3CDB236E5B1A12E159008D106D1CF6C14C5F7335A4A5D80E008F0106F636EF750723B50511F37B3BA6FFBEB27A270828B9CB123D7F59EA0BE956C0D024C77AC06086460998F18610ECB94651DF47AB37DDDCDB9797203A4321CBC1E6E85EC64919EB74AC7E2F3C15FEB5DFCCFC2359D353C8B6B600152D4211A55477FF31026B34C10C5F1FC1A1DD1C1EF6A14B26CFD1AF70D6BAA4461B4387631E4DCFDFFAB118F710A8B8B2D12EEC4924751720B9AA9D94527B9F19E8B352222567F662FC6753AA4BE22C2A851F2378AD5EE5539C1E0F4DD90400DD7DC6F1EA675D9#) + ) + ) + ) diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c new file mode 100644 index 0000000..208a127 --- /dev/null +++ b/tests/t-mpi-bit.c @@ -0,0 +1,354 @@ +/* t-mpi-bit.c - Tests for bit level functions + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +#define PGM "t-mpi-bit" + +static const char *wherestr; +static int verbose; +static int error_count; + +#define xmalloc(a) gcry_xmalloc ((a)) +#define xcalloc(a,b) gcry_xcalloc ((a),(b)) +#define xfree(a) gcry_free ((a)) +#define pass() do { ; } while (0) + +static void +show (const char *format, ...) +{ + va_list arg_ptr; + + if (!verbose) + return; + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + if (wherestr) + fprintf (stderr, "%s: ", wherestr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + if (wherestr) + fprintf (stderr, "%s: ", wherestr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +/* Allocate a bit string consisting of '0' and '1' from the MPI + A. Return the LENGTH least significant bits. Caller needs to xfree + the result. */ +static char * +mpi2bitstr (gcry_mpi_t a, size_t length) +{ + char *p, *buf; + + buf = p = xmalloc (length+1); + while (length--) + *p++ = gcry_mpi_test_bit (a, length) ? '1':'0'; + *p = 0; + + return buf; +} + +/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do + not return any leading zero bits. Caller needs to xfree the + result. */ +static char * +mpi2bitstr_nlz (gcry_mpi_t a) +{ + char *p, *buf; + size_t length = gcry_mpi_get_nbits (a); + + buf = p = xmalloc (length + 1); + while (length-- > 1) + *p++ = gcry_mpi_test_bit (a, length) ? '1':'0'; + *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0'; + *p = 0; + + return buf; +} + +/* Shift a bit string to the right. */ +static void +rshiftbitstring (char *string, size_t n) +{ + size_t len = strlen (string); + + if (n > len) + n = len; + + memmove (string+n, string, len-n); + memset (string, '0', n); +} + +/* Shift a bit string to the left. Caller needs to free the result. */ +static char * +lshiftbitstring (const char *string, size_t n) +{ + size_t len = strlen (string); + char *result; + + if (len+n+1 < len) + die ("internal overflow\n"); + /* Allocate enough space. */ + result = xmalloc (len+n+1); + for (; *string == '0' && string[1]; string++, len--) + ; + memcpy (result, string, len); + if (*string == '0' && !string[1]) + n = 0; /* Avoid extra nulls for an only 0 string. */ + else + memset (result+len, '0', n); + result[len+n] = 0; + return result; +} + + +/* This is to check a bug reported by bpgcrypt at itaparica.org on + 2006-07-31 against libgcrypt 1.2.2. */ +static void +one_bit_only (int highbit) +{ + gcry_mpi_t a; + char *result; + int i; + + wherestr = "one_bit_only"; + show ("checking that set_%sbit does only set one bit\n", highbit?"high":""); + + a = gcry_mpi_new (0); + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + gcry_mpi_set_ui (a, 0); + + if (highbit) + gcry_mpi_set_highbit (a, 42); + else + gcry_mpi_set_bit (a, 42); + if (!gcry_mpi_test_bit (a, 42)) + fail ("failed to set a bit\n"); + gcry_mpi_clear_bit (a, 42); + if (gcry_mpi_test_bit (a, 42)) + fail ("failed to clear a bit\n"); + result = mpi2bitstr (a, 70); + assert (strlen (result) == 70); + for (i=0; result[i]; i++) + if ( result[i] != '0' ) + break; + if (result[i]) + fail ("spurious bits detected\n"); + xfree (result); + gcry_mpi_release (a); +} + +/* Check that the shifting actually works for an amount larger than + the number of bits per limb. */ +static void +test_rshift (int pass) +{ + gcry_mpi_t a, b; + char *result, *result2; + int i; + + wherestr = "test_rshift"; + show ("checking that rshift works as expected (pass %d)\n", pass); + + a = gcry_mpi_new (0); + b = gcry_mpi_new (0); + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + + for (i=0; i < 75; i++) + { + gcry_mpi_rshift (b, a, i); + + result = mpi2bitstr (b, 72); + result2 = mpi2bitstr (a, 72); + rshiftbitstring (result2, i); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("rshift by %d failed\n", i); + } + xfree (result); + xfree (result2); + } + + /* Again. This time using in-place operation. */ + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + + for (i=0; i < 75; i++) + { + gcry_mpi_release (b); + b = gcry_mpi_copy (a); + gcry_mpi_rshift (b, b, i); + + result = mpi2bitstr (b, 72); + result2 = mpi2bitstr (a, 72); + rshiftbitstring (result2, i); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("in-place rshift by %d failed\n", i); + } + xfree (result2); + xfree (result); + } + + gcry_mpi_release (b); + gcry_mpi_release (a); +} + +/* Check that the left shifting. */ +static void +test_lshift (int pass) +{ + static int size_list[] = {1, 31, 32, 63, 64, 65, 70, 0}; + int size_idx; + gcry_mpi_t a, b; + char *tmpstr, *result, *result2; + int i; + + wherestr = "test_lshift"; + show ("checking that lshift works as expected (pass %d)\n", pass); + + for (size_idx=0; size_list[size_idx]; size_idx++) + { + a = gcry_mpi_new (0); + b = gcry_mpi_new (0); + + /* gcry_mpi_randomize rounds up to full bytes, thus we need to + use gcry_mpi_clear_highbit to fix that. */ + gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); + gcry_mpi_clear_highbit (a, size_list[size_idx]); + + for (i=0; i < 75; i++) + { + gcry_mpi_lshift (b, a, i); + + result = mpi2bitstr_nlz (b); + tmpstr = mpi2bitstr_nlz (a); + result2 = lshiftbitstring (tmpstr, i); + xfree (tmpstr); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("lshift by %d failed\n", i); + } + xfree (result); + xfree (result2); + } + + /* Again. This time using in-place operation. */ + gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); + gcry_mpi_clear_highbit (a, size_list[size_idx]); + + for (i=0; i < 75; i++) + { + gcry_mpi_release (b); + b = gcry_mpi_copy (a); + gcry_mpi_lshift (b, b, i); + + result = mpi2bitstr_nlz (b); + tmpstr = mpi2bitstr_nlz (a); + result2 = lshiftbitstring (tmpstr, i); + xfree (tmpstr); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("in-place lshift by %d failed\n", i); + } + xfree (result2); + xfree (result); + } + + gcry_mpi_release (b); + gcry_mpi_release (a); + } +} + + +int +main (int argc, char **argv) +{ + int debug = 0; + int i; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + one_bit_only (0); + one_bit_only (1); + for (i=0; i < 5; i++) + test_rshift (i); /* Run several times due to random initializations. */ + + for (i=0; i < 5; i++) + test_lshift (i); /* Run several times due to random initializations. */ + + show ("All tests completed. Errors: %d\n", error_count); + return error_count ? 1 : 0; +} diff --git a/tests/testapi.c b/tests/testapi.c new file mode 100644 index 0000000..e14ae7b --- /dev/null +++ b/tests/testapi.c @@ -0,0 +1,112 @@ +/* testapi.c - for libgcrypt + * Copyright (C) 2000, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include + + +#define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\ + exit(2);} while(0) + +/* an ElGamal public key */ +struct { + const char *p,*g,*y; +} elg_testkey1 = { + "0x9D559F31A6D30492C383213844AEBB7772963A85D3239F3611AAB93A2A985F64FB735B9259EC326BF5720F909980D609D37C288C9223B0350FBE493C3B5AF54CA23031E952E92F8A3DBEDBC5A684993D452CD54F85B85160166FCD25BD7AB6AE9B1EB4FCC9D300DAFF081C4CBA6694906D3E3FF18196A5CCF7F0A6182962166B", + "0x5", + "0x9640024BB2A277205813FF685048AA27E2B192B667163E7C59E381E27003D044C700C531CE8FD4AA781B463BC9FFE74956AF09A38A098322B1CF72FC896F009E3A6BFF053D3B1D1E1994BF9CC07FA12963D782F027B51511DDE8C5F43421FBC12734A9C070F158C729A370BEE5FC51A772219438EDA8202C35FA3F5D8CD1997B" +}; + +void +test_sexp ( int argc, char **argv ) +{ + int rc, nbits; + gcry_sexp_t sexp; + gcry_mpi_t key[3]; + size_t n; + char *buf; + + if ( gcry_mpi_scan( &key[0], GCRYMPI_FMT_HEX, elg_testkey1.p, NULL ) ) + BUG(); + if ( gcry_mpi_scan( &key[1], GCRYMPI_FMT_HEX, elg_testkey1.g, NULL ) ) + BUG(); + if ( gcry_mpi_scan( &key[2], GCRYMPI_FMT_HEX, elg_testkey1.y, NULL ) ) + BUG(); + + /* get nbits from a key */ + rc = gcry_sexp_build ( &sexp, NULL, + "(public-key(elg(p%m)(g%m)(y%m)))", + key[0], key[1], key[2] ); + fputs ( "DUMP of PK:\n", stderr ); + gcry_sexp_dump ( sexp ); + { gcry_sexp_t x; + x = gcry_sexp_cdr ( sexp ); + fputs ( "DUMP of CDR:\n", stderr ); + gcry_sexp_dump ( x ); + gcry_sexp_release ( x ); + } + nbits = gcry_pk_get_nbits( sexp ); + printf ( "elg_testkey1 - nbits=%d\n", nbits ); + n = gcry_sexp_sprint ( sexp, 0, NULL, 0 ); + buf = gcry_xmalloc ( n ); + n = gcry_sexp_sprint ( sexp, 0, buf, n ); + printf ( "sprint length=%u\n", (unsigned int)n ); + gcry_free ( buf ); + gcry_sexp_release( sexp ); +} + + +void +test_genkey ( int argc, char **argv ) +{ + int rc, nbits = 1024; + gcry_sexp_t s_parms, s_key; + + gcry_control( GCRYCTL_INIT_SECMEM, 16384, 0 ); + rc = gcry_sexp_build ( &s_parms, NULL, "(genkey(dsa(nbits %d)))", nbits ); + rc = gcry_pk_genkey( &s_key, s_parms ); + if ( rc ) { + fprintf ( stderr, "genkey failed: %s\n", gpg_strerror (rc) ); + return; + } + gcry_sexp_release( s_parms ); + gcry_sexp_dump ( s_key ); + gcry_sexp_release( s_key ); +} + +int +main( int argc, char **argv ) +{ + if ( argc < 2 ) + printf("%s\n", gcry_check_version ( NULL ) ); + else if ( !strcmp ( argv[1], "version") ) + printf("%s\n", gcry_check_version ( argc > 2 ? argv[2] : NULL ) ); + else if ( !strcmp ( argv[1], "sexp" ) ) + test_sexp ( argc-2, argv+2 ); + else if ( !strcmp ( argv[1], "genkey" ) ) + test_genkey ( argc-2, argv+2 ); + else { + fprintf (stderr, "usage: testapi mode-string [mode-args]\n"); + return 1; + } + + return 0; +} diff --git a/tests/tsexp.c b/tests/tsexp.c new file mode 100644 index 0000000..21d54a6 --- /dev/null +++ b/tests/tsexp.c @@ -0,0 +1,456 @@ +/* tsexp.c - S-expression regression tests + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include "../src/gcrypt.h" + +#define PGMNAME "tsexp" + +static int verbose; +static int error_count; + +static void +info (const char *format, ...) +{ + va_list arg_ptr; + + if (verbose) + { + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + } +} + +static void +fail ( const char *format, ... ) +{ + va_list arg_ptr ; + + fputs (PGMNAME ": ", stderr); + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + error_count++; +} + + +/* fixme: we need better tests */ +static void +basic (void) +{ + int pass; + gcry_sexp_t sexp; + int idx; + char *secure_buffer; + size_t secure_buffer_len; + const char *string; + static struct { + const char *token; + const char *parm; + } values[] = { + { "public-key", NULL }, + { "dsa", NULL }, + { "dsa", "p" }, + { "dsa", "y" }, + { "dsa", "q" }, + { "dsa", "g" }, + { NULL } + }; + + info ("doing some pretty pointless tests\n"); + + secure_buffer_len = 99; + secure_buffer = gcry_xmalloc_secure (secure_buffer_len); + memset (secure_buffer, 'G', secure_buffer_len); + + for (pass=0;;pass++) + { + switch (pass) + { + case 0: + string = ("(public-key (dsa (p #41424344#) (y this_is_y) " + "(q #61626364656667#) (g %m)))"); + + if ( gcry_sexp_build (&sexp, NULL, string, + gcry_mpi_set_ui (NULL, 42)) ) + { + fail (" scanning `%s' failed\n", string); + return; + } + break; + + case 1: + string = ("(public-key (dsa (p #41424344#) (y this_is_y) " + "(q %b) (g %m)))"); + + if ( gcry_sexp_build (&sexp, NULL, string, + 15, "foo\0\x01\0x02789012345", + gcry_mpi_set_ui (NULL, 42)) ) + { + fail (" scanning `%s' failed\n", string); + return; + } + break; + + case 2: + string = ("(public-key (dsa (p #41424344#) (y silly_y_value) " + "(q %b) (g %m)))"); + + if ( gcry_sexp_build (&sexp, NULL, string, + secure_buffer_len, secure_buffer, + gcry_mpi_set_ui (NULL, 17)) ) + { + fail (" scanning `%s' failed\n", string); + return; + } + if (!gcry_is_secure (sexp)) + fail ("gcry_sexp_build did not switch to secure memory\n"); + break; + + case 3: + { + gcry_sexp_t help_sexp; + + if (gcry_sexp_new (&help_sexp, + "(foobar-parms (xp #1234#)(xq #03#))", 0, 1)) + { + fail (" scanning fixed string failed\n"); + return; + } + + string = ("(public-key (dsa (p #41424344#) (parm %S) " + "(y dummy)(q %b) (g %m)))"); + if ( gcry_sexp_build (&sexp, NULL, string, help_sexp, + secure_buffer_len, secure_buffer, + gcry_mpi_set_ui (NULL, 17)) ) + { + fail (" scanning `%s' failed\n", string); + return; + } + gcry_sexp_release (help_sexp); + } + break; + + + default: + return; /* Ready. */ + } + + + /* now find something */ + for (idx=0; values[idx].token; idx++) + { + const char *token = values[idx].token; + const char *parm = values[idx].parm; + gcry_sexp_t s1, s2; + gcry_mpi_t a; + const char *p; + size_t n; + + s1 = gcry_sexp_find_token (sexp, token, strlen(token) ); + if (!s1) + { + fail ("didn't found `%s'\n", token); + continue; + } + + p = gcry_sexp_nth_data (s1, 0, &n); + if (!p) + { + fail ("no car for `%s'\n", token); + continue; + } + info ("car=`%.*s'\n", (int)n, p); + + s2 = gcry_sexp_cdr (s1); + if (!s2) + { + fail ("no cdr for `%s'\n", token); + continue; + } + + p = gcry_sexp_nth_data (s2, 0, &n); + if (p) + { + fail ("data at car of `%s'\n", token); + continue; + } + + if (parm) + { + s2 = gcry_sexp_find_token (s1, parm, strlen (parm)); + if (!s2) + { + fail ("didn't found `%s'\n", parm); + continue; + } + p = gcry_sexp_nth_data (s2, 0, &n); + if (!p) + { + fail("no car for `%s'\n", parm ); + continue; + } + info ("car=`%.*s'\n", (int)n, p); + p = gcry_sexp_nth_data (s2, 1, &n); + if (!p) + { + fail("no cdr for `%s'\n", parm ); + continue; + } + info ("cdr=`%.*s'\n", (int)n, p); + + a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG); + if (!a) + { + fail("failed to cdr the mpi for `%s'\n", parm); + continue; + } + } + } + + gcry_sexp_release (sexp); + sexp = NULL; + } + gcry_free (secure_buffer); +} + + +static void +canon_len (void) +{ + static struct { + size_t textlen; /* length of the buffer */ + size_t expected;/* expected length or 0 on error and then ... */ + size_t erroff; /* ... and at this offset */ + gcry_error_t errcode; /* ... with this error code */ + const char *text; + } values[] = { + { 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " }, + { 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" }, + { 14, 0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" }, + { 15, 0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" }, + { 2, 0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"}, + { 4, 0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"}, + { 5, 5, 0, GPG_ERR_NO_ERROR, "(1:x)"}, + { 2, 2, 0, GPG_ERR_NO_ERROR, "()"}, + { 4, 2, 0, GPG_ERR_NO_ERROR, "()()"}, + { 4, 4, 0, GPG_ERR_NO_ERROR, "(())"}, + { 3, 0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"}, + { 3, 0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"}, + { 9, 9, 0, GPG_ERR_NO_ERROR, "(3:abc())"}, + { 10, 0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"}, + /* fixme: we need much more cases */ + { 0 }, + }; + int idx; + gcry_error_t errcode; + size_t n, erroff; + + info ("checking canoncial length test function\n"); + for (idx=0; values[idx].text; idx++) + { + n = gcry_sexp_canon_len ((const unsigned char*)values[idx].text, + values[idx].textlen, + &erroff, &errcode); + + if (n && n == values[idx].expected) + ; /* success */ + else if (!n && !values[idx].expected) + { /* we expected an error - check that this is the right one */ + if (values[idx].erroff != erroff) + fail ("canonical length test %d - wrong error offset %u\n", + idx, (unsigned int)erroff); + if (gcry_err_code (errcode) != values[idx].errcode) + fail ("canonical length test %d - wrong error code %d\n", + idx, errcode); + } + else + fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n", + idx, (unsigned int)n, (unsigned int)erroff, errcode); + } +} + + +static void +back_and_forth_one (int testno, const char *buffer, size_t length) +{ + gcry_error_t rc; + gcry_sexp_t se, se1; + size_t n, n1; + char *p1; + + rc = gcry_sexp_new (&se, buffer, length, 1); + if (rc) + { + fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc)); + return; + } + n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0); + if (!n1) + { + fail ("baf %d: get required length for canon failed\n", testno); + return; + } + p1 = gcry_xmalloc (n1); + n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1); + if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */ + { + fail ("baf %d: length mismatch for canon\n", testno); + return; + } + rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free); + if (rc) + { + fail ("baf %d: gcry_sexp_create failed: %s\n", + testno, gpg_strerror (rc)); + return; + } + gcry_sexp_release (se1); + + /* Again but with memory checking. */ + p1 = gcry_xmalloc (n1+2); + *p1 = '\x55'; + p1[n1+1] = '\xaa'; + n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1); + if (n1 != n+1) /* sprints adds an extra 0 but does not return it */ + { + fail ("baf %d: length mismatch for canon\n", testno); + return; + } + if (*p1 != '\x55' || p1[n1+1] != '\xaa') + fail ("baf %d: memory corrupted (1)\n", testno); + rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL); + if (rc) + { + fail ("baf %d: gcry_sexp_create failed: %s\n", + testno, gpg_strerror (rc)); + return; + } + if (*p1 != '\x55' || p1[n1+1] != '\xaa') + fail ("baf %d: memory corrupted (2)\n", testno); + gcry_sexp_release (se1); + if (*p1 != '\x55' || p1[n1+1] != '\xaa') + fail ("baf %d: memory corrupted (3)\n", testno); + gcry_free (p1); + + /* FIXME: we need a lot more tests */ + + gcry_sexp_release (se); +} + + + +static void +back_and_forth (void) +{ + static struct { const char *buf; int len; } tests[] = { + { "(7:g34:fgh1::2:())", 0 }, + { "(7:g34:fgh1::2:())", 18 }, + { +"(protected-private-key \n" +" (rsa \n" +" (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n" +" (e #010001#)\n" +" (protected openpgp-s2k3-sha1-aes-cbc \n" +" (\n" +" (sha1 #C2A5673BD3882405# \"96\")\n" +" #8D08AAF6A9209ED69D71EB7E64D78715#)\n" +" #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n" +" )\n" +" )\n", 0 }, + { NULL, 0 } + }; + int idx; + + for (idx=0; tests[idx].buf; idx++) + back_and_forth_one (idx, tests[idx].buf, tests[idx].len); +} + + +static void +check_sscan (void) +{ + static struct { + const char *text; + gcry_error_t expected_err; + } values[] = { + /* Bug reported by Olivier L'Heureux 2003-10-07 */ + { "(7:sig-val(3:dsa" + "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" + "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" + "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" + "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))", + GPG_ERR_NO_ERROR }, + { "(7:sig-val(3:dsa" + "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" + "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" + "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" + "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))", + GPG_ERR_SEXP_UNMATCHED_PAREN }, + { "(7:sig-val(3:dsa" + "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" + "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" + "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" + "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))", + GPG_ERR_SEXP_UNMATCHED_PAREN }, + { NULL, 0 } + }; + int idx; + gcry_error_t err; + gcry_sexp_t s; + + info ("checking gcry_sexp_sscan\n"); + for (idx=0; values[idx].text; idx++) + { + err = gcry_sexp_sscan (&s, NULL, + values[idx].text, + strlen (values[idx].text)); + if (gpg_err_code (err) != values[idx].expected_err) + fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err)); + gcry_sexp_release (s); + } +} + + + + +int +main (int argc, char **argv) +{ + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + basic (); + canon_len (); + back_and_forth (); + check_sscan (); + + return error_count? 1:0; +} diff --git a/tests/version.c b/tests/version.c new file mode 100644 index 0000000..03259af --- /dev/null +++ b/tests/version.c @@ -0,0 +1,58 @@ +/* version.c - This version test should be run first. + Copyright (C) 2007 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* This test should be run first because due to a failing config.links + script or bad configure parameters the just build libgcrypt may + crash in case MPI function for specific CPU revisions have been + enabled. Running this test first will print out information so to + make it easier to figure out the problem. */ + + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +#define PGM "version" + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + { + fprintf (stderr, PGM ": version mismatch\n"); + exit (1); + } + + gcry_control (GCRYCTL_PRINT_CONFIG, NULL); + + return 0; +} + -- 2.7.4