a couple of changes; but some parts are now broken

This commit is contained in:
Werner Koch 1998-02-11 03:25:44 +00:00
parent d6fa02add6
commit 4c0c155922
46 changed files with 1879 additions and 433 deletions

View File

@ -0,0 +1,5 @@
Tue Feb 10 11:57:23 1998 Werner Koch (wk@frodo)
* ddd/hhhh:

View File

@ -93,8 +93,8 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL \
Makefile.am Makefile.in NEWS TODO acconfig.h acinclude.m4 aclocal.m4 \
config.h.in configure configure.in stamp-h.in
Makefile.am Makefile.in NEWS THANKS TODO acconfig.h acinclude.m4 \
aclocal.m4 config.h.in configure configure.in stamp-h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

12
NEWS
View File

@ -1,3 +1,15 @@
Noteworthy changes in version 0.2.x
-----------------------------------
* nearly doubled the speed of the ElGamal signature verification.
* backup copies of keyrings are created.
* assembler stuff for Pentium; gives about 15% better perfomance.
Noteworthy changes in version 0.2.3
-----------------------------------
* Found a bug in the calculation of ELG fingerprints. This is now
fixed, but all existing fingerprints and keyids for ELG keys

26
THANKS Normal file
View File

@ -0,0 +1,26 @@
G10 has originally been written by Werner Koch. Other people contributed
by reporting problems, suggesting various improvements or submitting actual
code. Here is a list of these people. Help me keeping it complete and
exempt of errors.
Anand Kumria wildfire@progsoc.uts.edu.au
Daniel Eisenbud eisenbud@cs.swarthmore.edu
Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de
Ernst Molitor ernst.molitor@uni-bonn.de
Hendrik Buschkamp buschkamp@rheumanet.org
Jens Bachem bachem@rrz.uni-koeln.de
Peter Gutmann pgut001@cs.auckland.ac.nz
Ralph Gillen gillen@theochem.uni-duesseldorf.de
Thomas Roessler roessler@guug.de
Tomas Fasth tomas.fasth@twinspot.net
Walter Koch walterk@ddorf.rhein-ruhr.de
Werner Koch werner.koch@guug.de
Wim Vandeputte bunbun@reptile.rug.ac.be
Thanks to the German Unix User Group for providing FTP space and
Martin Hamilton for hosting the mailing list.
Many thanks to Gerlinde for having so much patience with me while
hacking late in the evening.

5
TODO
View File

@ -15,8 +15,6 @@
* complete cipher/cast.c
* complete cipher/dsa.c
* armor has now some problems.
* add g10 stuff to Mutt's pgpinvoke.c
* Burn the buffers used by fopen().
@ -27,7 +25,4 @@
we have a self-signature -> put this stuff into a kind of directory
record, as it does not belong to the pubkey record?
* Have no prototype for stpcpy() when using glibc 2; must switch on
the GNU extensions or see how configure can fix it.

View File

@ -1 +1 @@
0.2.3
0.2.3x

View File

@ -130,7 +130,7 @@ AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = ChangeLog Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

View File

@ -228,7 +228,7 @@ static const u32 ps[BLOWFISH_ROUNDS+2] = {
static u32
static inline u32
function_F( BLOWFISH_context *bc, u32 x )
{
u16 a, b, c, d;

View File

@ -311,25 +311,37 @@ elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey )
int rc;
MPI t1;
MPI t2;
MPI base[4];
MPI exp[4];
if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) )
return 0; /* assertion 0 < a < p failed */
t1 = mpi_alloc( mpi_get_nlimbs(a) );
t2 = mpi_alloc( mpi_get_nlimbs(a) );
/* t1 = (y^a mod p) * (a^b mod p) mod p
* fixme: should be calculated by a call which evalutes
* t1 = y^a * a^b mod p
* direct.
*/
mpi_powm( t1, pkey->y, a, pkey->p );
mpi_powm( t2, a, b, pkey->p );
mpi_mulm( t1, t1, t2, pkey->p );
#if 0
/* t1 = (y^a mod p) * (a^b mod p) mod p */
base[0] = pkey->y; exp[0] = a;
base[1] = a; exp[1] = b;
base[2] = NULL; exp[2] = NULL;
mpi_mulpowm( t1, base, exp, pkey->p );
/* t2 = g ^ input mod p */
mpi_powm( t2, pkey->g, input, pkey->p );
rc = !mpi_cmp( t1, t2 );
#else
/* t1 = g ^ - input * y ^ a * a ^ b mod p */
mpi_invm(t2, pkey->g, pkey->p );
base[0] = t2 ; exp[0] = input;
base[1] = pkey->y; exp[1] = a;
base[2] = a; exp[2] = b;
base[3] = NULL; exp[3] = NULL;
mpi_mulpowm( t1, base, exp, pkey->p );
rc = !mpi_cmp_ui( t1, 1 );
#endif
mpi_free(t1);
mpi_free(t2);

View File

@ -93,7 +93,18 @@ static byte PADDING[64] = {
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#if defined(__GNUC__) && defined(__i386__)
static inline u32
ROTATE_LEFT(u32 x, int n)
{
__asm__("roll %%cl,%0"
:"=r" (x)
:"0" (x),"c" (n));
return x;
}
#else
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#endif
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */

View File

@ -151,6 +151,20 @@ rmd160_init( RMD160_CONTEXT *hd )
}
#if defined(__GNUC__) && defined(__i386__)
static inline u32
rol(int n, u32 x)
{
__asm__("roll %%cl,%0"
:"=r" (x)
:"0" (x),"c" (n));
return x;
}
#else
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
#endif
/****************
* Transform the message X which consists of 16 32-bit-words
*/
@ -209,9 +223,6 @@ transform( RMD160_CONTEXT *hd, byte *data )
(a) < 64 ? F3((x),(y),(z)) : \
F4((x),(y),(z)) )
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
#ifdef BIG_ENDIAN_HOST
{ int i;
byte *p2, *p1;

View File

@ -99,14 +99,30 @@
#define K3 0x8F1BBCDCL /* Rounds 40-59 */
#define K4 0xCA62C1D6L /* Rounds 60-79 */
#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
#if defined(__GNUC__) && defined(__i386__)
static inline u32
rol(int n, u32 x)
{
__asm__("roll %%cl,%0"
:"=r" (x)
:"0" (x),"c" (n));
return x;
}
#else
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
#endif
#define expand(W,i) ( W[ i & 15 ] = \
ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
rol( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
#define subRound(a, b, c, d, e, f, k, data) \
( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
( e += rol( 5, a ) + f( b, c, d ) + k + data, b = rol( 30, b ) )
void

View File

@ -174,7 +174,7 @@ g10maint_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = ChangeLog Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

View File

@ -291,7 +291,7 @@ main( int argc, char **argv )
configname, strerror(errno) );
m_free(configname); configname = NULL;
}
if( parse_verbose > 1 )
if( parse_verbose > 1 && configname )
log_info(_("reading options from '%s'\n"), configname );
default_config = 0;
}
@ -640,7 +640,7 @@ main( int argc, char **argv )
void
g10_exit( int rc )
{
if( opt.verbose )
if( opt.debug )
secmem_dump_stats();
secmem_term();
rc = rc? rc : log_get_errorcount(0)? 2:0;

View File

@ -478,7 +478,7 @@ main( int argc, char **argv )
}
break;
case aTest: do_test( argc? atoi(*argv): 0 ); break;
case aTest: do_test( argc? atoi(*argv): 1 ); break;
case aListTrustDB:
if( !argc )
@ -603,27 +603,41 @@ print_mds( const char *fname )
static void
do_test(int times)
{
#if 0
MPI t = mpi_alloc( 50 );
MPI m = mpi_alloc( 50 );
MPI a = mpi_alloc( 50 );
MPI b = mpi_alloc( 50 );
MPI p = mpi_alloc( 50 );
MPI x = mpi_alloc( 50 );
MPI base[4];
MPI exp[4];
MPI t1 = mpi_alloc(50);
MPI t2 = mpi_alloc(50);
MPI t3 = mpi_alloc(50);
MPI tmp= mpi_alloc(50);
MPI m = mpi_alloc(50);
MPI res = mpi_alloc(50);
/* output = b/(a^x) mod p */
log_debug("invm %d times ", times);
for( ; times > 0; times -- ) {
mpi_fromstr(a, "0xef45678343589854354a4545545454554545455"
"aaaaaaaaaaaaa44444fffdecb33434343443331" );
mpi_fromstr(b, "0x8765765589854354a4545545454554545455"
"aaaaaaa466577778decb36666343443331" );
mpi_invm( t, a, b );
fputc('.', stderr); fflush(stderr);
}
mpi_fromstr( m, "0x10000000000000000000000000" );
base[0] = mpi_alloc_set_ui( 3 );
mpi_fromstr( base[0], "0x145984358945989898495ffdd13" );
base[1] = mpi_alloc_set_ui( 5 );
mpi_fromstr( base[1], "0x000effff9999000000001100001" );
base[2] = mpi_alloc_set_ui( 2 );
mpi_fromstr( base[2], "0x499eeeaaaaa0444444545466672" );
base[3] = NULL;
exp[0] = mpi_alloc_set_ui( 30 );
exp[1] = mpi_alloc_set_ui( 10 );
mpi_fromstr( exp[1], "0x3457878888888888aabbbccccc1" );
exp[2] = mpi_alloc_set_ui( 24 );
exp[3] = NULL;
mpi_powm( t1, base[0], exp[0], m );
mpi_powm( t2, base[1], exp[1], m );
mpi_powm( t3, base[2], exp[2], m );
mpi_mulm( tmp, t1, t2, m );
mpi_mulm( t1, tmp, t3, m );
log_mpidump("X=", t1 );
mpi_mulpowm( res, base, exp, m );
log_mpidump("X=", res );
m_check(NULL);
#endif
}

View File

@ -36,7 +36,6 @@ new_kbnode( PACKET *pkt )
KBNODE n = m_alloc( sizeof *n );
n->next = NULL;
n->pkt = pkt;
n->child = NULL;
n->flag = 0;
n->private_flag=0; /* kludge to delete a node */
return n;
@ -50,7 +49,6 @@ release_kbnode( KBNODE n )
while( n ) {
n2 = n->next;
release_kbnode( n->child );
free_packet( n->pkt );
m_free( n );
n = n2;
@ -60,7 +58,7 @@ release_kbnode( KBNODE n )
/****************
* Delete NODE from ROOT, ROOT must exist!
* Note does only work with walk_kbtree!!
* Note: This does only work with walk_kbnode!!
*/
void
delete_kbnode( KBNODE root, KBNODE node )
@ -82,56 +80,97 @@ add_kbnode( KBNODE root, KBNODE node )
}
/****************
* Append NODE to ROOT as child of ROOT
* Insert NODE into the list after root but before a packet with type PKTTYPE
* (only if PKTTYPE != 0)
*/
void
add_kbnode_as_child( KBNODE root, KBNODE node )
insert_kbnode( KBNODE root, KBNODE node, int pkttype )
{
KBNODE n1;
if( !(n1=root->child) )
root->child = node;
if( !pkttype ) {
node->next = root->next;
root->next = node;
}
else {
for( ; n1->next; n1 = n1->next)
;
KBNODE n1;
for(n1=root; n1->next; n1 = n1->next)
if( pkttype == n1->next->pkt->pkttype ) {
node->next = n1->next;
n1->next = node;
return;
}
/* no such packet, append */
node->next = NULL;
n1->next = node;
}
}
/****************
* Return the parent node of KBNODE from the tree with ROOT
* Find the previous node (if PKTTYPE = 0) or the previous node
* with pkttype PKTTYPE in the list starting with ROOT of NODE.
*/
KBNODE
find_kbparent( KBNODE root, KBNODE node )
find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
{
KBNODE n, n2;
KBNODE n1;
for( ; root; root = root->child) {
for( n = root; n; n = n->next) {
for( n2 = n->child; n2; n2 = n2->next ) {
if( n2 == node )
return n;
}
}
for(n1=NULL ; root && root != node; root = root->next )
if( !pkttype || root->pkt->pkttype == pkttype )
n1 = root;
return n1;
}
/****************
* Ditto, but find the next package. The behaviour is trivial if
* PKTTYPE is 0 but if it is specified, the next node with a packet
* of this type is returned. The function has some knowledge about
* the valid ordering of packets: e.g. if the next signature packet
* is requested, the function will not return one if it encounters
* a user-id.
*/
KBNODE
find_next_kbnode( KBNODE node, int pkttype )
{
for( node=node->next ; node; node = node->next ) {
if( !pkttype )
return node;
else if( pkttype == PKT_USER_ID
&& ( node->pkt->pkttype == PKT_PUBLIC_CERT
|| node->pkt->pkttype == PKT_SECRET_CERT ) )
return NULL;
else if( pkttype == PKT_SIGNATURE
&& ( node->pkt->pkttype == PKT_USER_ID
|| node->pkt->pkttype == PKT_PUBLIC_CERT
|| node->pkt->pkttype == PKT_SECRET_CERT ) )
return NULL;
else if( node->pkt->pkttype == pkttype )
return node;
}
return NULL;
}
KBNODE
find_kbnode( KBNODE node, int pkttype )
{
for( ; node; node = node->next ) {
if( node->pkt->pkttype == pkttype )
return node;
}
return NULL;
}
/****************
* Walk through a tree of kbnodes. This functions returns
* Walk through a list of kbnodes. This functions returns
* the next kbnode for each call; before using the function the first
* time, the caller must set CONTEXT to NULL (This has simply the effect
* to start with ROOT).
*/
KBNODE
walk_kbtree( KBNODE root, KBNODE *context )
{
return walk_kbtree2( root, context, 0 );
}
KBNODE
walk_kbtree2( KBNODE root, KBNODE *context, int all )
walk_kbnode( KBNODE root, KBNODE *context, int all )
{
KBNODE n;
@ -142,15 +181,7 @@ walk_kbtree2( KBNODE root, KBNODE *context, int all )
}
n = *context;
if( n->child ) {
n = n->child;
*context = n;
}
else if( n->next ) {
n = n->next;
*context = n;
}
else if( (n = find_kbparent( root, n )) ) {
if( n->next ) {
n = n->next;
*context = n;
}
@ -163,7 +194,6 @@ void
clear_kbnode_flags( KBNODE n )
{
for( ; n; n = n->next ) {
clear_kbnode_flags( n->child );
n->flag = 0;
}
}

View File

@ -37,9 +37,8 @@
typedef struct kbnode_struct *KBNODE;
struct kbnode_struct {
KBNODE next;
PACKET *pkt;
KBNODE next; /* used to form a link list */
KBNODE child;
int flag;
int private_flag;
};
@ -49,10 +48,9 @@ struct kbnode_struct {
* of a keyblock.
*/
struct keyblock_pos_struct {
int resno; /* resource number */
ulong offset; /* position information */
ulong length; /* length of thge keyblock */
int last_block;
int resno; /* resource number */
ulong offset; /* position information */
unsigned count; /* length of the keyblock in packets */
};
typedef struct keyblock_pos_struct KBPOS;
@ -130,10 +128,11 @@ KBNODE new_kbnode( PACKET *pkt );
void release_kbnode( KBNODE n );
void delete_kbnode( KBNODE root, KBNODE node );
void add_kbnode( KBNODE root, KBNODE node );
void add_kbnode_as_child( KBNODE root, KBNODE node );
KBNODE find_kbparent( KBNODE root, KBNODE node );
KBNODE walk_kbtree( KBNODE root, KBNODE *context );
KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all );
void insert_kbnode( KBNODE root, KBNODE node, int pkttype );
KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype );
KBNODE find_next_kbnode( KBNODE node, int pkttype );
KBNODE find_kbnode( KBNODE node, int pkttype );
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
void clear_kbnode_flags( KBNODE n );
/*-- ringedit.c --*/

View File

@ -102,25 +102,19 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
PKT_signature *sig;
PKT_user_id *uid;
int rc=0;
KBNODE kbctx, node;
KBNODE node;
PKT_public_cert *pkc;
if( opt.verbose )
log_info(_("writing self signature\n"));
/* get the uid packet from the tree */
for( kbctx=NULL; (node=walk_kbtree( root, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID )
break;
}
/* get the uid packet from the list */
node = find_kbnode( root, PKT_USER_ID );
if( !node )
BUG(); /* no user id packet in tree */
uid = node->pkt->pkt.user_id;
/* get the pkc packet from the pub_tree */
for( kbctx=NULL; (node=walk_kbtree( pub_root, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_PUBLIC_CERT )
break;
}
node = find_kbnode( root, PKT_PUBLIC_CERT );
if( !node )
BUG();
pkc = node->pkt->pkt.public_cert;

View File

@ -110,13 +110,13 @@ add_secret_cert( CTX c, PACKET *pkt )
static int
add_user_id( CTX c, PACKET *pkt )
{
KBNODE node, n1, n2;
KBNODE node, n1;
if( !c->cert ) {
log_error("orphaned user id\n" );
return 0;
}
/* goto the last certificate (currently ther is only one) */
/* goto the last certificate */
for(n1=c->cert; n1->next; n1 = n1->next )
;
assert( n1->pkt );
@ -127,13 +127,7 @@ add_user_id( CTX c, PACKET *pkt )
}
/* add a new user id node at the end */
node = new_kbnode( pkt );
if( !(n2=n1->child) )
n1->child = node;
else {
for( ; n2->next; n2 = n2->next)
;
n2->next = node;
}
add_kbnode( n1, node );
return 1;
}
@ -147,49 +141,36 @@ add_signature( CTX c, PACKET *pkt )
/* This is the first signature for a following datafile.
* G10 does not write such packets, instead it always uses
* onepass-sig packets. The drawback of PGP's method
* of writing prepending the signtaure to the data is,
* that it is not possible to make a signature from data
* read from stdin. But we are able to read these stuff. */
* of prepending the signtaure to the data is,
* that it is not possible to make a signature from data read
* from stdin. (Anyway, G10 is are able to read these stuff) */
node = new_kbnode( pkt );
node->next = c->cert;
c->cert = node;
return 1;
}
else if( !c->cert )
return 0;
return 0; /* oops */
else if( !c->cert->pkt )
BUG();
else if( c->cert->pkt->pkttype == PKT_ONEPASS_SIG ) {
/* The root is a onepass signature, so we are signing data
* The childs direct under the root are the signatures
* (there is no need to keep the correct sequence of packets) */
/* The root is a onepass signature, so we are signing data */
node = new_kbnode( pkt );
node->next = c->cert->child;
c->cert->child = node;
add_kbnode( c->cert, node );
return 1;
}
else if( !c->cert->child ) {
log_error("orphaned signature (no userid)\n" );
return 0;
}
/* goto the last user id */
for(n1=c->cert->child; n1->next; n1 = n1->next )
;
assert( n1->pkt );
if( n1->pkt->pkttype != PKT_USER_ID ) {
log_error("invalid parent type %d for sig\n", n1->pkt->pkttype);
for(n2=NULL, n1=c->cert; n1->next; n1 = n1->next )
if( n1->pkt->pkttype == PKT_USER_ID )
n2 = n1;
if( !n2 ) {
log_error("no user id for signature packet\n");
return 0;
}
n1 = n2;
/* and add a new signature node id at the end */
node = new_kbnode( pkt );
if( !(n2=n1->child) )
n1->child = node;
else {
for( ; n2->next; n2 = n2->next)
;
n2->next = node;
}
insert_kbnode( n1, node, PKT_USER_ID );
return 1;
}
@ -333,10 +314,9 @@ do_check_sig( CTX c, KBNODE node )
}
else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */
if( c->cert->pkt->pkttype == PKT_PUBLIC_CERT ) {
KBNODE n1 = find_kbparent( c->cert, node );
if( n1 && n1->pkt->pkttype == PKT_USER_ID ) {
KBNODE n1 = find_prev_kbnode( c->cert, node, PKT_USER_ID );
if( n1 ) {
if( c->cert->pkt->pkt.public_cert->mfx.md )
md = md_copy( c->cert->pkt->pkt.public_cert->mfx.md );
else
@ -411,7 +391,7 @@ print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
static void
list_node( CTX c, KBNODE node )
{
register KBNODE n2;
int any=0;
if( !node )
;
@ -422,21 +402,19 @@ list_node( CTX c, KBNODE node )
pubkey_letter( pkc->pubkey_algo ),
(ulong)keyid_from_pkc( pkc, NULL ),
datestr_from_pkc( pkc ) );
n2 = node->child;
if( !n2 )
printf("ERROR: no user id!\n");
else {
/* and now list all userids with their signatures */
for( ; n2; n2 = n2->next ) {
if( n2 != node->child )
printf( "%*s", 31, "" );
print_userid( n2->pkt );
putchar('\n');
if( opt.fingerprint && n2 == node->child )
print_fingerprint( pkc, NULL );
list_node(c, n2 );
}
/* and now list all userids with their signatures */
while( (node = find_next_kbnode(node, PKT_USER_ID)) ) {
if( any )
printf( "%*s", 31, "" );
print_userid( node->pkt );
putchar('\n');
if( opt.fingerprint && !any )
print_fingerprint( pkc, NULL );
list_node(c, node );
any=1;
}
if( !any )
printf("ERROR: no user id!\n");
}
else if( node->pkt->pkttype == PKT_SECRET_CERT ) {
PKT_secret_cert *skc = node->pkt->pkt.secret_cert;
@ -445,20 +423,21 @@ list_node( CTX c, KBNODE node )
pubkey_letter( skc->pubkey_algo ),
(ulong)keyid_from_skc( skc, NULL ),
datestr_from_skc( skc ) );
n2 = node->child;
if( !n2 )
printf("ERROR: no user id!\n");
else {
print_userid( n2->pkt );
/* and now list all userids */
while( (node = find_next_kbnode(node, PKT_USER_ID)) ) {
print_userid( node->pkt );
putchar('\n');
if( opt.fingerprint && n2 == node->child )
if( opt.fingerprint && !any )
print_fingerprint( NULL, skc );
any=1;
}
if( !any )
printf("ERROR: no user id!\n");
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
/* list everything under this user id */
for(n2=node->child; n2; n2 = n2->next )
list_node(c, n2 );
while( (node = find_next_kbnode(node, 0 )) )
list_node(c, node );
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
@ -467,7 +446,6 @@ list_node( CTX c, KBNODE node )
char *p;
int sigrc = ' ';
assert( !node->child );
if( !opt.list_sigs )
return;
@ -626,31 +604,26 @@ proc_tree( CTX c, KBNODE node )
else if( node->pkt->pkttype == PKT_SECRET_CERT )
list_node( c, node );
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
if( !node->child )
log_error("proc_tree: onepass_sig without data\n");
else if( node->child->pkt->pkttype != PKT_SIGNATURE )
log_error("proc_tree: onepass_sig not followed by signature\n");
else { /* check all signatures */
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
c->mfx.md = md_open(0, 0);
for(n1=node->child; n1; n1 = n1->next ) {
md_enable( c->mfx.md,
digest_algo_from_sig(n1->pkt->pkt.signature));
}
/* ask for file and hash it */
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
}
/* check all signatures */
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
c->mfx.md = md_open(0, 0);
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) {
md_enable( c->mfx.md,
digest_algo_from_sig(n1->pkt->pkt.signature));
}
/* ask for file and hash it */
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
}
for(n1=node->child; n1; n1 = n1->next )
check_sig_and_print( c, n1 );
}
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); )
check_sig_and_print( c, n1 );
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;

View File

@ -221,6 +221,9 @@ int list_packets( IOBUF a );
int set_packet_list_mode( int mode );
int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
int parse_packet( IOBUF inp, PACKET *ret_pkt);
int copy_all_packets( IOBUF inp, IOBUF out );
int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
int skip_some_packets( IOBUF inp, unsigned n );
/*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt );

View File

@ -37,7 +37,9 @@ static mpi_print_mode = 0;
static list_mode = 0;
static int parse( IOBUF inp, PACKET *pkt, int reqtype,
ulong *retpos, int *skip );
ulong *retpos, int *skip, IOBUF out, int do_skip );
static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
unsigned long pktlen );
static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
static void skip_rest( IOBUF inp, unsigned long pktlen );
static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
@ -51,7 +53,8 @@ static int parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static void parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen );
static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt );
@ -116,13 +119,13 @@ parse_packet( IOBUF inp, PACKET *pkt )
int skip, rc;
do {
rc = parse( inp, pkt, 0, NULL, &skip );
rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
} while( skip );
return rc;
}
/****************
* Like parse packet, but do only return packet of the given type.
* Like parse packet, but do only return packets of the given type.
*/
int
search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
@ -130,20 +133,68 @@ search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
int skip, rc;
do {
rc = parse( inp, pkt, pkttype, retpos, &skip );
rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
} while( skip );
return rc;
}
/****************
* Copy all packets from INP to OUT, thereby removing unused spaces.
*/
int
copy_all_packets( IOBUF inp, IOBUF out )
{
PACKET pkt;
int skip, rc=0;
do {
init_packet(&pkt);
} while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
return rc;
}
/****************
* Copy some packets from INP to OUT, thereby removing unused spaces.
* Stop after at offset STOPoff (i.e. don't copy the packet at this offset)
*/
int
copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
{
PACKET pkt;
int skip, rc=0;
do {
if( iobuf_tell(inp) >= stopoff )
return 0;
init_packet(&pkt);
} while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
return rc;
}
/****************
* Skip over N packets
*/
int
skip_some_packets( IOBUF inp, unsigned n )
{
int skip, rc=0;
PACKET pkt;
for( ;n && !rc; n--) {
init_packet(&pkt);
rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
}
return rc;
}
/****************
* Parse packet. Set the variable skip points to to 1 if the packet
* should be skipped; this is the case if either there is a
* requested packet type and the parsed packet doesn't match or the
* packet-type is 0, indicating deleted stuff.
* if OUT is not NULL, a special copymode is used.
*/
static int
parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
int *skip, IOBUF out, int do_skip )
{
int rc, c, ctb, pkttype, lenbytes;
unsigned long pktlen;
@ -206,7 +257,15 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
}
}
if( !pkttype || (reqtype && pkttype != reqtype) ) {
if( out && pkttype ) {
if( iobuf_write( out, hdr, hdrlen ) == -1 )
rc = G10ERR_WRITE_FILE;
else
rc = copy_packet(inp, out, pkttype, pktlen );
return rc;
}
if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
skip_packet(inp, pkttype, pktlen);
*skip = 1;
return 0;
@ -245,7 +304,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
parse_subkey(inp, pkttype, pktlen);
break;
case PKT_COMMENT:
parse_comment(inp, pkttype, pktlen);
rc = parse_comment(inp, pkttype, pktlen, pkt);
break;
case PKT_RING_TRUST:
parse_trust(inp, pkttype, pktlen);
@ -284,6 +343,37 @@ dump_hex_line( int c, int *i )
}
static int
copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
{
int n;
char buf[100];
if( iobuf_in_block_mode(inp) ) {
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
else if( !pktlen && pkttype == PKT_COMPRESSED ) {
/* compressed packet, copy till EOF */
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
else {
for( ; pktlen; pktlen -= n ) {
n = pktlen > 100 ? 100 : pktlen;
n = iobuf_read( inp, buf, n );
if( n == -1 )
return G10ERR_READ_FILE;
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
}
return 0;
}
static void
skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
{
@ -738,22 +828,29 @@ parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen )
static void
parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
static int
parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
packet->pkt.comment->len = pktlen;
p = packet->pkt.comment->data;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
if( list_mode ) {
printf(":comment packet: \"" );
for( ; pktlen; pktlen-- ) {
int c;
c = iobuf_get_noeof(inp);
if( c >= ' ' && c <= 'z' )
putchar(c);
int n = packet->pkt.comment->len;
printf(":comment packet: \"");
for(p=packet->pkt.comment->data; n; p++, n-- ) {
if( *p >= ' ' && *p <= 'z' )
putchar(*p);
else
printf("\\x%02x", c );
printf("\\x%02x", *p );
}
printf("\"\n");
}
skip_rest(inp, pktlen);
return 0;
}
@ -765,33 +862,6 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
c = iobuf_get_noeof(inp);
if( list_mode )
printf(":trust packet: flag=%02x\n", c );
#if 0 /* fixme: depending on the context we have different interpretations*/
if( prev_packet_is_a_key_packet ) {
int ot = c & 7; /* ownertrust bits (for the key owner) */
!ot ? "undefined" :
ot == 1 ? "unknown" : /* we don't know the owner of this key */
ot == 2 ? "no" : /* usually we do not trust this key owner */
/* to sign other keys */
ot == 5 ? "usually" : /* usually we trust this key owner to sign */
ot == 6 ? "always" : /* always trust this key owner to sign */
ot == 7 ? "ultimate" : /* also present in the secret keyring */
"" /* reserved value */
if( c & (1<<5) )
"key is disabled"
if( c & (1<<7) )
"buckstop"
else if( prev_packet_is_user_is_packet ) {
int kl = c & 3; /* keylegit bits */
0 = "unknown, undefined, or uninitialized trust"
1 = "we do not trust this key's ownership"
2 = "we have marginal confidence of this key's ownership"
3 = "we completely trust this key's ownership."
if( c & 0x80 )
"warnonly"
else if( prev_packet_is_a_signature ) {
}
#endif
}

View File

@ -35,7 +35,6 @@
*
* - Delete a key block
*
* FIXME: Add backup stuff
* FIXME: Keep track of all nodes, so that a change is propagated
* to all nodes. (or use shallow copies and ref-counting?)
*/
@ -46,6 +45,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include "util.h"
#include "packet.h"
@ -75,8 +77,7 @@ static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf );
static int keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos,
const char *fname);
static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_insert( KBPOS *kbpos, KBNODE root );
static int keyring_delete( KBPOS *kbpos );
static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
@ -308,7 +309,7 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
rc = keyring_insert( kbpos, root );
rc = keyring_copy( kbpos, 1, root );
return rc;
}
@ -327,7 +328,7 @@ delete_keyblock( KBPOS *kbpos )
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
rc = keyring_delete( kbpos );
rc = keyring_copy( kbpos, 2, NULL );
return rc;
}
@ -340,14 +341,11 @@ int
update_keyblock( KBPOS *kbpos, KBNODE root )
{
int rc;
KBPOS kbpos2;
/* we do it the simple way: */
memset( &kbpos2, 0, sizeof kbpos2 );
kbpos2.resno = kbpos->resno;
rc = insert_keyblock( &kbpos2, root );
if( !rc )
rc = delete_keyblock( kbpos );
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
rc = keyring_copy( kbpos, 3, root );
return rc;
}
@ -451,20 +449,12 @@ keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos, const char *fname )
init_packet(&pkt);
save_mode = set_packet_list_mode(0);
#if 0
if( iobuf_seek( iobuf, 0 ) ) {
log_error("can't rewind keyring file: %s\n", g10_errstr(rc));
rc = G10ERR_KEYRING_OPEN;
goto leave;
}
#else
iobuf = iobuf_open( fname );
if( !iobuf ) {
log_error("can't open '%s'\n", fname );
rc = G10ERR_OPEN_FILE;
goto leave;
}
#endif
while( !(rc=search_packet(iobuf, &pkt, PKT_PUBLIC_CERT, &offset)) ) {
PKT_public_cert *pkc = pkt.pkt.public_cert;
@ -505,9 +495,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
int rc;
RESTBL *rentry;
KBNODE root = NULL;
KBNODE node, n1, n2;
IOBUF a;
u32 offset, last_offset;
int in_cert = 0;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
@ -526,77 +515,37 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
kbpos->count=0;
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
kbpos->count++;
free_packet( pkt );
continue;
}
if( root && ( pkt->pkttype == PKT_PUBLIC_CERT
|| pkt->pkttype == PKT_SECRET_CERT ) )
goto ready;
offset = iobuf_tell(a);
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
root = new_kbnode( pkt );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
case PKT_USER_ID:
if( !root ) {
log_error("read_keyblock: orphaned user id\n" );
rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
if( in_cert )
goto ready;
}
offset = last_offset;
/* append the user id */
node = new_kbnode( pkt );
if( !(n1=root->child) )
root->child = node;
else {
for( ; n1->next; n1 = n1->next)
;
n1->next = node;
}
in_cert = 1;
default:
kbpos->count++;
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
case PKT_SIGNATURE:
if( !root ) {
log_error("read_keyblock: no root for signature\n" );
rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
break;
}
if( !root->child ) {
log_error("read_keyblock: no userid for signature\n" );
rc = G10ERR_INV_KEYRING;
break;
}
/* goto the last user id */
for(n1=root->child; n1->next; n1 = n1->next )
;
/* append the signature node */
node = new_kbnode( pkt );
if( !(n2=n1->child) )
n1->child = node;
else {
for( ; n2->next; n2 = n2->next)
;
n2->next = node;
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
default: /* ignore all other packets. FIXME: we should not do this */
free_packet( pkt );
break;
}
}
ready:
kbpos->last_block = rc == -1; /* flag, that this is the last block */
if( rc == -1 && root )
rc = 0;
@ -604,7 +553,6 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
release_kbnode( root );
else {
*ret_root = root;
kbpos->length = offset - kbpos->offset;
}
free_packet( pkt );
m_free( pkt );
@ -613,111 +561,175 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
}
/****************
* Insert the keyblock described by ROOT into the keyring described
* by KBPOS. This actually appends the data to the keyfile.
* Peromf insert/delete/update operation.
* mode 1 = insert
* 2 = delete
* 3 = update
*/
static int
keyring_insert( KBPOS *kbpos, KBNODE root )
keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
{
RESTBL *rentry;
IOBUF fp;
KBNODE kbctx, node;
IOBUF fp, newfp;
int rc;
char *bakfname = NULL;
char *tmpfname = NULL;
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
/* FIXME: we must close the file if it's already open, due to
* 2 reasons:
* - cannot open the same file twice on DOSish OSes
* - must sync with iobufs somehow
*/
/* open the file for append */
fp = iobuf_append( rentry->fname );
if( !fp ) {
log_error("can't append to '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
}
/* open the source file */
fp = iobuf_open( rentry->fname );
if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
KBNODE kbctx, node;
kbctx=NULL;
while( (node = walk_kbtree( root, &kbctx )) ) {
if( (rc = build_packet( fp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
/* insert: create a new file */
newfp = iobuf_create( rentry->fname );
if( !newfp ) {
log_error("%s: can't create: %s\n", rentry->fname, strerror(errno));
return G10ERR_OPEN_FILE;
}
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_cancel(newfp);
return G10ERR_WRITE_FILE;
}
}
if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
return G10ERR_CLOSE_FILE;
}
if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
rentry->fname, strerror(errno) );
return G10ERR_WRITE_FILE;
}
return 0;
}
iobuf_close(fp);
return 0;
}
static int
keyring_delete( KBPOS *kbpos )
{
RESTBL *rentry;
IOBUF fp;
int rc;
u32 len;
int ctb;
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
/* open the file for read/write */
fp = iobuf_openrw( rentry->fname );
if( !fp ) {
log_error("can't open '%s' for writing\n", rentry->fname );
return G10ERR_OPEN_FILE;
log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( iobuf_seek( fp, kbpos->offset ) ) {
log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc));
/* create the new file */
bakfname = m_alloc( strlen( rentry->fname ) + 2 );
strcpy(stpcpy(bakfname,rentry->fname),"~");
tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
newfp = iobuf_create( tmpfname );
if( !newfp ) {
log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
iobuf_close(fp);
return G10ERR_WRITE_FILE;
rc = G10ERR_OPEN_FILE;
goto leave;
}
len = kbpos->length;
assert( len < 100000 ); /* there is a bug somewhere */
/*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/
if( len < 2 )
BUG();
if( len < 256 ) {
ctb = 0x80;
len -= 2;
}
else if( len < 65536 ) {
ctb = 0x81;
len -= 3;
}
else {
ctb = 0x82;
len -= 5;
}
iobuf_put(fp, ctb );
if( ctb & 2 ) {
iobuf_put(fp, len >> 24 );
iobuf_put(fp, len >> 16 );
}
if( ctb & 3 )
iobuf_put(fp, len >> 8 );
if( iobuf_put(fp, len ) ) {
iobuf_close(fp);
return G10ERR_WRITE_FILE;
}
for( ; len; len-- )
if( iobuf_put(fp, 0xff ) ) {
if( mode == 1 ) { /* insert */
/* copy everything to the new file */
rc = copy_all_packets( fp, newfp );
if( rc != -1 ) {
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
return G10ERR_WRITE_FILE;
iobuf_cancel(newfp);
goto leave;
}
rc = 0;
}
if( mode == 2 || mode == 3 ) { /* delete or update */
/* copy first part to the new file */
rc = copy_some_packets( fp, newfp, kbpos->offset );
if( rc ) { /* should never get EOF here */
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
/* skip this keyblock */
assert( kbpos->count );
rc = skip_some_packets( fp, kbpos->count );
if( rc ) {
log_error("%s: skipping %u packets failed: %s\n",
rentry->fname, kbpos->count, g10_errstr(rc));
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
}
if( mode == 1 || mode == 3 ) { /* insert or update */
KBNODE kbctx, node;
/* append the new data */
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
if( mode == 2 || mode == 3 ) { /* delete or update */
/* copy the rest */
rc = copy_all_packets( fp, newfp );
if( rc != -1 ) {
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
rc = 0;
}
/* close both files */
iobuf_close(fp);
if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
rc = G10ERR_CLOSE_FILE;
goto leave;
}
/* if the new file is a secring, restrict the permissions */
if( rentry->secret ) {
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
tmpfname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
/* rename and make backup file */
if( rename( rentry->fname, bakfname ) ) {
log_error("%s: rename to %s failed: %s\n",
rentry->fname, bakfname, strerror(errno) );
rc = G10ERR_RENAME_FILE;
goto leave;
}
if( rename( tmpfname, rentry->fname ) ) {
log_error("%s: rename to %s failed: %s\n",
tmpfname, rentry->fname,strerror(errno) );
rc = G10ERR_RENAME_FILE;
goto leave;
}
return 0;
leave:
m_free(bakfname);
m_free(tmpfname);
return rc;
}

View File

@ -248,9 +248,9 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
if( (rc=check_digest_algo(algo)) )
return rc;
unode = find_kbparent( root, node );
unode = find_prev_kbnode( root, node, PKT_USER_ID );
if( unode && unode->pkt->pkttype == PKT_USER_ID ) {
if( unode ) {
PKT_user_id *uid = unode->pkt->pkt.user_id;
if( is_selfsig ) {

View File

@ -527,7 +527,7 @@ check_all_keysigs( KBNODE keyblock )
int no_key = 0;
int oth_err = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
PKT_signature *sig = node->pkt->pkt.signature;
@ -579,7 +579,7 @@ remove_keysigs( KBNODE keyblock, int all )
int count;
count = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( ((node->flag & 7) || all )
&& node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
@ -625,7 +625,7 @@ remove_keysigs( KBNODE keyblock, int all )
if( !yes )
return 0;
for( kbctx=NULL; (node=walk_kbtree2( keyblock, &kbctx, 1)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 1)) ; ) {
if( node->flag & 128)
delete_kbnode( keyblock, node );
}
@ -677,10 +677,7 @@ sign_key( const char *username, STRLIST locusr )
}
/* get the keyid from the keyblock */
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_PUBLIC_CERT )
break;
}
node = find_kbnode( keyblock, PKT_PUBLIC_CERT );
if( !node ) {
log_error("Oops; public key not found anymore!\n");
rc = G10ERR_GENERAL;
@ -719,7 +716,7 @@ sign_key( const char *username, STRLIST locusr )
u32 akeyid[2];
keyid_from_skc( skc_rover->skc, akeyid );
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
if( akeyid[0] == node->pkt->pkt.signature->keyid[0]
@ -744,7 +741,7 @@ sign_key( const char *username, STRLIST locusr )
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
if( skc_rover->mark )
continue;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( sign_it_p( pkc, node->pkt->pkt.user_id ) ) {
PACKET *pkt;
@ -763,7 +760,7 @@ sign_key( const char *username, STRLIST locusr )
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
add_kbnode_as_child( node, new_kbnode( pkt ) );
insert_kbnode( node, new_kbnode(pkt), PKT_USER_ID );
}
}
}
@ -789,7 +786,7 @@ edit_keysigs( const char *username )
{
int rc = 0;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBNODE node;
KBPOS kbpos;
PKT_public_cert *pkc;
u32 pkc_keyid[2];
@ -809,10 +806,7 @@ edit_keysigs( const char *username )
}
/* get the keyid from the keyblock */
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_PUBLIC_CERT )
break;
}
node = find_kbnode( keyblock, PKT_PUBLIC_CERT );
if( !node ) {
log_error("Oops; public key not found anymore!\n");
rc = G10ERR_GENERAL;
@ -855,7 +849,7 @@ change_passphrase( const char *username )
{
int rc = 0;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBNODE node;
KBPOS kbpos;
PKT_secret_cert *skc;
u32 skc_keyid[2];
@ -877,10 +871,7 @@ change_passphrase( const char *username )
}
/* get the keyid from the keyblock */
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_SECRET_CERT )
break;
}
node = find_kbnode( keyblock, PKT_SECRET_CERT );
if( !node ) {
log_error("Oops; secret key not found anymore!\n");
rc = G10ERR_GENERAL;

View File

@ -1090,7 +1090,7 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
LOCAL_ID_INFO *dups = NULL;
*selfsig_okay = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx,0)) ; ) {
if( node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
int selfsig;
@ -1190,7 +1190,7 @@ build_sigrecs( ulong pubkeyid )
rec.rectype = RECTYPE_SIG;
i = 0;
rnum = rnum2 = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
/* insert sigs which are not a selfsig nor a duplicate */
if( (node->flag & 1) && !(node->flag & 4) ) {
assert( node->pkt->pkttype == PKT_SIGNATURE );

View File

@ -55,5 +55,8 @@
#define G10ERR_TRUSTDB 33 /* a problem with the trustdb */
#define G10ERR_BAD_CERT 34 /* bad certicate */
#define G10ERR_INV_USER_ID 35
#define G10ERR_CLOSE_FILE 36
#define G10ERR_RENAME_FILE 37
#define G10ERR_DELETE_FILE 38
#endif /*G10_ERRORS_H*/

View File

@ -21,6 +21,10 @@
#ifndef G10_I18N_H
#define G10_I18N_H
#ifdef HAVE_LOCALE_H
#include <locale.h> /* suggested by Ernst Molitor */
#endif
#ifdef HAVE_LIBINTL
#include <libintl.h>
#define _(a) gettext (a)

View File

@ -88,6 +88,7 @@ ulong iobuf_tell( IOBUF a );
int iobuf_seek( IOBUF a, ulong newpos );
int iobuf_readbyte(IOBUF a);
int iobuf_read(IOBUF a, byte *buf, unsigned buflen );
int iobuf_writebyte(IOBUF a, unsigned c);
int iobuf_write(IOBUF a, byte *buf, unsigned buflen );
int iobuf_writestr(IOBUF a, const char *buf );

View File

@ -132,6 +132,9 @@ int mpi_gcd( MPI g, MPI a, MPI b );
void mpi_pow( MPI w, MPI u, MPI v);
void mpi_powm( MPI res, MPI base, MPI exp, MPI mod);
/*-- mpi-mpow.c --*/
void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod);
/*-- mpi-cmp.c --*/
int mpi_cmp_ui( MPI u, ulong v );
int mpi_cmp( MPI u, MPI v );

View File

@ -24,6 +24,7 @@ libmpi_a_SOURCES = longlong.h \
mpi-inv.c \
mpi-mul.c \
mpi-pow.c \
mpi-mpow.c \
mpi-scan.c \
mpicoder.c \
mpih-cmp.c \

View File

@ -106,6 +106,7 @@ libmpi_a_SOURCES = longlong.h \
mpi-inv.c \
mpi-mul.c \
mpi-pow.c \
mpi-mpow.c \
mpi-scan.c \
mpicoder.c \
mpih-cmp.c \
@ -138,13 +139,13 @@ LIBS = @LIBS@
libmpi_a_DEPENDENCIES = mpih-mul1.o mpih-mul2.o mpih-mul3.o mpih-add1.o \
mpih-sub1.o mpih-shift.o
libmpi_a_OBJECTS = mpi-add.o mpi-bit.o mpi-cmp.o mpi-div.o mpi-gcd.o \
mpi-inv.o mpi-mul.o mpi-pow.o mpi-scan.o mpicoder.o mpih-cmp.o \
mpih-add.o mpih-sub.o mpih-div.o mpih-mul.o mpiutil.o
mpi-inv.o mpi-mul.o mpi-pow.o mpi-mpow.o mpi-scan.o mpicoder.o \
mpih-cmp.o mpih-add.o mpih-sub.o mpih-div.o mpih-mul.o mpiutil.o
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = ChangeLog Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@ -152,10 +153,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
DEP_FILES = .deps/mpi-add.P .deps/mpi-bit.P .deps/mpi-cmp.P \
.deps/mpi-div.P .deps/mpi-gcd.P .deps/mpi-inv.P .deps/mpi-mul.P \
.deps/mpi-pow.P .deps/mpi-scan.P .deps/mpicoder.P .deps/mpih-add.P \
.deps/mpih-cmp.P .deps/mpih-div.P .deps/mpih-mul.P .deps/mpih-sub.P \
.deps/mpiutil.P
.deps/mpi-div.P .deps/mpi-gcd.P .deps/mpi-inv.P .deps/mpi-mpow.P \
.deps/mpi-mul.P .deps/mpi-pow.P .deps/mpi-scan.P .deps/mpicoder.P \
.deps/mpih-add.P .deps/mpih-cmp.P .deps/mpih-div.P .deps/mpih-mul.P \
.deps/mpih-sub.P .deps/mpiutil.P
SOURCES = $(libmpi_a_SOURCES)
OBJECTS = $(libmpi_a_OBJECTS)

View File

@ -10,7 +10,7 @@ test -d ./mpi || mkdir ./mpi
echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h
case "${target}" in
i[345]86*-*-linuxaout* | i[345]86*-*-linuxoldld* | i[345]86*-*-*bsd*)
i[34]86*-*-linuxaout* | i[34]86*-*-linuxoldld* | i[34]86*-*-*bsd*)
echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i386"
@ -20,14 +20,14 @@ case "${target}" in
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i586 i386"
;;
i[3456]86*-*-*)
i[34]86*-*-*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i386"
;;
i[56]86*-*-* | pentium-*-* | pentiumpro-*-*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
cat $srcdir/mpi/i586/syntax.h >>./mpi/asm-syntax.h
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i586 i386"
;;
alpha*-*-*)

26
mpi/i586/README Normal file
View File

@ -0,0 +1,26 @@
This directory contains mpn functions optimized for Intel Pentium
processors.
RELEVANT OPTIMIZATION ISSUES
1. Pentium doesn't allocate cache lines on writes, unlike most other modern
processors. Since the functions in the mpn class do array writes, we have to
handle allocating the destination cache lines by reading a word from it in the
loops, to achieve the best performance.
2. Pairing of memory operations requires that the two issued operations refer
to different cache banks. The simplest way to insure this is to read/write
two words from the same object. If we make operations on different objects,
they might or might not be to the same cache bank.
STATUS
1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium
documentation indicates that they should take only 43/8 = 5.375 cycles/limb,
or 5 cycles/limb asymptotically.
2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop
overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb.
3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they
should...

8
mpi/i586/distfiles Normal file
View File

@ -0,0 +1,8 @@
mpih-add1.S
mpih-mul1.S
mpih-mul2.S
mpih-mul3.S
mpih-shift.S
mpih-sub1.S
README

134
mpi/i586/mpih-add1.S Normal file
View File

@ -0,0 +1,134 @@
/* i80586 add_n -- Add two limb vectors of the same length > 0 and store
* sum in a third limb vector.
*
* Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4)
* mpi_ptr_t s1_ptr, (sp + 8)
* mpi_ptr_t s2_ptr, (sp + 12)
* mpi_size_t size) (sp + 16)
*/
.text
ALIGN (3)
.globl C_SYMBOL_NAME(mpihelp_add_n)
C_SYMBOL_NAME(mpihelp_add_n:)
pushl %edi
pushl %esi
pushl %ebx
pushl %ebp
movl 20(%esp),%edi /* res_ptr */
movl 24(%esp),%esi /* s1_ptr */
movl 28(%esp),%ebp /* s2_ptr */
movl 32(%esp),%ecx /* size */
movl (%ebp),%ebx
decl %ecx
movl %ecx,%edx
shrl $3,%ecx
andl $7,%edx
testl %ecx,%ecx /* zero carry flag */
jz Lend
pushl %edx
ALIGN (3)
Loop: movl 28(%edi),%eax /* fetch destination cache line */
leal 32(%edi),%edi
L1: movl (%esi),%eax
movl 4(%esi),%edx
adcl %ebx,%eax
movl 4(%ebp),%ebx
adcl %ebx,%edx
movl 8(%ebp),%ebx
movl %eax,-32(%edi)
movl %edx,-28(%edi)
L2: movl 8(%esi),%eax
movl 12(%esi),%edx
adcl %ebx,%eax
movl 12(%ebp),%ebx
adcl %ebx,%edx
movl 16(%ebp),%ebx
movl %eax,-24(%edi)
movl %edx,-20(%edi)
L3: movl 16(%esi),%eax
movl 20(%esi),%edx
adcl %ebx,%eax
movl 20(%ebp),%ebx
adcl %ebx,%edx
movl 24(%ebp),%ebx
movl %eax,-16(%edi)
movl %edx,-12(%edi)
L4: movl 24(%esi),%eax
movl 28(%esi),%edx
adcl %ebx,%eax
movl 28(%ebp),%ebx
adcl %ebx,%edx
movl 32(%ebp),%ebx
movl %eax,-8(%edi)
movl %edx,-4(%edi)
leal 32(%esi),%esi
leal 32(%ebp),%ebp
decl %ecx
jnz Loop
popl %edx
Lend:
decl %edx /* test %edx w/o clobbering carry */
js Lend2
incl %edx
Loop2:
leal 4(%edi),%edi
movl (%esi),%eax
adcl %ebx,%eax
movl 4(%ebp),%ebx
movl %eax,-4(%edi)
leal 4(%esi),%esi
leal 4(%ebp),%ebp
decl %edx
jnz Loop2
Lend2:
movl (%esi),%eax
adcl %ebx,%eax
movl %eax,(%edi)
sbbl %eax,%eax
negl %eax
popl %ebp
popl %ebx
popl %esi
popl %edi
ret

89
mpi/i586/mpih-mul1.S Normal file
View File

@ -0,0 +1,89 @@
/* i80586 mul_1 -- Multiply a limb vector with a limb and store
* the result in a second limb vector.
* Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4)
* mpi_ptr_t s1_ptr, (sp + 8)
* mpi_size_t s1_size, (sp + 12)
* mpi_limb_t s2_limb) (sp + 16)
*/
#define res_ptr edi
#define s1_ptr esi
#define size ecx
#define s2_limb ebp
TEXT
ALIGN (3)
GLOBL C_SYMBOL_NAME(mpihelp_mul_1)
C_SYMBOL_NAME(mpihelp_mul_1:)
INSN1(push,l ,R(edi))
INSN1(push,l ,R(esi))
INSN1(push,l ,R(ebx))
INSN1(push,l ,R(ebp))
INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
INSN2(mov,l ,R(size),MEM_DISP(esp,28))
INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
INSN1(neg,l ,R(size))
INSN2(xor,l ,R(ebx),R(ebx))
ALIGN (3)
Loop: INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
INSN1(mul,l ,R(s2_limb))
INSN2(add,l ,R(ebx),R(eax))
INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
INSN1(inc,l ,R(size))
INSN2(mov,l ,R(ebx),R(edx))
INSN1(jnz, ,Loop)
INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),R(ebx))
INSN1(pop,l ,R(ebp))
INSN1(pop,l ,R(ebx))
INSN1(pop,l ,R(esi))
INSN1(pop,l ,R(edi))
ret

94
mpi/i586/mpih-mul2.S Normal file
View File

@ -0,0 +1,94 @@
/* i80586 addmul_1 -- Multiply a limb vector with a limb and add
* the result to a second limb vector.
* Copyright (c) 1997 by Werner Koch (dd9jn)
* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4)
* mpi_ptr_t s1_ptr, (sp + 8)
* mpi_size_t s1_size, (sp + 12)
* mpi_limb_t s2_limb) (sp + 16)
*/
#define res_ptr edi
#define s1_ptr esi
#define size ecx
#define s2_limb ebp
TEXT
ALIGN (3)
GLOBL C_SYMBOL_NAME(mpihelp_addmul_1)
C_SYMBOL_NAME(mpihelp_addmul_1:)
INSN1(push,l ,R(edi))
INSN1(push,l ,R(esi))
INSN1(push,l ,R(ebx))
INSN1(push,l ,R(ebp))
INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
INSN2(mov,l ,R(size),MEM_DISP(esp,28))
INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
INSN1(neg,l ,R(size))
INSN2(xor,l ,R(ebx),R(ebx))
ALIGN (3)
Loop: INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
INSN1(mul,l ,R(s2_limb))
INSN2(add,l ,R(eax),R(ebx))
INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4))
INSN2(adc,l ,R(edx),$0)
INSN2(add,l ,R(ebx),R(eax))
INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
INSN1(inc,l ,R(size))
INSN2(mov,l ,R(ebx),R(edx))
INSN1(jnz, ,Loop)
INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),R(ebx))
INSN1(pop,l ,R(ebp))
INSN1(pop,l ,R(ebx))
INSN1(pop,l ,R(esi))
INSN1(pop,l ,R(edi))
ret

94
mpi/i586/mpih-mul3.S Normal file
View File

@ -0,0 +1,94 @@
/* i80586 submul_1 -- Multiply a limb vector with a limb and add
* the result to a second limb vector.
* Copyright (c) 1997 by Werner Koch (dd9jn)
* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4)
* mpi_ptr_t s1_ptr, (sp + 8)
* mpi_size_t s1_size, (sp + 12)
* mpi_limb_t s2_limb) (sp + 16)
*/
#define res_ptr edi
#define s1_ptr esi
#define size ecx
#define s2_limb ebp
TEXT
ALIGN (3)
GLOBL C_SYMBOL_NAME(mpihelp_submul_1)
C_SYMBOL_NAME(mpihelp_submul_1:)
INSN1(push,l ,R(edi))
INSN1(push,l ,R(esi))
INSN1(push,l ,R(ebx))
INSN1(push,l ,R(ebp))
INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
INSN2(mov,l ,R(size),MEM_DISP(esp,28))
INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
INSN1(neg,l ,R(size))
INSN2(xor,l ,R(ebx),R(ebx))
ALIGN (3)
Loop: INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
INSN1(mul,l ,R(s2_limb))
INSN2(add,l ,R(eax),R(ebx))
INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4))
INSN2(adc,l ,R(edx),$0)
INSN2(sub,l ,R(ebx),R(eax))
INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
INSN1(inc,l ,R(size))
INSN2(mov,l ,R(ebx),R(edx))
INSN1(jnz, ,Loop)
INSN2(adc,l ,R(ebx),$0)
INSN2(mov,l ,R(eax),R(ebx))
INSN1(pop,l ,R(ebp))
INSN1(pop,l ,R(ebx))
INSN1(pop,l ,R(esi))
INSN1(pop,l ,R(edi))
ret

426
mpi/i586/mpih-shift.S Normal file
View File

@ -0,0 +1,426 @@
/* i80586 rshift, lshift
* Copyright (c) 1997 by Werner Koch (dd9jn)
* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_lshift( mpi_ptr_t wp, (sp + 4)
* mpi_ptr_t up, (sp + 8)
* mpi_size_t usize, (sp + 12)
* unsigned cnt) (sp + 16)
*/
.text
ALIGN (3)
.globl C_SYMBOL_NAME(mpihelp_lshift)
C_SYMBOL_NAME(mpihelp_lshift:)
pushl %edi
pushl %esi
pushl %ebx
pushl %ebp
movl 20(%esp),%edi /* res_ptr */
movl 24(%esp),%esi /* s_ptr */
movl 28(%esp),%ebp /* size */
movl 32(%esp),%ecx /* cnt */
/* We can use faster code for shift-by-1 under certain conditions. */
cmp $1,%ecx
jne Lnormal
leal 4(%esi),%eax
cmpl %edi,%eax
jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */
leal (%esi,%ebp,4),%eax
cmpl %eax,%edi
jnc Lspecial /* jump if res_ptr >= s_ptr + size */
Lnormal:
leal -4(%edi,%ebp,4),%edi
leal -4(%esi,%ebp,4),%esi
movl (%esi),%edx
subl $4,%esi
xorl %eax,%eax
shldl %cl,%edx,%eax /* compute carry limb */
pushl %eax /* push carry limb onto stack */
decl %ebp
pushl %ebp
shrl $3,%ebp
jz Lend
movl (%edi),%eax /* fetch destination cache line */
ALIGN (2)
Loop: movl -28(%edi),%eax /* fetch destination cache line */
movl %edx,%ebx
movl (%esi),%eax
movl -4(%esi),%edx
shldl %cl,%eax,%ebx
shldl %cl,%edx,%eax
movl %ebx,(%edi)
movl %eax,-4(%edi)
movl -8(%esi),%ebx
movl -12(%esi),%eax
shldl %cl,%ebx,%edx
shldl %cl,%eax,%ebx
movl %edx,-8(%edi)
movl %ebx,-12(%edi)
movl -16(%esi),%edx
movl -20(%esi),%ebx
shldl %cl,%edx,%eax
shldl %cl,%ebx,%edx
movl %eax,-16(%edi)
movl %edx,-20(%edi)
movl -24(%esi),%eax
movl -28(%esi),%edx
shldl %cl,%eax,%ebx
shldl %cl,%edx,%eax
movl %ebx,-24(%edi)
movl %eax,-28(%edi)
subl $32,%esi
subl $32,%edi
decl %ebp
jnz Loop
Lend: popl %ebp
andl $7,%ebp
jz Lend2
Loop2: movl (%esi),%eax
shldl %cl,%eax,%edx
movl %edx,(%edi)
movl %eax,%edx
subl $4,%esi
subl $4,%edi
decl %ebp
jnz Loop2
Lend2: shll %cl,%edx /* compute least significant limb */
movl %edx,(%edi) /* store it */
popl %eax /* pop carry limb */
popl %ebp
popl %ebx
popl %esi
popl %edi
ret
/* We loop from least significant end of the arrays, which is only
permissable if the source and destination don't overlap, since the
function is documented to work for overlapping source and destination.
*/
Lspecial:
movl (%esi),%edx
addl $4,%esi
decl %ebp
pushl %ebp
shrl $3,%ebp
addl %edx,%edx
incl %ebp
decl %ebp
jz LLend
movl (%edi),%eax /* fetch destination cache line */
ALIGN (2)
LLoop: movl 28(%edi),%eax /* fetch destination cache line */
movl %edx,%ebx
movl (%esi),%eax
movl 4(%esi),%edx
adcl %eax,%eax
movl %ebx,(%edi)
adcl %edx,%edx
movl %eax,4(%edi)
movl 8(%esi),%ebx
movl 12(%esi),%eax
adcl %ebx,%ebx
movl %edx,8(%edi)
adcl %eax,%eax
movl %ebx,12(%edi)
movl 16(%esi),%edx
movl 20(%esi),%ebx
adcl %edx,%edx
movl %eax,16(%edi)
adcl %ebx,%ebx
movl %edx,20(%edi)
movl 24(%esi),%eax
movl 28(%esi),%edx
adcl %eax,%eax
movl %ebx,24(%edi)
adcl %edx,%edx
movl %eax,28(%edi)
leal 32(%esi),%esi /* use leal not to clobber carry */
leal 32(%edi),%edi
decl %ebp
jnz LLoop
LLend: popl %ebp
sbbl %eax,%eax /* save carry in %eax */
andl $7,%ebp
jz LLend2
addl %eax,%eax /* restore carry from eax */
LLoop2: movl %edx,%ebx
movl (%esi),%edx
adcl %edx,%edx
movl %ebx,(%edi)
leal 4(%esi),%esi /* use leal not to clobber carry */
leal 4(%edi),%edi
decl %ebp
jnz LLoop2
jmp LL1
LLend2: addl %eax,%eax /* restore carry from eax */
LL1: movl %edx,(%edi) /* store last limb */
sbbl %eax,%eax
negl %eax
popl %ebp
popl %ebx
popl %esi
popl %edi
ret
/*******************
* mpi_limb_t
* mpihelp_rshift( mpi_ptr_t wp, (sp + 4)
* mpi_ptr_t up, (sp + 8)
* mpi_size_t usize, (sp + 12)
* unsigned cnt) (sp + 16)
*/
.text
ALIGN (3)
.globl C_SYMBOL_NAME(mpihelp_rshift)
C_SYMBOL_NAME(mpihelp_rshift:)
pushl %edi
pushl %esi
pushl %ebx
pushl %ebp
movl 20(%esp),%edi /* res_ptr */
movl 24(%esp),%esi /* s_ptr */
movl 28(%esp),%ebp /* size */
movl 32(%esp),%ecx /* cnt */
/* We can use faster code for shift-by-1 under certain conditions. */
cmp $1,%ecx
jne Rnormal
leal 4(%edi),%eax
cmpl %esi,%eax
jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */
leal (%edi,%ebp,4),%eax
cmpl %eax,%esi
jnc Rspecial /* jump if s_ptr >= res_ptr + size */
Rnormal:
movl (%esi),%edx
addl $4,%esi
xorl %eax,%eax
shrdl %cl,%edx,%eax /* compute carry limb */
pushl %eax /* push carry limb onto stack */
decl %ebp
pushl %ebp
shrl $3,%ebp
jz Rend
movl (%edi),%eax /* fetch destination cache line */
ALIGN (2)
Roop: movl 28(%edi),%eax /* fetch destination cache line */
movl %edx,%ebx
movl (%esi),%eax
movl 4(%esi),%edx
shrdl %cl,%eax,%ebx
shrdl %cl,%edx,%eax
movl %ebx,(%edi)
movl %eax,4(%edi)
movl 8(%esi),%ebx
movl 12(%esi),%eax
shrdl %cl,%ebx,%edx
shrdl %cl,%eax,%ebx
movl %edx,8(%edi)
movl %ebx,12(%edi)
movl 16(%esi),%edx
movl 20(%esi),%ebx
shrdl %cl,%edx,%eax
shrdl %cl,%ebx,%edx
movl %eax,16(%edi)
movl %edx,20(%edi)
movl 24(%esi),%eax
movl 28(%esi),%edx
shrdl %cl,%eax,%ebx
shrdl %cl,%edx,%eax
movl %ebx,24(%edi)
movl %eax,28(%edi)
addl $32,%esi
addl $32,%edi
decl %ebp
jnz Roop
Rend: popl %ebp
andl $7,%ebp
jz Rend2
Roop2: movl (%esi),%eax
shrdl %cl,%eax,%edx /* compute result limb */
movl %edx,(%edi)
movl %eax,%edx
addl $4,%esi
addl $4,%edi
decl %ebp
jnz Roop2
Rend2: shrl %cl,%edx /* compute most significant limb */
movl %edx,(%edi) /* store it */
popl %eax /* pop carry limb */
popl %ebp
popl %ebx
popl %esi
popl %edi
ret
/* We loop from least significant end of the arrays, which is only
permissable if the source and destination don't overlap, since the
function is documented to work for overlapping source and destination.
*/
Rspecial:
leal -4(%edi,%ebp,4),%edi
leal -4(%esi,%ebp,4),%esi
movl (%esi),%edx
subl $4,%esi
decl %ebp
pushl %ebp
shrl $3,%ebp
shrl $1,%edx
incl %ebp
decl %ebp
jz RLend
movl (%edi),%eax /* fetch destination cache line */
ALIGN (2)
RLoop: movl -28(%edi),%eax /* fetch destination cache line */
movl %edx,%ebx
movl (%esi),%eax
movl -4(%esi),%edx
rcrl $1,%eax
movl %ebx,(%edi)
rcrl $1,%edx
movl %eax,-4(%edi)
movl -8(%esi),%ebx
movl -12(%esi),%eax
rcrl $1,%ebx
movl %edx,-8(%edi)
rcrl $1,%eax
movl %ebx,-12(%edi)
movl -16(%esi),%edx
movl -20(%esi),%ebx
rcrl $1,%edx
movl %eax,-16(%edi)
rcrl $1,%ebx
movl %edx,-20(%edi)
movl -24(%esi),%eax
movl -28(%esi),%edx
rcrl $1,%eax
movl %ebx,-24(%edi)
rcrl $1,%edx
movl %eax,-28(%edi)
leal -32(%esi),%esi /* use leal not to clobber carry */
leal -32(%edi),%edi
decl %ebp
jnz RLoop
RLend: popl %ebp
sbbl %eax,%eax /* save carry in %eax */
andl $7,%ebp
jz RLend2
addl %eax,%eax /* restore carry from eax */
RLoop2: movl %edx,%ebx
movl (%esi),%edx
rcrl $1,%edx
movl %ebx,(%edi)
leal -4(%esi),%esi /* use leal not to clobber carry */
leal -4(%edi),%edi
decl %ebp
jnz RLoop2
jmp RL1
RLend2: addl %eax,%eax /* restore carry from eax */
RL1: movl %edx,(%edi) /* store last limb */
movl $0,%eax
rcrl $1,%eax
popl %ebp
popl %ebx
popl %esi
popl %edi
ret

143
mpi/i586/mpih-sub1.S Normal file
View File

@ -0,0 +1,143 @@
/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store
* sum in a third limb vector.
* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
* Copyright (c) 1997 by Werner Koch (dd9jn)
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include "sysdep.h"
#include "asm-syntax.h"
/*******************
* mpi_limb_t
* mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4)
* mpi_ptr_t s1_ptr, (sp + 8)
* mpi_ptr_t s2_ptr, (sp + 12)
* mpi_size_t size) (sp + 16)
*/
.text
ALIGN (3)
.globl C_SYMBOL_NAME(mpihelp_sub_n)
C_SYMBOL_NAME(mpihelp_sub_n:)
pushl %edi
pushl %esi
pushl %ebx
pushl %ebp
movl 20(%esp),%edi /* res_ptr */
movl 24(%esp),%esi /* s1_ptr */
movl 28(%esp),%ebp /* s2_ptr */
movl 32(%esp),%ecx /* size */
movl (%ebp),%ebx
decl %ecx
movl %ecx,%edx
shrl $3,%ecx
andl $7,%edx
testl %ecx,%ecx /* zero carry flag */
jz Lend
pushl %edx
ALIGN (3)
Loop: movl 28(%edi),%eax /* fetch destination cache line */
leal 32(%edi),%edi
L1: movl (%esi),%eax
movl 4(%esi),%edx
sbbl %ebx,%eax
movl 4(%ebp),%ebx
sbbl %ebx,%edx
movl 8(%ebp),%ebx
movl %eax,-32(%edi)
movl %edx,-28(%edi)
L2: movl 8(%esi),%eax
movl 12(%esi),%edx
sbbl %ebx,%eax
movl 12(%ebp),%ebx
sbbl %ebx,%edx
movl 16(%ebp),%ebx
movl %eax,-24(%edi)
movl %edx,-20(%edi)
L3: movl 16(%esi),%eax
movl 20(%esi),%edx
sbbl %ebx,%eax
movl 20(%ebp),%ebx
sbbl %ebx,%edx
movl 24(%ebp),%ebx
movl %eax,-16(%edi)
movl %edx,-12(%edi)
L4: movl 24(%esi),%eax
movl 28(%esi),%edx
sbbl %ebx,%eax
movl 28(%ebp),%ebx
sbbl %ebx,%edx
movl 32(%ebp),%ebx
movl %eax,-8(%edi)
movl %edx,-4(%edi)
leal 32(%esi),%esi
leal 32(%ebp),%ebp
decl %ecx
jnz Loop
popl %edx
Lend:
decl %edx /* test %edx w/o clobbering carry */
js Lend2
incl %edx
Loop2:
leal 4(%edi),%edi
movl (%esi),%eax
sbbl %ebx,%eax
movl 4(%ebp),%ebx
movl %eax,-4(%edi)
leal 4(%esi),%esi
leal 4(%ebp),%ebp
decl %edx
jnz Loop2
Lend2:
movl (%esi),%eax
sbbl %ebx,%eax
movl %eax,(%edi)
sbbl %eax,%eax
negl %eax
popl %ebp
popl %ebx
popl %esi
popl %edi
ret

View File

@ -76,7 +76,7 @@ mpi_invm( MPI x, MPI a, MPI n )
mpi_free(t3);
mpi_free(u);
mpi_free(v);
#else
#elif 0
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercice 35 */
@ -156,6 +156,107 @@ mpi_invm( MPI x, MPI a, MPI n )
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
#else
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercice 35
* with further enhancement */
MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3;
unsigned k;
int sign;
int odd ;
u = mpi_copy(a);
v = mpi_copy(n);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
}
odd = mpi_test_bit(v,0);
u1 = mpi_alloc_set_ui(1);
if( !odd )
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v);
if( !odd ) {
v2 = mpi_alloc( mpi_get_nlimbs(u) );
mpi_sub( v2, u1, u ); /* U is used as const 1 */
}
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
if( !odd ) {
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
}
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
if( !odd )
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( !odd ) {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
}
else {
if( mpi_test_bit(t1, 0) )
mpi_add(t1, t1, v);
mpi_rshift(t1, t1, 1);
mpi_rshift(t3, t3, 1);
}
Y4:
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
if( !odd )
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
if( !odd )
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
if( !odd )
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
if( !odd )
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(v1);
mpi_free(t1);
if( !odd ) {
mpi_free(u2);
mpi_free(v2);
mpi_free(t2);
}
mpi_free(u3);
mpi_free(v3);
mpi_free(t3);
#endif
}

119
mpi/mpi-mpow.c Normal file
View File

@ -0,0 +1,119 @@
/* mpi-mpow.c - MPI functions
* Copyright (c) 1998 by Werner Koch (dd9jn)
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "longlong.h"
#include <assert.h>
static int
build_index( MPI *exparray, int k, int i, int t )
{
int j, bitno;
int index = 0;
bitno = t-i;
for(j=k-1; j >= 0; j-- ) {
index <<= 1;
if( mpi_test_bit( exparray[j], bitno ) )
index |= 1;
}
/*log_debug("t=%d i=%d index=%d\n", t, i, index );*/
return index;
}
/****************
* RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M
*/
void
mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
{
int k; /* number of elements */
int t; /* bit size of largest exponent */
int i, j, idx;
MPI *G; /* table with precomputed values of size 2^k */
MPI tmp;
for(k=0; basearray[k]; k++ )
;
assert(k);
for(t=0, i=0; (tmp=exparray[i]); i++ ) {
/*log_mpidump("exp: ", tmp );*/
j = mpi_get_nbits(tmp);
if( j > t )
t = j;
}
/*log_mpidump("mod: ", m );*/
assert(i==k);
assert(t);
assert( k < 10 );
G = m_alloc_clear( (1<<k) * sizeof *G );
#if 0
/* do the precomputation */
G[0] = mpi_alloc_set_ui( 1 );
for(i=1; i < (1<<k); i++ ) {
for(j=0; j < k; j++ ) {
if( (i & (1<<j) ) ) {
if( !G[i] )
G[i] = mpi_copy( basearray[j] );
else
mpi_mulm( G[i], G[i], basearray[j], m );
}
}
if( !G[i] )
G[i] = mpi_alloc(0);
}
#endif
/* and calculate */
tmp = mpi_alloc( mpi_get_nlimbs(m)+1 );
mpi_set_ui( res, 1 );
for(i = 1; i <= t; i++ ) {
mpi_mulm(tmp, res, res, m );
idx = build_index( exparray, k, i, t );
assert( idx >= 0 && idx < (1<<k) );
if( !G[idx] ) {
if( !idx )
G[0] = mpi_alloc_set_ui( 1 );
else {
for(j=0; j < k; j++ ) {
if( (idx & (1<<j) ) ) {
if( !G[idx] )
G[idx] = mpi_copy( basearray[j] );
else
mpi_mulm( G[idx], G[idx], basearray[j], m );
}
}
if( !G[idx] )
G[idx] = mpi_alloc(0);
}
}
mpi_mulm(res, tmp, G[idx], m );
}
/* cleanup */
m_free(tmp);
for(i=0; i < (1<<k); i++ )
mpi_free(G[i]);
m_free(G);
}

View File

@ -0,0 +1,5 @@
Tue Feb 10 11:57:23 1998 Werner Koch (wk@frodo)
* ddd/hhhh:

View File

@ -119,7 +119,7 @@ bftest_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = ChangeLog Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

View File

@ -109,7 +109,7 @@ AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DIST_COMMON = ChangeLog Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

View File

@ -313,7 +313,7 @@ iobuf_close( IOBUF a )
size_t dummy_len;
int rc=0;
for( ; a; a = a2 ) {
for( ; a && !rc ; a = a2 ) {
a2 = a->chain;
if( a->usage == 2 && (rc=iobuf_flush(a)) )
log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
@ -723,6 +723,26 @@ iobuf_readbyte(IOBUF a)
}
int
iobuf_read(IOBUF a, byte *buf, unsigned buflen )
{
int c, n;
for(n=0 ; n < buflen; n++, buf++ ) {
if( (c = iobuf_readbyte(a)) == -1 ) {
if( !n )
return -1; /* eof */
break;
}
else
*buf = c;
}
return n;
}
int
iobuf_writebyte(IOBUF a, unsigned c)
{