├── AUTHORS ├── NEWS ├── ChangeLog ├── doc └── Makefile.am ├── m4 ├── Makefile.am ├── ltversion.m4 ├── autobuild.m4 ├── ltsugar.m4 ├── gpg-error.m4 ├── libgcrypt.m4 ├── lt~obsolete.m4 └── ltoptions.m4 ├── TODO ├── autogen.rc ├── tests ├── key.script ├── runtests.bash ├── Makefile.am └── tgpgtest.c ├── README ├── .gitignore ├── tools ├── Makefile.am └── tgpg-keystore.c ├── src ├── s2k.h ├── protect.h ├── keystore.h ├── Makefile.am ├── pktparser.h ├── pkcs1.h ├── strerror.c ├── pkcs1.c ├── keystore.c ├── s2k.c ├── pktwriter.h ├── util.c ├── cryptglue.h ├── tgpgdefs.h ├── encrypt.c ├── tgpg.c ├── tgpg.h ├── decrypt.c ├── pktwriter.c ├── cryptglue.c └── protect.c ├── Makefile.am ├── README.SVN ├── configure.ac ├── autogen.sh └── INSTALL /AUTHORS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | EXTRA_DISTS = 3 | -------------------------------------------------------------------------------- /m4/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | EXTRA_DISTS = autobuild.m4 libgcrypt.m4 gpg-error.m4 3 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | * KeyID 3 | We might want to have a dedicated 32 bit type for it instead of 4 | unsigned long. 5 | * Proper cross-building 6 | Build tools/* for the host. 7 | -------------------------------------------------------------------------------- /autogen.rc: -------------------------------------------------------------------------------- 1 | # autogen.sh configuration for TGPG -*- sh -*- 2 | 3 | extra_aclocal_flags="" 4 | 5 | final_info="./configure --enable-maintainer-mode && make" 6 | -------------------------------------------------------------------------------- /tests/key.script: -------------------------------------------------------------------------------- 1 | %echo Generating a basic OpenPGP key 2 | Key-Type: RSA 3 | Key-Length: 1024 4 | Subkey-Type: RSA 5 | Subkey-Length: 1024 6 | Name-Real: Joe Tester 7 | Name-Email: joe@example.org 8 | Expire-Date: 7 9 | %no-protection 10 | %transient-key 11 | #%pubring test.pub 12 | #%secring test.sec 13 | # Do a commit here, so that we can later print "done" :-) 14 | %commit 15 | %echo done 16 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Tiny GNU Privacy Guard 2 | ========================== 3 | Version 0.0.0 4 | 5 | 6 | This is an OpenPGP implementation targeted to small devices and comes 7 | with a couple of restrictions. It does not feature a key management 8 | but relies on gpg to provide a useful set of keys. A syncronisation 9 | mechanism to achieve this is implemented. The API is similar to 10 | GPGME. 11 | 12 | 13 | 14 | Requirements: 15 | 16 | sizeof (char) == 8 17 | sizeof (int) >= 16 18 | sizeof (long) >= 32 19 | flat and linear address space 20 | C-89 toolchain 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.lo 2 | *.o 3 | .deps/ 4 | .libs/ 5 | /aclocal.m4 6 | /autom4te.cache 7 | /config.h.in 8 | /config.h 9 | /config.log 10 | /config.status 11 | /configure 12 | /libtool 13 | /stamp-h1 14 | /Makefile.in 15 | tools/Makefile.in 16 | doc/Makefile.in 17 | m4/Makefile.in 18 | src/Makefile.in 19 | tests/Makefile.in 20 | /Makefile 21 | m4/Makefile 22 | tools/Makefile 23 | doc/tgpg.info 24 | doc/stamp-vti 25 | doc/version.texi 26 | doc/Makefile 27 | src/Makefile 28 | src/libtgpg-config 29 | src/libtgpg.la 30 | tests/Makefile 31 | tests/gpghome 32 | tests/keystore.c 33 | tests/test* 34 | tests/tgpgtest 35 | tools/tgpg-keystore 36 | 37 | obj 38 | GPATH 39 | GRTAGS 40 | GSYMS 41 | GTAGS 42 | -------------------------------------------------------------------------------- /m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 3337 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.2]) 16 | m4_define([LT_PACKAGE_REVISION], [1.3337]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.2' 20 | macro_revision='1.3337' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /tests/runtests.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | TGPG="./tgpgtest" 6 | GPG2="gpg2 --homedir gpghome --quiet --decrypt" 7 | 8 | tests=0 9 | failed=0 10 | 11 | function ok() 12 | { 13 | let tests=$tests+1 14 | } 15 | 16 | function fail() 17 | { 18 | let tests=$tests+1 19 | let failed=$failed+1 20 | } 21 | 22 | while [ "$1" ] 23 | do 24 | chksum="$(sha1sum < $1)" 25 | test "$chksum" = "$(${TGPG} $1.gpg | sha1sum)" && ok || fail 26 | test "$chksum" = "$(${TGPG} --mandatory-mdc $1.gpg | sha1sum)" && fail || ok 27 | test "$chksum" = "$(${TGPG} --mandatory-mdc $1.gpg.mdc | sha1sum)" && ok || fail 28 | test "$chksum" = "$(${TGPG} $1.tgpg | sha1sum)" && ok || fail 29 | test "$chksum" = "$(${TGPG} --mandatory-mdc $1.tgpg.mdc | sha1sum)" && ok || fail 30 | test "$chksum" = "$(${GPG2} $1.tgpg | sha1sum)" && ok || fail 31 | test "$chksum" = "$(${GPG2} $1.tgpg.mdc | sha1sum)" && ok || fail 32 | shift 33 | done 34 | 35 | echo "$tests executed, $failed failed." 36 | 37 | exit $failed 38 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am - for tgpg/tools 2 | # Copyright (C) 2015 g10 Code GmbH 3 | # 4 | # This file is part of TGPG. 5 | # 6 | # TGPG is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # TGPG is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | 21 | ## Process this file with automake to produce Makefile.in 22 | 23 | AM_CFLAGS = $(LIBGCRYPT_CFLAGS) 24 | 25 | bin_PROGRAMS = tgpg-keystore 26 | 27 | tgpg_keystore_SOURCES = tgpg-keystore.c 28 | tgpg_keystore_CFLAGS = $(LIBGCRYPT_CFLAGS) 29 | tgpg_keystore_LDADD = $(LIBGCRYPT_LIBS) 30 | -------------------------------------------------------------------------------- /src/s2k.h: -------------------------------------------------------------------------------- 1 | /* s2k.h - Internal interface to the string to key functions. 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef S2K_H 22 | #define S2K_H 23 | 24 | int _tgpg_s2k_hash (const char *passphrase, int algo, 25 | int mode, const unsigned char *salt, unsigned long count, 26 | unsigned char *key, size_t keylen); 27 | 28 | #endif /*S2K_H*/ 29 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am - Top level makefile. 2 | # Copyright (C) 2007 g10 Code GmbH 3 | # 4 | # This file is part of TGPG. 5 | # 6 | # TGPG is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # TGPG is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | 21 | ## Process this file with automake to produce Makefile.in 22 | 23 | ACLOCAL_AMFLAGS = -I m4 24 | AUTOMAKE_OPTIONS = dist-bzip2 25 | 26 | EXTRA_DIST = autogen.sh README.SVN 27 | 28 | SUBDIRS = m4 tools src doc tests 29 | 30 | dist-hook: 31 | echo "$(VERSION)" > $(distdir)/VERSION 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/protect.h: -------------------------------------------------------------------------------- 1 | /* protect.h - Internal interface to the protec functions. 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef PROTECT_H 22 | #define PROTECT_H 23 | 24 | int _tgpg_is_protected (const unsigned char *seckey); 25 | 26 | int _tgpg_unprotect (const unsigned char *protectedkey, const char *passphrase, 27 | unsigned char **result, size_t *resultlen); 28 | 29 | 30 | #endif /*PROTECT_H*/ 31 | -------------------------------------------------------------------------------- /src/keystore.h: -------------------------------------------------------------------------------- 1 | /* keystore.h - Internal interface to the key storage. 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef KEYSTORE_H 22 | #define KEYSTORE_H 23 | 24 | #include "tgpg.h" 25 | #include "tgpgdefs.h" 26 | 27 | /* XXX: Rename this. */ 28 | const struct tgpg_key_s *seckey_table; 29 | 30 | int _tgpg_have_secret_key (keyinfo_t ki); 31 | int _tgpg_get_secret_key (keyinfo_t ki, tgpg_mpi_t *r_seckey); 32 | void _tgpg_free_secret_key (tgpg_mpi_t seckey); 33 | 34 | 35 | #endif /*KEYSTORE_H*/ 36 | -------------------------------------------------------------------------------- /m4/autobuild.m4: -------------------------------------------------------------------------------- 1 | # autobuild.m4 serial 2 (autobuild-3.3) 2 | # Copyright (C) 2004 Simon Josefsson 3 | # 4 | # This file is free software, distributed under the terms of the GNU 5 | # General Public License. As a special exception to the GNU General 6 | # Public License, this file may be distributed as part of a program 7 | # that contains a configuration script generated by Autoconf, under 8 | # the same distribution terms as the rest of that program. 9 | # 10 | # This file can can be used in projects which are not available under 11 | # the GNU General Public License or the GNU Library General Public 12 | # License but which still want to provide support for Autobuild. 13 | 14 | # Usage: AB_INIT([MODE]). 15 | AC_DEFUN([AB_INIT], 16 | [ 17 | AC_REQUIRE([AC_CANONICAL_BUILD]) 18 | AC_REQUIRE([AC_CANONICAL_HOST]) 19 | 20 | AC_MSG_NOTICE([autobuild project... ${PACKAGE_NAME:-$PACKAGE}]) 21 | AC_MSG_NOTICE([autobuild revision... ${PACKAGE_VERSION:-$VERSION}]) 22 | hostname=`hostname` 23 | if test "$hostname"; then 24 | AC_MSG_NOTICE([autobuild hostname... $hostname]) 25 | fi 26 | ifelse([$1],[],,[AC_MSG_NOTICE([autobuild mode... $1])]) 27 | date=`date +%Y%m%d-%H%M%S` 28 | if test "$?" != 0; then 29 | date=`date` 30 | fi 31 | if test "$date"; then 32 | AC_MSG_NOTICE([autobuild timestamp... $date]) 33 | fi 34 | ]) 35 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am - for tgpg/src 2 | # Copyright (C) 2007 g10 Code GmbH 3 | # 4 | # This file is part of TGPG. 5 | # 6 | # TGPG is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # TGPG is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | 21 | ## Process this file with automake to produce Makefile.in 22 | 23 | AM_CFLAGS = $(LIBGCRYPT_CFLAGS) 24 | 25 | include_HEADERS = tgpg.h 26 | 27 | lib_LTLIBRARIES = libtgpg.la 28 | 29 | libtgpg_la_SOURCES = \ 30 | tgpg.c tgpg.h tgpgdefs.h \ 31 | cryptglue.c cryptglue.h \ 32 | keystore.c keystore.h \ 33 | pktparser.c pktparser.h \ 34 | pktwriter.c pktwriter.h \ 35 | pkcs1.c pkcs1.h \ 36 | protect.c protect.h \ 37 | s2k.c s2k.h \ 38 | util.c \ 39 | strerror.c \ 40 | decrypt.c \ 41 | encrypt.c 42 | -------------------------------------------------------------------------------- /src/pktparser.h: -------------------------------------------------------------------------------- 1 | /* pktparser.h - Internal interface to the packet parser 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef PKTPARSER_H 22 | #define PKTPARSER_H 23 | 24 | int _tgpg_identify_message (bufdesc_t msg, tgpg_msg_type_t *r_type); 25 | 26 | int _tgpg_parse_encrypted_message (bufdesc_t msg, int *r_mdc, 27 | size_t *r_start, size_t *r_length, 28 | keyinfo_t r_keyinfo, tgpg_mpi_t r_encdat); 29 | 30 | int _tgpg_parse_plaintext_message (bufdesc_t msg, 31 | int mdc, 32 | const char *prefix, 33 | size_t prefixlen, 34 | unsigned char *r_format, 35 | char *r_filename, 36 | time_t *r_date, 37 | size_t *r_start, 38 | size_t *r_length); 39 | #endif /*PKTPARSER_H*/ 40 | -------------------------------------------------------------------------------- /src/pkcs1.h: -------------------------------------------------------------------------------- 1 | /* pkcs1.h - PKCS#1 EME-PKCS1-v1_5 encoding and decoding. 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef PKCS1_H 22 | #define PKCS1_H 23 | 24 | /* Encode a message as specified in OpenPGPs version of the PKCS#1 25 | functions EME-PKCS1-v1_5 described in RFC4880. As data is merely 26 | appended in this encoding, this function is not concerned with the 27 | body itself. The to-be-prepended data is written to EM which must 28 | be at least 11 bytes long. */ 29 | int 30 | _tgpg_eme_pkcs1_encode (char *em, size_t emlen); 31 | 32 | /* Decode the message EM of length EMLEN as specified in OpenPGPs 33 | version of the PKCS#1 functions EME-PKCS1-v1_5 described in 34 | RFC4880. A pointer to the embedded body of the message is returned 35 | in R_M, the length of the body is returned in R_MLEN. */ 36 | int 37 | _tgpg_eme_pkcs1_decode (const char *em, size_t emlen, 38 | const char **r_m, size_t *r_mlen); 39 | 40 | #endif /*PKCS1_H*/ 41 | -------------------------------------------------------------------------------- /README.SVN: -------------------------------------------------------------------------------- 1 | If you are building from Subversion, run the script 2 | 3 | ./autogen.sh 4 | 5 | first, to make sure that you have all the necessary maintainer tools 6 | are installed and to build the actual configuration files. If you 7 | have just updated from SVN, you should add the option "--force" to 8 | autogen.sh so that meta data from SVN is noticed. Then run 9 | 10 | ./configure --enable-maintainer-mode 11 | 12 | followed by the usual make. 13 | 14 | If autogen.sh complains about insufficient versions of the required 15 | tools, or the tools are not installed, you may use environment 16 | variables to override the default tool names: 17 | 18 | AUTOMAKE_SUFFIX is used as a suffix for all tools from the automake 19 | package. For example 20 | AUTOMAKE_SUFFIX="-1.7" ./autogen.sh 21 | uses "automake-1.7" and "aclocal-1.7. 22 | AUTOMAKE_PREFIX is used as a prefix for all tools from the automake 23 | page and may be combined with AUTOMAKE_SUFFIX. e.g.: 24 | AUTOMAKE_PREFIX=/usr/foo/bin ./autogen.sh 25 | uses "automake" and "aclocal" in the /usr/foo/bin 26 | directory. 27 | AUTOCONF_SUFFIX is used as a suffix for all tools from the automake 28 | package 29 | AUTOCONF_PREFIX is used as a prefix for all tools from the automake 30 | package 31 | GETTEXT_SUFFIX is used as a suffix for all tools from the gettext 32 | package 33 | GETTEXT_PREFIX is used as a prefix for all tools from the gettext 34 | package 35 | 36 | It is also possible to use the variable name AUTOMAKE, AUTOCONF, 37 | ACLOCAL, AUTOHEADER, GETTEXT and MSGMERGE to directly specify the name 38 | of the programs to run. It is however better to use the suffix and 39 | prefix forms as described above because that does not require 40 | knowledge about the actual tools used by autgen.sh. 41 | 42 | 43 | Please don't use autopoint, libtoolize or autoreconf unless you are 44 | the current maintainer and want to update the standard configuration 45 | files. All those files should be in the SVN and only updated manually 46 | if the maintainer decides that newer versions are required. The 47 | maintainer should also make sure that the required version of automake 48 | et al. are properly indicated at the top of configure.ac and take care 49 | to copy the files and not merely use symlinks. 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/strerror.c: -------------------------------------------------------------------------------- 1 | /* strerror.c - Error strings 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "tgpgdefs.h" 28 | 29 | /* Return a pointer to a string containing a description of the error 30 | code in the error value ERR. This function may not be thread-safe. */ 31 | const char * 32 | tgpg_strerror (int err) 33 | { 34 | switch (err) 35 | { 36 | case TGPG_SYSERROR: return strerror (errno); 37 | case TGPG_NO_ERROR: return "No error"; 38 | case TGPG_NO_DATA: return "No data for processing available"; 39 | case TGPG_INV_VAL: return "Invalid value"; 40 | case TGPG_INV_PKT: return "Invalid OpenPGP packet detected"; 41 | case TGPG_INV_MSG: return "Invalid OpenPGP message"; 42 | case TGPG_INV_MPI: return "An MPI value in a packet is malformed"; 43 | case TGPG_INV_DATA: return "Invalid data"; 44 | case TGPG_INV_ALGO: return "Algorithm is invalid or not supported"; 45 | case TGPG_INV_PASS: return "Invalid passphrase"; 46 | case TGPG_UNEXP_PKT: return "Unexpected packet"; 47 | case TGPG_UNEXP_DATA:return "Unexpected data"; 48 | case TGPG_NO_PUBKEY: return "No public key found"; 49 | case TGPG_NO_SECKEY: return "No secret key found"; 50 | case TGPG_CRYPT_ERR: return "Crypto error"; 51 | case TGPG_WRONG_KEY: return "Wrong key"; 52 | case TGPG_MDC_FAILED:return "Integrity check failed"; 53 | case TGPG_NOT_IMPL: return "Not implemented by TGPG"; 54 | case TGPG_BUG: return "Internal error in TGPG"; 55 | default: return "Unknown TGPG error code"; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am - for tgpg/src 2 | # Copyright (C) 2015 g10 Code GmbH 3 | # 4 | # This file is part of TGPG. 5 | # 6 | # TGPG is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # TGPG is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | 21 | ## Process this file with automake to produce Makefile.in 22 | 23 | AM_CFLAGS = $(LIBGCRYPT_CFLAGS) 24 | 25 | noinst_PROGRAMS = tgpgtest 26 | 27 | # The test driver. 28 | tgpgtest_SOURCES = tgpgtest.c keystore.c 29 | tgpgtest_CFLAGS = -I$(top_srcdir)/src 30 | tgpgtest_LDADD = $(LIBGCRYPT_LIBS) -L../src -ltgpg 31 | 32 | # Key generation 33 | GPG ?= gpg2 34 | TGPG ?= ./tgpgtest$(EXEEXT) 35 | GPGHOME ?= gpghome 36 | GPGFLAGS ?= 37 | GPGFLAGSH = --homedir "$(GPGHOME)" $(GPGFLAGS) 38 | GPGX = $(GPG) $(GPGFLAGSH) --with-colons --with-keygrip -k 39 | 40 | EXTRA_DIST = key.script runtests.bash 41 | 42 | gpghome: key.script 43 | mkdir "$@" 44 | chmod 700 "$@" 45 | $(GPG) --homedir "$@" $(GPGFLAGS) --gen-key --batch '$<' 46 | 47 | keystore.c: $(GPGHOME) ../tools/tgpg-keystore$(EXEEXT) 48 | ../tools/tgpg-keystore$(EXEEXT) \ 49 | `$(GPGX) | grep '^sub' | cut -d: -f5` \ 50 | "$<"/private-keys-v1.d/`$(GPGX) | grep '^grp' | tail -n 1 | cut -d: -f10`.key >"$@" 51 | 52 | %.gpg: % 53 | rm -f -- "$@" 54 | $(GPG) $(GPGFLAGSH) --recipient `$(GPGX) | grep '^sub' | cut -d: -f5` --disable-mdc -z0 --batch --encrypt --output="$@" "$<" 55 | 56 | %.gpg.mdc: % 57 | rm -f -- "$@" 58 | $(GPG) $(GPGFLAGSH) --recipient `$(GPGX) | grep '^sub' | cut -d: -f5` --force-mdc -z0 --batch --encrypt --output="$@" "$<" 59 | 60 | %.tgpg: % $(TGPG) 61 | rm -f -- "$@" 62 | $(TGPG) --debug --encrypt --disable-mdc "$<" >"$@" || ( rm "$@" ; exit 1 ) 63 | 64 | %.tgpg.mdc: % $(TGPG) 65 | rm -f -- "$@" 66 | $(TGPG) --debug --encrypt "$<" >"$@" || ( rm "$@" ; exit 1 ) 67 | 68 | TESTFILES = test0 test1 69 | TESTFILES_GPG = $(foreach TEST,$(TESTFILES),$(TEST).gpg $(TEST).gpg.mdc $(TEST).tgpg $(TEST).tgpg.mdc) 70 | 71 | test0: 72 | python -c "import sys; sys.stdout.write(64*'A')" >"$@" 73 | 74 | test1: 75 | dd if=/dev/urandom of="$@" bs=64 count=1 76 | 77 | 78 | check: tgpgtest $(TESTFILES_GPG) 79 | $(top_srcdir)/tests/runtests.bash $(TESTFILES) 80 | 81 | CLEANFILES = keystore.c $(TESTFILES) $(TESTFILES_GPG) 82 | clean-local: 83 | rm -rf -- gpghome 84 | -------------------------------------------------------------------------------- /src/pkcs1.c: -------------------------------------------------------------------------------- 1 | /* pkcs1.c - PKCS#1 EME-PKCS1-v1_5 encoding and decoding. 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "tgpgdefs.h" 31 | #include "cryptglue.h" 32 | #include "pktwriter.h" 33 | 34 | /* Encode a message as specified in OpenPGPs version of the PKCS#1 35 | functions EME-PKCS1-v1_5 described in RFC4880. As data is merely 36 | appended in this encoding, this function is not concerned with the 37 | body itself. The to-be-prepended data is written to EM which must 38 | be at least 10 bytes long. */ 39 | int 40 | _tgpg_eme_pkcs1_encode (char *em, size_t emlen) 41 | { 42 | size_t i, padding; 43 | 44 | if (emlen < 10) 45 | return TGPG_BUG; /* EM is too short. */ 46 | 47 | padding = emlen - 2; 48 | /* Note: The leading zero octet is lost in MPI encoding. */ 49 | *em++ = 2; 50 | 51 | /* Generate a padding of non-zero octets. */ 52 | _tgpg_randomize ((unsigned char *) em, padding); 53 | for (i = 0; i < padding; i++) 54 | while (em[i] == 0) 55 | _tgpg_randomize ((unsigned char *) &em[i], 1); 56 | 57 | em[padding] = 0; 58 | 59 | return 0; 60 | } 61 | 62 | /* Decode the message EM of length EMLEN as specified in OpenPGPs 63 | version of the PKCS#1 functions EME-PKCS1-v1_5 described in 64 | RFC4880. A pointer to the embedded body of the message is returned 65 | in R_M, the length of the body is returned in R_MLEN. */ 66 | int 67 | _tgpg_eme_pkcs1_decode (const char *em, size_t emlen, 68 | const char **r_m, size_t *r_mlen) 69 | { 70 | size_t n; 71 | 72 | /* Note: The leading zero octet is lost in MPI encoding. */ 73 | if (emlen < 10 || em[0] != 2) 74 | return TGPG_WRONG_KEY; /* Too short or not a type 2 block. */ 75 | 76 | /* Skip random part. */ 77 | for (n = 2; 1 < emlen && em[n]; n++) 78 | { /* skip */ } 79 | if (n < 9) 80 | return TGPG_WRONG_KEY; /* Not enough random bytes. */ 81 | 82 | n++; /* Skip the terminating 0. */ 83 | 84 | *r_m = &em[n]; 85 | *r_mlen = emlen - n; 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/keystore.c: -------------------------------------------------------------------------------- 1 | /* keystore.c - Key storage 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "tgpgdefs.h" 28 | #include "keystore.h" 29 | 30 | const struct tgpg_key_s *seckey_table = { { /* sentinel */ 0 } }; 31 | 32 | /* Return success (0) if we have the secret key matching the public 33 | key identified by KI. */ 34 | int 35 | _tgpg_have_secret_key (keyinfo_t ki) 36 | { 37 | int idx; 38 | 39 | fprintf (stderr, "DBG: Looking for keyid %04lx%04lx (algo %d)\n", 40 | ki->keyid[1], ki->keyid[0], ki->pubkey_algo); 41 | 42 | for (idx = 0; seckey_table[idx].algo; idx++) 43 | if (seckey_table[idx].algo == ki->pubkey_algo 44 | && seckey_table[idx].keyid_low == ki->keyid[0] 45 | && seckey_table[idx].keyid_high == ki->keyid[1]) 46 | return 0; 47 | 48 | 49 | return TGPG_NO_SECKEY; 50 | } 51 | 52 | 53 | /* Return the secret key matching KI at R_SECKEY. The caller needs to 54 | release the secret key later using _tgpg_free_secret_key. */ 55 | int 56 | _tgpg_get_secret_key (keyinfo_t ki, tgpg_mpi_t *r_seckey) 57 | { 58 | int idx, i; 59 | tgpg_mpi_t mpis; 60 | 61 | fprintf (stderr, "DBG: get-secret_key for keyid %04lx%04lx (algo %d)\n", 62 | ki->keyid[1], ki->keyid[0], ki->pubkey_algo); 63 | 64 | for (idx = 0; seckey_table[idx].algo; idx++) 65 | if (seckey_table[idx].algo == ki->pubkey_algo 66 | && seckey_table[idx].keyid_low == ki->keyid[0] 67 | && seckey_table[idx].keyid_high == ki->keyid[1]) 68 | break; 69 | if (!seckey_table[idx].algo) 70 | return TGPG_NO_SECKEY; 71 | 72 | if (seckey_table[idx].algo == PK_ALGO_RSA) 73 | { 74 | mpis = xtrycalloc (6+1, sizeof *mpis); 75 | if (!mpis) 76 | return TGPG_SYSERROR; 77 | for (i=0; i < 6; i++) 78 | { 79 | mpis[i].nbits = seckey_table[idx].mpis[i].nbits; 80 | mpis[i].valuelen = seckey_table[idx].mpis[i].valuelen; 81 | mpis[i].value = seckey_table[idx].mpis[i].value; 82 | } 83 | *r_seckey = mpis; 84 | } 85 | else 86 | return TGPG_INV_ALGO; 87 | 88 | return 0; 89 | } 90 | 91 | 92 | 93 | void 94 | _tgpg_free_secret_key (tgpg_mpi_t seckey) 95 | { 96 | xfree (seckey); 97 | } 98 | -------------------------------------------------------------------------------- /src/s2k.c: -------------------------------------------------------------------------------- 1 | /* s2k.c - String to key functions 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "tgpgdefs.h" 28 | #include "cryptglue.h" 29 | #include "s2k.h" 30 | 31 | 32 | 33 | /* Transform the string PASSPHRASE into a suitable key of length 34 | KEYLEN and stores it at the caller provided buffer KEY. Required 35 | arguments are an OpenPGP hash ALGO, a valid MODE and depending on 36 | that mode a SALT of 8 random bytes and a COUNT. See RFC-2440 for 37 | details. Returns 0 on success. */ 38 | int 39 | _tgpg_s2k_hash (const char *passphrase, int algo, 40 | int mode, const unsigned char *salt, unsigned long count, 41 | unsigned char *key, size_t keylen) 42 | { 43 | int rc; 44 | hash_t md; 45 | int pass, i; 46 | int used = 0; 47 | int pwlen = strlen (passphrase); 48 | 49 | if ( !passphrase 50 | || !algo 51 | || (mode != 0 && mode != 1 && mode != 3) 52 | || ((mode == 1 || mode == 3) && !salt) 53 | || !key || !keylen ) 54 | return TGPG_INV_VAL; 55 | 56 | rc = _tgpg_hash_open (&md, algo, HASH_FLAG_SECURE); 57 | if (rc) 58 | return rc; 59 | 60 | for (pass=0; used < keylen; pass++) 61 | { 62 | if (pass) 63 | { 64 | _tgpg_hash_reset (md); 65 | for (i=0; i < pass; i++) 66 | hash_putc (md, 0); 67 | } 68 | 69 | if (mode == 1 || mode == 3) 70 | { 71 | int len2 = pwlen + 8; 72 | unsigned long nbytes = len2; 73 | 74 | if (mode == 3) 75 | { 76 | nbytes = (16ul + (count & 15)) << ((count >> 4) + 6); 77 | if (nbytes < len2) 78 | nbytes = len2; 79 | } 80 | 81 | while (nbytes > len2) 82 | { 83 | hash_putbuf (md, salt, 8); 84 | hash_putbuf (md, passphrase, pwlen); 85 | nbytes -= len2; 86 | } 87 | if (nbytes < 8) 88 | hash_putbuf (md, salt, nbytes); 89 | else 90 | { 91 | hash_putbuf (md, salt, 8); 92 | nbytes -= 8; 93 | hash_putbuf (md, passphrase, nbytes); 94 | } 95 | } 96 | else 97 | hash_putbuf (md, passphrase, pwlen); 98 | 99 | i = hash_digestlen (md); 100 | if (i > keylen - used) 101 | i = keylen - used; 102 | memcpy (key+used, _tgpg_hash_read (md), i); 103 | used += i; 104 | } 105 | _tgpg_hash_close (md); 106 | return 0; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/pktwriter.h: -------------------------------------------------------------------------------- 1 | /* pktwriter.h - OpenPGP packet writing functions. 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef PKTWRITER_H 22 | #define PKTWRITER_H 23 | 24 | #include "tgpgdefs.h" 25 | 26 | /* Write the 8 bit unsigned value V as an OpenPGP value to *P, and 27 | advance *P accordingly. */ 28 | static inline void 29 | write_u8 (unsigned char **p, unsigned char v) 30 | { 31 | *(*p)++ = v; 32 | } 33 | 34 | /* Write the 16 bit unsigned value V as an OpenPGP value to *P, and 35 | advance *P accordingly. */ 36 | static inline void 37 | write_u16 (unsigned char **p, uint16_t v) 38 | { 39 | *(*p)++ = (v >> 8) & 0xff; 40 | *(*p)++ = (v >> 0) & 0xff; 41 | } 42 | 43 | /* Write the 32 bit unsigned value V as an OpenPGP value to *P, and 44 | advance *P accordingly. */ 45 | static inline void 46 | write_u32 (unsigned char **p, uint32_t v) 47 | { 48 | *(*p)++ = (v >> 24) & 0xff; 49 | *(*p)++ = (v >> 16) & 0xff; 50 | *(*p)++ = (v >> 8) & 0xff; 51 | *(*p)++ = (v >> 0) & 0xff; 52 | } 53 | 54 | /* Write the MPI value V as an OpenPGP value to *P, and advance *P 55 | accordingly. */ 56 | static inline void 57 | write_mpi (unsigned char **p, tgpg_mpi_t mpi) 58 | { 59 | write_u16 (p, mpi->nbits); 60 | memcpy (*p, mpi->value, mpi->valuelen); 61 | *p += mpi->valuelen; 62 | } 63 | 64 | /* Write an OpenPGP public key encrypted packet to *P, and advance *P 65 | accordingly. Return the size of the packet. If P is NULL, no data 66 | is actually written. */ 67 | size_t 68 | _tgpg_write_pubkey_enc_packet (unsigned char **p, 69 | keyinfo_t ki, 70 | tgpg_mpi_t encdat, size_t enclen); 71 | 72 | /* Write an OpenPGP symmetrically encrypted packet to *P, and advance 73 | *P accordingly. If MDC is non-zero, write an integrity protected 74 | packet of the given version. As the body is merely appended to 75 | this header, this function is not concerned with the body itself. 76 | Return the size of the packet. If P is NULL, no data is actually 77 | written. */ 78 | size_t 79 | _tgpg_write_sym_enc_packet (unsigned char **p, int mdc, size_t length); 80 | 81 | /* Construct a plaintext message in MSG, with the given FORMAT, 82 | FILENAME (which must not be larger than 0xff bytes), DATE, and 83 | containing the literal data PAYLOAD of given LENGTH. If MDC is 84 | non-zero, create a Modification Detection Code Packet of the given 85 | version. In that case, PREFIX of length PREFIXLEN must be the 86 | block cipher initialization data. */ 87 | int 88 | _tgpg_encode_plaintext_message (bufdesc_t msg, 89 | int mdc, 90 | const char *prefix, 91 | size_t prefixlen, 92 | unsigned char format, 93 | const char *filename, 94 | time_t date, 95 | const char *payload, 96 | size_t length); 97 | #endif /*PKTWRITER_H*/ 98 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /* util.c - Utility functions 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "tgpgdefs.h" 28 | 29 | 30 | /* Return the length of the canonical encoded S-expression in BUFFER 31 | of LENGTH. LENGTH may be 0 if it is assured that the S-expression 32 | is valid. Returns 0 on error. */ 33 | size_t 34 | _tgpg_canonsexp_len (const unsigned char *sexp, size_t length) 35 | { 36 | const unsigned char *p = sexp; 37 | size_t count = 0; 38 | int level = 0; 39 | const unsigned char *disphint = NULL; 40 | unsigned int datalen = 0; 41 | 42 | if (!p || *p != '(') 43 | return 0; /* Not a canonical S-expression. */ 44 | 45 | for ( ; ; p++, count++ ) 46 | { 47 | if (length && count >= length) 48 | break; /* Expression longer than buffer. */ 49 | 50 | if (datalen) 51 | { 52 | if (*p == ':') 53 | { 54 | if (length && (count+datalen) >= length) 55 | break; 56 | count += datalen; 57 | p += datalen; 58 | datalen = 0; 59 | } 60 | else if (*p >= '0' && *p <= '9') 61 | datalen = 10 * datalen + (*p - '0'); 62 | else 63 | break; /* Bad length specification. */ 64 | } 65 | else if (*p == '(') 66 | { 67 | if (disphint) 68 | break; /* Not closed. */ 69 | level++; 70 | } 71 | else if (*p == ')') 72 | { 73 | if (!level) 74 | break; /* No opening parenthesis. */ 75 | if (disphint) 76 | break; /* Not closed. */ 77 | if (!--level) 78 | { 79 | return ++count; /* End of expression - return count. */ 80 | } 81 | } 82 | else if (*p == '[') 83 | { 84 | if (disphint) 85 | break; /* Nested display hints are not allowed. */ 86 | disphint = p; 87 | } 88 | else if (*p == ']') 89 | { 90 | if ( !disphint ) 91 | break; /* Not in a display hint. */ 92 | disphint = NULL; 93 | } 94 | else if ( *p >= '1' && *p <= '9' ) 95 | { 96 | /* Note that leading zeroes are not allowed. */ 97 | datalen = (*p - '0'); 98 | } 99 | else 100 | break; /* Unexpected characters */ 101 | } 102 | 103 | return 0; /* Error. */ 104 | } 105 | 106 | 107 | /* Compute the sum modulo 2**16 over DATA of LENGTH storing the result 108 | in R_CSUM. */ 109 | void 110 | _tgpg_checksum (const char *data, size_t length, 111 | unsigned short *r_csum) 112 | { 113 | size_t n; 114 | unsigned short sum = 0; 115 | 116 | for (n = 0; n < length; n++) 117 | sum = (sum + ((const unsigned char *) data)[n]) & 0xffff; 118 | 119 | *r_csum = sum; 120 | } 121 | -------------------------------------------------------------------------------- /m4/ltsugar.m4: -------------------------------------------------------------------------------- 1 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. 4 | # Written by Gary V. Vaughan, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 6 ltsugar.m4 11 | 12 | # This is to help aclocal find these macros, as it can't see m4_define. 13 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) 14 | 15 | 16 | # lt_join(SEP, ARG1, [ARG2...]) 17 | # ----------------------------- 18 | # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their 19 | # associated separator. 20 | # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier 21 | # versions in m4sugar had bugs. 22 | m4_define([lt_join], 23 | [m4_if([$#], [1], [], 24 | [$#], [2], [[$2]], 25 | [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) 26 | m4_define([_lt_join], 27 | [m4_if([$#$2], [2], [], 28 | [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) 29 | 30 | 31 | # lt_car(LIST) 32 | # lt_cdr(LIST) 33 | # ------------ 34 | # Manipulate m4 lists. 35 | # These macros are necessary as long as will still need to support 36 | # Autoconf-2.59 which quotes differently. 37 | m4_define([lt_car], [[$1]]) 38 | m4_define([lt_cdr], 39 | [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], 40 | [$#], 1, [], 41 | [m4_dquote(m4_shift($@))])]) 42 | m4_define([lt_unquote], $1) 43 | 44 | 45 | # lt_append(MACRO-NAME, STRING, [SEPARATOR]) 46 | # ------------------------------------------ 47 | # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. 48 | # Note that neither SEPARATOR nor STRING are expanded; they are appended 49 | # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). 50 | # No SEPARATOR is output if MACRO-NAME was previously undefined (different 51 | # than defined and empty). 52 | # 53 | # This macro is needed until we can rely on Autoconf 2.62, since earlier 54 | # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. 55 | m4_define([lt_append], 56 | [m4_define([$1], 57 | m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) 58 | 59 | 60 | 61 | # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) 62 | # ---------------------------------------------------------- 63 | # Produce a SEP delimited list of all paired combinations of elements of 64 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list 65 | # has the form PREFIXmINFIXSUFFIXn. 66 | # Needed until we can rely on m4_combine added in Autoconf 2.62. 67 | m4_define([lt_combine], 68 | [m4_if(m4_eval([$# > 3]), [1], 69 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl 70 | [[m4_foreach([_Lt_prefix], [$2], 71 | [m4_foreach([_Lt_suffix], 72 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, 73 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) 74 | 75 | 76 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) 77 | # ----------------------------------------------------------------------- 78 | # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited 79 | # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. 80 | m4_define([lt_if_append_uniq], 81 | [m4_ifdef([$1], 82 | [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], 83 | [lt_append([$1], [$2], [$3])$4], 84 | [$5])], 85 | [lt_append([$1], [$2], [$3])$4])]) 86 | 87 | 88 | # lt_dict_add(DICT, KEY, VALUE) 89 | # ----------------------------- 90 | m4_define([lt_dict_add], 91 | [m4_define([$1($2)], [$3])]) 92 | 93 | 94 | # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) 95 | # -------------------------------------------- 96 | m4_define([lt_dict_add_subkey], 97 | [m4_define([$1($2:$3)], [$4])]) 98 | 99 | 100 | # lt_dict_fetch(DICT, KEY, [SUBKEY]) 101 | # ---------------------------------- 102 | m4_define([lt_dict_fetch], 103 | [m4_ifval([$3], 104 | m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), 105 | m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) 106 | 107 | 108 | # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) 109 | # ----------------------------------------------------------------- 110 | m4_define([lt_if_dict_fetch], 111 | [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], 112 | [$5], 113 | [$6])]) 114 | 115 | 116 | # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) 117 | # -------------------------------------------------------------- 118 | m4_define([lt_dict_filter], 119 | [m4_if([$5], [], [], 120 | [lt_join(m4_quote(m4_default([$4], [[, ]])), 121 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), 122 | [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl 123 | ]) 124 | -------------------------------------------------------------------------------- /m4/gpg-error.m4: -------------------------------------------------------------------------------- 1 | # gpg-error.m4 - autoconf macro to detect libgpg-error. 2 | # Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH 3 | # 4 | # This file is free software; as a special exception the author gives 5 | # unlimited permission to copy and/or distribute it, with or without 6 | # modifications, as long as this notice is preserved. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # 12 | # Last-changed: 2014-10-02 13 | 14 | 15 | dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, 16 | dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) 17 | dnl 18 | dnl Test for libgpg-error and define GPG_ERROR_CFLAGS, GPG_ERROR_LIBS, 19 | dnl GPG_ERROR_MT_CFLAGS, and GPG_ERROR_MT_LIBS. The _MT_ variants are 20 | dnl used for programs requireing real multi thread support. 21 | dnl 22 | dnl If a prefix option is not used, the config script is first 23 | dnl searched in $SYSROOT/bin and then along $PATH. If the used 24 | dnl config script does not match the host specification the script 25 | dnl is added to the gpg_config_script_warn variable. 26 | dnl 27 | AC_DEFUN([AM_PATH_GPG_ERROR], 28 | [ AC_REQUIRE([AC_CANONICAL_HOST]) 29 | gpg_error_config_prefix="" 30 | dnl --with-libgpg-error-prefix=PFX is the preferred name for this option, 31 | dnl since that is consistent with how our three siblings use the directory/ 32 | dnl package name in --with-$dir_name-prefix=PFX. 33 | AC_ARG_WITH(libgpg-error-prefix, 34 | AC_HELP_STRING([--with-libgpg-error-prefix=PFX], 35 | [prefix where GPG Error is installed (optional)]), 36 | [gpg_error_config_prefix="$withval"]) 37 | 38 | dnl Accept --with-gpg-error-prefix and make it work the same as 39 | dnl --with-libgpg-error-prefix above, for backwards compatibility, 40 | dnl but do not document this old, inconsistently-named option. 41 | AC_ARG_WITH(gpg-error-prefix,, 42 | [gpg_error_config_prefix="$withval"]) 43 | 44 | if test x"${GPG_ERROR_CONFIG}" = x ; then 45 | if test x"${gpg_error_config_prefix}" != x ; then 46 | GPG_ERROR_CONFIG="${gpg_error_config_prefix}/bin/gpg-error-config" 47 | else 48 | case "${SYSROOT}" in 49 | /*) 50 | if test -x "${SYSROOT}/bin/gpg-error-config" ; then 51 | GPG_ERROR_CONFIG="${SYSROOT}/bin/gpg-error-config" 52 | fi 53 | ;; 54 | '') 55 | ;; 56 | *) 57 | AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) 58 | ;; 59 | esac 60 | fi 61 | fi 62 | 63 | AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) 64 | min_gpg_error_version=ifelse([$1], ,0.0,$1) 65 | AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) 66 | ok=no 67 | if test "$GPG_ERROR_CONFIG" != "no" \ 68 | && test -f "$GPG_ERROR_CONFIG" ; then 69 | req_major=`echo $min_gpg_error_version | \ 70 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` 71 | req_minor=`echo $min_gpg_error_version | \ 72 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` 73 | gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` 74 | major=`echo $gpg_error_config_version | \ 75 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` 76 | minor=`echo $gpg_error_config_version | \ 77 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` 78 | if test "$major" -gt "$req_major"; then 79 | ok=yes 80 | else 81 | if test "$major" -eq "$req_major"; then 82 | if test "$minor" -ge "$req_minor"; then 83 | ok=yes 84 | fi 85 | fi 86 | fi 87 | fi 88 | if test $ok = yes; then 89 | GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` 90 | GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` 91 | GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --cflags 2>/dev/null` 92 | GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --libs 2>/dev/null` 93 | AC_MSG_RESULT([yes ($gpg_error_config_version)]) 94 | ifelse([$2], , :, [$2]) 95 | gpg_error_config_host=`$GPG_ERROR_CONFIG $gpg_error_config_args --host 2>/dev/null || echo none` 96 | if test x"$gpg_error_config_host" != xnone ; then 97 | if test x"$gpg_error_config_host" != x"$host" ; then 98 | AC_MSG_WARN([[ 99 | *** 100 | *** The config script $GPG_ERROR_CONFIG was 101 | *** built for $gpg_error_config_host and thus may not match the 102 | *** used host $host. 103 | *** You may want to use the configure option --with-gpg-error-prefix 104 | *** to specify a matching config script or use \$SYSROOT. 105 | ***]]) 106 | gpg_config_script_warn="$gpg_config_script_warn libgpg-error" 107 | fi 108 | fi 109 | else 110 | GPG_ERROR_CFLAGS="" 111 | GPG_ERROR_LIBS="" 112 | GPG_ERROR_MT_CFLAGS="" 113 | GPG_ERROR_MT_LIBS="" 114 | AC_MSG_RESULT(no) 115 | ifelse([$3], , :, [$3]) 116 | fi 117 | AC_SUBST(GPG_ERROR_CFLAGS) 118 | AC_SUBST(GPG_ERROR_LIBS) 119 | AC_SUBST(GPG_ERROR_MT_CFLAGS) 120 | AC_SUBST(GPG_ERROR_MT_LIBS) 121 | ]) 122 | -------------------------------------------------------------------------------- /src/cryptglue.h: -------------------------------------------------------------------------------- 1 | /* cryptglue.h - Internal interface to crypto layer. 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef CRYPTGLUE_H 22 | #define CRYPTGLUE_H 23 | 24 | /* P u b k e y */ 25 | 26 | /* The maximum nuber of parameters required in a public key encrypted 27 | packet. */ 28 | #define MAX_PK_NENC 2 29 | 30 | unsigned int _tgpg_pk_get_nenc (int algo); 31 | unsigned int _tgpg_pk_get_nsig (int algo); 32 | 33 | int _tgpg_pk_decrypt (int algo, tgpg_mpi_t seckey, tgpg_mpi_t encdat, 34 | char **r_plain, size_t *r_plainlen); 35 | 36 | int _tgpg_pk_encrypt (int algo, tgpg_mpi_t pubkey, 37 | char *plain, size_t plainlen, 38 | tgpg_mpi_t *r_encdat, size_t *r_enclen); 39 | 40 | 41 | /* C i p h er (symmetric) */ 42 | 43 | enum cipher_modes 44 | { 45 | CIPHER_MODE_CBC = 1, 46 | CIPHER_MODE_CFB = 2, 47 | CIPHER_MODE_CFB_PGP = 3, 48 | CIPHER_MODE_CFB_MDC = 4, 49 | }; 50 | 51 | unsigned int _tgpg_cipher_blocklen (int algo); 52 | unsigned int _tgpg_cipher_keylen (int algo); 53 | int _tgpg_cipher_decrypt (int algo, enum cipher_modes mode, 54 | const void *key, size_t keylen, 55 | const void *iv, size_t ivlen, 56 | char *prefix, size_t prefixlen, 57 | void *outbuf, size_t outbufsize, 58 | const void * inbuf, size_t inbuflen); 59 | int _tgpg_cipher_encrypt (int algo, enum cipher_modes mode, 60 | const void *key, size_t keylen, 61 | const void *iv, size_t ivlen, 62 | char *prefix, size_t prefixlen, 63 | void *outbuf, size_t outbufsize, 64 | const void *inbuf, size_t inbuflen); 65 | 66 | 67 | /* H a s h */ 68 | 69 | #define HASH_FLAG_SECURE 1 70 | 71 | /* The context used for hash functions. It needs to be poublic, so 72 | that we can do some buffer using macros. */ 73 | struct hash_context_s 74 | { 75 | void *handle; /* Internal handle. */ 76 | int secure; /* Secure mode. */ 77 | size_t digestlen; /* Length of the resulting digest. */ 78 | size_t buffersize; /* The allocated size of the buffer. */ 79 | size_t bufferpos; /* Offset to the next write position. */ 80 | unsigned char buffer[1]; /* the buffer is actually of size BUFFERSIZE. */ 81 | }; 82 | typedef struct hash_context_s *hash_t; 83 | 84 | /* Update the hash context CTX with the byte B. */ 85 | #define hash_putc(ctx,b) \ 86 | do { \ 87 | hash_t c_ = (ctx); \ 88 | if ( c_->bufferpos == c_->buffersize ) \ 89 | _tgpg_hash_write ( c_, NULL, 0 ); \ 90 | c_->buffer[c_->bufferpos++] = (b); \ 91 | } while (0) 92 | /* Update the ash context CTX with L bytes from buffer B. */ 93 | #define hash_putbuf(ctx,b,l) \ 94 | do { \ 95 | hash_t c_ = (ctx); \ 96 | const unsigned char *p_ = (const unsigned char*)(b); \ 97 | size_t l_ = (l); \ 98 | for ( ;l_; l_--, p_++) \ 99 | { \ 100 | if ( c_->bufferpos == c_->buffersize ) \ 101 | _tgpg_hash_write ( c_, NULL, 0 ); \ 102 | c_->buffer[c_->bufferpos++] = *p_; \ 103 | } \ 104 | } while (0) 105 | /* Return the length of the resulting digest of context CTX. */ 106 | #define hash_digestlen(ctx) ((ctx)->digestlen) 107 | 108 | void _tgpg_hash_buffer (int algo, unsigned char *digest, size_t digestlen, 109 | const void *buffer, size_t length); 110 | int _tgpg_hash_open (hash_t *rctx, int algo, unsigned int flags); 111 | void _tgpg_hash_close (hash_t ctx); 112 | void _tgpg_hash_reset (hash_t ctx); 113 | void _tgpg_hash_write (hash_t ctx, const void *buffer, size_t length); 114 | const void *_tgpg_hash_read (hash_t ctx); 115 | 116 | /* Random data. */ 117 | 118 | /* Fill BUFFER of given LENGTH with random data suitable for session 119 | keys. */ 120 | void _tgpg_randomize (unsigned char *buffer, size_t length); 121 | 122 | #endif /*CRYPTGLUE_H*/ 123 | -------------------------------------------------------------------------------- /src/tgpgdefs.h: -------------------------------------------------------------------------------- 1 | /* tgpgdefs.h - Internal declarations for Tiny GPG 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef TGPGDEFS_H 22 | #define TGPGDEFS_H 23 | 24 | #include 25 | 26 | #if HAVE_STDINT_H 27 | # include 28 | #endif 29 | #if defined UINT32_MAX || defined uint32_t 30 | typedef uint32_t keyid_t; 31 | #else 32 | # error "No uint32_t." 33 | #endif 34 | 35 | /* Include the public header. */ 36 | #include "tgpg.h" 37 | 38 | 39 | /* Library flags. */ 40 | extern int _tgpg_flags; 41 | 42 | 43 | /* The packet types we need to know about. */ 44 | enum packet_types 45 | { 46 | PKT_NONE = 0, 47 | PKT_PUBKEY_ENC = 1, /* Public key encrypted packet. */ 48 | PKT_SIGNATURE = 2, /* Secret key encrypted packet. */ 49 | PKT_SYMKEY_ENC = 3, /* Session key packet. */ 50 | PKT_ONEPASS_SIG = 4, /* One pass signature packet. */ 51 | PKT_SECRET_KEY = 5, /* Secret key packet. */ 52 | PKT_PUBLIC_KEY = 6, /* Public key packet. */ 53 | PKT_SECRET_SUBKEY = 7, /* Secret subkey packet. */ 54 | PKT_COMPRESSED = 8, /* Compressed data packet. */ 55 | PKT_ENCRYPTED = 9, /* Conventional encrypted data packet. */ 56 | PKT_MARKER = 10, /* Marker packet. */ 57 | PKT_PLAINTEXT = 11, /* Plaintext data with filename and mode. */ 58 | PKT_RING_TRUST = 12, /* Keyring trust packet. */ 59 | PKT_USER_ID = 13, /* User id packet. */ 60 | PKT_PUBLIC_SUBKEY = 14, /* Public subkey packet. */ 61 | PKT_ATTRIBUTE = 17, /* Attribute packet. */ 62 | PKT_ENCRYPTED_MDC = 18, /* Integrity protected encrypted data packet. */ 63 | PKT_MDC = 19 /* Manipulation detection code packet. */ 64 | }; 65 | 66 | 67 | /* Constants for OpenPGP public key algorithms. */ 68 | enum openpgp_pk_algos 69 | { 70 | PK_ALGO_RSA = 1, 71 | PK_ALGO_ELG = 16, 72 | PK_ALGO_DSA = 17 73 | }; 74 | 75 | /* Constants for OpenPGP hash algorithms. */ 76 | enum openpgp_md_algos 77 | { 78 | MD_ALGO_MD5 = 1, 79 | MD_ALGO_SHA1 = 2, 80 | MD_ALGO_RMD160 = 3, 81 | MD_ALGO_SHA256 = 8 82 | }; 83 | 84 | /* Constants for OpenPGP cipher algorithms. */ 85 | enum openpgp_cipher_algos 86 | { 87 | CIPHER_ALGO_3DES = 2, 88 | CIPHER_ALGO_CAST5 = 3, 89 | CIPHER_ALGO_AES = 7, 90 | CIPHER_ALGO_AES192 = 8, 91 | CIPHER_ALGO_AES256 = 9 92 | }; 93 | 94 | 95 | /* A buffer descriptor is used to keep track of memory buffers. */ 96 | struct tgpg_data_s 97 | { 98 | size_t length; /* Used length of the buffer or image. */ 99 | const char *image; /* The actual R/O image of the buffer. This 100 | either points to some external buffer or our 101 | own BUFFER (below). */ 102 | size_t allocated; /* Allocated size of the buffer. */ 103 | char *buffer; /* The allocated buffer. If a R/W buffer has 104 | not been allocated this may be NULL. */ 105 | }; 106 | typedef struct tgpg_data_s *bufdesc_t; 107 | 108 | 109 | /* Information pertaining to a public key. */ 110 | struct keyinfo_s 111 | { 112 | /* The key ID as defined by OpenPGP. */ 113 | uint32_t keyid[2]; 114 | /* The public key algorithm used. */ 115 | int pubkey_algo; 116 | }; 117 | typedef struct keyinfo_s *keyinfo_t; 118 | 119 | 120 | /* The context structure used with all TPGP operations. */ 121 | struct tgpg_context_s 122 | { 123 | int foo; 124 | 125 | }; 126 | 127 | 128 | 129 | 130 | /*-- tgpg.c --*/ 131 | int _tgpg_make_buffer_mutable (bufdesc_t buf); 132 | 133 | 134 | /*-- util.c --*/ 135 | size_t _tgpg_canonsexp_len (const unsigned char *sexp, size_t length); 136 | void _tgpg_checksum (const char *data, size_t length, 137 | unsigned short *r_csum); 138 | 139 | 140 | 141 | 142 | /* Memory allocation should always be done using these macros. */ 143 | #define xtrymalloc(a) malloc ((a)) 144 | #define xtrycalloc(a,b) calloc ((a),(b)) 145 | #define xtryrealloc(a, b) realloc ((a), (b)) 146 | #define xfree(a) do { void *a_ = (a); if (a_) free (a_); } while (0) 147 | 148 | /* Macro to wipe out the memory without allowing the compiler to 149 | remove it. */ 150 | #define wipememory(_ptr,_len) \ 151 | do { \ 152 | volatile char *_vptr = (volatile char *)(_ptr); \ 153 | size_t _vlen=(_len); \ 154 | while(_vlen) \ 155 | { \ 156 | *_vptr = 0; _vptr++; _vlen--; \ 157 | } \ 158 | } while(0) 159 | 160 | 161 | #endif /*TGPGDEFS_H*/ 162 | -------------------------------------------------------------------------------- /m4/libgcrypt.m4: -------------------------------------------------------------------------------- 1 | # libgcrypt.m4 - Autoconf macros to detect libgcrypt 2 | # Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH 3 | # 4 | # This file is free software; as a special exception the author gives 5 | # unlimited permission to copy and/or distribute it, with or without 6 | # modifications, as long as this notice is preserved. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # 12 | # Last-changed: 2014-10-02 13 | 14 | 15 | dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, 16 | dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) 17 | dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. 18 | dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed 19 | dnl with the API version to also check the API compatibility. Example: 20 | dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed 21 | dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using 22 | dnl this features allows to prevent build against newer versions of libgcrypt 23 | dnl with a changed API. 24 | dnl 25 | dnl If a prefix option is not used, the config script is first 26 | dnl searched in $SYSROOT/bin and then along $PATH. If the used 27 | dnl config script does not match the host specification the script 28 | dnl is added to the gpg_config_script_warn variable. 29 | dnl 30 | AC_DEFUN([AM_PATH_LIBGCRYPT], 31 | [ AC_REQUIRE([AC_CANONICAL_HOST]) 32 | AC_ARG_WITH(libgcrypt-prefix, 33 | AC_HELP_STRING([--with-libgcrypt-prefix=PFX], 34 | [prefix where LIBGCRYPT is installed (optional)]), 35 | libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") 36 | if test x"${LIBGCRYPT_CONFIG}" = x ; then 37 | if test x"${libgcrypt_config_prefix}" != x ; then 38 | LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config" 39 | else 40 | case "${SYSROOT}" in 41 | /*) 42 | if test -x "${SYSROOT}/bin/libgcrypt-config" ; then 43 | LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config" 44 | fi 45 | ;; 46 | '') 47 | ;; 48 | *) 49 | AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) 50 | ;; 51 | esac 52 | fi 53 | fi 54 | 55 | AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) 56 | tmp=ifelse([$1], ,1:1.2.0,$1) 57 | if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then 58 | req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` 59 | min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` 60 | else 61 | req_libgcrypt_api=0 62 | min_libgcrypt_version="$tmp" 63 | fi 64 | 65 | AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) 66 | ok=no 67 | if test "$LIBGCRYPT_CONFIG" != "no" ; then 68 | req_major=`echo $min_libgcrypt_version | \ 69 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` 70 | req_minor=`echo $min_libgcrypt_version | \ 71 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` 72 | req_micro=`echo $min_libgcrypt_version | \ 73 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` 74 | libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` 75 | major=`echo $libgcrypt_config_version | \ 76 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` 77 | minor=`echo $libgcrypt_config_version | \ 78 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` 79 | micro=`echo $libgcrypt_config_version | \ 80 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` 81 | if test "$major" -gt "$req_major"; then 82 | ok=yes 83 | else 84 | if test "$major" -eq "$req_major"; then 85 | if test "$minor" -gt "$req_minor"; then 86 | ok=yes 87 | else 88 | if test "$minor" -eq "$req_minor"; then 89 | if test "$micro" -ge "$req_micro"; then 90 | ok=yes 91 | fi 92 | fi 93 | fi 94 | fi 95 | fi 96 | fi 97 | if test $ok = yes; then 98 | AC_MSG_RESULT([yes ($libgcrypt_config_version)]) 99 | else 100 | AC_MSG_RESULT(no) 101 | fi 102 | if test $ok = yes; then 103 | # If we have a recent libgcrypt, we should also check that the 104 | # API is compatible 105 | if test "$req_libgcrypt_api" -gt 0 ; then 106 | tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` 107 | if test "$tmp" -gt 0 ; then 108 | AC_MSG_CHECKING([LIBGCRYPT API version]) 109 | if test "$req_libgcrypt_api" -eq "$tmp" ; then 110 | AC_MSG_RESULT([okay]) 111 | else 112 | ok=no 113 | AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) 114 | fi 115 | fi 116 | fi 117 | fi 118 | if test $ok = yes; then 119 | LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` 120 | LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` 121 | ifelse([$2], , :, [$2]) 122 | libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` 123 | if test x"$libgcrypt_config_host" != xnone ; then 124 | if test x"$libgcrypt_config_host" != x"$host" ; then 125 | AC_MSG_WARN([[ 126 | *** 127 | *** The config script $LIBGCRYPT_CONFIG was 128 | *** built for $libgcrypt_config_host and thus may not match the 129 | *** used host $host. 130 | *** You may want to use the configure option --with-libgcrypt-prefix 131 | *** to specify a matching config script or use \$SYSROOT. 132 | ***]]) 133 | gpg_config_script_warn="$gpg_config_script_warn libgcrypt" 134 | fi 135 | fi 136 | else 137 | LIBGCRYPT_CFLAGS="" 138 | LIBGCRYPT_LIBS="" 139 | ifelse([$3], , :, [$3]) 140 | fi 141 | AC_SUBST(LIBGCRYPT_CFLAGS) 142 | AC_SUBST(LIBGCRYPT_LIBS) 143 | ]) 144 | -------------------------------------------------------------------------------- /src/encrypt.c: -------------------------------------------------------------------------------- 1 | /* encrypt.c - Encrypt operation 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "tgpgdefs.h" 29 | #include "cryptglue.h" 30 | #include "keystore.h" 31 | #include "pkcs1.h" 32 | #include "pktwriter.h" 33 | 34 | /* Assume that PLAIN is a data object holding a complete plaintext 35 | message. Encrypt the message using KEY and store the result into 36 | CIPHER. CTX is the usual context. Returns 0 on success. */ 37 | int 38 | tgpg_encrypt (tgpg_t ctx, tgpg_data_t plain, 39 | tgpg_key_t key, tgpg_data_t cipher) 40 | { 41 | int rc; 42 | int i; 43 | size_t length; 44 | unsigned char *p; 45 | 46 | /* Asymmetric cipher parameters. */ 47 | struct keyinfo_s keyinfo = 48 | { 49 | { key->keyid_low, key->keyid_high }, 50 | key->algo 51 | }; 52 | tgpg_mpi_t encdat = NULL; 53 | size_t enclen; 54 | 55 | /* Block cipher parameters. */ 56 | int algo = CIPHER_ALGO_AES256; 57 | char *seskey; 58 | size_t seskeylen = _tgpg_cipher_keylen (algo); 59 | size_t blocksize = _tgpg_cipher_blocklen (algo); 60 | const char iv[16] = { 0 }; 61 | char prefix[18] = { 0 }; 62 | int mdc = ! (_tgpg_flags & TGPG_FLAG_DISABLE_MDC); 63 | 64 | /* The literal data packet. */ 65 | tgpg_data_t plainpacket = NULL; 66 | 67 | /* A buffer holding the PKCS1 encoded session key. */ 68 | char *buffer = NULL; 69 | unsigned short csum; 70 | size_t padding = 10; 71 | size_t bufferlen = 72 | padding 73 | + 1 /* algorithm */ 74 | + seskeylen 75 | + 2 /* checksum */; 76 | 77 | /* Generate cipher initialization data. */ 78 | _tgpg_randomize ((unsigned char *) prefix, blocksize); 79 | 80 | /* Session key quick check, repeat the last two octets. */ 81 | prefix[blocksize] = prefix[blocksize-2]; 82 | prefix[blocksize+1] = prefix[blocksize-1]; 83 | 84 | /* Firstly, build the literal data packet. */ 85 | rc = tgpg_data_new (&plainpacket); 86 | if (rc) 87 | return rc; 88 | 89 | rc = _tgpg_encode_plaintext_message (plainpacket, 90 | mdc, 91 | prefix, blocksize+2, 92 | 'b', 93 | "", 94 | 0, 95 | plain->image, 96 | plain->length); 97 | if (rc) 98 | goto leave; 99 | 100 | /* Allocate a buffer for the session key and PKCS1 encoding. */ 101 | buffer = p = xtrymalloc (bufferlen); 102 | if (buffer == NULL) 103 | { 104 | rc = TGPG_SYSERROR; 105 | goto leave; 106 | } 107 | 108 | /* Prepend encoding. */ 109 | rc = _tgpg_eme_pkcs1_encode (p, padding); 110 | if (rc) 111 | goto leave; 112 | p += padding; 113 | 114 | /* The cipher. */ 115 | write_u8 (&p, algo); 116 | 117 | /* The session key. */ 118 | seskey = (char *) p; 119 | p += seskeylen; 120 | 121 | /* Generate session key. */ 122 | _tgpg_randomize ((unsigned char *) seskey, seskeylen); 123 | 124 | /* The checksum. */ 125 | _tgpg_checksum (seskey, seskeylen, &csum); 126 | write_u16 (&p, csum); 127 | 128 | assert ((char *) p - buffer == bufferlen); 129 | 130 | /* Encrypt the session key. */ 131 | rc = _tgpg_pk_encrypt (key->algo, key->mpis, 132 | buffer, bufferlen, 133 | &encdat, &enclen); 134 | if (rc) 135 | goto leave; 136 | 137 | /* Compute the length of the cipher message, and resize the buffer 138 | accordingly. */ 139 | length = 140 | /* The pubkey packet, */ 141 | + _tgpg_write_pubkey_enc_packet (NULL, &keyinfo, encdat, enclen) 142 | /* and the encrypted data packet. */ 143 | + _tgpg_write_sym_enc_packet (NULL, mdc, 144 | blocksize + 2 + plainpacket->length); 145 | 146 | rc = tgpg_data_resize (cipher, length); 147 | if (rc) 148 | goto leave; 149 | 150 | p = cipher->buffer; 151 | #define WRITTEN (p - (unsigned char *) cipher->buffer) 152 | 153 | /* The Public-Key Encrypted Session Key Packet. */ 154 | _tgpg_write_pubkey_enc_packet (&p, &keyinfo, encdat, enclen); 155 | for (i = 0; i < enclen; i++) 156 | { 157 | wipememory (encdat[i].value, encdat[i].valuelen); 158 | xfree (encdat[i].value); 159 | } 160 | xfree (encdat); 161 | encdat = NULL; 162 | 163 | /* The Symmetrically Encrypted Data Packet. */ 164 | _tgpg_write_sym_enc_packet (&p, mdc, blocksize + 2 + plainpacket->length); 165 | 166 | /* Encrypt body. */ 167 | rc = _tgpg_cipher_encrypt (algo, 168 | ! mdc ? CIPHER_MODE_CFB_PGP : CIPHER_MODE_CFB_MDC, 169 | seskey, seskeylen, 170 | iv, blocksize, 171 | prefix, blocksize+2, 172 | p, 173 | cipher->length - WRITTEN, 174 | plainpacket->buffer, plainpacket->length); 175 | if (rc) 176 | goto leave; 177 | 178 | p += plainpacket->length + blocksize + 2; 179 | assert (WRITTEN == length); 180 | #undef WRITTEN 181 | 182 | leave: 183 | if (buffer != NULL) 184 | { 185 | /* This buffer contains the seskey. */ 186 | wipememory (buffer, bufferlen); 187 | xfree (buffer); 188 | } 189 | 190 | tgpg_data_release (plainpacket); 191 | assert (encdat == NULL); 192 | return rc; 193 | } 194 | -------------------------------------------------------------------------------- /m4/lt~obsolete.m4: -------------------------------------------------------------------------------- 1 | # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004. 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 5 lt~obsolete.m4 11 | 12 | # These exist entirely to fool aclocal when bootstrapping libtool. 13 | # 14 | # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) 15 | # which have later been changed to m4_define as they aren't part of the 16 | # exported API, or moved to Autoconf or Automake where they belong. 17 | # 18 | # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN 19 | # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us 20 | # using a macro with the same name in our local m4/libtool.m4 it'll 21 | # pull the old libtool.m4 in (it doesn't see our shiny new m4_define 22 | # and doesn't know about Autoconf macros at all.) 23 | # 24 | # So we provide this file, which has a silly filename so it's always 25 | # included after everything else. This provides aclocal with the 26 | # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything 27 | # because those macros already exist, or will be overwritten later. 28 | # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 29 | # 30 | # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. 31 | # Yes, that means every name once taken will need to remain here until 32 | # we give up compatibility with versions before 1.7, at which point 33 | # we need to keep only those names which we still refer to. 34 | 35 | # This is to help aclocal find these macros, as it can't see m4_define. 36 | AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) 37 | 38 | m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) 39 | m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) 40 | m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) 41 | m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) 42 | m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) 43 | m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) 44 | m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) 45 | m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) 46 | m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) 47 | m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) 48 | m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) 49 | m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) 50 | m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) 51 | m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) 52 | m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) 53 | m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) 54 | m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) 55 | m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) 56 | m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) 57 | m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) 58 | m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) 59 | m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) 60 | m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) 61 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) 62 | m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) 63 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) 64 | m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) 65 | m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) 66 | m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) 67 | m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) 68 | m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) 69 | m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) 70 | m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) 71 | m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) 72 | m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) 73 | m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) 74 | m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) 75 | m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) 76 | m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) 77 | m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) 78 | m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) 79 | m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) 80 | m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) 81 | m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) 82 | m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) 83 | m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) 84 | m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) 85 | m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) 86 | m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) 87 | m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) 88 | m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) 89 | m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) 90 | m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) 91 | m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) 92 | m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) 93 | m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) 94 | m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) 95 | m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) 96 | m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) 97 | m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) 98 | m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) 99 | -------------------------------------------------------------------------------- /src/tgpg.c: -------------------------------------------------------------------------------- 1 | /* tgpg.c - Tiny GPG 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "tgpg.h" 29 | #include "tgpgdefs.h" 30 | #include "pktparser.h" 31 | #include "keystore.h" 32 | 33 | int _tgpg_flags; 34 | 35 | /* Initialization. */ 36 | int 37 | tgpg_init (const tgpg_key_t keytable, int flags) 38 | { 39 | gcry_control (GCRYCTL_DISABLE_SECMEM, 0); 40 | if (! gcry_check_version (GCRYPT_VERSION)) 41 | { 42 | fprintf (stderr, "libtgpg: libgcrypt version mismatch\n"); 43 | return TGPG_BUG; 44 | } 45 | gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 46 | 47 | seckey_table = keytable; 48 | _tgpg_flags = flags; 49 | return TGPG_NO_ERROR; 50 | } 51 | 52 | /* Create a new context as an environment for all operations. Returns 53 | 0 on success and stores the new context at R_CTX. */ 54 | int 55 | tgpg_new (tgpg_t *r_ctx) 56 | { 57 | tgpg_t ctx; 58 | 59 | ctx = xtrycalloc (1, sizeof *ctx); 60 | if (!ctx) 61 | return TGPG_SYSERROR; 62 | 63 | *r_ctx = ctx; 64 | return 0; 65 | } 66 | 67 | 68 | /* Release all resources associated with the given context. Passing 69 | NULL is allowed as a no operation. */ 70 | void 71 | tgpg_release (tgpg_t ctx) 72 | { 73 | if (!ctx) 74 | return; 75 | xfree (ctx); 76 | } 77 | 78 | 79 | /* Make sure that BUF can be modified. This is done by taking a copy 80 | of the image. The function may return with an error to indicate an 81 | out of core condition. */ 82 | int 83 | _tgpg_make_buffer_mutable (bufdesc_t buf) 84 | { 85 | size_t len; 86 | 87 | if (buf->buffer) 88 | return 0; 89 | assert (buf->image); 90 | 91 | /* Make sure to allocate at least 1 one for the sake of broken 92 | malloc implementations. */ 93 | len = buf->length; 94 | if (!len) 95 | len = 1; 96 | buf->buffer = xtrymalloc (len); 97 | if (!buf->buffer) 98 | return TGPG_SYSERROR; 99 | buf->allocated = len; 100 | memcpy (buf->buffer, buf->image, buf->length); 101 | buf->image = buf->buffer; 102 | 103 | return 0; 104 | } 105 | 106 | 107 | /* Create a new and empty data buffer. */ 108 | int 109 | tgpg_data_new (tgpg_data_t *r_data) 110 | { 111 | bufdesc_t bufdesc; 112 | 113 | bufdesc = xtrycalloc (1, sizeof *bufdesc); 114 | if (!bufdesc) 115 | return TGPG_SYSERROR; 116 | 117 | bufdesc->length = 0; 118 | bufdesc->image = ""; 119 | 120 | *r_data = bufdesc; 121 | return 0; 122 | } 123 | 124 | 125 | 126 | 127 | /* Create a new data buffer filled with LENGTH bytes starting from 128 | BUFFER. If COPY is zero, copying is delayed until necessary, and 129 | the data is taken from the original location when needed. In this 130 | case the caller needs to make sure that he does not release or 131 | modify the memory at BUFFER as long as the returned handle is 132 | valid. */ 133 | int 134 | tgpg_data_new_from_mem (tgpg_data_t *r_data, 135 | const char *buffer, size_t length, int copy) 136 | { 137 | int rc; 138 | bufdesc_t bufdesc; 139 | 140 | if (!length || !buffer) 141 | return TGPG_INV_VAL; 142 | 143 | bufdesc = xtrycalloc (1, sizeof *bufdesc); 144 | if (!bufdesc) 145 | return TGPG_SYSERROR; 146 | 147 | bufdesc->length = length; 148 | bufdesc->image = buffer; 149 | 150 | if (copy) 151 | { 152 | rc = _tgpg_make_buffer_mutable (bufdesc); 153 | if (rc) 154 | { 155 | xfree (bufdesc); 156 | return rc; 157 | } 158 | } 159 | 160 | *r_data = bufdesc; 161 | return 0; 162 | } 163 | 164 | 165 | /* Make sure the given buffer is writable and at least SIZE long. */ 166 | int 167 | tgpg_data_resize (tgpg_data_t data, size_t size) 168 | { 169 | void *buf; 170 | 171 | buf = xtryrealloc (data->buffer, size); 172 | if (buf == NULL) 173 | return TGPG_SYSERROR; 174 | 175 | data->buffer = buf; 176 | if (data->image != data->buffer) 177 | { 178 | memcpy (data->buffer, data->image, data->length); 179 | data->image = data->buffer; 180 | } 181 | 182 | data->length = size; 183 | return TGPG_NO_ERROR; 184 | } 185 | 186 | 187 | /* Release all the memory associated with the DATA object. Passing 188 | NULL as an no-op is allowed. If the caller has allocated the 189 | object using a shallow copy (i.e. tgpg_data_new_from_mem with the 190 | copy flag cleared), he has full control over the provided memory 191 | after this function has returned. */ 192 | void 193 | tgpg_data_release (tgpg_data_t data) 194 | { 195 | if (!data) 196 | return; 197 | xfree (data->buffer); 198 | xfree (data); 199 | } 200 | 201 | /* Return a pointer to the actual data, and its length. Note that the 202 | data is not copied, and the pointer will turn stale if the DATA 203 | object is modified or destroyed. */ 204 | void 205 | tgpg_data_get (tgpg_data_t data, const char **ptr, size_t *length) 206 | { 207 | if (!data) 208 | { 209 | *ptr = NULL; 210 | *length = 0; 211 | } 212 | else 213 | { 214 | *ptr = data->image; 215 | *length = data->length; 216 | } 217 | } 218 | 219 | 220 | /* Given a data object holding an OpenPGP message, identify the type 221 | of the message. On success R_TYPE will receive on the TGPG_MSG 222 | values. R_TYPE may be passed as NULL to just run a basic check. */ 223 | int 224 | tgpg_identify (tgpg_data_t data, tgpg_msg_type_t *r_type) 225 | { 226 | int rc; 227 | tgpg_msg_type_t typ; 228 | 229 | if (!data) 230 | return TGPG_INV_VAL; 231 | rc = _tgpg_identify_message (data, &typ); 232 | switch (rc) 233 | { 234 | case TGPG_NO_DATA: 235 | typ = TGPG_MSG_UNKNOWN; 236 | rc = 0; 237 | break; 238 | case TGPG_UNEXP_PKT: 239 | typ = TGPG_MSG_INVALID; 240 | rc = 0; 241 | break; 242 | default: 243 | break; 244 | } 245 | if (r_type) 246 | *r_type = typ; 247 | return rc; 248 | } 249 | 250 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # configure.ac - for TGPG 2 | # Copyright (C) 2007 g10 Code GmbH 3 | # 4 | # This file is part of TGPG. 5 | # 6 | # TGPG is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # TGPG is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | 21 | # Process this file with autoconf to produce a configure script. 22 | AC_PREREQ(2.59) 23 | min_automake_version="1.9.3" 24 | 25 | # Remember to change the version number immediately *after* a release. 26 | # Set my_issvn to "yes" for non-released code. Remember to run an 27 | # "svn up" and "autogen.sh" right before creating a distribution. 28 | m4_define([my_version], [0.0.0]) 29 | m4_define([my_issvn], [yes]) 30 | 31 | m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ 32 | || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) 33 | AC_INIT([tgpg], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), 34 | [bug-tgpg@g10code.com]) 35 | # Set development_version to yes if the minor number is odd or you 36 | # feel that the default check for a development version is not 37 | # sufficient. 38 | development_version=no 39 | 40 | NEED_LIBGCRYPT_API=1 41 | NEED_LIBGCRYPT_VERSION=1.2.0 42 | 43 | AC_CONFIG_AUX_DIR([build-aux]) 44 | AC_CONFIG_SRCDIR(src/tgpg.c) 45 | AM_CONFIG_HEADER(config.h) 46 | AC_CONFIG_MACRO_DIR([m4]) 47 | AC_CANONICAL_TARGET() 48 | AM_INIT_AUTOMAKE 49 | AB_INIT 50 | 51 | AC_GNU_SOURCE 52 | 53 | # Some status variables. 54 | have_libgcrypt=no 55 | 56 | 57 | 58 | # Confog.h top and bottom templates. 59 | # To avoid double inclusion of config.h which might happen at some 60 | # places, we add the usual double inclusion protection at the top of 61 | # config.h. 62 | # 63 | AH_TOP([ 64 | #ifndef TGPG_CONFIG_H_INCLUDED 65 | #define TGPG_CONFIG_H_INCLUDED 66 | ]) 67 | 68 | AH_BOTTOM([ 69 | 70 | /* We explicitly need to disable PTH's soft mapping as Debian 71 | currently enables it by default for no reason. */ 72 | #define PTH_SYSCALL_SOFT 0 73 | 74 | 75 | #endif /*TGPG_CONFIG_H_INCLUDED*/ 76 | ]) 77 | 78 | 79 | AM_MAINTAINER_MODE 80 | 81 | # Checks for programs. 82 | AC_PROG_MAKE_SET 83 | AM_SANITY_CHECK 84 | missing_dir=`cd $ac_aux_dir && pwd` 85 | AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) 86 | AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) 87 | AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) 88 | AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) 89 | AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) 90 | AC_PROG_AWK 91 | AC_PROG_CC 92 | AC_PROG_CPP 93 | AC_PROG_INSTALL 94 | AC_PROG_LN_S 95 | AC_CHECK_TOOL(AR, ar, :) 96 | AC_ISC_POSIX 97 | #gl_EARLY 98 | AC_SYS_LARGEFILE 99 | 100 | # 101 | # Libtool. 102 | # 103 | LT_INIT 104 | 105 | # 106 | # Checks for libraries. 107 | # 108 | 109 | # 110 | # Libgcrypt is our generic crypto library 111 | # 112 | AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", 113 | have_libgcrypt=yes,have_libgcrypt=no) 114 | 115 | 116 | 117 | # 118 | # Checks for header files. 119 | # 120 | AC_HEADER_STDC 121 | AC_CHECK_HEADERS([string.h unistd.h langinfo.h locale.h inttypes.h]) 122 | AC_HEADER_TIME 123 | 124 | 125 | # 126 | # Checks for typedefs, structures, and compiler characteristics. 127 | # 128 | AC_C_CONST 129 | AC_C_INLINE 130 | AC_C_VOLATILE 131 | AC_TYPE_SIZE_T 132 | AC_TYPE_MODE_T 133 | AC_TYPE_UINT32_T 134 | 135 | 136 | # 137 | # Checks for library functions. 138 | # 139 | AC_FUNC_VPRINTF 140 | AC_FUNC_FORK 141 | AC_CHECK_FUNCS([strerror strlwr mmap strcasecmp strncasecmp gmtime_r]) 142 | AC_CHECK_FUNCS([gettimeofday atexit]) 143 | 144 | # 145 | # gnulib checks 146 | # 147 | 148 | 149 | # 150 | # W32 specific test 151 | # 152 | 153 | 154 | 155 | # 156 | # Do we have zlib? Must do it here because Solaris failed 157 | # when compiling a conftest (due to the "-lz" from LIBS). 158 | # Note that we combine zlib and bzlib2 in ZLIBS. 159 | # 160 | _cppflags="${CPPFLAGS}" 161 | _ldflags="${LDFLAGS}" 162 | AC_ARG_WITH(zlib, 163 | [ --with-zlib=DIR use libz in DIR],[ 164 | if test -d "$withval"; then 165 | CPPFLAGS="${CPPFLAGS} -I$withval/include" 166 | LDFLAGS="${LDFLAGS} -L$withval/lib" 167 | fi 168 | ]) 169 | 170 | AC_CHECK_HEADER(zlib.h, 171 | AC_CHECK_LIB(z, deflateInit2_, 172 | ZLIBS="-lz", 173 | CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), 174 | CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) 175 | 176 | AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) 177 | 178 | # 179 | # Setup gcc specific options 180 | # 181 | if test "$GCC" = yes; then 182 | # Note that it is okay to use CFLAGS here because this are just 183 | # warning options and the user should have a chance of overriding 184 | # them. 185 | if test "$USE_MAINTAINER_MODE" = "yes"; then 186 | CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" 187 | CFLAGS="$CFLAGS -Wno-format-y2k -Wformat-security -Wformat-nonliteral" 188 | else 189 | CFLAGS="$CFLAGS -Wall" 190 | fi 191 | fi 192 | 193 | 194 | # 195 | # This is handy for debugging so the compiler doesn't rearrange 196 | # things and eliminate variables. 197 | # 198 | AC_ARG_ENABLE(optimization, 199 | AC_HELP_STRING([--disable-optimization], 200 | [disable compiler optimization]), 201 | [if test $enableval = no ; then 202 | CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'` 203 | fi]) 204 | 205 | 206 | # 207 | # Print errors here so that they are visible all 208 | # together and the user can acquire them all together. 209 | # 210 | die=no 211 | if test "$have_libgcrypt" = "no"; then 212 | die=no 213 | AC_MSG_NOTICE([[ 214 | *** 215 | *** You need libgcrypt to build this program. 216 | ** This library is for example available at 217 | *** ftp://ftp.gnupg.org/gcrypt/libgcrypt/ 218 | *** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.) 219 | ***]]) 220 | fi 221 | 222 | if test "$die" = "yes"; then 223 | AC_MSG_ERROR([[ 224 | *** 225 | *** Required libraries not found. Please consult the above messages 226 | *** and install them before running configure again. 227 | ***]]) 228 | fi 229 | 230 | 231 | 232 | AC_CONFIG_FILES([ m4/Makefile 233 | Makefile 234 | tools/Makefile 235 | src/Makefile 236 | doc/Makefile 237 | tests/Makefile 238 | ]) 239 | AC_OUTPUT 240 | 241 | 242 | echo " 243 | TGPG v${VERSION} has been configured as follows: 244 | 245 | Platform: $host 246 | " 247 | 248 | -------------------------------------------------------------------------------- /src/tgpg.h: -------------------------------------------------------------------------------- 1 | /* tgpg.h - Public interface to Tiny GPG 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifndef TGPG_H 22 | #define TGPG_H 23 | 24 | 25 | /* 26 | Opaque data types used by TGPG. 27 | */ 28 | 29 | 30 | /* Library initialization. */ 31 | 32 | /* Flags. */ 33 | #define TGPG_FLAG_DISABLE_MDC 0x01 /* Disable MDC encryption. */ 34 | #define TGPG_FLAG_MANDATORY_MDC 0x02 /* Make MDC mandatory when 35 | decrypting files. */ 36 | 37 | 38 | /* Error codes. */ 39 | enum tgpg_error_codes 40 | { 41 | /* FIXME: Assign fixed values once we are ready. */ 42 | TGPG_SYSERROR = -1, /* The error is further described by ERRNO. */ 43 | TGPG_NO_ERROR = 0, /* No error. Needs to have a value of 0. */ 44 | TGPG_NO_DATA, /* No data for processing available. */ 45 | TGPG_INV_VAL, /* Invalid value. */ 46 | TGPG_INV_PKT, /* Invalid OpenPGP packet detected. */ 47 | TGPG_INV_MSG, /* Invalid OpenPGP message. */ 48 | TGPG_INV_MPI, /* An MPI value in a packet is malformed. */ 49 | TGPG_INV_DATA, /* Invalid data. */ 50 | TGPG_INV_ALGO, /* Algorithm is invalid or not supported. */ 51 | TGPG_INV_PASS, /* Invalid passphrase. */ 52 | TGPG_UNEXP_PKT, /* Unexpected packet. */ 53 | TGPG_UNEXP_DATA, /* Unexpected data. */ 54 | TGPG_NO_PUBKEY, /* No public key found. */ 55 | TGPG_NO_SECKEY, /* No secret key found. */ 56 | TGPG_CRYPT_ERR, /* Error from the crypto layer. */ 57 | TGPG_WRONG_KEY, /* Wrong key; can't decrypt using this key. */ 58 | TGPG_MDC_FAILED, /* The integrity check failed. */ 59 | 60 | TGPG_NOT_IMPL, /* Not implemented. */ 61 | TGPG_BUG /* Internal error. */ 62 | }; 63 | 64 | 65 | /* Type of a message. */ 66 | typedef enum 67 | { 68 | TGPG_MSG_UNKNOWN = 0, /* Unknown type of the message (e.g. not 69 | OpenPGP). */ 70 | TGPG_MSG_INVALID = 1, /* The message is not valid, though it 71 | looks like an OpenPGP one. */ 72 | TGPG_MSG_ENCRYPTED = 2, /* The message is encrypted. */ 73 | TGPG_MSG_SIGNED = 3, /* The message is signed. */ 74 | TGPG_MSG_CLEARSIGNED = 4, /* The message is clearsigned. */ 75 | TGPG_MSG_KEYDATA = 5, /* The message contains key data. */ 76 | TGPG_MSG_PLAINTEXT = 6, /* The message contains plain text data. */ 77 | } 78 | tgpg_msg_type_t; 79 | 80 | 81 | /* The context is the main anchor for all operations. It is used by 82 | almost all functions to keep a state. */ 83 | struct tgpg_context_s; 84 | typedef struct tgpg_context_s *tgpg_t; 85 | 86 | /* The structure used to identify an memory object passed to or from 87 | tgpg. */ 88 | struct tgpg_data_s; 89 | typedef struct tgpg_data_s *tgpg_data_t; 90 | 91 | /* Key management. */ 92 | 93 | /* A descriptor for an MPI. We do not store the actual value but let 94 | it point to a buffer, this avoids an extra copy. */ 95 | struct tgpg_mpi_s 96 | { 97 | unsigned int nbits; /* The length of the MPI measured in bits. */ 98 | size_t valuelen; /* The length of this value measured in bytes. */ 99 | const char *value; /* The value of the MPI. */ 100 | }; 101 | typedef struct tgpg_mpi_s *tgpg_mpi_t; 102 | 103 | /* A key for use with TGPG. */ 104 | struct tgpg_key_s 105 | { 106 | int algo; 107 | unsigned long keyid_high; 108 | unsigned long keyid_low; 109 | struct tgpg_mpi_s mpis[6]; 110 | }; 111 | typedef struct tgpg_key_s *tgpg_key_t; 112 | 113 | /* 114 | Prototypes 115 | */ 116 | 117 | /*-- tgpg.c --*/ 118 | 119 | /* Initialize the library. KEYTABLE must be an array of keys 120 | terminated by a sentinel value. Returns 0 on success. */ 121 | int tgpg_init (const tgpg_key_t keytable, int flags); 122 | 123 | /* Create a new context as an environment for all operations. Returns 124 | 0 on success and stores the new context at R_CTX. */ 125 | int tgpg_new (tgpg_t *r_ctx); 126 | 127 | /* Release all resources associated with the given context. Passing 128 | NULL is allowed to do nothing. */ 129 | void tgpg_release (tgpg_t ctx); 130 | 131 | 132 | /* Create a new and empty data buffer. */ 133 | int tgpg_data_new (tgpg_data_t *r_data); 134 | 135 | /* Create a new data buffer filled with LENGTH bytes starting from 136 | BUFFER. If COPY is zero, copying is delayed until necessary, and 137 | the data is taken from the original location when needed. In this 138 | case the caller needs to make sure that he does not release or 139 | modify the memory at BUFFER as long as the returned handle is 140 | valid. */ 141 | int tgpg_data_new_from_mem (tgpg_data_t *r_data, 142 | const char *buffer, size_t length, int copy); 143 | 144 | /* Make sure the given buffer is writable and at least SIZE long. */ 145 | int tgpg_data_resize (tgpg_data_t data, size_t size); 146 | 147 | /* Release all the memory associated with the DATA object. Passing 148 | NULL as an no-op is allowed. If the caller has allocated the 149 | object using a shallow copy (i.e. tgpg_data_new_from_mem with the 150 | copy flag cleared), he has full control over the provided memory 151 | after this function has returned. */ 152 | void tgpg_data_release (tgpg_data_t data); 153 | 154 | /* Return a pointer to the actual data, and its length. Note that the 155 | data is not copied, and the pointer will turn stale if the DATA 156 | object is modified or destroyed. */ 157 | void 158 | tgpg_data_get (tgpg_data_t data, const char **ptr, size_t *length); 159 | 160 | /* Given a data object holding an OpenPGP message, identify the type 161 | of the message. On success R_TYPE will receive on the TGPG_MSG 162 | values. R_TYPE may be passed as NULL to just run a basic check. */ 163 | int tgpg_identify (tgpg_data_t data, tgpg_msg_type_t *r_type); 164 | 165 | 166 | /*-- strerror.c --*/ 167 | 168 | /* Return a pointer to a string containing a description of the error 169 | code in the error value ERR. This function may not be thread-safe. */ 170 | const char *tgpg_strerror (int err); 171 | 172 | 173 | /*-- decrypt.c --*/ 174 | 175 | int tgpg_decrypt (tgpg_t ctx, tgpg_data_t cipher, tgpg_data_t plain); 176 | 177 | 178 | /*-- encrypt.c --*/ 179 | 180 | int tgpg_encrypt (tgpg_t ctx, tgpg_data_t plain, 181 | tgpg_key_t key, tgpg_data_t cipher); 182 | 183 | #endif /*TGPG_H*/ 184 | -------------------------------------------------------------------------------- /src/decrypt.c: -------------------------------------------------------------------------------- 1 | /* decrypt.c - Decrypt operation 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "tgpgdefs.h" 29 | #include "pktparser.h" 30 | #include "keystore.h" 31 | #include "cryptglue.h" 32 | #include "pkcs1.h" 33 | 34 | 35 | static int 36 | decrypt_session_key (keyinfo_t keyinfo, tgpg_mpi_t encdat, 37 | int *r_algo, char **r_seskey, size_t *r_seskeylen) 38 | { 39 | int rc; 40 | tgpg_mpi_t seckey; 41 | char *plain; 42 | size_t plainlen; 43 | 44 | *r_seskey = NULL; 45 | *r_seskeylen = 0; 46 | *r_algo = 0; 47 | 48 | rc = _tgpg_get_secret_key (keyinfo, &seckey); 49 | if (rc) 50 | { 51 | fprintf (stderr, "DBG: error getting secret key: %s\n", 52 | tgpg_strerror (rc)); 53 | return rc; 54 | } 55 | 56 | rc = _tgpg_pk_decrypt (keyinfo->pubkey_algo, seckey, encdat, 57 | &plain, &plainlen); 58 | _tgpg_free_secret_key (seckey); 59 | if (rc) 60 | fprintf (stderr, "DBG: decrypting session key failed: %s\n", 61 | tgpg_strerror (rc)); 62 | else 63 | { 64 | const char *body; 65 | size_t bodylen; 66 | rc = _tgpg_eme_pkcs1_decode (plain, plainlen, &body, &bodylen); 67 | if (! rc) 68 | { 69 | /* body -> <2bytes checksum> */ 70 | int algo; 71 | size_t seskeylen; 72 | const char *seskey; 73 | unsigned short csum, csum2; 74 | 75 | algo = ((unsigned char*)body)[0]; 76 | seskey = body + 1; 77 | seskeylen = bodylen - 1 - 2; 78 | csum = ((((unsigned char *)body)[bodylen-2] << 8) 79 | | ((unsigned char *)body)[bodylen-1]); 80 | _tgpg_checksum (seskey, seskeylen, &csum2); 81 | if (csum != csum2) 82 | rc = TGPG_WRONG_KEY; 83 | else if (!(*r_seskey = xtrymalloc (seskeylen))) 84 | rc = TGPG_SYSERROR; 85 | else 86 | { 87 | memcpy (*r_seskey, seskey, seskeylen); 88 | *r_seskeylen = seskeylen; 89 | *r_algo = algo; 90 | } 91 | } 92 | } 93 | 94 | if (plain) 95 | { 96 | wipememory (plain, plainlen); 97 | xfree (plain); 98 | } 99 | 100 | return rc; 101 | } 102 | 103 | /* Assume that CIPHER is a data object holding a complete encrypted 104 | message. Decrypt the message and store the result into PLAIN. 105 | CTX is the usual context. Returns 0 on success. */ 106 | int 107 | tgpg_decrypt (tgpg_t ctx, tgpg_data_t cipher, tgpg_data_t plain) 108 | { 109 | int rc; 110 | size_t startoff; 111 | size_t length; 112 | 113 | /* Asymmetric cipher parameters. */ 114 | keyinfo_t keyinfo; 115 | tgpg_mpi_t encdat; 116 | 117 | /* Block cipher parameters. */ 118 | int mdc = 0; 119 | int algo; 120 | char *seskey = NULL; 121 | size_t seskeylen; 122 | size_t blocksize = 8; 123 | const char iv[16] = { 0 }; 124 | char prefix[18]; 125 | 126 | /* The decrypted literal data packet. */ 127 | char *buffer = NULL; 128 | size_t bufferlen; 129 | tgpg_data_t plainpacket = NULL; 130 | tgpg_msg_type_t msgtype; 131 | 132 | /* Plaintext data. */ 133 | unsigned char format; 134 | char filename[0xff + 1]; 135 | time_t date; 136 | size_t start; 137 | 138 | keyinfo = xtrycalloc (1, sizeof *keyinfo); 139 | if (!keyinfo) 140 | return TGPG_SYSERROR; 141 | encdat = xtrycalloc (MAX_PK_NENC, sizeof *encdat); 142 | if (!encdat) 143 | { 144 | xfree (keyinfo); 145 | return TGPG_SYSERROR; 146 | } 147 | 148 | rc = _tgpg_parse_encrypted_message (cipher, &mdc, 149 | &startoff, &length, 150 | keyinfo, encdat); 151 | if (rc) 152 | goto leave; 153 | 154 | if (! mdc) 155 | { 156 | int mandatory = _tgpg_flags & TGPG_FLAG_MANDATORY_MDC; 157 | fprintf (stderr, "tgpg: %s: message was not integrity protected\n", 158 | mandatory ? "ERROR" : "WARNING"); 159 | if (mandatory) 160 | { 161 | rc = TGPG_MDC_FAILED; 162 | goto leave; 163 | } 164 | } 165 | 166 | rc = decrypt_session_key (keyinfo, encdat, &algo, &seskey, &seskeylen); 167 | if (rc) 168 | goto leave; 169 | 170 | blocksize = _tgpg_cipher_blocklen (algo); 171 | 172 | /* Allocate buffer for the plaintext. */ 173 | bufferlen = length - blocksize - 2; 174 | buffer = xtrymalloc (bufferlen); 175 | if (buffer == NULL) 176 | { 177 | rc = TGPG_SYSERROR; 178 | goto leave; 179 | } 180 | 181 | /* Decrypt body. */ 182 | rc = _tgpg_cipher_decrypt (algo, 183 | ! mdc ? CIPHER_MODE_CFB_PGP : CIPHER_MODE_CFB_MDC, 184 | seskey, seskeylen, 185 | iv, blocksize, 186 | prefix, sizeof prefix, 187 | buffer, bufferlen, 188 | &cipher->image[startoff], length); 189 | if (rc) 190 | goto leave; 191 | 192 | /* Put it in a container so that we can parse it. */ 193 | rc = tgpg_data_new_from_mem (&plainpacket, buffer, bufferlen, 1); 194 | if (rc) 195 | goto leave; 196 | 197 | rc = tgpg_identify (plainpacket, &msgtype); 198 | if (rc) 199 | goto leave; 200 | 201 | if (msgtype != TGPG_MSG_PLAINTEXT) 202 | { 203 | rc = TGPG_INV_MSG; 204 | goto leave; 205 | } 206 | 207 | /* Finally, parse the decrypted data... */ 208 | rc = _tgpg_parse_plaintext_message (plainpacket, 209 | mdc, 210 | prefix, sizeof prefix, 211 | &format, 212 | filename, 213 | &date, 214 | &start, 215 | &length); 216 | if (rc) 217 | goto leave; 218 | fprintf (stderr, "DBG: format %c, filename %s, length %zd, date %s", 219 | format, filename, length, ctime (&date)); 220 | 221 | /* ... and present the content to the user. */ 222 | rc = tgpg_data_resize (plain, length); 223 | if (rc) 224 | goto leave; 225 | 226 | memcpy (plain->buffer, &plainpacket->buffer[start], length); 227 | 228 | leave: 229 | if (seskey) 230 | { 231 | wipememory (seskey, seskeylen); 232 | xfree (seskey); 233 | } 234 | tgpg_data_release (plainpacket); 235 | xfree (buffer); 236 | xfree (encdat); 237 | xfree (keyinfo); 238 | return rc; 239 | } 240 | 241 | 242 | -------------------------------------------------------------------------------- /src/pktwriter.c: -------------------------------------------------------------------------------- 1 | /* pktwriter.c - OpenPGP packet writing functions. 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "tgpgdefs.h" 31 | #include "cryptglue.h" 32 | #include "keystore.h" 33 | #include "pktwriter.h" 34 | 35 | /* Return the size of a new-style CTB with the given LENGTH. */ 36 | static size_t __attribute ((const)) 37 | header_size (size_t length) 38 | { 39 | if (length < 192) 40 | return 2; 41 | if (length < 8384) 42 | return 3; 43 | return 5; 44 | } 45 | 46 | /* Write an OpenPGP packet header with the given TAG and LENGTH to *P, 47 | and advance *P accordingly. Return the size of the header. If P 48 | is NULL, no data is actually written. */ 49 | static size_t 50 | write_header (unsigned char **p, unsigned char tag, size_t length) 51 | { 52 | assert (tag < 1<<6 || ! "invalid tag"); 53 | 54 | if (p == NULL) 55 | return header_size (length); 56 | 57 | /* Write packet tag. */ 58 | write_u8 (p, 0x80 /* always one */ 59 | | 0x40 /* new-style packet */ 60 | | tag); 61 | 62 | /* Write length. */ 63 | switch (header_size (length)) 64 | { 65 | case 2: 66 | write_u8 (p, length); 67 | break; 68 | 69 | case 3:; 70 | size_t l = length - 192; 71 | write_u8 (p, ((l >> 8) & 0xff) + 192); 72 | write_u8 (p, ((l >> 0) & 0xff)); 73 | break; 74 | 75 | case 5: 76 | write_u32 (p, length); 77 | } 78 | 79 | return header_size (length); 80 | } 81 | 82 | /* Write an OpenPGP public key encrypted packet to *P, and advance *P 83 | accordingly. Return the size of the packet. If P is NULL, no data 84 | is actually written. */ 85 | size_t 86 | _tgpg_write_pubkey_enc_packet (unsigned char **p, 87 | keyinfo_t ki, 88 | tgpg_mpi_t encdat, size_t enclen) 89 | { 90 | int i; 91 | size_t length; 92 | unsigned char *start; 93 | 94 | assert (enclen || ! "invalid algorithm"); 95 | assert (enclen <= MAX_PK_NENC); 96 | 97 | length = 10 /* version, keyid and algorithm */; 98 | for (i = 0; i < enclen; i++) 99 | length += 2 /* length */ + encdat[i].valuelen /* value */; 100 | 101 | if (p == NULL) 102 | return length + header_size (length); 103 | 104 | write_header (p, PKT_PUBKEY_ENC, length); 105 | start = *p; 106 | 107 | /* The packet version. */ 108 | write_u8 (p, 3); 109 | 110 | /* The keyid. */ 111 | write_u32 (p, ki->keyid[1]); 112 | write_u32 (p, ki->keyid[0]); 113 | 114 | /* The asymmetric encryption algorithm. */ 115 | write_u8 (p, ki->pubkey_algo); 116 | 117 | /* The encrypted session key. */ 118 | for (i = 0; i < enclen; i++) 119 | write_mpi (p, &encdat[i]); 120 | 121 | assert (*p - start == length); 122 | return length + header_size (length); 123 | } 124 | 125 | /* Write an OpenPGP symmetrically encrypted packet to *P, and advance 126 | *P accordingly. If MDC is non-zero, write an integrity protected 127 | packet of the given version. As the body is merely appended to 128 | this header, this function is not concerned with the body itself. 129 | Return the size of the packet. If P is NULL, no data is actually 130 | written. */ 131 | size_t 132 | _tgpg_write_sym_enc_packet (unsigned char **p, int mdc, size_t length) 133 | { 134 | size_t mdc_length, packet_length; 135 | 136 | switch (mdc) 137 | { 138 | case 0: 139 | mdc_length = 0; 140 | break; 141 | case 1: 142 | mdc_length = 1; 143 | break; 144 | default: 145 | return TGPG_BUG; 146 | } 147 | 148 | packet_length = write_header (p, ! mdc ? PKT_ENCRYPTED : PKT_ENCRYPTED_MDC, 149 | length + mdc_length) 150 | + length + mdc_length; 151 | 152 | if (p && mdc) 153 | write_u8 (p, mdc); 154 | 155 | return packet_length; 156 | } 157 | 158 | 159 | /* Construct a plaintext message in MSG, with the given FORMAT, 160 | FILENAME (which must not be larger than 0xff bytes), DATE, and 161 | containing the literal data PAYLOAD of given LENGTH. If MDC is 162 | non-zero, create a Modification Detection Code Packet of the given 163 | version. In that case, PREFIX of length PREFIXLEN must be the 164 | block cipher initialization data. */ 165 | int 166 | _tgpg_encode_plaintext_message (bufdesc_t msg, 167 | int mdc, 168 | const char *prefix, 169 | size_t prefixlen, 170 | unsigned char format, 171 | const char *filename, 172 | time_t date, 173 | const char *payload, 174 | size_t length) 175 | { 176 | int rc; 177 | unsigned char *p; 178 | size_t header_length; 179 | size_t mdc_length; 180 | 181 | if (strlen (filename) > 0xff) 182 | return TGPG_INV_VAL; 183 | 184 | switch (mdc) 185 | { 186 | case 0: 187 | mdc_length = 0; 188 | break; 189 | 190 | case 1: 191 | mdc_length = 20; 192 | break; 193 | 194 | default: 195 | return TGPG_BUG; 196 | } 197 | 198 | header_length = 199 | + 2 /* format and filename length */ 200 | + strlen (filename) 201 | + 4 /* the date */; 202 | 203 | rc = tgpg_data_resize (msg, 204 | + header_size (header_length 205 | + length) 206 | + header_length 207 | + length 208 | + (mdc ? (header_size (mdc_length) 209 | + mdc_length) 210 | : 0)); 211 | if (rc) 212 | return rc; 213 | 214 | p = (unsigned char *) msg->buffer; 215 | write_header (&p, PKT_PLAINTEXT, header_length + length); 216 | 217 | /* The format. */ 218 | write_u8 (&p, format); 219 | 220 | /* The filename, with its length prepended to it encoded as a single 221 | octet. */ 222 | write_u8 (&p, strlen (filename)); 223 | memcpy (p, filename, strlen (filename)); 224 | p += strlen (filename); 225 | 226 | /* The date. */ 227 | write_u32 (&p, (uint32_t) date); 228 | 229 | /* The literal data. */ 230 | memcpy (p, payload, length); 231 | p += length; 232 | 233 | switch (mdc) 234 | { 235 | hash_t h; 236 | case 1: 237 | rc = _tgpg_hash_open (&h, MD_ALGO_SHA1, 0); 238 | if (rc) 239 | return rc; 240 | 241 | write_header (&p, PKT_MDC, hash_digestlen (h)); 242 | 243 | _tgpg_hash_write (h, prefix, prefixlen); 244 | _tgpg_hash_write (h, msg->image, p - (unsigned char *) msg->image); 245 | memcpy ((char *) p, _tgpg_hash_read (h), hash_digestlen (h)); 246 | _tgpg_hash_close (h); 247 | } 248 | 249 | return TGPG_NO_ERROR; 250 | } 251 | -------------------------------------------------------------------------------- /tests/tgpgtest.c: -------------------------------------------------------------------------------- 1 | /* tgpgtest.c - Test driver for TGPG. 2 | Copyright (C) 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include 23 | #endif /*HAVE_CONFIG_H*/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include /* Obviously we only include the public header. */ 35 | 36 | #define PGM "tgpgtest" 37 | #ifndef PACKAGE_BUGREPORT 38 | #define PACKAGE_BUGREPORT "nobody@example.net" 39 | #endif /*PACKAGE_BUGREPORT*/ 40 | 41 | /* The keystore is linked in. */ 42 | extern struct tgpg_key_s keystore[]; 43 | 44 | static int opt_encrypt; 45 | static int verbose; 46 | static int debug; 47 | 48 | 49 | 50 | /* Read the file with name FNAME into a buffer and return a pointer to 51 | the buffer as well as the length of the file. A file name of "-" 52 | indiocates reading from stdin. Returns NULL on error after 53 | printing a diagnostic. */ 54 | static char * 55 | read_file (const char *fname, size_t *r_length) 56 | { 57 | FILE *fp; 58 | char *buf, *newbuf; 59 | size_t buflen; 60 | 61 | if (!strcmp (fname, "-")) 62 | { 63 | size_t nread, bufsize = 0; 64 | 65 | fp = stdin; 66 | #ifdef HAVE_DOSISH_SYSTEM 67 | setmode ( fileno (fp), O_BINARY ); 68 | #endif 69 | buf = NULL; 70 | buflen = 0; 71 | #define NCHUNK 8192 72 | do 73 | { 74 | bufsize += NCHUNK; 75 | if (!buf) 76 | newbuf = malloc (bufsize); 77 | else 78 | newbuf = realloc (buf, bufsize); 79 | if (!newbuf) 80 | { 81 | fprintf (stderr, PGM": malloc or realloc failed: %s\n", 82 | strerror (errno)); 83 | free (buf); 84 | return NULL; 85 | } 86 | buf = newbuf; 87 | 88 | nread = fread (buf+buflen, 1, NCHUNK, fp); 89 | if (nread < NCHUNK && ferror (fp)) 90 | { 91 | fprintf (stderr, PGM ": error reading `[stdin]': %s\n", 92 | strerror (errno)); 93 | free (buf); 94 | return NULL; 95 | } 96 | buflen += nread; 97 | } 98 | while (nread == NCHUNK); 99 | #undef NCHUNK 100 | 101 | } 102 | else 103 | { 104 | struct stat st; 105 | 106 | fp = fopen (fname, "rb"); 107 | if (!fp) 108 | { 109 | fprintf (stderr, PGM": can't open `%s': %s\n", 110 | fname, strerror (errno)); 111 | return NULL; 112 | } 113 | 114 | if (fstat (fileno(fp), &st)) 115 | { 116 | fprintf (stderr, PGM": can't stat `%s': %s\n", 117 | fname, strerror (errno)); 118 | fclose (fp); 119 | return NULL; 120 | } 121 | 122 | buflen = st.st_size; 123 | buf = malloc (buflen+1); 124 | if (!buf) 125 | { 126 | fprintf (stderr, PGM": malloc failed (file too large?): %s\n", 127 | strerror (errno)); 128 | fclose (fp); 129 | return NULL; 130 | } 131 | if (fread (buf, buflen, 1, fp) != 1) 132 | { 133 | fprintf (stderr, PGM ": error reading `%s': %s\n", 134 | fname, strerror (errno)); 135 | fclose (fp); 136 | free (buf); 137 | return NULL; 138 | } 139 | fclose (fp); 140 | } 141 | 142 | *r_length = buflen; 143 | return buf; 144 | } 145 | 146 | 147 | static int 148 | do_decrypt (tgpg_t ctx, tgpg_data_t inpdata, tgpg_data_t outdata) 149 | { 150 | int rc; 151 | tgpg_msg_type_t msgtype; 152 | 153 | rc = tgpg_identify (inpdata, &msgtype); 154 | if (rc) 155 | { 156 | fprintf (stderr, PGM": can't identify file: %s\n", 157 | tgpg_strerror (rc)); 158 | goto leave; 159 | } 160 | 161 | if (msgtype == TGPG_MSG_ENCRYPTED) 162 | rc = tgpg_decrypt (ctx, inpdata, outdata); 163 | else 164 | rc = TGPG_MSG_INVALID; 165 | 166 | leave: 167 | return rc; 168 | } 169 | 170 | static int 171 | do_encrypt (tgpg_t ctx, tgpg_data_t inpdata, tgpg_data_t outdata) 172 | { 173 | int rc; 174 | 175 | rc = tgpg_encrypt (ctx, inpdata, &keystore[0], outdata); 176 | if (rc) 177 | goto leave; 178 | 179 | leave: 180 | return rc; 181 | } 182 | 183 | 184 | static int 185 | process_file (const char *fname) 186 | { 187 | char *inpfile; 188 | size_t inplen; 189 | int rc; 190 | tgpg_data_t inpdata = NULL; 191 | tgpg_data_t outdata = NULL; 192 | tgpg_t ctx = NULL; 193 | const char *data; 194 | size_t length; 195 | 196 | inpfile = read_file (fname, &inplen); 197 | if (!inpfile) 198 | return TGPG_SYSERROR; 199 | 200 | if (verbose) 201 | fprintf (stderr, PGM": file `%s' of size %lu read\n", 202 | fname, (unsigned long)inplen); 203 | 204 | rc = tgpg_data_new_from_mem (&inpdata, inpfile, inplen, 0); 205 | if (rc) 206 | { 207 | fprintf (stderr, PGM": can't create data object for `%s': %s\n", 208 | fname, tgpg_strerror (rc)); 209 | goto leave; 210 | } 211 | 212 | rc = tgpg_data_new (&outdata); 213 | if (rc) 214 | goto leave; 215 | 216 | rc = tgpg_new (&ctx); 217 | if (rc) 218 | { 219 | fprintf (stderr, PGM": can't create context object: %s\n", 220 | tgpg_strerror (rc)); 221 | goto leave; 222 | } 223 | 224 | rc = (opt_encrypt ? do_encrypt : do_decrypt) (ctx, inpdata, outdata); 225 | if (rc) 226 | { 227 | fprintf (stderr, PGM": %scryption failed: %s\n", 228 | opt_encrypt ? "en" : "de", tgpg_strerror (rc)); 229 | goto leave; 230 | } 231 | 232 | tgpg_data_get (outdata, &data, &length); 233 | write (fileno (stdout), data, length); 234 | 235 | leave: 236 | tgpg_release (ctx); 237 | tgpg_data_release (outdata); 238 | tgpg_data_release (inpdata); 239 | free (inpfile); 240 | return rc; 241 | } 242 | 243 | 244 | 245 | 246 | int 247 | main (int argc, char **argv) 248 | { 249 | int err; 250 | int last_argc = -1; 251 | int flags = 0; 252 | 253 | if (argc) 254 | { 255 | argc--; argv++; 256 | } 257 | 258 | while (argc && last_argc != argc ) 259 | { 260 | last_argc = argc; 261 | if (!strcmp (*argv, "--")) 262 | { 263 | argc--; argv++; 264 | break; 265 | } 266 | else if (!strcmp (*argv, "--help")) 267 | { 268 | puts ( 269 | "Usage: " PGM " [OPTION] [FILE]\n" 270 | "Simple tool to test TGPG.\n\n" 271 | " --encrypt encrypt rather than decrypt (the default)\n" 272 | " --disable-mdc do not use MDC for encryption\n" 273 | " --mandatory-mdc make MDC mandatory for decryption\n" 274 | " --verbose enable extra informational output\n" 275 | " --debug enable additional debug output\n" 276 | " --help display this help and exit\n\n" 277 | "With no FILE, or when FILE is -, read standard input.\n\n" 278 | "Report bugs to <" PACKAGE_BUGREPORT ">."); 279 | exit (0); 280 | } 281 | else if (!strcmp (*argv, "--encrypt")) 282 | { 283 | opt_encrypt = 1; 284 | argc--; argv++; 285 | } 286 | else if (!strcmp (*argv, "--disable-mdc")) 287 | { 288 | flags |= TGPG_FLAG_DISABLE_MDC; 289 | argc--; argv++; 290 | } 291 | else if (!strcmp (*argv, "--mandatory-mdc")) 292 | { 293 | flags |= TGPG_FLAG_MANDATORY_MDC; 294 | argc--; argv++; 295 | } 296 | else if (!strcmp (*argv, "--verbose")) 297 | { 298 | verbose = 1; 299 | argc--; argv++; 300 | } 301 | else if (!strcmp (*argv, "--debug")) 302 | { 303 | verbose = debug = 1; 304 | argc--; argv++; 305 | } 306 | } 307 | 308 | if (argc > 1) 309 | { 310 | fprintf (stderr, "usage: " PGM 311 | " [OPTION] [FILE] (try --help for more information)\n"); 312 | exit (1); 313 | } 314 | 315 | err = tgpg_init (keystore, flags); 316 | if (err) 317 | exit (1); 318 | 319 | if (argc) 320 | err = process_file (*argv); 321 | else 322 | err = process_file ("-"); 323 | 324 | return err ? EXIT_FAILURE : EXIT_SUCCESS; 325 | } 326 | -------------------------------------------------------------------------------- /tools/tgpg-keystore.c: -------------------------------------------------------------------------------- 1 | /* tgpg-keystore.c - Utility to produce the static keystore for TGPG. 2 | Copyright (C) 2015 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include 23 | #endif /*HAVE_CONFIG_H*/ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #define PGM "tgpg-keystore" 37 | #define DIM(v) (sizeof(v)/sizeof((v)[0])) 38 | 39 | static const char *name = "keystore"; 40 | static int verbose; 41 | static int debug; 42 | static FILE *stream; 43 | 44 | /* Read the file with name FNAME into a buffer and return a pointer to 45 | the buffer as well as the length of the file. A file name of "-" 46 | indiocates reading from stdin. Returns NULL on error after 47 | printing a diagnostic. */ 48 | static char * 49 | read_file (const char *fname, size_t *r_length) 50 | { 51 | FILE *fp; 52 | char *buf, *newbuf; 53 | size_t buflen; 54 | 55 | if (!strcmp (fname, "-")) 56 | { 57 | size_t nread, bufsize = 0; 58 | 59 | fp = stdin; 60 | #ifdef HAVE_DOSISH_SYSTEM 61 | setmode ( fileno (fp), O_BINARY ); 62 | #endif 63 | buf = NULL; 64 | buflen = 0; 65 | #define NCHUNK 8192 66 | do 67 | { 68 | bufsize += NCHUNK; 69 | if (!buf) 70 | newbuf = malloc (bufsize); 71 | else 72 | newbuf = realloc (buf, bufsize); 73 | if (!newbuf) 74 | { 75 | fprintf (stderr, PGM": malloc or realloc failed: %s\n", 76 | strerror (errno)); 77 | free (buf); 78 | return NULL; 79 | } 80 | buf = newbuf; 81 | 82 | nread = fread (buf+buflen, 1, NCHUNK, fp); 83 | if (nread < NCHUNK && ferror (fp)) 84 | { 85 | fprintf (stderr, PGM ": error reading `[stdin]': %s\n", 86 | strerror (errno)); 87 | free (buf); 88 | return NULL; 89 | } 90 | buflen += nread; 91 | } 92 | while (nread == NCHUNK); 93 | #undef NCHUNK 94 | 95 | } 96 | else 97 | { 98 | struct stat st; 99 | 100 | fp = fopen (fname, "rb"); 101 | if (!fp) 102 | { 103 | fprintf (stderr, PGM": can't open `%s': %s\n", 104 | fname, strerror (errno)); 105 | return NULL; 106 | } 107 | 108 | if (fstat (fileno(fp), &st)) 109 | { 110 | fprintf (stderr, PGM": can't stat `%s': %s\n", 111 | fname, strerror (errno)); 112 | fclose (fp); 113 | return NULL; 114 | } 115 | 116 | buflen = st.st_size; 117 | buf = malloc (buflen+1); 118 | if (!buf) 119 | { 120 | fprintf (stderr, PGM": malloc failed (file too large?): %s\n", 121 | strerror (errno)); 122 | fclose (fp); 123 | return NULL; 124 | } 125 | if (fread (buf, buflen, 1, fp) != 1) 126 | { 127 | fprintf (stderr, PGM ": error reading `%s': %s\n", 128 | fname, strerror (errno)); 129 | fclose (fp); 130 | free (buf); 131 | return NULL; 132 | } 133 | fclose (fp); 134 | } 135 | 136 | *r_length = buflen; 137 | return buf; 138 | } 139 | 140 | struct keyid { 141 | unsigned long high, low; 142 | }; 143 | 144 | int 145 | parse_keyid (const char *s, struct keyid *id) 146 | { 147 | char buf[9]; 148 | char *endptr; 149 | 150 | if (strlen (s) != 16) 151 | goto errout; 152 | 153 | strncpy (buf, s, 8); 154 | buf[8] = 0; 155 | id->high = strtoul (buf, &endptr, 16); 156 | if (*endptr != 0) 157 | goto errout; 158 | 159 | strncpy (buf, s+8, 8); 160 | buf[8] = 0; 161 | id->low = strtoul (buf, &endptr, 16); 162 | if (*endptr != 0) 163 | goto errout; 164 | 165 | return 0; 166 | 167 | errout: 168 | fprintf (stderr, "Invalid key id '%s'", s); 169 | return 1; 170 | } 171 | 172 | 173 | 174 | static void 175 | process_file (const struct keyid *keyid, const char *fname, FILE *stream) 176 | { 177 | char *inpfile; 178 | size_t inplen; 179 | gcry_sexp_t sexp = NULL; 180 | gcry_error_t err; 181 | unsigned int keysize; 182 | const char *keys = "nedpqu"; 183 | const int shifts[] = {0, 0, 0, 1, 1, 1}; 184 | gcry_mpi_t mpis[7] = {}; 185 | int i; 186 | 187 | inpfile = read_file (fname, &inplen); 188 | if (!inpfile) 189 | goto leave; 190 | if (verbose) 191 | fprintf (stderr, PGM": file `%s' of size %lu read\n", 192 | fname, (unsigned long)inplen); 193 | 194 | err = gcry_sexp_new (&sexp, inpfile, inplen, 1); 195 | if (err) 196 | goto leave; 197 | 198 | err = gcry_sexp_extract_param (sexp, "private-key", keys, 199 | &mpis[0], 200 | &mpis[1], 201 | &mpis[2], 202 | &mpis[3], 203 | &mpis[4], 204 | &mpis[5], 205 | NULL); 206 | if (err) 207 | goto leave; 208 | 209 | keysize = gcry_pk_get_nbits (sexp); 210 | 211 | fprintf (stream, 212 | " {\n" 213 | " 1 /* PK_ALGO_RSA */, 0x%08lx, 0x%08lx,\n" 214 | " {\n", 215 | keyid->high, keyid->low); 216 | 217 | for (i = 0; i < 6; i++) 218 | { 219 | unsigned char *buf, *data; 220 | int size_delta; 221 | size_t len; 222 | 223 | err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, &len, mpis[i]); 224 | if (err) 225 | goto leave; 226 | 227 | data = buf; 228 | len -= 1; /* trailing zero */ 229 | assert (len % 2 == 0); 230 | 231 | if (keys[i] != 'e') 232 | { 233 | /* Normalize data. */ 234 | size_delta = (keysize >> (3 + shifts[i])) - (len / 2); 235 | 236 | /* Skip leading zeroes. */ 237 | while (size_delta < 0 238 | && strncmp ((const char *) data, "00", 2) == 0) 239 | data += 2, len -= 2; 240 | 241 | /* Fill up with leading zeroes. */ 242 | if (size_delta > 0) 243 | { 244 | size_t new_len = keysize >> (3 + shifts[i] - 1 /* hex */); 245 | char *p, *new = malloc (new_len); 246 | if (! new) 247 | goto leave; 248 | 249 | fprintf (stderr, "%d %d\n", size_delta, 0); 250 | for (p = new; p - new < size_delta * 2 /* hex */; p++) 251 | *p = '0'; 252 | 253 | memcpy (p, data, len); 254 | free (buf); 255 | 256 | buf = data = new, len = new_len; 257 | } 258 | size_delta = (keysize >> (3 + shifts[i])) - (len / 2); 259 | assert (size_delta == 0); 260 | } 261 | 262 | #define INDENT " " 263 | fprintf (stream, 264 | " { /* %c: */ %u /* bits */, %u /* bytes */,\n" 265 | INDENT "\"", 266 | keys[i], len << 2, len / 2); 267 | 268 | const unsigned char *c; 269 | for (c = data; c - data < len; c += 2) 270 | { 271 | ptrdiff_t d = c - data; 272 | if (d > 0 && d % 16 == 0) 273 | fprintf (stream, "\"\n" INDENT "\""); 274 | 275 | fprintf (stream, "\\x%.2s", c); 276 | } 277 | #undef INDENT 278 | 279 | fprintf (stream, "\" },\n"); 280 | 281 | free (buf); 282 | } 283 | 284 | fprintf (stream, 285 | " },\n" 286 | " },\n"); 287 | 288 | leave: 289 | free (inpfile); 290 | gcry_sexp_release (sexp); 291 | for (i = 0; i < DIM (mpis); i++) 292 | gcry_mpi_release (mpis[i]); 293 | } 294 | 295 | int 296 | main (int argc, char **argv) 297 | { 298 | int last_argc = -1; 299 | 300 | if (argc) 301 | { 302 | argc--; argv++; 303 | } 304 | 305 | gcry_control (GCRYCTL_DISABLE_SECMEM, 0); 306 | if (!gcry_check_version (GCRYPT_VERSION)) 307 | { 308 | fprintf (stderr, PGM ": libgcrypt version mismatch\n"); 309 | exit (1); 310 | } 311 | gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 312 | 313 | while (argc && last_argc != argc ) 314 | { 315 | last_argc = argc; 316 | if (!strcmp (*argv, "--")) 317 | { 318 | argc--; argv++; 319 | break; 320 | } 321 | else if (!strcmp (*argv, "--help")) 322 | { 323 | puts ( 324 | "Usage: " PGM " [OPTION] KEYID PRIVATE-KEY-FILE [KEYID PKF...]\n" 325 | "Simple tool to generate static keystores for TGPG.\n\n" 326 | " --name NAME specify name of the symbol [default: keystore]\n" 327 | " --verbose enable extra informational output\n" 328 | " --debug enable additional debug output\n" 329 | " --help display this help and exit\n\n" 330 | "Report bugs to <" PACKAGE_BUGREPORT ">."); 331 | exit (0); 332 | } 333 | else if (!strcmp (*argv, "--name")) 334 | { 335 | if (! argc) 336 | { 337 | fprintf (stderr, "expected a name\n"); 338 | exit (1); 339 | } 340 | name = argv[1]; 341 | argc -= 2, argv += 2; 342 | } 343 | else if (!strcmp (*argv, "--verbose")) 344 | { 345 | verbose = 1; 346 | argc--; argv++; 347 | } 348 | else if (!strcmp (*argv, "--debug")) 349 | { 350 | verbose = debug = 1; 351 | argc--; argv++; 352 | } 353 | } 354 | 355 | if (argc < 2 || argc % 2 == 1) 356 | { 357 | fprintf (stderr, "usage: " PGM 358 | " [OPTION] KEYID PRIVATE-KEY-FILE [KEYID PKF...]\n" 359 | " (try --help for more information)\n"); 360 | exit (1); 361 | } 362 | 363 | stream = stdout; 364 | 365 | fprintf (stream, 366 | "#include \n" 367 | "#include \n" 368 | "\n" 369 | "struct tgpg_key_s %s[] = {\n", 370 | name); 371 | 372 | for (; argc; argc -= 2, argv += 2) 373 | { 374 | struct keyid id; 375 | if (parse_keyid (argv[0], &id)) 376 | return EXIT_FAILURE; 377 | 378 | process_file (&id, argv[1], stream); 379 | } 380 | fprintf (stream, 381 | " { /* sentinel */ 0 },\n" 382 | "};\n"); 383 | 384 | return EXIT_SUCCESS; 385 | } 386 | -------------------------------------------------------------------------------- /m4/ltoptions.m4: -------------------------------------------------------------------------------- 1 | # Helper functions for option handling. -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, 4 | # Inc. 5 | # Written by Gary V. Vaughan, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 7 ltoptions.m4 12 | 13 | # This is to help aclocal find these macros, as it can't see m4_define. 14 | AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) 15 | 16 | 17 | # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) 18 | # ------------------------------------------ 19 | m4_define([_LT_MANGLE_OPTION], 20 | [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) 21 | 22 | 23 | # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) 24 | # --------------------------------------- 25 | # Set option OPTION-NAME for macro MACRO-NAME, and if there is a 26 | # matching handler defined, dispatch to it. Other OPTION-NAMEs are 27 | # saved as a flag. 28 | m4_define([_LT_SET_OPTION], 29 | [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl 30 | m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), 31 | _LT_MANGLE_DEFUN([$1], [$2]), 32 | [m4_warning([Unknown $1 option `$2'])])[]dnl 33 | ]) 34 | 35 | 36 | # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) 37 | # ------------------------------------------------------------ 38 | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. 39 | m4_define([_LT_IF_OPTION], 40 | [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) 41 | 42 | 43 | # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) 44 | # ------------------------------------------------------- 45 | # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME 46 | # are set. 47 | m4_define([_LT_UNLESS_OPTIONS], 48 | [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 49 | [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), 50 | [m4_define([$0_found])])])[]dnl 51 | m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 52 | ])[]dnl 53 | ]) 54 | 55 | 56 | # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) 57 | # ---------------------------------------- 58 | # OPTION-LIST is a space-separated list of Libtool options associated 59 | # with MACRO-NAME. If any OPTION has a matching handler declared with 60 | # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about 61 | # the unknown option and exit. 62 | m4_defun([_LT_SET_OPTIONS], 63 | [# Set options 64 | m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 65 | [_LT_SET_OPTION([$1], _LT_Option)]) 66 | 67 | m4_if([$1],[LT_INIT],[ 68 | dnl 69 | dnl Simply set some default values (i.e off) if boolean options were not 70 | dnl specified: 71 | _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no 72 | ]) 73 | _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no 74 | ]) 75 | dnl 76 | dnl If no reference was made to various pairs of opposing options, then 77 | dnl we run the default mode handler for the pair. For example, if neither 78 | dnl `shared' nor `disable-shared' was passed, we enable building of shared 79 | dnl archives by default: 80 | _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) 81 | _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) 82 | _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) 83 | _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], 84 | [_LT_ENABLE_FAST_INSTALL]) 85 | ]) 86 | ])# _LT_SET_OPTIONS 87 | 88 | 89 | ## --------------------------------- ## 90 | ## Macros to handle LT_INIT options. ## 91 | ## --------------------------------- ## 92 | 93 | # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) 94 | # ----------------------------------------- 95 | m4_define([_LT_MANGLE_DEFUN], 96 | [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) 97 | 98 | 99 | # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) 100 | # ----------------------------------------------- 101 | m4_define([LT_OPTION_DEFINE], 102 | [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl 103 | ])# LT_OPTION_DEFINE 104 | 105 | 106 | # dlopen 107 | # ------ 108 | LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes 109 | ]) 110 | 111 | AU_DEFUN([AC_LIBTOOL_DLOPEN], 112 | [_LT_SET_OPTION([LT_INIT], [dlopen]) 113 | AC_DIAGNOSE([obsolete], 114 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 115 | put the `dlopen' option into LT_INIT's first parameter.]) 116 | ]) 117 | 118 | dnl aclocal-1.4 backwards compatibility: 119 | dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) 120 | 121 | 122 | # win32-dll 123 | # --------- 124 | # Declare package support for building win32 dll's. 125 | LT_OPTION_DEFINE([LT_INIT], [win32-dll], 126 | [enable_win32_dll=yes 127 | 128 | case $host in 129 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) 130 | AC_CHECK_TOOL(AS, as, false) 131 | AC_CHECK_TOOL(DLLTOOL, dlltool, false) 132 | AC_CHECK_TOOL(OBJDUMP, objdump, false) 133 | ;; 134 | esac 135 | 136 | test -z "$AS" && AS=as 137 | _LT_DECL([], [AS], [1], [Assembler program])dnl 138 | 139 | test -z "$DLLTOOL" && DLLTOOL=dlltool 140 | _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl 141 | 142 | test -z "$OBJDUMP" && OBJDUMP=objdump 143 | _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl 144 | ])# win32-dll 145 | 146 | AU_DEFUN([AC_LIBTOOL_WIN32_DLL], 147 | [AC_REQUIRE([AC_CANONICAL_HOST])dnl 148 | _LT_SET_OPTION([LT_INIT], [win32-dll]) 149 | AC_DIAGNOSE([obsolete], 150 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 151 | put the `win32-dll' option into LT_INIT's first parameter.]) 152 | ]) 153 | 154 | dnl aclocal-1.4 backwards compatibility: 155 | dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) 156 | 157 | 158 | # _LT_ENABLE_SHARED([DEFAULT]) 159 | # ---------------------------- 160 | # implement the --enable-shared flag, and supports the `shared' and 161 | # `disable-shared' LT_INIT options. 162 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 163 | m4_define([_LT_ENABLE_SHARED], 164 | [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl 165 | AC_ARG_ENABLE([shared], 166 | [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], 167 | [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], 168 | [p=${PACKAGE-default} 169 | case $enableval in 170 | yes) enable_shared=yes ;; 171 | no) enable_shared=no ;; 172 | *) 173 | enable_shared=no 174 | # Look at the argument we got. We use all the common list separators. 175 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 176 | for pkg in $enableval; do 177 | IFS="$lt_save_ifs" 178 | if test "X$pkg" = "X$p"; then 179 | enable_shared=yes 180 | fi 181 | done 182 | IFS="$lt_save_ifs" 183 | ;; 184 | esac], 185 | [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) 186 | 187 | _LT_DECL([build_libtool_libs], [enable_shared], [0], 188 | [Whether or not to build shared libraries]) 189 | ])# _LT_ENABLE_SHARED 190 | 191 | LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) 192 | LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) 193 | 194 | # Old names: 195 | AC_DEFUN([AC_ENABLE_SHARED], 196 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) 197 | ]) 198 | 199 | AC_DEFUN([AC_DISABLE_SHARED], 200 | [_LT_SET_OPTION([LT_INIT], [disable-shared]) 201 | ]) 202 | 203 | AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) 204 | AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) 205 | 206 | dnl aclocal-1.4 backwards compatibility: 207 | dnl AC_DEFUN([AM_ENABLE_SHARED], []) 208 | dnl AC_DEFUN([AM_DISABLE_SHARED], []) 209 | 210 | 211 | 212 | # _LT_ENABLE_STATIC([DEFAULT]) 213 | # ---------------------------- 214 | # implement the --enable-static flag, and support the `static' and 215 | # `disable-static' LT_INIT options. 216 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 217 | m4_define([_LT_ENABLE_STATIC], 218 | [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl 219 | AC_ARG_ENABLE([static], 220 | [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], 221 | [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], 222 | [p=${PACKAGE-default} 223 | case $enableval in 224 | yes) enable_static=yes ;; 225 | no) enable_static=no ;; 226 | *) 227 | enable_static=no 228 | # Look at the argument we got. We use all the common list separators. 229 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 230 | for pkg in $enableval; do 231 | IFS="$lt_save_ifs" 232 | if test "X$pkg" = "X$p"; then 233 | enable_static=yes 234 | fi 235 | done 236 | IFS="$lt_save_ifs" 237 | ;; 238 | esac], 239 | [enable_static=]_LT_ENABLE_STATIC_DEFAULT) 240 | 241 | _LT_DECL([build_old_libs], [enable_static], [0], 242 | [Whether or not to build static libraries]) 243 | ])# _LT_ENABLE_STATIC 244 | 245 | LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) 246 | LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) 247 | 248 | # Old names: 249 | AC_DEFUN([AC_ENABLE_STATIC], 250 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) 251 | ]) 252 | 253 | AC_DEFUN([AC_DISABLE_STATIC], 254 | [_LT_SET_OPTION([LT_INIT], [disable-static]) 255 | ]) 256 | 257 | AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) 258 | AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) 259 | 260 | dnl aclocal-1.4 backwards compatibility: 261 | dnl AC_DEFUN([AM_ENABLE_STATIC], []) 262 | dnl AC_DEFUN([AM_DISABLE_STATIC], []) 263 | 264 | 265 | 266 | # _LT_ENABLE_FAST_INSTALL([DEFAULT]) 267 | # ---------------------------------- 268 | # implement the --enable-fast-install flag, and support the `fast-install' 269 | # and `disable-fast-install' LT_INIT options. 270 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 271 | m4_define([_LT_ENABLE_FAST_INSTALL], 272 | [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl 273 | AC_ARG_ENABLE([fast-install], 274 | [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], 275 | [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], 276 | [p=${PACKAGE-default} 277 | case $enableval in 278 | yes) enable_fast_install=yes ;; 279 | no) enable_fast_install=no ;; 280 | *) 281 | enable_fast_install=no 282 | # Look at the argument we got. We use all the common list separators. 283 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 284 | for pkg in $enableval; do 285 | IFS="$lt_save_ifs" 286 | if test "X$pkg" = "X$p"; then 287 | enable_fast_install=yes 288 | fi 289 | done 290 | IFS="$lt_save_ifs" 291 | ;; 292 | esac], 293 | [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) 294 | 295 | _LT_DECL([fast_install], [enable_fast_install], [0], 296 | [Whether or not to optimize for fast installation])dnl 297 | ])# _LT_ENABLE_FAST_INSTALL 298 | 299 | LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) 300 | LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) 301 | 302 | # Old names: 303 | AU_DEFUN([AC_ENABLE_FAST_INSTALL], 304 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) 305 | AC_DIAGNOSE([obsolete], 306 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 307 | the `fast-install' option into LT_INIT's first parameter.]) 308 | ]) 309 | 310 | AU_DEFUN([AC_DISABLE_FAST_INSTALL], 311 | [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) 312 | AC_DIAGNOSE([obsolete], 313 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 314 | the `disable-fast-install' option into LT_INIT's first parameter.]) 315 | ]) 316 | 317 | dnl aclocal-1.4 backwards compatibility: 318 | dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) 319 | dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) 320 | 321 | 322 | # _LT_WITH_PIC([MODE]) 323 | # -------------------- 324 | # implement the --with-pic flag, and support the `pic-only' and `no-pic' 325 | # LT_INIT options. 326 | # MODE is either `yes' or `no'. If omitted, it defaults to `both'. 327 | m4_define([_LT_WITH_PIC], 328 | [AC_ARG_WITH([pic], 329 | [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], 330 | [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], 331 | [lt_p=${PACKAGE-default} 332 | case $withval in 333 | yes|no) pic_mode=$withval ;; 334 | *) 335 | pic_mode=default 336 | # Look at the argument we got. We use all the common list separators. 337 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 338 | for lt_pkg in $withval; do 339 | IFS="$lt_save_ifs" 340 | if test "X$lt_pkg" = "X$lt_p"; then 341 | pic_mode=yes 342 | fi 343 | done 344 | IFS="$lt_save_ifs" 345 | ;; 346 | esac], 347 | [pic_mode=default]) 348 | 349 | test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) 350 | 351 | _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl 352 | ])# _LT_WITH_PIC 353 | 354 | LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) 355 | LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) 356 | 357 | # Old name: 358 | AU_DEFUN([AC_LIBTOOL_PICMODE], 359 | [_LT_SET_OPTION([LT_INIT], [pic-only]) 360 | AC_DIAGNOSE([obsolete], 361 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 362 | put the `pic-only' option into LT_INIT's first parameter.]) 363 | ]) 364 | 365 | dnl aclocal-1.4 backwards compatibility: 366 | dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) 367 | 368 | ## ----------------- ## 369 | ## LTDL_INIT Options ## 370 | ## ----------------- ## 371 | 372 | m4_define([_LTDL_MODE], []) 373 | LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], 374 | [m4_define([_LTDL_MODE], [nonrecursive])]) 375 | LT_OPTION_DEFINE([LTDL_INIT], [recursive], 376 | [m4_define([_LTDL_MODE], [recursive])]) 377 | LT_OPTION_DEFINE([LTDL_INIT], [subproject], 378 | [m4_define([_LTDL_MODE], [subproject])]) 379 | 380 | m4_define([_LTDL_TYPE], []) 381 | LT_OPTION_DEFINE([LTDL_INIT], [installable], 382 | [m4_define([_LTDL_TYPE], [installable])]) 383 | LT_OPTION_DEFINE([LTDL_INIT], [convenience], 384 | [m4_define([_LTDL_TYPE], [convenience])]) 385 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # autogen.sh 3 | # Copyright (C) 2003, 2014 g10 Code GmbH 4 | # 5 | # This file is free software; as a special exception the author gives 6 | # unlimited permission to copy and/or distribute it, with or without 7 | # modifications, as long as this notice is preserved. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 11 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | # 13 | # This is a generic script to create the configure script and handle cross 14 | # build environments. It requires the presence of a autogen.rc file to 15 | # configure it for the respective package. It is maintained as part of 16 | # GnuPG and source copied by other packages. 17 | # 18 | # Version: 2014-06-06 19 | 20 | configure_ac="configure.ac" 21 | 22 | cvtver () { 23 | awk 'NR==1 {split($NF,A,".");X=1000000*A[1]+1000*A[2]+A[3];print X;exit 0}' 24 | } 25 | 26 | check_version () { 27 | if [ $(( `("$1" --version || echo "0") | cvtver` >= $2 )) = 1 ]; then 28 | return 0 29 | fi 30 | echo "**Error**: "\`$1\'" not installed or too old." >&2 31 | echo ' Version '$3' or newer is required.' >&2 32 | [ -n "$4" ] && echo ' Note that this is part of '\`$4\''.' >&2 33 | DIE="yes" 34 | return 1 35 | } 36 | 37 | fatal () { 38 | echo "autogen.sh:" "$*" >&2 39 | DIE=yes 40 | } 41 | 42 | info () { 43 | if [ -z "${SILENT}" ]; then 44 | echo "autogen.sh:" "$*" >&2 45 | fi 46 | } 47 | 48 | die_p () { 49 | if [ "$DIE" = "yes" ]; then 50 | echo "autogen.sh: Stop." >&2 51 | exit 1 52 | fi 53 | } 54 | 55 | replace_sysroot () { 56 | configure_opts=$(echo $configure_opts | sed "s#@SYSROOT@#${w32root}#g") 57 | extraoptions=$(echo $extraoptions | sed "s#@SYSROOT@#${w32root}#g") 58 | } 59 | 60 | # Allow to override the default tool names 61 | AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX} 62 | AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX} 63 | 64 | AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX} 65 | ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} 66 | 67 | GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX} 68 | MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} 69 | 70 | DIE=no 71 | FORCE= 72 | SILENT= 73 | PRINT_HOST=no 74 | PRINT_BUILD=no 75 | tmp=$(dirname "$0") 76 | tsdir=$(cd "${tmp}"; pwd) 77 | version_parts=3 78 | 79 | if [ -n "${AUTOGEN_SH_SILENT}" ]; then 80 | SILENT=" --silent" 81 | fi 82 | if test x"$1" = x"--help"; then 83 | echo "usage: ./autogen.sh [--silent] [--force] [--build-TYPE] [ARGS]" 84 | exit 0 85 | fi 86 | if test x"$1" = x"--silent"; then 87 | SILENT=" --silent" 88 | shift 89 | fi 90 | if test x"$1" = x"--force"; then 91 | FORCE=" --force" 92 | shift 93 | fi 94 | if test x"$1" = x"--print-host"; then 95 | PRINT_HOST=yes 96 | shift 97 | fi 98 | if test x"$1" = x"--print-build"; then 99 | PRINT_BUILD=yes 100 | shift 101 | fi 102 | 103 | 104 | # Reject unsafe characters in $HOME, $tsdir and cwd. We consider spaces 105 | # as unsafe because it is too easy to get scripts wrong in this regard. 106 | am_lf=' 107 | ' 108 | case `pwd` in 109 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 110 | fatal "unsafe working directory name" ;; 111 | esac 112 | case $tsdir in 113 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 114 | fatal "unsafe source directory: \`$tsdir'" ;; 115 | esac 116 | case $HOME in 117 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 118 | fatal "unsafe home directory: \`$HOME'" ;; 119 | esac 120 | die_p 121 | 122 | 123 | # List of variables sourced from autogen.rc. The strings '@SYSROOT@' in 124 | # these variables are replaced by the actual system root. 125 | configure_opts= 126 | extraoptions= 127 | # List of optional variables sourced from autogen.rc and ~/.gnupg-autogen.rc 128 | w32_toolprefixes= 129 | w32_extraoptions= 130 | w32ce_toolprefixes= 131 | w32ce_extraoptions= 132 | w64_toolprefixes= 133 | w64_extraoptions= 134 | amd64_toolprefixes= 135 | # End list of optional variables sourced from ~/.gnupg-autogen.rc 136 | # What follows are variables which are sourced but default to 137 | # environment variables or lacking them hardcoded values. 138 | #w32root= 139 | #w32ce_root= 140 | #w64root= 141 | #amd64root= 142 | 143 | # Convenience option to use certain configure options for some hosts. 144 | myhost="" 145 | myhostsub="" 146 | case "$1" in 147 | --find-version) 148 | myhost="find-version" 149 | SILENT=" --silent" 150 | shift 151 | ;; 152 | --build-w32) 153 | myhost="w32" 154 | shift 155 | ;; 156 | --build-w32ce) 157 | myhost="w32" 158 | myhostsub="ce" 159 | shift 160 | ;; 161 | --build-w64) 162 | myhost="w32" 163 | myhostsub="64" 164 | shift 165 | ;; 166 | --build-amd64) 167 | myhost="amd64" 168 | shift 169 | ;; 170 | --build*) 171 | fatal "**Error**: invalid build option $1" 172 | shift 173 | ;; 174 | *) 175 | ;; 176 | esac 177 | die_p 178 | 179 | 180 | # Source our configuration 181 | if [ -f "${tsdir}/autogen.rc" ]; then 182 | . "${tsdir}/autogen.rc" 183 | fi 184 | 185 | # Source optional site specific configuration 186 | if [ -f "$HOME/.gnupg-autogen.rc" ]; then 187 | info "sourcing extra definitions from $HOME/.gnupg-autogen.rc" 188 | . "$HOME/.gnupg-autogen.rc" 189 | fi 190 | 191 | 192 | # **** FIND VERSION **** 193 | # This is a helper for the configure.ac M4 magic 194 | # Called 195 | # ./autogen.sh --find-version PACKAGE MAJOR MINOR [MICRO] 196 | # returns a complete version string with automatic beta numbering. 197 | if [ "$myhost" = "find-version" ]; then 198 | package="$1" 199 | major="$2" 200 | minor="$3" 201 | micro="$4" 202 | 203 | case "$version_parts" in 204 | 2) 205 | matchstr1="$package-$major.[0-9]*" 206 | matchstr2="$package-$major-base" 207 | vers="$major.$minor" 208 | ;; 209 | *) 210 | matchstr1="$package-$major.$minor.[0-9]*" 211 | matchstr2="$package-$major.$minor-base" 212 | vers="$major.$minor.$micro" 213 | ;; 214 | esac 215 | 216 | beta=no 217 | if [ -d .git ]; then 218 | ingit=yes 219 | tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null) 220 | if [ -n "$tmp" ]; then 221 | tmp=$(echo "$tmp"|awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}') 222 | else 223 | tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null \ 224 | | awk -F- '$4!=0{print"-beta"$4}') 225 | fi 226 | [ -n "$tmp" ] && beta=yes 227 | rev=$(git rev-parse --short HEAD | tr -d '\n\r') 228 | rvd=$((0x$(echo ${rev} | head -c 4))) 229 | else 230 | ingit=no 231 | beta=yes 232 | tmp="-unknown" 233 | rev="0000000" 234 | rvd="0" 235 | fi 236 | 237 | echo "$package-$vers$tmp:$beta:$ingit:$vers$tmp:$vers:$tmp:$rev:$rvd:" 238 | exit 0 239 | fi 240 | # **** end FIND VERSION **** 241 | 242 | 243 | if [ ! -f "$tsdir/build-aux/config.guess" ]; then 244 | fatal "$tsdir/build-aux/config.guess not found" 245 | exit 1 246 | fi 247 | build=`$tsdir/build-aux/config.guess` 248 | if [ $PRINT_BUILD = yes ]; then 249 | echo "$build" 250 | exit 0 251 | fi 252 | 253 | 254 | 255 | # ****************** 256 | # W32 build script 257 | # ****************** 258 | if [ "$myhost" = "w32" ]; then 259 | case $myhostsub in 260 | ce) 261 | w32root="$w32ce_root" 262 | [ -z "$w32root" ] && w32root="$HOME/w32ce_root" 263 | toolprefixes="$w32ce_toolprefixes arm-mingw32ce" 264 | extraoptions="$extraoptions $w32ce_extraoptions" 265 | ;; 266 | 64) 267 | w32root="$w64root" 268 | [ -z "$w32root" ] && w32root="$HOME/w64root" 269 | toolprefixes="$w64_toolprefixes x86_64-w64-mingw32" 270 | extraoptions="$extraoptions $w64_extraoptions" 271 | ;; 272 | *) 273 | [ -z "$w32root" ] && w32root="$HOME/w32root" 274 | toolprefixes="$w32_toolprefixes i686-w64-mingw32 i586-mingw32msvc" 275 | toolprefixes="$toolprefixes i386-mingw32msvc mingw32" 276 | extraoptions="$extraoptions $w32_extraoptions" 277 | ;; 278 | esac 279 | info "Using $w32root as standard install directory" 280 | replace_sysroot 281 | 282 | # Locate the cross compiler 283 | crossbindir= 284 | for host in $toolprefixes; do 285 | if ${host}-gcc --version >/dev/null 2>&1 ; then 286 | crossbindir=/usr/${host}/bin 287 | conf_CC="CC=${host}-gcc" 288 | break; 289 | fi 290 | done 291 | if [ -z "$crossbindir" ]; then 292 | fatal "cross compiler kit not installed" 293 | if [ -z "$myhostsub" ]; then 294 | info "Under Debian GNU/Linux, you may install it using" 295 | info " apt-get install mingw32 mingw32-runtime mingw32-binutils" 296 | fi 297 | die_p 298 | fi 299 | if [ $PRINT_HOST = yes ]; then 300 | echo "$host" 301 | exit 0 302 | fi 303 | 304 | if [ -f "$tsdir/config.log" ]; then 305 | if ! head $tsdir/config.log | grep "$host" >/dev/null; then 306 | fatal "Please run a 'make distclean' first" 307 | die_p 308 | fi 309 | fi 310 | 311 | $tsdir/configure --enable-maintainer-mode ${SILENT} \ 312 | --prefix=${w32root} \ 313 | --host=${host} --build=${build} SYSROOT=${w32root} \ 314 | PKG_CONFIG_LIBDIR=${w32root} \ 315 | ${configure_opts} ${extraoptions} "$@" 316 | rc=$? 317 | exit $rc 318 | fi 319 | # ***** end W32 build script ******* 320 | 321 | # ***** AMD64 cross build script ******* 322 | # Used to cross-compile for AMD64 (for testing) 323 | if [ "$myhost" = "amd64" ]; then 324 | [ -z "$amd64root" ] && amd64root="$HOME/amd64root" 325 | info "Using $amd64root as standard install directory" 326 | replace_sysroot 327 | 328 | toolprefixes="$amd64_toolprefixes x86_64-linux-gnu amd64-linux-gnu" 329 | 330 | # Locate the cross compiler 331 | crossbindir= 332 | for host in $toolprefixes ; do 333 | if ${host}-gcc --version >/dev/null 2>&1 ; then 334 | crossbindir=/usr/${host}/bin 335 | conf_CC="CC=${host}-gcc" 336 | break; 337 | fi 338 | done 339 | if [ -z "$crossbindir" ]; then 340 | echo "Cross compiler kit not installed" >&2 341 | echo "Stop." >&2 342 | exit 1 343 | fi 344 | if [ $PRINT_HOST = yes ]; then 345 | echo "$host" 346 | exit 0 347 | fi 348 | 349 | if [ -f "$tsdir/config.log" ]; then 350 | if ! head $tsdir/config.log | grep "$host" >/dev/null; then 351 | echo "Please run a 'make distclean' first" >&2 352 | exit 1 353 | fi 354 | fi 355 | 356 | $tsdir/configure --enable-maintainer-mode ${SILENT} \ 357 | --prefix=${amd64root} \ 358 | --host=${host} --build=${build} \ 359 | ${configure_opts} ${extraoptions} "$@" 360 | rc=$? 361 | exit $rc 362 | fi 363 | # ***** end AMD64 cross build script ******* 364 | 365 | 366 | # Grep the required versions from configure.ac 367 | autoconf_vers=`sed -n '/^AC_PREREQ(/ { 368 | s/^.*(\(.*\))/\1/p 369 | q 370 | }' ${configure_ac}` 371 | autoconf_vers_num=`echo "$autoconf_vers" | cvtver` 372 | 373 | automake_vers=`sed -n '/^min_automake_version=/ { 374 | s/^.*="\(.*\)"/\1/p 375 | q 376 | }' ${configure_ac}` 377 | automake_vers_num=`echo "$automake_vers" | cvtver` 378 | 379 | if [ -d "${tsdir}/po" ]; then 380 | gettext_vers=`sed -n '/^AM_GNU_GETTEXT_VERSION(/ { 381 | s/^.*\[\(.*\)])/\1/p 382 | q 383 | }' ${configure_ac}` 384 | gettext_vers_num=`echo "$gettext_vers" | cvtver` 385 | else 386 | gettext_vers="n/a" 387 | fi 388 | 389 | if [ -z "$autoconf_vers" -o -z "$automake_vers" -o -z "$gettext_vers" ] 390 | then 391 | echo "**Error**: version information not found in "\`${configure_ac}\'"." >&2 392 | exit 1 393 | fi 394 | 395 | 396 | if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then 397 | check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf 398 | fi 399 | if check_version $AUTOMAKE $automake_vers_num $automake_vers; then 400 | check_version $ACLOCAL $automake_vers_num $autoconf_vers automake 401 | fi 402 | if [ "$gettext_vers" != "n/a" ]; then 403 | if check_version $GETTEXT $gettext_vers_num $gettext_vers; then 404 | check_version $MSGMERGE $gettext_vers_num $gettext_vers gettext 405 | fi 406 | fi 407 | 408 | if [ "$DIE" = "yes" ]; then 409 | cat < 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "tgpgdefs.h" 31 | #include "cryptglue.h" 32 | 33 | /* The size of the buffer we allocate for hash contexts. */ 34 | #define HASH_BUFFERSIZE 1024 35 | 36 | 37 | 38 | /* Map gpg-error codes to tgpg error codes. */ 39 | static int 40 | maperr (gpg_error_t err) 41 | { 42 | return err? TGPG_CRYPT_ERR : 0; 43 | } 44 | 45 | 46 | 47 | 48 | /* 49 | 50 | P U B K E Y F u n c t i o n s 51 | 52 | */ 53 | 54 | /* Return the number of parameters required to encrypt using the 55 | public key algorithm with ALGO. ALGO is of course an OpenPGP id. 56 | The function returns 0 for not supported algorithms. */ 57 | unsigned int 58 | _tgpg_pk_get_nenc (int algo) 59 | { 60 | switch (algo) 61 | { 62 | case PK_ALGO_RSA: return 1; 63 | case PK_ALGO_ELG: return 2; 64 | default: return 0; 65 | } 66 | } 67 | 68 | /* Return the number of parameters required to sign using the 69 | public key algorithm with ALGO. ALGO is of course an OpenPGP id. 70 | The function returns 0 for not supported algorithms. */ 71 | unsigned int 72 | _tgpg_pk_get_nsig (int algo) 73 | { 74 | switch (algo) 75 | { 76 | case PK_ALGO_RSA: return 1; 77 | case PK_ALGO_DSA: return 2; 78 | default: return 0; 79 | } 80 | } 81 | 82 | 83 | 84 | /* Run a decrypt operation on the data in ENCDAT using the provided key 85 | SECKEY and algorithm ALGO. On success the result is stored as a 86 | new allocated buffer at the address R_PLAN and its length at 87 | R_PLAINLEN. On error PLAIN and R_PLAINLEN are set to NULL/0.*/ 88 | int 89 | _tgpg_pk_decrypt (int algo, tgpg_mpi_t seckey, tgpg_mpi_t encdat, 90 | char **r_plain, size_t *r_plainlen) 91 | { 92 | int rc; 93 | gcry_sexp_t s_plain, s_data, s_key; 94 | const char *result; 95 | size_t resultlen; 96 | 97 | *r_plain = NULL; 98 | *r_plainlen = 0; 99 | 100 | if (algo == PK_ALGO_RSA) 101 | { 102 | rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%b)))", 103 | (int)encdat[0].valuelen, encdat[0].value); 104 | if (rc) 105 | return TGPG_INV_DATA; 106 | 107 | rc = gcry_sexp_build (&s_key, NULL, 108 | "(private-key(rsa(n%b)(e%b)(d%b)(p%b)(q%b)(u%b)))", 109 | (int)seckey[0].valuelen, seckey[0].value, 110 | (int)seckey[1].valuelen, seckey[1].value, 111 | (int)seckey[2].valuelen, seckey[2].value, 112 | (int)seckey[3].valuelen, seckey[3].value, 113 | (int)seckey[4].valuelen, seckey[4].value, 114 | (int)seckey[5].valuelen, seckey[5].value); 115 | if (rc) 116 | { 117 | gcry_sexp_release (s_data); 118 | return TGPG_INV_DATA; 119 | } 120 | } 121 | else 122 | return TGPG_INV_ALGO; 123 | 124 | rc = gcry_pk_decrypt (&s_plain, s_data, s_key); 125 | gcry_sexp_release (s_data); 126 | gcry_sexp_release (s_key); 127 | if (rc) 128 | return TGPG_CRYPT_ERR; 129 | 130 | result = gcry_sexp_nth_data (s_plain, 0, &resultlen); 131 | if (!result || !resultlen) 132 | { 133 | gcry_sexp_release (s_plain); 134 | return TGPG_CRYPT_ERR; 135 | } 136 | 137 | *r_plain = xtrymalloc (resultlen); 138 | if (!*r_plain) 139 | { 140 | gcry_sexp_release (s_plain); 141 | return TGPG_SYSERROR; 142 | } 143 | 144 | memcpy (*r_plain, result, resultlen); 145 | *r_plainlen = resultlen; 146 | gcry_sexp_release (s_plain); 147 | return rc; 148 | } 149 | 150 | 151 | /* Run an encrypt operation on PLAIN of length PLAINLEN using the 152 | algorithm ALGO and key PUBKEY. On success, the result is stored in 153 | an allocated array R_ENCDAT with R_ENCLEN elements. */ 154 | int 155 | _tgpg_pk_encrypt (int algo, tgpg_mpi_t pubkey, 156 | char *plain, size_t plainlen, 157 | tgpg_mpi_t *r_encdat, size_t *r_enclen) 158 | { 159 | int rc; 160 | int i; 161 | gcry_sexp_t s_plain, s_key, s_cipher, s_list; 162 | 163 | switch (algo) 164 | { 165 | case PK_ALGO_RSA: 166 | rc = gcry_sexp_build (&s_plain, NULL, 167 | "(data(flags)(value%b))", 168 | (int) plainlen, plain); 169 | if (rc) 170 | return TGPG_INV_DATA; 171 | 172 | rc = gcry_sexp_build (&s_key, NULL, 173 | "(public-key(rsa(n%b)(e%b)))", 174 | (int) pubkey[0].valuelen, pubkey[0].value, 175 | (int) pubkey[1].valuelen, pubkey[1].value); 176 | if (rc) 177 | { 178 | gcry_sexp_release (s_plain); 179 | return TGPG_INV_DATA; 180 | } 181 | break; 182 | 183 | default: 184 | return TGPG_INV_ALGO; 185 | } 186 | 187 | rc = gcry_pk_encrypt (&s_cipher, s_plain, s_key); 188 | gcry_sexp_release (s_plain); 189 | gcry_sexp_release (s_key); 190 | if (rc) 191 | { 192 | rc = TGPG_CRYPT_ERR; 193 | goto leave; 194 | } 195 | 196 | *r_enclen = _tgpg_pk_get_nenc (algo); 197 | *r_encdat = xtrymalloc (*r_enclen * sizeof **r_encdat); 198 | if (r_encdat == NULL) 199 | { 200 | rc = TGPG_SYSERROR; 201 | goto leave; 202 | } 203 | 204 | for (i = 0; i < *r_enclen; i++) 205 | { 206 | const char *keys = "ab"; 207 | tgpg_mpi_t r = &(*r_encdat)[i]; 208 | 209 | s_list = gcry_sexp_find_token (s_cipher, &keys[i], 1); 210 | 211 | errno = 0; 212 | r->value = 213 | gcry_sexp_nth_buffer (s_list, 1, &r->valuelen); 214 | if (r->value == NULL) 215 | { 216 | rc = errno != 0 ? TGPG_SYSERROR : TGPG_BUG; 217 | goto leave; 218 | } 219 | 220 | r->nbits = r->valuelen << 3; 221 | gcry_sexp_release (s_list); 222 | } 223 | 224 | leave: 225 | gcry_sexp_release (s_cipher); 226 | return rc; 227 | } 228 | 229 | 230 | /* 231 | 232 | C I P H E R F u n c t i o n s 233 | 234 | */ 235 | 236 | /* Return the block length in bytes of the cipher ALGO. */ 237 | unsigned int 238 | _tgpg_cipher_blocklen (int algo) 239 | { 240 | return gcry_cipher_get_algo_blklen (algo); 241 | } 242 | 243 | 244 | /* Return the key length in bytes of the cipher ALGO. */ 245 | unsigned int 246 | _tgpg_cipher_keylen (int algo) 247 | { 248 | return gcry_cipher_get_algo_keylen (algo); 249 | } 250 | 251 | 252 | /* Core of the en- and decrypt functions. With DO_ENCRYPT true an 253 | encryption is done, otherwise it will decrypt. */ 254 | static int 255 | cipher_endecrypt (int do_encrypt, 256 | int algo, enum cipher_modes mode, 257 | const void *key, size_t keylen, 258 | const void *iv, size_t ivlen, 259 | char *prefix, size_t prefixlen, 260 | void *outbuf, size_t outbufsize, 261 | const void * inbuf, size_t inbuflen) 262 | { 263 | gpg_error_t err; 264 | int flags = 0; 265 | int pgp_cipher_init = 0; 266 | gcry_cipher_hd_t hd; 267 | size_t bs = _tgpg_cipher_blocklen (algo); 268 | 269 | switch (mode) 270 | { 271 | case CIPHER_MODE_CBC: mode = GCRY_CIPHER_MODE_CBC; break; 272 | case CIPHER_MODE_CFB: mode = GCRY_CIPHER_MODE_CFB; break; 273 | case CIPHER_MODE_CFB_PGP: 274 | flags |= GCRY_CIPHER_ENABLE_SYNC; 275 | /* Fallthrough. */ 276 | case CIPHER_MODE_CFB_MDC: 277 | mode = GCRY_CIPHER_MODE_CFB; 278 | pgp_cipher_init = 1; 279 | if (prefixlen != bs + 2) 280 | return TGPG_BUG; 281 | break; 282 | default: return TGPG_BUG; 283 | } 284 | 285 | err = gcry_cipher_open (&hd, algo, mode, flags); 286 | if (err) 287 | goto leave; 288 | err = gcry_cipher_setkey (hd, key, keylen); 289 | if (err) 290 | goto leave; 291 | err = gcry_cipher_setiv (hd, iv, ivlen); 292 | if (err) 293 | goto leave; 294 | 295 | /* Handle cipher initialization and re-synchronization. */ 296 | if (pgp_cipher_init) 297 | { 298 | if (do_encrypt) 299 | { 300 | /* Check that the last two octets are repeated. */ 301 | if (prefix[bs-2] != prefix[bs] || prefix[bs-1] != prefix[bs+1]) 302 | { 303 | err = TGPG_BUG; 304 | goto leave; 305 | } 306 | 307 | err = gcry_cipher_encrypt (hd, outbuf, outbufsize, 308 | prefix, prefixlen); 309 | outbuf += prefixlen, outbufsize -= prefixlen; 310 | } 311 | else 312 | { 313 | err = gcry_cipher_decrypt (hd, prefix, prefixlen, 314 | inbuf, prefixlen); 315 | if (err) 316 | goto leave; 317 | inbuf += prefixlen, inbuflen -= prefixlen; 318 | 319 | /* The last two octets are repeated. */ 320 | if (prefix[bs-2] != prefix[bs] || prefix[bs-1] != prefix[bs+1]) 321 | err = TGPG_WRONG_KEY; 322 | } 323 | if (err) 324 | goto leave; 325 | 326 | err = gcry_cipher_sync (hd); 327 | if (err) 328 | goto leave; 329 | } 330 | 331 | err = \ 332 | (do_encrypt ? gcry_cipher_encrypt : gcry_cipher_decrypt) \ 333 | (hd, outbuf, outbufsize, inbuf, inbuflen); 334 | 335 | leave: 336 | gcry_cipher_close (hd); 337 | return maperr (err); 338 | } 339 | 340 | /* Decrypt the data at INBUF of length INBUFLEN and write them to the 341 | caller provided OUTBUF which has a length of OUTBUFSIZE. ALGO is 342 | the algorithm to use, MODE, the encryption modus, KEY and KEYLEN 343 | describes the key and IV and IVLEN the IV. Returns an error 344 | code. */ 345 | int 346 | _tgpg_cipher_decrypt (int algo, enum cipher_modes mode, 347 | const void *key, size_t keylen, 348 | const void *iv, size_t ivlen, 349 | char *prefix, size_t prefixlen, 350 | void *outbuf, size_t outbufsize, 351 | const void * inbuf, size_t inbuflen) 352 | { 353 | return cipher_endecrypt (0, algo, mode, key, keylen, iv, ivlen, 354 | prefix, prefixlen, 355 | outbuf, outbufsize, inbuf, inbuflen); 356 | } 357 | 358 | /* Encrypt the data at INBUF of length INBUFLEN and write them to the 359 | caller provided OUTBUF which has a length of OUTBUFSIZE. ALGO is 360 | the algorithm to use, MODE, the encryption modus, KEY and KEYLEN 361 | describes the key and IV and IVLEN the IV. Returns an error 362 | code. */ 363 | int 364 | _tgpg_cipher_encrypt (int algo, enum cipher_modes mode, 365 | const void *key, size_t keylen, 366 | const void *iv, size_t ivlen, 367 | char *prefix, size_t prefixlen, 368 | void *outbuf, size_t outbufsize, 369 | const void *inbuf, size_t inbuflen) 370 | { 371 | return cipher_endecrypt (1, algo, mode, key, keylen, iv, ivlen, 372 | prefix, prefixlen, 373 | outbuf, outbufsize, inbuf, inbuflen); 374 | } 375 | 376 | 377 | 378 | 379 | /* 380 | 381 | H A S H F u n c t i o n s 382 | 383 | */ 384 | 385 | /* Hash LENGTH bytes of BUFFER using the hash algorithm ALGO and put 386 | the result into the caller provided buffer DIGEST. DIGEST must be 387 | allocated large enough to hold the entire digest. DIGESTLEN is only 388 | used for cross-checking. */ 389 | void 390 | _tgpg_hash_buffer (int algo, unsigned char *digest, size_t digestlen, 391 | const void *buffer, size_t length) 392 | { 393 | gcry_md_hash_buffer (algo, digest, buffer, length); 394 | } 395 | 396 | 397 | /* Create a new context for hash operations using the hash algorithm 398 | ALGO. On success a new handle is return at RCTX and the return 399 | value will be 0; on error NULL is stored at RCTX and an error code 400 | is returned. The caller needs to release the context after use by 401 | calling _tgpg_hash_close. */ 402 | int 403 | _tgpg_hash_open (hash_t *rctx, int algo, unsigned int flags) 404 | { 405 | gpg_error_t err; 406 | gcry_md_hd_t hd; 407 | hash_t ctx; 408 | 409 | *rctx = NULL; 410 | 411 | err = gcry_md_open (&hd, algo, 412 | (flags & HASH_FLAG_SECURE)? GCRY_MD_FLAG_SECURE : 0); 413 | if (err) 414 | return maperr (err); 415 | ctx = xtrymalloc (sizeof *ctx - 1 + HASH_BUFFERSIZE); 416 | if (!ctx) 417 | { 418 | int tmperr = errno; 419 | gcry_md_close (hd); 420 | errno = tmperr; 421 | return TGPG_SYSERROR; 422 | } 423 | ctx->handle = hd; 424 | ctx->secure = !!(flags & HASH_FLAG_SECURE); 425 | ctx->digestlen = gcry_md_get_algo_dlen (algo); 426 | ctx->buffersize = HASH_BUFFERSIZE; 427 | ctx->bufferpos = 0; 428 | 429 | *rctx = ctx; 430 | return 0; 431 | } 432 | 433 | 434 | /* Close the hash context CTX. Passing NULL is a nop. */ 435 | void 436 | _tgpg_hash_close (hash_t ctx) 437 | { 438 | if (ctx) 439 | { 440 | gcry_md_hd_t hd = ctx->handle; 441 | 442 | gcry_md_close (hd); 443 | if (ctx->secure) 444 | wipememory (ctx->buffer, ctx->buffersize); 445 | xfree (ctx); 446 | } 447 | } 448 | 449 | /* Reset the hash context and discard any buffered stuff. This may be 450 | used instead of a close, open sequence if retaining the same 451 | context is desired. */ 452 | void 453 | _tgpg_hash_reset (hash_t ctx) 454 | { 455 | gcry_md_hd_t hd = ctx->handle; 456 | 457 | gcry_md_reset (hd); 458 | ctx->bufferpos = 0; 459 | 460 | } 461 | 462 | /* Hash LENGTH bytes from BUFFER into the hash context CTX. */ 463 | void 464 | _tgpg_hash_write (hash_t ctx, const void *buffer, size_t length) 465 | { 466 | gcry_md_hd_t hd = ctx->handle; 467 | 468 | if (ctx->bufferpos) 469 | { 470 | gcry_md_write (hd, ctx->buffer, ctx->bufferpos); 471 | ctx->bufferpos = 0; 472 | } 473 | if (buffer && length) 474 | gcry_md_write (hd, buffer, length); 475 | } 476 | 477 | /* Finalize the hash digest and return it. The returned value is 478 | valid as long as the context is valid and no hash_reset has been 479 | used. The length of the hash may be determined by using the 480 | hash_digestlen macro. */ 481 | const void * 482 | _tgpg_hash_read (hash_t ctx) 483 | { 484 | gcry_md_hd_t hd = ctx->handle; 485 | 486 | return gcry_md_read (hd, 0); 487 | } 488 | 489 | void 490 | _tgpg_randomize (unsigned char *buffer, size_t length) 491 | { 492 | gcry_randomize (buffer, length, GCRY_STRONG_RANDOM); 493 | } 494 | -------------------------------------------------------------------------------- /src/protect.c: -------------------------------------------------------------------------------- 1 | /* protect.c - Un/Protect a secret key 2 | Copyright (C) 2002, 2007 g10 Code GmbH 3 | 4 | This file is part of TGPG. 5 | 6 | TGPG is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | TPGP is distributed in the hope that it will be useful, but WITHOUT 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 | License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | MA 02110-1301, USA. 20 | 21 | 22 | Note: This code has originally been written for NewPG and then in 23 | turn integrated into GnuPG 1.9. It has entirely been written by 24 | g10 Code staff. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "tgpgdefs.h" 33 | #include "s2k.h" 34 | #include "cryptglue.h" 35 | #include "protect.h" 36 | 37 | #define PROT_CIPHER CIPHER_ALGO_AES 38 | #define PROT_CIPHER_STRING "aes" 39 | #define PROT_CIPHER_KEYLEN (128/8) 40 | 41 | 42 | /* A table containing the information needed to create a protected 43 | private key */ 44 | static struct 45 | { 46 | const char *algo; 47 | const char *parmlist; 48 | int prot_from, prot_to; 49 | } protect_info[] = { 50 | { "rsa", "nedpqu", 2, 5 }, 51 | { "dsa", "pqgyx", 4, 4 }, 52 | { "elg", "pgyx", 3, 3 }, 53 | { NULL } 54 | }; 55 | 56 | 57 | /* Return the length of the next canonical S-expression part and 58 | update the pointer to the first data byte. 0 is returned on 59 | error. */ 60 | static size_t 61 | snext (unsigned char const **buf) 62 | { 63 | const unsigned char *s; 64 | int n; 65 | 66 | s = *buf; 67 | for (n=0; *s && *s != ':' && (*s >= '0' && *s <= '9'); s++) 68 | n = n*10 + (*s - '0'); 69 | if (!n || *s != ':') 70 | return 0; /* we don't allow empty lengths */ 71 | *buf = s+1; 72 | return n; 73 | } 74 | 75 | /* Skip over the S-expression BUF points to and update BUF to point to 76 | the character right behind. DEPTH gives the initial number of open 77 | lists and may be passed as a positive number to skip over the 78 | remainder of an S-expression if the current position is somewhere 79 | within an S-expression. This function returns 0 on success. */ 80 | static int 81 | sskip (unsigned char const **buf, int *depth) 82 | { 83 | const unsigned char *s = *buf; 84 | size_t n; 85 | int d = *depth; 86 | 87 | while (d > 0) 88 | { 89 | if (*s == '(') 90 | { 91 | d++; 92 | s++; 93 | } 94 | else if (*s == ')') 95 | { 96 | d--; 97 | s++; 98 | } 99 | else 100 | { 101 | if (!d) 102 | return TGPG_INV_DATA; 103 | n = snext (&s); 104 | if (!n) 105 | return TGPG_INV_DATA; 106 | s += n; 107 | } 108 | } 109 | *buf = s; 110 | *depth = d; 111 | return 0; 112 | } 113 | 114 | 115 | /* Check whether the string at the address BUF points to, matches the 116 | string TOKEN. Returns true on match and updates BUF to point 117 | behind the token string. Return false and does not update the 118 | buffer if tehre is no match. */ 119 | static int 120 | smatch (unsigned char const **buf, size_t buflen, const char *token) 121 | { 122 | size_t toklen = strlen (token); 123 | 124 | if (buflen != toklen || memcmp (*buf, token, toklen)) 125 | return 0; 126 | *buf += toklen; 127 | return 1; 128 | } 129 | 130 | 131 | 132 | 133 | /* Calculate the MIC for a private key S-Exp. SHA1HASH should point 134 | to a 20 byte buffer. */ 135 | static int 136 | calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) 137 | { 138 | const unsigned char *hash_begin, *hash_end; 139 | const unsigned char *s; 140 | size_t n; 141 | 142 | s = plainkey; 143 | if (*s != '(') 144 | return TGPG_INV_DATA; 145 | s++; 146 | n = snext (&s); 147 | if (!n) 148 | return TGPG_INV_DATA; 149 | if (!smatch (&s, n, "private-key")) 150 | return TGPG_UNEXP_DATA; 151 | if (*s != '(') 152 | return TGPG_UNEXP_DATA; 153 | hash_begin = s; 154 | s++; 155 | n = snext (&s); 156 | if (!n) 157 | return TGPG_INV_DATA; 158 | s += n; /* Skip the algorithm name. */ 159 | 160 | while (*s == '(') 161 | { 162 | s++; 163 | n = snext (&s); 164 | if (!n) 165 | return TGPG_INV_DATA; 166 | s += n; 167 | n = snext (&s); 168 | if (!n) 169 | return TGPG_INV_DATA; 170 | s += n; 171 | if ( *s != ')' ) 172 | return TGPG_INV_DATA; 173 | s++; 174 | } 175 | if (*s != ')') 176 | return TGPG_INV_DATA; 177 | s++; 178 | hash_end = s; 179 | 180 | _tgpg_hash_buffer (MD_ALGO_SHA1, sha1hash, 20, 181 | hash_begin, hash_end - hash_begin); 182 | 183 | return 0; 184 | } 185 | 186 | 187 | 188 | /* Do the actual decryption and check the return list for 189 | consistency. */ 190 | static int 191 | do_decryption (const unsigned char *protected, size_t protectedlen, 192 | const char *passphrase, 193 | const unsigned char *s2ksalt, unsigned long s2kcount, 194 | const unsigned char *iv, size_t ivlen, 195 | unsigned char **result) 196 | { 197 | int rc; 198 | int blklen; 199 | unsigned char *outbuf; 200 | size_t reallen; 201 | 202 | blklen = _tgpg_cipher_blocklen (PROT_CIPHER); 203 | if (protectedlen < 4 || (protectedlen%blklen)) 204 | return TGPG_INV_DATA; /* Corrupted protection. */ 205 | 206 | outbuf = xtrymalloc (protectedlen); 207 | if (!outbuf) 208 | return TGPG_SYSERROR; 209 | 210 | { 211 | unsigned char *key; 212 | size_t keylen; 213 | 214 | keylen = PROT_CIPHER_KEYLEN; 215 | key = xtrymalloc (keylen); 216 | if (!key) 217 | { 218 | xfree (outbuf); 219 | return TGPG_SYSERROR; 220 | } 221 | 222 | rc = _tgpg_s2k_hash (passphrase, MD_ALGO_SHA1, 3, s2ksalt, s2kcount, 223 | key, keylen); 224 | if (!rc) 225 | rc = _tgpg_cipher_decrypt (PROT_CIPHER, CIPHER_MODE_CBC, 226 | key, keylen, 227 | iv, ivlen, 228 | NULL, 0, 229 | outbuf, protectedlen, 230 | protected, protectedlen); 231 | wipememory (key, keylen); 232 | xfree (key); 233 | } 234 | if (rc) 235 | { 236 | xfree (outbuf); 237 | return rc; 238 | } 239 | 240 | /* Check that the result is a valid S-expression. */ 241 | if ( (*outbuf != '(' && outbuf[1] != '(') 242 | || !(reallen = _tgpg_canonsexp_len (outbuf, protectedlen)) 243 | || (reallen + blklen < protectedlen) ) 244 | { 245 | xfree (outbuf); 246 | return TGPG_INV_PASS; 247 | } 248 | 249 | *result = outbuf; 250 | return 0; 251 | } 252 | 253 | 254 | /* Merge the parameter list contained in CLEARTEXT with the original 255 | protect lists PROTECTEDKEY by replacing the list at REPLACEPOS. 256 | Return the new list in RESULT and the MIC value in the 20 byte 257 | buffer SHA1HASH. */ 258 | static int 259 | merge_lists (const unsigned char *protectedkey, 260 | size_t replacepos, 261 | const unsigned char *cleartext, 262 | unsigned char *sha1hash, 263 | unsigned char **result, size_t *resultlen) 264 | { 265 | size_t n, newlistlen; 266 | unsigned char *newlist, *p; 267 | const unsigned char *s; 268 | const unsigned char *startpos, *endpos; 269 | int i; 270 | 271 | *result = NULL; 272 | *resultlen = 0; 273 | 274 | if (replacepos < 26) 275 | return TGPG_BUG; 276 | 277 | /* Estimate the required size of the resulting list. We have a 278 | large safety margin of >20 bytes (MIC hash from CLEARTEXT and the 279 | removed "protected-". We already now that this is a valid one, 280 | thus there is no need to pass the length. */ 281 | newlistlen = _tgpg_canonsexp_len (protectedkey, 0); 282 | if (!newlistlen) 283 | return TGPG_BUG; 284 | n = _tgpg_canonsexp_len (cleartext, 0); 285 | if (!n) 286 | return TGPG_BUG; 287 | newlistlen += n; 288 | newlist = xtrymalloc (newlistlen); 289 | if (!newlist) 290 | return TGPG_SYSERROR; 291 | 292 | /* Copy the initial segment. (10 == strlen("protected-")) */ 293 | memcpy (newlist, "(11:private-key", 15); 294 | p = newlist + 15; 295 | memcpy (p, protectedkey+15+10, replacepos-15-10); 296 | p += replacepos-15-10; 297 | 298 | /* Copy the cleartext. */ 299 | s = cleartext; 300 | if (*s != '(' && s[1] != '(') 301 | return TGPG_BUG; /* We already checked this. */ 302 | s += 2; 303 | startpos = s; 304 | while ( *s == '(' ) 305 | { 306 | s++; 307 | n = snext (&s); 308 | if (!n) 309 | goto invalid_sexp; 310 | s += n; 311 | n = snext (&s); 312 | if (!n) 313 | goto invalid_sexp; 314 | s += n; 315 | if ( *s != ')' ) 316 | goto invalid_sexp; 317 | s++; 318 | } 319 | if ( *s != ')' ) 320 | goto invalid_sexp; 321 | endpos = s; 322 | s++; 323 | 324 | /* Now get the MIC. */ 325 | if (*s != '(') 326 | goto invalid_sexp; 327 | s++; 328 | n = snext (&s); 329 | if (!smatch (&s, n, "hash")) 330 | goto invalid_sexp; 331 | n = snext (&s); 332 | if (!smatch (&s, n, "sha1")) 333 | goto invalid_sexp; 334 | n = snext (&s); 335 | if (n != 20) 336 | goto invalid_sexp; 337 | memcpy (sha1hash, s, 20); 338 | s += n; 339 | if (*s != ')') 340 | goto invalid_sexp; 341 | 342 | /* Append the parameter list. */ 343 | memcpy (p, startpos, endpos - startpos); 344 | p += endpos - startpos; 345 | 346 | /* Skip the protected list element from the original list. */ 347 | s = protectedkey + replacepos; 348 | assert (*s == '('); 349 | s++; 350 | i = 1; 351 | if ( sskip (&s, &i) ) 352 | goto invalid_sexp; 353 | startpos = s; 354 | i = 2; /* We are at this level. */ 355 | if ( sskip (&s, &i) ) 356 | goto invalid_sexp; 357 | assert (s[-1] == ')'); 358 | endpos = s; /* Now one behind the end of the list. */ 359 | 360 | /* Append the rest. */ 361 | memcpy (p, startpos, endpos - startpos); 362 | p += endpos - startpos; 363 | 364 | /* That's it. */ 365 | *result = newlist; 366 | *resultlen = newlistlen; 367 | return 0; 368 | 369 | invalid_sexp: 370 | wipememory (newlist, newlistlen); 371 | xfree (newlist); 372 | return TGPG_INV_DATA; 373 | } 374 | 375 | 376 | /* Check whether SECKEY is a protected secret key and return 0 in this 377 | case. */ 378 | int 379 | _tgpg_is_protected (const unsigned char *seckey) 380 | { 381 | const unsigned char *s; 382 | size_t n; 383 | 384 | s = seckey; 385 | if (*s != '(') 386 | return TGPG_INV_DATA; 387 | s++; 388 | n = snext (&s); 389 | if (!n) 390 | return TGPG_INV_DATA; 391 | if (!smatch (&s, n, "protected-private-key")) 392 | return 0; 393 | return TGPG_NO_DATA; 394 | } 395 | 396 | 397 | 398 | /* Unprotect the key encoded in canonical format. We assume a valid 399 | S-expression here. */ 400 | int 401 | _tgpg_unprotect (const unsigned char *protectedkey, const char *passphrase, 402 | unsigned char **result, size_t *resultlen) 403 | { 404 | int rc; 405 | const unsigned char *s; 406 | size_t n; 407 | int infidx, i; 408 | unsigned char sha1hash[20], sha1hash2[20]; 409 | const unsigned char *s2ksalt; 410 | unsigned long s2kcount; 411 | const unsigned char *iv; 412 | const unsigned char *prot_begin; 413 | unsigned char *cleartext; 414 | unsigned char *final; 415 | size_t finallen; 416 | 417 | s = protectedkey; 418 | if (*s != '(') 419 | return TGPG_INV_DATA; 420 | s++; 421 | n = snext (&s); 422 | if (!n) 423 | return TGPG_INV_DATA; 424 | if (!smatch (&s, n, "protected-private-key")) 425 | return TGPG_UNEXP_DATA; 426 | if (*s != '(') 427 | return TGPG_UNEXP_DATA; 428 | s++; 429 | n = snext (&s); 430 | if (!n) 431 | return TGPG_INV_DATA; 432 | 433 | for (infidx=0; (protect_info[infidx].algo 434 | && !smatch (&s, n, protect_info[infidx].algo)); infidx++) 435 | ; 436 | if (!protect_info[infidx].algo) 437 | return TGPG_INV_ALGO; 438 | 439 | /* Now find the list with the protected information. Here is an 440 | example for such a list: 441 | (protected openpgp-s2k3-sha1-aes-cbc 442 | ((sha1 ) ) 443 | ) 444 | */ 445 | for (;;) 446 | { 447 | if (*s != '(') 448 | return TGPG_INV_DATA; 449 | prot_begin = s; 450 | s++; 451 | n = snext (&s); 452 | if (!n) 453 | return TGPG_INV_DATA; 454 | if (smatch (&s, n, "protected")) 455 | break; 456 | s += n; 457 | i = 1; 458 | rc = sskip (&s, &i); 459 | if (rc) 460 | return rc; 461 | } 462 | /* Found. */ 463 | n = snext (&s); 464 | if (!n) 465 | return TGPG_INV_DATA; 466 | if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc")) 467 | return TGPG_NOT_IMPL; 468 | if (*s != '(' || s[1] != '(') 469 | return TGPG_INV_DATA; 470 | s += 2; 471 | n = snext (&s); 472 | if (!n) 473 | return TGPG_INV_DATA; 474 | if (!smatch (&s, n, "sha1")) 475 | return TGPG_NOT_IMPL; 476 | n = snext (&s); 477 | if (n != 8) 478 | return TGPG_INV_DATA; /* Corrupted protection. */ 479 | s2ksalt = s; 480 | s += n; 481 | n = snext (&s); 482 | if (!n) 483 | return TGPG_INV_DATA; /* Corrupted protection. */ 484 | /* We expect a list close as next item, so we can simply use 485 | strtoul() here. We might want to check that we only have digits 486 | - but this is nothing we should worry about */ 487 | if (s[n] != ')' ) 488 | return TGPG_INV_DATA; 489 | s2kcount = strtoul ((const char*)s, NULL, 10); 490 | if (!s2kcount) 491 | return TGPG_INV_DATA; /* Corrupted protection. */ 492 | s += n; 493 | s++; /* Skip list end. */ 494 | 495 | n = snext (&s); 496 | if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */ 497 | return TGPG_INV_DATA; /* Corrupted protection. */ 498 | iv = s; 499 | s += n; 500 | if (*s != ')' ) 501 | return TGPG_INV_DATA; 502 | s++; 503 | n = snext (&s); 504 | if (!n) 505 | return TGPG_INV_DATA; 506 | 507 | rc = do_decryption (s, n, 508 | passphrase, s2ksalt, s2kcount, 509 | iv, 16, 510 | &cleartext); 511 | if (rc) 512 | return rc; 513 | 514 | rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext, 515 | sha1hash, &final, &finallen); 516 | wipememory (cleartext, n); 517 | xfree (cleartext); 518 | if (rc) 519 | return rc; 520 | 521 | rc = calculate_mic (final, sha1hash2); 522 | if (!rc && memcmp (sha1hash, sha1hash2, 20)) 523 | rc = TGPG_INV_DATA; /* Corrupted protection. */ 524 | if (rc) 525 | { 526 | wipememory (final, finallen); 527 | xfree (final); 528 | return rc; 529 | } 530 | 531 | *result = final; 532 | *resultlen = _tgpg_canonsexp_len (final, 0); 533 | return 0; 534 | } 535 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell command `./configure && make && make install' 16 | should configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf limitation. Until the limitation is lifted, you can use 313 | this workaround: 314 | 315 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 316 | 317 | `configure' Invocation 318 | ====================== 319 | 320 | `configure' recognizes the following options to control how it 321 | operates. 322 | 323 | `--help' 324 | `-h' 325 | Print a summary of all of the options to `configure', and exit. 326 | 327 | `--help=short' 328 | `--help=recursive' 329 | Print a summary of the options unique to this package's 330 | `configure', and exit. The `short' variant lists options used 331 | only in the top level, while the `recursive' variant lists options 332 | also present in any nested packages. 333 | 334 | `--version' 335 | `-V' 336 | Print the version of Autoconf used to generate the `configure' 337 | script, and exit. 338 | 339 | `--cache-file=FILE' 340 | Enable the cache: use and save the results of the tests in FILE, 341 | traditionally `config.cache'. FILE defaults to `/dev/null' to 342 | disable caching. 343 | 344 | `--config-cache' 345 | `-C' 346 | Alias for `--cache-file=config.cache'. 347 | 348 | `--quiet' 349 | `--silent' 350 | `-q' 351 | Do not print messages saying which checks are being made. To 352 | suppress all normal output, redirect it to `/dev/null' (any error 353 | messages will still be shown). 354 | 355 | `--srcdir=DIR' 356 | Look for the package's source code in directory DIR. Usually 357 | `configure' can determine that directory automatically. 358 | 359 | `--prefix=DIR' 360 | Use DIR as the installation prefix. *note Installation Names:: 361 | for more details, including other options available for fine-tuning 362 | the installation locations. 363 | 364 | `--no-create' 365 | `-n' 366 | Run the configure checks, but stop before creating any output 367 | files. 368 | 369 | `configure' also accepts some other, not widely useful, options. Run 370 | `configure --help' for more details. 371 | --------------------------------------------------------------------------------