diff options
Diffstat (limited to 'g10/encode.c')
-rw-r--r-- | g10/encode.c | 519 |
1 files changed, 341 insertions, 178 deletions
diff --git a/g10/encode.c b/g10/encode.c index f033c76ae..80a9039ec 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -1,5 +1,5 @@ /* encode.c - encode data - * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,69 +30,18 @@ #include "errors.h" #include "iobuf.h" #include "keydb.h" -#include <gcrypt.h> +#include "memory.h" #include "util.h" #include "main.h" #include "filter.h" #include "trustdb.h" #include "i18n.h" +#include "status.h" - -static int encode_simple( const char *filename, int mode ); +static int encode_simple( const char *filename, int mode, int compat ); static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ); -/**************** - * Emulate our old PK interface here - sometime in the future we might - * change the internal design to directly fit to libgcrypt. - */ -static int -pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) -{ - GCRY_SEXP s_ciph, s_data, s_pkey; - int rc; - - /* make a sexp from pkey */ - if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) { - rc = gcry_sexp_build ( &s_pkey, NULL, - "(public-key(elg(p%m)(g%m)(y%m)))", - pkey[0], pkey[1], pkey[2] ); - } - else - return GPGERR_PUBKEY_ALGO; - - if ( rc ) - BUG (); - - /* put the data into a simple list */ - if ( gcry_sexp_build( &s_data, NULL, "%m", data ) ) - BUG (); - - /* pass it to libgcrypt */ - rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey ); - gcry_sexp_release( s_data ); - gcry_sexp_release( s_pkey ); - - if( rc ) - ; - else { /* add better error handling or make gnupg use S-Exp directly */ - GCRY_SEXP list = gcry_sexp_find_token( s_ciph, "a" , 0 ); - assert( list ); - resarr[0] = gcry_sexp_nth_mpi( list, 1, 0 ); - assert( resarr[0] ); - gcry_sexp_release ( list ); - - list = gcry_sexp_find_token( s_ciph, "b" , 0 ); - assert( list ); - resarr[1] = gcry_sexp_nth_mpi( list, 1, 0 ); - assert( resarr[1] ); - gcry_sexp_release ( list ); - } - - gcry_sexp_release( s_ciph ); - return rc; -} - /**************** * Encode FILENAME with only the symmetric cipher. Take input from @@ -101,7 +50,11 @@ pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) int encode_symmetric( const char *filename ) { - return encode_simple( filename, 1 ); + int compat = 1; + + if ( opt.expert ) + compat = 0; /* PGP knows how to handle this mode. */ + return encode_simple( filename, 1, compat ); } /**************** @@ -111,19 +64,49 @@ encode_symmetric( const char *filename ) int encode_store( const char *filename ) { - return encode_simple( filename, 0 ); + return encode_simple( filename, 0, 1 ); } - +static void +encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey ) +{ + CIPHER_HANDLE hd; + DEK *c; + byte buf[33]; + + assert ( dek->keylen < 32 ); + + c = m_alloc_clear( sizeof *c ); + c->keylen = dek->keylen; + c->algo = dek->algo; + make_session_key( c ); + /*log_hexdump( "thekey", c->key, c->keylen );*/ + + buf[0] = c->algo; + memcpy( buf + 1, c->key, c->keylen ); + + hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); + cipher_setkey( hd, dek->key, dek->keylen ); + cipher_setiv( hd, NULL, 0 ); + cipher_encrypt( hd, buf, buf, c->keylen + 1 ); + cipher_close( hd ); + + memcpy( enckey, buf, c->keylen + 1 ); + memset( buf, 0, sizeof buf ); /* burn key */ + *ret_dek = c; +} static int -encode_simple( const char *filename, int mode ) +encode_simple( const char *filename, int mode, int compat ) { IOBUF inp, out; PACKET pkt; + DEK *dek = NULL; PKT_plaintext *pt = NULL; STRING2KEY *s2k = NULL; + byte enckey[33]; int rc = 0; + int seskeylen = 0; u32 filesize; cipher_filter_context_t cfx; armor_filter_context_t afx; @@ -136,40 +119,62 @@ encode_simple( const char *filename, int mode ) memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet(&pkt); + + if (opt.compress == -1 && is_file_compressed(filename, &rc)) + { + if (opt.verbose) + log_info(_("`%s' already compressed\n"), filename); + do_compress = 0; + } + if (rc) + return rc; /* prepare iobufs */ if( !(inp = iobuf_open(filename)) ) { log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]", strerror(errno) ); - return GPGERR_OPEN_FILE; + return G10ERR_OPEN_FILE; } if( opt.textmode ) iobuf_push_filter( inp, text_filter, &tfx ); + /* Due the the fact that we use don't use an IV to encrypt the + session key we can't use the new mode with RFC1991 because + it has no S2K salt. RFC1991 always uses simple S2K. */ + if ( opt.rfc1991 && !compat ) + compat = 1; + cfx.dek = NULL; if( mode ) { - s2k = gcry_xcalloc( 1, sizeof *s2k ); + 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; cfx.dek = passphrase_to_dek( NULL, 0, - opt.def_cipher_algo ? opt.def_cipher_algo - : opt.s2k_cipher_algo , s2k, 2 ); + opt.def_cipher_algo ? opt.def_cipher_algo + : opt.s2k_cipher_algo , s2k, 2, NULL ); if( !cfx.dek || !cfx.dek->keylen ) { - rc = GPGERR_PASSPHRASE; - gcry_free(cfx.dek); - gcry_free(s2k); + rc = G10ERR_PASSPHRASE; + m_free(cfx.dek); + m_free(s2k); iobuf_close(inp); - log_error(_("error creating passphrase: %s\n"), gpg_errstr(rc) ); + log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); return rc; } + if ( !compat ) { + seskeylen = cipher_get_keylen( opt.def_cipher_algo ? + opt.def_cipher_algo: + opt.s2k_cipher_algo ) / 8; + encode_sesskey( cfx.dek, &dek, enckey ); + m_free( cfx.dek ); cfx.dek = dek; + } } if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) { iobuf_cancel(inp); - gcry_free(cfx.dek); - gcry_free(s2k); + m_free(cfx.dek); + m_free(s2k); return rc; } @@ -184,15 +189,19 @@ encode_simple( const char *filename, int mode ) } #endif if( s2k && !opt.rfc1991 ) { - PKT_symkey_enc *enc = gcry_xcalloc( 1, sizeof *enc ); + PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; + if ( !compat && seskeylen ) { + enc->seskeylen = seskeylen + 1; /* algo id */ + memcpy( enc->seskey, enckey, seskeylen + 1 ); + } pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if( (rc = build_packet( out, &pkt )) ) - log_error("build symkey packet failed: %s\n", gpg_errstr(rc) ); - gcry_free(enc); + log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); + m_free(enc); } if (!opt.no_literal) { @@ -200,30 +209,36 @@ encode_simple( const char *filename, int mode ) if( filename || opt.set_filename ) { char *s = make_basename( opt.set_filename ? opt.set_filename : filename ); - pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 ); + pt = m_alloc( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); - gcry_free(s); + m_free(s); } else { /* no filename */ - pt = gcry_xmalloc( sizeof *pt - 1 ); + pt = m_alloc( sizeof *pt - 1 ); pt->namelen = 0; } } - /* pgp5 has problems to decrypt symmetrically encrypted data from - * GnuPG if the filelength is in the inner packet. It works - * when only partial length headers are use. Until we have - * tracked this problem down. We use this temporary fix - * (fixme: remove the && !mode ) - */ - if( filename && !opt.textmode && !mode ) { + /* Note that PGP 5 has problems decrypting symmetrically encrypted + data if the file length is in the inner packet. It works when + only partial length headers are use. In the past, we always + used partial body length here, but since PGP 2, PGP 6, and PGP + 7 need the file length, and nobody should be using PGP 5 + nowadays anyway, this is now set to the file length. Note also + that this only applies to the RFC-1991 style symmetric + messages, and not the RFC-2440 style. PGP 6 and 7 work with + either partial length or fixed length with the new style + messages. */ + + if( filename && !opt.textmode ) { if( !(filesize = iobuf_get_filelength(inp)) ) log_info(_("%s: WARNING: empty file\n"), filename ); /* we can't yet encode the length of very large files, - * so we switch to partial length encoding in this case */ + * so we switch to partial lengthn encoding in this case */ if ( filesize >= IOBUF_FILELENGTH_LIMIT ) filesize = 0; + } else filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ @@ -239,7 +254,11 @@ encode_simple( const char *filename, int mode ) cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0; } else - cfx.datalen = filesize && !do_compress ? filesize : 0; + { + cfx.datalen = filesize && !do_compress ? filesize : 0; + pkt.pkttype = 0; + pkt.pkt.generic = NULL; + } /* register the cipher filter */ if( mode ) @@ -251,7 +270,7 @@ encode_simple( const char *filename, int mode ) /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", gpg_errstr(rc) ); + log_error("build_packet failed: %s\n", g10_errstr(rc) ); } else { /* user requested not to create a literal packet, @@ -260,8 +279,8 @@ encode_simple( const char *filename, int mode ) int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = GPGERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", gpg_errstr(rc) ); + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", g10_errstr(rc) ); break; } memset(copy_buffer, 0, 4096); /* burn buffer */ @@ -271,13 +290,16 @@ encode_simple( const char *filename, int mode ) iobuf_close(inp); if (rc) iobuf_cancel(out); - else + else { iobuf_close(out); /* fixme: check returncode */ + if (mode) + write_status( STATUS_END_ENCRYPTION ); + } if (pt) pt->buf = NULL; free_packet(&pkt); - gcry_free(cfx.dek); - gcry_free(s2k); + m_free(cfx.dek); + m_free(s2k); return rc; } @@ -291,123 +313,203 @@ encode_crypt( const char *filename, STRLIST remusr ) IOBUF inp = NULL, out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; - int rc = 0; + int rc = 0, rc2 = 0; u32 filesize; + cipher_filter_context_t cfx; armor_filter_context_t afx; compress_filter_context_t zfx; text_filter_context_t tfx; - encrypt_filter_context_t efx; - PK_LIST pk_list; + PK_LIST pk_list,work_list; int do_compress = opt.compress && !opt.rfc1991; + + memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); - memset( &efx, 0, sizeof efx); init_packet(&pkt); - if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) ) + if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) ) return rc; + if(opt.pgp2) { + for(work_list=pk_list; work_list; work_list=work_list->next) + if(!(is_RSA(work_list->pk->pubkey_algo) && + nbits_from_pk(work_list->pk)<=2048)) + { + log_info(_("you can only encrypt to RSA keys of 2048 bits or " + "less in --pgp2 mode\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); + opt.pgp2=0; + break; + } + } + + if (opt.compress == -1 && is_file_compressed(filename, &rc2)) + { + if (opt.verbose) + log_info(_("`%s' already compressed\n"), filename); + do_compress = 0; + } + if (rc2) + { + rc = rc2; + goto leave; + } + /* prepare iobufs */ if( !(inp = iobuf_open(filename)) ) { log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]", strerror(errno) ); - rc = GPGERR_OPEN_FILE; + rc = G10ERR_OPEN_FILE; goto leave; } else if( opt.verbose ) log_info(_("reading from `%s'\n"), filename? filename: "[stdin]"); - /* If the user selected textmode, push the text filter onto the input */ if( opt.textmode ) iobuf_push_filter( inp, text_filter, &tfx ); - /* Now we can create the outputfile */ if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) goto leave; - /* The first thing we have to push on the output stream - * is the armor filter */ + if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); + #ifdef ENABLE_COMMENT_PACKETS + else { + write_comment( out, "#created by GNUPG v" VERSION " (" + PRINTABLE_OS_NAME ")"); + if( opt.comment_string ) + write_comment( out, opt.comment_string ); + } + #endif + /* create a session key */ + 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,-1,NULL); + /* The only way select_algo_from_prefs can fail here is when + mixing v3 and v4 keys, as v4 keys have an implicit + preference entry for 3DES, and the pk_list cannot be empty. + In this case, use 3DES anyway as it's the safest choice - + perhaps the v3 key is being used in an OpenPGP + implementation and we know that the implementation behind + any v4 key can handle 3DES. */ + if( cfx.dek->algo == -1 ) { + cfx.dek->algo = CIPHER_ALGO_3DES; + + if( opt.pgp2 ) { + log_info(_("unable to use the IDEA cipher for all of the keys " + "you are encrypting to.\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); + opt.pgp2=0; + } + } + } + else { + if(!opt.expert && + select_algo_from_prefs(pk_list,PREFTYPE_SYM, + opt.def_cipher_algo,NULL)!=opt.def_cipher_algo) + log_info(_("forcing symmetric cipher %s (%d) " + "violates recipient preferences\n"), + cipher_algo_to_string(opt.def_cipher_algo), + opt.def_cipher_algo); + + cfx.dek->algo = opt.def_cipher_algo; + } + cfx.dek->use_mdc = select_mdc_from_pklist (pk_list); - /* Prepare the plaintext packet */ - { - if (!opt.no_literal) { - if( filename || opt.set_filename ) { - char *s = make_basename( opt.set_filename ? - opt.set_filename : filename ); - pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 ); - pt->namelen = strlen(s); - memcpy(pt->name, s, pt->namelen ); - gcry_free(s); - } - else { /* no filename */ - pt = gcry_xmalloc( sizeof *pt - 1 ); - pt->namelen = 0; - } - } - - if( filename && !opt.textmode ) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); - /* we can't yet encode the length of very large files, - * so we switch to partial lengthn encoding in this case */ - if ( filesize >= IOBUF_FILELENGTH_LIMIT ) - 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; - pkt.pkttype = PKT_PLAINTEXT; - pkt.pkt.plaintext = pt; - efx.cfx.datalen = filesize && !do_compress? - calc_packet_length( &pkt ) : 0; - } - else - efx.cfx.datalen = filesize && !do_compress ? filesize : 0; - } /* end preparation of plaintext packet */ - - /* push in the actual encryption filter */ - efx.pk_list = pk_list; - iobuf_push_filter( out, encrypt_filter, &efx ); - - /* register the compress filter (so that it is done before encryption) */ + make_session_key( cfx.dek ); + if( DBG_CIPHER ) + log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); + + rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out ); + if( rc ) + goto leave; + + if (!opt.no_literal) { + /* setup the inner packet */ + if( filename || opt.set_filename ) { + char *s = make_basename( opt.set_filename ? opt.set_filename : filename ); + 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; + } + } + + if( filename && !opt.textmode ) { + if( !(filesize = iobuf_get_filelength(inp)) ) + log_info(_("%s: WARNING: empty file\n"), filename ); + /* 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; + } + 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; + pkt.pkttype = PKT_PLAINTEXT; + pkt.pkt.plaintext = pt; + cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0; + } + else + cfx.datalen = filesize && !do_compress ? filesize : 0; + + /* register the cipher filter */ + iobuf_push_filter( out, cipher_filter, &cfx ); + + /* register the compress filter */ if( do_compress ) { - int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); - if( !compr_algo ) - ; /* don't use compression */ - else { - if( compr_algo == 1 ) - zfx.algo = 1; /* default is 2 */ + int compr_algo = opt.def_compress_algo; + + if(compr_algo==-1) + { + if((compr_algo= + select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1) + compr_algo=DEFAULT_COMPRESS_ALGO; + } + else if(!opt.expert && + select_algo_from_prefs(pk_list,PREFTYPE_ZIP, + compr_algo,NULL)!=compr_algo) + log_info(_("forcing compression algorithm %s (%d) " + "violates recipient preferences\n"), + compress_algo_to_string(compr_algo),compr_algo); + + /* algo 0 means no compression */ + if( compr_algo ) + { + zfx.algo = compr_algo; iobuf_push_filter( out, compress_filter, &zfx ); - } + } } /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", gpg_errstr(rc) ); + log_error("build_packet failed: %s\n", g10_errstr(rc) ); } else { - /* user requested not to create a literal packet, - * so we copy the plain data */ + /* user requested not to create a literal packet, so we copy the plain data */ 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 = GPGERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", gpg_errstr(rc) ); + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", g10_errstr(rc) ); break; } - memset(copy_buffer, 0, DIM(copy_buffer)); /* burn buffer */ + memset(copy_buffer, 0, 4096); /* burn buffer */ } /* finish the stuff */ @@ -415,13 +517,14 @@ encode_crypt( const char *filename, STRLIST remusr ) iobuf_close(inp); if( rc ) iobuf_cancel(out); - else + else { iobuf_close(out); /* fixme: check returncode */ + write_status( STATUS_END_ENCRYPTION ); + } if( pt ) pt->buf = NULL; free_packet(&pkt); - gcry_free(efx.cfx.dek); /* Hmmm, why does the encrypt filter does not - * take care about this? */ + m_free(cfx.dek); release_pk_list( pk_list ); return rc; } @@ -430,7 +533,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /**************** - * Filter to handle the entire public key encryption. + * Filter to do a complete public key encryption. */ int encrypt_filter( void *opaque, int control, @@ -445,16 +548,32 @@ encrypt_filter( void *opaque, int control, } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { - efx->cfx.dek = gcry_xmalloc_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 ) + select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL); + 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 { + if(!opt.expert && + select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM, + opt.def_cipher_algo, + NULL)!=opt.def_cipher_algo) + log_info(_("forcing symmetric cipher %s (%d) " + "violates recipient preferences\n"), + cipher_algo_to_string(opt.def_cipher_algo), + opt.def_cipher_algo); + + efx->cfx.dek->algo = opt.def_cipher_algo; } - else - efx->cfx.dek->algo = opt.def_cipher_algo; + + efx->cfx.dek->use_mdc = select_mdc_from_pklist (efx->pk_list); + make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", @@ -497,7 +616,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) pk = pk_list->pk; print_pubkey_algo_note( pk->pubkey_algo ); - enc = gcry_xcalloc( 1, sizeof *enc ); + enc = m_alloc_clear( sizeof *enc ); enc->pubkey_algo = pk->pubkey_algo; keyid_from_pk( pk, enc->keyid ); enc->throw_keyid = opt.throw_keyid; @@ -517,17 +636,17 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) */ frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo, pk->pkey ) ); - rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); - mpi_release( frame ); + rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); + mpi_free( frame ); if( rc ) - log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) ); + log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) ); else { if( opt.verbose ) { char *ustr = get_user_id_string_native( enc->keyid ); log_info(_("%s/%s encrypted for: %s\n"), - gcry_pk_algo_name(enc->pubkey_algo), - gcry_cipher_algo_name(dek->algo), ustr ); - gcry_free(ustr); + pubkey_algo_to_string(enc->pubkey_algo), + cipher_algo_to_string(dek->algo), ustr ); + m_free(ustr); } /* and write it */ init_packet(&pkt); @@ -535,7 +654,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) pkt.pkt.pubkey_enc = enc; rc = build_packet( out, &pkt ); if( rc ) - log_error("build_packet(pubkey_enc) failed: %s\n", gpg_errstr(rc)); + log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc)); } free_pubkey_enc(enc); if( rc ) @@ -544,3 +663,47 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) return 0; } +void +encode_crypt_files(int nfiles, char **files, STRLIST remusr) +{ + int rc = 0; + + if (opt.outfile) + { + log_error(_("--output doesn't work for this command\n")); + return; + } + + if (!nfiles) + { + char line[2048]; + unsigned int lno = 0; + while ( fgets(line, DIM(line), stdin) ) + { + lno++; + if (!*line || line[strlen(line)-1] != '\n') + { + log_error("input line %u too long or missing LF\n", lno); + return; + } + line[strlen(line)-1] = '\0'; + print_file_status(STATUS_FILE_START, line, 2); + if ( (rc = encode_crypt(line, remusr)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(line), g10_errstr(rc) ); + write_status( STATUS_FILE_DONE ); + } + } + else + { + while (nfiles--) + { + print_file_status(STATUS_FILE_START, *files, 2); + if ( (rc = encode_crypt(*files, remusr)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(*files), g10_errstr(rc) ); + write_status( STATUS_FILE_DONE ); + files++; + } + } +} |