aboutsummaryrefslogtreecommitdiffstats
path: root/g10/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/misc.c')
-rw-r--r--g10/misc.c704
1 files changed, 456 insertions, 248 deletions
diff --git a/g10/misc.c b/g10/misc.c
index 2348e46f0..c2330d959 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1,5 +1,5 @@
/* misc.c - miscellaneous functions
- * 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.
*
@@ -22,28 +22,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <errno.h>
+#ifdef HAVE_STAT
+#include <sys/stat.h>
+#endif
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#include <asm/sysinfo.h>
#include <asm/unistd.h>
#endif
#ifdef HAVE_SETRLIMIT
+ #include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#endif
-#include <assert.h>
-
-#include <gcrypt.h>
#include "util.h"
#include "main.h"
+#include "photoid.h"
#include "options.h"
#include "i18n.h"
-#define MAX_EXTERN_MPI_BITS 16384
+const char *g10m_revision_string(int);
+const char *g10c_revision_string(int);
+const char *g10u_revision_string(int);
+
+#ifdef __GNUC__
+volatile
+#endif
+ void
+pull_in_libs(void)
+{
+ g10m_revision_string(0);
+ g10c_revision_string(0);
+ g10u_revision_string(0);
+}
+
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
-#warning using trap_unaligned
static int
setsysinfo(unsigned long op, void *buffer, unsigned long size,
int *start, void *arg, unsigned long flag)
@@ -68,7 +84,6 @@ trap_unaligned(void)
#endif
-
int
disable_core_dumps()
{
@@ -91,166 +106,23 @@ disable_core_dumps()
-/****************
- * write an mpi to out.
- */
-int
-mpi_write( IOBUF out, MPI a )
-{
- char buffer[(MAX_EXTERN_MPI_BITS+7)/8];
- size_t nbytes;
- int rc;
-
- nbytes = (MAX_EXTERN_MPI_BITS+7)/8;
- rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
- if( !rc )
- rc = iobuf_write( out, buffer, nbytes );
-
- return rc;
-}
-
-/****************
- * Writye a MPI to out, but in this case it is an opaque one,
- * s used vor v3 protected keys.
- */
-int
-mpi_write_opaque( IOBUF out, MPI a )
-{
- size_t nbytes, nbits;
- int rc;
- char *p;
-
- assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
- p = gcry_mpi_get_opaque( a, &nbits );
- nbytes = (nbits+7) / 8;
- iobuf_put( out, nbits >> 8 );
- iobuf_put( out, nbits );
- rc = iobuf_write( out, p, nbytes );
- return rc;
-}
-
-
-/****************
- * Read an external representation of an mpi and return the MPI
- * The external format is a 16 bit unsigned value stored in network byte order,
- * giving the number of bits for the following integer. The integer is stored
- * with MSB first (left padded with zeroes to align on a byte boundary).
- */
-MPI
-mpi_read(IOBUF inp, unsigned int *ret_nread, int secure)
+u16
+checksum_u16( unsigned n )
{
- int c, c1, c2, i;
- unsigned int nbits, nbytes, nread=0;
- MPI a = NULL;
- byte *buf = NULL;
- byte *p;
-
- if( (c = c1 = iobuf_get(inp)) == -1 )
- goto leave;
- nbits = c << 8;
- if( (c = c2 = iobuf_get(inp)) == -1 )
- goto leave;
- nbits |= c;
- if( nbits > MAX_EXTERN_MPI_BITS ) {
- log_error("mpi too large (%u bits)\n", nbits);
- goto leave;
- }
- nread = 2;
- nbytes = (nbits+7) / 8;
- buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 );
- p = buf;
- p[0] = c1;
- p[1] = c2;
- for( i=0 ; i < nbytes; i++ ) {
- p[i+2] = iobuf_get(inp) & 0xff;
- nread++;
- }
- nread += nbytes;
- if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) )
- a = NULL;
-
- leave:
- gcry_free(buf);
- if( nread > *ret_nread )
- log_bug("mpi larger than packet");
- else
- *ret_nread = nread;
- return a;
-}
+ u16 a;
-/****************
- * Same as mpi_read but the value is stored as an opaque MPI.
- * This function is used to read encrypted MPI of v3 packets.
- */
-GCRY_MPI
-mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
-{
- int c, c1, c2, i;
- unsigned nbits, nbytes, nread=0;
- GCRY_MPI a = NULL;
- byte *buf = NULL;
- byte *p;
-
- if( (c = c1 = iobuf_get(inp)) == -1 )
- goto leave;
- nbits = c << 8;
- if( (c = c2 = iobuf_get(inp)) == -1 )
- goto leave;
- nbits |= c;
- if( nbits > MAX_EXTERN_MPI_BITS ) {
- log_error("mpi too large (%u bits)\n", nbits);
- goto leave;
- }
- nread = 2;
- nbytes = (nbits+7) / 8;
- buf = gcry_xmalloc( nbytes );
- p = buf;
- for( i=0 ; i < nbytes; i++ ) {
- p[i] = iobuf_get(inp) & 0xff;
+ a = (n >> 8) & 0xff;
+ if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
+ a |= n & 0xff;
+ log_debug("csum_u16 emulated for n=%u\n", n);
}
- nread += nbytes;
- a = gcry_mpi_set_opaque(NULL, buf, nbits );
- buf = NULL;
-
- leave:
- gcry_free(buf);
- if( nread > *ret_nread )
- log_bug("mpi larger than packet");
else
- *ret_nread = nread;
+ a += n & 0xff;
return a;
}
-
-int
-mpi_print( FILE *fp, MPI a, int mode )
-{
- int n=0;
-
- if( !a )
- return fprintf(fp, "[MPI_NULL]");
- if( !mode ) {
- unsigned int n1;
- n1 = gcry_mpi_get_nbits(a);
- n += fprintf(fp, "[%u bits]", n1);
- }
- else {
- int rc;
- char *buffer;
-
- rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a );
- assert( !rc );
- fputs( buffer, fp );
- n += strlen(buffer);
- gcry_free( buffer );
- }
- return n;
-}
-
-
-
-u16
-checksum_u16( unsigned n )
+static u16
+checksum_u16_nobug( unsigned n )
{
u16 a;
@@ -272,22 +144,47 @@ checksum( byte *p, unsigned n )
u16
checksum_mpi( MPI a )
{
- int rc;
u16 csum;
byte *buffer;
- size_t nbytes;
-
- rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a );
- assert( !rc );
- /* fixme: for numbers not in the suecre memory we
- * should use a stack based buffer and only allocate
- * a larger one when the mpi_print return an error
+ unsigned nbytes;
+ unsigned nbits;
+
+ buffer = mpi_get_buffer( a, &nbytes, NULL );
+ /* some versions of gpg encode wrong values for the length of an mpi
+ * so that mpi_get_nbits() which counts the mpi yields another (shorter)
+ * value than the one store with the mpi. mpi_get_nbit_info() returns
+ * this stored value if it is still available.
*/
- buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes);
- rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
- assert( !rc );
- csum = checksum( buffer, nbytes );
- gcry_free( buffer );
+
+ if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
+ nbits = 0;
+ else
+ nbits = mpi_get_nbit_info(a);
+ if( !nbits )
+ nbits = mpi_get_nbits(a);
+ csum = checksum_u16( nbits );
+ csum += checksum( buffer, nbytes );
+ m_free( buffer );
+ return csum;
+}
+
+/****************
+ * This is the correct function
+ */
+u16
+checksum_mpi_counted_nbits( MPI a )
+{
+ u16 csum;
+ byte *buffer;
+ unsigned nbytes;
+ unsigned nbits;
+
+ buffer = mpi_get_buffer( a, &nbytes, NULL );
+ nbits = mpi_get_nbits(a);
+ mpi_set_nbit_info(a,nbits);
+ csum = checksum_u16_nobug( nbits );
+ csum += checksum( buffer, nbytes );
+ m_free( buffer );
return csum;
}
@@ -327,11 +224,13 @@ print_cipher_algo_note( int algo )
{
if( algo >= 100 && algo <= 110 )
no_exp_algo();
- else if( algo == GCRY_CIPHER_3DES
- || algo == GCRY_CIPHER_CAST5
- || algo == GCRY_CIPHER_BLOWFISH
- || algo == GCRY_CIPHER_RIJNDAEL
- || algo == GCRY_CIPHER_TWOFISH
+ else if( algo == CIPHER_ALGO_3DES
+ || algo == CIPHER_ALGO_CAST5
+ || algo == CIPHER_ALGO_BLOWFISH
+ || algo == CIPHER_ALGO_TWOFISH
+ || algo == CIPHER_ALGO_RIJNDAEL
+ || algo == CIPHER_ALGO_RIJNDAEL192
+ || algo == CIPHER_ALGO_RIJNDAEL256
)
;
else {
@@ -339,7 +238,7 @@ print_cipher_algo_note( int algo )
if( !did_note ) {
did_note = 1;
- log_info(_("this cipher algorithm is depreciated; "
+ log_info(_("this cipher algorithm is deprecated; "
"please use a more standard one!\n"));
}
}
@@ -353,6 +252,32 @@ print_digest_algo_note( int algo )
}
+/* Return a string which is used as a kind of process ID */
+const byte *
+get_session_marker( size_t *rlen )
+{
+ static byte marker[SIZEOF_UNSIGNED_LONG*2];
+ static int initialized;
+
+ if ( !initialized ) {
+ volatile ulong aa, bb; /* we really want the uninitialized value */
+ ulong a, b;
+
+ initialized = 1;
+ /* also this marker is guessable it is not easy to use this
+ * for a faked control packet because an attacker does not
+ * have enough control about the time the verification does
+ * take place. Of course, we can add just more random but
+ * than we need the random generator even for verification
+ * tasks - which does not make sense. */
+ a = aa ^ (ulong)getpid();
+ b = bb ^ (ulong)time(NULL);
+ memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
+ memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
+ }
+ *rlen = sizeof(marker);
+ return marker;
+}
/****************
* Wrapper around the libgcrypt function with addional checks on
@@ -362,122 +287,405 @@ int
openpgp_cipher_test_algo( int algo )
{
if( algo < 0 || algo > 110 )
- return GCRYERR_INV_CIPHER_ALGO;
- return gcry_cipher_test_algo(algo);
+ return G10ERR_CIPHER_ALGO;
+ return check_cipher_algo(algo);
}
int
openpgp_pk_test_algo( int algo, unsigned int usage_flags )
{
- size_t n = usage_flags;
-
if( algo < 0 || algo > 110 )
- return GCRYERR_INV_PK_ALGO;
- return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
+ return G10ERR_PUBKEY_ALGO;
+ return check_pubkey_algo2( algo, usage_flags );
}
int
openpgp_pk_algo_usage ( int algo )
{
- int usage = 0;
+ int use = 0;
- /* some are hardwired */
+ /* they are hardwired in gpg 1.0 */
switch ( algo ) {
- case GCRY_PK_RSA:
- usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
+ case PUBKEY_ALGO_RSA:
+ use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
break;
- case GCRY_PK_RSA_E:
- usage = GCRY_PK_USAGE_ENCR;
+ case PUBKEY_ALGO_RSA_E:
+ use = PUBKEY_USAGE_ENC;
break;
- case GCRY_PK_RSA_S:
- usage = GCRY_PK_USAGE_SIGN;
+ case PUBKEY_ALGO_RSA_S:
+ use = PUBKEY_USAGE_SIG;
break;
- case GCRY_PK_ELG_E:
- usage = GCRY_PK_USAGE_ENCR;
+ case PUBKEY_ALGO_ELGAMAL_E:
+ use = PUBKEY_USAGE_ENC;
break;
- case GCRY_PK_DSA:
- usage = GCRY_PK_USAGE_SIGN;
+ case PUBKEY_ALGO_DSA:
+ use = PUBKEY_USAGE_SIG;
break;
- case GCRY_PK_ELG:
- usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
+ case PUBKEY_ALGO_ELGAMAL:
+ use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
break;
default:
- usage = gcry_pk_algo_info ( algo, GCRYCTL_GET_ALGO_USAGE,
- NULL, NULL);
+ break;
}
- return usage;
-
+ return use;
}
-
-
int
openpgp_md_test_algo( int algo )
{
if( algo < 0 || algo > 110 )
- return GCRYERR_INV_MD_ALGO;
- return gcry_md_test_algo(algo);
+ return G10ERR_DIGEST_ALGO;
+ return check_digest_algo(algo);
}
-
int
-pubkey_get_npkey( int algo )
+check_permissions(const char *path,int extension,int checkonly)
{
- int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
- return n > 0? n : 0;
+#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
+ char *tmppath;
+ struct stat statbuf;
+ int ret=1;
+ int isdir=0;
+
+ if(opt.no_perm_warn)
+ return 0;
+
+ if(extension && path[0]!=DIRSEP_C)
+ {
+ if(strchr(path,DIRSEP_C))
+ tmppath=make_filename(path,NULL);
+ else
+ tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
+ }
+ else
+ tmppath=m_strdup(path);
+
+ /* It's okay if the file doesn't exist */
+ if(stat(tmppath,&statbuf)!=0)
+ {
+ ret=0;
+ goto end;
+ }
+
+ isdir=S_ISDIR(statbuf.st_mode);
+
+ /* We may have to revisit this if we start piping keyrings to gpg
+ over a named pipe or keyserver character device :) */
+ if(!isdir && !S_ISREG(statbuf.st_mode))
+ {
+ ret=0;
+ goto end;
+ }
+
+ /* Per-user files must be owned by the user. Extensions must be
+ owned by the user or root. */
+ if((!extension && statbuf.st_uid != getuid()) ||
+ (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
+ {
+ if(!checkonly)
+ log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
+ isdir?"directory":extension?"extension":"file",path);
+ goto end;
+ }
+
+ /* This works for both directories and files - basically, we don't
+ care what the owner permissions are, so long as the group and
+ other permissions are 0 for per-user files, and non-writable for
+ extensions. */
+ if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
+ (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
+ {
+ char *dir;
+
+ /* However, if the directory the directory/file is in is owned
+ by the user and is 700, then this is not a problem.
+ Theoretically, we could walk this test up to the root
+ directory /, but for the sake of sanity, I'm stopping at one
+ level down. */
+
+ dir=make_dirname(tmppath);
+ if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
+ S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
+ {
+ m_free(dir);
+ ret=0;
+ goto end;
+ }
+
+ m_free(dir);
+
+ if(!checkonly)
+ log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
+ isdir?"directory":extension?"extension":"file",path);
+ goto end;
+ }
+
+ ret=0;
+
+ end:
+ m_free(tmppath);
+
+ return ret;
+
+#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
+
+ return 0;
}
-int
-pubkey_get_nskey( int algo )
+/* Special warning for the IDEA cipher */
+void
+idea_cipher_warn(int show)
{
- int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
- return n > 0? n : 0;
+ static int warned=0;
+
+ if(!warned || show)
+ {
+ log_info(_("the IDEA cipher plugin is not present\n"));
+ log_info(_("please see http://www.gnupg.org/why-not-idea.html "
+ "for more information\n"));
+ warned=1;
+ }
}
-int
-pubkey_get_nsig( int algo )
+/* Expand %-strings. Returns a string which must be m_freed. Returns
+ NULL if the string cannot be expanded (too large). */
+char *
+pct_expando(const char *string,struct expando_args *args)
{
- int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
- return n > 0? n : 0;
+ const char *ch=string;
+ int idx=0,maxlen=0,done=0;
+ u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
+ char *ret=NULL;
+
+ if(args->pk)
+ keyid_from_pk(args->pk,pk_keyid);
+
+ if(args->sk)
+ keyid_from_sk(args->sk,sk_keyid);
+
+ if(!args->pk && args->sk)
+ keyid_from_sk(args->sk,pk_keyid);
+
+ while(*ch!='\0')
+ {
+ char *str=NULL;
+
+ if(!done)
+ {
+ /* 8192 is way bigger than we'll need here */
+ if(maxlen>=8192)
+ goto fail;
+
+ maxlen+=1024;
+ ret=m_realloc(ret,maxlen);
+ }
+
+ done=0;
+
+ if(*ch=='%')
+ {
+ switch(*(ch+1))
+ {
+ case 's': /* short key id */
+ if(idx+8<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
+ idx+=8;
+ done=1;
+ }
+ break;
+
+ case 'S': /* long key id */
+ if(idx+16<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX%08lX",
+ (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
+ idx+=16;
+ done=1;
+ }
+ break;
+
+ case 'k': /* short key id */
+ if(idx+8<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
+ idx+=8;
+ done=1;
+ }
+ break;
+
+ case 'K': /* long key id */
+ if(idx+16<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX%08lX",
+ (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
+ idx+=16;
+ done=1;
+ }
+ break;
+
+ case 'f': /* fingerprint */
+ {
+ byte array[MAX_FINGERPRINT_LEN];
+ size_t len;
+ int i;
+
+ if(args->pk)
+ fingerprint_from_pk(args->pk,array,&len);
+ else
+ memset(array,0,MAX_FINGERPRINT_LEN);
+
+ if(idx+(len*2)<maxlen)
+ {
+ for(i=0;i<len;i++)
+ {
+ sprintf(&ret[idx],"%02X",array[i]);
+ idx+=2;
+ }
+ done=1;
+ }
+ }
+ break;
+
+ case 't': /* e.g. "jpg" */
+ str=image_type_to_string(args->imagetype,0);
+ /* fall through */
+
+ case 'T': /* e.g. "image/jpeg" */
+ if(str==NULL)
+ str=image_type_to_string(args->imagetype,2);
+
+ if(idx+strlen(str)<maxlen)
+ {
+ strcpy(&ret[idx],str);
+ idx+=strlen(str);
+ done=1;
+ }
+ break;
+
+ case '%':
+ if(idx+1<maxlen)
+ {
+ ret[idx++]='%';
+ ret[idx]='\0';
+ done=1;
+ }
+ break;
+
+ /* Any unknown %-keys (like %i, %o, %I, and %O) are
+ passed through for later expansion. Note this also
+ handles the case where the last character in the
+ string is a '%' - the terminating \0 will end up here
+ and properly terminate the string. */
+ default:
+ if(idx+2<maxlen)
+ {
+ ret[idx++]='%';
+ ret[idx++]=*(ch+1);
+ ret[idx]='\0';
+ done=1;
+ }
+ break;
+ }
+
+ if(done)
+ ch++;
+ }
+ else
+ {
+ if(idx+1<maxlen)
+ {
+ ret[idx++]=*ch;
+ ret[idx]='\0';
+ done=1;
+ }
+ }
+
+ if(done)
+ ch++;
+ }
+
+ return ret;
+
+ fail:
+ m_free(ret);
+ return NULL;
}
int
-pubkey_get_nenc( int algo )
+hextobyte( const char *s )
{
- int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
- return n > 0? n : 0;
+ int c;
+
+ if( *s >= '0' && *s <= '9' )
+ c = 16 * (*s - '0');
+ else if( *s >= 'A' && *s <= 'F' )
+ c = 16 * (10 + *s - 'A');
+ else if( *s >= 'a' && *s <= 'f' )
+ c = 16 * (10 + *s - 'a');
+ else
+ return -1;
+ s++;
+ if( *s >= '0' && *s <= '9' )
+ c += *s - '0';
+ else if( *s >= 'A' && *s <= 'F' )
+ c += 10 + *s - 'A';
+ else if( *s >= 'a' && *s <= 'f' )
+ c += 10 + *s - 'a';
+ else
+ return -1;
+ return c;
}
-
-unsigned int
-pubkey_nbits( int algo, MPI *key )
+void
+deprecated_warning(const char *configname,unsigned int configlineno,
+ const char *option,const char *repl1,const char *repl2)
{
- int rc, nbits;
- GCRY_SEXP sexp;
+ if(configname)
+ {
+ if(strncmp("--",option,2)==0)
+ option+=2;
- if( algo == GCRY_PK_DSA ) {
- rc = gcry_sexp_build ( &sexp, NULL,
- "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
- key[0], key[1], key[2], key[3] );
- }
- else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
- rc = gcry_sexp_build ( &sexp, NULL,
- "(public-key(elg(p%m)(g%m)(y%m)))",
- key[0], key[1], key[2] );
- }
- else if( algo == GCRY_PK_RSA ) {
- rc = gcry_sexp_build ( &sexp, NULL,
- "(public-key(rsa(n%m)(e%m)))",
- key[0], key[1] );
+ if(strncmp("--",repl1,2)==0)
+ repl1+=2;
+
+ log_info(_("%s:%d: deprecated option \"%s\"\n"),
+ configname,configlineno,option);
}
- else
- return 0;
+ else
+ log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
+
+ log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
+}
+
+const char *
+compress_algo_to_string(int algo)
+{
+ const char *s="?";
- if ( rc )
- BUG ();
+ switch(algo)
+ {
+ case 0:
+ s="Uncompressed";
+ break;
- nbits = gcry_pk_get_nbits( sexp );
- gcry_sexp_release( sexp );
- return nbits;
+ case 1:
+ s="ZIP";
+ break;
+
+ case 2:
+ s="ZLIB";
+ break;
+ }
+
+ return s;
}
+int
+check_compress_algo(int algo)
+{
+ if(algo>=0 && algo<=2)
+ return 0;
+
+ return G10ERR_COMPR_ALGO;
+}