mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
See ChangeLog: Mon Sep 18 16:35:45 CEST 2000 Werner Koch
This commit is contained in:
parent
c2fff8f204
commit
986d928ce2
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
||||
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* acinclude.m4 (GNUPG_CHECK_MLOCK): Removed that silly mkdir().
|
||||
|
||||
* configure.in: Changes to allow for Solaris random device.
|
||||
By Nils Ellmenreich.
|
||||
(--with-egd-socket): New.
|
||||
|
||||
* configure.in (GNUPG_HOMEDIR): New.
|
||||
|
||||
* configure.in: Check for fstat64 and fopen64
|
||||
|
||||
* acinclude.m4 (GNUPG_CHECK_FAQPROG): New.
|
||||
* configure.in: Test for this.
|
||||
|
||||
* configure.in (DYNLINK_MOD_CFLAGS): Fix by David Champion.
|
||||
|
||||
Tue Aug 22 14:31:15 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
Version 1.1.1
|
||||
|
34
NEWS
34
NEWS
@ -1,8 +1,38 @@
|
||||
Noteworthy changes in version 1.1.1
|
||||
-----------------------------------
|
||||
Noteworthy changes in the current CVS HEAD
|
||||
------------------------------------------
|
||||
|
||||
THIS IS A DEVELOPMENT VERSION; see README-alpha
|
||||
|
||||
* Fixed problems with piping to/from other MS-Windows software
|
||||
|
||||
* Expiration time of the primary key can be changed again.
|
||||
|
||||
* Revoked user IDs are now marked in the output of --list-key
|
||||
|
||||
* New options --merge-only and --try-all-secrets.
|
||||
|
||||
* New configuration option --with-egd-socket.
|
||||
|
||||
* The --trusted-key option is back after it left us with 0.9.5
|
||||
|
||||
* RSA is supported. Key generation does not yet work but will come
|
||||
soon.
|
||||
|
||||
* CAST5 and SHA-1 are now the default algorithms to protect the key
|
||||
and for symmetric-only encryption. This should solve a couple
|
||||
of compatibility problems because the old algorithms are optional
|
||||
according to RFC2440
|
||||
|
||||
* Twofish and MDC enhanced encryption is now used. PGP 7 supports
|
||||
this. Older versions of GnuPG don't support it, so they should be
|
||||
upgraded to at least 1.0.2
|
||||
|
||||
|
||||
|
||||
|
||||
Noteworthy changes in version 1.1.1
|
||||
-----------------------------------
|
||||
|
||||
* Add gpg-agent.
|
||||
|
||||
* Removed option --emulate-checksum-bug
|
||||
|
@ -74,6 +74,8 @@
|
||||
#undef NAME_OF_DEV_URANDOM
|
||||
/* Linux has an ioctl */
|
||||
#undef HAVE_DEV_RANDOM_IOCTL
|
||||
/* see cipher/rndegd.c */
|
||||
#undef EGD_SOCKET_NAME
|
||||
|
||||
|
||||
#undef USE_DYNAMIC_LINKING
|
||||
|
28
acinclude.m4
28
acinclude.m4
@ -67,6 +67,32 @@ AC_DEFUN(GNUPG_CHECK_GNUMAKE,
|
||||
fi
|
||||
])
|
||||
|
||||
dnl GNUPG_CHECK_FAQPROG
|
||||
dnl
|
||||
AC_DEFUN(GNUPG_CHECK_FAQPROG,
|
||||
[ AC_MSG_CHECKING(for faqprog.pl)
|
||||
if faqprog.pl -V 2>/dev/null | grep '^faqprog.pl ' >/dev/null 2>&1; then
|
||||
working_faqprog=yes
|
||||
FAQPROG="faqprog.pl"
|
||||
else
|
||||
working_faqprog=no
|
||||
FAQPROG=": "
|
||||
fi
|
||||
AC_MSG_RESULT($working_faqprog)
|
||||
AC_SUBST(FAQPROG)
|
||||
AM_CONDITIONAL(WORKING_FAQPROG, test "$working_faqprog" = "yes" )
|
||||
|
||||
if test $working_faqprog = no; then
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** It seems that the faqprog.pl program is not installed.
|
||||
*** Unless you do not change the source of the FAQs it is not required.
|
||||
*** The working version of this utility should be available at:
|
||||
*** ftp://ftp.gnupg.org/pub/gcrypt/contrib/faqprog.pl
|
||||
***]])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
dnl GNUPG_LINK_FILES( SRC, DEST )
|
||||
@ -358,7 +384,7 @@ define(GNUPG_CHECK_MLOCK,
|
||||
#endif
|
||||
], [
|
||||
int i;
|
||||
mkdir ("foo", 0);
|
||||
|
||||
/* glibc defines this for functions which it implements
|
||||
* to always fail with ENOSYS. Some functions are actually
|
||||
* named something starting with __ and the normal name
|
||||
|
@ -1,3 +1,21 @@
|
||||
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rndlinux.c (open_device): Loose random device checking.
|
||||
By Nils Ellmenreich.
|
||||
|
||||
* random.c (fast_random_poll): Check ENOSYS for getrusage.
|
||||
* rndunix.c: Add 2 sources for QNX. By Sam Roberts.
|
||||
|
||||
* pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE.
|
||||
|
||||
* rsa.c: Changed the comment about the patent.
|
||||
(secret): Speed up by using the CRT. For a 2k keys this
|
||||
is about 3 times faster.
|
||||
(stronger_key_check): New but unused code to check the secret key.
|
||||
* Makefile.am: Included rsa.[ch].
|
||||
* pubkey.c: Enabled RSA support.
|
||||
(pubkey_get_npkey): Removed RSA workaround.
|
||||
|
||||
Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new
|
||||
|
@ -50,6 +50,7 @@ libcipher_la_SOURCES = cipher.c \
|
||||
rmd.h \
|
||||
dsa.h \
|
||||
dsa.c \
|
||||
rsa.c rsa.h \
|
||||
smallprime.c \
|
||||
construct.c
|
||||
|
||||
|
@ -30,9 +30,7 @@
|
||||
#include "cipher.h"
|
||||
#include "elgamal.h"
|
||||
#include "dsa.h"
|
||||
#if 0
|
||||
#include "rsa.h"
|
||||
#endif
|
||||
#include "dynload.h"
|
||||
|
||||
/* FIXME: use set_lasterr() */
|
||||
@ -196,7 +194,6 @@ setup_pubkey_table(void)
|
||||
BUG();
|
||||
i++;
|
||||
|
||||
#if 0
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_RSA;
|
||||
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
@ -248,7 +245,6 @@ setup_pubkey_table(void)
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
#endif
|
||||
|
||||
for( ; i < TABLE_SIZE; i++ )
|
||||
pubkey_table[i].name = NULL;
|
||||
@ -433,8 +429,6 @@ pubkey_get_npkey( int algo )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].npkey;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 2; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -450,8 +444,6 @@ pubkey_get_nskey( int algo )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nskey;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 6; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -467,8 +459,6 @@ pubkey_get_nsig( int algo )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nsig;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 1; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -484,8 +474,6 @@ pubkey_get_nenc( int algo )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nenc;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 1; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1509,6 +1497,11 @@ gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
|
||||
* Buffer must be NULL, nbytes may have the address of a variable
|
||||
* with the required usage of the algorithm. It may be 0 for don't
|
||||
* care or a combination of the GCRY_PK_USAGE_xxx flags;
|
||||
* GCRYCTL_GET_ALGO_USAGE:
|
||||
* Return the usage glafs for the give algo. An invalid alog
|
||||
* does return 0. Disabled algos are ignored here becuase we
|
||||
* only want to know whether the algo is at all capable of
|
||||
* the usage.
|
||||
*
|
||||
* On error the value -1 is returned and the error reason may be
|
||||
* retrieved by gcry_errno().
|
||||
@ -1535,6 +1528,15 @@ gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
|
||||
}
|
||||
break;
|
||||
|
||||
case GCRYCTL_GET_ALGO_USAGE:
|
||||
do {
|
||||
int i;
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].use;
|
||||
} while( load_pubkey_modules() );
|
||||
return 0;
|
||||
|
||||
case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
|
||||
case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
|
||||
case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
|
||||
|
@ -604,7 +604,9 @@ fast_random_poll()
|
||||
#endif
|
||||
#else
|
||||
{ struct rusage buf;
|
||||
if( getrusage( RUSAGE_SELF, &buf ) )
|
||||
/* QNX/Neutrino does return ENOSYS - so we just ignore it and
|
||||
* add whatever is in buf */
|
||||
if( getrusage( RUSAGE_SELF, &buf ) && errno != ENOSYS )
|
||||
BUG();
|
||||
add_randomness( &buf, sizeof buf, 1 );
|
||||
memset( &buf, 0, sizeof buf );
|
||||
|
@ -63,7 +63,7 @@ get_entropy_count( int fd )
|
||||
#endif
|
||||
|
||||
/****************
|
||||
* Used to open the Linux and xBSD /dev/random devices
|
||||
* Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists), ...)
|
||||
*/
|
||||
static int
|
||||
open_device( const char *name, int minor )
|
||||
@ -76,8 +76,9 @@ open_device( const char *name, int minor )
|
||||
g10_log_fatal("can't open %s: %s\n", name, strerror(errno) );
|
||||
if( fstat( fd, &sb ) )
|
||||
g10_log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
|
||||
if( !S_ISCHR(sb.st_mode) )
|
||||
g10_log_fatal("invalid random device!\n" );
|
||||
/* Don't check device type for better portability */
|
||||
/* if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
|
||||
g10_log_fatal("invalid random device!\n" ); */
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,7 @@ static struct RI {
|
||||
{ "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/
|
||||
{ "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 },
|
||||
/* Unreliable source, depends on system usage */
|
||||
@ -292,6 +293,10 @@ static struct RI {
|
||||
/* This is a complex and screwball program. Some systems have things
|
||||
* like rX_dmn, x = integer, for RAID systems, but the statistics are
|
||||
* pretty dodgy */
|
||||
#ifdef __QNXNTO__
|
||||
{ "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
|
||||
NULL, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if 0
|
||||
/* The following aren't enabled since they're somewhat slow and not very
|
||||
* unpredictable, however they give an indication of the sort of sources
|
||||
|
136
cipher/rsa.c
136
cipher/rsa.c
@ -1,10 +1,6 @@
|
||||
/* rsa.c - RSA function
|
||||
* Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
|
||||
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
***********************************************************************
|
||||
* ATTENTION: This code should not be used in the United States
|
||||
* before the U.S. Patent #4,405,829 expires on September 20, 2000!
|
||||
***********************************************************************
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,11 +19,16 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* This code uses an algorithm protected by U.S. Patent #4,405,829
|
||||
which expires on September 20, 2000. The patent holder placed that
|
||||
patent into the public domain on Sep 6th, 2000.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "g10lib.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "rsa.h"
|
||||
@ -68,7 +69,7 @@ test_keys( RSA_secret_key *sk, unsigned nbits )
|
||||
pk.e = sk->e;
|
||||
{ char *p = get_random_bits( nbits, 0, 0 );
|
||||
mpi_set_buffer( test, p, (nbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
g10_free(p);
|
||||
}
|
||||
|
||||
public( out1, test, &pk );
|
||||
@ -200,22 +201,111 @@ public(MPI output, MPI input, RSA_public_key *pkey )
|
||||
mpi_powm( output, input, pkey->e, pkey->n );
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
stronger_key_check ( RSA_secret_key *skey )
|
||||
{
|
||||
MPI t = mpi_alloc_secure ( 0 );
|
||||
MPI t1 = mpi_alloc_secure ( 0 );
|
||||
MPI t2 = mpi_alloc_secure ( 0 );
|
||||
MPI phi = mpi_alloc_secure ( 0 );
|
||||
|
||||
/* check that n == p * q */
|
||||
mpi_mul( t, skey->p, skey->q);
|
||||
if (mpi_cmp( t, skey->n) )
|
||||
log_info ( "RSA Oops: n != p * q\n" );
|
||||
|
||||
/* check that p is less than q */
|
||||
if( mpi_cmp( skey->p, skey->q ) > 0 )
|
||||
log_info ("RSA Oops: p >= q\n");
|
||||
|
||||
|
||||
/* check that e divides neither p-1 nor q-1 */
|
||||
mpi_sub_ui(t, skey->p, 1 );
|
||||
mpi_fdiv_r(t, t, skey->e );
|
||||
if ( !mpi_cmp_ui( t, 0) )
|
||||
log_info ( "RSA Oops: e divides p-1\n" );
|
||||
mpi_sub_ui(t, skey->q, 1 );
|
||||
mpi_fdiv_r(t, t, skey->e );
|
||||
if ( !mpi_cmp_ui( t, 0) )
|
||||
log_info ( "RSA Oops: e divides q-1\n" );
|
||||
|
||||
/* check that d is correct */
|
||||
mpi_sub_ui( t1, skey->p, 1 );
|
||||
mpi_sub_ui( t2, skey->q, 1 );
|
||||
mpi_mul( phi, t1, t2 );
|
||||
mpi_gcd(t, t1, t2);
|
||||
mpi_fdiv_q(t, phi, t);
|
||||
mpi_invm(t, skey->e, t );
|
||||
if ( mpi_cmp(t, skey->d ) )
|
||||
log_info ( "RSA Oops: d is wrong\n");
|
||||
|
||||
/* check for crrectness of u */
|
||||
mpi_invm(t, skey->p, skey->q );
|
||||
if ( mpi_cmp(t, skey->u ) )
|
||||
log_info ( "RSA Oops: u is wrong\n");
|
||||
|
||||
log_info ( "RSA secret key check finished\n");
|
||||
|
||||
mpi_free (t);
|
||||
mpi_free (t1);
|
||||
mpi_free (t2);
|
||||
mpi_free (phi);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT.
|
||||
*
|
||||
* m = c^d mod n
|
||||
*
|
||||
* Where m is OUTPUT, c is INPUT and d,n are elements of PKEY.
|
||||
* Or faster:
|
||||
*
|
||||
* FIXME: We should better use the Chinese Remainder Theorem
|
||||
* m1 = c ^ (d mod (p-1)) mod p
|
||||
* m2 = c ^ (d mod (q-1)) mod q
|
||||
* h = u * (m2 - m1) mod q
|
||||
* m = m1 + h * p
|
||||
*
|
||||
* Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY.
|
||||
*/
|
||||
static void
|
||||
secret(MPI output, MPI input, RSA_secret_key *skey )
|
||||
{
|
||||
#if 0
|
||||
mpi_powm( output, input, skey->d, skey->n );
|
||||
#else
|
||||
MPI m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
MPI m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
MPI h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
|
||||
/* m1 = c ^ (d mod (p-1)) mod p */
|
||||
mpi_sub_ui( h, skey->p, 1 );
|
||||
mpi_fdiv_r( h, skey->d, h );
|
||||
mpi_powm( m1, input, h, skey->p );
|
||||
/* m2 = c ^ (d mod (q-1)) mod q */
|
||||
mpi_sub_ui( h, skey->q, 1 );
|
||||
mpi_fdiv_r( h, skey->d, h );
|
||||
mpi_powm( m2, input, h, skey->q );
|
||||
/* h = u * ( m2 - m1 ) mod q */
|
||||
mpi_sub( h, m2, m1 );
|
||||
if ( mpi_is_neg( h ) )
|
||||
mpi_add ( h, h, skey->q );
|
||||
mpi_mulm( h, skey->u, h, skey->q );
|
||||
/* m = m2 + h * p */
|
||||
mpi_mul ( h, h, skey->p );
|
||||
mpi_add ( output, m1, h );
|
||||
/* ready */
|
||||
|
||||
mpi_free ( h );
|
||||
mpi_free ( m1 );
|
||||
mpi_free ( m2 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************************************
|
||||
************** interface ******************
|
||||
*********************************************/
|
||||
@ -226,7 +316,7 @@ rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( !is_RSA(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
generate( &sk, nbits );
|
||||
skey[0] = sk.n;
|
||||
@ -236,7 +326,7 @@ rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
skey[4] = sk.q;
|
||||
skey[5] = sk.u;
|
||||
/* make an empty list of factors */
|
||||
*retfactors = m_alloc_clear( 1 * sizeof **retfactors );
|
||||
*retfactors = g10_xcalloc( 1, sizeof **retfactors );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -247,7 +337,7 @@ rsa_check_secret_key( int algo, MPI *skey )
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( !is_RSA(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
@ -256,7 +346,7 @@ rsa_check_secret_key( int algo, MPI *skey )
|
||||
sk.q = skey[4];
|
||||
sk.u = skey[5];
|
||||
if( !check_secret_key( &sk ) )
|
||||
return G10ERR_BAD_SECKEY;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -269,7 +359,7 @@ rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
RSA_public_key pk;
|
||||
|
||||
if( algo != 1 && algo != 2 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
pk.n = pkey[0];
|
||||
pk.e = pkey[1];
|
||||
@ -284,7 +374,7 @@ rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( algo != 1 && algo != 2 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
@ -303,7 +393,7 @@ rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( algo != 1 && algo != 3 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
@ -326,13 +416,13 @@ rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int rc;
|
||||
|
||||
if( algo != 1 && algo != 3 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
pk.n = pkey[0];
|
||||
pk.e = pkey[1];
|
||||
result = mpi_alloc( (160+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB);
|
||||
public( result, data[0], &pk );
|
||||
/*rc = (*cmp)( opaquev, result );*/
|
||||
rc = mpi_cmp( result, hash )? G10ERR_BAD_SIGN:0;
|
||||
rc = mpi_cmp( result, hash )? GCRYERR_BAD_SIGNATURE:0;
|
||||
mpi_free(result);
|
||||
|
||||
return rc;
|
||||
@ -366,10 +456,16 @@ rsa_get_info( int algo,
|
||||
*nsig = 1;
|
||||
|
||||
switch( algo ) {
|
||||
case 1: *usage = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; return "RSA";
|
||||
case 2: *usage = PUBKEY_USAGE_ENC; return "RSA-E";
|
||||
case 3: *usage = PUBKEY_USAGE_SIG; return "RSA-S";
|
||||
case 1: *usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR; return "RSA";
|
||||
case 2: *usage = GCRY_PK_USAGE_ENCR; return "RSA-E";
|
||||
case 3: *usage = GCRY_PK_USAGE_SIGN; return "RSA-S";
|
||||
default:*usage = 0; return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
33
configure.in
33
configure.in
@ -48,6 +48,11 @@ case "$use_static_rnd" in
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(egd-socket,
|
||||
[ --with-egd-socket=NAME Use NAME for the EGD socket)],
|
||||
egd_socket_name="$withval", egd_socket_name="" )
|
||||
AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name")
|
||||
|
||||
|
||||
|
||||
dnl
|
||||
@ -164,6 +169,7 @@ AC_ISC_POSIX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_AWK
|
||||
GPH_PROG_DOCBOOK
|
||||
GNUPG_CHECK_FAQPROG
|
||||
|
||||
|
||||
dnl
|
||||
@ -271,19 +277,30 @@ case "${target}" in
|
||||
*-openbsd*)
|
||||
NAME_OF_DEV_RANDOM="/dev/srandom"
|
||||
NAME_OF_DEV_URANDOM="/dev/urandom"
|
||||
DYNLINK_MOD_CFLAGS="-shared -rdynamic -fpic -Wl,-Bshareable -Wl,-x"
|
||||
DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x"
|
||||
;;
|
||||
|
||||
*-netbsd*)
|
||||
NAME_OF_DEV_RANDOM="/dev/random"
|
||||
NAME_OF_DEV_URANDOM="/dev/urandom"
|
||||
DYNLINK_MOD_CFLAGS="-shared -rdynamic -fpic -Wl,-Bshareable -Wl,-x"
|
||||
DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x"
|
||||
;;
|
||||
|
||||
*-solaris*)
|
||||
NAME_OF_DEV_RANDOM="/dev/random"
|
||||
NAME_OF_DEV_URANDOM="/dev/random"
|
||||
DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC"
|
||||
;;
|
||||
|
||||
*)
|
||||
NAME_OF_DEV_RANDOM="/dev/random"
|
||||
NAME_OF_DEV_URANDOM="/dev/urandom"
|
||||
DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC"
|
||||
# -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC.
|
||||
if test -n "$GCC" ; then
|
||||
DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC"
|
||||
else
|
||||
DYNLINK_MOD_CFLAGS="$CFLAGS_PIC"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM")
|
||||
@ -429,7 +446,7 @@ 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(memicmp atexit raise getpagesize strftime nl_langinfo)
|
||||
AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask)
|
||||
AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask fopen64 fstat64)
|
||||
|
||||
GNUPG_CHECK_MLOCK
|
||||
GNUPG_FUNC_MKDIR_TAKES_ONE_ARG
|
||||
@ -473,7 +490,7 @@ dnl check whether we have a random device
|
||||
dnl
|
||||
if test "$try_dev_random" = yes ; then
|
||||
AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
|
||||
[if test -c "$NAME_OF_DEV_RANDOM" && test -c "$NAME_OF_DEV_URANDOM" ; then
|
||||
[if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then
|
||||
ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi])
|
||||
if test "$ac_cv_have_dev_random" = yes; then
|
||||
AC_DEFINE(HAVE_DEV_RANDOM)
|
||||
@ -740,10 +757,16 @@ cat >gnupg-defs.tmp <<G10EOF
|
||||
#define GNUPG_LOCALEDIR "c:/lib/gnupg/locale"
|
||||
#define GNUPG_LIBDIR "c:/lib/gnupg"
|
||||
#define GNUPG_DATADIR "c:/lib/gnupg"
|
||||
#define GNUPG_HOMEDIR "c:/gnupg-test"
|
||||
#else
|
||||
#define GNUPG_LOCALEDIR "${prefix}/${DATADIRNAME}/locale"
|
||||
#define GNUPG_LIBDIR "${libdir}/gnupg"
|
||||
#define GNUPG_DATADIR "${datadir}/gnupg"
|
||||
#ifdef __VMS
|
||||
#define GNUPG_HOMEDIR "/SYS\$LOGIN/gnupg"
|
||||
#else
|
||||
#define GNUPG_HOMEDIR "~/.gnupg-test"
|
||||
#endif
|
||||
#endif
|
||||
G10EOF
|
||||
if cmp -s gnupg-defs.h gnupg-defs.tmp 2>/dev/null; then
|
||||
|
@ -1,3 +1,81 @@
|
||||
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* parse-packet.c (dump_sig_subpkt): Dump key flags.
|
||||
(parse_one_sig_subpkt,can_handle_critical): Add KeyFlags support.
|
||||
* build-packet.c (build_sig_subpkt): Ditto.
|
||||
|
||||
* g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen.
|
||||
* keygen.c (ask_user_id): Implemented here.
|
||||
|
||||
* parse-packet.c (dump_sig_subpkt): Print info about the ARR.
|
||||
|
||||
* openfile.c (overwrite_filep): Always return okay if the file is
|
||||
called /dev/null.
|
||||
(make_outfile_name): Add ".sign" to the list of know extensions.
|
||||
(open_sigfile): Ditto.
|
||||
|
||||
* getkey.c: Large parts rewritten to have a better sub key selection
|
||||
and handle some meta information from signatures more correctly.
|
||||
(get_primary_seckey): Removed.
|
||||
* seckey_cert.c (do_check): Set main keyid from the data in the sk.
|
||||
* free-packet.c (copy_public_parts_to_secret_key): New.
|
||||
* sig-check.c (check_key_signature2): Enabled shortcut for already
|
||||
checked signatures.
|
||||
* keydb.h: New macros IS_xxx_SIG, IS_xxx_REV.
|
||||
* misc.c (openpgp_pk_algo_usage): New.
|
||||
* packet.h: New field req_uage and do not use pubkey_usage anymore
|
||||
to request a specific usage. Changed at all places.
|
||||
* keyid.c (keyid_from_sk): Cache the keyid in the sk
|
||||
|
||||
* passphrase.c (hash_passphrase): Removed funny assert. Reported by
|
||||
David Mathog.
|
||||
|
||||
* keyedit.c (keyedit_menu): Allow "debug" on secret keys.
|
||||
|
||||
* keygen.c (keygen_add_std_prefs): Changed order of preferences to
|
||||
twofish, cast5, blowfish.
|
||||
|
||||
* gpg.c: The --trusted-key option is back.
|
||||
* trustdb.c (verify_own_key): Handle this option.
|
||||
(add_ultimate_key): Moved stuff from verify_own_key to this new func.
|
||||
(register_trusted_key): New.
|
||||
|
||||
* openfile.c (try_make_homedir): Changes for non-Posix systems.
|
||||
* gpg.c (main): Take the default homedir from macro.
|
||||
|
||||
* encode.c (encode_simple, encode_crypt): Fix for large files.
|
||||
* sign.c (sign_file): Ditto.
|
||||
|
||||
* gpg.c (main): Don't set --quite along with --no-tty. By Frank Tobin.
|
||||
|
||||
* misc.c (disable_core_dump): Don't display a warning here but a return
|
||||
a status value and ...
|
||||
* gpg.c (main): ...print warning here. Suggested by Sam Roberts.
|
||||
|
||||
* misc.c (print_pubkey_algo_note): Do not print the RSA notice.
|
||||
* sig-check.c (do_signature_check): Do not emit the RSA status message.
|
||||
* pubkey-enc.c (get_session_key): Ditto.
|
||||
|
||||
* ringedit.c (cmp_seckey): Fix for v4 RSA keys.
|
||||
* seckey-cert.c (do_check): Workaround for PGP 7 bug.
|
||||
|
||||
* pkclist.c (algo_available): Removed hack to disable Twofish.
|
||||
|
||||
* gpg.c (main): Default S2K algorithms are now SHA1 and CAST5 - this
|
||||
should solve a lot of compatibility problems with other OpenPGP
|
||||
apps because those algorithms are SHOULD and not optional. The old
|
||||
way to force it was by using the --openpgp option whith the drawback
|
||||
that this would disable a couple of workarounds for PGP.
|
||||
|
||||
* gpg.c: New option --merge-only. Suggested by Brendan O'Dea.
|
||||
* import.c (import_one): Implemented it here.
|
||||
(import_secret_one): Ditto.
|
||||
(print_stats): and give some stats.
|
||||
|
||||
* gpg.c: New option --try-all-secrets on suggestion from
|
||||
Matthias Urlichs.
|
||||
* pubkey-enc.c (get_session_key): Quite easy to implement here.
|
||||
|
||||
Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* gpg.c: New option --use-agent
|
||||
|
@ -701,6 +701,7 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
||||
case SIGSUBPKT_NOTATION:
|
||||
case SIGSUBPKT_POLICY:
|
||||
case SIGSUBPKT_REVOC_REASON:
|
||||
case SIGSUBPKT_KEY_FLAGS:
|
||||
hashed = 1; break;
|
||||
default: hashed = 0; break;
|
||||
}
|
||||
|
@ -220,6 +220,10 @@ encode_simple( const char *filename, int mode )
|
||||
if( filename && !opt.textmode && !mode ) {
|
||||
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 */
|
||||
@ -368,6 +372,10 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
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 */
|
||||
|
@ -139,6 +139,32 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
||||
return copy_public_key_new_namehash( d, s, NULL );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Replace all common parts of a sk by the one from the public key.
|
||||
* This is a hack and a better solution will be to just store the real secret
|
||||
* parts somewhere and don't duplicate all the other stuff.
|
||||
*/
|
||||
void
|
||||
copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
|
||||
{
|
||||
sk->expiredate = pk->expiredate;
|
||||
sk->pubkey_algo = pk->pubkey_algo;
|
||||
sk->pubkey_usage= pk->pubkey_usage;
|
||||
sk->created = pk->created;
|
||||
sk->req_usage = pk->req_usage;
|
||||
sk->req_algo = pk->req_algo;
|
||||
sk->has_expired = pk->has_expired;
|
||||
sk->is_revoked = pk->is_revoked;
|
||||
sk->is_valid = pk->is_valid;
|
||||
sk->main_keyid[0]= pk->main_keyid[0];
|
||||
sk->main_keyid[1]= pk->main_keyid[1];
|
||||
sk->keyid[0] = pk->keyid[0];
|
||||
sk->keyid[1] = pk->keyid[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
PKT_signature *
|
||||
copy_signature( PKT_signature *d, PKT_signature *s )
|
||||
{
|
||||
@ -450,3 +476,7 @@ cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1693
g10/getkey.c
1693
g10/getkey.c
File diff suppressed because it is too large
Load Diff
44
g10/gpg.c
44
g10/gpg.c
@ -179,6 +179,7 @@ enum cmd_and_opt_values { aNull = 0,
|
||||
oDisableCipherAlgo,
|
||||
oDisablePubkeyAlgo,
|
||||
oAllowNonSelfsignedUID,
|
||||
oAllowFreeformUID,
|
||||
oNoLiteral,
|
||||
oSetFilesize,
|
||||
oHonorHttpProxy,
|
||||
@ -188,7 +189,9 @@ enum cmd_and_opt_values { aNull = 0,
|
||||
oNoRandomSeedFile,
|
||||
oNoAutoKeyRetrieve,
|
||||
oUseAgent,
|
||||
oEmu3DESS2KBug, /* will be removed in 1.1 */
|
||||
oMergeOnly,
|
||||
oTryAllSecrets,
|
||||
oTrustedKey,
|
||||
oEmuMDEncodeBug,
|
||||
aTest };
|
||||
|
||||
@ -290,6 +293,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ oCompletesNeeded, "completes-needed", 1, "@"},
|
||||
{ oMarginalsNeeded, "marginals-needed", 1, "@"},
|
||||
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
|
||||
{ oTrustedKey, "trusted-key", 2, N_("|KEYID|ulimately trust this key")},
|
||||
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
|
||||
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
|
||||
{ oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")},
|
||||
@ -362,6 +366,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ oDisableCipherAlgo, "disable-cipher-algo", 2, "@" },
|
||||
{ oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" },
|
||||
{ oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" },
|
||||
{ oAllowFreeformUID, "allow-freeform-uid", 0, "@" },
|
||||
{ oNoLiteral, "no-literal", 0, "@" },
|
||||
{ oSetFilesize, "set-filesize", 20, "@" },
|
||||
{ oHonorHttpProxy,"honor-http-proxy", 0, "@" },
|
||||
@ -370,7 +375,8 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
|
||||
{ oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
|
||||
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
|
||||
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
|
||||
{ oMergeOnly, "merge-only", 0, "@" },
|
||||
{ oTryAllSecrets, "try-all-secrets", 0, "@" },
|
||||
{ oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
|
||||
{0} };
|
||||
|
||||
@ -601,6 +607,7 @@ main( int argc, char **argv )
|
||||
char **orig_argv;
|
||||
const char *fname;
|
||||
char *username;
|
||||
int may_coredump;
|
||||
STRLIST sl, remusr= NULL, locusr=NULL;
|
||||
STRLIST nrings=NULL, sec_nrings=NULL;
|
||||
armor_filter_context_t afx;
|
||||
@ -642,7 +649,7 @@ main( int argc, char **argv )
|
||||
}
|
||||
|
||||
gcry_control( GCRYCTL_USE_SECURE_RNDPOOL );
|
||||
disable_core_dumps();
|
||||
may_coredump = disable_core_dumps();
|
||||
init_signals();
|
||||
create_dotlock(NULL); /* register locking cleanup */
|
||||
i18n_init();
|
||||
@ -653,8 +660,8 @@ main( int argc, char **argv )
|
||||
opt.def_digest_algo = 0;
|
||||
opt.def_compress_algo = 2;
|
||||
opt.s2k_mode = 3; /* iterated+salted */
|
||||
opt.s2k_digest_algo = GCRY_MD_RMD160;
|
||||
opt.s2k_cipher_algo = GCRY_CIPHER_BLOWFISH;
|
||||
opt.s2k_digest_algo = GCRY_MD_SHA1;
|
||||
opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
|
||||
opt.completes_needed = 1;
|
||||
opt.marginals_needed = 3;
|
||||
opt.max_cert_depth = 5;
|
||||
@ -666,11 +673,7 @@ main( int argc, char **argv )
|
||||
opt.homedir = getenv("GNUPGHOME");
|
||||
#endif
|
||||
if( !opt.homedir || !*opt.homedir ) {
|
||||
#ifdef HAVE_DRIVE_LETTERS
|
||||
opt.homedir = "c:/gnupg-test";
|
||||
#else
|
||||
opt.homedir = "~/.gnupg-test";
|
||||
#endif
|
||||
opt.homedir = GNUPG_HOMEDIR;
|
||||
}
|
||||
|
||||
/* check whether we have a config file on the commandline */
|
||||
@ -801,7 +804,7 @@ main( int argc, char **argv )
|
||||
case oArmor: opt.armor = 1; opt.no_armor=0; break;
|
||||
case oOutput: opt.outfile = pargs.r.ret_str; break;
|
||||
case oQuiet: opt.quiet = 1; break;
|
||||
case oNoTTY: opt.quiet = 1; tty_no_terminal(1); break;
|
||||
case oNoTTY: tty_no_terminal(1); break;
|
||||
case oDryRun: opt.dry_run = 1; break;
|
||||
case oInteractive: opt.interactive = 1; break;
|
||||
case oVerbose:
|
||||
@ -894,7 +897,6 @@ main( int argc, char **argv )
|
||||
opt.s2k_digest_algo = GCRY_MD_SHA1;
|
||||
opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
|
||||
break;
|
||||
case oEmu3DESS2KBug: opt.emulate_bugs |= EMUBUG_3DESS2K; break;
|
||||
case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
|
||||
case oCompressSigs: opt.compress_sigs = 1; break;
|
||||
case oRunAsShmCP:
|
||||
@ -965,6 +967,7 @@ main( int argc, char **argv )
|
||||
}
|
||||
break;
|
||||
case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break;
|
||||
case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
|
||||
case oNoLiteral: opt.no_literal = 1; break;
|
||||
case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
|
||||
case oHonorHttpProxy: opt.honor_http_proxy = 1; break;
|
||||
@ -973,6 +976,9 @@ main( int argc, char **argv )
|
||||
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
|
||||
case oNoRandomSeedFile: use_random_seed = 0; break;
|
||||
case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break;
|
||||
case oMergeOnly: opt.merge_only = 1; break;
|
||||
case oTryAllSecrets: opt.try_all_secrets = 1; break;
|
||||
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
|
||||
|
||||
default : pargs.err = configfp? 1:2; break;
|
||||
}
|
||||
@ -1001,6 +1007,10 @@ main( int argc, char **argv )
|
||||
log_info("used in a production environment or with production keys!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if( may_coredump && !opt.quiet )
|
||||
log_info(_("WARNING: program may create a core file!\n"));
|
||||
|
||||
if (opt.no_literal) {
|
||||
log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
|
||||
if (opt.textmode)
|
||||
@ -1406,9 +1416,13 @@ main( int argc, char **argv )
|
||||
|
||||
|
||||
case aPrimegen:
|
||||
{ int mode = argc < 2 ? 0 : atoi(*argv);
|
||||
{
|
||||
#if 1
|
||||
log_error( "command is currently not implemented\n");
|
||||
#else
|
||||
/* FIXME: disabled until we have an API to create primes */
|
||||
int mode = argc < 2 ? 0 : atoi(*argv);
|
||||
|
||||
#if 0 /* FIXME: disabled until we have an API to create primes */
|
||||
if( mode == 1 && argc == 2 ) {
|
||||
mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1);
|
||||
}
|
||||
@ -1435,9 +1449,9 @@ main( int argc, char **argv )
|
||||
mpi_release(g);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
wrong_args("--gen-prime mode bits [qbits] ");
|
||||
putchar('\n');
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
13
g10/import.c
13
g10/import.c
@ -50,6 +50,7 @@ static struct {
|
||||
ulong secret_read;
|
||||
ulong secret_imported;
|
||||
ulong secret_dups;
|
||||
ulong skipped_new_keys;
|
||||
} stats;
|
||||
|
||||
|
||||
@ -201,6 +202,9 @@ print_stats()
|
||||
{
|
||||
if( !opt.quiet ) {
|
||||
log_info(_("Total number processed: %lu\n"), stats.count );
|
||||
if( stats.skipped_new_keys )
|
||||
log_info(_(" skipped new keys: %lu\n"),
|
||||
stats.skipped_new_keys );
|
||||
if( stats.no_user_id )
|
||||
log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id );
|
||||
if( stats.imported || stats.imported_rsa ) {
|
||||
@ -413,6 +417,13 @@ import_one( const char *fname, KBNODE keyblock, int fast )
|
||||
log_error( _("key %08lX: public key not found: %s\n"),
|
||||
(ulong)keyid[1], gpg_errstr(rc));
|
||||
}
|
||||
else if ( rc && opt.merge_only ) {
|
||||
if( opt.verbose )
|
||||
log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] );
|
||||
rc = 0;
|
||||
fast = 1; /* so that we don't get into the trustdb update */
|
||||
stats.skipped_new_keys++;
|
||||
}
|
||||
else if( rc ) { /* insert this key */
|
||||
/* get default resource */
|
||||
if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
|
||||
@ -583,7 +594,7 @@ import_secret_one( const char *fname, KBNODE keyblock )
|
||||
|
||||
/* do we have this key already in one of our secrings ? */
|
||||
rc = seckey_available( keyid );
|
||||
if( rc == GPGERR_NO_SECKEY ) { /* simply insert this key */
|
||||
if( rc == GPGERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */
|
||||
/* get default resource */
|
||||
if( get_keyblock_handle( NULL, 1, &kbpos ) ) {
|
||||
log_error("no default secret keyring\n");
|
||||
|
@ -31,6 +31,15 @@
|
||||
|
||||
#define MAX_FINGERPRINT_LEN 20
|
||||
|
||||
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
|
||||
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
|
||||
#define IS_SUBKEY_SIG(s) ((s)->sig_class == 0x18)
|
||||
#define IS_KEY_REV(s) ((s)->sig_class == 0x20)
|
||||
#define IS_UID_REV(s) ((s)->sig_class == 0x30)
|
||||
#define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28)
|
||||
|
||||
|
||||
|
||||
struct getkey_ctx_s;
|
||||
typedef struct getkey_ctx_s *GETKEY_CTX;
|
||||
|
||||
|
@ -592,7 +592,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
||||
{ N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") },
|
||||
{ N_("s") , cmdSIGN , 0,1,1, NULL },
|
||||
{ N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") },
|
||||
{ N_("debug") , cmdDEBUG , 0,1,0, NULL },
|
||||
{ N_("debug") , cmdDEBUG , 0,0,0, NULL },
|
||||
{ N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
|
||||
{ N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") },
|
||||
{ N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
|
||||
|
10
g10/keygen.c
10
g10/keygen.c
@ -136,8 +136,8 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
|
||||
keygen_add_key_expire( sig, opaque );
|
||||
|
||||
buf[0] = GCRY_CIPHER_TWOFISH;
|
||||
buf[1] = GCRY_CIPHER_BLOWFISH;
|
||||
buf[2] = GCRY_CIPHER_CAST5;
|
||||
buf[1] = GCRY_CIPHER_CAST5;
|
||||
buf[2] = GCRY_CIPHER_BLOWFISH;
|
||||
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 3 );
|
||||
|
||||
buf[0] = GCRY_MD_RMD160;
|
||||
@ -889,7 +889,11 @@ ask_user_id( int mode )
|
||||
aname = cpr_get("keygen.name",_("Real name: "));
|
||||
trim_spaces(aname);
|
||||
cpr_kill_prompt();
|
||||
if( strpbrk( aname, "<([])>" ) )
|
||||
|
||||
if( opt.allow_freeform_uid )
|
||||
break;
|
||||
|
||||
if( strpbrk( aname, "<>" ) )
|
||||
tty_printf(_("Invalid character in name\n"));
|
||||
else if( isdigit(*aname) )
|
||||
tty_printf(_("Name may not start with a digit\n"));
|
||||
|
10
g10/keyid.c
10
g10/keyid.c
@ -166,11 +166,17 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
|
||||
if( !keyid )
|
||||
keyid = dummy_keyid;
|
||||
|
||||
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
||||
if( sk->keyid[0] || sk->keyid[1] ) {
|
||||
keyid[0] = sk->keyid[0];
|
||||
keyid[1] = sk->keyid[1];
|
||||
}
|
||||
else if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
||||
if( pubkey_get_npkey(sk->pubkey_algo) )
|
||||
v3_keyid( sk->skey[0], keyid ); /* take n */
|
||||
else
|
||||
keyid[0] = keyid[1] = 0;
|
||||
sk->keyid[0] = keyid[0];
|
||||
sk->keyid[1] = keyid[1];
|
||||
}
|
||||
else {
|
||||
const byte *dp;
|
||||
@ -180,6 +186,8 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
|
||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
||||
gcry_md_close(md);
|
||||
sk->keyid[0] = keyid[0];
|
||||
sk->keyid[1] = keyid[1];
|
||||
}
|
||||
|
||||
return keyid[1];
|
||||
|
@ -51,7 +51,7 @@ char *make_radix64_string( const byte *data, size_t len );
|
||||
|
||||
/*-- misc.c --*/
|
||||
void trap_unaligned(void);
|
||||
void disable_core_dumps(void);
|
||||
int disable_core_dumps(void);
|
||||
u16 checksum_u16( unsigned n );
|
||||
u16 checksum( byte *p, unsigned n );
|
||||
u16 checksum_mpi( MPI a );
|
||||
@ -65,6 +65,7 @@ int mpi_print( FILE *fp, MPI a, int mode );
|
||||
|
||||
int openpgp_cipher_test_algo( int algo );
|
||||
int openpgp_pk_test_algo( int algo, unsigned int usage_flags );
|
||||
int openpgp_pk_algo_usage ( int algo );
|
||||
int openpgp_md_test_algo( int algo );
|
||||
|
||||
int pubkey_get_npkey( int algo );
|
||||
|
59
g10/misc.c
59
g10/misc.c
@ -68,22 +68,24 @@ trap_unaligned(void)
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
|
||||
int
|
||||
disable_core_dumps()
|
||||
{
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
return 0;
|
||||
#else
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
struct rlimit limit;
|
||||
|
||||
limit.rlim_cur = 0;
|
||||
limit.rlim_max = 0;
|
||||
if( !setrlimit( RLIMIT_CORE, &limit ) )
|
||||
return;
|
||||
if( errno != EINVAL )
|
||||
return 0;
|
||||
if( errno != EINVAL && errno != ENOSYS )
|
||||
log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
|
||||
#endif
|
||||
if( !opt.quiet )
|
||||
log_info(_("WARNING: program may create a core file!\n"));
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -318,15 +320,6 @@ print_pubkey_algo_note( int algo )
|
||||
{
|
||||
if( algo >= 100 && algo <= 110 )
|
||||
no_exp_algo();
|
||||
else if( is_RSA( algo ) ) {
|
||||
static int did_note = 0;
|
||||
|
||||
if( !did_note ) {
|
||||
did_note = 1;
|
||||
log_info(_("RSA keys are deprecated; please consider "
|
||||
"creating a new key and use this key in the future\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -362,7 +355,7 @@ print_digest_algo_note( int algo )
|
||||
|
||||
/****************
|
||||
* Wrapper around the libgcrypt function with addional checks on
|
||||
* openPGP contrainst for the algo ID.
|
||||
* openPGP contraints for the algo ID.
|
||||
*/
|
||||
int
|
||||
openpgp_cipher_test_algo( int algo )
|
||||
@ -382,6 +375,40 @@ openpgp_pk_test_algo( int algo, unsigned int usage_flags )
|
||||
return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
|
||||
}
|
||||
|
||||
int
|
||||
openpgp_pk_algo_usage ( int algo )
|
||||
{
|
||||
int usage = 0;
|
||||
|
||||
/* some are hardwired */
|
||||
switch ( algo ) {
|
||||
case GCRY_PK_RSA:
|
||||
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
|
||||
break;
|
||||
case GCRY_PK_RSA_E:
|
||||
usage = GCRY_PK_USAGE_ENCR;
|
||||
break;
|
||||
case GCRY_PK_RSA_S:
|
||||
usage = GCRY_PK_USAGE_SIGN;
|
||||
break;
|
||||
case GCRY_PK_ELG_E:
|
||||
usage = GCRY_PK_USAGE_ENCR;
|
||||
break;
|
||||
case GCRY_PK_DSA:
|
||||
usage = GCRY_PK_USAGE_SIGN;
|
||||
break;
|
||||
case GCRY_PK_ELG:
|
||||
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
|
||||
break;
|
||||
default:
|
||||
usage = gcry_pk_algo_info ( algo, GCRYCTL_GET_ALGO_USAGE,
|
||||
NULL, NULL);
|
||||
}
|
||||
return usage;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
openpgp_md_test_algo( int algo )
|
||||
|
@ -70,6 +70,11 @@ overwrite_filep( const char *fname )
|
||||
if( access( fname, F_OK ) )
|
||||
return 1; /* does not exist */
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if ( !strcmp ( fname, "/dev/null" ) )
|
||||
return 1; /* does not do any harm */
|
||||
#endif
|
||||
|
||||
/* fixme: add some backup stuff in case of overwrite */
|
||||
if( opt.answer_yes )
|
||||
return 1;
|
||||
@ -105,6 +110,12 @@ make_outfile_name( const char *iname )
|
||||
buf[n-4] = 0;
|
||||
return buf;
|
||||
}
|
||||
else if( n > 5 && !CMP_FILENAME(iname+n-5,".sign") ) {
|
||||
char *buf = gcry_xstrdup( iname );
|
||||
buf[n-5] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
log_info(_("%s: unknown suffix\n"), iname );
|
||||
return NULL;
|
||||
@ -241,6 +252,7 @@ open_sigfile( const char *iname )
|
||||
if( iname && !(*iname == '-' && !iname[1]) ) {
|
||||
len = strlen(iname);
|
||||
if( len > 4 && ( !strcmp(iname + len - 4, ".sig")
|
||||
|| ( len > 5 && !strcmp(iname + len - 5, ".sign") )
|
||||
|| !strcmp(iname + len - 4, ".asc")) ) {
|
||||
char *buf;
|
||||
buf = gcry_xstrdup(iname);
|
||||
@ -305,10 +317,24 @@ copy_options_file( const char *destdir )
|
||||
void
|
||||
try_make_homedir( const char *fname )
|
||||
{
|
||||
const char *defhome = GNUPG_HOMEDIR;
|
||||
|
||||
/* Create the directory only if the supplied directory name
|
||||
* is the same as the default one. This way we avoid to create
|
||||
* arbitrary directories when a non-default homedirectory is used.
|
||||
* To cope with HOME, we do compare only the suffix if we see that
|
||||
* the default homedir does start with a tilde.
|
||||
*/
|
||||
if( opt.dry_run )
|
||||
return;
|
||||
if( strlen(fname) >= 7
|
||||
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
|
||||
|
||||
if ( ( *defhome == '~'
|
||||
&& ( strlen(fname) >= strlen (defhome+1)
|
||||
&& !strcmp(fname+strlen(defhome+1)-strlen(defhome+1),
|
||||
defhome+1 ) ))
|
||||
|| ( *defhome != '~'
|
||||
&& !compare_filenames( fname, defhome ) )
|
||||
) {
|
||||
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
|
||||
log_fatal( _("%s: can't create directory: %s\n"),
|
||||
fname, strerror(errno) );
|
||||
@ -321,3 +347,5 @@ try_make_homedir( const char *fname )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -84,6 +84,7 @@ struct {
|
||||
const char *set_policy_url;
|
||||
int use_embedded_filename;
|
||||
int allow_non_selfsigned_uid;
|
||||
int allow_freeform_uid;
|
||||
int no_literal;
|
||||
ulong set_filesize;
|
||||
int honor_http_proxy;
|
||||
@ -92,6 +93,8 @@ struct {
|
||||
int command_fd;
|
||||
int auto_key_retrieve;
|
||||
int use_agent;
|
||||
int merge_only;
|
||||
int try_all_secrets;
|
||||
} opt;
|
||||
|
||||
|
||||
|
23
g10/packet.h
23
g10/packet.h
@ -128,8 +128,15 @@ typedef struct {
|
||||
byte hdrbytes; /* number of header bytes */
|
||||
byte version;
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
byte pubkey_usage; /* for now only used to pass it to getkey() */
|
||||
byte pubkey_usage; /* the actual allowed usage as set by getkey() */
|
||||
u32 created; /* according to the self-signature */
|
||||
byte req_usage; /* hack to pass a request to getkey() */
|
||||
byte req_algo; /* Ditto */
|
||||
u32 has_expired; /* set to the expiration date if expired */
|
||||
int is_revoked; /* key has been revoked */
|
||||
int is_valid; /* key (especially subkey) is valid */
|
||||
ulong local_id; /* internal use, valid if > 0 */
|
||||
u32 main_keyid[2]; /* keyid of the primary key */
|
||||
u32 keyid[2]; /* calculated by keyid_from_pk() */
|
||||
byte *namehash; /* if != NULL: found by this name */
|
||||
MPI pkey[GNUPG_MAX_NPKEY];
|
||||
@ -142,6 +149,14 @@ typedef struct {
|
||||
byte version;
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
byte pubkey_usage;
|
||||
u32 created; /* according to the self-signature */
|
||||
byte req_usage;
|
||||
byte req_algo;
|
||||
u32 has_expired; /* set to the expiration date if expired */
|
||||
int is_revoked; /* key has been revoked */
|
||||
int is_valid; /* key (especially subkey) is valid */
|
||||
u32 main_keyid[2]; /* keyid of the primary key */
|
||||
u32 keyid[2];
|
||||
byte is_primary;
|
||||
byte is_protected; /* The secret info is protected and must */
|
||||
/* be decrypted before use, the protected */
|
||||
@ -169,6 +184,10 @@ typedef struct {
|
||||
int len; /* length of the name */
|
||||
char *photo; /* if this is not NULL, the packet is a photo ID */
|
||||
int photolen; /* and the length of the photo */
|
||||
int help_key_usage;
|
||||
u32 help_key_expire;
|
||||
int is_primary;
|
||||
u32 created; /* according to the self-signature */
|
||||
char name[1];
|
||||
} PKT_user_id;
|
||||
|
||||
@ -322,6 +341,8 @@ PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
|
||||
PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d,
|
||||
PKT_public_key *s,
|
||||
const byte *namehash );
|
||||
void copy_public_parts_to_secret_key( PKT_public_key *pk,
|
||||
PKT_secret_key *sk );
|
||||
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
|
||||
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
||||
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );
|
||||
|
@ -700,6 +700,17 @@ dump_sig_subpkt( int hashed, int type, int critical,
|
||||
const char *p=NULL;
|
||||
int i;
|
||||
|
||||
/* The CERT has warning out with explains how to use GNUPG to
|
||||
* detect the ARRs - we print our old message here when it is a faked
|
||||
* ARR and add an additional notice */
|
||||
if ( type == SIGSUBPKT_ARR && !hashed ) {
|
||||
printf("\tsubpkt %d len %u (additional recipient request)\n"
|
||||
"WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
|
||||
"encrypt to this key and thereby reveal the plaintext to "
|
||||
"the owner of this ARR key. Detailed info follows:\n",
|
||||
type, (unsigned)length );
|
||||
}
|
||||
|
||||
printf("\t%s%ssubpkt %d len %u (", /*)*/
|
||||
critical ? "critical ":"",
|
||||
hashed ? "hashed ":"", type, (unsigned)length );
|
||||
@ -737,9 +748,6 @@ dump_sig_subpkt( int hashed, int type, int critical,
|
||||
printf("key expires after %s",
|
||||
strtimevalue( buffer_to_u32(buffer) ) );
|
||||
break;
|
||||
case SIGSUBPKT_ARR:
|
||||
p = "additional recipient request";
|
||||
break;
|
||||
case SIGSUBPKT_PREF_SYM:
|
||||
fputs("pref-sym-algos:", stdout );
|
||||
for( i=0; i < length; i++ )
|
||||
@ -809,8 +817,10 @@ dump_sig_subpkt( int hashed, int type, int critical,
|
||||
print_string( stdout, buffer, length, ')' );
|
||||
break;
|
||||
case SIGSUBPKT_KEY_FLAGS:
|
||||
p = "key flags";
|
||||
break;
|
||||
fputs ( "key flags:", stdout );
|
||||
for( i=0; i < length; i++ )
|
||||
printf(" %02X", buffer[i] );
|
||||
break;
|
||||
case SIGSUBPKT_SIGNERS_UID:
|
||||
p = "signer's user ID";
|
||||
break;
|
||||
@ -821,6 +831,16 @@ dump_sig_subpkt( int hashed, int type, int critical,
|
||||
p = ")";
|
||||
}
|
||||
break;
|
||||
case SIGSUBPKT_ARR:
|
||||
fputs("Big Brother's key (ignored): ", stdout );
|
||||
if( length < 22 )
|
||||
p = "[too short]";
|
||||
else {
|
||||
printf("c=%02x a=%d f=", buffer[0], buffer[1] );
|
||||
for( i=2; i < length; i++ )
|
||||
printf("%02X", buffer[i] );
|
||||
}
|
||||
break;
|
||||
case SIGSUBPKT_PRIV_ADD_SIG:
|
||||
p = "signs additional user ID";
|
||||
break;
|
||||
@ -846,6 +866,8 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
|
||||
if( n < 4 )
|
||||
break;
|
||||
return 0;
|
||||
case SIGSUBPKT_KEY_FLAGS:
|
||||
return 0;
|
||||
case SIGSUBPKT_EXPORTABLE:
|
||||
if( !n )
|
||||
break;
|
||||
@ -867,6 +889,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
|
||||
case SIGSUBPKT_PREF_COMPR:
|
||||
case SIGSUBPKT_POLICY:
|
||||
return 0;
|
||||
case SIGSUBPKT_PRIMARY_UID:
|
||||
if ( n != 1 )
|
||||
break;
|
||||
return 0;
|
||||
case SIGSUBPKT_PRIV_ADD_SIG:
|
||||
/* because we use private data, we check the GNUPG marker */
|
||||
if( n < 24 )
|
||||
@ -897,6 +923,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
|
||||
case SIGSUBPKT_PREF_SYM:
|
||||
case SIGSUBPKT_PREF_HASH:
|
||||
case SIGSUBPKT_PREF_COMPR:
|
||||
case SIGSUBPKT_KEY_FLAGS:
|
||||
return 1;
|
||||
|
||||
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
|
||||
@ -1288,7 +1315,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
sk->version = version;
|
||||
sk->is_primary = pkttype == PKT_SECRET_KEY;
|
||||
sk->pubkey_algo = algorithm;
|
||||
sk->pubkey_usage = 0; /* not yet used */
|
||||
sk->req_usage = 0;
|
||||
sk->pubkey_usage = 0; /* will be set by getkey functions */
|
||||
}
|
||||
else {
|
||||
PKT_public_key *pk = pkt->pkt.public_key;
|
||||
@ -1298,7 +1326,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
pk->hdrbytes = hdrlen;
|
||||
pk->version = version;
|
||||
pk->pubkey_algo = algorithm;
|
||||
pk->pubkey_usage = 0; /* not yet used */
|
||||
pk->req_usage = 0;
|
||||
pk->pubkey_usage = 0; /* will be set bey getkey functions */
|
||||
pk->is_revoked = 0;
|
||||
pk->keyid[0] = 0;
|
||||
pk->keyid[1] = 0;
|
||||
}
|
||||
|
@ -640,7 +640,6 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
|
||||
else {
|
||||
gcry_md_write( md, s2k->salt, 8 );
|
||||
count -= 8;
|
||||
assert( count >= 0 );
|
||||
gcry_md_write( md, pw, count );
|
||||
}
|
||||
}
|
||||
|
@ -814,13 +814,12 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
|
||||
any_recipients = 1;
|
||||
else if( (use & GCRY_PK_USAGE_ENCR) && !opt.no_encrypt_to ) {
|
||||
pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
pk->pubkey_usage = use;
|
||||
pk->req_usage = use;
|
||||
if( (rc = get_pubkey_byname( NULL, pk, rov->d, NULL )) ) {
|
||||
free_public_key( pk ); pk = NULL;
|
||||
log_error(_("%s: skipped: %s\n"), rov->d, gpg_errstr(rc) );
|
||||
}
|
||||
else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) {
|
||||
|
||||
/* Skip the actual key if the key is already present
|
||||
* in the list */
|
||||
if (key_present_in_pk_list(pk_list, pk) == 0) {
|
||||
@ -871,7 +870,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
|
||||
if( pk )
|
||||
free_public_key( pk );
|
||||
pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
pk->pubkey_usage = use;
|
||||
pk->req_usage = use;
|
||||
rc = get_pubkey_byname( NULL, pk, answer, NULL );
|
||||
if( rc )
|
||||
tty_printf(_("No such user ID.\n"));
|
||||
@ -937,7 +936,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
|
||||
}
|
||||
else if( !any_recipients && (def_rec = default_recipient()) ) {
|
||||
pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
pk->pubkey_usage = use;
|
||||
pk->req_usage = use;
|
||||
rc = get_pubkey_byname( NULL, pk, def_rec, NULL );
|
||||
if( rc )
|
||||
log_error(_("unknown default recipient `%s'\n"), def_rec );
|
||||
@ -962,7 +961,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
|
||||
continue; /* encrypt-to keys are already handled */
|
||||
|
||||
pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
pk->pubkey_usage = use;
|
||||
pk->req_usage = use;
|
||||
if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) {
|
||||
free_public_key( pk ); pk = NULL;
|
||||
log_error(_("%s: skipped: %s\n"), remusr->d, gpg_errstr(rc) );
|
||||
@ -1033,8 +1032,6 @@ static int
|
||||
algo_available( int preftype, int algo )
|
||||
{
|
||||
if( preftype == PREFTYPE_SYM ) {
|
||||
if( algo == GCRY_CIPHER_TWOFISH )
|
||||
return 0; /* we don't want to generate Twofish messages for now*/
|
||||
return algo && !openpgp_cipher_test_algo( algo );
|
||||
}
|
||||
else if( preftype == PREFTYPE_HASH ) {
|
||||
|
@ -106,14 +106,11 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
PKT_secret_key *sk = NULL;
|
||||
int rc;
|
||||
|
||||
if( is_RSA(k->pubkey_algo) ) /* warn about that */
|
||||
write_status(STATUS_RSA_OR_IDEA);
|
||||
|
||||
rc = openpgp_pk_test_algo( k->pubkey_algo, 0 );
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
if( k->keyid[0] || k->keyid[1] ) {
|
||||
if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
|
||||
if( !(rc = get_seckey( sk, k->keyid )) )
|
||||
|
@ -1114,7 +1114,13 @@ cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
|
||||
|
||||
n = pubkey_get_nskey( req_sk->pubkey_algo );
|
||||
for(i=0; i < n; i++ ) {
|
||||
if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
|
||||
/* Note: because v4 protected keys have nothing in the
|
||||
* mpis except for the first one, we skip all NULL MPIs.
|
||||
* This might not be always correct in cases where the both
|
||||
* keys do not match in their secret parts but we can ignore that
|
||||
* because the need for this function is quite ugly. */
|
||||
if( req_sk->skey[1] && sk->skey[i]
|
||||
&& mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -100,10 +100,8 @@ do_check( PKT_secret_key *sk )
|
||||
keyid_from_sk( sk, keyid );
|
||||
keyid[2] = keyid[3] = 0;
|
||||
if( !sk->is_primary ) {
|
||||
PKT_secret_key *sk2 = gcry_xcalloc( 1, sizeof *sk2 );
|
||||
if( !get_primary_seckey( sk2, keyid ) )
|
||||
keyid_from_sk( sk2, keyid+2 );
|
||||
free_secret_key( sk2 );
|
||||
keyid[2] = sk->main_keyid[0];
|
||||
keyid[3] = sk->main_keyid[1];
|
||||
}
|
||||
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
|
||||
&sk->protect.s2k, 0 );
|
||||
@ -128,11 +126,14 @@ do_check( PKT_secret_key *sk )
|
||||
size_t ndata;
|
||||
unsigned int ndatabits;
|
||||
byte *p, *data;
|
||||
u16 csumc = 0;
|
||||
|
||||
i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
|
||||
ndata = (ndatabits+7)/8;
|
||||
if ( ndata > 1 )
|
||||
csumc = p[ndata-2] << 8 | p[ndata-1];
|
||||
data = gcry_xmalloc_secure( ndata );
|
||||
gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
|
||||
mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
|
||||
@ -145,6 +146,10 @@ do_check( PKT_secret_key *sk )
|
||||
else {
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = data[ndata-2] << 8 | data[ndata-1];
|
||||
if ( sk->csum != csum ) {
|
||||
/* This is a PGP 7.0.0 workaround */
|
||||
sk->csum = csumc; /* take the encrypted one */
|
||||
}
|
||||
}
|
||||
/* must check it here otherwise the mpi_read_xx would fail
|
||||
* because the length may have an arbitrary value */
|
||||
@ -321,8 +326,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
||||
|
||||
#warning FIXME: replace set/get buffer
|
||||
if( sk->version >= 4 ) {
|
||||
/* FIXME: There is a bug in this function for all algorithms
|
||||
* where the secret MPIs are more than 1 */
|
||||
byte *bufarr[GNUPG_MAX_NSKEY];
|
||||
unsigned narr[GNUPG_MAX_NSKEY];
|
||||
unsigned nbits[GNUPG_MAX_NSKEY];
|
||||
|
@ -134,9 +134,6 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
int rc=0;
|
||||
|
||||
if( is_RSA(sig->pubkey_algo) )
|
||||
write_status(STATUS_RSA_OR_IDEA);
|
||||
|
||||
*r_expiredate = 0;
|
||||
if( get_pubkey( pk, sig->keyid ) )
|
||||
rc = GPGERR_NO_PUBKEY;
|
||||
@ -451,10 +448,18 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
||||
sig = node->pkt->pkt.signature;
|
||||
algo = sig->digest_algo;
|
||||
|
||||
#if 0 /* I am not sure whether this is a good thing to do */
|
||||
if( sig->flags.checked )
|
||||
#if 0
|
||||
if( sig->flags.checked ) {
|
||||
log_debug("check_key_signature: already checked: %s\n",
|
||||
sig->flags.valid? "good":"bad" );
|
||||
if ( sig->flags.valid )
|
||||
return 0; /* shortcut already checked signatures */
|
||||
/* FIXME: We should also do this with bad signatures but here we
|
||||
* have to distinguish between several reasons; e.g. for a missing
|
||||
* public key. the key may now be available.
|
||||
* For now we simply don't shortcut bad signatures
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (rc=openpgp_md_test_algo(algo)) )
|
||||
|
@ -485,6 +485,10 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
||||
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
|
||||
|
@ -59,7 +59,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
PKT_secret_key *sk;
|
||||
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk->pubkey_usage = use;
|
||||
sk->req_usage = use;
|
||||
if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error("no default secret key: %s\n", gpg_errstr(rc) );
|
||||
@ -90,7 +90,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
PKT_secret_key *sk;
|
||||
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk->pubkey_usage = use;
|
||||
sk->req_usage = use;
|
||||
if( (rc = get_seckey_byname( sk, locusr->d, unlock )) ) {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error(_("skipped `%s': %s\n"), locusr->d, gpg_errstr(rc) );
|
||||
|
121
g10/trustdb.c
121
g10/trustdb.c
@ -109,6 +109,7 @@ static TN used_tns;
|
||||
static int alloced_tns;
|
||||
static int max_alloced_tns;
|
||||
|
||||
static struct keyid_list *trusted_key_list;
|
||||
|
||||
static LOCAL_ID_TABLE new_lid_table(void);
|
||||
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
|
||||
@ -463,6 +464,64 @@ lid_from_keyid_no_sdir( u32 *keyid )
|
||||
************* Initialization ****************
|
||||
***********************************************/
|
||||
|
||||
void
|
||||
register_trusted_key( const char *string )
|
||||
{
|
||||
u32 keyid[2];
|
||||
struct keyid_list *r;
|
||||
|
||||
if( classify_user_id( string, keyid, NULL, NULL, NULL ) != 11 ) {
|
||||
log_error(_("'%s' is not a valid long keyID\n"), string );
|
||||
return;
|
||||
}
|
||||
|
||||
for( r = trusted_key_list; r; r = r->next )
|
||||
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] )
|
||||
return;
|
||||
r = gcry_xmalloc( sizeof *r );
|
||||
r->keyid[0] = keyid[0];
|
||||
r->keyid[1] = keyid[1];
|
||||
r->next = trusted_key_list;
|
||||
trusted_key_list = r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
add_ultimate_key( PKT_public_key *pk, u32 *keyid )
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* first make sure that the pubkey is in the trustdb */
|
||||
rc = query_trust_record( pk );
|
||||
if( rc == -1 && opt.dry_run )
|
||||
return;
|
||||
if( rc == -1 ) { /* put it into the trustdb */
|
||||
rc = insert_trust_record_by_pk( pk );
|
||||
if( rc ) {
|
||||
log_error(_("key %08lX: can't put it into the trustdb\n"),
|
||||
(ulong)keyid[1] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( rc ) {
|
||||
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
|
||||
return;
|
||||
}
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("key %08lX.%lu: stored into ultikey_table\n",
|
||||
(ulong)keyid[1], pk->local_id );
|
||||
|
||||
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
|
||||
log_error(_("key %08lX: already in trusted key table\n"),
|
||||
(ulong)keyid[1]);
|
||||
else if( opt.verbose > 1 )
|
||||
log_info(_("key %08lX: accepted as trusted key.\n"),
|
||||
(ulong)keyid[1]);
|
||||
|
||||
}
|
||||
|
||||
/****************
|
||||
* Verify that all our public keys are in the trustdb.
|
||||
*/
|
||||
@ -474,7 +533,27 @@ verify_own_keys(void)
|
||||
PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
u32 keyid[2];
|
||||
struct keyid_list *kl;
|
||||
|
||||
|
||||
/* put the trusted keys into the ultikey table */
|
||||
for( kl = trusted_key_list; kl; kl = kl->next ) {
|
||||
keyid[0] = kl->keyid[0];
|
||||
keyid[1] = kl->keyid[1];
|
||||
/* get the public key */
|
||||
memset( pk, 0, sizeof *pk );
|
||||
rc = get_pubkey( pk, keyid );
|
||||
if( rc ) {
|
||||
log_info(_("key %08lX: no public key for trusted key - skipped\n"),
|
||||
(ulong)keyid[1] );
|
||||
}
|
||||
else {
|
||||
add_ultimate_key( pk, keyid );
|
||||
release_public_key_parts( pk );
|
||||
}
|
||||
}
|
||||
|
||||
/* And now add all secret keys to the ultikey table */
|
||||
while( !(rc=enum_secret_keys( &enum_context, sk, 0 ) ) ) {
|
||||
int have_pk = 0;
|
||||
|
||||
@ -487,6 +566,10 @@ verify_own_keys(void)
|
||||
log_info(_("NOTE: secret key %08lX is NOT protected.\n"),
|
||||
(ulong)keyid[1] );
|
||||
|
||||
for( kl = trusted_key_list; kl; kl = kl->next ) {
|
||||
if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
|
||||
goto skip; /* already in trusted key table */
|
||||
}
|
||||
|
||||
/* see whether we can access the public key of this secret key */
|
||||
memset( pk, 0, sizeof *pk );
|
||||
@ -504,33 +587,8 @@ verify_own_keys(void)
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* make sure that the pubkey is in the trustdb */
|
||||
rc = query_trust_record( pk );
|
||||
if( rc == -1 && opt.dry_run )
|
||||
goto skip;
|
||||
if( rc == -1 ) { /* put it into the trustdb */
|
||||
rc = insert_trust_record_by_pk( pk );
|
||||
if( rc ) {
|
||||
log_error(_("key %08lX: can't put it into the trustdb\n"),
|
||||
(ulong)keyid[1] );
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
else if( rc ) {
|
||||
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
|
||||
goto skip;
|
||||
add_ultimate_key( pk, keyid );
|
||||
|
||||
}
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("key %08lX.%lu: stored into ultikey_table\n",
|
||||
(ulong)keyid[1], pk->local_id );
|
||||
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
|
||||
log_error(_("key %08lX: already in trusted key table\n"),
|
||||
(ulong)keyid[1]);
|
||||
else if( opt.verbose > 1 )
|
||||
log_info(_("key %08lX: accepted as trusted key.\n"),
|
||||
(ulong)keyid[1]);
|
||||
skip:
|
||||
release_secret_key_parts( sk );
|
||||
if( have_pk )
|
||||
@ -541,6 +599,15 @@ verify_own_keys(void)
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
/* release the trusted keyid table */
|
||||
{ struct keyid_list *kl2;
|
||||
for( kl = trusted_key_list; kl; kl = kl2 ) {
|
||||
kl2 = kl->next;
|
||||
gcry_free( kl );
|
||||
}
|
||||
trusted_key_list = NULL;
|
||||
}
|
||||
|
||||
enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
|
||||
free_secret_key( sk );
|
||||
free_public_key( pk );
|
||||
@ -548,6 +615,8 @@ verify_own_keys(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Perform some checks over the trustdb
|
||||
* level 0: only open the db
|
||||
|
@ -116,6 +116,7 @@ size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen );
|
||||
void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp );
|
||||
|
||||
u32 iobuf_get_filelength( IOBUF a );
|
||||
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
|
||||
const char *iobuf_get_real_fname( IOBUF a );
|
||||
const char *iobuf_get_fname( IOBUF a );
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* ring-a-party: substr starts at offset 1 not 0. Many thanks to Mike
|
||||
for finding this bug. Flush the last key.
|
||||
|
||||
Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@>
|
||||
|
||||
* mail-signed-keys: New.
|
||||
|
@ -31,6 +31,9 @@ BEGIN { FS=":"
|
||||
page = 0;
|
||||
now = strftime("%b %d %H:%M %Y");
|
||||
}
|
||||
END {
|
||||
if (any) myflush();
|
||||
}
|
||||
$1 == "pub" {
|
||||
if( any ) myflush();
|
||||
uidcount = 0;
|
||||
@ -84,7 +87,7 @@ function printfpr16( s )
|
||||
printf "f16 Fingerprint16 =";
|
||||
for(i=0; i < 16; i++ ) {
|
||||
if( i == 8 ) printf " ";
|
||||
printf " %s", substr( s, i*2, 2 );
|
||||
printf " %s", substr( s, i*2+1, 2 );
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
@ -94,10 +97,13 @@ function printfpr20( s )
|
||||
printf "f20 Fingerprint20 =";
|
||||
for(i=0; i < 10; i++ ) {
|
||||
if( i == 5 ) printf " ";
|
||||
printf " %s", substr( s, i*4, 4 );
|
||||
printf " %s", substr( s, i*4+1, 4 );
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
' | tee a.pub | gpg --print-mds
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,3 +1,15 @@
|
||||
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* strgutil.c (utf8_to_native): Fixed null ptr problem. By
|
||||
Giampaolo Tomassoni.
|
||||
|
||||
* iobuf.c: Use fopen64 insead of fopen when available.
|
||||
(iobuf_get_filelength): Use fstat64 when available but return
|
||||
2^32-1 if the file is larger than this value.
|
||||
|
||||
* miscutil.c (answer_is_yes_no_quit): Swapped order of yes/no test
|
||||
so that no is returned for an empty input. By David Champion.
|
||||
|
||||
Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* logger.c (log_set_file): Allow to set the file by name.
|
||||
|
29
util/iobuf.c
29
util/iobuf.c
@ -36,6 +36,14 @@
|
||||
#include "util.h"
|
||||
#include "iobuf.h"
|
||||
|
||||
|
||||
#if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
|
||||
#define fopen(a,b) fopen64 ((a),(b))
|
||||
#define fstat(a,b) fstat64 ((a),(b))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
FILE *fp; /* open file handle */
|
||||
int print_only_name; /* flags indicating that fname is not a real file*/
|
||||
@ -1312,25 +1320,40 @@ iobuf_set_limit( IOBUF a, unsigned long nlimit )
|
||||
u32
|
||||
iobuf_get_filelength( IOBUF a )
|
||||
{
|
||||
#if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
|
||||
struct stat64 st;
|
||||
#else
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
if( a->directfp ) {
|
||||
FILE *fp = a->directfp;
|
||||
|
||||
if( !fstat(fileno(fp), &st) )
|
||||
return st.st_size;
|
||||
if( !fstat(fileno(fp), &st) ) {
|
||||
#if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
|
||||
if( st.st_size >= IOBUF_FILELENGTH_LIMIT )
|
||||
return IOBUF_FILELENGTH_LIMIT;
|
||||
#endif
|
||||
return (u32)st.st_size;
|
||||
}
|
||||
log_error("fstat() failed: %s\n", strerror(errno) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Hmmm: file_filter may have already been removed */
|
||||
for( ; a; a = a->chain )
|
||||
if( !a->chain && a->filter == file_filter ) {
|
||||
file_filter_ctx_t *b = a->filter_ov;
|
||||
FILE *fp = b->fp;
|
||||
|
||||
if( !fstat(fileno(fp), &st) )
|
||||
if( !fstat(fileno(fp), &st) ) {
|
||||
#if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
|
||||
if( st.st_size >= IOBUF_FILELENGTH_LIMIT )
|
||||
return IOBUF_FILELENGTH_LIMIT;
|
||||
#endif
|
||||
return st.st_size;
|
||||
}
|
||||
log_error("fstat() failed: %s\n", strerror(errno) );
|
||||
break;
|
||||
}
|
||||
|
@ -311,16 +311,16 @@ answer_is_yes_no_quit( const char *s )
|
||||
char *short_no = _("nN");
|
||||
char *short_quit = _("qQ");
|
||||
|
||||
if( !stricmp(s, long_yes ) )
|
||||
return 1;
|
||||
if( !stricmp(s, long_no ) )
|
||||
return 0;
|
||||
if( !stricmp(s, long_yes ) )
|
||||
return 1;
|
||||
if( !stricmp(s, long_quit ) )
|
||||
return -1;
|
||||
if( strchr( short_yes, *s ) && !s[1] )
|
||||
return 1;
|
||||
if( strchr( short_no, *s ) && !s[1] )
|
||||
return 0;
|
||||
if( strchr( short_yes, *s ) && !s[1] )
|
||||
return 1;
|
||||
if( strchr( short_quit, *s ) && !s[1] )
|
||||
return -1;
|
||||
if( !stricmp(s, "yes" ) )
|
||||
|
@ -389,7 +389,8 @@ utf8_to_native( const char *string, size_t length )
|
||||
case 0 : n++; if( p ) *p++ = '0'; break;
|
||||
default: n += 3;
|
||||
sprintf( p, "x%02x", *s );
|
||||
p += 3;
|
||||
if ( p )
|
||||
p += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -496,3 +497,7 @@ utf8_to_native( const char *string, size_t length )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user