diff options
author | Werner Koch <[email protected]> | 2001-08-20 19:10:34 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-08-20 19:10:34 +0000 |
commit | 98a8843e28810c6195eda82da716fdc6e983451c (patch) | |
tree | 9e11de39504f62a3e729ab28af09d6173cd0ac42 | |
parent | Applied Stefan's patches to support RISCOS. (diff) | |
download | gnupg-98a8843e28810c6195eda82da716fdc6e983451c.tar.gz gnupg-98a8843e28810c6195eda82da716fdc6e983451c.zip |
Implemented -cs and some fixes to the rfc1991 symmetric only mode
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | acinclude.m4 | 1 | ||||
-rw-r--r-- | configure.ac | 136 | ||||
-rw-r--r-- | g10/ChangeLog | 13 | ||||
-rw-r--r-- | g10/encode.c | 9 | ||||
-rw-r--r-- | g10/encr-data.c | 3 | ||||
-rw-r--r-- | g10/g10.c | 17 | ||||
-rw-r--r-- | g10/main.h | 1 | ||||
-rw-r--r-- | g10/mainproc.c | 35 | ||||
-rw-r--r-- | g10/passphrase.c | 14 | ||||
-rw-r--r-- | g10/sign.c | 322 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/cipher.h | 1 | ||||
-rw-r--r-- | util/ChangeLog | 4 | ||||
-rw-r--r-- | util/secmem.c | 11 |
17 files changed, 522 insertions, 64 deletions
@@ -1,5 +1,15 @@ 2001-08-20 Werner Koch <[email protected]> + * acinclude.m4: Add check for plock if mlock is broken. + * configure.ac: Use regular tests for -lsocket and -lnsl, + more thorough test for gethrtime, allow specifying the path to + the zlib library if it is not in the default compiler/linker + search path, use ${datadir}. All these test enhancements are by + Albert Chin. + + * configure.ac: Set some compiler flags for dec-osf and hpux. By + Tim Mooney. + * configure.ac: Create g10defs.h with EXTSEP_S et al. 2001-08-03 Werner Koch <[email protected]> @@ -24,6 +24,7 @@ * Merged Stefan's patches for RISCOS in. See comments in scripts/build-riscos. + * It is now possible to sign an convenional encrypt a message (-cs). Noteworthy changes in version 1.0.6 (2001-05-29) ------------------------------------------------ @@ -7,8 +7,6 @@ * Put a note into readme.w32 that there is a man page and a options file; write the registry stuff in regedit format. - * Allow "gpg -cs" - * Show more info does not work from edit->trust * keyedit_menu: We first look for a secret key and then for a public @@ -77,6 +75,8 @@ * Using --list-only to check for recipients while decrypting may yield an error about an unknown packet. + * Check that the way we select cipher and digest algorithms w/o + preferences is okay and make AES the default. Scheduled for 1.1 ----------------- diff --git a/acinclude.m4 b/acinclude.m4 index 5a245fe29..4ba4be9b9 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -436,6 +436,7 @@ define(GNUPG_CHECK_MLOCK, AC_DEFINE(HAVE_BROKEN_MLOCK,1, [Defined if the mlock() call does not work]) AC_MSG_RESULT(yes) + AC_CHECK_FUNCS(plock) else if test "$gnupg_cv_have_broken_mlock" = "no"; then AC_MSG_RESULT(no) diff --git a/configure.ac b/configure.ac index 0180bfa44..5d65e6774 100644 --- a/configure.ac +++ b/configure.ac @@ -239,6 +239,15 @@ case "${target}" in CFLAGS="$CFLAGS -w" fi ;; + *-dec-osf5*) + if test -z "$GCC" ; then + # Use the newer compiler `-msg_disable ptrmismatch' to + # get rid of the unsigned/signed char mismatch warnings. + # Using this may hide other pointer mismatch warnings, but + # it at least lets other warning classes through + CFLAGS="$CFLAGS -msg_disable ptrmismatch" + fi + ;; m68k-atari-mint) ;; *) @@ -279,7 +288,13 @@ esac AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) -dnl Fixme: Are these the best flags for OpenBSD???? + +# +# 1. Set flags to be used for the extension modules +# 2. Set names of random devices +# +NAME_OF_DEV_RANDOM="/dev/random" +NAME_OF_DEV_URANDOM="/dev/urandom" case "${target}" in *-openbsd* | *-netbsd*) NAME_OF_DEV_RANDOM="/dev/srandom" @@ -287,15 +302,39 @@ case "${target}" in DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x" ;; + hpux*) + # if using the vendor (ANSI) compiler, arrange to have `-b' passed + # to the linker. If using gcc, it supports `-shared' to do the same. + if test -n "$GCC" ; then + DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" + else + DYNLINK_MOD_CFLAGS='-Wl,-b' + fi + ;; + + *-irix6.5*) + # Irix 6.5 (and probably a lot earlier, but I only still have + # access to 6.5.x) doesn't require any additional flags, as `-KPIC' + # is the default. Also, `-shared' works with the vendor compiler + DYNLINK_MOD_CFLAGS="-shared" + ;; + + alpha*-dec-osf*) + # osf (i.e. OSF/1, Digital UNIX, or Tru64 UNIX, pick any one...) + # on alpha doesn't require any PIC flags, everything is PIC. + # This may not be the case for osf ports to other machines, so + # hence the more specific match for target. + # + # Also, `-shared' works with the vendor compiler or gcc. + # -expect_unresolved turns off warnings about unresolved symbols. + DYNLINK_MOD_CFLAGS='-shared -Wl,-expect_unresolved,\*' + ;; + *-solaris* | *-irix* | *-dec-osf* ) - NAME_OF_DEV_RANDOM="/dev/random" - NAME_OF_DEV_URANDOM="/dev/urandom" DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" ;; *) - NAME_OF_DEV_RANDOM="/dev/random" - NAME_OF_DEV_URANDOM="/dev/urandom" # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. if test -n "$GCC" ; then DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" @@ -335,28 +374,33 @@ if test "$ac_cv_header_gdbm_h" = yes ; then fi fi +dnl This old test is here just for reference tin case it fails: +dnl dnl Solaris needs -lsocket and -lnsl. Unisys system includes dnl gethostbyname in libsocket but needs libnsl for socket. dnl The test does not workfor all system, so some are hardcoded here. -case "${target}" in - i386-univel-sysv4*) - LIBS="$LIBS -lsocket -lnsl" - ;; - *) - AC_CHECK_LIB(nsl, gethostbyname) - AC_CHECK_LIB(socket, socket, ac_need_libsocket=1, ac_try_nsl=1) - if test x$ac_need_libsocket = x1; then - LIBS="$LIBS -lsocket" - fi - if test x$ac_try_nsl = x1; then - AC_CHECK_LIB(nsl, gethostbyname, ac_need_libnsl=1) - if test x$ac_need_libnsl = x1 - then - LIBS="$LIBS -lnsl" - fi - fi - ;; -esac +dnl case "${target}" in +dnl i386-univel-sysv4*) +dnl LIBS="$LIBS -lsocket -lnsl" +dnl ;; +dnl *) +dnl AC_CHECK_LIB(nsl, gethostbyname) +dnl AC_CHECK_LIB(socket, socket, ac_need_libsocket=1, ac_try_nsl=1) +dnl if test x$ac_need_libsocket = x1; then +dnl LIBS="$LIBS -lsocket" +dnl fi +dnl if test x$ac_try_nsl = x1; then +dnl AC_CHECK_LIB(nsl, gethostbyname, ac_need_libnsl=1) +dnl if test x$ac_need_libnsl = x1 +dnl then +dnl LIBS="$LIBS -lnsl" +dnl fi +dnl fi +dnl ;; +dnl esac + +AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname)) +AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) if test "$try_dynload" = yes ; then @@ -446,10 +490,17 @@ fi dnl Checks for library functions. AC_FUNC_VPRINTF AC_CHECK_FUNCS(strerror stpcpy strlwr stricmp tcgetattr rand strtoul mmap) -AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime setrlimit clock_gettime) +AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) AC_CHECK_FUNCS(memicmp atexit raise getpagesize strftime nl_langinfo) AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask fseeko) +AC_MSG_CHECKING(for gethrtime) +AC_TRY_LINK([#include <sys/times.h>],[ + hrtime_t tv; + tv = gethrtime(); + ],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_GETHRTIME)], AC_MSG_RESULT(no)) + + GNUPG_CHECK_MLOCK GNUPG_FUNC_MKDIR_TAKES_ONE_ARG @@ -696,12 +747,25 @@ use_local_zlib=yes if test "$g10_force_zlib" = "yes"; then : else - AC_CHECK_HEADERS(zlib.h) - if test "$ac_cv_header_zlib_h" = yes ; then - AC_CHECK_LIB(z,deflateInit2_,use_local_zlib=no,:) - fi + _cppflags="${CPPFLAGS}" + _ldflags="${LDFLAGS}" + + AC_ARG_WITH(zlib, + [ --with-zlib=DIR use libz in DIR],[ + if test -d "$withval"; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + ]) + + AC_CHECK_HEADER(zlib.h, + AC_CHECK_LIB(z, deflateInit2_, + use_local_zlib=no + LIBS="$LIBS -lz", + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) fi - + if test "$use_local_zlib" = yes ; then AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, true) AC_CONFIG_LINKS(zlib.h:zlib/zlib.h zconf.h:zlib/zconf.h ) @@ -709,7 +773,6 @@ if test "$use_local_zlib" = yes ; then else AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, false) ZLIBS= - LIBS="-lz $LIBS" fi AC_SUBST(ZLIBS) @@ -757,7 +820,7 @@ cat >g10defs.tmp <<G10EOF #define GNUPG_DATADIR "c:/lib/gnupg" #define GNUPG_HOMEDIR "c:/gnupg" #else - #define G10_LOCALEDIR "${prefix}/${DATADIRNAME}/locale" + #define G10_LOCALEDIR "${datadir}/locale" #define GNUPG_LIBDIR "${libdir}/gnupg" #define GNUPG_DATADIR "${datadir}/gnupg" #ifdef __VMS @@ -806,14 +869,15 @@ checks/Makefile AC_OUTPUT # Give some feedback -echo "Configured for: $PRINTABLE_OS_NAME ($target)" +echo +echo " Configured for: $PRINTABLE_OS_NAME ($target)" if test -n "$show_dynlink"; then - echo "Dynamically linked modules:$show_dynlink" + echo " Dynamically linked modules:$show_dynlink" fi if test -n "$show_statlink"; then - echo "Statically linked modules:$show_statlink" + echo " Statically linked modules:$show_statlink" fi if test -n "$show_extraasm"; then - echo "Extra cpu specific functions:$show_extraasm" + echo " Extra cpu specific functions:$show_extraasm" fi diff --git a/g10/ChangeLog b/g10/ChangeLog index 7d583db9d..0ffbf1f0c 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,18 @@ 2001-08-20 Werner Koch <[email protected]> + * encr-data.c (decrypt_data): Keep track on whether we already + printed information about the used algorithm. + * mainproc.c (proc_encrypted): Removed the non-working IDEA hack + and print a message about the assumed algorithm. + * passphrase.c (passphrase_to_dek): Use the same algorithm as above. + (proc_symkey_enc): Print the algorithm, so that the user knows it + before entering the passphrase. + (proc_pubkey_enc, proc_pubkey_enc): Zero the DEK out. + * encode.c (encode_crypt, encrypt_filter): Ditto. + + * g10.c: Allow for --sign --symmetric. + * sign.c (sign_and_symencrypt): New. + Applied patches from Stefan Bellon <[email protected]> to support the RISCOS. Nearly all of these patches are identified by the __riscos__ macro. diff --git a/g10/encode.c b/g10/encode.c index 5726be5a4..8cc44c152 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -291,7 +291,7 @@ encode_crypt( const char *filename, STRLIST remusr ) } #endif /* create a session key */ - cfx.dek = m_alloc_secure( sizeof *cfx.dek ); + cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM ); if( cfx.dek->algo == -1 ) @@ -415,13 +415,16 @@ encrypt_filter( void *opaque, int control, } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { - efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek ); + efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek ); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ efx->cfx.dek->algo = select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM ); - if( efx->cfx.dek->algo == -1 ) + if( efx->cfx.dek->algo == -1 ) { + /* because 3DES is implicitly in the prefs, this can only + * happen if we do not have any public keys in the list */ efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO; + } } else efx->cfx.dek->algo = opt.def_cipher_algo; diff --git a/g10/encr-data.c b/g10/encr-data.c index ee8c188fc..e2752bf36 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -60,12 +60,13 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) unsigned nprefix; memset( &dfx, 0, sizeof dfx ); - if( opt.verbose ) { + if( opt.verbose && !dek->algo_info_printed ) { const char *s = cipher_algo_to_string( dek->algo ); if( s ) log_info(_("%s encrypted data\n"), s ); else log_info(_("encrypted with unknown algorithm %d\n"), dek->algo ); + dek->algo_info_printed = 1; } if( (rc=check_cipher_algo(dek->algo)) ) goto leave; @@ -73,6 +73,7 @@ enum cmd_and_opt_values { aNull = 0, aStore, aKeygen, aSignEncr, + aSignSym, aSignKey, aLSignKey, aListPackets, @@ -607,6 +608,10 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) cmd = aSignEncr; else if( cmd == aEncr && new_cmd == aSign ) cmd = aSignEncr; + else if( cmd == aSign && new_cmd == aSym ) + cmd = aSignSym; + else if( cmd == aSym && new_cmd == aSign ) + cmd = aSignSym; else if( cmd == aKMode && new_cmd == aSym ) cmd = aKModeC; else if( ( cmd == aSign && new_cmd == aClearsign ) @@ -1316,11 +1321,21 @@ main( int argc, char **argv ) free_strlist(sl); break; + case aSignSym: /* sign and conventionally encrypt the given file */ + if (argc > 1) + wrong_args(_("--sign --symmetric [filename]")); + rc = sign_symencrypt_file (fname, locusr); + if (rc) + log_error("%s: sign+symmetric failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + break; + case aClearsign: /* make a clearsig */ if( argc > 1 ) wrong_args(_("--clearsign [filename]")); if( (rc = clearsign_file(fname, locusr, NULL)) ) - log_error("%s: clearsign failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); + log_error("%s: clearsign failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); break; case aVerify: diff --git a/g10/main.h b/g10/main.h index 353d5bd94..43dd72ee3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -82,6 +82,7 @@ int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ); int sign_file( STRLIST filenames, int detached, STRLIST locusr, int do_encrypt, STRLIST remusr, const char *outfile ); int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ); +int sign_symencrypt_file (const char *fname, STRLIST locusr); /*-- sig-check.c --*/ int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); diff --git a/g10/mainproc.c b/g10/mainproc.c index af50f6a58..02a423804 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -247,8 +247,19 @@ proc_symkey_enc( CTX c, PACKET *pkt ) if (enc->seskeylen) log_error ("symkey_enc packet with session keys are not supported!\n"); else { + int algo = enc->cipher_algo; + const char *s; + + s = cipher_algo_to_string (algo); + if( s ) + log_info(_("%s encrypted data\n"), s ); + else + log_info(_("encrypted with unknown algorithm %d\n"), algo ); + c->last_was_session_key = 2; - c->dek = passphrase_to_dek( NULL, 0, enc->cipher_algo, &enc->s2k, 0 ); + c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0 ); + if (c->dek) + c->dek->algo_info_printed = 1; } free_packet(pkt); } @@ -276,10 +287,10 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) } if( !opt.list_only && opt.override_session_key ) { - /* It does not make nuch sense to store the session key in + /* It does not make much sense to store the session key in * secure memory because it has already been passed on the * command line and the GCHQ knows about it */ - c->dek = m_alloc( sizeof *c->dek ); + c->dek = m_alloc_clear( sizeof *c->dek ); result = get_override_session_key ( c->dek, opt.override_session_key ); if ( result ) { m_free(c->dek); c->dek = NULL; @@ -293,7 +304,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) if( opt.list_only ) result = -1; else { - c->dek = m_alloc_secure( sizeof *c->dek ); + c->dek = m_alloc_secure_clear( sizeof *c->dek ); if( (result = get_session_key( enc, c->dek )) ) { /* error: delete the DEK */ m_free(c->dek); c->dek = NULL; @@ -409,14 +420,14 @@ proc_encrypted( CTX c, PACKET *pkt ) if( opt.list_only ) result = -1; else if( !c->dek && !c->last_was_session_key ) { - int def_algo; - /* assume this is old conventional encrypted data - * We use IDEA here if it is installed */ - def_algo = check_cipher_algo (CIPHER_ALGO_IDEA)? - DEFAULT_CIPHER_ALGO : CIPHER_ALGO_IDEA; - c->dek = passphrase_to_dek( NULL, 0, - opt.def_cipher_algo ? opt.def_cipher_algo - : DEFAULT_CIPHER_ALGO, NULL, 0 ); + int algo = opt.def_cipher_algo ? opt.def_cipher_algo + : opt.s2k_cipher_algo; + /* assume this is old style conventional encrypted data */ + log_info(_("assuming %s encrypted data\n"), + cipher_algo_to_string (algo) ); + c->dek = passphrase_to_dek( NULL, 0, algo, NULL, 0); + if (c->dek) + c->dek->algo_info_printed = 1; } else if( !c->dek ) result = G10ERR_NO_SECKEY; diff --git a/g10/passphrase.c b/g10/passphrase.c index c626e9adc..c6c7cb27d 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -513,16 +513,14 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, STRING2KEY help_s2k; if( !s2k ) { - int def_algo; + /* This is used for the old rfc1991 mode + * Note: This must match the code in encode.c with opt.rfc1991 set */ + int algo = opt.def_digest_algo ? opt.def_digest_algo + : opt.s2k_digest_algo; s2k = &help_s2k; s2k->mode = 0; - /* If we have IDEA installed we use MD5 otherwise the default - * hash algorithm. This can always be overriden from the - * commandline */ - def_algo = check_cipher_algo (CIPHER_ALGO_IDEA)? - DEFAULT_DIGEST_ALGO : DIGEST_ALGO_MD5; - s2k->hash_algo = opt.def_digest_algo? opt.def_digest_algo : def_algo; + s2k->hash_algo = algo; } if( !next_pw && is_status_enabled() ) { @@ -632,7 +630,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, if( !pw || !*pw ) write_status( STATUS_MISSING_PASSPHRASE ); - dek = m_alloc_secure( sizeof *dek ); + dek = m_alloc_secure_clear ( sizeof *dek ); dek->algo = cipher_algo; if( !*pw && mode == 2 ) dek->keylen = 0; diff --git a/g10/sign.c b/g10/sign.c index bd3faf2b5..913d82be7 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -797,6 +797,328 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) return rc; } +/* + * Sign and conventionally encrypt the given file. + * FIXME: Far too much code is duplicated - revamp the whole file. + */ +int +sign_symencrypt_file (const char *fname, STRLIST locusr) +{ + armor_filter_context_t afx; + compress_filter_context_t zfx; + md_filter_context_t mfx; + text_filter_context_t tfx; + cipher_filter_context_t cfx; + IOBUF inp = NULL, out = NULL; + PACKET pkt; + PKT_plaintext *pt = NULL; + STRING2KEY *s2k = NULL; + u32 filesize; + int rc = 0; + SK_LIST sk_list = NULL; + SK_LIST sk_rover = NULL; + int old_style = opt.rfc1991; + int compr_algo = -1; /* unknown */ + int algo; + + memset( &afx, 0, sizeof afx); + memset( &zfx, 0, sizeof zfx); + memset( &mfx, 0, sizeof mfx); + memset( &tfx, 0, sizeof tfx); + memset( &cfx, 0, sizeof cfx); + init_packet( &pkt ); + + rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG); + if (rc) + goto leave; + if( !old_style ) + old_style = only_old_style( sk_list ); + + /* prepare iobufs */ + inp = iobuf_open(fname); + if( !inp ) { + log_error("can't open %s: %s\n", fname? fname: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + + /* prepare key */ + s2k = m_alloc_clear( sizeof *s2k ); + s2k->mode = opt.rfc1991? 0:opt.s2k_mode; + s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo + : opt.s2k_digest_algo; + + algo = opt.def_cipher_algo ? opt.def_cipher_algo : opt.s2k_cipher_algo; + if (!opt.quiet || !opt.batch) + log_info (_("%s encryption will be used\n"), + cipher_algo_to_string(algo) ); + cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2 ); + + if (!cfx.dek || !cfx.dek->keylen) { + rc = G10ERR_PASSPHRASE; + log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); + goto leave; + } + + /* now create the outfile */ + rc = open_outfile (fname, opt.armor? 1:0, &out); + if (rc) + goto leave; + + /* prepare to calculate the MD over the input */ + if (opt.textmode) + iobuf_push_filter (inp, text_filter, &tfx); + mfx.md = md_open(0, 0); + + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { + PKT_secret_key *sk = sk_rover->sk; + md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); + } + + iobuf_push_filter (inp, md_filter, &mfx); + + /* Push armor output filter */ + if (opt.armor) + iobuf_push_filter (out, armor_filter, &afx); + + /* Write the symmetric key packet */ + /*(current filters: armor)*/ + if (!opt.rfc1991) { + PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); + enc->version = 4; + enc->cipher_algo = cfx.dek->algo; + enc->s2k = *s2k; + pkt.pkttype = PKT_SYMKEY_ENC; + pkt.pkt.symkey_enc = enc; + if( (rc = build_packet( out, &pkt )) ) + log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); + m_free(enc); + } + + /* Push the encryption filter */ + iobuf_push_filter( out, cipher_filter, &cfx ); + + /* Push the Zip filter */ + if (opt.compress) { + if (!compr_algo) + ; /* don't use compression */ + else { + if( old_style || compr_algo == 1 ) + zfx.algo = 1; /* use the non optional algorithm */ + iobuf_push_filter( out, compress_filter, &zfx ); + } + } + + /* Write the one-pass signature packets */ + /*(current filters: zip - encrypt - armor)*/ + if (!old_style) { + int skcount=0; + /* loop over the secret certificates and build headers + * The specs now say that the data should be bracket by + * the onepass-sig and signature-packet; so we must build it + * here in reverse order */ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + skcount++; + for( ; skcount; skcount-- ) { + PKT_secret_key *sk; + PKT_onepass_sig *ops; + int i = 0; + + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + if( ++i == skcount ) + break; + + sk = sk_rover->sk; + ops = m_alloc_clear( sizeof *ops ); + ops->sig_class = opt.textmode? 0x01 : 0x00; + ops->digest_algo = hash_for(sk->pubkey_algo, sk->version); + ops->pubkey_algo = sk->pubkey_algo; + keyid_from_sk( sk, ops->keyid ); + ops->last = skcount == 1; + + init_packet(&pkt); + pkt.pkttype = PKT_ONEPASS_SIG; + pkt.pkt.onepass_sig = ops; + rc = build_packet( out, &pkt ); + free_packet( &pkt ); + if( rc ) { + log_error("build onepass_sig packet failed: %s\n", + g10_errstr(rc)); + goto leave; + } + } + } + + /* Pipe data through all filters; i.e. write the signed stuff */ + /*(current filters: zip - encrypt - armor)*/ + if (!opt.no_literal) { + if (fname || opt.set_filename) { + char *s = make_basename (opt.set_filename? opt.set_filename + : fname ); + pt = m_alloc (sizeof *pt + strlen(s) - 1 ); + pt->namelen = strlen (s); + memcpy (pt->name, s, pt->namelen ); + m_free (s); + } + else { /* no filename */ + pt = m_alloc( sizeof *pt - 1 ); + pt->namelen = 0; + } + } + + /* try to calculate the length of the data */ + if (fname) { + if( !(filesize = iobuf_get_filelength(inp)) ) + log_info(_("WARNING: `%s' is an empty file\n"), fname ); + /* we can't yet encode the length of very large files, + * so we switch to partial length encoding in this case */ + if (filesize >= IOBUF_FILELENGTH_LIMIT) + filesize = 0; + + /* because the text_filter modifies the length of the + * data, it is not possible to know the used length + * without a double read of the file - to avoid that + * we simple use partial length packets. + */ + if (opt.textmode) + filesize = 0; + } + else { + filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ + } + + if (!opt.no_literal) { + pt->timestamp = make_timestamp(); + pt->mode = opt.textmode? 't':'b'; + pt->len = filesize; + pt->new_ctb = !pt->len && !opt.rfc1991; + pt->buf = inp; /* take data from this iobuf */ + pkt.pkttype = PKT_PLAINTEXT; + pkt.pkt.plaintext = pt; + /* build packet automagically write all the data */ + if( (rc = build_packet( out, &pkt )) ) + log_error("build_packet(PLAINTEXT) failed: %s\n", g10_errstr(rc) ); + pt->buf = NULL; + } + else { + byte copy_buffer[4096]; + int bytes_copied; + while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) + if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", g10_errstr(rc)); + break; + } + memset(copy_buffer, 0, 4096); /* burn buffer */ + } + + /* catch errors from above */ + if (rc) + goto leave; + + /* Write the signature by looping over the secret certificates */ + /*(current filters: zip - encrypt - armor)*/ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk; + PKT_signature *sig; + MD_HANDLE md; + + sk = sk_rover->sk; + + /* build the signature packet */ + /* fixme: this code is partly duplicated in make_keysig_packet */ + sig = m_alloc_clear( sizeof *sig ); + sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version; + keyid_from_sk( sk, sig->keyid ); + sig->digest_algo = hash_for(sk->pubkey_algo, sk->version); + sig->pubkey_algo = sk->pubkey_algo; + sig->timestamp = make_timestamp(); + sig->sig_class = opt.textmode? 0x01 : 0x00; + + md = md_copy( mfx.md ); + + if( sig->version >= 4 ) { + build_sig_subpkt_from_sig( sig ); + md_putc( md, sig->version ); + } + + mk_notation_and_policy( sig ); + + md_putc( md, sig->sig_class ); + if( sig->version < 4 ) { + u32 a = sig->timestamp; + md_putc( md, (a >> 24) & 0xff ); + md_putc( md, (a >> 16) & 0xff ); + md_putc( md, (a >> 8) & 0xff ); + md_putc( md, a & 0xff ); + } + else { + byte buf[6]; + size_t n; + + md_putc( md, sig->pubkey_algo ); + md_putc( md, sig->digest_algo ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n ); + n += 6; + } + else { + md_putc( md, 0 ); /* always hash the length of the subpacket*/ + md_putc( md, 0 ); + n = 6; + } + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write( md, buf, 6 ); + + } + md_final( md ); + + rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo, sk->version) ); + md_close( md ); + + if( !rc ) { /* and write it */ + init_packet(&pkt); + pkt.pkttype = PKT_SIGNATURE; + pkt.pkt.signature = sig; + rc = build_packet( out, &pkt ); + if( !rc && is_status_enabled() ) { + print_status_sig_created ( sk, sig, 'S'); + } + free_packet( &pkt ); + if( rc ) + log_error("build signature packet failed: %s\n", g10_errstr(rc) ); + } + if( rc ) + goto leave; + + } + + + leave: + if( rc ) + iobuf_cancel(out); + else { + iobuf_close(out); + write_status( STATUS_END_ENCRYPTION ); + } + iobuf_close(inp); + release_sk_list( sk_list ); + md_close( mfx.md ); + m_free(cfx.dek); + m_free(s2k); + return rc; +} + /**************** * Create a signature packet for the given public key certificate and diff --git a/include/ChangeLog b/include/ChangeLog index 128176c10..aecb92b4a 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,10 +1,12 @@ 2001-08-20 Werner Koch <[email protected]> + * cipher.h (DEK): Added algo_info_printed; + * util.h [__riscos__]: Added prototypes and made sure that we never use __attribute__. * cipher.h, iobuf.h, memory.h, mpi.h [__riscos__]: extern hack. * i18n.h [__riscos__]: Use another include file - + 2001-05-30 Werner Koch <[email protected]> * ttyio.h (tty_printf): Add missing parenthesis for non gcc. diff --git a/include/cipher.h b/include/cipher.h index 6863f98ec..ef00e5c3f 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -63,6 +63,7 @@ typedef struct { int algo; int keylen; + int algo_info_printed; byte key[32]; /* this is the largest used keylen (256 bit) */ } DEK; diff --git a/util/ChangeLog b/util/ChangeLog index 3e361bcdb..c70c28596 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -13,6 +13,10 @@ * memory.c [__riscos__]: Minor patches * riscos.c (set_filetype): New. + * secmem.c (lock_pool): Under HPUX mlock is broken but we might + have plock, so we use this to lock the entire process. By Albert + Chin. + 2001-07-03 Werner Koch <[email protected]> * strgutil.c (utf8_to_native): Fixed printing of invalid utf-8 diff --git a/util/secmem.c b/util/secmem.c index 148ea1e88..c7fc597ee 100644 --- a/util/secmem.c +++ b/util/secmem.c @@ -32,6 +32,9 @@ #ifdef USE_CAPABILITIES #include <sys/capability.h> #endif + #ifdef HAVE_PLOCK + #include <sys/lock.h> + #endif #endif #include "types.h" @@ -120,6 +123,13 @@ lock_pool( void *p, size_t n ) uid = getuid(); #ifdef HAVE_BROKEN_MLOCK + /* ick. but at least we get secured memory. about to lock + entire data segment. */ + #ifdef HAVE_PLOCK + err = plock( DATLOCK ); + if( err && errno ) + err = errno; +#else /*!HAVE_PLOCK*/ if( uid ) { errno = EPERM; err = errno; @@ -129,6 +139,7 @@ lock_pool( void *p, size_t n ) if( err && errno ) err = errno; } + #endif /*!HAVE_PLOCK*/ #else err = mlock( p, n ); if( err && errno ) |