diff options
author | Werner Koch <wk@gnupg.org> | 1998-01-12 11:18:17 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 1998-01-12 11:18:17 +0100 |
commit | ed3609258828942808702a07ef2986d7328efa3f (patch) | |
tree | 185f17c055b38fee37bc0090789dcf96a1535c8c | |
parent | patchlevel 2 (diff) | |
download | gnupg2-ed3609258828942808702a07ef2986d7328efa3f.tar.xz gnupg2-ed3609258828942808702a07ef2986d7328efa3f.zip |
started with trust stuff
54 files changed, 1870 insertions, 709 deletions
@@ -1,26 +1,183 @@ - - 1) Configure for your machine: - - ./configure - - or use - - ./configure --enable-m-debug - - to enable the integrated malloc debugging stuff. - - - 2) Run make: - - make - - - 3) Install - - make install - - - 4) You end up with a binary "g10" in /usr/local/bin - - +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. @@ -0,0 +1,6 @@ + + * The string "(INSECURE!)" is appended to a new user-id if this + is generated on a system without a good random number generator. + + * works (more or less) on a UltraPenguin (sparc64--gnu-linux) + @@ -42,6 +42,24 @@ + Installation + ------------ + + 1) "./configure" + + to enable the integrated malloc debugging stuff, use: + + "./configure --enable-m-debug" + + 2) "make" + + 3) "make install" + + 4) You end up with a binary "g10" in /usr/local/bin + + + + Resources --------- G10 needs a directory "~/.g10" to store the default keyrings @@ -37,4 +37,6 @@ * add g10 stuff to Mutt's pgpinvoke.c + * Burn the buffers used by fopen(). + @@ -1 +1 @@ -0.1.2 +0.1.3 diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 0855d7da9..ecd91a731 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -23,6 +23,7 @@ cipher_SOURCES = blowfish.c \ dsa.h \ dsa.c \ md.c \ + md.h \ misc.c \ smallprime.c diff --git a/cipher/Makefile.in b/cipher/Makefile.in index 7bd7691f8..221efdd25 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -60,6 +60,7 @@ cipher_SOURCES = blowfish.c \ dsa.h \ dsa.c \ md.c \ + md.h \ misc.c \ smallprime.c diff --git a/cipher/md.c b/cipher/md.c index 67f5356a8..e88a45c77 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -27,146 +27,135 @@ #include "errors.h" -int -md_okay( int algo ) -{ - return check_digest_algo( algo ); -} - - -MD_HANDLE * +/**************** + * Open a message digest handle for use with algorithm ALGO. + * More algorithms may be added by md_enable(). The initial algorithm + * may be 0. + */ +MD_HANDLE md_open( int algo, int secure ) { - MD_HANDLE *hd; - - hd = m_alloc( sizeof *hd + 19 ); - hd->algo = algo; - hd->datalen = 0; - if( algo == DIGEST_ALGO_MD5 ) - hd->u.md5 = md5_open( secure ); - else if( algo == DIGEST_ALGO_RMD160 ) - hd->u.rmd= rmd160_open( secure ); - else if( algo == DIGEST_ALGO_SHA1 ) - hd->u.sha1 = sha1_open( secure ); - else - return NULL; + MD_HANDLE hd; + hd = secure ? m_alloc_secure_clear( sizeof *hd ) + : m_alloc_clear( sizeof *hd ); + if( algo ) + md_enable( hd, algo ); return hd; } - -MD_HANDLE * -md_copy( MD_HANDLE *a ) +void +md_enable( MD_HANDLE h, int algo ) { - MD_HANDLE *hd; - - hd = m_alloc( sizeof *hd + 19 ); - hd->algo = a->algo; - hd->datalen = 0; - if( a->algo == DIGEST_ALGO_MD5 ) - hd->u.md5 = md5_copy( a->u.md5 ); - else if( a->algo == DIGEST_ALGO_RMD160 ) - hd->u.rmd= rmd160_copy( a->u.rmd ); - else if( a->algo == DIGEST_ALGO_SHA1 ) - hd->u.sha1= sha1_copy( a->u.sha1 ); + if( algo == DIGEST_ALGO_MD5 ) { + md5_init( &h->md5 ); + h->use_md5 = 1; + } + else if( algo == DIGEST_ALGO_RMD160 ) { + rmd160_init( &h->rmd160 ); + h->use_rmd160 = 1; + } + else if( algo == DIGEST_ALGO_SHA1 ) { + sha1_init( &h->sha1 ); + h->use_sha1 = 1; + } else - log_bug(NULL); - return hd; + log_bug("md_enable(%d)", algo ); } -/* used for a BAD Kludge in rmd160.c, md5.c */ -MD_HANDLE * -md_makecontainer( int algo ) +MD_HANDLE +md_copy( MD_HANDLE a ) { - MD_HANDLE *hd; - - hd = m_alloc( sizeof *hd + 19 ); - hd->algo = algo; - hd->datalen = 0; - if( algo == DIGEST_ALGO_MD5 ) - ; - else if( algo == DIGEST_ALGO_RMD160 ) - ; - else if( algo == DIGEST_ALGO_SHA1 ) - ; - else - log_bug(NULL); - return hd; + MD_HANDLE b; + + b = m_is_secure(a)? m_alloc_secure( sizeof *b ) + : m_alloc( sizeof *b ); + memcpy( b, a, sizeof *a ); + return b; } + void -md_close(MD_HANDLE *a) +md_close(MD_HANDLE a) { if( !a ) return; - if( a->algo == DIGEST_ALGO_MD5 ) - md5_close( a->u.md5 ); - else if( a->algo == DIGEST_ALGO_RMD160 ) - rmd160_close( a->u.rmd ); - else if( a->algo == DIGEST_ALGO_SHA1 ) - sha1_close( a->u.sha1 ); - else - log_bug(NULL); m_free(a); } void -md_write( MD_HANDLE *a, byte *inbuf, size_t inlen) +md_write( MD_HANDLE a, byte *inbuf, size_t inlen) { - if( a->algo == DIGEST_ALGO_MD5 ) - md5_write( a->u.md5, inbuf, inlen ); - else if( a->algo == DIGEST_ALGO_RMD160 ) - rmd160_write( a->u.rmd, inbuf, inlen ); - else if( a->algo == DIGEST_ALGO_SHA1 ) - sha1_write( a->u.sha1, inbuf, inlen ); - else - log_bug(NULL); + if( a->use_rmd160 ) { + rmd160_write( &a->rmd160, a->buffer, a->bufcount ); + rmd160_write( &a->rmd160, inbuf, inlen ); + } + if( a->use_sha1 ) { + sha1_write( &a->sha1, a->buffer, a->bufcount ); + sha1_write( &a->sha1, inbuf, inlen ); + } + if( a->use_md5 ) { + md5_write( &a->md5, a->buffer, a->bufcount ); + md5_write( &a->md5, inbuf, inlen ); + } + a->bufcount = 0; } + void -md_putchar( MD_HANDLE *a, int c ) +md_final(MD_HANDLE a) { - if( a->algo == DIGEST_ALGO_MD5 ) - md5_putchar( a->u.md5, c ); - else if( a->algo == DIGEST_ALGO_RMD160 ) - rmd160_putchar( a->u.rmd, c ); - else if( a->algo == DIGEST_ALGO_SHA1 ) - sha1_putchar( a->u.sha1, c ); - else - log_bug(NULL); + if( a->bufcount ) + md_write( a, NULL, 0 ); + if( a->use_rmd160 ) { + byte *p; + rmd160_final( &a->rmd160 ); + p = rmd160_read( &a->rmd160 ); + } + if( a->use_sha1 ) + sha1_final( &a->sha1 ); + if( a->use_md5 ) + md5_final( &a->md5 ); } +/**************** + * if ALGO is null get the digest for the used algo (which should be only one) + */ byte * -md_final(MD_HANDLE *a) +md_read( MD_HANDLE a, int algo ) { - if( a->algo == DIGEST_ALGO_MD5 ) { - if( !a->datalen ) { - md5_final( a->u.md5 ); - memcpy(a->data, md5_read( a->u.md5 ), 16); - a->datalen = 16; - } - return a->data; + if( !algo ) { + if( a->use_rmd160 ) + return rmd160_read( &a->rmd160 ); + if( a->use_sha1 ) + return sha1_read( &a->sha1 ); + if( a->use_md5 ) + return md5_read( &a->md5 ); } - else if( a->algo == DIGEST_ALGO_RMD160 ) { - if( !a->datalen ) { - memcpy(a->data, rmd160_final( a->u.rmd ), 20 ); - a->datalen = 20; - } - return a->data; + else { + if( algo == DIGEST_ALGO_RMD160 ) + return rmd160_read( &a->rmd160 ); + if( algo == DIGEST_ALGO_SHA1 ) + return sha1_read( &a->sha1 ); + if( algo == DIGEST_ALGO_MD5 ) + return md5_read( &a->md5 ); } - else if( a->algo == DIGEST_ALGO_SHA1 ) { - if( !a->datalen ) { - memcpy(a->data, sha1_final( a->u.sha1 ), 20 ); - a->datalen = 20; - } - return a->data; - } - else - log_bug(NULL); + log_bug(NULL); } +int +md_get_algo( MD_HANDLE a ) +{ + if( a->use_rmd160 ) + return DIGEST_ALGO_RMD160; + if( a->use_sha1 ) + return DIGEST_ALGO_SHA1; + if( a->use_md5 ) + return DIGEST_ALGO_MD5; + return 0; +} diff --git a/cipher/md.h b/cipher/md.h new file mode 100644 index 000000000..8a7886d03 --- /dev/null +++ b/cipher/md.h @@ -0,0 +1,60 @@ +/* md.h - digest functions + * 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 + */ +#ifndef G10_MD_H +#define G10_MD_H + +#include "types.h" +#include "rmd.h" +#include "sha1.h" +#include "md5.h" + +#define MD_BUFFER_SIZE 512 + +typedef struct { + int use_rmd160; + RMD160_CONTEXT rmd160; + int use_sha1; + SHA1_CONTEXT sha1; + int use_md5; + MD5_CONTEXT md5; + byte buffer[MD_BUFFER_SIZE]; /* primary buffer */ + int bufcount; +} *MD_HANDLE; + + +#define md_putc(h,c) \ + do { \ + if( (h)->bufcount == MD_BUFFER_SIZE ) \ + md_write( (h), NULL, 0 ); \ + (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ + } while(0) + +/*-- md.c --*/ +MD_HANDLE md_open( int algo, int secure ); +void md_enable( MD_HANDLE hd, int algo ); +MD_HANDLE md_copy( MD_HANDLE a ); +void md_close(MD_HANDLE a); +void md_write( MD_HANDLE a, byte *inbuf, size_t inlen); +void md_final(MD_HANDLE a); +byte *md_read( MD_HANDLE a, int algo ); +int md_get_algo( MD_HANDLE a ); + + +#endif /*G10_MD_H*/ diff --git a/cipher/md5.c b/cipher/md5.c index be2602695..6906503d4 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -61,7 +61,6 @@ #include <assert.h> #include "util.h" #include "md5.h" -#include "cipher.h" /* kludge for md5_copy2md() */ #include "memory.h" @@ -74,7 +73,7 @@ #endif -static void Init( MD5HANDLE mdContext); +static void Init( MD5_CONTEXT *mdContext); static void Transform(u32 *buf,u32 *in); static byte PADDING[64] = { @@ -120,56 +119,9 @@ static byte PADDING[64] = { (a) += (b); \ } -/* The routine Init initializes the message-digest context - * mdContext. All fields are set to zero. - * mode should be zero is reserved for extensions. - */ - -MD5HANDLE -md5_open(int secure) -{ - MD5HANDLE mdContext; - - mdContext = secure? m_alloc_secure( sizeof *mdContext ) - : m_alloc( sizeof *mdContext ); - Init(mdContext); - return mdContext; -} - - -MD5HANDLE -md5_copy( MD5HANDLE a ) -{ - MD5HANDLE mdContext; - - assert(a); - mdContext = m_is_secure(a)? m_alloc_secure( sizeof *mdContext ) - : m_alloc( sizeof *mdContext ); - memcpy( mdContext, a, sizeof *a ); - return mdContext; -} - - -/* BAD Kludge!!! */ -MD_HANDLE * -md5_copy2md( MD5HANDLE a ) -{ - MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_MD5 ); - md->u.md5 = md5_copy( a ); - return md; -} - void -md5_close(MD5HANDLE hd) -{ - if( hd ) - m_free(hd); -} - - -static void -Init( MD5HANDLE mdContext) +md5_init( MD5_CONTEXT *mdContext) { mdContext->i[0] = mdContext->i[1] = (u32)0; /* Load magic initialization constants. @@ -178,7 +130,7 @@ Init( MD5HANDLE mdContext) mdContext->buf[1] = (u32)0xefcdab89L; mdContext->buf[2] = (u32)0x98badcfeL; mdContext->buf[3] = (u32)0x10325476L; - mdContext->bufcount = 0; + mdContext->count = 0; } /* The routine Update updates the message-digest context to @@ -186,15 +138,15 @@ Init( MD5HANDLE mdContext) * in the message whose digest is being computed. */ void -md5_write( MD5HANDLE mdContext, byte *inBuf, size_t inLen) +md5_write( MD5_CONTEXT *mdContext, byte *inBuf, size_t inLen) { register int i, ii; int mdi; u32 in[16]; - if(mdContext->bufcount) { /* flush the buffer */ - i = mdContext->bufcount; - mdContext->bufcount = 0; + if(mdContext->count) { /* flush the buffer */ + i = mdContext->count; + mdContext->count = 0; md5_write( mdContext, mdContext->digest, i); } if( !inBuf ) @@ -227,20 +179,6 @@ md5_write( MD5HANDLE mdContext, byte *inBuf, size_t inLen) } -/**************** - * Process a single character, this character will be buffered to - * increase performance. The digest-field is used as a buffer. - */ - -void -md5_putchar( MD5HANDLE mdContext, int c ) -{ - if(mdContext->bufcount == 16) - md5_write( mdContext, NULL, 0 ); - mdContext->digest[mdContext->bufcount++] = c & 0xff; -} - - /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. @@ -249,14 +187,14 @@ md5_putchar( MD5HANDLE mdContext, int c ) */ void -md5_final(MD5HANDLE mdContext) +md5_final( MD5_CONTEXT *mdContext ) { u32 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; - if(mdContext->bufcount) /* flush buffer */ + if(mdContext->count) /* flush buffer */ md5_write(mdContext, NULL, 0 ); /* save number of bits */ in[14] = mdContext->i[0]; @@ -284,49 +222,6 @@ md5_final(MD5HANDLE mdContext) mdContext->digest[ii+2] = (byte)((mdContext->buf[i] >> 16) & 0xFF); mdContext->digest[ii+3] = (byte)((mdContext->buf[i] >> 24) & 0xFF); } - Init(mdContext); -} - -/********** - * Returns 16 bytes representing the digest. - */ -byte * -md5_read(MD5HANDLE mdContext) -{ - return mdContext->digest; -} - - - -/**************** - * Converts the result form Read into a printable representation. - * This should only be used direct after a md5_read(), because it uses - * In-Place conversion. - * Returns digest. - */ - -char * -md5_tostring( byte *digest ) -{ - static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ." - "abcdefghijklmnopqrstuvwxyz_" - "0123456789"; - int i; - byte *d, *s; - - memmove(digest+8,digest, 16); /* make some room */ - d = digest; - s = digest+8; - for(i=0; i < 5; i++, s += 3 ) { - *d++ = bintoasc[(*s >> 2) & 077]; - *d++ = bintoasc[(((*s << 4) & 060) | ((s[1] >> 4) & 017)) & 077]; - *d++ = bintoasc[(((s[1] << 2) & 074) | ((s[2] >> 6) & 03)) & 077]; - *d++ = bintoasc[s[2] & 077]; - } - *d++ = bintoasc[(*s >> 2) & 077]; - *d++ = bintoasc[((*s << 4) & 060) & 077]; - *d = 0; - return (char*)digest; } diff --git a/cipher/md5.h b/cipher/md5.h index fa401a162..c46075a3b 100644 --- a/cipher/md5.h +++ b/cipher/md5.h @@ -25,20 +25,15 @@ typedef struct { u32 i[2]; /* number of _bits_ handled mod 2^64 */ u32 buf[4]; /* scratch buffer */ + int count; byte in[64]; /* input buffer */ byte digest[16+8+1]; /* actual digest after Final call */ - byte bufcount; /* extra room for bintoascii */ -} *MD5HANDLE; +} MD5_CONTEXT; -/*-- md5.c --*/ -MD5HANDLE md5_open(int); -MD5HANDLE md5_copy(MD5HANDLE a); -void md5_write(MD5HANDLE hd, byte *inBuf, size_t inLen); -void md5_putchar(MD5HANDLE hd, int c ); -void md5_final(MD5HANDLE hd); -byte *md5_read(MD5HANDLE hd); -char *md5_tostring( byte *digest ); -void md5_close(MD5HANDLE hd); +void md5_init( MD5_CONTEXT *c ); +void md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen); +void md5_final( MD5_CONTEXT *hd); +#define md5_read(h) ( (h)->digest ) #endif /*G10_MD5_H*/ diff --git a/cipher/random.c b/cipher/random.c index a95e7e50d..41f001e7e 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -82,13 +82,12 @@ open_device( const char *name, int minor ) log_fatal("can't open %s: %s\n", name, strerror(errno) ); if( fstat( fd, &sb ) ) log_fatal("stat() off %s failed: %s\n", name, strerror(errno) ); - if( !S_ISCHR(sb.st_mode) - #ifdef __linux__ - || (sb.st_rdev >> 8) != 1 - || (sb.st_rdev & 0xff) != minor - #endif - ) + #if defined(__sparc__) && defined(__linux__) + #warning something is wrong with UltraPenguin /dev/random + #else + if( !S_ISCHR(sb.st_mode) ) log_fatal("invalid random device!\n" ); + #endif return fd; } @@ -140,6 +139,10 @@ the OS a chance to collect more entropy! (Need %d more bytes)\n", length ); assert( length < 200 ); do { n = read(fd, buffer, length ); + if( n > length ) { + log_error("bogus read from random device (n=%d)\n", n ); + n = length; + } } while( n == -1 && errno == EINTR ); if( n == -1 ) log_fatal("read error on random device: %s\n", strerror(errno) ); diff --git a/cipher/rmd.h b/cipher/rmd.h index 3d260cdca..8f53634d8 100644 --- a/cipher/rmd.h +++ b/cipher/rmd.h @@ -25,27 +25,14 @@ typedef struct { u32 h0,h1,h2,h3,h4; u32 nblocks; - byte buffer[64]; - int bufcount; -} *RMDHANDLE; + byte buf[64]; + int count; +} RMD160_CONTEXT; -/**************** - * Process a single character, this character will be buffered to - * increase performance. - */ -#define rmd160_putchar(h,c) \ - do { \ - if( (h)->bufcount == 64 ) \ - rmd160_write( (h), NULL, 0 ); \ - (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ - } while(0) - -RMDHANDLE rmd160_open( int secure ); -RMDHANDLE rmd160_copy( RMDHANDLE a ); -void rmd160_close(RMDHANDLE hd); -void rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen); -byte * rmd160_final(RMDHANDLE hd); - +void rmd160_init( RMD160_CONTEXT *c ); +void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen); +void rmd160_final(RMD160_CONTEXT *hd); +#define rmd160_read(h) ( (h)->buf ) #endif /*G10_RMD_H*/ diff --git a/cipher/rmd160.c b/cipher/rmd160.c index e8c424fa6..0b501d77b 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -25,7 +25,6 @@ #include <assert.h> #include "util.h" #include "memory.h" -#include "cipher.h" /* grrrr */ #include "rmd.h" /********************************* @@ -139,16 +138,16 @@ */ -static void -initialize( RMDHANDLE hd ) +void +rmd160_init( RMD160_CONTEXT *hd ) { hd->h0 = 0x67452301; hd->h1 = 0xEFCDAB89; hd->h2 = 0x98BADCFE; hd->h3 = 0x10325476; hd->h4 = 0xC3D2E1F0; - hd->bufcount = 0; hd->nblocks = 0; + hd->count = 0; } @@ -156,7 +155,7 @@ initialize( RMDHANDLE hd ) * Transform the message X which consists of 16 32-bit-words */ static void -transform( RMDHANDLE hd, byte *data ) +transform( RMD160_CONTEXT *hd, byte *data ) { static int r[80] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -257,68 +256,22 @@ transform( RMDHANDLE hd, byte *data ) - -RMDHANDLE -rmd160_open( int secure ) -{ - RMDHANDLE hd; - - hd = secure? m_alloc_secure( sizeof *hd ) - : m_alloc( sizeof *hd ); - initialize(hd); - return hd; -} - - -RMDHANDLE -rmd160_copy( RMDHANDLE a ) -{ - RMDHANDLE b; - - assert(a); - b = m_is_secure(a)? m_alloc_secure( sizeof *b ) - : m_alloc( sizeof *b ); - memcpy( b, a, sizeof *a ); - return b; -} - - -/* BAD Kludge!!! */ -MD_HANDLE * -rmd160_copy2md( RMDHANDLE a ) -{ - MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_RMD160 ); - md->u.rmd = rmd160_copy( a ); - return md; -} - - - -void -rmd160_close(RMDHANDLE hd) -{ - if( hd ) - m_free(hd); -} - - - /* Update the message digest with the contents * of INBUF with length INLEN. */ void -rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen) +rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) { - if( hd->bufcount == 64 ) { /* flush the buffer */ - transform( hd, hd->buffer ); - hd->bufcount = 0; + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + hd->count = 0; hd->nblocks++; } if( !inbuf ) return; - if( hd->bufcount ) { - for( ; inlen && hd->bufcount < 64; inlen-- ) - hd->buffer[hd->bufcount++] = *inbuf++; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; rmd160_write( hd, NULL, 0 ); if( !inlen ) return; @@ -326,25 +279,21 @@ rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen) while( inlen >= 64 ) { transform( hd, inbuf ); - hd->bufcount = 0; + hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } - for( ; inlen && hd->bufcount < 64; inlen-- ) - hd->buffer[hd->bufcount++] = *inbuf++; + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; } -/* The routine final terminates the computation and - * returns the digest. - * The handle is prepared for a new cycle, but adding bytes to the - * handle will the destroy the returned buffer. - * Returns: 20 bytes representing the digest. +/* The routine terminates the computation */ -byte * -rmd160_final(RMDHANDLE hd) +void +rmd160_final( RMD160_CONTEXT *hd ) { u32 t, msb, lsb; byte *p; @@ -357,37 +306,37 @@ rmd160_final(RMDHANDLE hd) msb++; msb += t >> 26; t = lsb; - if( (lsb = t + hd->bufcount) < t ) /* add the bufcount */ + if( (lsb = t + hd->count) < t ) /* add the count */ msb++; t = lsb; if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */ msb++; msb += t >> 29; - if( hd->bufcount < 56 ) { /* enough room */ - hd->buffer[hd->bufcount++] = 0x80; /* pad */ - while( hd->bufcount < 56 ) - hd->buffer[hd->bufcount++] = 0; /* pad */ + if( hd->count < 56 ) { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ - hd->buffer[hd->bufcount++] = 0x80; /* pad character */ - while( hd->bufcount < 64 ) - hd->buffer[hd->bufcount++] = 0; + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; rmd160_write(hd, NULL, 0); /* flush */; - memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */ + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->buffer[56] = lsb ; - hd->buffer[57] = lsb >> 8; - hd->buffer[58] = lsb >> 16; - hd->buffer[59] = lsb >> 24; - hd->buffer[60] = msb ; - hd->buffer[61] = msb >> 8; - hd->buffer[62] = msb >> 16; - hd->buffer[63] = msb >> 24; - transform( hd, hd->buffer ); - - p = hd->buffer; + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + + p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) @@ -400,10 +349,6 @@ rmd160_final(RMDHANDLE hd) X(3); X(4); #undef X - - initialize( hd ); /* prepare for next cycle */ - return hd->buffer; /* now contains the digest */ } - diff --git a/cipher/sha1.c b/cipher/sha1.c index 1685058f3..51029c451 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -84,7 +84,6 @@ #include <assert.h> #include "util.h" #include "memory.h" -#include "cipher.h" /* grrrr */ #include "sha1.h" @@ -110,16 +109,16 @@ ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) -static void -initialize( SHA1HANDLE hd ) +void +sha1_init( SHA1_CONTEXT *hd ) { hd->h0 = 0x67452301; hd->h1 = 0xefcdab89; hd->h2 = 0x98badcfe; hd->h3 = 0x10325476; hd->h4 = 0xc3d2e1f0; - hd->bufcount = 0; hd->nblocks = 0; + hd->count = 0; } @@ -127,7 +126,7 @@ initialize( SHA1HANDLE hd ) * Transform the message X which consists of 16 32-bit-words */ static void -transform( SHA1HANDLE hd, byte *data ) +transform( SHA1_CONTEXT *hd, byte *data ) { u32 A, B, C, D, E; /* Local vars */ u32 eData[ 16 ]; /* Expanded data */ @@ -247,69 +246,22 @@ transform( SHA1HANDLE hd, byte *data ) } - - -SHA1HANDLE -sha1_open( int secure ) -{ - SHA1HANDLE hd; - - hd = secure? m_alloc_secure( sizeof *hd ) - : m_alloc( sizeof *hd ); - initialize(hd); - return hd; -} - - -SHA1HANDLE -sha1_copy( SHA1HANDLE a ) -{ - SHA1HANDLE b; - - assert(a); - b = m_is_secure(a)? m_alloc_secure( sizeof *b ) - : m_alloc( sizeof *b ); - memcpy( b, a, sizeof *a ); - return b; -} - - -/* BAD Kludge!!! */ -MD_HANDLE * -sha1_copy2md( SHA1HANDLE a ) -{ - MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_SHA1 ); - md->u.sha1 = sha1_copy( a ); - return md; -} - - - -void -sha1_close(SHA1HANDLE hd) -{ - if( hd ) - m_free(hd); -} - - - /* Update the message digest with the contents * of INBUF with length INLEN. */ void -sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen) +sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) { - if( hd->bufcount == 64 ) { /* flush the buffer */ - transform( hd, hd->buffer ); - hd->bufcount = 0; + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + hd->count = 0; hd->nblocks++; } if( !inbuf ) return; - if( hd->bufcount ) { - for( ; inlen && hd->bufcount < 64; inlen-- ) - hd->buffer[hd->bufcount++] = *inbuf++; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; sha1_write( hd, NULL, 0 ); if( !inlen ) return; @@ -317,13 +269,13 @@ sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen) while( inlen >= 64 ) { transform( hd, inbuf ); - hd->bufcount = 0; + hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } - for( ; inlen && hd->bufcount < 64; inlen-- ) - hd->buffer[hd->bufcount++] = *inbuf++; + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; } @@ -334,8 +286,8 @@ sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen) * Returns: 20 bytes representing the digest. */ -byte * -sha1_final(SHA1HANDLE hd) +void +sha1_final(SHA1_CONTEXT *hd) { u32 t, msb, lsb; byte *p; @@ -348,37 +300,37 @@ sha1_final(SHA1HANDLE hd) msb++; msb += t >> 26; t = lsb; - if( (lsb = t + hd->bufcount) < t ) /* add the bufcount */ + if( (lsb = t + hd->count) < t ) /* add the count */ msb++; t = lsb; if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */ msb++; msb += t >> 29; - if( hd->bufcount < 56 ) { /* enough room */ - hd->buffer[hd->bufcount++] = 0x80; /* pad */ - while( hd->bufcount < 56 ) - hd->buffer[hd->bufcount++] = 0; /* pad */ + if( hd->count < 56 ) { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ - hd->buffer[hd->bufcount++] = 0x80; /* pad character */ - while( hd->bufcount < 64 ) - hd->buffer[hd->bufcount++] = 0; + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; sha1_write(hd, NULL, 0); /* flush */; - memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */ + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->buffer[56] = msb >> 24; - hd->buffer[57] = msb >> 16; - hd->buffer[58] = msb >> 8; - hd->buffer[59] = msb ; - hd->buffer[60] = lsb >> 24; - hd->buffer[61] = lsb >> 16; - hd->buffer[62] = lsb >> 8; - hd->buffer[63] = lsb ; - transform( hd, hd->buffer ); - - p = hd->buffer; + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb ; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb ; + transform( hd, hd->buf ); + + p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) #else /* little endian */ @@ -392,8 +344,6 @@ sha1_final(SHA1HANDLE hd) X(4); #undef X - initialize( hd ); /* prepare for next cycle */ - return hd->buffer; /* now contains the digest */ } diff --git a/cipher/sha1.h b/cipher/sha1.h index ca03936f2..93af2cace 100644 --- a/cipher/sha1.h +++ b/cipher/sha1.h @@ -25,26 +25,14 @@ typedef struct { u32 h0,h1,h2,h3,h4; u32 nblocks; - byte buffer[64]; - int bufcount; -} *SHA1HANDLE; + byte buf[64]; + int count; +} SHA1_CONTEXT; -/**************** - * Process a single character, this character will be buffered to - * increase performance. - */ -#define sha1_putchar(h,c) \ - do { \ - if( (h)->bufcount == 64 ) \ - sha1_write( (h), NULL, 0 ); \ - (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ - } while(0) - -SHA1HANDLE sha1_open( int secure ); -SHA1HANDLE sha1_copy( SHA1HANDLE a ); -void sha1_close( SHA1HANDLE hd ); -void sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen ); -byte * sha1_final( SHA1HANDLE hd ); +void sha1_init( SHA1_CONTEXT *c ); +void sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen); +void sha1_final( SHA1_CONTEXT *hd); +#define sha1_read(h) ( (h)->buf ) #endif /*G10_SHA1_H*/ diff --git a/doc/DETAILS b/doc/DETAILS index 3b447c79b..a3a2773fb 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -2,6 +2,107 @@ * For packet version 3 we calculate the keyids this way: RSA := low 64 bits of n - ELGAMAL := low 64 bits of y + ELGAMAL := build a v3 pubkey packet (with CTB 0x99) and calculate + a rmd160 hash value from it. This is used as the + fingerprint and the low 64 bits are the keyid. + + +Layout of the TrustDB +===================== +The TrustDB is build from fixed length records, where the first bytes +describes the record type. All numeric values are stored in network +byte order. The length of each record is 40 bytes. The first record of +the DB is always of type 1 and this is the only record of this type. + +Record type 0: +-------------- + Unused record, can be reused for any purpose. + +Record type 1: +-------------- + Version information for this TrustDB. This is always the first + record of the DB and the onyl one with type 1. + 1 byte value 1 + 3 bytes 'g10' magic value + 1 byte Version of the TrustDB + 3 byte reserved + 1 u32 locked by (pid) 0 = not locked. + 1 u32 timestamp of trustdb creation + 1 u32 timestamp of last modification + 1 u32 timestamp of last validation + (Used to keep track of the time, when this TrustDB was checked + against the pubring) + 1 u32 Local-Id-Counter. Used to keep track of Local-IDs. + 32 bits are enough numbers for all practial purposes; if this + counter rolls over (due to deleted keyblock,an d new ones), + the software should reassign new Local-Ids to the whole + database (not expected to ever occur). + 1 byte marginals needed + 1 byte completes needed + 1 byte max. cert depth + If any of this 3 values are changed, all cache records + muts be invalidated. + 9 bytes reserved + +Record type 2: +-------------- + Informations about a public key certificate. + + 1 byte value 2 + 1 byte reserved + 1 u32 Local-Id. This is used to bind all records for + a given certificate together. It is valid only in this TrustDB + and usefull if we have duplicate keyids + It is not defined, how an implementaion selects such + a Local-Id, but it may use the local-ID counter from + record type 1 + 8 bytes keyid (of the primary key) + 1 byte pubkey algorithm + 1 byte reserved + 20 bytes fingerprint of the public key + 1 byte ownertrust: + Bits 2-0: + 0 = undefined (not yet initialized) + 1 = unknown owner (could not initialize it) + 2 = do not trust this owner + 3 = usually trust this owner + 4 = always trust this owner + 5 = ultimately trust this owner. This can only be set if + we have control over the secret key too. + Bit 3: set if key is revoked; do not use it. + Bit 7-4: reserved + 3 byte reserved + + +Record type 3: (cache record) +-------------- + Used to bind the trustDB to the concrete instance of keyblock in + a pubring. This is used to cache informations. + + 1 byte value 3 + 1 byte reserved + 1 u32 Local-Id. + 8 bytes keyid of the primary key + 1 byte cache-is-valid the following stuff is only + valid if this is set. + 1 byte reserved + 20 bytes rmd160 hash value over the complete keyblock + This is used to detect any changes of the keyblock with all + CTBs and lengths headers. Calculation is easy if the keyblock + is optained from a keyserved: simply create the hash from all + received data bytes. + + 1 byte number of untrusted signatures. + 1 byte number of marginal trusted signatures. + 1 byte number of fully trusted signatures. + (255 is stored for all values greater than 254) + 1 byte Trustlevel + 0 = undefined (not calculated) + 1 = unknown + 2 = not trusted + 3 = marginally trusted + 4 = fully trusted + 5 = ultimately trusted (have secret key too). + diff --git a/g10/Makefile.am b/g10/Makefile.am index 901370ffb..b6b9ce572 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -31,6 +31,7 @@ g10_SOURCES = g10.c \ openfile.c \ keyid.c \ trustdb.c \ + trustdb.h \ packet.h \ parse-packet.c \ passphrase.c \ diff --git a/g10/Makefile.in b/g10/Makefile.in index 531b1b8e9..7e5ef73ac 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -69,6 +69,7 @@ g10_SOURCES = g10.c \ openfile.c \ keyid.c \ trustdb.c \ + trustdb.h \ packet.h \ parse-packet.c \ passphrase.c \ diff --git a/g10/build-packet.c b/g10/build-packet.c index 6c526e346..5bacf3f86 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -196,7 +196,7 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc ) * Make a hash value from the public key certificate */ void -hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc ) +hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc ) { PACKET pkt; int rc = 0; @@ -210,7 +210,7 @@ hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc ) if( (rc = build_packet( a, &pkt )) ) log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc)); while( (c=iobuf_get(a)) != -1 ) - md_putchar( md, c ); + md_putc( md, c ); iobuf_cancel(a); } @@ -66,7 +66,7 @@ g10_elg_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ) void -g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ) +g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md ) { ELG_secret_key skey; MPI frame; @@ -74,9 +74,10 @@ g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ) assert( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ); - dp = md_final( md ); + md_final( md ); + dp = md_read( md, 0 ); keyid_from_skc( skc, sig->keyid ); - sig->d.elg.digest_algo = md->algo; + sig->d.elg.digest_algo = md_get_algo(md); sig->d.elg.digest_start[0] = dp[0]; sig->d.elg.digest_start[1] = dp[1]; sig->d.elg.a = mpi_alloc( mpi_get_nlimbs(skc->d.elg.p) ); diff --git a/g10/filter.h b/g10/filter.h index 83ed3d153..bedacf9b6 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -23,9 +23,7 @@ #include "cipher.h" typedef struct { - MD_HANDLE *md; /* catch all */ - MD5HANDLE md5; /* if !NULL create md5 */ - RMDHANDLE rmd160; /* if !NULL create rmd160 */ + MD_HANDLE md; /* catch all */ size_t maxbuf_size; } md_filter_context_t; diff --git a/g10/free-packet.c b/g10/free-packet.c index dfd6f4b08..fb5949a8f 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -68,8 +68,7 @@ free_public_cert( PKT_public_cert *cert ) mpi_free( cert->d.rsa.rsa_n ); mpi_free( cert->d.rsa.rsa_e ); } - md5_close( cert->mfx.md5 ); - rmd160_close( cert->mfx.rmd160 ); + md_close( cert->mfx.md ); m_free(cert); } @@ -88,8 +87,7 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s ) d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n ); d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e ); } - d->mfx.md5 = NULL; - d->mfx.rmd160 =NULL; + d->mfx.md = NULL; return d; } @@ -34,6 +34,7 @@ #include "mpi.h" #include "cipher.h" #include "filter.h" +#include "trustdb.h" enum cmd_values { aNull = 0, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, @@ -392,6 +393,13 @@ main( int argc, char **argv ) } } + if( cmd != aPrimegen && cmd != aPrintMDs ) { + rc = check_trustdb(0); + if( rc ) + log_error("failed to initialize the TrustDB: %s\n", g10_errstr(rc)); + } + + switch( cmd ) { case aStore: /* only store the file */ if( argc > 1 ) @@ -582,9 +590,7 @@ print_mds( const char *fname ) FILE *fp; char buf[1024]; size_t n; - MD5HANDLE md5; - RMDHANDLE rmd160; - SHA1HANDLE sha1; + MD_HANDLE md; if( !fname ) { fp = stdin; @@ -597,31 +603,26 @@ print_mds( const char *fname ) return; } - md5 = md5_open(0); - rmd160 = rmd160_open(0); - sha1 = sha1_open(0); + md = md_open( DIGEST_ALGO_MD5, 0 ); + md_enable( md, DIGEST_ALGO_RMD160 ); + md_enable( md, DIGEST_ALGO_SHA1 ); - while( (n=fread( buf, 1, DIM(buf), fp )) ) { - md5_write( md5, buf, n ); - rmd160_write( rmd160, buf, n ); - sha1_write( sha1, buf, n ); - } + while( (n=fread( buf, 1, DIM(buf), fp )) ) + md_write( md, buf, n ); if( ferror(fp) ) log_error("%s: %s\n", fname, strerror(errno) ); else { byte *p; - md5_final(md5); - printf( "%s: MD5 =", fname ); print_hex(md5_read(md5), 16 ); - printf("\n%s: RMD160 =", fname ); print_hex(rmd160_final(rmd160), 20 ); - printf("\n%s: SHA1 =", fname ); print_hex(sha1_final(sha1), 20 ); + md_final(md); + printf( "%s: MD5 =", fname ); print_hex(md_read(md, DIGEST_ALGO_MD5), 16 ); + printf("\n%s: RMD160 =", fname ); print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 ); + printf("\n%s: SHA1 =", fname ); print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 ); putchar('\n'); } - md5_close(md5); - rmd160_close(rmd160); - sha1_close(sha1); + md_close(md); if( fp != stdin ) fclose(fp); diff --git a/g10/keygen.c b/g10/keygen.c index fddeedbbc..c83d8660a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <ctype.h> #include <errno.h> #include <assert.h> #include "util.h" @@ -408,7 +409,7 @@ generate_keypair() tty_printf( "\n" "You need a User-ID to identify your key; the software constructs the user id\n" "from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) <heinrichh@uni-duesseldorf.de>\"\n" ); +" \"Heinrich Heine (Der Dichter) <heinrichh@uni-duesseldorf.de>\"\n\n" ); uid = NULL; aname=acomment=amail=NULL; for(;;) { @@ -422,6 +423,8 @@ generate_keypair() tty_kill_prompt(); if( strpbrk( aname, "<([])>" ) ) tty_printf("Invalid character in name\n"); + else if( isdigit(*aname) ) + tty_printf("Name may not start with a digit\n"); else if( strlen(aname) < 5 ) tty_printf("Name must be at least 5 characters long\n"); else @@ -464,12 +467,15 @@ generate_keypair() } m_free(uid); - uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+10); + uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10); p = stpcpy(p, aname ); if( *acomment ) p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); if( *amail ) p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); + #ifndef HAVE_DEV_RANDOM + strcpy(p, " (INSECURE!)" ); + #endif tty_printf("You selected this USER-ID:\n \"%s\"\n\n", uid); for(;;) { diff --git a/g10/keyid.c b/g10/keyid.c index 43413e083..01604dfe1 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -48,14 +48,14 @@ pubkey_letter( int algo ) /* this is special code for V3 which uses ElGamal and * calculates a fingerprint like V4, but with rmd160 - * and a version byte of 3. Returns an rmd160 handle, caller must - * do rmd160_final() + * and a version byte of 3. Returns an md handle, caller must + * do md_close() */ -static RMDHANDLE +static MD_HANDLE v3_elg_fingerprint_md( PKT_public_cert *pkc ) { - RMDHANDLE md; + MD_HANDLE md; byte *buf1, *buf2, *buf3; byte *p1, *p2, *p3; unsigned n1, n2, n3; @@ -73,35 +73,36 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc ) /* calculate length of packet (1+4+2+1+2+n1+2+n2+2+n3) */ n = 14 + n1 + n2 + n3; - md = rmd160_open(0); + md = md_open( DIGEST_ALGO_RMD160, 0); - rmd160_putchar( md, 0x99 ); /* ctb */ - rmd160_putchar( md, n >> 8 ); /* 2 byte length header */ - rmd160_putchar( md, n ); - rmd160_putchar( md, 3 ); /* version */ + md_putc( md, 0x99 ); /* ctb */ + md_putc( md, n >> 8 ); /* 2 byte length header */ + md_putc( md, n ); + md_putc( md, 3 ); /* version */ { u32 a = pkc->timestamp; - rmd160_putchar( md, a >> 24 ); - rmd160_putchar( md, a >> 16 ); - rmd160_putchar( md, a >> 8 ); - rmd160_putchar( md, a ); + md_putc( md, a >> 24 ); + md_putc( md, a >> 16 ); + md_putc( md, a >> 8 ); + md_putc( md, a ); } { u16 a = pkc->valid_days; - rmd160_putchar( md, a >> 8 ); - rmd160_putchar( md, a ); + md_putc( md, a >> 8 ); + md_putc( md, a ); } - rmd160_putchar( md, pkc->pubkey_algo ); - rmd160_putchar( md, n1>>8); rmd160_putchar( md, n1 ); rmd160_write( md, p1, n1 ); - rmd160_putchar( md, n2>>8); rmd160_putchar( md, n2 ); rmd160_write( md, p2, n2 ); - rmd160_putchar( md, n3>>8); rmd160_putchar( md, n3 ); rmd160_write( md, p3, n3 ); + md_putc( md, pkc->pubkey_algo ); + md_putc( md, n1>>8); md_putc( md, n1 ); md_write( md, p1, n1 ); + md_putc( md, n2>>8); md_putc( md, n2 ); md_write( md, p2, n2 ); + md_putc( md, n3>>8); md_putc( md, n3 ); md_write( md, p3, n3 ); m_free(buf1); m_free(buf2); m_free(buf3); + md_final( md ); return md; } -static RMDHANDLE +static MD_HANDLE v3_elg_fingerprint_md_skc( PKT_secret_cert *skc ) { PKT_public_cert pkc; @@ -133,13 +134,13 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ) if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { const byte *dp; - RMDHANDLE md; + MD_HANDLE md; md = v3_elg_fingerprint_md_skc(skc); - dp = rmd160_final( md ); + dp = md_read( md, DIGEST_ALGO_RMD160 ); 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] ; lowbits = keyid[1]; - rmd160_close(md); + md_close(md); } else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { lowbits = mpi_get_keyid( skc->d.rsa.rsa_n, keyid ); @@ -166,13 +167,13 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ) if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { const byte *dp; - RMDHANDLE md; + MD_HANDLE md; md = v3_elg_fingerprint_md(pkc); - dp = rmd160_final( md ); + dp = md_read( md, DIGEST_ALGO_RMD160 ); 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] ; lowbits = keyid[1]; - rmd160_close(md); + md_close(md); } else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { lowbits = mpi_get_keyid( pkc->d.rsa.rsa_n, keyid ); @@ -310,33 +311,33 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) unsigned n; if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { - RMDHANDLE md; + MD_HANDLE md; md = v3_elg_fingerprint_md(pkc); - dp = rmd160_final( md ); + dp = md_read( md, DIGEST_ALGO_RMD160 ); array = m_alloc( 20 ); len = 20; memcpy(array, dp, 20 ); - rmd160_close(md); + md_close(md); } else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { - MD5HANDLE md; + MD_HANDLE md; - md = md5_open(0); + md = md_open( DIGEST_ALGO_MD5, 0); p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL ); for( ; !*p && n; p++, n-- ) ; - md5_write( md, p, n ); + md_write( md, p, n ); m_free(buf); p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL ); for( ; !*p && n; p++, n-- ) ; - md5_write( md, p, n ); + md_write( md, p, n ); m_free(buf); - md5_final(md); + md_final(md); array = m_alloc( 16 ); len = 16; - memcpy(array, md5_read(md), 16 ); - md5_close(md); + memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); + md_close(md); } else { array = m_alloc(1); diff --git a/g10/main.h b/g10/main.h index 747ab70a8..a10ce4ba3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -64,18 +64,18 @@ MPI encode_session_key( DEK *dek, unsigned nbits ); MPI encode_sha1_value( byte *md, unsigned len, unsigned nbits ); MPI encode_rmd160_value( byte *md, unsigned len, unsigned nbits ); MPI encode_md5_value( byte *md, unsigned len, unsigned nbits ); -MPI encode_md_value( MD_HANDLE *md, unsigned nbits ); +MPI encode_md_value( MD_HANDLE md, unsigned nbits ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); /*-- elg.c --*/ void g10_elg_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ); -void g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ); +void g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md ); /*-- rsa.c --*/ void g10_rsa_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ); -void g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ); +void g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md ); #endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index a99c975fd..f64a2cda5 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -268,7 +268,7 @@ proc_plaintext( CTX c, PACKET *pkt ) * And look at the sigclass to check wether we should use the * textmode filter (sigclass 0x01) */ - c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0); + c->mfx.md = md_open( DIGEST_ALGO_RMD160, 0); rc = handle_plaintext( pt, &c->mfx ); if( rc ) log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); @@ -302,7 +302,7 @@ static int do_check_sig( CTX c, KBNODE node ) { PKT_signature *sig; - MD_HANDLE *md; + MD_HANDLE md; int algo, rc; assert( node->pkt->pkttype == PKT_SIGNATURE ); @@ -314,7 +314,7 @@ do_check_sig( CTX c, KBNODE node ) algo = sig->d.rsa.digest_algo; else return G10ERR_PUBKEY_ALGO; - if( (rc=md_okay(algo)) ) + if( (rc=check_digest_algo(algo)) ) return rc; if( sig->sig_class == 0x00 ) { @@ -328,10 +328,6 @@ do_check_sig( CTX c, KBNODE node ) if( c->cert->pkt->pkt.public_cert->mfx.md ) md = md_copy( c->cert->pkt->pkt.public_cert->mfx.md ); - else if( algo == DIGEST_ALGO_RMD160 ) - md = rmd160_copy2md( c->cert->pkt->pkt.public_cert->mfx.rmd160 ); - else if( algo == DIGEST_ALGO_MD5 ) - md = md5_copy2md( c->cert->pkt->pkt.public_cert->mfx.md5 ); else log_bug(NULL); md_write( md, n1->pkt->pkt.user_id->name, n1->pkt->pkt.user_id->len); diff --git a/g10/mdfilter.c b/g10/mdfilter.c index 5a77c9012..17cf259eb 100644 --- a/g10/mdfilter.c +++ b/g10/mdfilter.c @@ -53,12 +53,8 @@ md_filter( void *opaque, int control, buf[i] = c; } - if( i ) { - if( mfx->md5 ) - md5_write(mfx->md5, buf, i ); - if( mfx->rmd160 ) - rmd160_write(mfx->rmd160, buf, i ); - } + if( i ) + md_write(mfx->md, buf, i ); else rc = -1; /* eof */ *ret_len = i; @@ -72,12 +68,8 @@ md_filter( void *opaque, int control, void free_md_filter_context( md_filter_context_t *mfx ) { - if( mfx->md5 ) - md5_close(mfx->md5); - mfx->md5 = NULL; - if( mfx->rmd160 ) - rmd160_close(mfx->rmd160); - mfx->rmd160 = NULL; + md_close(mfx->md); + mfx->md = NULL; mfx->maxbuf_size = 0; } diff --git a/g10/packet.h b/g10/packet.h index 03a7f328f..e82248a85 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -220,7 +220,7 @@ int parse_packet( IOBUF inp, PACKET *ret_pkt); /*-- build-packet.c --*/ int build_packet( IOBUF inp, PACKET *pkt ); u32 calc_packet_length( PACKET *pkt ); -void hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc ); +void hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc ); /*-- free-packet.c --*/ void free_pubkey_enc( PKT_pubkey_enc *enc ); @@ -235,7 +235,7 @@ PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s ); /*-- sig-check.c --*/ -int signature_check( PKT_signature *sig, MD_HANDLE *digest ); +int signature_check( PKT_signature *sig, MD_HANDLE digest ); /*-- seckey-cert.c --*/ int is_secret_key_protected( PKT_secret_cert *cert ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 70eef4007..1d056d8ea 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -438,11 +438,11 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, int is_v4=0; if( pkttype == PKT_PUBLIC_CERT ) { - pkt->pkt.public_cert->mfx.md5 = md5_open(0); - pkt->pkt.public_cert->mfx.rmd160 = rmd160_open(0); + pkt->pkt.public_cert->mfx.md = md_open(DIGEST_ALGO_MD5, 0); + md_enable(pkt->pkt.public_cert->mfx.md, DIGEST_ALGO_RMD160); + md_enable(pkt->pkt.public_cert->mfx.md, DIGEST_ALGO_SHA1); pkt->pkt.public_cert->mfx.maxbuf_size = 1; - md5_write(pkt->pkt.public_cert->mfx.md5, hdr, hdrlen); - rmd160_write(pkt->pkt.public_cert->mfx.rmd160, hdr, hdrlen); + md_write(pkt->pkt.public_cert->mfx.md, hdr, hdrlen); iobuf_push_filter( inp, md_filter, &pkt->pkt.public_cert->mfx ); } diff --git a/g10/passphrase.c b/g10/passphrase.c index df8ac7176..462c7c752 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -143,13 +143,14 @@ hash_passphrase( DEK *dek, char *pw ) dek->keylen = 0; if( dek->algo == CIPHER_ALGO_BLOWFISH ) { - RMDHANDLE rmd; + MD_HANDLE md; - rmd = rmd160_open(1); - rmd160_write( rmd, pw, strlen(pw) ); + md = md_open(DIGEST_ALGO_RMD160, 1); + md_write( md, pw, strlen(pw) ); + md_final( md ); dek->keylen = 20; - memcpy( dek->key, rmd160_final(rmd), dek->keylen ); - rmd160_close(rmd); + memcpy( dek->key, md_read(md,0), dek->keylen ); + md_close(md); } else rc = G10ERR_UNSUPPORTED; diff --git a/g10/pkclist.c b/g10/pkclist.c index 1356a06f9..f753eb6fc 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -31,6 +31,22 @@ #include "keydb.h" #include "memory.h" #include "util.h" +#include "trustdb.h" + + +/**************** + * Check wether we can trust this pkc which has a trustlevel of TRUSTLEVEL + * Returns: true if we trust. + */ +static int +do_we_trust( PKT_public_cert *pkc, int trustlevel ) +{ + /* Eventuell fragen falls der trustlevel nicht ausreichend ist */ + + + return 1; /* yes */ +} + void @@ -64,13 +80,27 @@ build_pkc_list( STRLIST remusr, PKC_LIST *ret_pkc_list ) free_public_cert( pkc ); pkc = NULL; log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) ); } - else if( is_valid_pubkey_algo(pkc->pubkey_algo) ) { - PKC_LIST r; - r = m_alloc( sizeof *r ); - r->pkc = pkc; pkc = NULL; - r->next = pkc_list; - r->mark = 0; - pkc_list = r; + else if( !(rc=check_pubkey_algo(pkc->pubkey_algo)) ) { + int trustlevel; + + rc = check_pkc_trust( pkc, &trustlevel ); + if( rc ) { + free_public_cert( pkc ); pkc = NULL; + log_error("error checking pkc of '%s': %s\n", + remusr->d, g10_errstr(rc) ); + } + else if( do_we_trust( pkc, trustlevel ) ) { + PKC_LIST r; + + r = m_alloc( sizeof *r ); + r->pkc = pkc; pkc = NULL; + r->next = pkc_list; + r->mark = 0; + pkc_list = r; + } + else { /* we don't trust this pkc */ + free_public_cert( pkc ); pkc = NULL; + } } else { free_public_cert( pkc ); pkc = NULL; diff --git a/g10/plaintext.c b/g10/plaintext.c index 114db1df0..ea43a1e6f 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -79,11 +79,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) goto leave; } if( mfx->md ) - md_putchar(mfx->md, c ); - if( mfx->rmd160 ) - rmd160_putchar(mfx->rmd160, c ); - if( mfx->md5 ) - md5_putchar(mfx->md5, c ); + md_putc(mfx->md, c ); if( putc( c, fp ) == EOF ) { log_error("Error writing to '%s': %s\n", fname, strerror(errno) ); rc = G10ERR_WRITE_FILE; @@ -93,10 +89,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) } else { while( (c = iobuf_get(pt->buf)) != -1 ) { - if( mfx->rmd160 ) - rmd160_putchar(mfx->rmd160, c ); - if( mfx->md5 ) - md5_putchar(mfx->md5, c ); + if( mfx->md ) + md_putc(mfx->md, c ); if( putc( c, fp ) == EOF ) { log_error("Error writing to '%s': %s\n", fname, strerror(errno) ); @@ -162,11 +156,7 @@ ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname ) while( (c = iobuf_get(fp)) != -1 ) { if( mfx->md ) - md_putchar(mfx->md, c ); - if( mfx->rmd160 ) - rmd160_putchar(mfx->rmd160, c ); - if( mfx->md5 ) - md5_putchar(mfx->md5, c ); + md_putc(mfx->md, c ); } iobuf_close(fp); @@ -64,7 +64,7 @@ g10_rsa_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ) void -g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ) +g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE md ) { #ifdef HAVE_RSA_CIPHER RSA_secret_key skey; @@ -72,10 +72,11 @@ g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, MD_HANDLE *md ) assert( sig->pubkey_algo == PUBKEY_ALGO_RSA ); - dp = md_final( md ); + md_final( md ); + dp = md_read( md, 0 ); keyid_from_skc( skc, sig->keyid ); - sig->d.rsa.digest_algo = md->algo; + sig->d.rsa.digest_algo = md_get_algo( md ); sig->d.rsa.digest_start[0] = dp[0]; sig->d.rsa.digest_start[1] = dp[1]; sig->d.rsa.rsa_integer = diff --git a/g10/seskey.c b/g10/seskey.c index 2698c73c7..c99bed598 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -226,16 +226,17 @@ encode_md5_value( byte *md, unsigned len, unsigned nbits ) } MPI -encode_md_value( MD_HANDLE *md, unsigned nbits ) +encode_md_value( MD_HANDLE md, unsigned nbits ) { - byte *p = md_final( md ); - if( md->algo == DIGEST_ALGO_MD5 ) - return encode_md5_value( p, 16, nbits ); - else if( md->algo == DIGEST_ALGO_RMD160 ) - return encode_rmd160_value( p, 20, nbits ); - else if( md->algo == DIGEST_ALGO_SHA1 ) - return encode_sha1_value( p, 20, nbits ); - else + switch( md_get_algo( md ) ) { + case DIGEST_ALGO_MD5: + return encode_md5_value( md_read(md, DIGEST_ALGO_MD5), 16, nbits ); + case DIGEST_ALGO_RMD160: + return encode_rmd160_value( md_read(md, DIGEST_ALGO_RMD160), 20, nbits ); + case DIGEST_ALGO_SHA1: + return encode_sha1_value( md_read(md, DIGEST_ALGO_SHA1), 20, nbits ); + default: log_bug(NULL); + } } diff --git a/g10/sig-check.c b/g10/sig-check.c index 856d57daa..74517507e 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -38,7 +38,7 @@ * is able to append some data, before getting the digest. */ int -signature_check( PKT_signature *sig, MD_HANDLE *digest ) +signature_check( PKT_signature *sig, MD_HANDLE digest ) { PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); MPI result = NULL; @@ -54,16 +54,17 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest ) if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { ELG_public_key pkey; - if( (rc=md_okay(sig->d.elg.digest_algo)) ) + if( (rc=check_digest_algo(sig->d.elg.digest_algo)) ) goto leave; /* complete the digest */ - md_putchar( digest, sig->sig_class ); + md_putc( digest, sig->sig_class ); { u32 a = sig->timestamp; - md_putchar( digest, (a >> 24) & 0xff ); - md_putchar( digest, (a >> 16) & 0xff ); - md_putchar( digest, (a >> 8) & 0xff ); - md_putchar( digest, a & 0xff ); + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); } + md_final( digest ); result = encode_md_value( digest, mpi_get_nbits(pkc->d.elg.p)); pkey.p = pkc->d.elg.p; pkey.g = pkc->d.elg.g; @@ -134,14 +135,15 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest ) } /* complete the digest */ - md_putchar( digest, sig->sig_class ); + md_putc( digest, sig->sig_class ); { u32 a = sig->timestamp; - md_putchar( digest, (a >> 24) & 0xff ); - md_putchar( digest, (a >> 16) & 0xff ); - md_putchar( digest, (a >> 8) & 0xff ); - md_putchar( digest, a & 0xff ); + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); } - dp = md_final( digest ); + md_final( digest ); + dp = md_read( digest, 0 ); for(i=19; i >= 0; i--, dp++ ) if( mpi_getbyte( result, i ) != *dp ) { rc = G10ERR_BAD_SIGN; @@ -177,14 +179,15 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest ) } /* complete the digest */ - md_putchar( digest, sig->sig_class ); + md_putc( digest, sig->sig_class ); { u32 a = sig->timestamp; - md_putchar( digest, (a >> 24) & 0xff ); - md_putchar( digest, (a >> 16) & 0xff ); - md_putchar( digest, (a >> 8) & 0xff ); - md_putchar( digest, a & 0xff ); + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); } - dp = md_final( digest ); + md_final( digest ); + dp = md_read( digest, 0 ); for(i=15; i >= 0; i--, dp++ ) if( mpi_getbyte( result, i ) != *dp ) { rc = G10ERR_BAD_SIGN; @@ -220,7 +223,7 @@ int check_key_signature( KBNODE root, KBNODE node ) { KBNODE unode; - MD_HANDLE *md; + MD_HANDLE md; PKT_public_cert *pkc; PKT_signature *sig; int algo; @@ -239,7 +242,7 @@ check_key_signature( KBNODE root, KBNODE node ) algo = sig->d.rsa.digest_algo; else return G10ERR_PUBKEY_ALGO; - if( (rc=md_okay(algo)) ) + if( (rc=check_digest_algo(algo)) ) return rc; unode = find_kbparent( root, node ); diff --git a/g10/sign.c b/g10/sign.c index d0596d669..04ae72a2f 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -41,7 +41,7 @@ static int -complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE *md ) +complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE md ) { int rc=0; @@ -119,7 +119,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, /* prepare to calculate the MD over the input */ if( opt.textmode && opt.armor ) iobuf_push_filter( inp, text_filter, &tfx ); - mfx.rmd160 = rmd160_open(0); + mfx.md = md_open(DIGEST_ALGO_RMD160, 0); iobuf_push_filter( inp, md_filter, &mfx ); if( opt.armor ) @@ -194,7 +194,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) { PKT_secret_cert *skc; PKT_signature *sig; - RMDHANDLE rmd; + MD_HANDLE md; byte *dp; skc = skc_rover->skc; @@ -205,15 +205,16 @@ sign_file( const char *filename, int detached, STRLIST locusr, sig->timestamp = make_timestamp(); sig->sig_class = opt.textmode? 0x01 : 0x00; - rmd = rmd160_copy( mfx.rmd160 ); - rmd160_putchar( rmd, sig->sig_class ); + md = md_copy( mfx.md ); + md_putc( md, sig->sig_class ); { u32 a = sig->timestamp; - rmd160_putchar( rmd, (a >> 24) & 0xff ); - rmd160_putchar( rmd, (a >> 16) & 0xff ); - rmd160_putchar( rmd, (a >> 8) & 0xff ); - rmd160_putchar( rmd, a & 0xff ); + md_putc( md, (a >> 24) & 0xff ); + md_putc( md, (a >> 16) & 0xff ); + md_putc( md, (a >> 8) & 0xff ); + md_putc( md, a & 0xff ); } - dp = rmd160_final( rmd ); + md_final( md ); + dp = md_read( md, DIGEST_ALGO_RMD160 ); if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { ELG_secret_key skey; @@ -268,7 +269,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, else log_bug(NULL); - rmd160_close( rmd ); + md_close( md ); /* and write it */ init_packet(&pkt); @@ -289,7 +290,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, else iobuf_close(out); iobuf_close(inp); - rmd160_close( mfx.rmd160 ); + md_close( mfx.md ); release_skc_list( skc_list ); release_pkc_list( pkc_list ); return rc; @@ -621,7 +622,7 @@ sign_key( const char *username, STRLIST locusr ) leave: release_kbnode( keyblock ); release_skc_list( skc_list ); - rmd160_close( mfx.rmd160 ); + md_close( mfx.md ); return rc; } @@ -830,7 +831,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, { PKT_signature *sig; int rc=0; - MD_HANDLE *md; + MD_HANDLE md; assert( sigclass >= 0x10 && sigclass <= 0x13 ); md = md_open( digest_algo, 0 ); @@ -843,12 +844,12 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, sig->timestamp = make_timestamp(); sig->sig_class = sigclass; - md_putchar( md, sig->sig_class ); + md_putc( md, sig->sig_class ); { u32 a = sig->timestamp; - md_putchar( md, (a >> 24) & 0xff ); - md_putchar( md, (a >> 16) & 0xff ); - md_putchar( md, (a >> 8) & 0xff ); - md_putchar( md, a & 0xff ); + md_putc( md, (a >> 24) & 0xff ); + md_putc( md, (a >> 16) & 0xff ); + md_putc( md, (a >> 8) & 0xff ); + md_putc( md, a & 0xff ); } rc = complete_sig( sig, skc, md ); diff --git a/g10/skclist.c b/g10/skclist.c index 75e547ffb..e7c9071d6 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -60,7 +60,7 @@ build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock ) free_secret_cert( skc ); skc = NULL; log_error("no default secret key: %s\n", g10_errstr(rc) ); } - else if( is_valid_pubkey_algo(skc->pubkey_algo) ) { + else if( !(rc=check_pubkey_algo(skc->pubkey_algo)) ) { SKC_LIST r; r = m_alloc( sizeof *r ); r->skc = skc; skc = NULL; @@ -82,7 +82,7 @@ build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock ) free_secret_cert( skc ); skc = NULL; log_error("skipped '%s': %s\n", locusr->d, g10_errstr(rc) ); } - else if ( is_valid_pubkey_algo(skc->pubkey_algo) ) { + else if( !(rc=check_pubkey_algo(skc->pubkey_algo)) ) { SKC_LIST r; r = m_alloc( sizeof *r ); r->skc = skc; skc = NULL; diff --git a/g10/trustdb.c b/g10/trustdb.c index 00774f572..46c950021 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <errno.h> #include <assert.h> @@ -30,6 +31,215 @@ #include "keydb.h" #include "memory.h" #include "util.h" +#include "trustdb.h" +#include "options.h" +#define TRUST_RECORD_LEN 40 + +struct trust_record { + byte rectype; + byte reserved; + union { + byte raw[TRUST_RECORD_LEN-2]; + struct { /* version record: */ + byte magic[2]; + byte version; /* should be 1 */ + byte reserved[3]; + u32 locked; /* pid of process which holds a lock */ + u32 created; /* timestamp of trustdb creation */ + u32 modified; /* timestamp of last modification */ + u32 validated; /* timestamp of last validation */ + u32 local_id_counter; + byte marginals_needed; + byte completes_needed; + byte max_cert_depth; + } version; + struct { /* public key record */ + u32 local_id; + u32 keyid[2]; + byte algo; + byte reserved; + byte fingerprint[20]; + byte ownertrust; + } pubkey; + struct { /* cache record */ + u32 local_id; + u32 keyid[2]; + byte valid; + byte reserved; + byte blockhash[20]; + byte n_untrusted; + byte n_marginal; + byte n_fully; + byte trustlevel; + } cache; + } r; +}; + + + +static char *db_name; + +/************************************************** + ************** read and write helpers ************ + **************************************************/ + +static void +fwrite_8(FILE *fp, byte a) +{ + if( putc( a & 0xff, fp ) == EOF ) + log_fatal("error writing byte to trustdb: %s\n", strerror(errno) ); +} + +static void +fwrite_16(FILE *fp, u16 a) +{ + putc( (a>>8) & 0x0ff , fp ); + if( putc( a & 0xff, fp ) == EOF ) + log_fatal("error writing u16 to trustdb: %s\n", strerror(errno) ); +} + +static int +fwrite_32( FILE*fp, u32 a) +{ + putc( (a>>24) & 0xff, fp ); + putc( (a>>16) & 0xff, fp ); + putc( (a>> 8) & 0xff, fp ); + if( putc( a & 0xff, fp ) == EOF ) + log_fatal("error writing u32 to trustdb: %s\n", strerror(errno) ); +} + +static int +fwrite_zeros( FILE *fp, size_t n) +{ + while( n-- ) + if( putc( 0, fp ) == EOF ) + log_fatal("error writing zeros to trustdb: %s\n", strerror(errno) ); +} + + +/************************************************** + ************** read and write stuff ************** + **************************************************/ + + +/**************** + * Create a new trustdb + */ +static void +create_db( const char *fname ) +{ + FILE *fp; + u32 along; + u16 ashort; + + fp =fopen( fname, "w" ); + if( !fp ) + log_fatal("can't create %s: %s\n", fname, strerror(errno) ); + fwrite_8( fp, 1 ); + fwrite_8( fp, 'g' ); + fwrite_8( fp, '1' ); + fwrite_8( fp, '0' ); + fwrite_8( fp, 1 ); /* version */ + fwrite_zeros( fp, 3 ); /* reserved */ + fwrite_32( fp, 0 ); /* not locked */ + fwrite_32( fp, make_timestamp() ); /* created */ + fwrite_32( fp, 0 ); /* not yet modified */ + fwrite_32( fp, 0 ); /* not yet validated*/ + fwrite_32( fp, 0 ); /* local-id-counter */ + fwrite_8( fp, 3 ); /* marginals needed */ + fwrite_8( fp, 1 ); /* completes needed */ + fwrite_8( fp, 4 ); /* max_cet_depth */ + fwrite_zeros( fp, 9 ); /* filler */ + fclose(fp); +} + + + + + + + + + + + + + +/*********************************************** + ************* trust logic ******************* + ***********************************************/ + + + + + +/********************************************************* + **************** API Interface ************************ + *********************************************************/ + +/**************** + * Perform some checks over the trustdb + * level 0: used on initial program startup + */ +int +check_trustdb( int level ) +{ + if( !level ) { + char *fname = make_filename("~/.g10", "trustDB", NULL ); + if( access( fname, R_OK ) ) { + if( errno != ENOENT ) { + log_error("can't access %s: %s\n", fname, strerror(errno) ); + m_free(fname); + return G10ERR_TRUSTDB; + } + create_db( fname ); + } + m_free(db_name); + db_name = fname; + + /* we can verify a signature about our local data (secring and trustdb) + * in ~/.g10/ here + */ + } + else + log_bug(NULL); + + return 0; +} + + +/**************** + * Get the trustlevel for this PKC. + * Note: This does not ask any questions + * Returns: 0 okay of an errorcode + * + * It operates this way: + * locate the pkc in the trustdb + * found: + * Do we have a valid cache record for it? + * yes: return trustlevel from cache + * no: make a cache record + * not found: + * Return with a trustlevel, saying that we do not have + * a trust record for it. The caller may use insert_trust_record() + * and then call this function here again. + * + * Problems: How do we get the complete keyblock to check that the + * cache record is actually valid? Think we need a clever + * cache in getkey.c to keep track of this stuff. Maybe it + * is not necessary to check this if we use a local pubring. Hmmmm. + */ +int +check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel ) +{ + int trustlevel = 0; + + if( opt.verbose ) + log_info("check_pkc_trust() called.\n"); + + *r_trustlevel = trustlevel; + return 0; +} diff --git a/g10/trustdb.h b/g10/trustdb.h new file mode 100644 index 000000000..01f126808 --- /dev/null +++ b/g10/trustdb.h @@ -0,0 +1,28 @@ +/* trustdb.h - Trust database + * 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 + */ + +#ifndef G10_TRUSTDB_H +#define G10_TRUSTDB_H + +/*-- trustdb.c --*/ +int check_trustdb( int level ); +int check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel ); + +#endif /*G10_TRUSTDB_H*/ diff --git a/include/cipher.h b/include/cipher.h index fd7886c90..1f615e54d 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -28,9 +28,7 @@ #define DBG_CIPHER cipher_debug_mode #include "mpi.h" -#include "../cipher/md5.h" -#include "../cipher/rmd.h" -#include "../cipher/sha1.h" +#include "../cipher/md.h" #ifdef HAVE_RSA_CIPHER #include "../cipher/rsa.h" #endif @@ -67,26 +65,9 @@ typedef struct { byte key[20]; /* this is the largest used keylen */ } DEK; -typedef struct { - int algo; /* digest algo */ - union { - MD5HANDLE md5; - RMDHANDLE rmd; - SHA1HANDLE sha1; - } u; - int datalen; - char data[1]; -} MD_HANDLE; - int cipher_debug_mode; -#ifdef HAVE_RSA_CIPHER - #define is_valid_pubkey_algo(a) ( (a) == PUBKEY_ALGO_ELGAMAL \ - || (a) == PUBKEY_ALGO_RSA ) -#else - #define is_valid_pubkey_algo(a) ( (a) == PUBKEY_ALGO_ELGAMAL ) -#endif /*-- misc.c --*/ int string_to_cipher_algo( const char *string ); @@ -96,19 +77,6 @@ int check_cipher_algo( int algo ); int check_pubkey_algo( int algo ); int check_digest_algo( int algo ); -/*-- md.c --*/ -int md_okay( int algo ); -MD_HANDLE *md_open( int algo, int secure ); -MD_HANDLE *md_copy( MD_HANDLE *a ); -MD_HANDLE *md_makecontainer( int algo ); /* used for a bad kludge */ -void md_write( MD_HANDLE *a, byte *inbuf, size_t inlen); -void md_putchar( MD_HANDLE *a, int c ); -byte *md_final(MD_HANDLE *a); -void md_close(MD_HANDLE *a); - -MD_HANDLE *md5_copy2md( MD5HANDLE a ); /* (in md5.c) */ -MD_HANDLE *rmd160_copy2md( RMDHANDLE a ); /* (in rmd160.c) */ - /*-- random.c --*/ void randomize_buffer( byte *buffer, size_t length, int level ); byte get_random_byte( int level ); diff --git a/include/errors.h b/include/errors.h index 9679e9153..450d910cf 100644 --- a/include/errors.h +++ b/include/errors.h @@ -52,5 +52,6 @@ #define G10ERR_BAD_MPI 30 #define G10ERR_RESOURCE_LIMIT 31 #define G10ERR_INV_KEYRING 32 +#define G10ERR_TRUSTDB 33 /* a problem with the trustdb */ #endif /*G10_ERRORS_H*/ diff --git a/include/mpi.h b/include/mpi.h index 4e25ab201..7c4639f18 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -39,27 +39,11 @@ #define DBG_MPI mpi_debug_mode int mpi_debug_mode; -#if defined(__i386__) - #define BITS_PER_MPI_LIMB 32 - #define BYTES_PER_MPI_LIMB 4 - #define BYTES_PER_MPI_LIMB2 8 - typedef unsigned long int mpi_limb_t; - typedef signed long int mpi_limb_signed_t; -#elif defined(__hppa__) - #define BITS_PER_MPI_LIMB 32 - #define BYTES_PER_MPI_LIMB 4 - #define BYTES_PER_MPI_LIMB2 8 - typedef unsigned long int mpi_limb_t; - typedef signed long int mpi_limb_signed_t; -#elif defined(__alpha__) - #define BITS_PER_MPI_LIMB 64 - #define BYTES_PER_MPI_LIMB 8 - #define BYTES_PER_MPI_LIMB2 16 - typedef unsigned long int mpi_limb_t; - typedef signed long int mpi_limb_signed_t; -#else - #error add definions for this machine here -#endif +#define BITS_PER_MPI_LIMB (8*SIZEOF_UNSIGNED_LONG) +#define BYTES_PER_MPI_LIMB SIZEOF_UNSIGNED_LONG +#define BYTES_PER_MPI_LIMB2 (2*SIZEOF_UNSIGNED_LONG) +typedef unsigned long int mpi_limb_t; +typedef signed long int mpi_limb_signed_t; typedef struct mpi_struct { int alloced; /* array size (# of allocated limbs) */ diff --git a/mpi/config.links b/mpi/config.links index 9ee1d0568..fd580e51e 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -48,6 +48,24 @@ case "${target}" in path="pa7100 hppa1_1 hppa" mpi_extra_modules="udiv-qrnnd" ;; + sparc9*-*-* | sparc64*-*-* | ultrasparc*-*-*) + echo '/* configured for sparc9 or higher */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + sparc8*-*-* | microsparc*-*-*) + echo '/* configured for sparc8 */' >>./mpi/asm-syntax.h + path="sparc32v8" + ;; + supersparc*-*-*) + echo '/* configured for supersparc */' >>./mpi/asm-syntax.h + path="supersparc sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc*-*-*) + echo '/* configured for sparc */' >>./mpi/asm-syntax.h + path="sparc32" + mpi_extra_modules="udiv" + ;; *) echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h path="" diff --git a/mpi/sparc32/distfiles b/mpi/sparc32/distfiles new file mode 100644 index 000000000..7933edc8f --- /dev/null +++ b/mpi/sparc32/distfiles @@ -0,0 +1,4 @@ + +mpih-add1.S +udiv.S + diff --git a/mpi/sparc32/mpih-add1.S b/mpi/sparc32/mpih-add1.S new file mode 100644 index 000000000..04315d106 --- /dev/null +++ b/mpi/sparc32/mpih-add1.S @@ -0,0 +1,237 @@ +! SPARC __mpn_add_n -- Add two limb vectors of the same length > 0 and store +! sum in a third limb vector. + +! Copyright (C) 1995, 1996 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, + * mpi_ptr_t s1_ptr, + * mpi_ptr_t s2_ptr, + * mpi_size_t size) + */ + +! INPUT PARAMETERS +#define res_ptr %o0 +#define s1_ptr %o1 +#define s2_ptr %o2 +#define size %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n): + xor s2_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L1 ! branch if alignment differs + nop +! ** V1a ** +L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0 + be L_v1 ! if no, branch + nop +/* Add least significant limb separately to align res_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr +L_v1: addx %g0,%g0,%o4 ! save cy in register + cmp size,2 ! if size < 2 ... + bl Lend2 ! ... branch to tail code + subcc %g0,%o4,%g0 ! restore cy + + ld [s1_ptr+0],%g4 + addcc size,-10,size + ld [s1_ptr+4],%g1 + ldd [s2_ptr+0],%g2 + blt Lfin1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addxcc %g4,%g2,%o4 + ld [s1_ptr+16],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+20],%g1 + ldd [s2_ptr+16],%g2 + std %o4,[res_ptr+8] + addxcc %g4,%g2,%o4 + ld [s1_ptr+24],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+28],%g1 + ldd [s2_ptr+24],%g2 + std %o4,[res_ptr+16] + addxcc %g4,%g2,%o4 + ld [s1_ptr+32],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+36],%g1 + ldd [s2_ptr+32],%g2 + std %o4,[res_ptr+24] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop1 + subcc %g0,%o4,%g0 ! restore cy + +Lfin1: addcc size,8-2,size + blt Lend1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 2 limbs until less than 2 limbs remain */ +Loope1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope1 + subcc %g0,%o4,%g0 ! restore cy +Lend1: addxcc %g4,%g2,%o4 + addxcc %g1,%g3,%o5 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + + andcc size,1,%g0 + be Lret1 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ + ld [s1_ptr+8],%g4 + ld [s2_ptr+8],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr+8] + +Lret1: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + +L1: xor s1_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L2 + nop +! ** V1b ** + mov s2_ptr,%g1 + mov s1_ptr,s2_ptr + b L0 + mov %g1,s1_ptr + +! ** V2 ** +/* If we come here, the alignment of s1_ptr and res_ptr as well as the + alignment of s2_ptr and res_ptr differ. Since there are only two ways + things can be aligned (that we care about) we now know that the alignment + of s1_ptr and s2_ptr are the same. */ + +L2: cmp size,1 + be Ljone + nop + andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0 + be L_v2 ! if no, branch + nop +/* Add least significant limb separately to align s1_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr + +L_v2: addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + blt Lfin2 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + ldd [s1_ptr+8],%g2 + ldd [s2_ptr+8],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+8] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+12] + ldd [s1_ptr+16],%g2 + ldd [s2_ptr+16],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+16] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+20] + ldd [s1_ptr+24],%g2 + ldd [s2_ptr+24],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+24] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+28] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop2 + subcc %g0,%o4,%g0 ! restore cy + +Lfin2: addcc size,8-2,size + blt Lend2 + subcc %g0,%o4,%g0 ! restore cy +Loope2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope2 + subcc %g0,%o4,%g0 ! restore cy +Lend2: andcc size,1,%g0 + be Lret2 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ +Ljone: ld [s1_ptr],%g4 + ld [s2_ptr],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr] + +Lret2: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + + + diff --git a/mpi/sparc32/udiv.S b/mpi/sparc32/udiv.S new file mode 100644 index 000000000..3e2376cfc --- /dev/null +++ b/mpi/sparc32/udiv.S @@ -0,0 +1,188 @@ +! SPARC v7 __udiv_qrnnd division support, used from longlong.h. +! This is for v7 CPUs without a floating-point unit. + +! Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +! INPUT PARAMETERS +! rem_ptr o0 +! n1 o1 +! n0 o2 +! d o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + tst %o3 + bneg Largedivisor + mov 8,%g1 + + b Lp1 + addxcc %o2,%o2,%o2 + +Lplop: bcc Ln1 + addxcc %o2,%o2,%o2 +Lp1: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln2 + addxcc %o2,%o2,%o2 +Lp2: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln3 + addxcc %o2,%o2,%o2 +Lp3: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln4 + addxcc %o2,%o2,%o2 +Lp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne Lplop + subcc %o1,%o3,%o4 + bcc Ln5 + addxcc %o2,%o2,%o2 +Lp5: st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +Lnlop: bcc Lp1 + addxcc %o2,%o2,%o2 +Ln1: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp2 + addxcc %o2,%o2,%o2 +Ln2: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp3 + addxcc %o2,%o2,%o2 +Ln3: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp4 + addxcc %o2,%o2,%o2 +Ln4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne Lnlop + subcc %o4,%o3,%o1 + bcc Lp5 + addxcc %o2,%o2,%o2 +Ln5: st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Largedivisor: + and %o2,1,%o5 ! %o5 = n0 & 1 + + srl %o2,1,%o2 + sll %o1,31,%g2 + or %g2,%o2,%o2 ! %o2 = lo(n1n0 >> 1) + srl %o1,1,%o1 ! %o1 = hi(n1n0 >> 1) + + and %o3,1,%g2 + srl %o3,1,%g3 ! %g3 = floor(d / 2) + add %g3,%g2,%g3 ! %g3 = ceil(d / 2) + + b LLp1 + addxcc %o2,%o2,%o2 + +LLplop: bcc LLn1 + addxcc %o2,%o2,%o2 +LLp1: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn2 + addxcc %o2,%o2,%o2 +LLp2: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn3 + addxcc %o2,%o2,%o2 +LLp3: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn4 + addxcc %o2,%o2,%o2 +LLp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne LLplop + subcc %o1,%g3,%o4 + bcc LLn5 + addxcc %o2,%o2,%o2 +LLp5: add %o1,%o1,%o1 ! << 1 + tst %g2 + bne Oddp + add %o5,%o1,%o1 + st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +LLnlop: bcc LLp1 + addxcc %o2,%o2,%o2 +LLn1: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp2 + addxcc %o2,%o2,%o2 +LLn2: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp3 + addxcc %o2,%o2,%o2 +LLn3: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp4 + addxcc %o2,%o2,%o2 +LLn4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne LLnlop + subcc %o4,%g3,%o1 + bcc LLp5 + addxcc %o2,%o2,%o2 +LLn5: add %o4,%o4,%o4 ! << 1 + tst %g2 + bne Oddn + add %o5,%o4,%o4 + st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Oddp: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o1 + addcc %o1,%o2,%o1 + bcc LLp6 + addx %o2,0,%o2 + sub %o1,%o3,%o1 +LLp6: subcc %o1,%o3,%g0 + bcs LLp7 + subx %o2,-1,%o2 + sub %o1,%o3,%o1 +LLp7: st %o1,[%o0] + retl + mov %o2,%o0 + +Oddn: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o4 + addcc %o4,%o2,%o4 + bcc LLn6 + addx %o2,0,%o2 + sub %o4,%o3,%o4 +LLn6: subcc %o4,%o3,%g0 + bcs LLn7 + subx %o2,-1,%o2 + sub %o4,%o3,%o4 +LLn7: st %o4,[%o0] + retl + mov %o2,%o0 diff --git a/mpi/sparc32v8/distfiles b/mpi/sparc32v8/distfiles new file mode 100644 index 000000000..5789f35b3 --- /dev/null +++ b/mpi/sparc32v8/distfiles @@ -0,0 +1,5 @@ + +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S + diff --git a/mpi/sparc32v8/mpih-mul1.S b/mpi/sparc32v8/mpih-mul1.S new file mode 100644 index 000000000..8bc1db57a --- /dev/null +++ b/mpi/sparc32v8/mpih-mul1.S @@ -0,0 +1,101 @@ +! SPARC v8 __mpn_mul_1 -- Multiply a limb vector with a single limb and +! store the product in a second limb vector. + +! Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 8 + .global C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1): + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + ld [%o1+0],%o4 ! 1 +LL: +LL00: add %o0,-4,%o0 + add %o1,-4,%o1 + b Loop00 /* 4, 8, 12, ... */ + orcc %g0,%g0,%g2 +LL01: b Loop01 /* 1, 5, 9, ... */ + orcc %g0,%g0,%g2 + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + add %o1,4,%o1 + b Loop10 + orcc %g0,%g0,%g2 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + add %o1,-8,%o1 + b Loop11 + orcc %g0,%g0,%g2 + +Loop: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + st %g3,[%o0+0] ! 1 + rd %y,%g2 ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + st %g3,[%o0+4] ! 2 + rd %y,%g2 ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + add %o1,16,%o1 + st %g3,[%o0+8] ! 3 + rd %y,%g2 ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg Loop + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + st %g3,[%o0+0] ! 4 + rd %y,%g2 ! 4 + + retl + addx %g0,%g2,%o0 + + diff --git a/mpi/sparc32v8/mpih-mul2.S b/mpi/sparc32v8/mpih-mul2.S new file mode 100644 index 000000000..9055f89e8 --- /dev/null +++ b/mpi/sparc32v8/mpih-mul2.S @@ -0,0 +1,124 @@ +! SPARC v8 __mpn_addmul_1 -- Multiply a limb vector with a limb and +! add the result to a second limb vector. + +! Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1): + orcc %g0,%g0,%g2 + ld [%o1+0],%o4 ! 1 + + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + nop +LL: +LL00: add %o0,-4,%o0 + b Loop00 /* 4, 8, 12, ... */ + add %o1,-4,%o1 + nop +LL01: b Loop01 /* 1, 5, 9, ... */ + nop + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + b Loop10 + add %o1,4,%o1 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + b Loop11 + add %o1,-8,%o1 + nop + +1: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + rd %y,%g2 ! 1 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + ld [%o0+4],%g1 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + rd %y,%g2 ! 2 + addx %g0,%g2,%g2 + nop + addcc %g1,%g3,%g3 + st %g3,[%o0+4] ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + rd %y,%g2 ! 3 + add %o1,16,%o1 + addx %g0,%g2,%g2 + ld [%o0+8],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+8] ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+12],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg 1b + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 4 + addx %g0,%g2,%o0 + + retl + nop + + +! umul, ld, addxcc, rd, st + +! umul, ld, addxcc, rd, ld, addcc, st, addx + diff --git a/mpi/sparc32v8/mpih-mul3.S b/mpi/sparc32v8/mpih-mul3.S new file mode 100644 index 000000000..efd83de41 --- /dev/null +++ b/mpi/sparc32v8/mpih-mul3.S @@ -0,0 +1,60 @@ +! SPARC v8 __mpn_submul_1 -- Multiply a limb vector with a limb and +! subtract the result from a second limb vector. + +! Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1): + sub %g0,%o2,%o2 ! negate ... + sll %o2,2,%o2 ! ... and scale size + sub %o1,%o2,%o1 ! o1 is offset s1_ptr + sub %o0,%o2,%g1 ! g1 is offset res_ptr + + mov 0,%o0 ! clear cy_limb + +Loop: ld [%o1+%o2],%o4 + ld [%g1+%o2],%g2 + umul %o4,%o3,%o5 + rd %y,%g3 + addcc %o5,%o0,%o5 + addx %g3,0,%o0 + subcc %g2,%o5,%g2 + addx %o0,0,%o0 + st %g2,[%g1+%o2] + + addcc %o2,4,%o2 + bne Loop + nop + + retl + nop + + diff --git a/mpi/supersparc/distfiles b/mpi/supersparc/distfiles new file mode 100644 index 000000000..5506c419b --- /dev/null +++ b/mpi/supersparc/distfiles @@ -0,0 +1,3 @@ + +udiv.S + diff --git a/mpi/supersparc/udiv.S b/mpi/supersparc/udiv.S new file mode 100644 index 000000000..07d904c70 --- /dev/null +++ b/mpi/supersparc/udiv.S @@ -0,0 +1,110 @@ +! SuperSPARC __udiv_qrnnd division support, used from longlong.h. +! This is for SuperSPARC only, to compensate for its semi-functional +! udiv instruction. + +! Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +! This file is part of the GNU MP Library. + +! The GNU MP Library is free software; you can redistribute it and/or modify +! it under the terms of the GNU Library General Public License as published by +! the Free Software Foundation; either version 2 of the License, or (at your +! option) any later version. + +! The GNU MP Library 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 Library General Public +! License for more details. + +! You should have received a copy of the GNU Library General Public License +! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +! MA 02111-1307, USA. + + +! INPUT PARAMETERS +! rem_ptr i0 +! n1 i1 +! n0 i2 +! d i3 + +#include "sysdep.h" +#undef ret /* Kludge for glibc */ + + .text + .align 8 +LC0: .double 0r4294967296 +LC1: .double 0r2147483648 + + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + !#PROLOGUE# 0 + save %sp,-104,%sp + !#PROLOGUE# 1 + st %i1,[%fp-8] + ld [%fp-8],%f10 + sethi %hi(LC0),%o7 + fitod %f10,%f4 + ldd [%o7+%lo(LC0)],%f8 + cmp %i1,0 + bge L248 + mov %i0,%i5 + faddd %f4,%f8,%f4 +L248: + st %i2,[%fp-8] + ld [%fp-8],%f10 + fmuld %f4,%f8,%f6 + cmp %i2,0 + bge L249 + fitod %f10,%f2 + faddd %f2,%f8,%f2 +L249: + st %i3,[%fp-8] + faddd %f6,%f2,%f2 + ld [%fp-8],%f10 + cmp %i3,0 + bge L250 + fitod %f10,%f4 + faddd %f4,%f8,%f4 +L250: + fdivd %f2,%f4,%f2 + sethi %hi(LC1),%o7 + ldd [%o7+%lo(LC1)],%f4 + fcmped %f2,%f4 + nop + fbge,a L251 + fsubd %f2,%f4,%f2 + fdtoi %f2,%f2 + st %f2,[%fp-8] + b L252 + ld [%fp-8],%i4 +L251: + fdtoi %f2,%f2 + st %f2,[%fp-8] + ld [%fp-8],%i4 + sethi %hi(-2147483648),%g2 + xor %i4,%g2,%i4 +L252: + umul %i3,%i4,%g3 + rd %y,%i0 + subcc %i2,%g3,%o7 + subxcc %i1,%i0,%g0 + be L253 + cmp %o7,%i3 + + add %i4,-1,%i0 + add %o7,%i3,%o7 + st %o7,[%i5] + ret + restore +L253: + blu L246 + mov %i4,%i0 + add %i4,1,%i0 + sub %o7,%i3,%o7 +L246: + st %o7,[%i5] + ret + restore + |