diff -Nru a/arch/i386/config.in b/arch/i386/config.in --- a/arch/i386/config.in Mon Feb 2 14:26:23 2004 +++ b/arch/i386/config.in Mon Feb 2 14:26:23 2004 @@ -483,6 +483,8 @@ int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0 +source security/Config.in + endmenu source crypto/Config.in diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Mon Feb 2 14:26:23 2004 +++ b/fs/binfmt_elf.c Mon Feb 2 14:26:23 2004 @@ -41,6 +41,7 @@ #define DLINFO_ITEMS 13 #include +#include static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); static int load_elf_library(struct file*); @@ -706,6 +707,37 @@ if (k > elf_brk) elf_brk = k; } + +#if defined(CONFIG_CRYPTOMARK) + /* Shell scripts get checked in binfmt_script.c */ + if (!bprm->sh_bang && (cryptomark_ops)) { + struct immunix_digital_sig * sig; + int error ; + + sig = cryptomark_ops->compute_elf_sig (elf_phdata, elf_ex.e_phnum, bprm->filename); + + error = cryptomark_ops->compare_elf_sig (bprm->dentry, &elf_ex, sig, bprm->filename); + + cryptomark_dbg ("compare_elf_sig for %s returned %d", bprm->filename, error); + + if (!error) { + cryptomark_dbg ("%s: Digests are the same", bprm->filename); + } else { + if (error > 0) { + cryptomark_dbg ("Signature is not valid for %s", bprm->filename); + /* Kill the sucker */ + fput(file); + dput(interpreter_dentry); + kfree(elf_interpreter); + kfree(elf_phdata); + send_sig(SIGKILL, current, 0); + return -EACCES; + } else /* error < 0 */ { + cryptomark_dbg ("No signature found in %s", bprm->filename); + } + } + } /* if */ +#endif /* CONFIG_CRYPTOMARK */ elf_entry += load_bias; elf_bss += load_bias; diff -Nru a/fs/immunix_scaffold.c b/fs/immunix_scaffold.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/immunix_scaffold.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,111 @@ +/*======================================================================*/ +/* */ +/* Kernel Programming Interface for Immunix CoDomain and CryptoMark */ +/* Copyright 1998, 1999, 2000 Wirex Communications */ +/* */ +/* Written by Steve Beattie */ +/* modified by Greg Kroah-Hartman */ +/* */ +/* linux/fs/immunix_scaffold.c: */ +/* */ +/*======================================================================*/ + +#include +#include +#include +#include +#include + +#include +#include + +#undef DEBUG_CODOMAIN + +#ifdef DEBUG_CODOMAIN + #define PDEBUG(fmt, args...) printk(KERN_DEBUG "Immunix: " fmt "\n" , ## args) +#else + #define PDEBUG(fmt, args...) do {} while (0) +#endif + +#define PWARN(fmt, args...) printk(KERN_WARNING "Immunix: " fmt "\n", ## args) + + +/*====================================================================== + * Global variables and kernel symbols to be exported + *======================================================================*/ + +/* the ops structures are global as it would be a mess of #ifdefs to keep them both seperate */ +struct cryptomark_operations * cryptomark_ops; + +EXPORT_SYMBOL(register_cryptomark); +EXPORT_SYMBOL(unregister_cryptomark); + + + +/*======================================================================*/ +/* */ +/* immunix_scaffolding_startup: */ +/* Initialization routines for the scaffold. */ +/* This is called from filesystems.c */ +/*======================================================================*/ + +void immunix_scaffolding_startup (void) +{ + printk ( KERN_INFO "WireX/Immunix Scaffold v " IMMUNIX_SCAFFOLD_VERSION " initialized\n") ; + +#ifdef CONFIG_CRYPTOMARK + printk ( KERN_INFO "CryptoMark scaffold enabled.\n"); +#endif + + PDEBUG ( __FUNCTION__ " called" ) ; + cryptomark_ops = NULL; +} + + +/*======================================================================*/ +/* */ +/* register_cryptomark: */ +/* Performs the work of registering the cryptomark module with the */ +/* kernel. Modeled after the other register_xxx() routines. */ +/* */ +/*======================================================================*/ +int register_cryptomark (struct cryptomark_operations *ops) +{ + PDEBUG (__FUNCTION__" called"); + + /* verify the version of the structure matches what we think it should be */ + if (ops->version != CRYPTOMARK_INTERFACE_VERSION) { + PDEBUG ("Mismatched version of cryptomark_operation structure used, "__FUNCTION__" failed"); + return -EINVAL; + } + + /* Perform a little sanity checking on our inputs */ + if ( !ops || + !ops->compare_elf_sig || + !ops->compute_elf_sig ) { + PDEBUG ("Not enough functions specified in the cryptomark_operations structure, "__FUNCTION__" failed"); + return -EINVAL ; + } + + cryptomark_ops = ops; + + return 0; +} + +/*======================================================================*/ +/* */ +/* unregister_cryptomark: */ +/* This routine performs the kernel cleanup when the cryptomark */ +/* module is removed. Note that modules have their own seperate */ +/* cleanup routines that are called directly by the module */ +/* mechanism, so we don't need to call it here. */ +/* */ +/*======================================================================*/ +int unregister_cryptomark (struct cryptomark_operations *ops) +{ + PDEBUG (__FUNCTION__ " called"); + + cryptomark_ops = NULL; + + return 0; +} diff -Nru a/include/linux/immunix.h b/include/linux/immunix.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/immunix.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,76 @@ +/*======================================================================*/ +/* */ +/* Immunix CoDomain / CryptoMark Toolkit: */ +/* Copyright 2000 Wirex Communications, Inc. */ +/* */ +/* Written by Steve Beattie */ +/* and Greg Kroah-Hartman */ +/* */ +/* linux/include/linux/immunix.h: */ +/* */ +/*======================================================================*/ + +#ifndef _IMMUNIX_H +#define _IMMUNIX_H + +#define IMMUNIX_SCAFFOLD_VERSION "0.2.6" + + +/*====================================================================== + * + * Immunix MD5 digital signature things + * + *======================================================================*/ +#define IMMUNIX_DIGI_SIG_SIZE 16 /* Number of (unsigned) bytes in a digital signature - md5 is 16 bytes */ + +struct immunix_digital_sig { + unsigned char md5[IMMUNIX_DIGI_SIG_SIZE]; +}; + + +#include +#include + +/*====================================================================== + * + * Immunix MD5 digital signature module prototypes + * + *======================================================================*/ +extern struct immunix_digital_sig * immunix_compute_elf_sig (struct elf_phdr *elf_phdata, int elf_e_phnum, char *name); +extern struct immunix_digital_sig * immunix_compute_script_sig (struct dentry *script_dentry , char *name); + + +/********************************************* + * CryptoMark stuff + *********************************************/ + +#define CRYPTOMARK_INTERFACE_VERSION 0x00000302 /* change this every time the cryptomark_operations structure changes */ + +struct cryptomark_operations { + int version; + int (* compare_elf_sig) (struct dentry *elf_inode, struct elfhdr *elf_ex, struct immunix_digital_sig *sig, char * name); + struct immunix_digital_sig * (* compute_elf_sig) (struct elf_phdr *elf_phdata , int elf_e_phnum , char *name); +}; + + +#ifdef CONFIG_CRYPTOMARK_DEBUG + #define cryptomark_dbg(fmt, args...) printk(KERN_DEBUG "CryptoMark: " fmt "\n" , ## args) +#else + #define cryptomark_dbg(fmt, args...) do {} while (0) +#endif + + +/*====================================================================== + * prototypes + *======================================================================*/ + +extern int register_cryptomark (struct cryptomark_operations *ops); +extern int unregister_cryptomark (struct cryptomark_operations *ops); + +extern struct cryptomark_operations *cryptomark_ops; + + +#endif /* ! _IMMUNIX_H */ + +/*======================================================================*/ + diff -Nru a/security/Config.in b/security/Config.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/Config.in Mon Feb 2 14:26:23 2004 @@ -0,0 +1,6 @@ +mainmenu_option next_comment +comment 'Security options' + +tristate 'WireX CryptoMark support' CONFIG_CRYPTOMARK + +endmenu diff -Nru a/security/Makefile b/security/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,11 @@ + +O_TARGET := security.o + +mod-subdirs := md5 cryptomark + +subdir-$(CONFIG_CRYPTOMARK) += md5 +subdir-$(CONFIG_CRYPTOMARK) += cryptomark + +include $(TOPDIR)/Rules.make + + diff -Nru a/security/cryptomark/Makefile b/security/cryptomark/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,68 @@ +O_TARGET := cryptomark.o + +list-multi := cryptomark.o + + +obj-$(CONFIG_CRYPTOMARK) += cryptomark.o + + +cryptomark-objs := gnupg/cipher/construct.o \ + gnupg/cipher/dynload.o \ + gnupg/cipher/elgamal.o \ + gnupg/cipher/md.o \ + gnupg/cipher/md5.o \ + gnupg/cipher/pubkey.o \ + gnupg/cipher/rmd160.o \ + gnupg/cipher/sha1.o \ + gnupg/mpi/mpi-add.o \ + gnupg/mpi/mpi-bit.o \ + gnupg/mpi/mpi-cmp.o \ + gnupg/mpi/mpi-div.o \ + gnupg/mpi/mpi-mul.o \ + gnupg/mpi/mpih-add1.o \ + gnupg/mpi/mpih-cmp.o \ + gnupg/mpi/mpih-div.o \ + gnupg/mpi/mpih-lshift.o \ + gnupg/mpi/mpih-mul.o \ + gnupg/mpi/mpih-mul1.o \ + gnupg/mpi/mpih-mul2.o \ + gnupg/mpi/mpih-mul3.o \ + gnupg/mpi/mpih-rshift.o \ + gnupg/mpi/mpih-sub1.o \ + gnupg/mpi/mpiutil.o \ + gnupg/mpi/mpi-inv.o \ + gnupg/mpi/mpi-pow.o \ + gnupg/mpi/mpi-mpow.o \ + gnupg/mpi/mpicoder.o \ + gnupg/armor.o \ + gnupg/iobuf.o \ + gnupg/plaintext.o \ + gnupg/memory.o \ + gnupg/parse-packet.o \ + gnupg/misc.o \ + gnupg/free-packet.o \ + gnupg/mdfilter.o \ + gnupg/fileutil.o \ + gnupg/kbnode.o \ + gnupg/strgutil.o \ + gnupg/getkey.o \ + gnupg/keyid.o \ + gnupg/status.o \ + gnupg/ringedit.o \ + gnupg/sig-check.o \ + gnupg/pkclist.o \ + gnupg/seskey.o \ + gnupg/build-packet.o \ + gnupg/mainproc.o \ + main.o \ + calc_sig.o \ + proc.o \ + verify.o + + + +include $(TOPDIR)/Rules.make + +cryptomark.o: $(cryptomark-objs) + $(LD) -r -o $@ $(cryptomark-objs) + diff -Nru a/security/cryptomark/calc_sig.c b/security/cryptomark/calc_sig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/calc_sig.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,44 @@ +/*====================================================================== +* +* Immunix CryptoMark module +* Copyright 1998, 1999, 2000 Wirex Communications & +* Oregon Graduate Institute +* +* Greg Kroah-Hartman +* +*======================================================================*/ + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ + #include +#endif + + + +/* __NO_VERSION__ is needed or else symbols get defined multiply */ +//#define __NO_VERSION__ +//#include +//#include + +#include +#include + +#include "cryptomark.h" +#include "cryptomark_log.h" + +/*====================================================================== +* +* crypto_compute_elf_sig: +* Calls the immunix-md5 module to get a digital signature for +* elf executables. +* +*======================================================================*/ +struct immunix_digital_sig * crypto_compute_elf_sig (struct elf_phdr *elf_phdata, int elf_e_phnum, char * name) +{ + dbg (__FUNCTION__ ": name = %s", name); + return immunix_compute_elf_sig (elf_phdata, elf_e_phnum, name); +} + + diff -Nru a/security/cryptomark/cryptomark.h b/security/cryptomark/cryptomark.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/cryptomark.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,57 @@ + +#ifndef __CRYPTOMARK_H +#define __CRYPTOMARK_H + +#ifdef __KERNEL__ + +#define CRYPTOMARK_TITLE "WireX CryptoMark module" +#define CRYPTOMARK_COPYRIGHT "Copyright 1998, 1999, 2000 WireX Communications Inc." + +extern const char *cryptomark_title; +extern const char *cryptomark_copyright; + +#define DIGI_SIG_SIZE 16 /* Number of (unsigned) bytes in a + * digital signature - md5 is 16 bytes */ +#define CRYPTOMARK_NAME "CM_MD5Sig" /* elf section for the signage */ + +/*====================================================================== + * + * prototypes + * + *======================================================================*/ + +extern struct immunix_digital_sig * crypto_compute_elf_sig (struct elf_phdr *elf_phdata, int elf_e_phnum, char *name); +extern int crypto_compare_elf_sig (struct dentry *elf_inode, struct elfhdr *elf_ex, struct immunix_digital_sig *sig, char * name); + + +extern int crypto_verify_data (unsigned char * inp, unsigned long size, unsigned char **data); + + +extern void proc_init (void); +extern void proc_done (void); + +/*====================================================================== + * + * Other macros that are useful for us + * + *======================================================================*/ + +#endif /* __KERNEL__ */ + +#ifndef TRUE + #define TRUE (1) +#endif +#ifndef FALSE + #define FALSE (0) +#endif + +#ifdef MAX + #define MAX(a,b) (((a)>(b))?(a):(b)) +#endif +#ifndef MIN + #define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +/*======================================================================*/ + +#endif /* __CRYPTOMARK_H */ diff -Nru a/security/cryptomark/cryptomark_log.h b/security/cryptomark/cryptomark_log.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/cryptomark_log.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,64 @@ + +#ifndef __CRYPTOMARK_LOG_H +#define __CRYPTOMARK_LOG_H + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ + #include +#endif + +#undef TRACE_CRYPTOMARK +//#define TRACE_CRYPTOMARK + +#ifdef __KERNEL__ + +#include +#include + +/*====================================================================== + * + * Debugging macros + * + *======================================================================*/ +#ifdef CONFIG_CRYPTOMARK_DEBUG + #define dbg(fmt, args...) printk(KERN_DEBUG "CryptoMark: " fmt "\n" , ## args) +#else + #define dbg(fmt, args...) do {} while (0) +#endif + +#ifdef TRACE_CRYPTOMARK + #define trace() printk(KERN_DEBUG "CryptoMark: "__FUNCTION__"\n") +#else + #define trace() do {} while (0) +#endif + + +#define err(format, arg...) printk(KERN_ERR "CryptoMark: " format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO "CryptoMark: " format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "CryptoMark: " format "\n" , ## arg) + + +#ifdef CONFIG_CRYPTOMARK_DEBUG + #define g10_log_debug(format, args...) printk(KERN_DEBUG "CryptoMark g10: " format "\n", ## args) + #define g10_log_info(format, arg...) printk(KERN_INFO "CryptoMark gnupg: " format "\n", ## arg) + #define g10_log_error(format, arg...) printk(KERN_ERR "CryptoMark gnupg: " format "\n", ## arg) + #define g10_log_fatal(format, arg...) printk(KERN_ERR "CryptoMark gnupg: " format "\n", ## arg) + #define g10_log_warn(format, arg...) printk(KERN_WARNING "CryptoMark gnupg: " format "\n", ## arg) + #define g10_log_bug0(format, arg...) printk(KERN_ERR "CryptoMark gnupg Bug: " format "\n", ## arg) + #define g10_log_bug(format, arg...) printk(KERN_ERR "CryptoMark gnupg Bug: " format "\n", ## arg) +#else + #define g10_log_debug(format, args...) do {} while (0) + #define g10_log_info(format, arg...) do {} while (0) + #define g10_log_error(format, arg...) do {} while (0) + #define g10_log_fatal(format, arg...) do {} while (0) + #define g10_log_warn(format, arg...) do {} while (0) + #define g10_log_bug0(format, arg...) do {} while (0) + #define g10_log_bug(format, arg...) do {} while (0) +#endif + + +#endif /* __KERNEL__ */ + +#endif /* __CRYPTOMARK_LOG_H */ diff -Nru a/security/cryptomark/cryptomark_version.h b/security/cryptomark/cryptomark_version.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/cryptomark_version.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1 @@ +#define CRYPTOMARK_VERSION "1.0-pre3" diff -Nru a/security/cryptomark/gnupg/Makefile b/security/cryptomark/gnupg/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,152 @@ +# ====================================================================== +# +# Immunix CryptoMark Module +# Copyright 1998, 1999, 2000 Wirex Communications & +# Oregon Graduate Institute +# +# Written by Steve Beattie and +# Greg Kroah-Hartman +# +# ====================================================================== + +# stuff to make a release tarball +VERSION = 0.1 +NAME = cryptomark +MISC_FILES = Makefile BUGS NOTES CHANGELOG README + +# +# Determine if the user is using a StackGuarded compiler, and if so, set +# the switch to turn off the canary death handler option. +# +CANARY_FLAG = $(shell if $(CC) -fno-canary-all-functions -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-canary-all-functions"; fi) +CANARY_FLAG += $(shell if $(CC) -mno-terminator-canary -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-terminator-canary"; fi) + +# Comment/uncomment the following line to enable/disable debugging +#DEBUG = y + +# Change it here or specify it on the "make" commandline +INCLUDEDIR = /usr/include + +ifeq ($(DEBUG),y) + DEBFLAGS = -O -g -DDEBUG_IMMUNIX_MMFS +else + DEBFLAGS = -O2 +endif + +CFLAGS = -malign-loops=2 -malign-jumps=2 -malign-functions=2 -D__KERNEL__ \ + -DMODULE -Wall -Wstrict-prototypes $(CANARY_FLAG) \ + -fomit-frame-pointer $(DEBFLAGS) +CFLAGS += -I$(INCLUDEDIR) +LINKER=ld -r + + +# get the kernel version from the include file +# we need this to determine where to put the module for installation. +KERNEL_VERSION = $(shell grep UTS_RELEASE $(INCLUDEDIR)/linux/version.h | cut -f 2 -d \" ) + +# macro for the immunix header file for us lazy typers +IMMUNIX_H = $(INCLUDEDIR)/linux/immunix.h + + +TARGETS = $(CRYPTOMARK) +CRYPTOMARK = cryptomark.o +CIPHER_OBJS = \ + cipher/construct.o \ + cipher/dynload.o \ + cipher/elgamal.o \ + cipher/md.o \ + cipher/md5.o \ + cipher/pubkey.o \ + cipher/rmd160.o \ + cipher/sha1.o + +MPI_OBJS = \ + mpi/mpi-add.o \ + mpi/mpi-bit.o \ + mpi/mpi-cmp.o \ + mpi/mpi-div.o \ + mpi/mpi-mul.o \ + mpi/mpih-add1.o \ + mpi/mpih-cmp.o \ + mpi/mpih-div.o \ + mpi/mpih-lshift.o \ + mpi/mpih-mul.o \ + mpi/mpih-mul1.o \ + mpi/mpih-mul2.o \ + mpi/mpih-mul3.o \ + mpi/mpih-rshift.o \ + mpi/mpih-sub1.o \ + mpi/mpiutil.o \ + mpi/mpi-inv.o \ + mpi/mpi-pow.o \ + mpi/mpi-mpow.o \ + mpi/mpicoder.o + +OBJS = $(CIPHER_OBJS) \ + $(MPI_OBJS) \ + armor.o \ + iobuf.o \ + plaintext.o \ + memory.o \ + parse-packet.o \ + misc.o \ + free-packet.o \ + mdfilter.o \ + fileutil.o \ + kbnode.o \ + strgutil.o \ + getkey.o \ + keyid.o \ + status.o \ + ringedit.o \ + sig-check.o \ + pkclist.o \ + seskey.o \ + build-packet.o \ + mainproc.o + + + +all: $(TARGETS) + +mainproc.o: mainproc.c + +main.o: main.c + +iobuf.o: iobuf.c + +armor.o: armor.c + +calc_sig.o: calc_sig.c cryptomark.h $(IMMUNIX_H) + +verify.o: verify.c cryptomark.h $(IMMUNIX_H) + +sysctl.o: sysctl.c subdomain.h + +list.o: list.c subdomain.h info.h + +prefetch.o: prefetch.c subdomain.h + +info.o: info.c info.h info_p.h + + +$(CRYPTOMARK): $(OBJS) + $(LINKER) -o $@ $(OBJS) + +clean: + rm -f *.o *.ver *~ + +install: all + -mkdir /lib/modules/$(KERNEL_VERSION)/ + -mkdir /lib/modules/$(KERNEL_VERSION)/misc/ + cp $(TARGETS) /lib/modules/$(KERNEL_VERSION)/misc/ + +release: + -rm -rf $(NAME)-$(VERSION) + mkdir $(NAME)-$(VERSION) + cp *.c $(NAME)-$(VERSION) + cp *.h $(NAME)-$(VERSION) + cp $(MISC_FILES) $(NAME)-$(VERSION) + tar czv -f $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION) + rm -rf $(NAME)-$(VERSION) + diff -Nru a/security/cryptomark/gnupg/armor.c b/security/cryptomark/gnupg/armor.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/armor.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1103 @@ +/* armor.c - Armor flter + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include + +#include "errors.h" +#include "iobuf.h" +#include "memory.h" +#include "util.h" +#include "filter.h" +#include "packet.h" +#include "options.h" +#include "main.h" +#include "status.h" +#include "i18n.h" + + +#define MAX_LINELEN 20000 + +#define CRCINIT 0xB704CE +#define CRCPOLY 0X864CFB +#define CRCUPDATE(a,c) do { \ + a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \ + a &= 0x00ffffff; \ + } while(0) +static u32 crc_table[256]; +static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +static byte asctobin[256]; /* runtime initialized */ +static int is_initialized; + + +typedef enum { + fhdrHASArmor = 0, + fhdrNOArmor, + fhdrINIT, + fhdrINITCont, + fhdrINITSkip, + fhdrCHECKBegin, + fhdrWAITHeader, + fhdrWAITClearsig, + fhdrSKIPHeader, + fhdrCLEARSIG, + fhdrREADClearsig, + fhdrNullClearsig, + fhdrEMPTYClearsig, + fhdrCHECKClearsig, + fhdrCHECKClearsig2, + fhdrCHECKDashEscaped, + fhdrCHECKDashEscaped2, + fhdrCHECKDashEscaped3, + fhdrREADClearsigNext, + fhdrENDClearsig, + fhdrENDClearsigHelp, + fhdrTESTSpaces, + fhdrCLEARSIGSimple, + fhdrCLEARSIGSimpleNext, + fhdrTEXT, + fhdrTEXTSimple, + fhdrERROR, + fhdrERRORShow, + fhdrEOF +} fhdr_state_t; + + +/* if we encounter this armor string with this index, go + * into a mode which fakes packets and wait for the next armor */ +#define BEGIN_SIGNATURE 2 +#define BEGIN_SIGNED_MSG_IDX 3 +static char *head_strings[] = { + "BEGIN PGP MESSAGE", + "BEGIN PGP PUBLIC KEY BLOCK", + "BEGIN PGP SIGNATURE", + "BEGIN PGP SIGNED MESSAGE", + "BEGIN PGP ARMORED FILE", /* gnupg extension */ + "BEGIN PGP PRIVATE KEY BLOCK", + "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */ + NULL +}; +static char *tail_strings[] = { + "END PGP MESSAGE", + "END PGP PUBLIC KEY BLOCK", + "END PGP SIGNATURE", + "END dummy", + "END PGP ARMORED FILE", + "END PGP PRIVATE KEY BLOCK", + "END PGP SECRET KEY BLOCK", + NULL +}; + + + +static void +initialize(void) +{ + int i, j; + u32 t; + byte *s; + + trace(); + + /* init the crc lookup table */ + crc_table[0] = 0; + for(i=j=0; j < 128; j++ ) { + t = crc_table[j]; + if( t & 0x00800000 ) { + t <<= 1; + crc_table[i++] = t ^ CRCPOLY; + crc_table[i++] = t; + } + else { + t <<= 1; + crc_table[i++] = t; + crc_table[i++] = t ^ CRCPOLY; + } + } + /* build the helptable for radix64 to bin conversion */ + for(i=0; i < 256; i++ ) + asctobin[i] = 255; /* used to detect invalid characters */ + for(s=bintoasc,i=0; *s; s++,i++ ) + asctobin[*s] = i; + + is_initialized=1; +} + +/**************** + * Check whether this is an armored file or not + * See also parse-packet.c for details on this code + * Returns: True if it seems to be armored + */ +static int +is_armored( const byte *buf ) +{ + int ctb, pkttype; + + trace(); + + ctb = *buf; + if( !(ctb & 0x80) ) + return 1; /* invalid packet: assume it is armored */ + pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf); + switch( pkttype ) { + case PKT_MARKER: + case PKT_SYMKEY_ENC: + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_PUBKEY_ENC: + case PKT_SIGNATURE: + case PKT_COMMENT: + case PKT_OLD_COMMENT: + case PKT_PLAINTEXT: + case PKT_COMPRESSED: + case PKT_ENCRYPTED: + return 0; /* seems to be a regular packet: not armored */ + } + + return 1; +} + + +/**************** + * Try to check whether the iobuf is armored + * Returns true if this may be the case; the caller should use the + * filter to do further processing. + */ +int +use_armor_filter( IOBUF a ) +{ + byte buf[1]; + int n; + + trace(); + + n = iobuf_peek(a, buf, 1 ); + if( n == -1 ) + return 0; /* EOF, doesn't matter whether armored or not */ + if( !n ) + return 1; /* can't check it: try armored */ + return is_armored(buf); +} + + + + +static void +invalid_armor(void) +{ + err (__FUNCTION__": not good!"); +// write_status(STATUS_BADARMOR); +// g10_exit(1); /* stop here */ +} + + +/**************** + * check whether the armor header is valid on a signed message. + * this is for security reasons: the header lines are not included in the + * hash and by using some creative formatting rules, Mallory could fake + * any text at the beginning of a document; assuming it is read with + * a simple viewer. We only allow the Hash Header. + */ +static int +parse_hash_header( const char *line ) +{ + const char *s, *s2; + unsigned found = 0; + + trace(); + + if( strlen(line) < 6 || strlen(line) > 60 ) + return 0; /* too short or too long */ + if( memcmp( line, "Hash:", 5 ) ) + return 0; /* invalid header */ + s = line+5; + for(s=line+5;;s=s2) { + for(; *s && (*s==' ' || *s == '\t'); s++ ) + ; + if( !*s ) + break; + for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ ) + ; + if( !strncmp( s, "RIPEMD160", s2-s ) ) + found |= 1; + else if( !strncmp( s, "SHA1", s2-s ) ) + found |= 2; + else if( !strncmp( s, "MD5", s2-s ) ) + found |= 4; + else if( !strncmp( s, "TIGER", s2-s ) ) + found |= 8; + else + return 0; + for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) + ; + if( *s2 && *s2 != ',' ) + return 0; + if( *s2 ) + s2++; + } + return found; +} + + + +/**************** + * Check whether this is a armor line. + * returns: -1 if it is not a armor header or the index number of the + * armor header. + */ +static int +is_armor_header( byte *line, unsigned len ) +{ + const char *s; + byte *save_p, *p; + int save_c; + int i; + + trace(); + + if( len < 15 ) + return -1; /* too short */ + if( memcmp( line, "-----", 5 ) ) + return -1; /* no */ + p = strstr( line+5, "-----"); + if( !p ) + return -1; + save_p = p; + p += 5; + if( *p == '\r' ) + p++; + if( *p == '\n' ) + p++; + if( *p ) + return -1; /* garbage after dashes */ + save_c = *save_p; *save_p = 0; + p = line+5; + for(i=0; (s=head_strings[i]); i++ ) + if( !strcmp(s, p) ) + break; + *save_p = save_c; + if( !s ) + return -1; /* unknown armor line */ + +// if( opt.verbose > 1 ) +// log_info(_("armor: %s\n"), head_strings[i]); + return i; +} + + + +/**************** + * Parse a header lines + * Return 0: Empty line (end of header lines) + * -1: invalid header line + * >0: Good header line + */ +static int +parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len ) +{ + byte *p; + int hashes=0; + + trace(); + + /* fixme: why this double check? I think the original code w/o the + * second check for an empty line was done from an early draft of + * of OpenPGP - or simply very stupid code */ + if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) ) + return 0; /* empty line */ + len = trim_trailing_ws( line, len ); + if( !len ) + return 0; /* WS only same as empty line */ + + p = strchr( line, ':'); + if( !p || !p[1] ) { +// log_error(_("invalid armor header: ")); + log_error("invalid armor header: "); +// print_string( stderr, line, len, 0 ); +// putc('\n', stderr); + return -1; + } + + if( opt.verbose ) { +// log_info(_("armor header: ")); + log_info("armor header: "); +// print_string( stderr, line, len, 0 ); +// putc('\n', stderr); + } + + if( afx->in_cleartext ) { + if( (hashes=parse_hash_header( line )) ) + afx->hashes |= hashes; + else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) ) + afx->not_dash_escaped = 1; + else { +// log_error(_("invalid clearsig header\n")); + log_error("invalid clearsig header\n"); + return -1; + } + } + return 1; +} + + + +/* figure out whether the data is armored or not */ +static int +check_input( armor_filter_context_t *afx, IOBUF a ) +{ + int rc = 0; + int i; + byte *line; + unsigned len; + unsigned maxlen; + int hdr_line = -1; + + trace(); + + /* read the first line to see whether this is armored data */ + maxlen = MAX_LINELEN; + len = afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + if( !maxlen ) { + /* line has been truncated: assume not armored */ + afx->inp_checked = 1; + afx->inp_bypass = 1; + return 0; + } + + if( !len ) { + return -1; /* eof */ + } + + /* (the line is always a C string but maybe longer) */ + if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) ) + ; + else if( !is_armored( line ) ) { + afx->inp_checked = 1; + afx->inp_bypass = 1; + return 0; + } + + /* find the armor header */ + while(len) { + i = is_armor_header( line, len ); + if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) { + hdr_line = i; + if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { + if( afx->in_cleartext ) { +// log_error(_("nested clear text signatures\n")); + log_error("nested clear text signatures\n"); + rc = G10ERR_INVALID_ARMOR; + } + afx->in_cleartext = 1; + } + break; + } + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + len = afx->buffer_len; + } while( !maxlen ); + } + + /* parse the header lines */ + while(len) { + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + len = afx->buffer_len; + } while( !maxlen ); + + i = parse_header_line( afx, line, len ); + if( i <= 0 ) { + if( i ) + rc = G10ERR_INVALID_ARMOR; + break; + } + } + + + if( rc ) + invalid_armor(); + else if( afx->in_cleartext ) + afx->faked = 1; + else { + afx->inp_checked = 1; + afx->crc = CRCINIT; + afx->idx = 0; + afx->radbuf[0] = 0; + } + + return rc; +} + + + +/**************** + * Fake a literal data packet and wait for the next armor line + * fixme: empty line handling and null length clear text signature are + * not implemented/checked. + */ +static int +fake_packet( armor_filter_context_t *afx, IOBUF a, + size_t *retn, byte *buf, size_t size ) +{ + int rc = 0; + size_t len = 0; + int lastline = 0; + unsigned maxlen, n; + byte *p; + + trace(); + + len = 2; /* reserve 2 bytes for the length header */ + size -= 2; /* and 2 for the terminating header */ + while( !rc && len < size ) { + /* copy what we have in the line buffer */ + if( afx->faked == 1 ) + afx->faked++; /* skip the first (empty) line */ + else { + while( len < size && afx->buffer_pos < afx->buffer_len ) + buf[len++] = afx->buffer[afx->buffer_pos++]; + if( len >= size ) + continue; + } + + /* read the next line */ + maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !afx->buffer_len ) { + rc = -1; /* eof (should not happen) */ + continue; + } + if( !maxlen ) + afx->truncated++; + if( !afx->not_dash_escaped ) { + /* PGP2 does not treat a tab as white space character */ + afx->buffer_len = + trim_trailing_chars( afx->buffer, afx->buffer_len, + afx->pgp2mode ? " \r\n" : " \t\r\n"); + /* the buffer is always allocated with enough space to append + * a CR, LF, Nul */ + afx->buffer[afx->buffer_len++] = '\r'; + afx->buffer[afx->buffer_len++] = '\n'; + afx->buffer[afx->buffer_len] = 0; + } + p = afx->buffer; + n = afx->buffer_len; + + if( n > 2 && *p == '-' ) { + /* check for dash escaped or armor header */ + if( p[1] == ' ' && !afx->not_dash_escaped ) { + /* issue a warning if it is not regular encoded */ + if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) { +// log_info(_("invalid dash escaped line: ")); + log_info("invalid dash escaped line: "); +// print_string( stderr, p, n, 0 ); +// putc('\n', stderr); + } + afx->buffer_pos = 2; /* skip */ + } + else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) { + int type = is_armor_header( p, n ); + if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) + ; /* this is okay */ + else { + if( type != BEGIN_SIGNATURE ) { +// log_info(_("unexpected armor:")); + log_info("unexpected armor:"); +// print_string( stderr, p, n, 0 ); +// putc('\n', stderr); + } + lastline = 1; + rc = -1; + } + } + } + } + + buf[0] = (len-2) >> 8; + buf[1] = (len-2); + if( lastline ) { /* write last (ending) length header */ + if( buf[0] || buf[1] ) { /* only if we have some text */ + buf[len++] = 0; + buf[len++] = 0; + } + rc = 0; + afx->faked = 0; + afx->in_cleartext = 0; + /* and now read the header lines */ + afx->buffer_pos = 0; + for(;;) { + int i; + + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + } while( !maxlen ); + p = afx->buffer; + n = afx->buffer_len; + if( !n ) { + rc = -1; + break; /* eof */ + } + i = parse_header_line( afx, p , n ); + if( i <= 0 ) { + if( i ) + invalid_armor(); + break; + } + } + afx->inp_checked = 1; + afx->crc = CRCINIT; + afx->idx = 0; + afx->radbuf[0] = 0; + } + + *retn = len; + return rc; +} + + + +static int +radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, + byte *buf, size_t size ) +{ + byte val; + int c=0, c2; /*init c because gcc is not clever enough for the continue*/ + int checkcrc=0; + int rc = 0; + size_t n = 0; + int idx, i; + u32 crc; + + trace(); + + crc = afx->crc; + idx = afx->idx; + val = afx->radbuf[0]; + for( n=0; n < size; ) { + + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + + again: + if( c == '\n' || c == ' ' || c == '\r' || c == '\t' ) + continue; + else if( c == '=' ) { /* pad character: stop */ + /* some mailers leave quoted-printable encoded characters + * so we try to workaround this */ + if( afx->buffer_pos+2 < afx->buffer_len ) { + int cc1, cc2, cc3; + cc1 = afx->buffer[afx->buffer_pos]; + cc2 = afx->buffer[afx->buffer_pos+1]; + cc3 = afx->buffer[afx->buffer_pos+2]; + if( isxdigit(cc1) && isxdigit(cc2) + && strchr( "=\n\r\t ", cc3 )) { + /* well it seems to be the case - adjust */ + c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10); + c <<= 4; + c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10); + afx->buffer_pos += 2; + afx->qp_detected = 1; + goto again; + } + } + + if( idx == 1 ) + buf[n++] = val; + checkcrc++; + break; + } + else if( (c = asctobin[(c2=c)]) == 255 ) { +// log_error(_("invalid radix64 character %02x skipped\n"), c2); + log_error("invalid radix64 character %02x skipped\n", c2); + continue; + } + switch(idx) { + case 0: val = c << 2; break; + case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break; + case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break; + case 3: val |= c&0x3f; buf[n++] = val; break; + } + idx = (idx+1) % 4; + } + + for(i=0; i < n; i++ ) + crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; + crc &= 0x00ffffff; + afx->crc = crc; + afx->idx = idx; + afx->radbuf[0] = val; + + if( checkcrc ) { + afx->any_data = 1; + afx->inp_checked=0; + afx->faked = 0; + for(;;) { /* skip lf and pad characters */ + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + if( c == '\n' || c == ' ' || c == '\r' + || c == '\t' || c == '=' ) + continue; + break; + } + if( c == -1 ) { +// log_error(_("premature eof (no CRC)\n")); + log_error("premature eof (no CRC)\n"); + } + else { + u32 mycrc = 0; + idx = 0; + do { + if( (c = asctobin[c]) == 255 ) + break; + switch(idx) { + case 0: val = c << 2; break; + case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break; + case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break; + case 3: val |= c&0x3f; mycrc |= val; break; + } + for(;;) { + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, + &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + break; + } + if( !afx->buffer_len ) + break; /* eof */ + } while( ++idx < 4 ); + if( c == -1 ) { +// log_error(_("premature eof (in CRC)\n")); + log_error("premature eof (in CRC)\n"); + rc = G10ERR_INVALID_ARMOR; + } + else if( idx != 4 ) { +// log_error(_("malformed CRC\n")); + log_error("malformed CRC\n"); + rc = G10ERR_INVALID_ARMOR; + } + else if( mycrc != afx->crc ) { +// log_error(_("CRC error; %06lx - %06lx\n"), (ulong)afx->crc, (ulong)mycrc); + log_error("CRC error; %06lx - %06lx\n", (ulong)afx->crc, (ulong)mycrc); + rc = G10ERR_INVALID_ARMOR; + } + else { + rc = 0; + #if 0 + for(rc=0;!rc;) { + rc = 0 /*check_trailer( &fhdr, c )*/; + if( !rc ) { + if( (c=iobuf_get(a)) == -1 ) + rc = 2; + } + } + if( rc == -1 ) + rc = 0; + else if( rc == 2 ) { +// log_error(_("premature eof (in Trailer)\n")); + log_error("premature eof (in Trailer)\n"); + rc = G10ERR_INVALID_ARMOR; + } + else { +// log_error(_("error in trailer line\n")); + log_error("error in trailer line\n"); + rc = G10ERR_INVALID_ARMOR; + } + #endif + } + } + } + + if( !n ) + rc = -1; + + *retn = n; + return rc; +} + +/**************** + * This filter is used to handle the armor stuff + */ +int +armor_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len) +{ + size_t size = *ret_len; + armor_filter_context_t *afx = opaque; + int rc=0, i, c; + byte radbuf[3]; + int idx, idx2; + size_t n=0; + u32 crc; + #if 0 + static FILE *fp ; + + if( !fp ) { + fp = fopen("armor.out", "w"); + assert(fp); + } + #endif + + trace(); + + dbg (__FUNCTION__": control = %d", control); + if( DBG_FILTER ) + log_debug("armor-filter: control: %d\n", control ); + if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) { + n = 0; + if( afx->buffer_len ) { + for(; n < size && afx->buffer_pos < afx->buffer_len; n++ ) + buf[n++] = afx->buffer[afx->buffer_pos++]; + if( afx->buffer_pos >= afx->buffer_len ) + afx->buffer_len = 0; + } + for(; n < size; n++ ) { + if( (c=iobuf_get(a)) == -1 ) + break; + buf[n] = c & 0xff; + } + if( !n ) + rc = -1; + *ret_len = n; + } + else if( control == IOBUFCTRL_UNDERFLOW ) { + if( size < 15+(4*15) ) /* need space for up to 4 onepass_sigs */ + BUG(); /* supplied buffer too short */ + + if( afx->faked ) + rc = fake_packet( afx, a, &n, buf, size ); + else if( !afx->inp_checked ) { + rc = check_input( afx, a ); + if( afx->inp_bypass ) { + for(n=0; n < size && afx->buffer_pos < afx->buffer_len; ) + buf[n++] = afx->buffer[afx->buffer_pos++]; + if( afx->buffer_pos >= afx->buffer_len ) + afx->buffer_len = 0; + if( !n ) + rc = -1; + } + else if( afx->faked ) { + unsigned hashes = afx->hashes; + /* the buffer is at least 15+n*15 bytes long, so it + * is easy to construct the packets */ + + hashes &= 1|2|4|8; + if( !hashes ) { + hashes |= 4; /* default to MD 5 */ + afx->pgp2mode = 1; + } + n=0; + do { + /* first some onepass signature packets */ + buf[n++] = 0x90; /* old format, type 4, 1 length byte */ + buf[n++] = 13; /* length */ + buf[n++] = 3; /* version */ + buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/ + if( hashes & 1 ) { + hashes &= ~1; + buf[n++] = DIGEST_ALGO_RMD160; + } + else if( hashes & 2 ) { + hashes &= ~2; + buf[n++] = DIGEST_ALGO_SHA1; + } + else if( hashes & 4 ) { + hashes &= ~4; + buf[n++] = DIGEST_ALGO_MD5; + } + else if( hashes & 8 ) { + hashes &= ~8; + buf[n++] = DIGEST_ALGO_TIGER; + } + else + buf[n++] = 0; /* (don't know) */ + + buf[n++] = 0; /* public key algo (don't know) */ + memset(buf+n, 0, 8); /* don't know the keyid */ + n += 8; + buf[n++] = !hashes; /* last one */ + } while( hashes ); + + /* followed by a plaintext packet */ + buf[n++] = 0xaf; /* old packet format, type 11, var length */ + buf[n++] = 0; /* set the length header */ + buf[n++] = 6; + buf[n++] = 't'; /* canonical text mode */ + buf[n++] = 0; /* namelength */ + memset(buf+n, 0, 4); /* timestamp */ + n += 4; + } + else if( !rc ) + rc = radix64_read( afx, a, &n, buf, size ); + } + else + rc = radix64_read( afx, a, &n, buf, size ); + #if 0 + if( n ) + if( fwrite(buf, n, 1, fp ) != 1 ) + BUG(); + #endif + *ret_len = n; + } + else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { + if( !afx->status ) { /* write the header line */ + if( afx->what >= DIM(head_strings) ) + log_bug("afx->what=%d", afx->what); + iobuf_writestr(a, "-----"); + iobuf_writestr(a, head_strings[afx->what] ); + iobuf_writestr(a, "-----\n"); +// if( !opt.no_version ) +// iobuf_writestr(a, "Version: GnuPG v" VERSION " (" +// PRINTABLE_OS_NAME ")\n"); + + if( opt.comment_string ) { + const char *s = opt.comment_string; + if( *s ) { + iobuf_writestr(a, "Comment: " ); + for( ; *s; s++ ) { + if( *s == '\n' ) + iobuf_writestr(a, "\\n" ); + else if( *s == '\r' ) + iobuf_writestr(a, "\\r" ); + else if( *s == '\v' ) + iobuf_writestr(a, "\\v" ); + else + iobuf_put(a, *s ); + } + iobuf_put(a, '\n' ); + } + } + else + iobuf_writestr(a, + "Comment: For info see http://www.gnupg.org\n"); + if( afx->hdrlines ) + iobuf_writestr(a, afx->hdrlines); + iobuf_put(a, '\n'); + afx->status++; + afx->idx = 0; + afx->idx2 = 0; + afx->crc = CRCINIT; + } + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + radbuf[i] = afx->radbuf[i]; + + for(i=0; i < size; i++ ) + crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; + crc &= 0x00ffffff; + + for( ; size; buf++, size-- ) { + radbuf[idx++] = *buf; + if( idx > 2 ) { + idx = 0; + c = bintoasc[(*radbuf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[radbuf[2]&077]; + iobuf_put(a, c); + if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ + iobuf_put(a, '\n'); + idx2=0; + } + } + } + for(i=0; i < idx; i++ ) + afx->radbuf[i] = radbuf[i]; + afx->idx = idx; + afx->idx2 = idx2; + afx->crc = crc; + } + else if( control == IOBUFCTRL_INIT ) { + if( !is_initialized ) + initialize(); + } + else if( control == IOBUFCTRL_CANCEL ) { + afx->cancel = 1; + } + else if( control == IOBUFCTRL_FREE ) { + if( afx->cancel ) + ; + else if( afx->status ) { /* pad, write cecksum, and bottom line */ + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + radbuf[i] = afx->radbuf[i]; + if( idx ) { + c = bintoasc[(*radbuf>>2)&077]; + iobuf_put(a, c); + if( idx == 1 ) { + c = bintoasc[((*radbuf << 4) & 060) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + iobuf_put(a, '='); + } + else { /* 2 */ + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[((radbuf[1] << 2) & 074) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + } + if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ + iobuf_put(a, '\n'); + idx2=0; + } + } + /* may need a linefeed */ + if( idx2 ) + iobuf_put(a, '\n'); + /* write the CRC */ + iobuf_put(a, '='); + radbuf[0] = crc >>16; + radbuf[1] = crc >> 8; + radbuf[2] = crc; + c = bintoasc[(*radbuf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[radbuf[2]&077]; + iobuf_put(a, c); + iobuf_put(a, '\n'); + /* and the the trailer */ + if( afx->what >= DIM(tail_strings) ) + log_bug("afx->what=%d", afx->what); + iobuf_writestr(a, "-----"); + iobuf_writestr(a, tail_strings[afx->what] ); + iobuf_writestr(a, "-----\n"); + } + else if( !afx->any_data && !afx->inp_bypass ) { +// log_error(_("no valid OpenPGP data found.\n")); + log_error("no valid OpenPGP data found.\n"); + afx->no_openpgp_data = 1; + write_status_text( STATUS_NODATA, "1" ); + } + if( afx->truncated ){ +// log_info(_("invalid armor: line longer than %d characters\n"), MAX_LINELEN ); + log_info("invalid armor: line longer than %d characters\n", MAX_LINELEN ); + } + /* issue an error to enforce dissemination of correct software */ + if( afx->qp_detected ) { +// log_error(_("quoted printable character in armor - probably a buggy MTA has been used\n") ); + log_error("quoted printable character in armor - probably a buggy MTA has been used\n"); + } + m_free( afx->buffer ); + afx->buffer = NULL; + } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "armor_filter"; + return rc; +} + + +/**************** + * create a radix64 encoded string. + */ +char * +make_radix64_string( const byte *data, size_t len ) +{ + char *buffer, *p; + + trace(); + + buffer = p = m_alloc( (len+2)/3*4 + 1 ); + for( ; len >= 3 ; len -= 3, data += 3 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; + *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077]; + *p++ = bintoasc[data[2]&077]; + } + if( len == 2 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; + *p++ = bintoasc[((data[1]<<2)&074)]; + } + else if( len == 1 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(data[0] <<4)&060]; + } + *p = 0; + return buffer; +} + diff -Nru a/security/cryptomark/gnupg/build-packet.c b/security/cryptomark/gnupg/build-packet.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/build-packet.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1052 @@ +/* build-packet.c - assemble packets and write them + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include + +#include "packet.h" +#include "errors.h" +#include "iobuf.h" +#include "mpi.h" +#include "util.h" +#include "cipher.h" +#include "memory.h" +#include "options.h" + + +static int do_comment( IOBUF out, int ctb, PKT_comment *rem ); +static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); +static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); +static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); +static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); +static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); +static u32 calc_plaintext( PKT_plaintext *pt ); +static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); +static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); +static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); +static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); + +static int calc_header_length( u32 len, int new_ctb ); +static int write_16(IOBUF inp, u16 a); +static int write_32(IOBUF inp, u32 a); +static int write_header( IOBUF out, int ctb, u32 len ); +static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); +static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ); +static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_version( IOBUF out, int ctb ); + +/**************** + * Build a packet and write it to INP + * Returns: 0 := okay + * >0 := error + * Note: Caller must free the packet + */ +int +build_packet( IOBUF out, PACKET *pkt ) +{ + int new_ctb=0, rc=0, ctb; + int pkttype; + + trace(); + + if( DBG_PACKET ) + log_debug("build_packet() type=%d\n", pkt->pkttype ); +// assert( pkt->pkt.generic ); + + switch( (pkttype = pkt->pkttype) ) { + case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break; + case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; + case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; + case PKT_USER_ID: + if( pkt->pkt.user_id->photo ) + pkttype = PKT_PHOTO_ID; + break; + default: break; + } + + if( new_ctb || pkttype > 15 ) /* new format */ + ctb = 0xc0 | (pkttype & 0x3f); + else + ctb = 0x80 | ((pkttype & 15)<<2); + switch( pkttype ) { + case PKT_PHOTO_ID: + case PKT_USER_ID: + rc = do_user_id( out, ctb, pkt->pkt.user_id ); + break; + case PKT_COMMENT: + rc = do_comment( out, ctb, pkt->pkt.comment ); + break; + case PKT_PUBLIC_SUBKEY: + case PKT_PUBLIC_KEY: + rc = do_public_key( out, ctb, pkt->pkt.public_key ); + break; + case PKT_SECRET_SUBKEY: + case PKT_SECRET_KEY: + rc = do_secret_key( out, ctb, pkt->pkt.secret_key ); + break; + case PKT_SYMKEY_ENC: + rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc ); + break; + case PKT_PUBKEY_ENC: + rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc ); + break; + case PKT_PLAINTEXT: + rc = do_plaintext( out, ctb, pkt->pkt.plaintext ); + break; + case PKT_ENCRYPTED: + rc = do_encrypted( out, ctb, pkt->pkt.encrypted ); + break; + case PKT_ENCRYPTED_MDC: + rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted ); + break; + case PKT_COMPRESSED: + rc = do_compressed( out, ctb, pkt->pkt.compressed ); + break; + case PKT_SIGNATURE: + rc = do_signature( out, ctb, pkt->pkt.signature ); + break; + case PKT_ONEPASS_SIG: + rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig ); + break; + case PKT_RING_TRUST: + break; /* ignore it */ + default: + log_bug("invalid packet type in build_packet()\n"); + break; + } + + return rc; +} + +///**************** +// * calculate the length of a packet described by PKT +// */ +//u32 +//calc_packet_length( PACKET *pkt ) +//{ +// u32 n=0; +// int new_ctb = 0; +// +// assert( pkt->pkt.generic ); +// switch( pkt->pkttype ) { +// case PKT_PLAINTEXT: +// n = calc_plaintext( pkt->pkt.plaintext ); +// new_ctb = pkt->pkt.plaintext->new_ctb; +// break; +// case PKT_PHOTO_ID: +// case PKT_USER_ID: +// case PKT_COMMENT: +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// case PKT_SYMKEY_ENC: +// case PKT_PUBKEY_ENC: +// case PKT_ENCRYPTED: +// case PKT_SIGNATURE: +// case PKT_ONEPASS_SIG: +// case PKT_RING_TRUST: +// case PKT_COMPRESSED: +// default: +// log_bug("invalid packet type in calc_packet_length()"); +// break; +// } +// +// n += calc_header_length(n, new_ctb); +// return n; +//} + +static void +write_fake_data( IOBUF out, MPI a ) +{ + trace(); + + if( a ) { + int i; + void *p; + + p = mpi_get_opaque( a, &i ); + iobuf_write( out, p, i ); + } +} + + +static int +do_comment( IOBUF out, int ctb, PKT_comment *rem ) +{ + trace(); + + if( !opt.no_comment ) { + write_header(out, ctb, rem->len); + if( iobuf_write( out, rem->data, rem->len ) ) + return G10ERR_WRITE_FILE; + } + return 0; +} + +static int +do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) +{ + trace(); + + if( uid->photo ) { + write_header(out, ctb, uid->photolen); + if( iobuf_write( out, uid->photo, uid->photolen ) ) + return G10ERR_WRITE_FILE; + } + else { + write_header(out, ctb, uid->len); + if( iobuf_write( out, uid->name, uid->len ) ) + return G10ERR_WRITE_FILE; + } + return 0; +} + +static int +do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + trace(); + + if( !pk->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, pk->version ); + write_32(a, pk->timestamp ); + if( pk->version < 4 ) { + u16 ndays; + if( pk->expiredate ) + ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, ndays ); + } + iobuf_put(a, pk->pubkey_algo ); + n = pubkey_get_npkey( pk->pubkey_algo ); + if( !n ) + write_fake_data( a, pk->pkey[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, pk->pkey[i] ); + + write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +/**************** + * Make a hash value from the public key certificate + */ +void +hash_public_key( MD_HANDLE md, PKT_public_key *pk ) +{ + PACKET pkt; + int rc = 0; + int ctb; + ulong pktlen; + int c; + IOBUF a = iobuf_temp(); + #if 0 + FILE *fp = fopen("dump.pk", "a"); + int i=0; + + fprintf(fp, "\nHashing PK (v%d):\n", pk->version); + #endif + + trace(); + + /* build the packet */ + init_packet(&pkt); + pkt.pkttype = PKT_PUBLIC_KEY; + pkt.pkt.public_key = pk; + if( (rc = build_packet( a, &pkt )) ) + log_fatal("build public_key for hashing failed: %d\n", rc); + + if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { + /* skip the constructed header but don't do this for our very old + * v3 ElG keys */ + ctb = iobuf_get_noeof(a); + pktlen = 0; + if( (ctb & 0x40) ) { + c = iobuf_get_noeof(a); + if( c < 192 ) + pktlen = c; + else if( c < 224 ) { + pktlen = (c - 192) * 256; + c = iobuf_get_noeof(a); + pktlen += c + 192; + } + else if( c == 255 ) { + pktlen = iobuf_get_noeof(a) << 24; + pktlen |= iobuf_get_noeof(a) << 16; + pktlen |= iobuf_get_noeof(a) << 8; + pktlen |= iobuf_get_noeof(a); + } + } + else { + int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); + for( ; lenbytes; lenbytes-- ) { + pktlen <<= 8; + pktlen |= iobuf_get_noeof(a); + } + } + /* hash a header */ + md_putc( md, 0x99 ); + pktlen &= 0xffff; /* can't handle longer packets */ + md_putc( md, pktlen >> 8 ); + md_putc( md, pktlen & 0xff ); + } + /* hash the packet body */ + while( (c=iobuf_get(a)) != -1 ) { + #if 0 + fprintf( fp," %02x", c ); + if( (++i == 24) ) { + putc('\n', fp); + i=0; + } + #endif + md_putc( md, c ); + } + #if 0 + putc('\n', fp); + fclose(fp); + #endif + iobuf_cancel(a); +} + + +static int +do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) +{ + int rc = 0; + int i, nskey, npkey; + IOBUF a = iobuf_temp(); + + trace(); + + if( !sk->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, sk->version ); + write_32(a, sk->timestamp ); + if( sk->version < 4 ) { + u16 ndays; + if( sk->expiredate ) + ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, 0 ); + } + iobuf_put(a, sk->pubkey_algo ); + nskey = pubkey_get_nskey( sk->pubkey_algo ); + npkey = pubkey_get_npkey( sk->pubkey_algo ); + if( !npkey ) { + write_fake_data( a, sk->skey[0] ); + goto leave; + } +// assert( npkey < nskey ); + + for(i=0; i < npkey; i++ ) + mpi_write(a, sk->skey[i] ); + if( sk->is_protected ) { + if( is_RSA(sk->pubkey_algo) && sk->version < 4 + && !sk->protect.s2k.mode ) { + iobuf_put(a, sk->protect.algo ); + iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); + } + else { + iobuf_put(a, 0xff ); + iobuf_put(a, sk->protect.algo ); + iobuf_put(a, sk->protect.s2k.mode ); + iobuf_put(a, sk->protect.s2k.hash_algo ); + if( sk->protect.s2k.mode == 1 + || sk->protect.s2k.mode == 3 ) + iobuf_write(a, sk->protect.s2k.salt, 8 ); + if( sk->protect.s2k.mode == 3 ) + iobuf_put(a, sk->protect.s2k.count ); + iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); + } + } + else + iobuf_put(a, 0 ); + if( sk->is_protected && sk->version >= 4 ) { + byte *p; +// assert( mpi_is_opaque( sk->skey[npkey] ) ); + p = mpi_get_opaque( sk->skey[npkey], &i ); + iobuf_write(a, p, i ); + } + else { + for( ; i < nskey; i++ ) + mpi_write(a, sk->skey[i] ); + write_16(a, sk->csum ); + } + + leave: + write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + +static int +do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) +{ + int rc = 0; + IOBUF a = iobuf_temp(); + + trace(); + +// assert( enc->version == 4 ); + switch( enc->s2k.mode ) { + case 0: case 1: case 3: break; + default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); + } + iobuf_put( a, enc->version ); + iobuf_put( a, enc->cipher_algo ); + iobuf_put( a, enc->s2k.mode ); + iobuf_put( a, enc->s2k.hash_algo ); + if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { + iobuf_write(a, enc->s2k.salt, 8 ); + if( enc->s2k.mode == 3 ) + iobuf_put(a, enc->s2k.count); + } + if( enc->seskeylen ) + iobuf_write(a, enc->seskey, enc->seskeylen ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + + + +static int +do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + trace(); + + write_version( a, ctb ); + if( enc->throw_keyid ) { + write_32(a, 0 ); /* don't tell Eve who can decrypt the message */ + write_32(a, 0 ); + } + else { + write_32(a, enc->keyid[0] ); + write_32(a, enc->keyid[1] ); + } + iobuf_put(a,enc->pubkey_algo ); + n = pubkey_get_nenc( enc->pubkey_algo ); + if( !n ) + write_fake_data( a, enc->data[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, enc->data[i] ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + + + +static u32 +calc_plaintext( PKT_plaintext *pt ) +{ + return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; +} + +static int +do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) +{ + int i, rc = 0; + u32 n; + byte buf[1000]; /* this buffer has the plaintext! */ + int nbytes; + + trace(); + + write_header(out, ctb, calc_plaintext( pt ) ); + iobuf_put(out, pt->mode ); + iobuf_put(out, pt->namelen ); + for(i=0; i < pt->namelen; i++ ) + iobuf_put(out, pt->name[i] ); + if( write_32(out, pt->timestamp ) ) + rc = G10ERR_WRITE_FILE; + + n = 0; + while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { + if( iobuf_write(out, buf, nbytes) == -1 ) { + rc = G10ERR_WRITE_FILE; + break; + } + n += nbytes; + } + memset(buf,0,1000); /* at least burn the buffer */ + if( !pt->len ) + iobuf_set_block_mode(out, 0 ); /* write end marker */ + else if( n != pt->len ) + log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", + (ulong)n, (ulong)pt->len ); + + return rc; +} + + + +static int +do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) +{ + int rc = 0; + u32 n; + + trace(); + + n = ed->len ? (ed->len + 10) : 0; + write_header(out, ctb, n ); + + /* This is all. The caller has to write the real data */ + + return rc; +} + +static int +do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) +{ + int rc = 0; + u32 n; + + trace(); + +// assert( ed->mdc_method ); + + n = ed->len ? (ed->len + 10) : 0; + write_header(out, ctb, n ); + iobuf_put(out, 1 ); /* version */ + iobuf_put(out, ed->mdc_method ); + + /* This is all. The caller has to write the real data */ + + return rc; +} + +static int +do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) +{ + int rc = 0; + + trace(); + + /* we must use the old convention and don't use blockmode */ + write_header2(out, ctb, 0, 0, 0 ); + iobuf_put(out, cd->algorithm ); + + /* This is all. The caller has to write the real data */ + + return rc; +} + + +// +///**************** +// * Find a subpacket of type REQTYPE in BUFFER and a return a pointer +// * to the first byte of that subpacket data. +// * And return the length of the packet in RET_N and the number of +// * header bytes in RET_HLEN (length header and type byte). +// */ +//byte * +//find_subpkt( byte *buffer, sigsubpkttype_t reqtype, +// size_t *ret_hlen, size_t *ret_n ) +//{ +// int buflen; +// sigsubpkttype_t type; +// byte *bufstart; +// size_t n; +// +// if( !buffer ) +// return NULL; +// buflen = (*buffer << 8) | buffer[1]; +// buffer += 2; +// for(;;) { +// if( !buflen ) +// return NULL; /* end of packets; not found */ +// bufstart = buffer; +// n = *buffer++; buflen--; +// if( n == 255 ) { +// if( buflen < 4 ) +// break; +// n = (buffer[0] << 24) | (buffer[1] << 16) +// | (buffer[2] << 8) | buffer[3]; +// buffer += 4; +// buflen -= 4; +// } +// else if( n >= 192 ) { +// if( buflen < 2 ) +// break; +// n = (( n - 192 ) << 8) + *buffer + 192; +// buffer++; +// buflen--; +// } +// if( buflen < n ) +// break; +// type = *buffer & 0x7f; +// if( type == reqtype ) { +// buffer++; +// n--; +// if( n > buflen ) +// break; +// if( ret_hlen ) +// *ret_hlen = buffer - bufstart; +// if( ret_n ) +// *ret_n = n; +// return buffer; +// } +// buffer += n; buflen -=n; +// } +// +// log_error("find_subpkt: buffer shorter than subpacket\n"); +// return NULL; +//} +// +// +///**************** +// * Create or update a signature subpacket for SIG of TYPE. +// * This functions knows where to put the data (hashed or unhashed). +// * The function may move data from the unhased part to the hashed one. +// * Note: All pointers into sig->[un]hashed are not valid after a call +// * to this function. The data to but into the subpaket should be +// * in buffer with a length of buflen. +// */ +//void +//build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, +// const byte *buffer, size_t buflen ) +//{ +// +// byte *data; +// size_t hlen, dlen, nlen; +// int found=0; +// int critical, hashed, realloced; +// size_t n, n0; +// +// critical = (type & SIGSUBPKT_FLAG_CRITICAL); +// type &= ~SIGSUBPKT_FLAG_CRITICAL; +// +// if( type == SIGSUBPKT_NOTATION ) +// ; /* we allow multiple packets */ +// else if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) ) +// found = 1; +// else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen ))) +// found = 2; +// +// if( found ) +// log_bug("build_sig_packet: update nyi\n"); +// if( (buflen+1) >= 8384 ) +// nlen = 5; +// else if( (buflen+1) >= 192 ) +// nlen = 2; +// else +// nlen = 1; +// +// switch( type ) { +// case SIGSUBPKT_SIG_CREATED: +// case SIGSUBPKT_PRIV_ADD_SIG: +// case SIGSUBPKT_PREF_SYM: +// case SIGSUBPKT_PREF_HASH: +// case SIGSUBPKT_PREF_COMPR: +// case SIGSUBPKT_KS_FLAGS: +// case SIGSUBPKT_KEY_EXPIRE: +// case SIGSUBPKT_NOTATION: +// case SIGSUBPKT_POLICY: +// hashed = 1; break; +// default: hashed = 0; break; +// } +// +// if( hashed ) { +// n0 = sig->hashed_data ? ((*sig->hashed_data << 8) +// | sig->hashed_data[1]) : 0; +// n = n0 + nlen + 1 + buflen; /* length, type, buffer */ +// realloced = !!sig->hashed_data; +// data = sig->hashed_data ? m_realloc( sig->hashed_data, n+2 ) +// : m_alloc( n+2 ); +// } +// else { +// n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8) +// | sig->unhashed_data[1]) : 0; +// n = n0 + nlen + 1 + buflen; /* length, type, buffer */ +// realloced = !!sig->unhashed_data; +// data = sig->unhashed_data ? m_realloc( sig->unhashed_data, n+2 ) +// : m_alloc( n+2 ); +// } +// +// if( critical ) +// type |= SIGSUBPKT_FLAG_CRITICAL; +// +// data[0] = (n >> 8) & 0xff; +// data[1] = n & 0xff; +// if( nlen == 5 ) { +// data[n0+2] = 255; +// data[n0+3] = (buflen+1) >> 24; +// data[n0+4] = (buflen+1) >> 16; +// data[n0+5] = (buflen+1) >> 8; +// data[n0+6] = (buflen+1); +// data[n0+7] = type; +// memcpy(data+n0+8, buffer, buflen ); +// } +// else if( nlen == 2 ) { +// data[n0+2] = (buflen+1-192) / 256 + 192; +// data[n0+3] = (buflen+1-192) & 256; +// data[n0+4] = type; +// memcpy(data+n0+5, buffer, buflen ); +// } +// else { +// data[n0+2] = buflen+1; +// data[n0+3] = type; +// memcpy(data+n0+4, buffer, buflen ); +// } +// +// if( hashed ) { +// if( !realloced ) +// m_free(sig->hashed_data); +// sig->hashed_data = data; +// } +// else { +// if( !realloced ) +// m_free(sig->unhashed_data); +// sig->unhashed_data = data; +// } +//} +// +///**************** +// * Put all the required stuff from SIG into subpackets of sig. +// */ +//void +//build_sig_subpkt_from_sig( PKT_signature *sig ) +//{ +// u32 u; +// byte buf[8]; +// +// u = sig->keyid[0]; +// buf[0] = (u >> 24) & 0xff; +// buf[1] = (u >> 16) & 0xff; +// buf[2] = (u >> 8) & 0xff; +// buf[3] = u & 0xff; +// u = sig->keyid[1]; +// buf[4] = (u >> 24) & 0xff; +// buf[5] = (u >> 16) & 0xff; +// buf[6] = (u >> 8) & 0xff; +// buf[7] = u & 0xff; +// build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 ); +// +// u = sig->timestamp; +// buf[0] = (u >> 24) & 0xff; +// buf[1] = (u >> 16) & 0xff; +// buf[2] = (u >> 8) & 0xff; +// buf[3] = u & 0xff; +// build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 ); +//} +// +// +static int +do_signature( IOBUF out, int ctb, PKT_signature *sig ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + trace(); + + if( !sig->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, sig->version ); + if( sig->version < 4 ) + iobuf_put(a, 5 ); /* constant */ + iobuf_put(a, sig->sig_class ); + if( sig->version < 4 ) { + write_32(a, sig->timestamp ); + write_32(a, sig->keyid[0] ); + write_32(a, sig->keyid[1] ); + } + iobuf_put(a, sig->pubkey_algo ); + iobuf_put(a, sig->digest_algo ); + if( sig->version >= 4 ) { + size_t nn; + /* timestamp and keyid must have been packed into the + * subpackets prior to the call of this function, because + * these subpackets are hashed */ + nn = sig->hashed_data?((sig->hashed_data[0]<<8) + |sig->hashed_data[1]) :0; + write_16(a, nn); + if( nn ) + iobuf_write( a, sig->hashed_data+2, nn ); + nn = sig->unhashed_data?((sig->unhashed_data[0]<<8) + |sig->unhashed_data[1]) :0; + write_16(a, nn); + if( nn ) + iobuf_write( a, sig->unhashed_data+2, nn ); + } + iobuf_put(a, sig->digest_start[0] ); + iobuf_put(a, sig->digest_start[1] ); + n = pubkey_get_nsig( sig->pubkey_algo ); + if( !n ) + write_fake_data( a, sig->data[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, sig->data[i] ); + + if( is_RSA(sig->pubkey_algo) && sig->version < 4 ) + write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); + else + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +static int +do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) +{ + int rc = 0; + IOBUF a = iobuf_temp(); + + trace(); + + write_version( a, ctb ); + iobuf_put(a, ops->sig_class ); + iobuf_put(a, ops->digest_algo ); + iobuf_put(a, ops->pubkey_algo ); + write_32(a, ops->keyid[0] ); + write_32(a, ops->keyid[1] ); + iobuf_put(a, ops->last ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +static int +write_16(IOBUF out, u16 a) +{ + trace(); + + iobuf_put(out, a>>8); + if( iobuf_put(out,a) ) + return -1; + return 0; +} + +static int +write_32(IOBUF out, u32 a) +{ + trace(); + + iobuf_put(out, a>> 24); + iobuf_put(out, a>> 16); + iobuf_put(out, a>> 8); + if( iobuf_put(out, a) ) + return -1; + return 0; +} + + +///**************** +// * calculate the length of a header +// */ +//static int +//calc_header_length( u32 len, int new_ctb ) +//{ +// if( !len ) +// return 1; /* only the ctb */ +// +// if( new_ctb ) { +// if( len < 192 ) +// return 2; +// if( len < 8384 ) +// return 3; +// else +// return 6; +// } +// if( len < 256 ) +// return 2; +// if( len < 65536 ) +// return 3; +// +// return 5; +//} +// +/**************** + * Write the CTB and the packet length + */ +static int +write_header( IOBUF out, int ctb, u32 len ) +{ + trace(); + + return write_header2( out, ctb, len, 0, 1 ); +} + + +static int +write_sign_packet_header( IOBUF out, int ctb, u32 len ) +{ + trace(); + + /* work around a bug in the pgp read function for signature packets, + * which are not correctly coded and silently assume at some + * point 2 byte length headers.*/ + iobuf_put(out, 0x89 ); + iobuf_put(out, len >> 8 ); + return iobuf_put(out, len ) == -1 ? -1:0; +} + +/**************** + * if HDRLEN is > 0, try to build a header of this length. + * we need this, so that we can hash packets without reading them again. + */ +static int +write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ) +{ + trace(); + + if( ctb & 0x40 ) + return write_new_header( out, ctb, len, hdrlen ); + + if( hdrlen ) { + if( !len ) + ctb |= 3; + else if( hdrlen == 2 && len < 256 ) + ; + else if( hdrlen == 3 && len < 65536 ) + ctb |= 1; + else + ctb |= 2; + } + else { + if( !len ) + ctb |= 3; + else if( len < 256 ) + ; + else if( len < 65536 ) + ctb |= 1; + else + ctb |= 2; + } + if( iobuf_put(out, ctb ) ) + return -1; + if( !len ) { + if( blkmode ) + iobuf_set_block_mode(out, 8196 ); + } + else { + if( ctb & 2 ) { + iobuf_put(out, len >> 24 ); + iobuf_put(out, len >> 16 ); + } + if( ctb & 3 ) + iobuf_put(out, len >> 8 ); + if( iobuf_put(out, len ) ) + return -1; + } + return 0; +} + + +static int +write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) +{ + trace(); + + if( hdrlen ) + log_bug("can't cope with hdrlen yet\n"); + + if( iobuf_put(out, ctb ) ) + return -1; + if( !len ) { + iobuf_set_partial_block_mode(out, 512 ); + } + else { + if( len < 192 ) { + if( iobuf_put(out, len ) ) + return -1; + } + else if( len < 8384 ) { + len -= 192; + if( iobuf_put( out, (len / 256) + 192) ) + return -1; + if( iobuf_put( out, (len % 256) ) ) + return -1; + } + else { + if( iobuf_put( out, 0xff ) ) + return -1; + if( iobuf_put( out, (len >> 24)&0xff ) ) + return -1; + if( iobuf_put( out, (len >> 16)&0xff ) ) + return -1; + if( iobuf_put( out, (len >> 8)&0xff ) ) + return -1; + if( iobuf_put( out, len & 0xff ) ) + return -1; + } + } + return 0; +} + +static int +write_version( IOBUF out, int ctb ) +{ + trace(); + + if( iobuf_put( out, 3 ) ) + return -1; + return 0; +} + diff -Nru a/security/cryptomark/gnupg/cipher/Makefile b/security/cryptomark/gnupg/cipher/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,99 @@ +# ====================================================================== +# +# Immunix CryptoMark Module +# Copyright 1998, 1999, 2000 Wirex Communications & +# Oregon Graduate Institute +# +# Written by Steve Beattie and +# Greg Kroah-Hartman +# +# ====================================================================== + +# stuff to make a release tarball +VERSION = 0.1 +NAME = cryptomark +MISC_FILES = Makefile BUGS NOTES CHANGELOG README + +# +# Determine if the user is using a StackGuarded compiler, and if so, set +# the switch to turn off the canary death handler option. +# +CANARY_FLAG = $(shell if $(CC) -fno-canary-all-functions -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-canary-all-functions"; fi) +CANARY_FLAG += $(shell if $(CC) -mno-terminator-canary -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-terminator-canary"; fi) + +# Comment/uncomment the following line to enable/disable debugging +#DEBUG = y + +# Change it here or specify it on the "make" commandline +INCLUDEDIR = /usr/include + +ifeq ($(DEBUG),y) + DEBFLAGS = -O -g -DDEBUG_IMMUNIX_MMFS +else + DEBFLAGS = -O2 +endif + +CFLAGS = -malign-loops=2 -malign-jumps=2 -malign-functions=2 -D__KERNEL__ \ + -DMODULE -Wall -Wstrict-prototypes $(CANARY_FLAG) \ + -fomit-frame-pointer $(DEBFLAGS) +CFLAGS += -I$(INCLUDEDIR) +LINKER=ld -r + + +# get the kernel version from the include file +# we need this to determine where to put the module for installation. +KERNEL_VERSION = $(shell grep UTS_RELEASE $(INCLUDEDIR)/linux/version.h | cut -f 2 -d \" ) + +# macro for the immunix header file for us lazy typers +IMMUNIX_H = $(INCLUDEDIR)/linux/immunix.h + + +TARGETS = $(CRYPTOMARK) +CRYPTOMARK = cryptomark.o +OBJS = md.o construct.o dynload.o sha1.o md5.o rmd160.o pubkey.o elgamal.o + + + +all: $(TARGETS) + +mainproc.o: mainproc.c + +main.o: main.c + +iobuf.o: iobuf.c + +armor.o: armor.c + +calc_sig.o: calc_sig.c cryptomark.h $(IMMUNIX_H) + +verify.o: verify.c cryptomark.h $(IMMUNIX_H) + +sysctl.o: sysctl.c subdomain.h + +list.o: list.c subdomain.h info.h + +prefetch.o: prefetch.c subdomain.h + +info.o: info.c info.h info_p.h + + +$(CRYPTOMARK): $(OBJS) + $(LINKER) -o $@ $(OBJS) + +clean: + rm -f *.o *.ver *~ + +install: all + -mkdir /lib/modules/$(KERNEL_VERSION)/ + -mkdir /lib/modules/$(KERNEL_VERSION)/misc/ + cp $(TARGETS) /lib/modules/$(KERNEL_VERSION)/misc/ + +release: + -rm -rf $(NAME)-$(VERSION) + mkdir $(NAME)-$(VERSION) + cp *.c $(NAME)-$(VERSION) + cp *.h $(NAME)-$(VERSION) + cp $(MISC_FILES) $(NAME)-$(VERSION) + tar czv -f $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION) + rm -rf $(NAME)-$(VERSION) + diff -Nru a/security/cryptomark/gnupg/cipher/bithelp.h b/security/cryptomark/gnupg/cipher/bithelp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/bithelp.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,41 @@ +/* bithelp.h - Some bit manipulation helpers + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_BITHELP_H +#define G10_BITHELP_H + + +/**************** + * Rotate a 32 bit integer by n bytes + */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol( u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + + +#endif /*G10_BITHELP_H*/ diff -Nru a/security/cryptomark/gnupg/cipher/construct.c b/security/cryptomark/gnupg/cipher/construct.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/construct.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,20 @@ +/* automatically generated by configure - do not edit */ + +//void rndlinux_constructor(void); +void sha1_constructor(void); +void rmd160_constructor(void); +void md5_constructor(void); + +void +cipher_modules_constructor(void) +{ + static int done = 0; + if( done ) + return; + done = 1; + +// rndlinux_constructor(); + sha1_constructor(); + rmd160_constructor(); + md5_constructor(); +} diff -Nru a/security/cryptomark/gnupg/cipher/dynload.c b/security/cryptomark/gnupg/cipher/dynload.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/dynload.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,603 @@ +/* dynload.c - load cipher extensions + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#ifdef HAVE_DL_DLOPEN +// #include +//#elif defined(HAVE_DLD_DLD_LINK) +// #include +//#elif defined(HAVE_DL_SHL_LOAD) +// #include +// #include +//#endif +#include "../util.h" +#include "../cipher.h" +#include "dynload.h" + +#ifdef WITH_SYMBOL_UNDERSCORE + #define SYMBOL_VERSION "_gnupgext_version" + #define SYMBOL_ENUM "_gnupgext_enum_func" +#else + #define SYMBOL_VERSION "gnupgext_version" + #define SYMBOL_ENUM "gnupgext_enum_func" +#endif + + +#ifndef RTLD_NOW + #define RTLD_NOW 1 +#endif + +#ifdef HAVE_DL_SHL_LOAD /* HPUX has shl_load instead of dlopen */ +#define HAVE_DL_DLOPEN +#define dlopen(PATHNAME,MODE) \ + ((void *) shl_load(PATHNAME, DYNAMIC_PATH | \ + (((MODE) & RTLD_NOW) ? BIND_IMMEDIATE : BIND_DEFERRED), 0L)) +#define dlclose(HANDLE) shl_unload((shl_t) (HANDLE)) +#define dlerror() (errno == 0 ? NULL : strerror(errno)) + +static void * +dlsym(void *handle, char *name) +{ + void *addr; + if (shl_findsym((shl_t *)&handle,name,(short)TYPE_UNDEFINED,&addr) != 0) { + return NULL; + } + return addr; +} +#endif /*HAVE_DL_SHL_LOAD*/ + + + +typedef struct ext_list { + struct ext_list *next; + int internal; + #ifdef HAVE_DL_DLOPEN + void *handle; /* handle from dlopen() */ + #else + int handle; /* if the function has been loaded, this is true */ + #endif + int failed; /* already tried but failed */ + void * (*enumfunc)(int, int*, int*, int*); + char *hintstr; /* pointer into name */ + char name[1]; +} *EXTLIST; + +static EXTLIST extensions; + +typedef struct { + EXTLIST r; + int seq1; + int seq2; + void *sym; + int reqalgo; +} ENUMCONTEXT; + + +//#ifdef HAVE_DLD_DLD_LINK +//static char *mainpgm_path; +//static int did_dld_init; +//static int dld_available; +//#endif +// +// +///**************** +// * Register an extension module. The last registered module will +// * be loaded first. A name may have a list of classes +// * appended; e.g: +// * mymodule.so(1:17,3:20,3:109) +// * means that this module provides digest algorithm 17 and public key +// * algorithms 20 and 109. This is only a hint but if it is there the +// * loader may decide to only load a module which claims to have a +// * requested algorithm. +// * +// * mainpgm is the path to the program which wants to load a module +// * it is only used in some environments. +// */ +//void +//register_cipher_extension( const char *mainpgm, const char *fname ) +//{ +// EXTLIST r, el, intex; +// char *p, *pe; +// +// #ifdef HAVE_DLD_DLD_LINK +// if( !mainpgm_path && mainpgm && *mainpgm ) +// mainpgm_path = m_strdup(mainpgm); +// #endif +// if( *fname != '/' ) { /* do tilde expansion etc */ +// char *tmp; +// +// if( strchr(fname, '/') ) +// tmp = make_filename(fname, NULL); +// else +// tmp = make_filename(GNUPG_LIBDIR, fname, NULL); +// el = m_alloc_clear( sizeof *el + strlen(tmp) ); +// strcpy(el->name, tmp ); +// m_free(tmp); +// } +// else { +// el = m_alloc_clear( sizeof *el + strlen(fname) ); +// strcpy(el->name, fname ); +// } +// /* check whether we have a class hint */ +// if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) { +// *p = *pe = 0; +// el->hintstr = p+1; +// } +// else +// el->hintstr = NULL; +// +// /* check that it is not already registered */ +// intex = NULL; +// for(r = extensions; r; r = r->next ) { +// if( !compare_filenames(r->name, el->name) ) { +// log_info("extension `%s' already registered\n", el->name ); +// m_free(el); +// return; +// } +// else if( r->internal ) +// intex = r; +// } +// /* and register */ +// /* we put them after the internal extension modules */ +// /* this is so that the external modules do not get loaded */ +// /* as soon as the internal modules are requested */ +// if( intex ) { +// el->next = intex->next; +// intex->next = el; +// } +// else { +// el->next = extensions; +// extensions = el; +// } +//} + +void +register_internal_cipher_extension( + const char *module_id, + void * (*enumfunc)(int, int*, int*, int*) + ) +{ + EXTLIST r, el; + + trace(); + + el = m_alloc_clear( sizeof *el + strlen(module_id) ); + strcpy(el->name, module_id ); + el->internal = 1; + + /* check that it is not already registered */ + for(r = extensions; r; r = r->next ) { + if( !compare_filenames(r->name, el->name) ) { + log_info("extension `%s' already registered\n", el->name ); + m_free(el); + return; + } + } + /* and register */ + el->enumfunc = enumfunc; + #ifdef HAVE_DL_DLOPEN + el->handle = (void*)1; + #else + el->handle = 1; + #endif + el->next = extensions; + extensions = el; +} + + +static int +load_extension( EXTLIST el ) +{ + #ifdef USE_DYNAMIC_LINKING + char **name; + #ifdef HAVE_DL_DLOPEN + const char *err; + int seq = 0; + int class, vers; + void *sym; + #else + unsigned long addr; + int rc; + #endif + + trace(); + + /* make sure we are not setuid */ + if( getuid() != geteuid() ) + log_bug("trying to load an extension while still setuid\n"); + + /* now that we are not setuid anymore, we can safely load modules */ + #ifdef HAVE_DL_DLOPEN + el->handle = dlopen(el->name, RTLD_NOW); + if( !el->handle ) { + log_error("%s: error loading extension: %s\n", el->name, dlerror() ); + goto failure; + } + name = (char**)dlsym(el->handle, SYMBOL_VERSION); + if( (err=dlerror()) ) { + log_error("%s: not a gnupg extension: %s\n", el->name, err ); + goto failure; + } + #else /* have dld */ + if( !did_dld_init ) { + did_dld_init = 1; + if( !mainpgm_path ) + log_error("DLD is not correctly initialized\n"); + else { + rc = dld_init( dld_find_executable(mainpgm_path) ); + if( rc ) + log_error("DLD init failed: %s\n", dld_strerror(rc) ); + else + dld_available = 1; + } + } + if( !dld_available ) { + log_error("%s: DLD not available\n", el->name ); + goto failure; + } + + rc = dld_link( el->name ); + if( rc ) { + log_error("%s: error loading extension: %s\n", + el->name, dld_strerror(rc) ); + goto failure; + } + addr = dld_get_symbol(SYMBOL_VERSION); + if( !addr ) { + log_error("%s: not a gnupg extension: %s\n", + el->name, dld_strerror(dld_errno) ); + goto failure; + } + name = (char**)addr; + #endif + + if( g10_opt_verbose > 1 ) + log_info("%s: %s%s%s%s\n", el->name, *name, + el->hintstr? " (":"", + el->hintstr? el->hintstr:"", + el->hintstr? ")":""); + + #ifdef HAVE_DL_DLOPEN + sym = dlsym(el->handle, SYMBOL_ENUM); + if( (err=dlerror()) ) { + log_error("%s: invalid gnupg extension: %s\n", el->name, err ); + goto failure; + } + el->enumfunc = (void *(*)(int,int*,int*,int*))sym; + #else /* dld */ + addr = dld_get_func(SYMBOL_ENUM); + if( !addr ) { + log_error("%s: invalid gnupg extension: %s\n", + el->name, dld_strerror(dld_errno) ); + goto failure; + } + rc = dld_function_executable_p(SYMBOL_ENUM); + if( rc ) { + log_error("%s: extension function is not executable: %s\n", + el->name, dld_strerror(rc) ); + goto failure; + } + el->enumfunc = (void *(*)(int,int*,int*,int*))addr; + el->handle = 1; /* mark as usable */ + #endif + + #ifdef HAVE_DL_DLOPEN + if( g10_opt_verbose > 2 ) { + /* list the contents of the module */ + while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) { + if( vers != 1 ) { + log_info("%s: ignoring func with version %d\n",el->name,vers); + continue; + } + switch( class ) { + case 11: + case 21: + case 31: + log_info("%s: provides %s algorithm %d\n", el->name, + class == 11? "md" : + class == 21? "cipher" : "pubkey", + *(int*)sym); + break; + default: + /*log_debug("%s: skipping class %d\n", el->name, class);*/ + break; + } + } + } + #endif + return 0; + + failure: + #ifdef HAVE_DL_DLOPEN + if( el->handle ) { + dlclose(el->handle); + el->handle = NULL; + } + #endif + el->failed = 1; + #endif /*USE_DYNAMIC_LINKING*/ + return -1; +} + + + +int +enum_gnupgext_digests( void **enum_context, + int *algo, + const char *(**r_get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ) +{ + EXTLIST r; + ENUMCONTEXT *ctx; + + trace(); + + if( !*enum_context ) { /* init context */ + ctx = m_alloc_clear( sizeof( *ctx ) ); + ctx->r = extensions; + ctx->reqalgo = *algo; + *enum_context = ctx; + } + else if( !algo ) { /* release the context */ + m_free(*enum_context); + *enum_context = NULL; + return 0; + } + else + ctx = *enum_context; + + for( r = ctx->r; r; r = r->next ) { + int class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + /* get a digest info function */ + if( ctx->sym ) + goto inner_loop; + while( (ctx->sym = (*r->enumfunc)(10, &ctx->seq1, &class, &vers)) ) { + void *sym; + /* must check class because enumfunc may be wrong coded */ + if( vers != 1 || class != 10 ) + continue; + inner_loop: + *r_get_info = ctx->sym; + while( (sym = (*r->enumfunc)(11, &ctx->seq2, &class, &vers)) ) { + if( vers != 1 || class != 11 ) + continue; + *algo = *(int*)sym; + ctx->r = r; + return 1; + } + ctx->seq2 = 0; + } + ctx->seq1 = 0; + } + ctx->r = r; + return 0; +} + +const char * +enum_gnupgext_ciphers( void **enum_context, int *algo, + size_t *keylen, size_t *blocksize, size_t *contextsize, + int (**setkeyf)( void *c, byte *key, unsigned keylen ), + void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), + void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) + ) +{ + EXTLIST r; + ENUMCONTEXT *ctx; + const char * (*finfo)(int, size_t*, size_t*, size_t*, + int (**)( void *, byte *, unsigned), + void (**)( void *, byte *, byte *), + void (**)( void *, byte *, byte *)); + + trace(); + + if( !*enum_context ) { /* init context */ + ctx = m_alloc_clear( sizeof( *ctx ) ); + ctx->r = extensions; + *enum_context = ctx; + } + else if( !algo ) { /* release the context */ + m_free(*enum_context); + *enum_context = NULL; + return NULL; + } + else + ctx = *enum_context; + + for( r = ctx->r; r; r = r->next ) { + int class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + /* get a cipher info function */ + if( ctx->sym ) + goto inner_loop; + while( (ctx->sym = (*r->enumfunc)(20, &ctx->seq1, &class, &vers)) ) { + void *sym; + /* must check class because enumfunc may be wrong coded */ + if( vers != 1 || class != 20 ) + continue; + inner_loop: + finfo = ctx->sym; + while( (sym = (*r->enumfunc)(21, &ctx->seq2, &class, &vers)) ) { + const char *algname; + if( vers != 1 || class != 21 ) + continue; + *algo = *(int*)sym; + algname = (*finfo)( *algo, keylen, blocksize, contextsize, + setkeyf, encryptf, decryptf ); + if( algname ) { + ctx->r = r; + return algname; + } + } + ctx->seq2 = 0; + } + ctx->seq1 = 0; + } + ctx->r = r; + return NULL; +} + +const char * +enum_gnupgext_pubkeys( void **enum_context, int *algo, + int *npkey, int *nskey, int *nenc, int *nsig, int *use, + int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ), + int (**check_secret_key)( int algo, MPI *skey ), + int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ), + int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ), + int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), + int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ), + unsigned (**get_nbits)( int algo, MPI *pkey ) ) +{ + EXTLIST r; + ENUMCONTEXT *ctx; + const char * (*finfo)( int, int *, int *, int *, int *, int *, + int (**)( int, unsigned, MPI *, MPI **), + int (**)( int, MPI * ), + int (**)( int, MPI *, MPI , MPI * ), + int (**)( int, MPI *, MPI *, MPI * ), + int (**)( int, MPI *, MPI , MPI * ), + int (**)( int, MPI , MPI *, MPI *, + int (*)(void*,MPI), void *), + unsigned (**)( int , MPI * ) ); + + trace(); + + if( !*enum_context ) { /* init context */ + ctx = m_alloc_clear( sizeof( *ctx ) ); + ctx->r = extensions; + *enum_context = ctx; + } + else if( !algo ) { /* release the context */ + m_free(*enum_context); + *enum_context = NULL; + return NULL; + } + else + ctx = *enum_context; + + for( r = ctx->r; r; r = r->next ) { + int class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + /* get a pubkey info function */ + if( ctx->sym ) + goto inner_loop; + while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) { + void *sym; + if( vers != 1 || class != 30 ) + continue; + inner_loop: + finfo = ctx->sym; + while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) { + const char *algname; + if( vers != 1 || class != 31 ) + continue; + *algo = *(int*)sym; + algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, use, + generate, check_secret_key, encryptf, + decryptf, sign, verify, get_nbits ); + if( algname ) { + ctx->r = r; + return algname; + } + } + ctx->seq2 = 0; + } + ctx->seq1 = 0; + } + ctx->r = r; + return NULL; +} + + +int (* +dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int, + size_t, int) +{ + EXTLIST r; + void *sym; + + trace(); + + for( r = extensions; r; r = r->next ) { + int seq, class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + seq = 0; + while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) { + if( vers != 1 || class != 40 ) + continue; + return (int (*)(void (*)(const void*, size_t, int), int, + size_t, int))sym; + } + } + return NULL; +} + + +void (* +dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int) +{ + EXTLIST r; + void *sym; + + trace(); + + for( r = extensions; r; r = r->next ) { + int seq, class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + seq = 0; + while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) { + if( vers != 1 || class != 41 ) + continue; + return (void (*)( void (*)(const void*, size_t, int), int))sym; + } + } + return NULL; +} + diff -Nru a/security/cryptomark/gnupg/cipher/dynload.h b/security/cryptomark/gnupg/cipher/dynload.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/dynload.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,68 @@ +/* dynload.5 + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_CIPHER_DYNLOAD_H +#define G10_CIPHER_DYNLOAD_H + +#include "../mpi.h" + + +void register_internal_cipher_extension( const char *module_id, + void * (*enumfunc)(int, int*, int*, int*) ); + +int +enum_gnupgext_digests( void **enum_context, + int *algo, + const char *(**r_get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ); + +const char * +enum_gnupgext_ciphers( void **enum_context, int *algo, + size_t *keylen, size_t *blocksize, size_t *contextsize, + int (**setkeyf)( void *c, byte *key, unsigned keylen ), + void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), + void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) + ); + + +const char * +enum_gnupgext_pubkeys( void **enum_context, int *algo, + int *npkey, int *nskey, int *nenc, int *nsig, int *use, + int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ), + int (**check_secret_key)( int algo, MPI *skey ), + int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ), + int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ), + int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), + int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ), + unsigned (**get_nbits)( int algo, MPI *pkey ) ); + + +int (*dynload_getfnc_gather_random(void))( void (*)(const void*, size_t, int), + int, size_t, int); +void (*dynload_getfnc_fast_random_poll(void) + )( void (*)(const void*, size_t, int), int ); + + +/** This function is in construct.c **/ +void cipher_modules_constructor(void); + +#endif /*G10_CIPHER_DYNLOAD_H*/ diff -Nru a/security/cryptomark/gnupg/cipher/elgamal.c b/security/cryptomark/gnupg/cipher/elgamal.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/elgamal.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,614 @@ +/* elgamal.c - ElGamal Public Key encryption + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 476 ff. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../mpi.h" +#include "../cipher.h" +#include "elgamal.h" + +typedef struct { + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ +} ELG_public_key; + + +typedef struct { + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ + MPI x; /* secret exponent */ +} ELG_secret_key; + + +//static void test_keys( ELG_secret_key *sk, unsigned nbits ); +//static MPI gen_k( MPI p ); +//static void generate( ELG_secret_key *sk, unsigned nbits, MPI **factors ); +//static int check_secret_key( ELG_secret_key *sk ); +//static void encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ); +static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ); +//static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey); +static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); + + +//static void +//progress( int c ) +//{ +// fputc( c, stderr ); +//} + + +//static void +//test_keys( ELG_secret_key *sk, unsigned nbits ) +//{ +// ELG_public_key pk; +// MPI test = mpi_alloc( 0 ); +// MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); +// MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); +// MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); +// +// pk.p = sk->p; +// pk.g = sk->g; +// pk.y = sk->y; +// +// /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ +// { char *p = get_random_bits( nbits, 0, 0 ); +// mpi_set_buffer( test, p, (nbits+7)/8, 0 ); +// m_free(p); +// } +// +// encrypt( out1_a, out1_b, test, &pk ); +// decrypt( out2, out1_a, out1_b, sk ); +// if( mpi_cmp( test, out2 ) ) +// log_fatal("ElGamal operation: encrypt, decrypt failed\n"); +// +// sign( out1_a, out1_b, test, sk ); +// if( !verify( out1_a, out1_b, test, &pk ) ) +// log_fatal("ElGamal operation: sign, verify failed\n"); +// +// mpi_free( test ); +// mpi_free( out1_a ); +// mpi_free( out1_b ); +// mpi_free( out2 ); +//} +// +// +///**************** +// * generate a random secret exponent k from prime p, so +// * that k is relatively prime to p-1 +// */ +//static MPI +//gen_k( MPI p ) +//{ +// MPI k = mpi_alloc_secure( 0 ); +// MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); +// MPI p_1 = mpi_copy(p); +// unsigned int nbits = mpi_get_nbits(p); +// unsigned int nbytes = (nbits+7)/8; +// char *rndbuf = NULL; +// +// if( DBG_CIPHER ) +// log_debug("choosing a random k "); +// mpi_sub_ui( p_1, p, 1); +// for(;;) { +// if( DBG_CIPHER ) +// progress('.'); +// if( !rndbuf || nbits < 32 ) { +// m_free(rndbuf); +// rndbuf = get_random_bits( nbits, 1, 1 ); +// } +// else { /* change only some of the higher bits */ +// /* we could imporove this by directly requesting more memory +// * at the first call to get_random_bits() and use this the here +// * maybe it is easier to do this directly in random.c */ +// char *pp = get_random_bits( 32, 1, 1 ); +// memcpy( rndbuf,pp, 4 ); +// m_free(pp); +// } +// mpi_set_buffer( k, rndbuf, nbytes, 0 ); +// +// for(;;) { +// /* make sure that the number is of the exact lenght */ +// if( mpi_test_bit( k, nbits-1 ) ) +// mpi_set_highbit( k, nbits-1 ); +// else { +// mpi_set_highbit( k, nbits-1 ); +// mpi_clear_bit( k, nbits-1 ); +// } +// if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */ +// if( DBG_CIPHER ) +// progress('+'); +// break; /* no */ +// } +// if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ +// if( DBG_CIPHER ) +// progress('-'); +// break; /* no */ +// } +// if( mpi_gcd( temp, k, p_1 ) ) +// goto found; /* okay, k is relatively prime to (p-1) */ +// mpi_add_ui( k, k, 1 ); +// } +// } +// found: +// m_free(rndbuf); +// if( DBG_CIPHER ) +// progress('\n'); +// mpi_free(p_1); +// mpi_free(temp); +// +// return k; +//} +// +///**************** +// * Generate a key pair with a key of size NBITS +// * Returns: 2 structures filles with all needed values +// * and an array with n-1 factors of (p-1) +// */ +//static void +//generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) +//{ +// MPI p; /* the prime */ +// MPI p_min1; +// MPI g; +// MPI x; /* the secret exponent */ +// MPI y; +// MPI temp; +// unsigned qbits; +// byte *rndbuf; +// +// p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); +// temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); +// if( nbits < 512 ) +// qbits = 120; +// else if( nbits <= 1024 ) +// qbits = 160; +// else if( nbits <= 2048 ) +// qbits = 200; +// else +// qbits = 240; +// g = mpi_alloc(1); +// p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); +// mpi_sub_ui(p_min1, p, 1); +// +// +// /* select a random number which has these properties: +// * 0 < x < p-1 +// * This must be a very good random number because this is the +// * secret part. The prime is public and may be shared anyway, +// * so a random generator level of 1 is used for the prime. +// */ +// x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB ); +// if( DBG_CIPHER ) +// log_debug("choosing a random x "); +// rndbuf = NULL; +// do { +// if( DBG_CIPHER ) +// progress('.'); +// if( rndbuf ) { /* change only some of the higher bits */ +// if( nbits < 16 ) {/* should never happen ... */ +// m_free(rndbuf); +// rndbuf = get_random_bits( nbits, 2, 1 ); +// } +// else { +// char *r = get_random_bits( 16, 2, 1 ); +// memcpy(rndbuf, r, 16/8 ); +// m_free(r); +// } +// } +// else +// rndbuf = get_random_bits( nbits, 2, 1 ); +// mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 ); +// mpi_clear_highbit( x, nbits+1 ); +// } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); +// m_free(rndbuf); +// +// y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); +// mpi_powm( y, g, x, p ); +// +// if( DBG_CIPHER ) { +// progress('\n'); +// log_mpidump("elg p= ", p ); +// log_mpidump("elg g= ", g ); +// log_mpidump("elg y= ", y ); +// log_mpidump("elg x= ", x ); +// } +// +// /* copy the stuff to the key structures */ +// sk->p = p; +// sk->g = g; +// sk->y = y; +// sk->x = x; +// +//// /* now we can test our keys (this should never fail!) */ +//// test_keys( sk, nbits - 64 ); +// +// mpi_free( p_min1 ); +// mpi_free( temp ); +//} +// +// +///**************** +// * Test whether the secret key is valid. +// * Returns: if this is a valid key. +// */ +//static int +//check_secret_key( ELG_secret_key *sk ) +//{ +// int rc; +// MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); +// +// mpi_powm( y, sk->g, sk->x, sk->p ); +// rc = !mpi_cmp( y, sk->y ); +// mpi_free( y ); +// return rc; +//} +// +// +//static void +//encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) +//{ +// MPI k; +// +// /* Note: maybe we should change the interface, so that it +// * is possible to check that input is < p and return an +// * error code. +// */ +// +// k = gen_k( pkey->p ); +// mpi_powm( a, pkey->g, k, pkey->p ); +// /* b = (y^k * input) mod p +// * = ((y^k mod p) * (input mod p)) mod p +// * and because input is < p +// * = ((y^k mod p) * input) mod p +// */ +// mpi_powm( b, pkey->y, k, pkey->p ); +// mpi_mulm( b, b, input, pkey->p ); +// #if 0 +// if( DBG_CIPHER ) { +// log_mpidump("elg encrypted y= ", pkey->y); +// log_mpidump("elg encrypted p= ", pkey->p); +// log_mpidump("elg encrypted k= ", k); +// log_mpidump("elg encrypted M= ", input); +// log_mpidump("elg encrypted a= ", a); +// log_mpidump("elg encrypted b= ", b); +// } +// #endif +// mpi_free(k); +//} +// +// +// + +static void +decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) +{ + MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); + + trace(); + + /* output = b/(a^x) mod p */ + + mpi_powm( t1, a, skey->x, skey->p ); + mpi_invm( t1, t1, skey->p ); + mpi_mulm( output, b, t1, skey->p ); + #if 0 + if( DBG_CIPHER ) { + log_mpidump("elg decrypted x= ", skey->x); + log_mpidump("elg decrypted p= ", skey->p); + log_mpidump("elg decrypted a= ", a); + log_mpidump("elg decrypted b= ", b); + log_mpidump("elg decrypted M= ", output); + } + #endif + mpi_free(t1); +} + + +///**************** +// * Make an Elgamal signature out of INPUT +// */ +// +//static void +//sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) +//{ +// MPI k; +// MPI t = mpi_alloc( mpi_get_nlimbs(a) ); +// MPI inv = mpi_alloc( mpi_get_nlimbs(a) ); +// MPI p_1 = mpi_copy(skey->p); +// +// /* +// * b = (t * inv) mod (p-1) +// * b = (t * inv(k,(p-1),(p-1)) mod (p-1) +// * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) +// * +// */ +// mpi_sub_ui(p_1, p_1, 1); +// k = gen_k( skey->p ); +// mpi_powm( a, skey->g, k, skey->p ); +// mpi_mul(t, skey->x, a ); +// mpi_subm(t, input, t, p_1 ); +// while( mpi_is_neg(t) ) { +// BUG(); /* That is nonsense code - left over from a very early test?*/ +// mpi_add(t, t, p_1); +// } +// mpi_invm(inv, k, p_1 ); +// mpi_mulm(b, t, inv, p_1 ); +// +// #if 0 +// if( DBG_CIPHER ) { +// log_mpidump("elg sign p= ", skey->p); +// log_mpidump("elg sign g= ", skey->g); +// log_mpidump("elg sign y= ", skey->y); +// log_mpidump("elg sign x= ", skey->x); +// log_mpidump("elg sign k= ", k); +// log_mpidump("elg sign M= ", input); +// log_mpidump("elg sign a= ", a); +// log_mpidump("elg sign b= ", b); +// } +// #endif +// mpi_free(k); +// mpi_free(t); +// mpi_free(inv); +// mpi_free(p_1); +//} +// + +/**************** + * Returns true if the signature composed of A and B is valid. + */ +static int +verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) +{ + int rc; + MPI t1; + MPI t2; + MPI base[4]; + MPI exp[4]; + + trace(); + + if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) + return 0; /* assertion 0 < a < p failed */ + + t1 = mpi_alloc( mpi_get_nlimbs(a) ); + t2 = mpi_alloc( mpi_get_nlimbs(a) ); + + #if 0 + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + mpi_powm( t1, pkey->y, a, pkey->p ); + mpi_powm( t2, a, b, pkey->p ); + mpi_mulm( t1, t1, t2, pkey->p ); + + /* t2 = g ^ input mod p */ + mpi_powm( t2, pkey->g, input, pkey->p ); + + rc = !mpi_cmp( t1, t2 ); + #elif 0 + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + base[0] = pkey->y; exp[0] = a; + base[1] = a; exp[1] = b; + base[2] = NULL; exp[2] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); + + /* t2 = g ^ input mod p */ + mpi_powm( t2, pkey->g, input, pkey->p ); + + rc = !mpi_cmp( t1, t2 ); + #else + /* t1 = g ^ - input * y ^ a * a ^ b mod p */ + mpi_invm(t2, pkey->g, pkey->p ); + base[0] = t2 ; exp[0] = input; + base[1] = pkey->y; exp[1] = a; + base[2] = a; exp[2] = b; + base[3] = NULL; exp[3] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); + rc = !mpi_cmp_ui( t1, 1 ); + + #endif + + mpi_free(t1); + mpi_free(t2); + return rc; +} + +/********************************************* + ************** interface ****************** + *********************************************/ + +//int +//elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +//{ +// ELG_secret_key sk; +// +// if( !is_ELGAMAL(algo) ) +// return G10ERR_PUBKEY_ALGO; +// +// generate( &sk, nbits, retfactors ); +// skey[0] = sk.p; +// skey[1] = sk.g; +// skey[2] = sk.y; +// skey[3] = sk.x; +// return 0; +//} +// +// +//int +//elg_check_secret_key( int algo, MPI *skey ) +//{ +// ELG_secret_key sk; +// +// if( !is_ELGAMAL(algo) ) +// return G10ERR_PUBKEY_ALGO; +// if( !skey[0] || !skey[1] || !skey[2] || !skey[3] ) +// return G10ERR_BAD_MPI; +// +// sk.p = skey[0]; +// sk.g = skey[1]; +// sk.y = skey[2]; +// sk.x = skey[3]; +// if( !check_secret_key( &sk ) ) +// return G10ERR_BAD_SECKEY; +// +// return 0; +//} +// +// +// +//int +//elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +//{ +// ELG_public_key pk; +// +// if( !is_ELGAMAL(algo) ) +// return G10ERR_PUBKEY_ALGO; +// if( !data || !pkey[0] || !pkey[1] || !pkey[2] ) +// return G10ERR_BAD_MPI; +// +// pk.p = pkey[0]; +// pk.g = pkey[1]; +// pk.y = pkey[2]; +// resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); +// resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); +// encrypt( resarr[0], resarr[1], data, &pk ); +// return 0; +//} + +int +elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +{ + ELG_secret_key sk; + + trace(); + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data[0] || !data[1] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) + return G10ERR_BAD_MPI; + + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); + decrypt( *result, data[0], data[1], &sk ); + return 0; +} + +//int +//elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ) +//{ +// ELG_secret_key sk; +// +// if( !is_ELGAMAL(algo) ) +// return G10ERR_PUBKEY_ALGO; +// if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) +// return G10ERR_BAD_MPI; +// +// sk.p = skey[0]; +// sk.g = skey[1]; +// sk.y = skey[2]; +// sk.x = skey[3]; +// resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); +// resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); +// sign( resarr[0], resarr[1], data, &sk ); +// return 0; +//} +// +int +elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) +{ + ELG_public_key pk; + + trace(); + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data[0] || !data[1] || !hash + || !pkey[0] || !pkey[1] || !pkey[2] ) + return G10ERR_BAD_MPI; + + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + if( !verify( data[0], data[1], hash, &pk ) ) + return G10ERR_BAD_SIGN; + return 0; +} + + + +unsigned +elg_get_nbits( int algo, MPI *pkey ) +{ + trace(); + + if( !is_ELGAMAL(algo) ) + return 0; + return mpi_get_nbits( pkey[0] ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + * Usage: Bit 0 set : allows signing + * 1 set : allows encryption + * NOTE: This function allows signing also for ELG-E, which is not + * okay but a bad hack to allow to work with old gpg keys. The real check + * is done in the gnupg ocde depending on the packet version. + */ +const char * +elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, + int *use ) +{ + *npkey = 3; + *nskey = 4; + *nenc = 2; + *nsig = 2; + + trace(); + + switch( algo ) { + case PUBKEY_ALGO_ELGAMAL: + *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; + return "ELG"; + case PUBKEY_ALGO_ELGAMAL_E: + *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; + return "ELG-E"; + default: *use = 0; return NULL; + } +} + + diff -Nru a/security/cryptomark/gnupg/cipher/elgamal.h b/security/cryptomark/gnupg/cipher/elgamal.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/elgamal.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,35 @@ +/* elgamal.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_ELGAMAL_H +#define G10_ELGAMAL_H + +int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); +int elg_check_secret_key( int algo, MPI *skey ); +int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); +int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ); +int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ); +unsigned elg_get_nbits( int algo, MPI *pkey ); +const char *elg_get_info( int algo, int *npkey, int *nskey, + int *nenc, int *nsig, int *use ); + + +#endif /*G10_ELGAMAL_H*/ diff -Nru a/security/cryptomark/gnupg/cipher/md.c b/security/cryptomark/gnupg/cipher/md.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/md.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,524 @@ +/* md.c - message digest dispatcher + * Copyright (C) 1998,1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../../cryptomark_log.h" +//#include +//#include +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../cipher.h" +#include "../errors.h" +#include "dynload.h" +#include "rmd.h" + + +/**************** + * This structure is used for the list of available algorithms + * and for the list of algorithms in MD_HANDLE. + */ +struct md_digest_list_s { + struct md_digest_list_s *next; + const char *name; + int algo; + byte *asnoid; + int asnlen; + int mdlen; + void (*init)( void *c ); + void (*write)( void *c, byte *buf, size_t nbytes ); + void (*final)( void *c ); + byte *(*read)( void *c ); + size_t contextsize; /* allocate this amount of context */ + PROPERLY_ALIGNED_TYPE context; +}; + +static struct md_digest_list_s *digest_list; + + +static struct md_digest_list_s * +new_list_item( int algo, + const char *(*get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)) ) +{ + struct md_digest_list_s *r; + + r = m_alloc_clear( sizeof *r ); + r->algo = algo, + r->name = (*get_info)( algo, &r->contextsize, + &r->asnoid, &r->asnlen, &r->mdlen, + &r->init, &r->write, &r->final, &r->read ); + if( !r->name ) { + m_free(r); + r = NULL; + } + return r; +} + + + +/**************** + * Try to load the modules with the requeste algorithm + * and return true if new modules are available + * If req_alog is -1 try to load all digest algorithms. + */ +static int +load_digest_module( int req_algo ) +{ + static int initialized = 0; + static u32 checked_algos[256/32]; + static int checked_all = 0; + struct md_digest_list_s *r; + void *context = NULL; + int algo; + int any = 0; + const char *(*get_info)( int, size_t*,byte**, int*, int*, + void (**)(void*), + void (**)(void*,byte*,size_t), + void (**)(void*),byte *(**)(void*)); + + if( !initialized ) { + cipher_modules_constructor(); + initialized = 1; + } + algo = req_algo; + if( algo > 255 || !algo ) + return 0; /* algorithm number too high (does not fit into out bitmap)*/ + if( checked_all ) + return 0; /* already called with -1 */ + if( algo < 0 ) + checked_all = 1; + else if( (checked_algos[algo/32] & (1 << (algo%32))) ) + return 0; /* already checked and not found */ + else + checked_algos[algo/32] |= (1 << (algo%32)); + + while( enum_gnupgext_digests( &context, &algo, &get_info ) ) { + if( req_algo != -1 && algo != req_algo ) + continue; + for(r=digest_list; r; r = r->next ) + if( r->algo == algo ) + break; + if( r ) { + log_info("skipping digest %d: already loaded\n", algo ); + continue; + } + r = new_list_item( algo, get_info ); + if( ! r ) { + log_info("skipping digest %d: no name\n", algo ); + continue; + } + /* put it into the list */ + if( g10_opt_verbose > 1 ) + log_info("loaded digest %d\n", algo); + r->next = digest_list; + digest_list = r; + any = 1; + if( req_algo != -1 ) + break; + } + enum_gnupgext_digests( &context, NULL, NULL ); + return any; +} + + + +/**************** + * Map a string to the digest algo + */ +int +string_to_digest_algo( const char *string ) +{ + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) + if( !stricmp( r->name, string ) ) + return r->algo; + } while( !r && load_digest_module(-1) ); + return 0; +} + + +/**************** + * Map a digest algo to a string + */ +const char * +digest_algo_to_string( int algo ) +{ + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + return r->name; + } while( !r && load_digest_module( algo ) ); + return NULL; +} + + +int +check_digest_algo( int algo ) +{ + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + return 0; + } while( !r && load_digest_module(algo) ); + return G10ERR_DIGEST_ALGO; +} + + + +/**************** + * 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; + int bufsize; + + if( secure ) { + bufsize = 512 - sizeof( *hd ); + hd = m_alloc_secure_clear( sizeof *hd + bufsize ); + } + else { + bufsize = 1024 - sizeof( *hd ); + hd = m_alloc_clear( sizeof *hd + bufsize ); + } + + hd->bufsize = bufsize+1; /* hd has already one byte allocated */ + hd->secure = secure; + if( algo ) + md_enable( hd, algo ); +// fast_random_poll(); + return hd; +} + +void +md_enable( MD_HANDLE h, int algo ) +{ + struct md_digest_list_s *r, *ac; + + for( ac=h->list; ac; ac = ac->next ) + if( ac->algo == algo ) + return ; /* already enabled */ + /* find the algorithm */ + do { + for(r = digest_list; r; r = r->next ) + if( r->algo == algo ) + break; + } while( !r && load_digest_module( algo ) ); + if( !r ) { + log_error("md_enable: algorithm %d not available\n", algo ); + return; + } + /* and allocate a new list entry */ + ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize + - sizeof(r->context) ) + : m_alloc( sizeof *ac + r->contextsize + - sizeof(r->context) ); + *ac = *r; + ac->next = h->list; + h->list = ac; + /* and init this instance */ + (*ac->init)( &ac->context.c ); +} + + +MD_HANDLE +md_copy( MD_HANDLE a ) +{ + MD_HANDLE b; + struct md_digest_list_s *ar, *br; + + if( a->bufcount ) + md_write( a, NULL, 0 ); + b = a->secure ? m_alloc_secure( sizeof *b + a->bufsize - 1 ) + : m_alloc( sizeof *b + a->bufsize - 1 ); + memcpy( b, a, sizeof *a + a->bufsize - 1 ); + b->list = NULL; +// b->debug = NULL; + /* and now copy the complete list of algorithms */ + /* I know that the copied list is reversed, but that doesn't matter */ + for( ar=a->list; ar; ar = ar->next ) { + br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize + - sizeof(ar->context) ) + : m_alloc( sizeof *br + ar->contextsize + - sizeof(ar->context) ); + memcpy( br, ar, sizeof(*br) + ar->contextsize + - sizeof(ar->context) ); + br->next = b->list; + b->list = br; + } + +// if( a->debug ) +// md_start_debug( b, "unknown" ); + return b; +} + + +/**************** + * Reset all contexts and discard any buffered stuff. This may be used + * instead of a md_close(); md_open(). + */ +void +md_reset( MD_HANDLE a ) +{ + struct md_digest_list_s *r; + + a->bufcount = a->finalized = 0; + for( r=a->list; r; r = r->next ) { + memset( r->context.c, 0, r->contextsize ); + (*r->init)( &r->context.c ); + } +} + + +void +md_close(MD_HANDLE a) +{ + struct md_digest_list_s *r, *r2; + + if( !a ) + return; +// if( a->debug ) +// md_stop_debug(a); + for(r=a->list; r; r = r2 ) { + r2 = r->next; + m_free(r); + } + m_free(a); +} + + +void +md_write( MD_HANDLE a, byte *inbuf, size_t inlen) +{ + struct md_digest_list_s *r; + +// if( a->debug ) { +// if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 ) +// BUG(); +// if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 ) +// BUG(); +// } + for(r=a->list; r; r = r->next ) { + (*r->write)( &r->context.c, a->buffer, a->bufcount ); + (*r->write)( &r->context.c, inbuf, inlen ); + } + a->bufcount = 0; +} + + + +void +md_final(MD_HANDLE a) +{ + struct md_digest_list_s *r; + + if( a->finalized ) + return; + + if( a->bufcount ) + md_write( a, NULL, 0 ); + + for(r=a->list; r; r = r->next ) { + (*r->final)( &r->context.c ); + } + a->finalized = 1; +} + + +/**************** + * if ALGO is null get the digest for the used algo (which should be only one) + */ +byte * +md_read( MD_HANDLE a, int algo ) +{ + struct md_digest_list_s *r; + + if( !algo ) { /* return the first algorithm */ + if( (r=a->list) ) { + if( r->next ) + log_debug("more than algorithm in md_read(0)\n"); + return (*r->read)( &r->context.c ); + } + } + else { + for(r=a->list; r; r = r->next ) + if( r->algo == algo ) + return (*r->read)( &r->context.c ); + } +// BUG(); + return NULL; +} + + +/**************** + * This function combines md_final and md_read but keeps the context + * intact. This function can be used to calculate intermediate + * digests. The digest is copied into buffer and the digestlength is + * returned. If buffer is NULL only the needed size for buffer is returned. + * buflen gives the max size of buffer. If the buffer is too shourt to + * hold the complete digest, the buffer is filled with as many bytes are + * possible and this value is returned. + */ +int +md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ) +{ + struct md_digest_list_s *r = NULL; + char *context; + char *digest; + + if( a->bufcount ) + md_write( a, NULL, 0 ); + + if( !algo ) { /* return digest for the first algorithm */ + if( (r=a->list) && r->next ) + log_debug("more than algorithm in md_digest(0)\n"); + } + else { + for(r=a->list; r; r = r->next ) + if( r->algo == algo ) + break; + } +// if( !r ) +// BUG(); + + if( !buffer ) + return r->mdlen; + + /* I don't want to change the interface, so I simply work on a copy + * the context (extra overhead - should be fixed)*/ + context = a->secure ? m_alloc_secure( r->contextsize ) + : m_alloc( r->contextsize ); + memcpy( context, r->context.c, r->contextsize ); + (*r->final)( context ); + digest = (*r->read)( context ); + + if( buflen > r->mdlen ) + buflen = r->mdlen; + memcpy( buffer, digest, buflen ); + + m_free(context); + return buflen; +} + + +int +md_get_algo( MD_HANDLE a ) +{ + struct md_digest_list_s *r; + + if( (r=a->list) ) { + if( r->next ) + log_error("WARNING: more than algorithm in md_get_algo()\n"); + return r->algo; + } + return 0; +} + +/**************** + * Return the length of the digest + */ +int +md_digest_length( int algo ) +{ + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) { + if( r->algo == algo ) + return r->mdlen; + } + } while( !r && load_digest_module( algo ) ); + log_error("WARNING: no length for md algo %d\n", algo); + return 0; +} + + +/* Hmmm: add a mode to enumerate the OIDs + * to make g10/sig-check.c more portable */ +const byte * +md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ) +{ + struct md_digest_list_s *r; + + do { + for(r = digest_list; r; r = r->next ) { + if( r->algo == algo ) { + if( asnlen ) + *asnlen = r->asnlen; + if( mdlen ) + *mdlen = r->mdlen; + return r->asnoid; + } + } + } while( !r && load_digest_module( algo ) ); +// log_bug("no asn for md algo %d\n", algo); + return NULL; +} + + +//void +//md_start_debug( MD_HANDLE md, const char *suffix ) +//{ +// static int idx=0; +// char buf[25]; +// +// if( md->debug ) { +// log_debug("Oops: md debug already started\n"); +// return; +// } +// idx++; +// sprintf(buf, "dbgmd-%05d.%.10s", idx, suffix ); +// md->debug = fopen(buf, "w"); +// if( !md->debug ) +// log_debug("md debug: can't open %s\n", buf ); +//} +// +//void +//md_stop_debug( MD_HANDLE md ) +//{ +// if( md->debug ) { +// if( md->bufcount ) +// md_write( md, NULL, 0 ); +// fclose(md->debug); +// md->debug = NULL; +// } +// #ifdef HAVE_U64_TYPEDEF +// { /* a kludge to pull in the __muldi3 for Solaris */ +// volatile u32 a = (u32)(ulong)md; +// volatile u64 b = 42; +// volatile u64 c; +// c = a * b; +// } +// #endif +//} +// diff -Nru a/security/cryptomark/gnupg/cipher/md5.c b/security/cryptomark/gnupg/cipher/md5.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/md5.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,412 @@ +/* md5.c - MD5 Message-Digest Algorithm + * Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc. + * + * according to the definition of MD5 in RFC 1321 from April 1992. + * NOTE: This is *not* the same file as the one from glibc. + * + * This program 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, or (at your option) any + * later version. + * + * This program 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. + */ +/* Written by Ulrich Drepper , 1995. */ +/* heavily modified for GnuPG by */ + +/* Test values: + * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E + * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 + * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 + * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 + */ + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../memory.h" +#include "dynload.h" + +#include "bithelp.h" + + +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 nblocks; + byte buf[64]; + int count; +} MD5_CONTEXT; + + +static void +md5_init( MD5_CONTEXT *ctx ) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + + + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + + +/**************** + * transform n*64 bytes + */ +static void +/*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/ +transform( MD5_CONTEXT *ctx, byte *data ) +{ + u32 correct_words[16]; + u32 A = ctx->A; + u32 B = ctx->B; + u32 C = ctx->C; + u32 D = ctx->D; + u32 *cwp = correct_words; + + #ifdef BIG_ENDIAN_HOST + { int i; + byte *p2, *p1; + for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } + #else + memcpy( correct_words, data, 64 ); + #endif + + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++) + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word about the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen) +{ + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md5_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD5 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md5_final( MD5_CONTEXT *hd ) +{ + u32 t, msb, lsb; + byte *p; + + md5_write(hd, NULL, 0); /* flush */; + + msb = 0; + t = hd->nblocks; + if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */ + msb++; + msb += t >> 26; + t = lsb; + 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->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->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md5_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + 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->##a ; *p++ = hd->##a >> 8; \ + *p++ = hd->##a >> 16; *p++ = hd->##a >> 24; } while(0) + #else /* little endian */ + /*#define X(a) do { *(u32*)p = hd->##a ; p += 4; } while(0)*/ + /* Unixware's cpp doesn't like the above construct so we do it his way: + * (reported by Allan Clark) */ + #define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) + #endif + X(A); + X(B); + X(C); + X(D); + #undef X + +} + +static byte * +md5_read( MD5_CONTEXT *hd ) +{ + return hd->buf; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +md5_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; + + if( algo != 1 ) + return NULL; + + *contextsize = sizeof(MD5_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 16; + *r_init = (void (*)(void *))md5_init; + *r_write = (void (*)(void *, byte*, size_t))md5_write; + *r_final = (void (*)(void *))md5_final; + *r_read = (byte *(*)(void *))md5_read; + + return "MD5"; +} + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "MD5 ($Revision: 1.2 $)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))md5_get_info }, + { 11, 1, 1 }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + do { + if( i >= DIM(func_table) || i < 0 ) + return NULL; + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: case 21: case 31: ret = &func_table[i].value; break; + default: ret = func_table[i].func; break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + return ret; +} + + + + +#ifndef IS_MODULE +void +md5_constructor(void) +{ + register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); +} +#endif + + + +/* end of file */ diff -Nru a/security/cryptomark/gnupg/cipher/pubkey.c b/security/cryptomark/gnupg/cipher/pubkey.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/pubkey.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,601 @@ +/* pubkey.c - pubkey dispatcher + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../errors.h" +#include "../mpi.h" +#include "../cipher.h" +#include "elgamal.h" +//#include "dsa.h" +#include "dynload.h" + + +#define TABLE_SIZE 10 + +struct pubkey_table_s { + const char *name; + int algo; + int npkey; + int nskey; + int nenc; + int nsig; + int use; + int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); + int (*check_secret_key)( int algo, MPI *skey ); + int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ); + int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey ); + int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey ); + int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ); + unsigned (*get_nbits)( int algo, MPI *pkey ); +}; + +static struct pubkey_table_s pubkey_table[TABLE_SIZE]; +static int disabled_algos[TABLE_SIZE]; + + +static int +dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_check_secret_key( int algo, MPI *skey ) +{ log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +{ log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +{ log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey ) +{ log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) +{ log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static unsigned +dummy_get_nbits( int algo, MPI *pkey ) +{ log_bug("no get_nbits() for %d\n", algo ); return 0; } + + +/**************** + * Put the static entries into the table. + * This is out constructor function which fill the table + * of algorithms with the one we have statically linked. + */ +static void +setup_pubkey_table(void) +{ + int i; + + trace(); + + i = 0; + pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL; + pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, + &pubkey_table[i].npkey, + &pubkey_table[i].nskey, + &pubkey_table[i].nenc, + &pubkey_table[i].nsig, + &pubkey_table[i].use ); +// pubkey_table[i].generate = elg_generate; + pubkey_table[i].generate = dummy_generate; +// pubkey_table[i].check_secret_key = elg_check_secret_key; + pubkey_table[i].check_secret_key = dummy_check_secret_key; +// pubkey_table[i].encrypt = elg_encrypt; + pubkey_table[i].encrypt = dummy_encrypt; + pubkey_table[i].decrypt = elg_decrypt; +// pubkey_table[i].sign = elg_sign; + pubkey_table[i].sign = dummy_sign; + pubkey_table[i].verify = elg_verify; + pubkey_table[i].get_nbits = elg_get_nbits; + if( !pubkey_table[i].name ) + BUG(); + i++; + pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E; + pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, + &pubkey_table[i].npkey, + &pubkey_table[i].nskey, + &pubkey_table[i].nenc, + &pubkey_table[i].nsig, + &pubkey_table[i].use ); +// pubkey_table[i].generate = elg_generate; + pubkey_table[i].generate = dummy_generate; +// pubkey_table[i].check_secret_key = elg_check_secret_key; + pubkey_table[i].check_secret_key = dummy_check_secret_key; +// pubkey_table[i].encrypt = elg_encrypt; + pubkey_table[i].encrypt = dummy_encrypt; + pubkey_table[i].decrypt = elg_decrypt; +// pubkey_table[i].sign = elg_sign; + pubkey_table[i].sign = dummy_sign; + pubkey_table[i].verify = elg_verify; + pubkey_table[i].get_nbits = elg_get_nbits; + if( !pubkey_table[i].name ) + BUG(); + i++; +// pubkey_table[i].algo = PUBKEY_ALGO_DSA; +// pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo, +// &pubkey_table[i].npkey, +// &pubkey_table[i].nskey, +// &pubkey_table[i].nenc, +// &pubkey_table[i].nsig, +// &pubkey_table[i].use ); +// pubkey_table[i].generate = dsa_generate; +// pubkey_table[i].check_secret_key = dsa_check_secret_key; +// pubkey_table[i].encrypt = dummy_encrypt; +// pubkey_table[i].decrypt = dummy_decrypt; +// pubkey_table[i].sign = dsa_sign; +// pubkey_table[i].verify = dsa_verify; +// pubkey_table[i].get_nbits = dsa_get_nbits; +// if( !pubkey_table[i].name ) +// BUG(); +// i++; + + for( ; i < TABLE_SIZE; i++ ) + pubkey_table[i].name = NULL; +} + + +/**************** + * Try to load all modules and return true if new modules are available + */ +static int +load_pubkey_modules(void) +{ + static int initialized = 0; + static int done = 0; + void *context = NULL; + struct pubkey_table_s *ct; + int ct_idx; + int i; + const char *name; + int any = 0; + + + trace(); + + if( !initialized ) { + cipher_modules_constructor(); + setup_pubkey_table(); + initialized = 1; + return 1; + } + if( done ) + return 0; + done = 1; + for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) { + if( !ct->name ) + break; + } + if( ct_idx >= TABLE_SIZE-1 ) + BUG(); /* table already full */ + /* now load all extensions */ + while( (name = enum_gnupgext_pubkeys( &context, &ct->algo, + &ct->npkey, &ct->nskey, &ct->nenc, + &ct->nsig, &ct->use, + &ct->generate, + &ct->check_secret_key, + &ct->encrypt, + &ct->decrypt, + &ct->sign, + &ct->verify, + &ct->get_nbits )) ) { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == ct->algo ) + break; + if( pubkey_table[i].name ) { + log_info("skipping pubkey %d: already loaded\n", ct->algo ); + continue; + } + + if( !ct->generate ) ct->generate = dummy_generate; + if( !ct->check_secret_key ) ct->check_secret_key = + dummy_check_secret_key; + if( !ct->encrypt ) ct->encrypt = dummy_encrypt; + if( !ct->decrypt ) ct->decrypt = dummy_decrypt; + if( !ct->sign ) ct->sign = dummy_sign; + if( !ct->verify ) ct->verify = dummy_verify; + if( !ct->get_nbits ) ct->get_nbits= dummy_get_nbits; + /* put it into the table */ + if( g10_opt_verbose > 1 ) + log_info("loaded pubkey %d (%s)\n", ct->algo, name); + ct->name = name; + ct_idx++; + ct++; + any = 1; + /* check whether there are more available table slots */ + if( ct_idx >= TABLE_SIZE-1 ) { + log_info("pubkey table full; ignoring other extensions\n"); + break; + } + } + enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + return any; +} + +// +///**************** +// * Map a string to the pubkey algo +// */ +//int +//string_to_pubkey_algo( const char *string ) +//{ +// int i; +// const char *s; +// +// do { +// for(i=0; (s=pubkey_table[i].name); i++ ) +// if( !stricmp( s, string ) ) +// return pubkey_table[i].algo; +// } while( load_pubkey_modules() ); +// return 0; +//} + + +/**************** + * Map a pubkey algo to a string + */ +const char * +pubkey_algo_to_string( int algo ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].name; + } while( load_pubkey_modules() ); + return NULL; +} + + +//void +//disable_pubkey_algo( int algo ) +//{ +// int i; +// +// for(i=0; i < DIM(disabled_algos); i++ ) { +// if( !disabled_algos[i] || disabled_algos[i] == algo ) { +// disabled_algos[i] = algo; +// return; +// } +// } +// log_fatal("can't disable pubkey algo %d: table full\n", algo ); +//} +// + +int +check_pubkey_algo( int algo ) +{ + trace(); + + return check_pubkey_algo2( algo, 0 ); +} + +/**************** + * a use of 0 means: don't care + */ +int +check_pubkey_algo2( int algo, unsigned use ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + if( (use & PUBKEY_USAGE_SIG) + && !(pubkey_table[i].use & PUBKEY_USAGE_SIG) ) + return G10ERR_WR_PUBKEY_ALGO; + if( (use & PUBKEY_USAGE_ENC) + && !(pubkey_table[i].use & PUBKEY_USAGE_ENC) ) + return G10ERR_WR_PUBKEY_ALGO; + + for(i=0; i < DIM(disabled_algos); i++ ) { + if( disabled_algos[i] == algo ) + return G10ERR_PUBKEY_ALGO; + } + return 0; /* okay */ + } + } while( load_pubkey_modules() ); + return G10ERR_PUBKEY_ALGO; +} + + + + +/**************** + * Return the number of public key material numbers + */ +int +pubkey_get_npkey( int algo ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].npkey; + } while( load_pubkey_modules() ); + if( is_RSA(algo) ) /* special hack, so that we are able to */ + return 2; /* see the RSA keyids */ + return 0; +} + +/**************** + * Return the number of secret key material numbers + */ +int +pubkey_get_nskey( int algo ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nskey; + } while( load_pubkey_modules() ); + if( is_RSA(algo) ) /* special hack, so that we are able to */ + return 6; /* see the RSA keyids */ + return 0; +} + +/**************** + * Return the number of signature material numbers + */ +int +pubkey_get_nsig( int algo ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nsig; + } while( load_pubkey_modules() ); + if( is_RSA(algo) ) /* special hack, so that we are able to */ + return 1; /* see the RSA keyids */ + return 0; +} + +/**************** + * Return the number of encryption material numbers + */ +int +pubkey_get_nenc( int algo ) +{ + int i; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nenc; + } while( load_pubkey_modules() ); + if( is_RSA(algo) ) /* special hack, so that we are able to */ + return 1; /* see the RSA keyids */ + return 0; +} + +///**************** +// * Get the number of nbits from the public key +// */ +//unsigned +//pubkey_nbits( int algo, MPI *pkey ) +//{ +// int i; +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) +// return (*pubkey_table[i].get_nbits)( algo, pkey ); +// } while( load_pubkey_modules() ); +// if( is_RSA(algo) ) /* we always wanna see the length of a key :-) */ +// return mpi_get_nbits( pkey[0] ); +// return 0; +//} +// +// +//int +//pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +//{ +// int i; +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) +// return (*pubkey_table[i].generate)( algo, nbits, +// skey, retfactors ); +// } while( load_pubkey_modules() ); +// return G10ERR_PUBKEY_ALGO; +//} +// +// +//int +//pubkey_check_secret_key( int algo, MPI *skey ) +//{ +// int i; +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) +// return (*pubkey_table[i].check_secret_key)( algo, skey ); +// } while( load_pubkey_modules() ); +// return G10ERR_PUBKEY_ALGO; +//} +// +// +///**************** +// * This is the interface to the public key encryption. +// * Encrypt DATA with PKEY and put it into RESARR which +// * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the +// * algorithm allows this - check with pubkey_get_nenc() ) +// */ +//int +//pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +//{ +// int i, rc; +// +// if( DBG_CIPHER ) { +// log_debug("pubkey_encrypt: algo=%d\n", algo ); +// for(i=0; i < pubkey_get_npkey(algo); i++ ) +// log_mpidump(" pkey:", pkey[i] ); +// log_mpidump(" data:", data ); +// } +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) { +// rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey ); +// goto ready; +// } +// } while( load_pubkey_modules() ); +// rc = G10ERR_PUBKEY_ALGO; +// ready: +// if( !rc && DBG_CIPHER ) { +// for(i=0; i < pubkey_get_nenc(algo); i++ ) +// log_mpidump(" encr:", resarr[i] ); +// } +// return rc; +//} +// +// +// +///**************** +// * This is the interface to the public key decryption. +// * ALGO gives the algorithm to use and this implicitly determines +// * the size of the arrays. +// * result is a pointer to a mpi variable which will receive a +// * newly allocated mpi or NULL in case of an error. +// */ +//int +//pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +//{ +// int i, rc; +// +// *result = NULL; /* so the caller can always do an mpi_free */ +// if( DBG_CIPHER ) { +// log_debug("pubkey_decrypt: algo=%d\n", algo ); +// for(i=0; i < pubkey_get_nskey(algo); i++ ) +// log_mpidump(" skey:", skey[i] ); +// for(i=0; i < pubkey_get_nenc(algo); i++ ) +// log_mpidump(" data:", data[i] ); +// } +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) { +// rc = (*pubkey_table[i].decrypt)( algo, result, data, skey ); +// goto ready; +// } +// } while( load_pubkey_modules() ); +// rc = G10ERR_PUBKEY_ALGO; +// ready: +// if( !rc && DBG_CIPHER ) { +// log_mpidump(" plain:", *result ); +// } +// return rc; +//} +// +// +///**************** +// * This is the interface to the public key signing. +// * Sign data with skey and put the result into resarr which +// * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the +// * algorithm allows this - check with pubkey_get_nsig() ) +// */ +//int +//pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) +//{ +// int i, rc; +// +// if( DBG_CIPHER ) { +// log_debug("pubkey_sign: algo=%d\n", algo ); +// for(i=0; i < pubkey_get_nskey(algo); i++ ) +// log_mpidump(" skey:", skey[i] ); +// log_mpidump(" data:", data ); +// } +// +// do { +// for(i=0; pubkey_table[i].name; i++ ) +// if( pubkey_table[i].algo == algo ) { +// rc = (*pubkey_table[i].sign)( algo, resarr, data, skey ); +// goto ready; +// } +// } while( load_pubkey_modules() ); +// rc = G10ERR_PUBKEY_ALGO; +// ready: +// if( !rc && DBG_CIPHER ) { +// for(i=0; i < pubkey_get_nsig(algo); i++ ) +// log_mpidump(" sig:", resarr[i] ); +// } +// return rc; +//} + +/**************** + * Verify a public key signature. + * Return 0 if the signature is good + */ +int +pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) +{ + int i, rc; + + trace(); + + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + rc = (*pubkey_table[i].verify)( algo, hash, data, pkey, + cmp, opaquev ); + goto ready; + } + } while( load_pubkey_modules() ); + rc = G10ERR_PUBKEY_ALGO; + ready: + return rc; +} + diff -Nru a/security/cryptomark/gnupg/cipher/rmd.h b/security/cryptomark/gnupg/cipher/rmd.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/rmd.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,35 @@ +/* rmd.h - RIPE-MD hash functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_RMD_H +#define G10_RMD_H + + +/* we need this here because random.c must have direct access */ +typedef struct { + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} RMD160_CONTEXT; + +void rmd160_init( RMD160_CONTEXT *hd ); +void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); + +#endif /*G10_RMD_H*/ diff -Nru a/security/cryptomark/gnupg/cipher/rmd160.c b/security/cryptomark/gnupg/cipher/rmd160.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/rmd160.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,655 @@ +/* rmd160.c - RIPE-MD160 + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../memory.h" +#include "rmd.h" +#include "../cipher.h" /* only used for the rmd160_hash_buffer() prototype */ +#include "dynload.h" + +#include "bithelp.h" + +/********************************* + * RIPEMD-160 is not patented, see (as of 25.10.97) + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * Note that the code uses Little Endian byteorder, which is good for + * 386 etc, but we must add some conversion when used on a big endian box. + * + * + * Pseudo-code for RIPEMD-160 + * + * RIPEMD-160 is an iterative hash function that operates on 32-bit words. + * The round function takes as input a 5-word chaining variable and a 16-word + * message block and maps this to a new chaining variable. All operations are + * defined on 32-bit words. Padding is identical to that of MD4. + * + * + * RIPEMD-160: definitions + * + * + * nonlinear functions at bit level: exor, mux, -, mux, - + * + * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) + * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) + * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) + * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) + * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) + * + * + * added constants (hexadecimal) + * + * K(j) = 0x00000000 (0 <= j <= 15) + * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) + * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) + * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) + * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) + * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) + * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) + * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) + * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) + * K'(j) = 0x00000000 (64 <= j <= 79) + * + * + * selection of message word + * + * r(j) = j (0 <= j <= 15) + * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 + * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 + * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 + * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 + * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 + * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 + * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 + * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + * + * + * amount for rotate left (rol) + * + * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 + * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 + * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 + * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 + * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 + * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 + * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 + * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 + * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + * + * + * initial value (hexadecimal) + * + * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; + * h4 = 0xC3D2E1F0; + * + * + * RIPEMD-160: pseudo-code + * + * It is assumed that the message after padding consists of t 16-word blocks + * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. + * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left + * shift (rotate) over s positions. + * + * + * for i := 0 to t-1 { + * A := h0; B := h1; C := h2; D = h3; E = h4; + * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; + * for j := 0 to 79 { + * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; + * A := E; E := D; D := rol_10(C); C := B; B := T; + * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] + [+] K'(j)) [+] E'; + * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; + * } + * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; + * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; + * } + */ + +/* Some examples: + * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 + * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe + * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc + * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 + * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc + * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b + * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 + * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb + * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 + */ + + +void +rmd160_init( RMD160_CONTEXT *hd ) +{ + trace(); + + hd->h0 = 0x67452301; + hd->h1 = 0xEFCDAB89; + hd->h2 = 0x98BADCFE; + hd->h3 = 0x10325476; + hd->h4 = 0xC3D2E1F0; + hd->nblocks = 0; + hd->count = 0; +} + + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform( RMD160_CONTEXT *hd, byte *data ) +{ + u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; + #ifdef BIG_ENDIAN_HOST + u32 x[16]; + + trace(); + + { int i; + byte *p2, *p1; + for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } + #else + #if 0 + u32 *x =(u32*)data; + #else + /* this version is better because it is always aligned; + * The performance penalty on a 586-100 is about 6% which + * is acceptable - because the data is more local it might + * also be possible that this is faster on some machines. + * This function (when compiled with -02 on gcc 2.7.2) + * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; + * [measured with a 4MB data and "gpgm --print-md rmd160"] */ + u32 x[16]; + memcpy( x, data, 64 ); + #endif + #endif + + +#define K0 0x00000000 +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8F1BBCDC +#define K4 0xA953FD4E +#define KK0 0x50A28BE6 +#define KK1 0x5C4DD124 +#define KK2 0x6D703EF3 +#define KK3 0x7A6D76E9 +#define KK4 0x00000000 +#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) +#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) +#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) +#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) +#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) +#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ + a = rol(t,s) + e; \ + c = rol(c,10); \ + } while(0) + + /* left lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F0, K0, 0, 11 ); + R( e, a, b, c, d, F0, K0, 1, 14 ); + R( d, e, a, b, c, F0, K0, 2, 15 ); + R( c, d, e, a, b, F0, K0, 3, 12 ); + R( b, c, d, e, a, F0, K0, 4, 5 ); + R( a, b, c, d, e, F0, K0, 5, 8 ); + R( e, a, b, c, d, F0, K0, 6, 7 ); + R( d, e, a, b, c, F0, K0, 7, 9 ); + R( c, d, e, a, b, F0, K0, 8, 11 ); + R( b, c, d, e, a, F0, K0, 9, 13 ); + R( a, b, c, d, e, F0, K0, 10, 14 ); + R( e, a, b, c, d, F0, K0, 11, 15 ); + R( d, e, a, b, c, F0, K0, 12, 6 ); + R( c, d, e, a, b, F0, K0, 13, 7 ); + R( b, c, d, e, a, F0, K0, 14, 9 ); + R( a, b, c, d, e, F0, K0, 15, 8 ); + R( e, a, b, c, d, F1, K1, 7, 7 ); + R( d, e, a, b, c, F1, K1, 4, 6 ); + R( c, d, e, a, b, F1, K1, 13, 8 ); + R( b, c, d, e, a, F1, K1, 1, 13 ); + R( a, b, c, d, e, F1, K1, 10, 11 ); + R( e, a, b, c, d, F1, K1, 6, 9 ); + R( d, e, a, b, c, F1, K1, 15, 7 ); + R( c, d, e, a, b, F1, K1, 3, 15 ); + R( b, c, d, e, a, F1, K1, 12, 7 ); + R( a, b, c, d, e, F1, K1, 0, 12 ); + R( e, a, b, c, d, F1, K1, 9, 15 ); + R( d, e, a, b, c, F1, K1, 5, 9 ); + R( c, d, e, a, b, F1, K1, 2, 11 ); + R( b, c, d, e, a, F1, K1, 14, 7 ); + R( a, b, c, d, e, F1, K1, 11, 13 ); + R( e, a, b, c, d, F1, K1, 8, 12 ); + R( d, e, a, b, c, F2, K2, 3, 11 ); + R( c, d, e, a, b, F2, K2, 10, 13 ); + R( b, c, d, e, a, F2, K2, 14, 6 ); + R( a, b, c, d, e, F2, K2, 4, 7 ); + R( e, a, b, c, d, F2, K2, 9, 14 ); + R( d, e, a, b, c, F2, K2, 15, 9 ); + R( c, d, e, a, b, F2, K2, 8, 13 ); + R( b, c, d, e, a, F2, K2, 1, 15 ); + R( a, b, c, d, e, F2, K2, 2, 14 ); + R( e, a, b, c, d, F2, K2, 7, 8 ); + R( d, e, a, b, c, F2, K2, 0, 13 ); + R( c, d, e, a, b, F2, K2, 6, 6 ); + R( b, c, d, e, a, F2, K2, 13, 5 ); + R( a, b, c, d, e, F2, K2, 11, 12 ); + R( e, a, b, c, d, F2, K2, 5, 7 ); + R( d, e, a, b, c, F2, K2, 12, 5 ); + R( c, d, e, a, b, F3, K3, 1, 11 ); + R( b, c, d, e, a, F3, K3, 9, 12 ); + R( a, b, c, d, e, F3, K3, 11, 14 ); + R( e, a, b, c, d, F3, K3, 10, 15 ); + R( d, e, a, b, c, F3, K3, 0, 14 ); + R( c, d, e, a, b, F3, K3, 8, 15 ); + R( b, c, d, e, a, F3, K3, 12, 9 ); + R( a, b, c, d, e, F3, K3, 4, 8 ); + R( e, a, b, c, d, F3, K3, 13, 9 ); + R( d, e, a, b, c, F3, K3, 3, 14 ); + R( c, d, e, a, b, F3, K3, 7, 5 ); + R( b, c, d, e, a, F3, K3, 15, 6 ); + R( a, b, c, d, e, F3, K3, 14, 8 ); + R( e, a, b, c, d, F3, K3, 5, 6 ); + R( d, e, a, b, c, F3, K3, 6, 5 ); + R( c, d, e, a, b, F3, K3, 2, 12 ); + R( b, c, d, e, a, F4, K4, 4, 9 ); + R( a, b, c, d, e, F4, K4, 0, 15 ); + R( e, a, b, c, d, F4, K4, 5, 5 ); + R( d, e, a, b, c, F4, K4, 9, 11 ); + R( c, d, e, a, b, F4, K4, 7, 6 ); + R( b, c, d, e, a, F4, K4, 12, 8 ); + R( a, b, c, d, e, F4, K4, 2, 13 ); + R( e, a, b, c, d, F4, K4, 10, 12 ); + R( d, e, a, b, c, F4, K4, 14, 5 ); + R( c, d, e, a, b, F4, K4, 1, 12 ); + R( b, c, d, e, a, F4, K4, 3, 13 ); + R( a, b, c, d, e, F4, K4, 8, 14 ); + R( e, a, b, c, d, F4, K4, 11, 11 ); + R( d, e, a, b, c, F4, K4, 6, 8 ); + R( c, d, e, a, b, F4, K4, 15, 5 ); + R( b, c, d, e, a, F4, K4, 13, 6 ); + + aa = a; bb = b; cc = c; dd = d; ee = e; + + /* right lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F4, KK0, 5, 8); + R( e, a, b, c, d, F4, KK0, 14, 9); + R( d, e, a, b, c, F4, KK0, 7, 9); + R( c, d, e, a, b, F4, KK0, 0, 11); + R( b, c, d, e, a, F4, KK0, 9, 13); + R( a, b, c, d, e, F4, KK0, 2, 15); + R( e, a, b, c, d, F4, KK0, 11, 15); + R( d, e, a, b, c, F4, KK0, 4, 5); + R( c, d, e, a, b, F4, KK0, 13, 7); + R( b, c, d, e, a, F4, KK0, 6, 7); + R( a, b, c, d, e, F4, KK0, 15, 8); + R( e, a, b, c, d, F4, KK0, 8, 11); + R( d, e, a, b, c, F4, KK0, 1, 14); + R( c, d, e, a, b, F4, KK0, 10, 14); + R( b, c, d, e, a, F4, KK0, 3, 12); + R( a, b, c, d, e, F4, KK0, 12, 6); + R( e, a, b, c, d, F3, KK1, 6, 9); + R( d, e, a, b, c, F3, KK1, 11, 13); + R( c, d, e, a, b, F3, KK1, 3, 15); + R( b, c, d, e, a, F3, KK1, 7, 7); + R( a, b, c, d, e, F3, KK1, 0, 12); + R( e, a, b, c, d, F3, KK1, 13, 8); + R( d, e, a, b, c, F3, KK1, 5, 9); + R( c, d, e, a, b, F3, KK1, 10, 11); + R( b, c, d, e, a, F3, KK1, 14, 7); + R( a, b, c, d, e, F3, KK1, 15, 7); + R( e, a, b, c, d, F3, KK1, 8, 12); + R( d, e, a, b, c, F3, KK1, 12, 7); + R( c, d, e, a, b, F3, KK1, 4, 6); + R( b, c, d, e, a, F3, KK1, 9, 15); + R( a, b, c, d, e, F3, KK1, 1, 13); + R( e, a, b, c, d, F3, KK1, 2, 11); + R( d, e, a, b, c, F2, KK2, 15, 9); + R( c, d, e, a, b, F2, KK2, 5, 7); + R( b, c, d, e, a, F2, KK2, 1, 15); + R( a, b, c, d, e, F2, KK2, 3, 11); + R( e, a, b, c, d, F2, KK2, 7, 8); + R( d, e, a, b, c, F2, KK2, 14, 6); + R( c, d, e, a, b, F2, KK2, 6, 6); + R( b, c, d, e, a, F2, KK2, 9, 14); + R( a, b, c, d, e, F2, KK2, 11, 12); + R( e, a, b, c, d, F2, KK2, 8, 13); + R( d, e, a, b, c, F2, KK2, 12, 5); + R( c, d, e, a, b, F2, KK2, 2, 14); + R( b, c, d, e, a, F2, KK2, 10, 13); + R( a, b, c, d, e, F2, KK2, 0, 13); + R( e, a, b, c, d, F2, KK2, 4, 7); + R( d, e, a, b, c, F2, KK2, 13, 5); + R( c, d, e, a, b, F1, KK3, 8, 15); + R( b, c, d, e, a, F1, KK3, 6, 5); + R( a, b, c, d, e, F1, KK3, 4, 8); + R( e, a, b, c, d, F1, KK3, 1, 11); + R( d, e, a, b, c, F1, KK3, 3, 14); + R( c, d, e, a, b, F1, KK3, 11, 14); + R( b, c, d, e, a, F1, KK3, 15, 6); + R( a, b, c, d, e, F1, KK3, 0, 14); + R( e, a, b, c, d, F1, KK3, 5, 6); + R( d, e, a, b, c, F1, KK3, 12, 9); + R( c, d, e, a, b, F1, KK3, 2, 12); + R( b, c, d, e, a, F1, KK3, 13, 9); + R( a, b, c, d, e, F1, KK3, 9, 12); + R( e, a, b, c, d, F1, KK3, 7, 5); + R( d, e, a, b, c, F1, KK3, 10, 15); + R( c, d, e, a, b, F1, KK3, 14, 8); + R( b, c, d, e, a, F0, KK4, 12, 8); + R( a, b, c, d, e, F0, KK4, 15, 5); + R( e, a, b, c, d, F0, KK4, 10, 12); + R( d, e, a, b, c, F0, KK4, 4, 9); + R( c, d, e, a, b, F0, KK4, 1, 12); + R( b, c, d, e, a, F0, KK4, 5, 5); + R( a, b, c, d, e, F0, KK4, 8, 14); + R( e, a, b, c, d, F0, KK4, 7, 6); + R( d, e, a, b, c, F0, KK4, 6, 8); + R( c, d, e, a, b, F0, KK4, 2, 13); + R( b, c, d, e, a, F0, KK4, 13, 6); + R( a, b, c, d, e, F0, KK4, 14, 5); + R( e, a, b, c, d, F0, KK4, 0, 15); + R( d, e, a, b, c, F0, KK4, 3, 13); + R( c, d, e, a, b, F0, KK4, 9, 11); + R( b, c, d, e, a, F0, KK4, 11, 11); + + + t = hd->h1 + d + cc; + hd->h1 = hd->h2 + e + dd; + hd->h2 = hd->h3 + a + ee; + hd->h3 = hd->h4 + b + aa; + hd->h4 = hd->h0 + c + bb; + hd->h0 = t; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) +{ + trace(); + + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + rmd160_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + +/**************** + * Apply the rmd160 transform function on the buffer which must have + * a length 64 bytes. Do not use this function together with the + * other functions, use rmd160_init to initialize internal variables. + * Returns: 16 bytes in buffer with the mixed contentes of buffer. + */ +void +rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) +{ + char *p = buffer; + trace(); + + transform( hd, buffer ); + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + + +/* The routine terminates the computation + */ + +static void +rmd160_final( RMD160_CONTEXT *hd ) +{ + u32 t, msb, lsb; + byte *p; + + trace(); + + rmd160_write(hd, NULL, 0); /* flush */; + + msb = 0; + t = hd->nblocks; + if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */ + msb++; + msb += t >> 26; + t = lsb; + 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->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->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + rmd160_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + 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) + #else /* little endian */ + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + #endif + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + +static byte * +rmd160_read( RMD160_CONTEXT *hd ) +{ + trace(); + + return hd->buf; +} + + + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ +void +rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) +{ + RMD160_CONTEXT hd; + + trace(); + + rmd160_init( &hd ); + rmd160_write( &hd, (byte*)buffer, length ); + rmd160_final( &hd ); + memcpy( outbuf, hd.buf, 20 ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +rmd160_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + + trace(); + + if( algo != 3 ) + return NULL; + + *contextsize = sizeof(RMD160_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *r_init = (void (*)(void *))rmd160_init; + *r_write = (void (*)(void *, byte*, size_t))rmd160_write; + *r_final = (void (*)(void *))rmd160_final; + *r_read = (byte *(*)(void *))rmd160_read; + + return "RIPEMD160"; +} + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "RMD160 ($Revision: 1.3 $)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))rmd160_get_info }, + { 11, 1, 3 }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + trace(); + + do { + if( i >= DIM(func_table) || i < 0 ) { + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: + case 21: + case 31: + ret = &func_table[i].value; + break; + default: + ret = func_table[i].func; + break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + return ret; +} + + + + +#ifndef IS_MODULE +void +rmd160_constructor(void) +{ + trace(); + + register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); +} +#endif + diff -Nru a/security/cryptomark/gnupg/cipher/sha1.c b/security/cryptomark/gnupg/cipher/sha1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher/sha1.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,426 @@ +/* sha1.c - SHA1 hash function + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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 + */ + + +/* Test vectors: + * + * "abc" + * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D + * + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 + */ + + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "../util.h" +#include "../memory.h" +#include "dynload.h" +#include "bithelp.h" + + +typedef struct { + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} SHA1_CONTEXT; + + + + +void +sha1_init( SHA1_CONTEXT *hd ) +{ + trace(); + + hd->h0 = 0x67452301; + hd->h1 = 0xefcdab89; + hd->h2 = 0x98badcfe; + hd->h3 = 0x10325476; + hd->h4 = 0xc3d2e1f0; + hd->nblocks = 0; + hd->count = 0; +} + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform( SHA1_CONTEXT *hd, byte *data ) +{ + u32 a,b,c,d,e,tm; + u32 x[16]; + + trace(); + + /* get values from the chaining vars */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + + #ifdef BIG_ENDIAN_HOST + memcpy( x, data, 64 ); + #else + { int i; + byte *p2; + for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } + #endif + + +#define K1 0x5A827999L +#define K2 0x6ED9EBA1L +#define K3 0x8F1BBCDCL +#define K4 0xCA62C1D6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) + + +#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ + ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ + , (x[i&0x0f] = (tm << 1) | (tm >> 31)) ) + +#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + + f( b, c, d ) \ + + k \ + + m; \ + b = rol( b, 30 ); \ + } while(0) + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + /* update chainig vars */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) +{ + trace(); + + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + sha1_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + 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. + */ + +static void +sha1_final(SHA1_CONTEXT *hd) +{ + u32 t, msb, lsb; + byte *p; + + trace(); + + sha1_write(hd, NULL, 0); /* flush */; + + msb = 0; + t = hd->nblocks; + if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */ + msb++; + msb += t >> 26; + t = lsb; + 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->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->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + sha1_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + 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 */ + #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) + #endif + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X + +} + +static byte * +sha1_read( SHA1_CONTEXT *hd ) +{ + trace(); + + return hd->buf; +} + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +sha1_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + trace(); + + if( algo != 2 ) + return NULL; + + *contextsize = sizeof(SHA1_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *r_init = (void (*)(void *))sha1_init; + *r_write = (void (*)(void *, byte*, size_t))sha1_write; + *r_final = (void (*)(void *))sha1_final; + *r_read = (byte *(*)(void *))sha1_read; + + return "SHA1"; +} + + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "SHA1 ($Revision: 1.3 $)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))sha1_get_info }, + { 11, 1, 2 }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + trace(); + + do { + if( i >= DIM(func_table) || i < 0 ) { + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: + case 21: + case 31: + ret = &func_table[i].value; + break; + default: + ret = func_table[i].func; + break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + return ret; +} + + + + +#ifndef IS_MODULE +void +sha1_constructor(void) +{ + trace(); + + register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); +} +#endif + diff -Nru a/security/cryptomark/gnupg/cipher.h b/security/cryptomark/gnupg/cipher.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/cipher.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,177 @@ +/* cipher.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_CIPHER_H +#define G10_CIPHER_H + +#define DBG_CIPHER g10c_debug_mode + +#include "mpi.h" +//#include "cipher/random.h" + + +#define CIPHER_ALGO_NONE 0 +#define CIPHER_ALGO_IDEA 1 +#define CIPHER_ALGO_3DES 2 +#define CIPHER_ALGO_CAST5 3 +#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ +#define CIPHER_ALGO_SAFER_SK128 5 +#define CIPHER_ALGO_DES_SK 6 +#define CIPHER_ALGO_TWOFISH 10 /* twofish 256 bit */ +#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */ +#define CIPHER_ALGO_TWOFISH_OLD 102 /* experimental: twofish 128 bit */ +#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ + +#define PUBKEY_ALGO_RSA 1 +#define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ +#define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ +#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/ +#define PUBKEY_ALGO_DSA 17 +#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ + +#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ +#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ + +#define DIGEST_ALGO_MD5 1 +#define DIGEST_ALGO_SHA1 2 +#define DIGEST_ALGO_RMD160 3 +#define DIGEST_ALGO_TIGER 6 + +#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ + || (a)==PUBKEY_ALGO_RSA_S ) +#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) + +typedef struct { + int algo; + int keylen; + byte key[32]; /* this is the largest used keylen (256 bit) */ +} DEK; + +struct cipher_handle_s; +typedef struct cipher_handle_s *CIPHER_HANDLE; + + +#define CIPHER_MODE_ECB 1 +#define CIPHER_MODE_CFB 2 +#define CIPHER_MODE_PHILS_CFB 3 +#define CIPHER_MODE_AUTO_CFB 4 +#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ +#define CIPHER_MODE_CBC 6 + +struct md_digest_list_s; + +struct gcry_md_context { + int secure; +// FILE *debug; + int finalized; + struct md_digest_list_s *list; + int bufcount; + int bufsize; + byte buffer[1]; +}; + +typedef struct gcry_md_context *MD_HANDLE; + + +int g10c_debug_mode; +int g10_opt_verbose; +const char *g10_opt_homedir; + +/*-- dynload.c --*/ +void register_cipher_extension( const char *mainpgm, const char *fname ); + +/*-- md.c --*/ +int string_to_digest_algo( const char *string ); +const char * digest_algo_to_string( int algo ); +int check_digest_algo( int algo ); +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_reset( 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_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ); +int md_get_algo( MD_HANDLE a ); +int md_digest_length( int algo ); +const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); +void md_start_debug( MD_HANDLE a, const char *suffix ); +void md_stop_debug( MD_HANDLE a ); +#define md_is_secure(a) ((a)->secure) +#define md_putc(h,c) \ + do { \ + if( (h)->bufcount == (h)->bufsize ) \ + md_write( (h), NULL, 0 ); \ + (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ + } while(0) +/*-- rmd160.c --*/ +void rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ); + + +/*-- cipher.c --*/ +int string_to_cipher_algo( const char *string ); +const char * cipher_algo_to_string( int algo ); +void disable_cipher_algo( int algo ); +int check_cipher_algo( int algo ); +unsigned cipher_get_keylen( int algo ); +unsigned cipher_get_blocksize( int algo ); +CIPHER_HANDLE cipher_open( int algo, int mode, int secure ); +void cipher_close( CIPHER_HANDLE c ); +int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ); +void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ); +void cipher_encrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_decrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_sync( CIPHER_HANDLE c ); + +/*-- pubkey.c --*/ +#define PUBKEY_MAX_NPKEY 4 +#define PUBKEY_MAX_NSKEY 6 +#define PUBKEY_MAX_NSIG 2 +#define PUBKEY_MAX_NENC 2 + +int string_to_pubkey_algo( const char *string ); +const char * pubkey_algo_to_string( int algo ); +void disable_pubkey_algo( int algo ); +int check_pubkey_algo( int algo ); +int check_pubkey_algo2( int algo, unsigned use ); +int pubkey_get_npkey( int algo ); +int pubkey_get_nskey( int algo ); +int pubkey_get_nsig( int algo ); +int pubkey_get_nenc( int algo ); +unsigned pubkey_nbits( int algo, MPI *pkey ); +int pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); +int pubkey_check_secret_key( int algo, MPI *skey ); +int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); +int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); +int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaque ); + +/*-- smallprime.c --*/ +extern ushort small_prime_numbers[]; + +/*-- primegen.c --*/ +MPI generate_secret_prime( unsigned nbits ); +MPI generate_public_prime( unsigned nbits ); +MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **factors ); + + +#endif /*G10_CIPHER_H*/ diff -Nru a/security/cryptomark/gnupg/errors.h b/security/cryptomark/gnupg/errors.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/errors.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,80 @@ +/* errors.h - erro code + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_ERRORS_H +#define G10_ERRORS_H + +#define G10ERR_GENERAL 1 +#define G10ERR_UNKNOWN_PACKET 2 +#define G10ERR_UNKNOWN_VERSION 3 /* Unknown version (in packet) */ +#define G10ERR_PUBKEY_ALGO 4 /* Unknown pubkey algorithm */ +#define G10ERR_DIGEST_ALGO 5 /* Unknown digest algorithm */ +#define G10ERR_BAD_PUBKEY 6 /* Bad public key */ +#define G10ERR_BAD_SECKEY 7 /* Bad secret key */ +#define G10ERR_BAD_SIGN 8 /* Bad signature */ +#define G10ERR_NO_PUBKEY 9 /* public key not found */ +#define G10ERR_CHECKSUM 10 /* checksum error */ +#define G10ERR_BAD_PASS 11 /* Bad passphrase */ +#define G10ERR_CIPHER_ALGO 12 /* Unknown cipher algorithm */ +#define G10ERR_KEYRING_OPEN 13 +#define G10ERR_INVALID_PACKET 14 +#define G10ERR_INVALID_ARMOR 15 +#define G10ERR_NO_USER_ID 16 +#define G10ERR_NO_SECKEY 17 /* secret key not available */ +#define G10ERR_WRONG_SECKEY 18 /* wrong seckey used */ +#define G10ERR_UNSUPPORTED 19 +#define G10ERR_BAD_KEY 20 /* bad (session) key */ +#define G10ERR_READ_FILE 21 +#define G10ERR_WRITE_FILE 22 +#define G10ERR_COMPR_ALGO 23 /* Unknown compress algorithm */ +#define G10ERR_OPEN_FILE 24 +#define G10ERR_CREATE_FILE 25 +#define G10ERR_PASSPHRASE 26 /* invalid passphrase */ +#define G10ERR_NI_PUBKEY 27 +#define G10ERR_NI_CIPHER 28 +#define G10ERR_SIG_CLASS 29 +#define G10ERR_BAD_MPI 30 +#define G10ERR_RESOURCE_LIMIT 31 +#define G10ERR_INV_KEYRING 32 +#define G10ERR_TRUSTDB 33 /* a problem with the trustdb */ +#define G10ERR_BAD_CERT 34 /* bad certicate */ +#define G10ERR_INV_USER_ID 35 +#define G10ERR_CLOSE_FILE 36 +#define G10ERR_RENAME_FILE 37 +#define G10ERR_DELETE_FILE 38 +#define G10ERR_UNEXPECTED 39 +#define G10ERR_TIME_CONFLICT 40 +#define G10ERR_WR_PUBKEY_ALGO 41 /* unusabe pubkey algo */ +#define G10ERR_FILE_EXISTS 42 +#define G10ERR_WEAK_KEY 43 /* NOTE: hardcoded into the cipher modules */ +#define G10ERR_WRONG_KEYLEN 44 /* NOTE: hardcoded into the cipher modules */ +#define G10ERR_INV_ARG 45 +#define G10ERR_BAD_URI 46 /* syntax error in URI */ +#define G10ERR_INVALID_URI 47 /* e.g. unsupported scheme */ +#define G10ERR_NETWORK 48 /* general network error */ +#define G10ERR_UNKNOWN_HOST 49 +#define G10ERR_SELFTEST_FAILED 50 +#define G10ERR_NOT_ENCRYPTED 51 +#define G10ERR_NOT_PROCESSED 52 + +#ifndef HAVE_STRERROR +char *strerror( int n ); +#endif + +#endif /*G10_ERRORS_H*/ diff -Nru a/security/cryptomark/gnupg/fileutil.c b/security/cryptomark/gnupg/fileutil.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/fileutil.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,162 @@ +/* fileutil.c - file utilities + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "memory.h" +#include "ttyio.h" + + +///*************** +// * Extract from a given path the filename component. +// * +// */ +//char * +//make_basename(const char *filepath) +//{ +// char *p; +// +// if ( !(p=strrchr(filepath, '/')) ) +// #ifdef HAVE_DRIVE_LETTERS +// if ( !(p=strrchr(filepath, '\\')) ) +// if ( !(p=strrchr(filepath, ':')) ) +// #endif +// { +// return m_strdup(filepath); +// } +// +// return m_strdup(p+1); +//} +// +// +// +///*************** +// * Extract from a given filename the path prepended to it. +// * If their isn't a path prepended to the filename, a dot +// * is returned ('.'). +// * +// */ +//char * +//make_dirname(const char *filepath) +//{ +// char *dirname; +// int dirname_length; +// char *p; +// +// if ( !(p=strrchr(filepath, '/')) ) +// #ifdef HAVE_DRIVE_LETTERS +// if ( !(p=strrchr(filepath, '\\')) ) +// if ( !(p=strrchr(filepath, ':')) ) +// #endif +// { +// return m_strdup("."); +// } +// +// dirname_length = p-filepath; +// dirname = m_alloc(dirname_length+1); +// strncpy(dirname, filepath, dirname_length); +// dirname[dirname_length] = 0; +// +// return dirname; +//} +// +// +// +///**************** +// * Construct a filename from the NULL terminated list of parts. +// * Tilde expansion is done here. +// */ +//char * +//make_filename( const char *first_part, ... ) +//{ +// va_list arg_ptr ; +// size_t n; +// const char *s; +// char *name, *home, *p; +// +// va_start( arg_ptr, first_part ) ; +// n = strlen(first_part)+1; +// while( (s=va_arg(arg_ptr, const char *)) ) +// n += strlen(s) + 1; +// va_end(arg_ptr); +// +// home = NULL; +// if( *first_part == '~' && first_part[1] == '/' +// && (home = getenv("HOME")) && *home ) +// n += strlen(home); +// +// name = m_alloc(n); +// p = home ? stpcpy(stpcpy(name,home), first_part+1) +// : stpcpy(name, first_part); +// va_start( arg_ptr, first_part ) ; +// while( (s=va_arg(arg_ptr, const char *)) ) +// p = stpcpy(stpcpy(p,"/"), s); +// va_end(arg_ptr); +// +// return name; +//} +// + +int +compare_filenames( const char *a, const char *b ) +{ + /* ? check whether this is an absolute filename and + * resolve symlinks? + */ + trace(); + + #ifdef HAVE_DRIVE_LETTERS + return stricmp(a,b); + #else + return strcmp(a,b); + #endif +} + + +///**************** +// * A simple function to decide whether the filename is stdout +// * or a real filename. +// */ +//const char * +//print_fname_stdout( const char *s ) +//{ +// if( !s || (*s == '-' && !s[1]) ) +// return "[stdout]"; +// return s; +//} +// +// +//const char * +//print_fname_stdin( const char *s ) +//{ +// if( !s || (*s == '-' && !s[1]) ) +// return "[stdin]"; +// return s; +//} +// +// diff -Nru a/security/cryptomark/gnupg/filter.h b/security/cryptomark/gnupg/filter.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/filter.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,131 @@ +/* filter.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_FILTER_H +#define G10_FILTER_H + +#include "types.h" +#include "cipher.h" + +typedef struct { + MD_HANDLE md; /* catch all */ + MD_HANDLE md2; /* if we want to calculate an alternate hash */ + size_t maxbuf_size; +} md_filter_context_t; + +typedef struct { + /* these fields may be initialized */ + int what; /* what kind of armor headers to write */ + int only_keyblocks; /* skip all headers but ".... key block" */ + const char *hdrlines; /* write these headerlines */ + + /* these fileds must be initialized to zero */ + int no_openpgp_data; /* output flag: "No valid OpenPGP data found" */ + + /* the following fields must be initialized to zero */ + int inp_checked; /* set if the input has been checked */ + int inp_bypass; /* set if the input is not armored */ + int in_cleartext; /* clear text message */ + int not_dash_escaped; /* clear text is not dash escaped */ + int hashes; /* detected hash algorithms */ + int faked; /* we are faking a literal data packet */ + int truncated; /* number of truncated lines */ + int qp_detected; + int pgp2mode; + + byte *buffer; /* malloced buffer */ + unsigned buffer_size; /* and size of this buffer */ + unsigned buffer_len; /* used length of the buffer */ + unsigned buffer_pos; /* read position */ + + byte radbuf[4]; + int idx, idx2; + u32 crc; + + int status; /* an internal state flag */ + int cancel; + int any_data; /* any valid armored data seen */ + int pending_lf; /* used together with faked */ +} armor_filter_context_t; + + +typedef struct { + int status; + void *opaque; /* (used for z_stream) */ + byte *inbuf; + unsigned inbufsize; + byte *outbuf; + unsigned outbufsize; + int algo; /* compress algo */ + int algo1hack; +} compress_filter_context_t; + + +typedef struct { + DEK *dek; + u32 datalen; + CIPHER_HANDLE cipher_hd; + int header; + MD_HANDLE mdc_hash; +} cipher_filter_context_t; + + + +typedef struct { + byte *buffer; /* malloced buffer */ + unsigned buffer_size; /* and size of this buffer */ + unsigned buffer_len; /* used length of the buffer */ + unsigned buffer_pos; /* read position */ + int truncated; /* number of truncated lines */ + int not_dash_escaped; + int escape_from; + MD_HANDLE md; + int pending_lf; + int pending_esc; +} text_filter_context_t; + + +/* encrypt_filter_context_t defined in main.h */ + +/*-- mdfilter.c --*/ +int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); +void free_md_filter_context( md_filter_context_t *mfx ); + +/*-- armor.c --*/ +int use_armor_filter( IOBUF a ); +int armor_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); + +/*-- compress.c --*/ +int compress_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); + +/*-- cipher.c --*/ +int cipher_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); + +/*-- textfilter.c --*/ +int text_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); +int copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, + int escape_dash, int escape_from, int pgp2mode ); + + + +#endif /*G10_FILTER_H*/ diff -Nru a/security/cryptomark/gnupg/free-packet.c b/security/cryptomark/gnupg/free-packet.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/free-packet.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,455 @@ +/* free-packet.c - cleanup stuff for packets + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include "packet.h" +#include "iobuf.h" +#include "mpi.h" +#include "util.h" +#include "cipher.h" +#include "memory.h" +#include "options.h" + +void +free_symkey_enc( PKT_symkey_enc *enc ) +{ + m_free(enc); +} + +void +free_pubkey_enc( PKT_pubkey_enc *enc ) +{ + int n, i; + n = pubkey_get_nenc( enc->pubkey_algo ); + if( !n ) + mpi_free(enc->data[0]); + for(i=0; i < n; i++ ) + mpi_free( enc->data[i] ); + m_free(enc); +} + +void +free_seckey_enc( PKT_signature *sig ) +{ + int n, i; + n = pubkey_get_nsig( sig->pubkey_algo ); + if( !n ) + mpi_free(sig->data[0]); + for(i=0; i < n; i++ ) + mpi_free( sig->data[i] ); + m_free(sig->hashed_data); + m_free(sig->unhashed_data); + m_free(sig); +} + + + +void +release_public_key_parts( PKT_public_key *pk ) +{ + int n, i; + n = pubkey_get_npkey( pk->pubkey_algo ); + if( !n ) + mpi_free(pk->pkey[0]); + for(i=0; i < n; i++ ) { + mpi_free( pk->pkey[i] ); + pk->pkey[i] = NULL; + } + if( pk->namehash ) { + m_free(pk->namehash); + pk->namehash = NULL; + } +} + + +void +free_public_key( PKT_public_key *pk ) +{ + release_public_key_parts( pk ); + m_free(pk); +} + + +static void * +cp_data_block( byte *s ) +{ + byte *d; + u16 len; + + if( !s ) + return NULL; + len = (s[0] << 8) | s[1]; + d = m_alloc( len+2 ); + memcpy(d, s, len+2); + return d; +} + + +PKT_public_key * +copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s, + const byte *namehash ) +{ + int n, i; + + if( !d ) + d = m_alloc(sizeof *d); + memcpy( d, s, sizeof *d ); + if( namehash ) { + d->namehash = m_alloc( 20 ); + memcpy(d->namehash, namehash, 20 ); + } + else if( s->namehash ) { + d->namehash = m_alloc( 20 ); + memcpy(d->namehash, s->namehash, 20 ); + } + n = pubkey_get_npkey( s->pubkey_algo ); + if( !n ) + d->pkey[0] = mpi_copy(s->pkey[0]); + else { + for(i=0; i < n; i++ ) + d->pkey[i] = mpi_copy( s->pkey[i] ); + } + return d; +} + +PKT_public_key * +copy_public_key( PKT_public_key *d, PKT_public_key *s ) +{ + return copy_public_key_new_namehash( d, s, NULL ); +} + +PKT_signature * +copy_signature( PKT_signature *d, PKT_signature *s ) +{ + int n, i; + + if( !d ) + d = m_alloc(sizeof *d); + memcpy( d, s, sizeof *d ); + n = pubkey_get_nsig( s->pubkey_algo ); + if( !n ) + d->data[0] = mpi_copy(s->data[0]); + else { + for(i=0; i < n; i++ ) + d->data[i] = mpi_copy( s->data[i] ); + } + d->hashed_data = cp_data_block(s->hashed_data); + d->unhashed_data = cp_data_block(s->unhashed_data); + return d; +} + + +PKT_user_id * +copy_user_id( PKT_user_id *d, PKT_user_id *s ) +{ + if( !d ) + d = m_alloc(sizeof *d + s->len - 1 ); + memcpy( d, s, sizeof *d + s->len - 1 ); + return d; +} + + + +void +release_secret_key_parts( PKT_secret_key *sk ) +{ + int n, i; + + n = pubkey_get_nskey( sk->pubkey_algo ); + if( !n ) + mpi_free(sk->skey[0]); + for(i=0; i < n; i++ ) { + mpi_free( sk->skey[i] ); + sk->skey[i] = NULL; + } +} + +void +free_secret_key( PKT_secret_key *sk ) +{ + release_secret_key_parts( sk ); + m_free(sk); +} + +PKT_secret_key * +copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) +{ + int n, i; + + if( !d ) + d = m_alloc(sizeof *d); + memcpy( d, s, sizeof *d ); + n = pubkey_get_nskey( s->pubkey_algo ); + if( !n ) + d->skey[0] = mpi_copy(s->skey[0]); + else { + for(i=0; i < n; i++ ) + d->skey[i] = mpi_copy( s->skey[i] ); + } + return d; +} + +void +free_comment( PKT_comment *rem ) +{ + m_free(rem); +} + +void +free_user_id( PKT_user_id *uid ) +{ + if( uid->photo ) + m_free( uid->photo ); + m_free(uid); +} + +void +free_compressed( PKT_compressed *zd ) +{ + if( zd->buf ) { /* have to skip some bytes */ + /* don't have any information about the length, so + * we assume this is the last packet */ + while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 ) + ; + } + m_free(zd); +} + +void +free_encrypted( PKT_encrypted *ed ) +{ + if( ed->buf ) { /* have to skip some bytes */ + if( iobuf_in_block_mode(ed->buf) ) { + while( iobuf_read( ed->buf, NULL, 1<<30 ) != -1 ) + ; + } + else { + while( ed->len ) { /* skip the packet */ + int n = iobuf_read( ed->buf, NULL, ed->len ); + if( n == -1 ) + ed->len = 0; + else + ed->len -= n; + } + } + } + m_free(ed); +} + + +void +free_plaintext( PKT_plaintext *pt ) +{ + if( pt->buf ) { /* have to skip some bytes */ + if( iobuf_in_block_mode(pt->buf) ) { + while( iobuf_read( pt->buf, NULL, 1<<30 ) != -1 ) + ; + } + else { + while( pt->len ) { /* skip the packet */ + int n = iobuf_read( pt->buf, NULL, pt->len ); + if( n == -1 ) + pt->len = 0; + else + pt->len -= n; + } + } + } + m_free(pt); +} + +/**************** + * Free the packet in pkt. + */ +void +free_packet( PACKET *pkt ) +{ + if( !pkt || !pkt->pkt.generic ) + return; + + if( DBG_MEMORY ) + log_debug("free_packet() type=%d\n", pkt->pkttype ); + + switch( pkt->pkttype ) { + case PKT_SIGNATURE: + free_seckey_enc( pkt->pkt.signature ); + break; + case PKT_PUBKEY_ENC: + free_pubkey_enc( pkt->pkt.pubkey_enc ); + break; + case PKT_SYMKEY_ENC: + free_symkey_enc( pkt->pkt.symkey_enc ); + break; + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + free_public_key( pkt->pkt.public_key ); + break; + case PKT_SECRET_KEY: + case PKT_SECRET_SUBKEY: + free_secret_key( pkt->pkt.secret_key ); + break; + case PKT_COMMENT: + free_comment( pkt->pkt.comment ); + break; + case PKT_USER_ID: + free_user_id( pkt->pkt.user_id ); + break; + case PKT_COMPRESSED: + free_compressed( pkt->pkt.compressed); + break; + case PKT_ENCRYPTED: + free_encrypted( pkt->pkt.encrypted ); + break; + case PKT_PLAINTEXT: + free_plaintext( pkt->pkt.plaintext ); + break; + default: + m_free( pkt->pkt.generic ); + break; + } + pkt->pkt.generic = NULL; +} + +///**************** +// * returns 0 if they match. +// */ +//int +//cmp_public_keys( PKT_public_key *a, PKT_public_key *b ) +//{ +// int n, i; +// +// if( a->timestamp != b->timestamp ) +// return -1; +// if( a->version < 4 && a->expiredate != b->expiredate ) +// return -1; +// if( a->pubkey_algo != b->pubkey_algo ) +// return -1; +// +// n = pubkey_get_npkey( b->pubkey_algo ); +// if( !n ) +// return -1; /* can't compare due to unknown algorithm */ +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( a->pkey[i], b->pkey[i] ) ) +// return -1; +// } +// +// return 0; +//} +// +///**************** +// * Returns 0 if they match. +// * We only compare the public parts. +// */ +//int +//cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ) +//{ +// int n, i; +// +// if( a->timestamp != b->timestamp ) +// return -1; +// if( a->version < 4 && a->expiredate != b->expiredate ) +// return -1; +// if( a->pubkey_algo != b->pubkey_algo ) +// return -1; +// +// n = pubkey_get_npkey( b->pubkey_algo ); +// if( !n ) +// return -1; /* can't compare due to unknown algorithm */ +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( a->skey[i], b->skey[i] ) ) +// return -1; +// } +// +// return 0; +//} +// +///**************** +// * Returns 0 if they match. +// */ +//int +//cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ) +//{ +// int n, i; +// +// if( pk->timestamp != sk->timestamp ) +// return -1; +// if( pk->version < 4 && pk->expiredate != sk->expiredate ) +// return -1; +// if( pk->pubkey_algo != sk->pubkey_algo ) +// return -1; +// +// n = pubkey_get_npkey( pk->pubkey_algo ); +// if( !n ) +// return -1; /* can't compare due to unknown algorithm */ +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) ) +// return -1; +// } +// return 0; +//} +// +// +// +//int +//cmp_signatures( PKT_signature *a, PKT_signature *b ) +//{ +// int n, i; +// +// if( a->keyid[0] != b->keyid[0] ) +// return -1; +// if( a->keyid[1] != b->keyid[1] ) +// return -1; +// if( a->pubkey_algo != b->pubkey_algo ) +// return -1; +// +// n = pubkey_get_nsig( a->pubkey_algo ); +// if( !n ) +// return -1; /* can't compare due to unknown algorithm */ +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( a->data[i] , b->data[i] ) ) +// return -1; +// } +// return 0; +//} +// +// +// +///**************** +// * Returns: true if the user ids do not match +// */ +//int +//cmp_user_ids( PKT_user_id *a, PKT_user_id *b ) +//{ +// int res; +// +// res = a->len - b->len; +// if( !res ) +// res = memcmp( a->name, b->name, a->len ); +// return res; +//} +// +// diff -Nru a/security/cryptomark/gnupg/getkey.c b/security/cryptomark/gnupg/getkey.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/getkey.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1985 @@ +/* getkey.c - Get a key from the database + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "packet.h" +#include "memory.h" +#include "iobuf.h" +#include "keydb.h" +#include "options.h" +#include "main.h" +#include "trustdb.h" +#include "i18n.h" + +#define MAX_UNK_CACHE_ENTRIES 1000 /* we use a linked list - so I guess + * this is a reasonable limit */ +#define MAX_PK_CACHE_ENTRIES 50 +#define MAX_UID_CACHE_ENTRIES 50 + +/* A map of the all characters valid used for word_match() + * Valid characters are in in this table converted to uppercase. + * because the upper 128 bytes have special meaning, we assume + * that they are all valid. + * Note: We must use numerical values here in case that this program + * will be converted to those little blue HAL9000s with their strange + * EBCDIC character set (user ids are UTF-8). */ +static const byte word_match_chars[256] = { + /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 40 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 58 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 60 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 68 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 78 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /* 88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + /* 98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + /* a8 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + /* b8 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + /* c8 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + /* d8 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + /* e8 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + /* f8 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +typedef struct { + int mode; + u32 keyid[2]; + byte fprint[20]; + char *namebuf; + const char *name; +} getkey_item_t; + +struct getkey_ctx_s { + /* make an array or a linked list from dome fields */ + int primary; + KBNODE keyblock; + KBPOS kbpos; + int last_rc; + ulong count; + int not_allocated; + int nitems; + getkey_item_t items[1]; +}; + + + + + +#if 0 +static struct { + int any; + int okay_count; + int nokey_count; + int error_count; +} lkup_stats[21]; +#endif + + + +#if MAX_UNK_CACHE_ENTRIES + typedef struct keyid_list { + struct keyid_list *next; + u32 keyid[2]; + } *keyid_list_t; + static keyid_list_t unknown_keyids; + static int unk_cache_entries; /* number of entries in unknown keys cache */ + static int unk_cache_disabled; +#endif + +#if MAX_PK_CACHE_ENTRIES + typedef struct pk_cache_entry { + struct pk_cache_entry *next; + u32 keyid[2]; + PKT_public_key *pk; + } *pk_cache_entry_t; + static pk_cache_entry_t pk_cache; + static int pk_cache_entries; /* number of entries in pk cache */ + static int pk_cache_disabled; +#endif + +#if MAX_UID_CACHE_ENTRIES < 5 + #error we really need the userid cache +#endif +typedef struct user_id_db { + struct user_id_db *next; + u32 keyid[2]; + int len; + char name[1]; +} *user_id_db_t; +static user_id_db_t user_id_db; +static int uid_cache_entries; /* number of entries in uid cache */ + + + +//static char* prepare_word_match( const byte *name ); +static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_kb ); +//static int lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_kb ); +// +// +//#if 0 +//static void +//print_stats() +//{ +// int i; +// for(i=0; i < DIM(lkup_stats); i++ ) { +// if( lkup_stats[i].any ) +// fprintf(stderr, +// "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", +// i, +// lkup_stats[i].okay_count, +// lkup_stats[i].nokey_count, +// lkup_stats[i].error_count ); +// } +//} +//#endif +// + +static void +cache_public_key( PKT_public_key *pk ) +{ + #if MAX_PK_CACHE_ENTRIES + pk_cache_entry_t ce; + u32 keyid[2]; + + trace(); + + if( pk_cache_disabled ) + return; + + if( is_ELGAMAL(pk->pubkey_algo) + || pk->pubkey_algo == PUBKEY_ALGO_DSA + || is_RSA(pk->pubkey_algo) ) { + keyid_from_pk( pk, keyid ); + } + else + return; /* don't know how to get the keyid */ + + for( ce = pk_cache; ce; ce = ce->next ) + if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { + if( DBG_CACHE ) + log_debug("cache_public_key: already in cache\n"); + return; + } + + if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) { + /* fixme: use another algorithm to free some cache slots */ + pk_cache_disabled=1; + if( opt.verbose > 1 ) + log_info("too many entries in pk cache - disabled\n"); + return; + } + pk_cache_entries++; + ce = m_alloc( sizeof *ce ); + ce->next = pk_cache; + pk_cache = ce; + ce->pk = copy_public_key( NULL, pk ); + ce->keyid[0] = keyid[0]; + ce->keyid[1] = keyid[1]; + #endif +} + + +/**************** + * Store the association of keyid and userid + */ +void +cache_user_id( PKT_user_id *uid, u32 *keyid ) +{ + user_id_db_t r; + + trace(); + + for(r=user_id_db; r; r = r->next ) + if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { + if( DBG_CACHE ) + log_debug("cache_user_id: already in cache\n"); + return; + } + + if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) { + /* fixme: use another algorithm to free some cache slots */ + r = user_id_db; + user_id_db = r->next; + m_free(r); + uid_cache_entries--; + } + r = m_alloc( sizeof *r + uid->len-1 ); + r->keyid[0] = keyid[0]; + r->keyid[1] = keyid[1]; + r->len = uid->len; + memcpy(r->name, uid->name, r->len); + r->next = user_id_db; + user_id_db = r; + uid_cache_entries++; +} + +// +//void +//getkey_disable_caches() +//{ +// #if MAX_UNK_CACHE_ENTRIES +// { +// keyid_list_t kl, kl2; +// for( kl = unknown_keyids; kl; kl = kl2 ) { +// kl2 = kl->next; +// m_free(kl); +// } +// unknown_keyids = NULL; +// unk_cache_disabled = 1; +// } +// #endif +// #if MAX_PK_CACHE_ENTRIES +// { +// pk_cache_entry_t ce, ce2; +// +// for( ce = pk_cache; ce; ce = ce2 ) { +// ce2 = ce->next; +// free_public_key( ce->pk ); +// m_free( ce ); +// } +// pk_cache_disabled=1; +// pk_cache_entries = 0; +// pk_cache = NULL; +// } +// #endif +// /* fixme: disable user id cache ? */ +//} +// + +/**************** + * Get a public key and store it into the allocated pk + * can be called with PK set to NULL to just read it into some + * internal structures. + */ +int +get_pubkey( PKT_public_key *pk, u32 *keyid ) +{ + int internal = 0; + int rc = 0; + + trace(); + + #if MAX_UNK_CACHE_ENTRIES + { /* let's see whether we checked the keyid already */ + keyid_list_t kl; + for( kl = unknown_keyids; kl; kl = kl->next ) + if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] ) + return G10ERR_NO_PUBKEY; /* already checked and not found */ + } + #endif + + #if MAX_PK_CACHE_ENTRIES + { /* Try to get it from the cache */ + pk_cache_entry_t ce; + for( ce = pk_cache; ce; ce = ce->next ) { + if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { + if( pk ) + copy_public_key( pk, ce->pk ); + return 0; + } + } + } + #endif + /* more init stuff */ + if( !pk ) { + pk = m_alloc_clear( sizeof *pk ); + internal++; + } + + + /* do a lookup */ + { struct getkey_ctx_s ctx; + memset( &ctx, 0, sizeof ctx ); + ctx.not_allocated = 1; + ctx.nitems = 1; + ctx.items[0].mode = 11; + ctx.items[0].keyid[0] = keyid[0]; + ctx.items[0].keyid[1] = keyid[1]; + rc = lookup_pk( &ctx, pk, NULL ); + get_pubkey_end( &ctx ); + } + if( !rc ) + goto leave; + + #if MAX_UNK_CACHE_ENTRIES + /* not found: store it for future reference */ + if( unk_cache_disabled ) + ; + else if( ++unk_cache_entries > MAX_UNK_CACHE_ENTRIES ) { + unk_cache_disabled = 1; + if( opt.verbose > 1 ) + log_info("too many entries in unk cache - disabled\n"); + } + else { + keyid_list_t kl; + + kl = m_alloc( sizeof *kl ); + kl->keyid[0] = keyid[0]; + kl->keyid[1] = keyid[1]; + kl->next = unknown_keyids; + unknown_keyids = kl; + } + #endif + rc = G10ERR_NO_PUBKEY; + + leave: + if( !rc ) + cache_public_key( pk ); + if( internal ) + free_public_key(pk); + return rc; +} + + +KBNODE +get_pubkeyblock( u32 *keyid ) +{ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + struct getkey_ctx_s ctx; + int rc = 0; + KBNODE keyblock = NULL; + + trace(); + + memset( &ctx, 0, sizeof ctx ); + ctx.not_allocated = 1; + ctx.nitems = 1; + ctx.items[0].mode = 11; + ctx.items[0].keyid[0] = keyid[0]; + ctx.items[0].keyid[1] = keyid[1]; + rc = lookup_pk( &ctx, pk, &keyblock ); + free_public_key(pk); + get_pubkey_end( &ctx ); + + return rc ? NULL : keyblock; +} + + +// +// +///**************** +// * Get a secret key and store it into sk +// */ +//int +//get_seckey( PKT_secret_key *sk, u32 *keyid ) +//{ +// int rc; +// struct getkey_ctx_s ctx; +// +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = 11; +// ctx.items[0].keyid[0] = keyid[0]; +// ctx.items[0].keyid[1] = keyid[1]; +// rc = lookup_sk( &ctx, sk, NULL ); +// get_seckey_end( &ctx ); +// if( !rc ) { +// /* check the secret key (this may prompt for a passprase to +// * unlock the secret key +// */ +// rc = check_secret_key( sk, 0 ); +// } +// +// return rc; +//} +// +// +///**************** +// * Get the primary secret key and store it into sk +// * Note: This function does not unprotect the key! +// */ +//int +//get_primary_seckey( PKT_secret_key *sk, u32 *keyid ) +//{ +// struct getkey_ctx_s ctx; +// int rc; +// +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.primary = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = 11; +// ctx.items[0].keyid[0] = keyid[0]; +// ctx.items[0].keyid[1] = keyid[1]; +// rc = lookup_sk( &ctx, sk, NULL ); +// get_seckey_end( &ctx ); +// return rc; +//} +// +// +// +///**************** +// * Check whether the secret key is available +// * Returns: 0 := key is available +// * G10ERR_NO_SECKEY := not availabe +// */ +//int +//seckey_available( u32 *keyid ) +//{ +// int rc; +// struct getkey_ctx_s ctx; +// PKT_secret_key *sk; +// +// sk = m_alloc_clear( sizeof *sk ); +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = 11; +// ctx.items[0].keyid[0] = keyid[0]; +// ctx.items[0].keyid[1] = keyid[1]; +// rc = lookup_sk( &ctx, sk, NULL ); +// get_seckey_end( &ctx ); +// free_secret_key( sk ); +// return rc; +//} +// +// +// +//static int +//hextobyte( const byte *s ) +//{ +// int c; +// +// if( *s >= '0' && *s <= '9' ) +// c = 16 * (*s - '0'); +// else if( *s >= 'A' && *s <= 'F' ) +// c = 16 * (10 + *s - 'A'); +// else if( *s >= 'a' && *s <= 'f' ) +// c = 16 * (10 + *s - 'a'); +// else +// return -1; +// s++; +// if( *s >= '0' && *s <= '9' ) +// c += *s - '0'; +// else if( *s >= 'A' && *s <= 'F' ) +// c += 10 + *s - 'A'; +// else if( *s >= 'a' && *s <= 'f' ) +// c += 10 + *s - 'a'; +// else +// return -1; +// return c; +//} +// +// +// +///**************** +// * Return the type of the user id: +// * +// * 0 = Invalid user ID +// * 1 = exact match +// * 2 = match a substring +// * 3 = match an email address +// * 4 = match a substring of an email address +// * 5 = match an email address, but compare from end +// * 6 = word match mode +// * 10 = it is a short KEYID (don't care about keyid[0]) +// * 11 = it is a long KEYID +// * 12 = it is a trustdb index (keyid is looked up) +// * 16 = it is a 16 byte fingerprint +// * 20 = it is a 20 byte fingerprint +// * +// * if fprint is not NULL, it should be an array of at least 20 bytes. +// * +// * Rules used: +// * - If the username starts with 8,9,16 or 17 hex-digits (the first one +// * must be in the range 0..9), this is considered a keyid; depending +// * on the length a short or complete one. +// * - If the username starts with 32,33,40 or 41 hex-digits (the first one +// * must be in the range 0..9), this is considered a fingerprint. +// * - If the username starts with a left angle, we assume it is a complete +// * email address and look only at this part. +// * - If the username starts with a '.', we assume it is the ending +// * part of an email address +// * - If the username starts with an '@', we assume it is a part of an +// * email address +// * - If the userid start with an '=' an exact compare is done. +// * - If the userid starts with a '*' a case insensitive substring search is +// * done (This is the default). +// * - If the userid starts with a '+' we will compare individual words +// * and a match requires that all the words are in the userid. +// * Words are delimited by white space or "()<>[]{}.@-+_,;/&!" +// * (note that you can't search for these characters). Compare +// * is not case sensitive. +// */ +// +//int +//classify_user_id( const char *name, u32 *keyid, byte *fprint, +// const char **retstr, size_t *retlen ) +//{ +// const char * s; +// int mode = 0; +// int hexprefix = 0; +// int hexlength; +// +// /* skip leading spaces. FIXME: what is with leading spaces? */ +// for(s = name; *s && isspace(*s); s++ ) +// ; +// +// switch (*s) { +// case 0: /* empty string is an error */ +// return 0; +// +// case '.': /* an email address, compare from end */ +// mode = 5; +// s++; +// break; +// +// case '<': /* an email address */ +// mode = 3; +// break; +// +// case '@': /* part of an email address */ +// mode = 4; +// s++; +// break; +// +// case '=': /* exact compare */ +// mode = 1; +// s++; +// break; +// +// case '*': /* case insensitive substring search */ +// mode = 2; +// s++; +// break; +// +// case '+': /* compare individual words */ +// mode = 6; +// s++; +// break; +// +// case '#': /* local user id */ +// mode = 12; +// s++; +// if (keyid) { +// if (keyid_from_lid(strtoul(s, NULL, 10), keyid)) +// keyid[0] = keyid[1] = 0; +// } +// break; +// +// default: +// if (s[0] == '0' && s[1] == 'x') { +// hexprefix = 1; +// s += 2; +// } +// +// hexlength = strspn(s, "0123456789abcdefABCDEF"); +// +// /* check if a hexadecimal number is terminated by EOS or blank */ +// if (hexlength && s[hexlength] && !isspace(s[hexlength])) { +// if (hexprefix) /* a "0x" prefix without correct */ +// return 0; /* termination is an error */ +// else /* The first chars looked like */ +// hexlength = 0; /* a hex number, but really were not. */ +// } +// +// if (hexlength == 8 || (!hexprefix && hexlength == 9 && *s == '0')){ +// /* short keyid */ +// if (hexlength == 9) +// s++; +// if (keyid) { +// keyid[0] = 0; +// keyid[1] = strtoul( s, NULL, 16 ); +// } +// mode = 10; +// } +// else if (hexlength == 16 || (!hexprefix && hexlength == 17 +// && *s == '0')) { +// /* complete keyid */ +// char buf[9]; +// if (hexlength == 17) +// s++; +// mem2str(buf, s, 9 ); +// keyid[0] = strtoul( buf, NULL, 16 ); +// keyid[1] = strtoul( s+8, NULL, 16 ); +// mode = 11; +// } +// else if (hexlength == 32 || (!hexprefix && hexlength == 33 +// && *s == '0')) { +// /* md5 fingerprint */ +// int i; +// if (hexlength == 33) +// s++; +// if (fprint) { +// memset(fprint+16, 4, 0); +// for (i=0; i < 16; i++, s+=2) { +// int c = hextobyte(s); +// if (c == -1) +// return 0; +// fprint[i] = c; +// } +// } +// mode = 16; +// } +// else if (hexlength == 40 || (!hexprefix && hexlength == 41 +// && *s == '0')) { +// /* sha1/rmd160 fingerprint */ +// int i; +// if (hexlength == 41) +// s++; +// if (fprint) { +// for (i=0; i < 20; i++, s+=2) { +// int c = hextobyte(s); +// if (c == -1) +// return 0; +// fprint[i] = c; +// } +// } +// mode = 20; +// } +// else { +// if (hexprefix) /* This was a hex number with a prefix */ +// return 0; /* and a wrong length */ +// +// mode = 2; /* Default is case insensitive substring search */ +// } +// } +// +// if( retstr ) +// *retstr = s; +// if( retlen ) +// *retlen = strlen(s); +// +// return mode; +//} +// +// +// +///**************** +// * Try to get the pubkey by the userid. This function looks for the +// * first pubkey certificate which has the given name in a user_id. +// * if pk/sk has the pubkey algo set, the function will only return +// * a pubkey with that algo. +// * The caller must provide provide storage for either the pk or the sk. +// * If ret_kb is not NULL the funtion will return the keyblock there. +// */ +// +//static int +//key_byname( GETKEY_CTX *retctx, STRLIST namelist, +// PKT_public_key *pk, PKT_secret_key *sk, KBNODE *ret_kb ) +//{ +// int rc = 0; +// int n; +// STRLIST r; +// GETKEY_CTX ctx; +// +// assert( !pk ^ !sk ); +// +// /* build the search context */ +// /* Performance hint: Use a static buffer if there is only one name */ +// /* and we don't have mode 6 */ +// for(n=0, r=namelist; r; r = r->next ) +// n++; +// ctx = m_alloc_clear( sizeof *ctx + (n-1)*sizeof ctx->items ); +// ctx->nitems = n; +// +// for(n=0, r=namelist; r; r = r->next, n++ ) { +// ctx->items[n].mode = classify_user_id( r->d, +// ctx->items[n].keyid, +// ctx->items[n].fprint, +// &ctx->items[n].name, +// NULL ); +// if( !ctx->items[n].mode ) { +// m_free( ctx ); +// return G10ERR_INV_USER_ID; +// } +// if( ctx->items[n].mode == 6 ) { +// ctx->items[n].namebuf = prepare_word_match(ctx->items[n].name); +// ctx->items[n].name = ctx->items[n].namebuf; +// } +// } +// +// /* and call the lookup function */ +// ctx->primary = 1; /* we want to look for the primary key only */ +// if( sk ) +// rc = lookup_sk( ctx, sk, ret_kb ); +// else +// rc = lookup_pk( ctx, pk, ret_kb ); +// +// if( retctx ) /* caller wants the context */ +// *retctx = ctx; +// else { +// /* Hmmm, why not get_pubkey-end here?? */ +// enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */ +// for(n=0; n < ctx->nitems; n++ ) +// m_free( ctx->items[n].namebuf ); +// m_free( ctx ); +// } +// +// return rc; +//} +// +//int +//get_pubkey_byname( GETKEY_CTX *retctx, PKT_public_key *pk, +// const char *name, KBNODE *ret_keyblock ) +//{ +// int rc; +// STRLIST namelist = NULL; +// +// add_to_strlist( &namelist, name ); +// +// if( !pk ) { +// /* Performance Hint: key_byname should not need a pk here */ +// pk = m_alloc_clear( sizeof *pk ); +// rc = key_byname( retctx, namelist, pk, NULL, ret_keyblock ); +// free_public_key( pk ); +// } +// else +// rc = key_byname( retctx, namelist, pk, NULL, ret_keyblock ); +// +// free_strlist( namelist ); +// return rc; +//} +// +//int +//get_pubkey_bynames( GETKEY_CTX *retctx, PKT_public_key *pk, +// STRLIST names, KBNODE *ret_keyblock ) +//{ +// int rc; +// +// if( !pk ) { +// /* Performance Hint: key_byname should not need a pk here */ +// pk = m_alloc_clear( sizeof *pk ); +// rc = key_byname( retctx, names, pk, NULL, ret_keyblock ); +// free_public_key( pk ); +// } +// else +// rc = key_byname( retctx, names, pk, NULL, ret_keyblock ); +// +// return rc; +//} +// +//int +//get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) +//{ +// int rc; +// +// if( !pk ) { +// /* Performance Hint: lookup_read should not need a pk in this case */ +// pk = m_alloc_clear( sizeof *pk ); +// rc = lookup_pk( ctx, pk, ret_keyblock ); +// free_public_key( pk ); +// } +// else +// rc = lookup_pk( ctx, pk, ret_keyblock ); +// return rc; +//} + +void +get_pubkey_end( GETKEY_CTX ctx ) +{ + trace(); + + if( ctx ) { + int n; + + enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */ + for(n=0; n < ctx->nitems; n++ ) + m_free( ctx->items[n].namebuf ); + if( !ctx->not_allocated ) + m_free( ctx ); + } +} + +///**************** +// * Search for a key with the given fingerprint. +// */ +//int +//get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len) +//{ +// int rc; +// +// if( fprint_len == 20 || fprint_len == 16 ) { +// struct getkey_ctx_s ctx; +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = fprint_len; +// memcpy( ctx.items[0].fprint, fprint, fprint_len ); +// rc = lookup_pk( &ctx, pk, NULL ); +// get_pubkey_end( &ctx ); +// } +// else +// rc = G10ERR_GENERAL; /* Oops */ +// return rc; +//} +// +///**************** +// * Search for a key with the given fingerprint and return the +// * complete keyblock which may have more than only this key. +// */ +//int +//get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, +// size_t fprint_len ) +//{ +// int rc; +// PKT_public_key *pk = m_alloc_clear( sizeof *pk ); +// +// if( fprint_len == 20 || fprint_len == 16 ) { +// struct getkey_ctx_s ctx; +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = fprint_len; +// memcpy( ctx.items[0].fprint, fprint, fprint_len ); +// rc = lookup_pk( &ctx, pk, ret_keyblock ); +// get_pubkey_end( &ctx ); +// } +// else +// rc = G10ERR_GENERAL; /* Oops */ +// +// free_public_key( pk ); +// return rc; +//} +// +// +// +///**************** +// * Search for a key with the given lid and return the complete keyblock +// */ +//int +//get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid ) +//{ +// int rc; +// PKT_public_key *pk = m_alloc_clear( sizeof *pk ); +// struct getkey_ctx_s ctx; +// u32 kid[2]; +// +// if( keyid_from_lid( lid, kid ) ) +// kid[0] = kid[1] = 0; +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = 12; +// ctx.items[0].keyid[0] = kid[0]; +// ctx.items[0].keyid[1] = kid[1]; +// rc = lookup_pk( &ctx, pk, ret_keyblock ); +// get_pubkey_end( &ctx ); +// +// free_public_key( pk ); +// return rc; +//} +// +// +// +// +// +///**************** +// * Get a secret key by name and store it into sk +// * If NAME is NULL use the default key +// */ +//int +//get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect ) +//{ +// STRLIST namelist = NULL; +// int rc; +// +// if( !name && opt.def_secret_key && *opt.def_secret_key ) { +// add_to_strlist( &namelist, opt.def_secret_key ); +// rc = key_byname( NULL, namelist, NULL, sk, NULL ); +// } +// else if( !name ) { /* use the first one as default key */ +// struct getkey_ctx_s ctx; +// +// memset( &ctx, 0, sizeof ctx ); +// ctx.not_allocated = 1; +// ctx.primary = 1; +// ctx.nitems = 1; +// ctx.items[0].mode = 15; +// rc = lookup_sk( &ctx, sk, NULL ); +// get_seckey_end( &ctx ); +// } +// else { +// add_to_strlist( &namelist, name ); +// rc = key_byname( NULL, namelist, NULL, sk, NULL ); +// } +// +// free_strlist( namelist ); +// +// if( !rc && unprotect ) +// rc = check_secret_key( sk, 0 ); +// +// return rc; +//} +// +//int +//get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk, +// STRLIST names, KBNODE *ret_keyblock ) +//{ +// int rc; +// +// if( !sk ) { +// /* Performance Hint: key_byname should not need a sk here */ +// sk = m_alloc_secure_clear( sizeof *sk ); +// rc = key_byname( retctx, names, NULL, sk, ret_keyblock ); +// free_secret_key( sk ); +// } +// else +// rc = key_byname( retctx, names, NULL, sk, ret_keyblock ); +// +// return rc; +//} +// +// +//int +//get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) +//{ +// int rc; +// +// if( !sk ) { +// /* Performance Hint: lookup_read should not need a pk in this case */ +// sk = m_alloc_secure_clear( sizeof *sk ); +// rc = lookup_sk( ctx, sk, ret_keyblock ); +// free_secret_key( sk ); +// } +// else +// rc = lookup_sk( ctx, sk, ret_keyblock ); +// return rc; +//} +// +//void +//get_seckey_end( GETKEY_CTX ctx ) +//{ +// if( ctx ) { +// int n; +// +// enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */ +// for(n=0; n < ctx->nitems; n++ ) +// m_free( ctx->items[n].namebuf ); +// if( !ctx->not_allocated ) +// m_free( ctx ); +// } +//} +// + + +/**************** + * Do a word match (original user id starts with a '+'). + * The pattern is already tokenized to a more suitable format: + * There are only the real words in it delimited by one space + * and all converted to uppercase. + * + * Returns: 0 if all words match. + * + * Note: This algorithm is a straightforward one and not very + * fast. It works for UTF-8 strings. The uidlen should + * be removed but due to the fact that old versions of + * pgp don't use UTF-8 we still use the length; this should + * be fixed in parse-packet (and replace \0 by some special + * UTF-8 encoding) + */ +static int +word_match( const byte *uid, size_t uidlen, const byte *pattern ) +{ + size_t wlen, n; + const byte *p; + const byte *s; + + trace(); + + for( s=pattern; *s; ) { + do { + /* skip leading delimiters */ + while( uidlen && !word_match_chars[*uid] ) + uid++, uidlen--; + /* get length of the word */ + n = uidlen; p = uid; + while( n && word_match_chars[*p] ) + p++, n--; + wlen = p - uid; + /* and compare against the current word from pattern */ + for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) { + if( word_match_chars[*p] != s[n] ) + break; + } + if( n == wlen && (s[n] == ' ' || !s[n]) ) + break; /* found */ + uid += wlen; + uidlen -= wlen; + } while( uidlen ); + if( !uidlen ) + return -1; /* not found */ + + /* advance to next word in pattern */ + for(; *s != ' ' && *s ; s++ ) + ; + if( *s ) + s++ ; + } + return 0; /* found */ +} + +///**************** +// * prepare word word_match; that is parse the name and +// * build the pattern. +// * caller has to free the returned pattern +// */ +//static char* +//prepare_word_match( const byte *name ) +//{ +// byte *pattern, *p; +// int c; +// +// /* the original length is always enough for the pattern */ +// p = pattern = m_alloc(strlen(name)+1); +// do { +// /* skip leading delimiters */ +// while( *name && !word_match_chars[*name] ) +// name++; +// /* copy as long as we don't have a delimiter and convert +// * to uppercase. +// * fixme: how can we handle utf8 uppercasing */ +// for( ; *name && (c=word_match_chars[*name]); name++ ) +// *p++ = c; +// *p++ = ' '; /* append pattern delimiter */ +// } while( *name ); +// p[-1] = 0; /* replace last pattern delimiter by EOS */ +// +// return pattern; +//} +// +// +// + + +static int +compare_name( const char *uid, size_t uidlen, const char *name, int mode ) +{ + int i; + const char *s, *se; + + trace(); + + if( mode == 1 ) { /* exact match */ + for(i=0; name[i] && uidlen; i++, uidlen-- ) + if( uid[i] != name[i] ) + break; + if( !uidlen && !name[i] ) + return 0; /* found */ + } + else if( mode == 2 ) { /* case insensitive substring */ + if( memistr( uid, uidlen, name ) ) + return 0; + } + else if( mode >= 3 && mode <= 5 ) { /* look at the email address */ + for( i=0, s= uid; i < uidlen && *s != '<'; s++, i++ ) + ; + if( i < uidlen ) { + /* skip opening delim and one char and look for the closing one*/ + s++; i++; + for( se=s+1, i++; i < uidlen && *se != '>'; se++, i++ ) + ; + if( i < uidlen ) { + i = se - s; + if( mode == 3 ) { /* exact email address */ + if( strlen(name)-2 == i && !memicmp( s, name+1, i) ) + return 0; + } + else if( mode == 4 ) { /* email substring */ + if( memistr( s, i, name ) ) + return 0; + } + else { /* email from end */ + /* nyi */ + } + } + } + } + else if( mode == 6 ) + return word_match( uid, uidlen, name ); + else + BUG(); + + return -1; /* not found */ +} + + + +/**************** + * Assume that knode points to a public key packet and keyblock is + * the entire keyblock. This function adds all relevant information from + * a selfsignature to the public key. + */ + +static void +merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode, + PKT_public_key *orig_pk ) +{ + PKT_public_key *pk = knode->pkt->pkt.public_key; + PKT_signature *sig; + KBNODE k; + u32 kid[2]; + u32 sigdate = 0; + + trace(); + +// assert( knode->pkt->pkttype == PKT_PUBLIC_KEY +// || knode->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + + if( pk->version < 4 ) + return; /* this is only needed for version >=4 packets */ + + + /* find the selfsignature */ + if( knode->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + k = find_kbnode( keyblock, PKT_PUBLIC_KEY ); + if( !k ) + BUG(); /* keyblock without primary key!!! */ + keyid_from_pk( knode->pkt->pkt.public_key, kid ); + } + else + keyid_from_pk( pk, kid ); + + for(k=knode->next; k; k = k->next ) { + if( k->pkt->pkttype == PKT_SIGNATURE + && (sig=k->pkt->pkt.signature)->sig_class >= 0x10 + && sig->sig_class <= 0x30 + && sig->keyid[0] == kid[0] + && sig->keyid[1] == kid[1] + && sig->version > 3 ) { + /* okay this is a self-signature which can be used. + * We use the latest self-signature. + * FIXME: We should only use this if the signature is valid + * but this is time consuming - we must provide another + * way to handle this + */ + const byte *p; + u32 ed; + + p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); + ed = p? pk->timestamp + buffer_to_u32(p):0; + /* use the latest self signature */ + if( sig->timestamp > sigdate ) { + pk->expiredate = ed; + orig_pk->expiredate = ed; + sigdate = sig->timestamp; + } + /* fixme: add usage etc. to pk */ + } + else if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* stop here */ + } +} + + +/**************** + * merge all selfsignatures with the keys. + */ +void +merge_keys_and_selfsig( KBNODE keyblock ) +{ + PKT_public_key *pk = NULL; + PKT_secret_key *sk = NULL; + PKT_signature *sig; + KBNODE k; + u32 kid[2] = { 0, 0 }; + u32 sigdate = 0; + + trace(); + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + pk = k->pkt->pkt.public_key; sk = NULL; + if( pk->version < 4 ) + pk = NULL; /* not needed for old keys */ + else if( k->pkt->pkttype == PKT_PUBLIC_KEY ) + keyid_from_pk( pk, kid ); + sigdate = 0; + } + else if( k->pkt->pkttype == PKT_SECRET_KEY + || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { + pk = NULL; sk = k->pkt->pkt.secret_key; + if( sk->version < 4 ) + sk = NULL; + else if( k->pkt->pkttype == PKT_SECRET_KEY ) + keyid_from_sk( sk, kid ); + sigdate = 0; + } + else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE + && (sig=k->pkt->pkt.signature)->sig_class >= 0x10 + && sig->sig_class <= 0x30 && sig->version > 3 + && sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) { + /* okay this is a self-signature which can be used. + * FIXME: We should only use this if the signature is valid + * but this is time consuming - we must provide another + * way to handle this + */ + const byte *p; + u32 ed; + + p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); + if( pk ) { + ed = p? pk->timestamp + buffer_to_u32(p):0; + if( sig->timestamp > sigdate ) { + pk->expiredate = ed; + sigdate = sig->timestamp; + } + } + else { + ed = p? sk->timestamp + buffer_to_u32(p):0; + if( sig->timestamp > sigdate ) { + sk->expiredate = ed; + sigdate = sig->timestamp; + } + } + } + } +} + + +static KBNODE +find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name, + int mode, byte *namehash, int *use_namehash ) +{ + KBNODE k, kk; + + trace(); + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_USER_ID + && !compare_name( k->pkt->pkt.user_id->name, + k->pkt->pkt.user_id->len, name, mode)) { + /* we found a matching name, look for the key */ + for(kk=keyblock; kk; kk = kk->next ) { + if( ( kk->pkt->pkttype == PKT_PUBLIC_KEY + || kk->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + && ( !pk->pubkey_algo + || pk->pubkey_algo + == kk->pkt->pkt.public_key->pubkey_algo) + && ( !pk->pubkey_usage + || !check_pubkey_algo2( + kk->pkt->pkt.public_key->pubkey_algo, + pk->pubkey_usage )) + ) + break; + } + if( kk ) { + u32 aki[2]; + keyid_from_pk( kk->pkt->pkt.public_key, aki ); + cache_user_id( k->pkt->pkt.user_id, aki ); + if( k->pkt->pkt.user_id->photo ) + rmd160_hash_buffer( namehash, + k->pkt->pkt.user_id->photo, + k->pkt->pkt.user_id->photolen ); + else + rmd160_hash_buffer( namehash, + k->pkt->pkt.user_id->name, + k->pkt->pkt.user_id->len ); + *use_namehash = 1; + return kk; + } + else if( is_RSA(pk->pubkey_algo) ) + log_error("RSA key cannot be used in this version\n"); + else + log_error("No key for user ID\n"); + } + } + return NULL; +} + +//static KBNODE +//find_by_name_sk( KBNODE keyblock, PKT_secret_key *sk, const char *name, +// int mode ) +//{ +// KBNODE k, kk; +// +// for(k=keyblock; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_USER_ID +// && !compare_name( k->pkt->pkt.user_id->name, +// k->pkt->pkt.user_id->len, name, mode)) { +// /* we found a matching name, look for the key */ +// for(kk=keyblock; kk; kk = kk->next ) { +// if( ( kk->pkt->pkttype == PKT_SECRET_KEY +// || kk->pkt->pkttype == PKT_SECRET_SUBKEY ) +// && ( !sk->pubkey_algo +// || sk->pubkey_algo +// == kk->pkt->pkt.secret_key->pubkey_algo) +// && ( !sk->pubkey_usage +// || !check_pubkey_algo2( +// kk->pkt->pkt.secret_key->pubkey_algo, +// sk->pubkey_usage )) +// ) +// break; +// } +// if( kk ) { +// u32 aki[2]; +// keyid_from_sk( kk->pkt->pkt.secret_key, aki ); +// cache_user_id( k->pkt->pkt.user_id, aki ); +// return kk; +// } +// else if( is_RSA(sk->pubkey_algo) ) +// log_error("RSA key cannot be used in this version\n"); +// else +// log_error("No key for user ID\n"); +// } +// } +// return NULL; +//} +// + +static KBNODE +find_by_keyid( KBNODE keyblock, PKT_public_key *pk, u32 *keyid, int mode ) +{ + KBNODE k; + + trace(); + + if( DBG_CACHE ) + log_debug("lookup keyid=%08lx%08lx req_algo=%d mode=%d\n", + (ulong)keyid[0], (ulong)keyid[1], pk->pubkey_algo, mode ); + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + u32 aki[2]; + keyid_from_pk( k->pkt->pkt.public_key, aki ); + if( DBG_CACHE ) + log_debug(" aki=%08lx%08lx algo=%d\n", + (ulong)aki[0], (ulong)aki[1], + k->pkt->pkt.public_key->pubkey_algo ); + + if( aki[1] == keyid[1] + && ( mode == 10 || aki[0] == keyid[0] ) + && ( !pk->pubkey_algo + || pk->pubkey_algo + == k->pkt->pkt.public_key->pubkey_algo) ){ + KBNODE kk; + /* cache the userid */ + for(kk=keyblock; kk; kk = kk->next ) + if( kk->pkt->pkttype == PKT_USER_ID ) + break; + if( kk ) + cache_user_id( kk->pkt->pkt.user_id, aki ); + else + log_error("No user ID for key\n"); + return k; /* found */ + } + } + } + return NULL; +} + +//static KBNODE +//find_by_keyid_sk( KBNODE keyblock, PKT_secret_key *sk, u32 *keyid, int mode ) +//{ +// KBNODE k; +// +// if( DBG_CACHE ) +// log_debug("lookup_sk keyid=%08lx%08lx req_algo=%d mode=%d\n", +// (ulong)keyid[0], (ulong)keyid[1], sk->pubkey_algo, mode ); +// +// for(k=keyblock; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_SECRET_KEY +// || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { +// u32 aki[2]; +// keyid_from_sk( k->pkt->pkt.secret_key, aki ); +// if( DBG_CACHE ) +// log_debug(" aki=%08lx%08lx algo=%d\n", +// (ulong)aki[0], (ulong)aki[1], +// k->pkt->pkt.secret_key->pubkey_algo ); +// +// if( aki[1] == keyid[1] +// && ( mode == 10 || aki[0] == keyid[0] ) +// && ( !sk->pubkey_algo +// || sk->pubkey_algo +// == k->pkt->pkt.secret_key->pubkey_algo) ){ +// KBNODE kk; +// /* cache the userid */ +// for(kk=keyblock; kk; kk = kk->next ) +// if( kk->pkt->pkttype == PKT_USER_ID ) +// break; +// if( kk ) +// cache_user_id( kk->pkt->pkt.user_id, aki ); +// else +// log_error("No user ID for key\n"); +// return k; /* found */ +// } +// } +// } +// return NULL; +//} +// + +static KBNODE +find_first( KBNODE keyblock, PKT_public_key *pk ) +{ + KBNODE k; + + trace(); + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + { + if( !pk->pubkey_algo + || pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo ) + return k; + } + } + return NULL; +} + +//static KBNODE +//find_first_sk( KBNODE keyblock, PKT_secret_key *sk ) +//{ +// KBNODE k; +// +// for(k=keyblock; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_SECRET_KEY +// || k->pkt->pkttype == PKT_SECRET_SUBKEY ) +// { +// if( !sk->pubkey_algo +// || sk->pubkey_algo == k->pkt->pkt.secret_key->pubkey_algo ) +// return k; +// } +// } +// return NULL; +//} +// + +static KBNODE +find_by_fpr( KBNODE keyblock, PKT_public_key *pk, const char *name, int mode ) +{ + KBNODE k; + + trace(); + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an ); + + if( DBG_CACHE ) { + u32 aki[2]; + keyid_from_pk( k->pkt->pkt.public_key, aki ); + log_debug(" aki=%08lx%08lx algo=%d mode=%d an=%u\n", + (ulong)aki[0], (ulong)aki[1], + k->pkt->pkt.public_key->pubkey_algo, mode, + (unsigned)an ); + } + + if( an == mode + && !memcmp( afp, name, an) + && ( !pk->pubkey_algo + || pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo) ) + return k; + } + } + return NULL; +} + +//static KBNODE +//find_by_fpr_sk( KBNODE keyblock, PKT_secret_key *sk, +// const char *name, int mode ) +//{ +// KBNODE k; +// +// for(k=keyblock; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_SECRET_KEY +// || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { +// byte afp[MAX_FINGERPRINT_LEN]; +// size_t an; +// +// fingerprint_from_sk(k->pkt->pkt.secret_key, afp, &an ); +// +// if( DBG_CACHE ) { +// u32 aki[2]; +// keyid_from_sk( k->pkt->pkt.secret_key, aki ); +// log_debug(" aki=%08lx%08lx algo=%d mode=%d an=%u\n", +// (ulong)aki[0], (ulong)aki[1], +// k->pkt->pkt.secret_key->pubkey_algo, mode, +// (unsigned)an ); +// } +// +// if( an == mode +// && !memcmp( afp, name, an) +// && ( !sk->pubkey_algo +// || sk->pubkey_algo == k->pkt->pkt.secret_key->pubkey_algo) ) +// return k; +// } +// } +// return NULL; +//} +// + +static void +finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash, + int use_namehash, int primary ) +{ +// assert( k->pkt->pkttype == PKT_PUBLIC_KEY +// || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ); +// assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ); + trace(); + + if( primary && !pk->pubkey_usage ) { + copy_public_key_new_namehash( pk, keyblock->pkt->pkt.public_key, + use_namehash? namehash:NULL); + merge_one_pk_and_selfsig( keyblock, keyblock, pk ); + } + else { + if( primary && pk->pubkey_usage + && check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo, + pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) { + /* if the usage is not correct, try to use a subkey */ + KBNODE save_k = k; + + k = NULL; + /* kludge for pgp 5: which doesn't accept type 20: + * try to use a type 16 subkey instead */ + if( pk->pubkey_usage == PUBKEY_USAGE_ENC ) { + for( k = save_k; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY + && k->pkt->pkt.public_key->pubkey_algo + == PUBKEY_ALGO_ELGAMAL_E + && !check_pubkey_algo2( + k->pkt->pkt.public_key->pubkey_algo, + pk->pubkey_usage ) ) + break; + } + } + + if( !k ) { + for(k = save_k ; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY + && !check_pubkey_algo2( + k->pkt->pkt.public_key->pubkey_algo, + pk->pubkey_usage ) ) + break; + } + } + if( !k ) + k = save_k; + else + log_info("using secondary key %08lX " + "instead of primary key %08lX\n", + (ulong)keyid_from_pk( k->pkt->pkt.public_key, NULL), + (ulong)keyid_from_pk( save_k->pkt->pkt.public_key, NULL) + ); + } + + copy_public_key_new_namehash( pk, k->pkt->pkt.public_key, + use_namehash? namehash:NULL); + merge_one_pk_and_selfsig( keyblock, k, pk ); + } +} + +//static void +//finish_lookup_sk( KBNODE keyblock, PKT_secret_key *sk, KBNODE k, int primary ) +//{ +// assert( k->pkt->pkttype == PKT_SECRET_KEY +// || k->pkt->pkttype == PKT_SECRET_SUBKEY ); +// assert( keyblock->pkt->pkttype == PKT_SECRET_KEY ); +// if( primary && !sk->pubkey_usage ) { +// copy_secret_key( sk, keyblock->pkt->pkt.secret_key ); +// } +// else { +// if( primary && sk->pubkey_usage +// && check_pubkey_algo2( k->pkt->pkt.secret_key->pubkey_algo, +// sk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) { +// /* if the usage is not correct, try to use a subkey */ +// KBNODE save_k = k; +// +// k = NULL; +// /* kludge for pgp 5: which doesn't accept type 20: +// * try to use a type 16 subkey instead */ +// if( sk->pubkey_usage == PUBKEY_USAGE_ENC ) { +// for( k = save_k; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_SECRET_SUBKEY +// && k->pkt->pkt.secret_key->pubkey_algo +// == PUBKEY_ALGO_ELGAMAL_E +// && !check_pubkey_algo2( +// k->pkt->pkt.secret_key->pubkey_algo, +// sk->pubkey_usage ) ) +// break; +// } +// } +// +// if( !k ) { +// for(k = save_k ; k; k = k->next ) { +// if( k->pkt->pkttype == PKT_SECRET_SUBKEY +// && !check_pubkey_algo2( +// k->pkt->pkt.secret_key->pubkey_algo, +// sk->pubkey_usage ) ) +// break; +// } +// } +// if( !k ) +// k = save_k; +// else +// log_info("using secondary key %08lX " +// "instead of primary key %08lX\n", +// (ulong)keyid_from_sk( k->pkt->pkt.secret_key, NULL), +// (ulong)keyid_from_sk( save_k->pkt->pkt.secret_key, NULL) +// ); +// } +// +// copy_secret_key( sk, k->pkt->pkt.secret_key ); +// } +//} +// + +static int +lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) +{ + int rc; + KBNODE k; + int oldmode = set_packet_list_mode(0); + byte namehash[20]; + int use_namehash=0; + + trace(); + + if( !ctx->count ) /* first time */ + rc = enum_keyblocks( 0, &ctx->kbpos, &ctx->keyblock ); + else + rc = 0; + if( !rc ) { + while( !(rc = enum_keyblocks( 1, &ctx->kbpos, &ctx->keyblock )) ) { + int n; + getkey_item_t *item; + /* fixme: we don't enum the complete keyblock, but + * use the first match and then continue with the next keyblock + */ + /* loop over all the user ids we want to look for */ + item = ctx->items; + for(n=0; n < ctx->nitems; n++, item++ ) { + if( item->mode < 10 ) + k = find_by_name( ctx->keyblock, pk, + item->name, item->mode, + namehash, &use_namehash ); + else if( item->mode >= 10 && item->mode <= 12 ) + k = find_by_keyid( ctx->keyblock, pk, + item->keyid, item->mode ); + else if( item->mode == 15 ) + k = find_first( ctx->keyblock, pk ); + else if( item->mode == 16 || item->mode == 20 ) + k = find_by_fpr( ctx->keyblock, pk, + item->fprint, item->mode ); + else + BUG(); + if( k ) { + finish_lookup( ctx->keyblock, pk, k, namehash, + use_namehash, ctx->primary ); + goto found; + } + } + release_kbnode( ctx->keyblock ); + ctx->keyblock = NULL; + } + found: ; + } + if( rc && rc != -1 ) + log_error("enum_keyblocks failed: %d\n", rc); + + if( !rc ) { + if( ret_keyblock ) { + *ret_keyblock = ctx->keyblock; + ctx->keyblock = NULL; + } + } + else if( rc == -1 ) + rc = G10ERR_NO_PUBKEY; + + release_kbnode( ctx->keyblock ); + ctx->keyblock = NULL; + set_packet_list_mode(oldmode); + #if 0 + if( opt.debug & DBG_MEMSTAT_VALUE ) { + static int initialized; + + if( !initialized ) { + initialized = 1; + atexit( print_stats ); + } + + assert( ctx->mode < DIM(lkup_stats) ); + lkup_stats[ctx->mode].any = 1; + if( !rc ) + lkup_stats[ctx->mode].okay_count++; + else if ( rc == G10ERR_NO_PUBKEY ) + lkup_stats[ctx->mode].nokey_count++; + else + lkup_stats[ctx->mode].error_count++; + } + #endif + + ctx->last_rc = rc; + ctx->count++; + return rc; +} + + +// +//static int +//lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) +//{ +// int rc; +// KBNODE k; +// int oldmode = set_packet_list_mode(0); +// +// if( !ctx->count ) /* first time */ +// rc = enum_keyblocks( 5, &ctx->kbpos, &ctx->keyblock ); +// else +// rc = 0; +// if( !rc ) { +// while( !(rc = enum_keyblocks( 1, &ctx->kbpos, &ctx->keyblock )) ) { +// int n; +// getkey_item_t *item; +// /* fixme: we don't enum the complete keyblock, but +// * use the first match and then continue with the next keyblock +// */ +// /* loop over all the user ids we want to look for */ +// item = ctx->items; +// for(n=0; n < ctx->nitems; n++, item++ ) { +// if( item->mode < 10 ) +// k = find_by_name_sk( ctx->keyblock, sk, +// item->name, item->mode ); +// else if( item->mode >= 10 && item->mode <= 12 ) +// k = find_by_keyid_sk( ctx->keyblock, sk, +// item->keyid, item->mode ); +// else if( item->mode == 15 ) +// k = find_first_sk( ctx->keyblock, sk ); +// else if( item->mode == 16 || item->mode == 20 ) +// k = find_by_fpr_sk( ctx->keyblock, sk, +// item->fprint, item->mode ); +// else +// BUG(); +// if( k ) { +// finish_lookup_sk( ctx->keyblock, sk, k, ctx->primary ); +// goto found; +// } +// } +// release_kbnode( ctx->keyblock ); +// ctx->keyblock = NULL; +// } +// found: ; +// } +// if( rc && rc != -1 ) +// log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); +// +// if( !rc ) { +// if( ret_keyblock ) { +// *ret_keyblock = ctx->keyblock; +// ctx->keyblock = NULL; +// } +// } +// else if( rc == -1 ) +// rc = G10ERR_NO_SECKEY; +// +// release_kbnode( ctx->keyblock ); +// ctx->keyblock = NULL; +// set_packet_list_mode(oldmode); +// +// ctx->last_rc = rc; +// ctx->count++; +// return rc; +//} +// +// +// +///**************** +// * fixme: replace by the generic function +// * +// * Enumerate all primary secret keys. Caller must use these procedure: +// * 1) create a void pointer and initialize it to NULL +// * 2) pass this void pointer by reference to this function +// * and provide space for the secret key (pass a buffer for sk) +// * 3) call this function as long as it does not return -1 +// * to indicate EOF. +// * 4) Always call this function a last time with SK set to NULL, +// * so that can free it's context. +// * +// * +// */ +//int +//enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) +//{ +// int rc=0; +// PACKET pkt; +// int save_mode; +// struct { +// int eof; +// int sequence; +// const char *name; +// IOBUF iobuf; +// } *c = *context; +// +// +// if( !c ) { /* make a new context */ +// c = m_alloc_clear( sizeof *c ); +// *context = c; +// c->sequence = 0; +// c->name = enum_keyblock_resources( &c->sequence, 1 ); +// } +// +// if( !sk ) { /* free the context */ +// if( c->iobuf ) +// iobuf_close(c->iobuf); +// m_free( c ); +// *context = NULL; +// return 0; +// } +// +// if( c->eof ) +// return -1; +// +// /* FIXME: This assumes a plain keyring file */ +// for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) { +// if( !c->iobuf ) { +// if( !(c->iobuf = iobuf_open( c->name ) ) ) { +// log_error("enum_secret_keys: can't open `%s'\n", c->name ); +// continue; /* try next file */ +// } +// } +// +// save_mode = set_packet_list_mode(0); +// init_packet(&pkt); +// while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) { +// if( rc ) +// ; /* e.g. unknown packet */ +// else if( pkt.pkttype == PKT_SECRET_KEY +// || ( with_subkeys && pkt.pkttype == PKT_SECRET_SUBKEY ) ) { +// copy_secret_key( sk, pkt.pkt.secret_key ); +// set_packet_list_mode(save_mode); +// return 0; /* found */ +// } +// free_packet(&pkt); +// } +// set_packet_list_mode(save_mode); +// iobuf_close(c->iobuf); c->iobuf = NULL; +// } +// c->eof = 1; +// return -1; +//} +// +// +///**************** +// * Return a string with a printable representation of the user_id. +// * this string must be freed by m_free. +// */ +//char* +//get_user_id_string( u32 *keyid ) +//{ +// user_id_db_t r; +// char *p; +// int pass=0; +// /* try it two times; second pass reads from key resources */ +// do { +// for(r=user_id_db; r; r = r->next ) +// if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { +// p = m_alloc( r->len + 10 ); +// sprintf(p, "%08lX %.*s", (ulong)keyid[1], r->len, r->name ); +// return p; +// } +// } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); +// p = m_alloc( 15 ); +// sprintf(p, "%08lX [?]", (ulong)keyid[1] ); +// return p; +//} +// +// +//char* +//get_user_id_string_native( u32 *keyid ) +//{ +// char *p = get_user_id_string( keyid ); +// char *p2 = utf8_to_native( p, strlen(p) ); +// +// m_free(p); +// return p2; +//} +// + +char* +get_long_user_id_string( u32 *keyid ) +{ + user_id_db_t r; + char *p; + int pass=0; + + trace(); + + /* try it two times; second pass reads from key resources */ + do { + for(r=user_id_db; r; r = r->next ) + if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { + p = m_alloc( r->len + 20 ); + sprintf(p, "%08lX%08lX %.*s", + (ulong)keyid[0], (ulong)keyid[1], r->len, r->name ); + return p; + } + } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); + p = m_alloc( 25 ); + sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] ); + return p; +} + +//char* +//get_user_id( u32 *keyid, size_t *rn ) +//{ +// user_id_db_t r; +// char *p; +// int pass=0; +// /* try it two times; second pass reads from key resources */ +// do { +// for(r=user_id_db; r; r = r->next ) +// if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { +// p = m_alloc( r->len ); +// memcpy(p, r->name, r->len ); +// *rn = r->len; +// return p; +// } +// } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); +// p = m_alloc( 19 ); +// memcpy(p, "[User id not found]", 19 ); +// *rn = 19; +// return p; +//} +// +// diff -Nru a/security/cryptomark/gnupg/hkp.h b/security/cryptomark/gnupg/hkp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/hkp.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,30 @@ +/* hkp.h - Horrowitz Keyserver Protocol + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_HKP_H +#define G10_HKP_H 1 + + +int hkp_ask_import( u32 *keyid ); +int hkp_import( STRLIST users ); +int hkp_export( STRLIST users ); + + +#endif /*G10_HKP_H*/ diff -Nru a/security/cryptomark/gnupg/host2net.h b/security/cryptomark/gnupg/host2net.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/host2net.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,43 @@ +/* host2net.h - Some macros + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_HOST2NET_H +#define G10_HOST2NET_H + +#include "types.h" + +#define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ + (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) +#define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1))) +#define ulongtobuf( p, a ) do { \ + ((byte*)p)[0] = a >> 24; \ + ((byte*)p)[1] = a >> 16; \ + ((byte*)p)[2] = a >> 8; \ + ((byte*)p)[3] = a ; \ + } while(0) +#define ushorttobuf( p, a ) do { \ + ((byte*)p)[0] = a >> 8; \ + ((byte*)p)[1] = a ; \ + } while(0) +#define buftou32( p) buftoulong( (p) ) +#define u32tobuf( p, a) ulongtobuf( (p), (a) ) + + +#endif /*G10_HOST2NET_H*/ diff -Nru a/security/cryptomark/gnupg/http.h b/security/cryptomark/gnupg/http.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/http.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,80 @@ +/* http.h - HTTP protocol handler + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_HTTP_H +#define G10_HTTP_H 1 + +#include "iobuf.h" + +struct uri_tuple { + struct uri_tuple *next; + const char *name; /* a pointer into name */ + char *value; /* a pointer to value (a Nul is always appended) */ + size_t valuelen; /* and the real length of the value */ + /* because the value may contain embedded Nuls */ +}; +typedef struct uri_tuple *URI_TUPLE; + +struct parsed_uri { + /* all these pointers point into buffer; most stuff is not escaped */ + char *scheme; /* pointer to the scheme string (lowercase) */ + char *host; /* host (converted to lowercase) */ + ushort port; /* port (always set if the host is set) */ + char *path; /* the path */ + URI_TUPLE params; /* ";xxxxx" */ + URI_TUPLE query; /* "?xxx=yyy" */ + char buffer[1]; /* buffer which holds a (modified) copy of the URI */ +}; +typedef struct parsed_uri *PARSED_URI; + +typedef enum { + HTTP_REQ_GET = 1, + HTTP_REQ_HEAD = 2, + HTTP_REQ_POST = 3 +} HTTP_REQ_TYPE; + +enum { /* put flag values into an enum, so that gdb can display them */ + HTTP_FLAG_TRY_PROXY = 1 +}; + +struct http_context { + int initialized; + unsigned int status_code; + int sock; + int in_data; + IOBUF fp_read; + IOBUF fp_write; + int is_http_0_9; + PARSED_URI uri; + HTTP_REQ_TYPE req_type; + byte *buffer; /* line buffer */ + unsigned buffer_size; + unsigned int flags; +}; +typedef struct http_context *HTTP_HD; + +int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, + unsigned int flags ); +void http_start_data( HTTP_HD hd ); +int http_wait_response( HTTP_HD hd, unsigned int *ret_status ); +void http_close( HTTP_HD hd ); + +int http_open_document( HTTP_HD hd, const char *document, unsigned int flags ); + +#endif /*G10_HTTP_H*/ diff -Nru a/security/cryptomark/gnupg/i18n.h b/security/cryptomark/gnupg/i18n.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/i18n.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,50 @@ +/* i18n.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_I18N_H +#define G10_I18N_H + +//#ifdef USE_SIMPLE_GETTEXT +// int set_gettext_file( const char *filename ); +// const char *gettext( const char *msgid ); +// +// #define _(a) gettext (a) +// #define N_(a) (a) +// +//#else +//#ifdef HAVE_LOCALE_H +// #include /* suggested by Ernst Molitor */ +//#endif +// +//#ifdef ENABLE_NLS +// #include +// #define _(a) gettext (a) +// #ifdef gettext_noop +// #define N_(a) gettext_noop (a) +// #else +// #define N_(a) (a) +// #endif +//#else + #define _(a) (a) + #define N_(a) (a) +//#endif +//#endif /* !USE_SIMPLE_GETTEXT */ + +#endif /*G10_I18N_H*/ diff -Nru a/security/cryptomark/gnupg/iobuf.c b/security/cryptomark/gnupg/iobuf.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/iobuf.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1612 @@ +/* iobuf.c - file handling + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include "memory.h" +#include "util.h" +#include "iobuf.h" + +//typedef struct { +// FILE *fp; /* open file handle */ +// int print_only_name; /* flags indicating that fname is not a real file*/ +// char fname[1]; /* name of the file */ +//} file_filter_ctx_t ; + + +/* The first partial length header block must be of size 512 + * to make it easier (and efficienter) we use a min. block size of 512 + * for all chunks (but the last one) */ +#define OP_MIN_PARTIAL_CHUNK 512 +#define OP_MIN_PARTIAL_CHUNK_2POW 9 + +typedef struct { + int use; + size_t size; + size_t count; + int partial; /* 1 = partial header, 2 in last partial packet */ + char *buffer; /* used for partial header */ + size_t buflen; /* used size of buffer */ + int first_c; /* of partial header (which is > 0)*/ + int eof; +} block_filter_ctx_t; + + +//static int underflow(IOBUF a); +// +///**************** +// * Read data from a file into buf which has an allocated length of *LEN. +// * return the number of read bytes in *LEN. OPAQUE is the FILE * of +// * the stream. A is not used. +// * control may be: +// * IOBUFCTRL_INIT: called just before the function is linked into the +// * list of function. This can be used to prepare internal +// * data structures of the function. +// * IOBUFCTRL_FREE: called just before the function is removed from the +// * list of functions and can be used to release internal +// * data structures or close a file etc. +// * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer +// * with new stuff. *RET_LEN is the available size of the +// * buffer, and should be set to the number of bytes +// * which were put into the buffer. The function +// * returns 0 to indicate success, -1 on EOF and +// * G10ERR_xxxxx for other errors. +// * +// * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff. +// * *RET_LAN is the number of bytes in BUF. +// * +// * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The +// * filter may take appropriate action on this message. +// */ +//static int +//file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) +//{ +// file_filter_ctx_t *a = opaque; +// FILE *fp = a->fp; +// size_t size = *ret_len; +// size_t nbytes = 0; +// int rc = 0; +// +// if( control == IOBUFCTRL_UNDERFLOW ) { +// assert( size ); /* need a buffer */ +// if ( feof(fp)) { /* On terminals you could easiely read as many EOFs as you call */ +// rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */ +// *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */ +// } +// else { +// clearerr( fp ); +// nbytes = fread( buf, 1, size, fp ); +// if( feof(fp) && !nbytes ) +// rc = -1; /* okay: we can return EOF now. */ +// else if( ferror(fp) && errno != EPIPE ) { +// log_error("%s: read error: %s\n", +// a->fname, strerror(errno)); +// rc = G10ERR_READ_FILE; +// } +// *ret_len = nbytes; +// } +// } +// else if( control == IOBUFCTRL_FLUSH ) { +// if( size ) { +// clearerr( fp ); +// nbytes = fwrite( buf, 1, size, fp ); +// if( ferror(fp) ) { +// log_error("%s: write error: %s\n", a->fname, strerror(errno)); +// rc = G10ERR_WRITE_FILE; +// } +// } +// *ret_len = nbytes; +// } +// else if( control == IOBUFCTRL_INIT ) { +// } +// else if( control == IOBUFCTRL_DESC ) { +// *(char**)buf = "file_filter"; +// } +// else if( control == IOBUFCTRL_FREE ) { +// if( fp != stdin && fp != stdout ) { +// if( DBG_IOBUF ) +// log_debug("%s: close fd %d\n", a->fname, fileno(fp) ); +// fclose(fp); +// } +// fp = NULL; +// m_free(a); /* we can free our context now */ +// } +// +// return rc; +//} +// + +/**************** + * This is used to implement the block write mode. + * Block reading is done on a byte by byte basis in readbyte(), + * without a filter + */ +static int +block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) +{ + block_filter_ctx_t *a = opaque; + size_t size = *ret_len; + int c, needed, rc = 0; + char *p; + + trace(); + + if( control == IOBUFCTRL_UNDERFLOW ) { + size_t n=0; + + p = buf; +// assert( size ); /* need a buffer */ + if( a->eof ) /* don't read any further */ + rc = -1; + while( !rc && size ) { + if( !a->size ) { /* get the length bytes */ + if( a->partial == 2 ) { + a->eof = 1; + if( !n ) + rc = -1; + break; + } + else if( a->partial ) { + /* These OpenPGP introduced huffman like encoded length + * bytes are really a mess :-( */ + if( a->first_c ) { + c = a->first_c; + a->first_c = 0; +// assert( c >= 224 && c < 255 ); + } + else if( (c = iobuf_get(chain)) == -1 ) { + log_error("block_filter: 1st length byte missing\n"); + rc = G10ERR_READ_FILE; + break; + } + if( c < 192 ) { + a->size = c; + a->partial = 2; + if( !a->size ) { + a->eof = 1; + if( !n ) + rc = -1; + break; + } + } + else if( c < 224 ) { + a->size = (c - 192) * 256; + if( (c = iobuf_get(chain)) == -1 ) { + log_error("block_filter: 2nd length byte missing\n"); + rc = G10ERR_READ_FILE; + break; + } + a->size += c + 192; + a->partial = 2; + if( !a->size ) { + a->eof = 1; + if( !n ) + rc = -1; + break; + } + } + else if( c == 255 ) { + a->size = iobuf_get(chain) << 24; + a->size |= iobuf_get(chain) << 16; + a->size |= iobuf_get(chain) << 8; + if( (c = iobuf_get(chain)) == -1 ) { + log_error("block_filter: invalid 4 byte length\n"); + rc = G10ERR_READ_FILE; + break; + } + a->size |= c; + } + else { /* next partial body length */ + a->size = 1 << (c & 0x1f); + } + /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/ + } + else { /* the gnupg partial length scheme - much better :-) */ + c = iobuf_get(chain); + a->size = c << 8; + c = iobuf_get(chain); + a->size |= c; + if( c == -1 ) { + log_error("block_filter: error reading length info\n"); + rc = G10ERR_READ_FILE; + } + if( !a->size ) { + a->eof = 1; + if( !n ) + rc = -1; + break; + } + } + } + + while( !rc && size && a->size ) { + needed = size < a->size ? size : a->size; + c = iobuf_read( chain, p, needed ); + if( c < needed ) { + if( c == -1 ) c = 0; + log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n", + a, (ulong)size+c, (ulong)a->size+c); + rc = G10ERR_READ_FILE; + } + else { + size -= c; + a->size -= c; + p += c; + n += c; + } + } + } + *ret_len = n; + } + else if( control == IOBUFCTRL_FLUSH ) { + if( a->partial ) { /* the complicated openpgp scheme */ + size_t blen, n, nbytes = size + a->buflen; + +// assert( a->buflen <= OP_MIN_PARTIAL_CHUNK ); + if( nbytes < OP_MIN_PARTIAL_CHUNK ) { + /* not enough to write a partial block out; so we store it*/ + if( !a->buffer ) + a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK ); + memcpy( a->buffer + a->buflen, buf, size ); + a->buflen += size; + } + else { /* okay, we can write out something */ + /* do this in a loop to use the most efficient block lengths */ + p = buf; + do { + /* find the best matching block length - this is limited + * by the size of the internal buffering */ + for( blen=OP_MIN_PARTIAL_CHUNK*2, + c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes; + blen *=2, c++ ) + ; + blen /= 2; c--; + /* write the partial length header */ +// assert( c <= 0x1f ); /*;-)*/ + c |= 0xe0; + iobuf_put( chain, c ); + if( (n=a->buflen) ) { /* write stuff from the buffer */ +// assert( n == OP_MIN_PARTIAL_CHUNK); + if( iobuf_write(chain, a->buffer, n ) ) + rc = G10ERR_WRITE_FILE; + a->buflen = 0; + nbytes -= n; + } + if( (n = nbytes) > blen ) + n = blen; + if( n && iobuf_write(chain, p, n ) ) + rc = G10ERR_WRITE_FILE; + p += n; + nbytes -= n; + } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK ); + /* store the rest in the buffer */ + if( !rc && nbytes ) { +// assert( !a->buflen ); +// assert( nbytes < OP_MIN_PARTIAL_CHUNK ); + if( !a->buffer ) + a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK ); + memcpy( a->buffer, p, nbytes ); + a->buflen = nbytes; + } + } + } + else { /* the gnupg scheme (which is not openpgp compliant) */ + size_t avail, n; + + for(p=buf; !rc && size; ) { + n = size; + avail = a->size - a->count; + if( !avail ) { + if( n > a->size ) { + iobuf_put( chain, (a->size >> 8) & 0xff ); + iobuf_put( chain, a->size & 0xff ); + avail = a->size; + a->count = 0; + } + else { + iobuf_put( chain, (n >> 8) & 0xff ); + iobuf_put( chain, n & 0xff ); + avail = n; + a->count = a->size - n; + } + } + if( n > avail ) + n = avail; + if( iobuf_write(chain, p, n ) ) + rc = G10ERR_WRITE_FILE; + a->count += n; + p += n; + size -= n; + } + } + } + else if( control == IOBUFCTRL_INIT ) { + if( DBG_IOBUF ) + log_debug("init block_filter %p\n", a ); + if( a->partial ) + a->count = 0; + else if( a->use == 1 ) + a->count = a->size = 0; + else + a->count = a->size; /* force first length bytes */ + a->eof = 0; + a->buffer = NULL; + a->buflen = 0; + } + else if( control == IOBUFCTRL_DESC ) { + *(char**)buf = "block_filter"; + } + else if( control == IOBUFCTRL_FREE ) { + if( a->use == 2 ) { /* write the end markers */ + if( a->partial ) { + u32 len; + /* write out the remaining bytes without a partial header + * the length of this header may be 0 - but if it is + * the first block we are not allowed to use a partial header + * and frankly we can't do so, because this length must be + * a power of 2. This is _really_ complicated because we + * have to check the possible length of a packet prior + * to it's creation: a chain of filters becomes complicated + * and we need a lot of code to handle compressed packets etc. + * :-((((((( + */ + /* construct header */ + len = a->buflen; + /*log_debug("partial: remaining length=%u\n", len );*/ + if( len < 192 ) + rc = iobuf_put(chain, len ); + else if( len < 8384 ) { + if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) ) + rc = iobuf_put( chain, ((len-192) % 256)); + } + else { /* use a 4 byte header */ + if( !(rc=iobuf_put( chain, 0xff )) ) + if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) ) + if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) ) + if( !(rc=iobuf_put( chain, (len >> 8)&0xff ))) + rc=iobuf_put( chain, len & 0xff ); + } + if( !rc && len ) + rc = iobuf_write(chain, a->buffer, len ); + if( rc ) { +// log_error("block_filter: write error: %s\n",strerror(errno)); + log_error("block_filter: write error\n"); + rc = G10ERR_WRITE_FILE; + } + m_free( a->buffer ); a->buffer = NULL; a->buflen = 0; + } + else { + iobuf_writebyte(chain, 0); + iobuf_writebyte(chain, 0); + } + } + else if( a->size ) { + log_error("block_filter: pending bytes!\n"); + } + if( DBG_IOBUF ) + log_debug("free block_filter %p\n", a ); + m_free(a); /* we can free our context now */ + } + + return rc; +} + + +static void +print_chain( IOBUF a ) +{ + trace(); + + if( !DBG_IOBUF ) + return; + for(; a; a = a->chain ) { + size_t dummy_len = 0; + const char *desc = "[none]"; + + if( a->filter ) + a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL, + (byte*)&desc, &dummy_len ); + + log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n", + a->no, a->subno, desc, a->filter_eof, + (int)a->d.start, (int)a->d.len ); + } +} + +//int +//iobuf_print_chain( IOBUF a ) +//{ +// print_chain(a); +// return 0; +//} + +/**************** + * Allocate a new io buffer, with no function assigned. + * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer + * BUFSIZE is a suggested buffer size. + */ +IOBUF +iobuf_alloc(int use, size_t bufsize) +{ + IOBUF a; + static int number=0; + + trace(); + + a = m_alloc_clear(sizeof *a); + a->use = use; + a->d.buf = m_alloc( bufsize ); + a->d.size = bufsize; + a->no = ++number; + a->subno = 0; + a->opaque = NULL; + a->real_fname = NULL; + return a; +} + + +int +iobuf_close( IOBUF a ) +{ + IOBUF a2; + size_t dummy_len; + int rc=0; + + trace(); + + if( a && a->directfp ) { +// fclose( a->directfp ); + m_free( a->real_fname ); + if( DBG_IOBUF ) + log_debug("iobuf_close -> %p\n", a->directfp ); + return 0; + } + + for( ; a && !rc ; a = a2 ) { + a2 = a->chain; + if( a->use == 2 && (rc=iobuf_flush(a)) ) + log_error("iobuf_flush failed on close: %d\n", rc); + + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc ); + if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, + a->chain, NULL, &dummy_len)) ) + log_error("IOBUFCTRL_FREE failed on close: %d\n", rc); + m_free(a->real_fname); + m_free(a->d.buf); + m_free(a); + } + return rc; +} + +int +iobuf_cancel( IOBUF a ) +{ +// const char *s; + IOBUF a2; + + trace(); + +// if( a && a->use == 2 ) { +// s = iobuf_get_real_fname(a); +// if( s && *s ) +// remove(s); /* remove the file. Fixme: this will fail for MSDOZE*/ +// } /* because the file is still open */ + + /* send a cancel message to all filters */ + for( a2 = a; a2 ; a2 = a2->chain ) { + size_t dummy; + if( a2->filter ) + a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, + NULL, &dummy ); + } + + return iobuf_close(a); +} + + +/**************** + * create a temporary iobuf, which can be used to collect stuff + * in an iobuf and later be written by iobuf_write_temp() to another + * iobuf. + */ +IOBUF +iobuf_temp() +{ + IOBUF a; + + trace(); + + a = iobuf_alloc(3, 8192 ); + + return a; +} + +IOBUF +iobuf_temp_with_content( const char *buffer, size_t length ) +{ + IOBUF a; + + trace(); + + a = iobuf_alloc(3, length ); + memcpy( a->d.buf, buffer, length ); + a->d.len = length; + + return a; +} + + +/**************** + * Create a head iobuf for reading from a file + * returns: NULL if an error occures and sets errno + */ + +extern unsigned char *cryptomark_key; +extern unsigned long cryptomark_key_length; + +IOBUF +iobuf_open( const char *fname ) +{ + + IOBUF a; + IOBUF temp; +// FILE *fp; +// file_filter_ctx_t *fcx; +// size_t len; +// int print_only = 0; + + trace(); + dbg (__FUNCTION__" - fname = %s", fname); + // HUGE hack, force our key into the iobuf + + if (!(temp = iobuf_temp_with_content (cryptomark_key, cryptomark_key_length))) { + warn (__FUNCTION__ ":can't create temp IOBUF" ) ; + return NULL; + } + dbg (__FUNCTION__ ": step 2"); + a = iobuf_alloc (1, 8192); + iobuf_write_temp (a, temp); + +// +// if( !fname || (*fname=='-' && !fname[1]) ) { +// fp = stdin; /* fixme: set binary mode for msdoze */ +// fname = "[stdin]"; +// print_only = 1; +// } +// else if( !(fp = fopen(fname, "rb")) ) +// return NULL; +// a = iobuf_alloc(1, 8192 ); +// fcx = m_alloc( sizeof *fcx + strlen(fname) ); +// fcx->fp = fp; +// fcx->print_only_name = print_only; +// strcpy(fcx->fname, fname ); +// if( !print_only ) +// a->real_fname = m_strdup( fname ); +// a->filter = file_filter; +// a->filter_ov = fcx; +// file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); +// file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); +// if( DBG_IOBUF ) +// log_debug("iobuf-%d.%d: open `%s' fd=%d\n", +// a->no, a->subno, fname, fileno(fcx->fp) ); +// + return a; +} +// +///**************** +// * Create a head iobuf for reading from a file +// * returns: NULL if an error occures and sets errno +// */ +//IOBUF +//iobuf_fdopen( int fd, const char *mode ) +//{ +// IOBUF a; +// FILE *fp; +// file_filter_ctx_t *fcx; +// size_t len; +// +// if( !(fp = fdopen(fd, mode)) ) +// return NULL; +// a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 ); +// fcx = m_alloc( sizeof *fcx + 20 ); +// fcx->fp = fp; +// fcx->print_only_name = 1; +// sprintf(fcx->fname, "[fd %d]", fd ); +// a->filter = file_filter; +// a->filter_ov = fcx; +// file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); +// file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); +// if( DBG_IOBUF ) +// log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname ); +// +// return a; +//} +// +///**************** +// * create an iobuf for writing to a file; the file will be created. +// */ +//IOBUF +//iobuf_create( const char *fname ) +//{ +// IOBUF a; +// FILE *fp; +// file_filter_ctx_t *fcx; +// size_t len; +// int print_only = 0; +// +// if( !fname || (*fname=='-' && !fname[1]) ) { +// fp = stdout; +// fname = "[stdout]"; +// print_only = 1; +// } +// else if( !(fp = fopen(fname, "wb")) ) +// return NULL; +// a = iobuf_alloc(2, 8192 ); +// fcx = m_alloc( sizeof *fcx + strlen(fname) ); +// fcx->fp = fp; +// fcx->print_only_name = print_only; +// strcpy(fcx->fname, fname ); +// if( !print_only ) +// a->real_fname = m_strdup( fname ); +// a->filter = file_filter; +// a->filter_ov = fcx; +// file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); +// file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); +// if( DBG_IOBUF ) +// log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc ); +// +// return a; +//} +// +///**************** +// * append to an iobuf; if the file does not exist, create it. +// * cannot be used for stdout. +// */ +//IOBUF +//iobuf_append( const char *fname ) +//{ +// IOBUF a; +// FILE *fp; +// file_filter_ctx_t *fcx; +// size_t len; +// +// if( !fname ) +// return NULL; +// else if( !(fp = fopen(fname, "ab")) ) +// return NULL; +// a = iobuf_alloc(2, 8192 ); +// fcx = m_alloc( sizeof *fcx + strlen(fname) ); +// fcx->fp = fp; +// strcpy(fcx->fname, fname ); +// a->real_fname = m_strdup( fname ); +// a->filter = file_filter; +// a->filter_ov = fcx; +// file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); +// file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); +// if( DBG_IOBUF ) +// log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc ); +// +// return a; +//} +// +//IOBUF +//iobuf_openrw( const char *fname ) +//{ +// IOBUF a; +// FILE *fp; +// file_filter_ctx_t *fcx; +// size_t len; +// +// if( !fname ) +// return NULL; +// else if( !(fp = fopen(fname, "r+b")) ) +// return NULL; +// a = iobuf_alloc(2, 8192 ); +// fcx = m_alloc( sizeof *fcx + strlen(fname) ); +// fcx->fp = fp; +// strcpy(fcx->fname, fname ); +// a->real_fname = m_strdup( fname ); +// a->filter = file_filter; +// a->filter_ov = fcx; +// file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); +// file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); +// if( DBG_IOBUF ) +// log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc ); +// +// return a; +//} +// +// +// +///**************** +// * You can overwrite the normal iobuf behaviour by using this function. +// * If used the iobuf is a simple wrapper around stdio. +// * NULL if an error occures and sets errno +// */ +//IOBUF +//iobuf_fopen( const char *fname, const char *mode ) +//{ +// IOBUF a; +// FILE *fp; +// int print_only = 0; +// +// if( !fname || (*fname=='-' && !fname[1]) ) { +// fp = stdin; /* fixme: set binary mode for msdoze */ +// fname = "[stdin]"; +// print_only = 1; +// } +// else if( !(fp = fopen(fname, mode) ) ) +// return NULL; +// a = iobuf_alloc(1, 8192 ); +// a->directfp = fp; +// a->real_fname = m_strdup( fname ); +// +// if( DBG_IOBUF ) +// log_debug("iobuf_fopen -> %p\n", a->directfp ); +// +// return a; +//} +// + + +/**************** + * Register an i/o filter. + */ +int +iobuf_push_filter( IOBUF a, + int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), void *ov ) +{ + trace(); + + return iobuf_push_filter2( a, f, ov, 0 ); +} + +int +iobuf_push_filter2( IOBUF a, + int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), + void *ov, int rel_ov ) +{ + IOBUF b; + size_t dummy_len=0; + int rc=0; + + trace(); + + if( a->directfp ) + BUG(); + + if( a->use == 2 && (rc=iobuf_flush(a)) ) + return rc; + /* make a copy of the current stream, so that + * A is the new stream and B the original one. + * The contents of the buffers are transferred to the + * new stream. + */ + b = m_alloc(sizeof *b); + memcpy(b, a, sizeof *b ); + /* fixme: it is stupid to keep a copy of the name at every level + * but we need the name somewhere because the name known by file_filter + * may have been released when we need the name of the file */ + b->real_fname = a->real_fname? m_strdup(a->real_fname):NULL; + /* remove the filter stuff from the new stream */ + a->filter = NULL; + a->filter_ov = NULL; + a->filter_ov_owner = 0; + a->filter_eof = 0; + if( a->use == 3 ) + a->use = 2; /* make a write stream from a temp stream */ + + if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */ + b->d.buf = m_alloc( a->d.size ); + b->d.len = 0; + b->d.start = 0; + } + else { /* allocate a fresh buffer for the new stream */ + a->d.buf = m_alloc( a->d.size ); + a->d.len = 0; + a->d.start = 0; + } + /* disable nlimit for the new stream */ + a->ntotal = b->ntotal + b->nbytes; + a->nlimit = a->nbytes = 0; + a->nofast &= ~1; + /* make a link from the new stream to the original stream */ + a->chain = b; + a->opaque = b->opaque; + + /* setup the function on the new stream */ + a->filter = f; + a->filter_ov = ov; + a->filter_ov_owner = rel_ov; + + a->subno = b->subno + 1; + f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len ); + +// if( DBG_IOBUF ) { +// log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc ); +// print_chain( a ); +// } + + /* now we can initialize the new function if we have one */ + if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain, + NULL, &dummy_len)) ) +// log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) ); + log_error("IOBUFCTRL_INIT failed: %d\n", rc ); + return rc; +} + +/**************** + * Remove an i/o filter. + */ +int +pop_filter( IOBUF a, int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), void *ov ) +{ + IOBUF b; + size_t dummy_len=0; + int rc=0; + + trace(); + + if( a->directfp ) + BUG(); + + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc ); + if( !a->filter ) { /* this is simple */ + b = a->chain; +// assert(b); + m_free(a->d.buf); + m_free(a->real_fname); + memcpy(a,b, sizeof *a); + m_free(b); + return 0; + } + for(b=a ; b; b = b->chain ) + if( b->filter == f && (!ov || b->filter_ov == ov) ) + break; + if( !b ) + log_bug("pop_filter(): filter function not found\n"); + + /* flush this stream if it is an output stream */ + if( a->use == 2 && (rc=iobuf_flush(b)) ) { +// log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc)); + log_error("iobuf_flush failed in pop_filter: %d\n", rc); + return rc; + } + /* and tell the filter to free it self */ + if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain, + NULL, &dummy_len)) ) { +// log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) ); + log_error("IOBUFCTRL_FREE failed: %d\n", rc ); + return rc; + } + if( b->filter_ov && b->filter_ov_owner ) { + m_free( b->filter_ov ); + b->filter_ov = NULL; + } + + + /* and see how to remove it */ + if( a == b && !b->chain ) + log_bug("can't remove the last filter from the chain\n"); + else if( a == b ) { /* remove the first iobuf from the chain */ + /* everything from b is copied to a. This is save because + * a flush has been done on the to be removed entry + */ + b = a->chain; + m_free(a->d.buf); + m_free(a->real_fname); + memcpy(a,b, sizeof *a); + m_free(b); + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno ); + } + else if( !b->chain ) { /* remove the last iobuf from the chain */ + log_bug("Ohh jeee, trying to remove a head filter\n"); + } + else { /* remove an intermediate iobuf from the chain */ + log_bug("Ohh jeee, trying to remove an intermediate filter\n"); + } + + return rc; +} + + +/**************** + * read underflow: read more bytes into the buffer and return + * the first byte or -1 on EOF. + */ +static int +underflow(IOBUF a) +{ + size_t len; + int rc; + + trace(); + +// assert( a->d.start == a->d.len ); + if( a->use == 3 ) + return -1; /* EOF because a temp buffer can't do an underflow */ + + if( a->filter_eof ) { + if( a->chain && a->filter_eof == 1 ) { + IOBUF b = a->chain; + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: pop `%s' in underflow\n", + a->no, a->subno, a->desc ); + m_free(a->d.buf); + m_free(a->real_fname); + memcpy(a, b, sizeof *a); + m_free(b); + print_chain(a); + } + else + a->filter_eof = 0; + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n", + a->no, a->subno ); + return -1; /* return one(!) EOF */ + } + if( a->error ) { + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: error\n", a->no, a->subno ); + return -1; + } + +// if( a->directfp ) { +// FILE *fp = a->directfp; +// +// len = fread( a->d.buf, 1, a->d.size, fp); +// if( len < a->d.size ) { +// if( ferror(fp) ) +// a->error = 1; +// } +// a->d.len = len; +// a->d.start = 0; +// return len? a->d.buf[a->d.start++] : -1; +// } + + + if( a->filter ) { + len = a->d.size; + rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, + a->d.buf, &len ); + if( DBG_IOBUF ) { + log_debug("iobuf-%d.%d: underflow: req=%lu got=%lu rc=%d\n", + a->no, a->subno, (ulong)a->d.size, (ulong)len, rc ); + #if 0 + if( a->no == 7 ) { + print_string(stderr, a->d.buf, len, 0 ); + putc('\n', stderr ); + } + #endif + + } + if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */ + size_t dummy_len; + + /* and tell the filter to free itself */ + if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain, + NULL, &dummy_len)) ) +// log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) ); + log_error("IOBUFCTRL_FREE failed: %d\n", rc ); + if( a->filter_ov && a->filter_ov_owner ) { + m_free( a->filter_ov ); + a->filter_ov = NULL; + } + a->filter = NULL; + a->desc = NULL; + a->filter_ov = NULL; + a->filter_eof = 1; + if( !len && a->chain ) { + IOBUF b = a->chain; + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n", + a->no, a->subno, a->desc ); + print_chain(a); + m_free(a->d.buf); + m_free(a->real_fname); + memcpy(a,b, sizeof *a); + m_free(b); + print_chain(a); + } + } + else if( rc ) + a->error = 1; + + if( !len ) { + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno ); + return -1; + } + a->d.len = len; + a->d.start = 0; + return a->d.buf[a->d.start++]; + } + else { + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: underflow: eof (no filter)\n", + a->no, a->subno ); + return -1; /* no filter; return EOF */ + } +} + + +int +iobuf_flush(IOBUF a) +{ + size_t len; + int rc; + + trace(); + + if( a->directfp ) + return 0; + + /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/ + if( a->use == 3 ) { /* increase the temp buffer */ + char *newbuf; + size_t newsize = a->d.size + 8192; + + log_debug("increasing temp iobuf from %lu to %lu\n", + (ulong)a->d.size, (ulong)newsize ); + newbuf = m_alloc( newsize ); + memcpy( newbuf, a->d.buf, a->d.len ); + m_free(a->d.buf); + a->d.buf = newbuf; + a->d.size = newsize; + return 0; + } + else if( a->use != 2 ) + log_bug("flush on non-output iobuf\n"); + else if( !a->filter ) + log_bug("iobuf_flush: no filter\n"); + len = a->d.len; + rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len ); + if( !rc && len != a->d.len ) { + log_info("iobuf_flush did not write all!\n"); + rc = G10ERR_WRITE_FILE; + } + else if( rc ) + a->error = 1; + a->d.len = 0; + + return rc; +} + + +/**************** + * Read a byte from the iobuf; returns -1 on EOF + */ +int +iobuf_readbyte(IOBUF a) +{ + int c; + + trace(); + + /* nlimit does not work together with unget */ + /* nbytes is also not valid! */ + if( a->unget.buf ) { + if( a->unget.start < a->unget.len ) + return a->unget.buf[a->unget.start++]; + m_free(a->unget.buf); + a->unget.buf = NULL; + a->nofast &= ~2; + } + + if( a->nlimit && a->nbytes >= a->nlimit ) { + dbg (__FUNCTION__ ": forced EOF"); + return -1; /* forced EOF */ + } + + if( a->d.start < a->d.len ) { + c = a->d.buf[a->d.start++]; + } + else if( (c=underflow(a)) == -1 ) { + dbg (__FUNCTION__ ": EOF"); + return -1; /* EOF */ + } + + a->nbytes++; + return c; +} + + +int +iobuf_read(IOBUF a, byte *buf, unsigned buflen ) +{ + int c, n; + + trace(); + + if( a->unget.buf || a->nlimit ) { + /* handle special cases */ + for(n=0 ; n < buflen; n++ ) { + if( (c = iobuf_readbyte(a)) == -1 ) { + if( !n ) + return -1; /* eof */ + break; + } + else + if( buf ) *buf = c; + if( buf ) buf++; + } + return n; + } + + n = 0; + do { + if( n < buflen && a->d.start < a->d.len ) { + unsigned size = a->d.len - a->d.start; + if( size > buflen - n ) + size = buflen - n; + if( buf ) + memcpy( buf, a->d.buf + a->d.start, size ); + n += size; + a->d.start += size; + if( buf ) + buf += size; + } + if( n < buflen ) { + if( (c=underflow(a)) == -1 ) { + a->nbytes += n; + return n? n : -1/*EOF*/; + } + if( buf ) + *buf++ = c; + n++; + } + } while( n < buflen ); + a->nbytes += n; + return n; +} + + +/**************** + * Have a look at the iobuf. + * NOTE: This only works in special cases. + */ +int +iobuf_peek(IOBUF a, byte *buf, unsigned buflen ) +{ + int n=0; + + trace(); + + if( a->filter_eof ) + return -1; + + if( !(a->d.start < a->d.len) ) { + if( underflow(a) == -1 ) + return -1; + /* and unget this character */ +// assert(a->d.start == 1); + a->d.start = 0; + } + + for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ ) + *buf = a->d.buf[n]; + return n; +} + + + + +int +iobuf_writebyte(IOBUF a, unsigned c) +{ + + trace(); + + if( a->directfp ) + BUG(); + + if( a->d.len == a->d.size ) + if( iobuf_flush(a) ) + return -1; + +// assert( a->d.len < a->d.size ); + a->d.buf[a->d.len++] = c; + return 0; +} + + +int +iobuf_write(IOBUF a, byte *buf, unsigned buflen ) +{ + + trace(); + + dbg (__FUNCTION__ ": buflen = %d", buflen); + + if( a->directfp ) + BUG(); + + do { + if( buflen && a->d.len < a->d.size ) { + unsigned size = a->d.size - a->d.len; + if( size > buflen ) size = buflen; + memcpy( a->d.buf + a->d.len, buf, size ); + buflen -= size; + buf += size; + a->d.len += size; + } + if( buflen ) { + if( iobuf_flush(a) ) { + dbg (__FUNCTION__ ": buflen = %d, returning -1", buflen); + return -1; + } + } + } while( buflen ); + return 0; +} + + +int +iobuf_writestr(IOBUF a, const char *buf ) +{ + trace(); + + for( ; *buf; buf++ ) + if( iobuf_writebyte(a, *buf) ) + return -1; + return 0; +} + + + +/**************** + * copy the contents of TEMP to A. + */ +int +iobuf_write_temp( IOBUF a, IOBUF temp ) +{ + trace(); + + while( temp->chain ) + pop_filter( temp, temp->filter, NULL ); + return iobuf_write(a, temp->d.buf, temp->d.len ); +} + +///**************** +// * copy the contents of the temp io stream to BUFFER. +// */ +//size_t +//iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ) +//{ +// size_t n = a->d.len; +// +// if( n > buflen ) +// n = buflen; +// memcpy( buffer, a->d.buf, n ); +// return n; +//} +// +// +///**************** +// * Call this function to terminate processing of the temp stream +// * without closing it. This removes all filters from the stream +// * makes sure that iobuf_get_temp_{buffer,length}() returns correct +// * values. +// */ +//void +//iobuf_flush_temp( IOBUF temp ) +//{ +// while( temp->chain ) +// pop_filter( temp, temp->filter, NULL ); +//} +// +// +///**************** +// * Set a limit on how many bytes may be read from the input stream A. +// * Setting the limit to 0 disables this feature. +// */ +//void +//iobuf_set_limit( IOBUF a, unsigned long nlimit ) +//{ +// if( nlimit ) +// a->nofast |= 1; +// else +// a->nofast &= ~1; +// a->nlimit = nlimit; +// a->ntotal += a->nbytes; +// a->nbytes = 0; +//} +// +// +// +///**************** +// * Return the length of an open file +// */ +//u32 +//iobuf_get_filelength( IOBUF a ) +//{ +// struct stat st; +// +// if( a->directfp ) { +// FILE *fp = a->directfp; +// +// if( !fstat(fileno(fp), &st) ) +// return st.st_size; +// log_error("fstat() failed: %s\n", strerror(errno) ); +// return 0; +// } +// +// /* Hmmm: file_filter may have already been removed */ +// for( ; a; a = a->chain ) +// if( !a->chain && a->filter == file_filter ) { +// file_filter_ctx_t *b = a->filter_ov; +// FILE *fp = b->fp; +// +// if( !fstat(fileno(fp), &st) ) +// return st.st_size; +// log_error("fstat() failed: %s\n", strerror(errno) ); +// break; +// } +// +// return 0; +//} + +/**************** + * Tell the file position, where the next read will take place + */ +ulong +iobuf_tell( IOBUF a ) +{ + trace(); + + return a->ntotal + a->nbytes; +} + + + +///**************** +// * This is a very limited implementation. It simply discards all internal +// * buffering and removes all filters but the first one. +// */ +//int +//iobuf_seek( IOBUF a, ulong newpos ) +//{ +// file_filter_ctx_t *b = NULL; +// +// if( a->directfp ) { +// FILE *fp = a->directfp; +// if( fseek( fp, newpos, SEEK_SET ) ) { +// log_error("can't seek to %lu: %s\n", newpos, strerror(errno) ); +// return -1; +// } +// clearerr(fp); +// } +// else { +// for( ; a; a = a->chain ) { +// if( !a->chain && a->filter == file_filter ) { +// b = a->filter_ov; +// break; +// } +// } +// if( !a ) +// return -1; +// if( fseek( b->fp, newpos, SEEK_SET ) ) { +// log_error("can't seek to %lu: %s\n", newpos, strerror(errno) ); +// return -1; +// } +// } +// a->d.len = 0; /* discard buffer */ +// a->d.start = 0; +// a->nbytes = 0; +// a->nlimit = 0; +// a->nofast &= ~1; +// a->ntotal = newpos; +// a->error = 0; +// /* remove filters, but the last */ +// if( a->chain ) +// log_debug("pop_filter called in iobuf_seek - please report\n"); +// while( a->chain ) +// pop_filter( a, a->filter, NULL ); +// +// return 0; +//} +// +// +// +// +// +// +///**************** +// * Retrieve the real filename +// */ +//const char * +//iobuf_get_real_fname( IOBUF a ) +//{ +// if( a->real_fname ) +// return a->real_fname; +// +// /* the old solution */ +// for( ; a; a = a->chain ) +// if( !a->chain && a->filter == file_filter ) { +// file_filter_ctx_t *b = a->filter_ov; +// return b->print_only_name? NULL : b->fname; +// } +// +// return NULL; +//} +// +// +/**************** + * Retrieve the filename + */ +const char * +iobuf_get_fname( IOBUF a ) +{ +// for( ; a; a = a->chain ) +// if( !a->chain && a->filter == file_filter ) { +// file_filter_ctx_t *b = a->filter_ov; +// return b->fname; +// } + + trace(); + + return NULL; +} + +/**************** + * Start the block write mode, see rfc1991.new for details. + * A value of 0 for N stops this mode (flushes and writes + * the end marker) + */ +void +iobuf_set_block_mode( IOBUF a, size_t n ) +{ + block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx ); + + trace(); + +// assert( a->use == 1 || a->use == 2 ); + ctx->use = a->use; + if( !n ) { + if( a->use == 1 ) + log_debug("pop_filter called in set_block_mode - please report\n"); + pop_filter(a, block_filter, NULL ); + } + else { + ctx->size = n; /* only needed for use 2 */ + iobuf_push_filter(a, block_filter, ctx ); + } +} + +/**************** + * enable partial block mode as described in the OpenPGP draft. + * LEN is the first length byte on read, but ignored on writes. + */ +void +iobuf_set_partial_block_mode( IOBUF a, size_t len ) +{ + block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx ); + + trace(); + +// assert( a->use == 1 || a->use == 2 ); + ctx->use = a->use; + if( !len ) { + if( a->use == 1 ) + log_debug("pop_filter called in set_partial_block_mode" + " - please report\n"); + pop_filter(a, block_filter, NULL ); + } + else { + ctx->partial = 1; + ctx->size = 0; + ctx->first_c = len; + iobuf_push_filter(a, block_filter, ctx ); + } +} + + +/**************** + * Checks whether the stream is in block mode + * Note: This does not work if other filters are pushed on the stream. + */ +int +iobuf_in_block_mode( IOBUF a ) +{ + trace(); + + if( a && a->filter == block_filter ) + return 1; /* yes */ + return 0; /* no */ +} + + +/**************** + * Same as fgets() but if the buffer is too short a larger one will + * be allocated up to some limit *max_length. + * A line is considered a byte stream ending in a LF. + * Returns the length of the line. EOF is indicated by a line of + * length zero. The last LF may be missing due to an EOF. + * is max_length is zero on return, the line has been truncated. + * + * Note: The buffer is allocated with enough space to append a CR,LF,EOL + */ +unsigned +iobuf_read_line( IOBUF a, byte **addr_of_buffer, + unsigned *length_of_buffer, unsigned *max_length ) +{ + int c; + char *buffer = *addr_of_buffer; + unsigned length = *length_of_buffer; + unsigned nbytes = 0; + unsigned maxlen = *max_length; + char *p; + + trace(); + + if( !buffer ) { /* must allocate a new buffer */ + length = 256; + buffer = m_alloc( length ); + *addr_of_buffer = buffer; + *length_of_buffer = length; + } + + length -= 3; /* reserve 3 bytes (cr,lf,eol) */ + p = buffer; + while( (c=iobuf_get(a)) != -1 ) { + if( nbytes == length ) { /* increase the buffer */ + if( length > maxlen ) { /* this is out limit */ + /* skip the rest of the line */ + while( c != '\n' && (c=iobuf_get(a)) != -1 ) + ; + *p++ = '\n'; /* always append a LF (we have reserved space) */ + nbytes++; + *max_length = 0; /* indicate truncation */ + break; + } + length += 3; /* correct for the reserved byte */ + length += length < 1024? 256 : 1024; + buffer = m_realloc( buffer, length ); + *addr_of_buffer = buffer; + *length_of_buffer = length; + length -= 3; /* and reserve again */ + p = buffer + nbytes; + } + *p++ = c; + nbytes++; + if( c == '\n' ) + break; + } + *p = 0; /* make sure the line is a string */ + + return nbytes; +} + diff -Nru a/security/cryptomark/gnupg/iobuf.h b/security/cryptomark/gnupg/iobuf.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/iobuf.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,148 @@ +/* iobuf.h - I/O buffer + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_IOBUF_H +#define G10_IOBUF_H + +#include "types.h" + + +#define DBG_IOBUF iobuf_debug_mode + + +#define IOBUFCTRL_INIT 1 +#define IOBUFCTRL_FREE 2 +#define IOBUFCTRL_UNDERFLOW 3 +#define IOBUFCTRL_FLUSH 4 +#define IOBUFCTRL_DESC 5 +#define IOBUFCTRL_CANCEL 6 +#define IOBUFCTRL_USER 16 + +typedef struct iobuf_struct *IOBUF; + +/* fixme: we should hide most of this stuff */ +struct iobuf_struct { + int use; /* 1 input , 2 output, 3 temp */ + unsigned long nlimit; + unsigned long nbytes; /* used together with nlimit */ + unsigned long ntotal; /* total bytes read (position of stream) */ + int nofast; /* used by the iobuf_get() */ + void *directfp; + struct { + size_t size; /* allocated size */ + size_t start; /* number of invalid bytes at the begin of the buffer */ + size_t len; /* currently filled to this size */ + byte *buf; + } d; + int filter_eof; + int error; + int (*filter)( void *opaque, int control, + IOBUF chain, byte *buf, size_t *len); + void *filter_ov; /* value for opaque */ + int filter_ov_owner; + char *real_fname; + IOBUF chain; /* next iobuf used for i/o if any (passed to filter) */ + int no, subno; + const char *desc; + void *opaque; /* can be used to hold any information */ + /* this value is copied to all instances */ + struct { + size_t size; /* allocated size */ + size_t start; /* number of invalid bytes at the begin of the buffer */ + size_t len; /* currently filled to this size */ + byte *buf; + } unget; +}; + +int iobuf_debug_mode; + +IOBUF iobuf_alloc(int use, size_t bufsize); +IOBUF iobuf_temp(void); +IOBUF iobuf_temp_with_content( const char *buffer, size_t length ); +IOBUF iobuf_open( const char *fname ); +IOBUF iobuf_fdopen( int fd, const char *mode ); +IOBUF iobuf_fopen( const char *fname, const char *mode ); +IOBUF iobuf_create( const char *fname ); +IOBUF iobuf_append( const char *fname ); +IOBUF iobuf_openrw( const char *fname ); +int iobuf_close( IOBUF iobuf ); +int iobuf_cancel( IOBUF iobuf ); + +int iobuf_push_filter( IOBUF a, int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), void *ov ); +int iobuf_push_filter2( IOBUF a, + int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), + void *ov, int rel_ov ); +int iobuf_flush(IOBUF a); +void iobuf_clear_eof(IOBUF a); +#define iobuf_set_error(a) do { (a)->error = 1; } while(0) +#define iobuf_error(a) ((a)->error) + +void iobuf_set_limit( IOBUF a, unsigned long nlimit ); + +ulong iobuf_tell( IOBUF a ); +int iobuf_seek( IOBUF a, ulong newpos ); + +int iobuf_readbyte(IOBUF a); +int iobuf_read(IOBUF a, byte *buf, unsigned buflen ); +unsigned iobuf_read_line( IOBUF a, byte **addr_of_buffer, + unsigned *length_of_buffer, unsigned *max_length ); +int iobuf_peek(IOBUF a, byte *buf, unsigned buflen ); +int iobuf_writebyte(IOBUF a, unsigned c); +int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); +int iobuf_writestr(IOBUF a, const char *buf ); + +void iobuf_flush_temp( IOBUF temp ); +int iobuf_write_temp( IOBUF a, IOBUF temp ); +size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); +void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ); + +u32 iobuf_get_filelength( IOBUF a ); +const char *iobuf_get_real_fname( IOBUF a ); +const char *iobuf_get_fname( IOBUF a ); + +void iobuf_set_block_mode( IOBUF a, size_t n ); +void iobuf_set_partial_block_mode( IOBUF a, size_t len ); +int iobuf_in_block_mode( IOBUF a ); + +/* get a byte form the iobuf; must check for eof prior to this function + * this function returns values in the range 0 .. 255 or -1 to indicate EOF + * iobuf_get_noeof() does not return -1 to indicate EOF, but masks the + * returned value to be in the range 0 ..255. + */ +#define iobuf_get(a) \ + ( ((a)->nofast || (a)->d.start >= (a)->d.len )? \ + iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) ) +#define iobuf_get_noeof(a) (iobuf_get((a))&0xff) + +/* write a byte to the iobuf and return true on write error + * This macro does only write the low order byte + */ +#define iobuf_put(a,c) iobuf_writebyte(a,c) + +#define iobuf_where(a) "[don't know]" +#define iobuf_id(a) ((a)->no) + +#define iobuf_get_temp_buffer(a) ( (a)->d.buf ) +#define iobuf_get_temp_length(a) ( (a)->d.len ) +#define iobuf_is_temp(a) ( (a)->use == 3 ) + +#endif /*G10_IOBUF_H*/ diff -Nru a/security/cryptomark/gnupg/kbnode.c b/security/cryptomark/gnupg/kbnode.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/kbnode.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,410 @@ +/* kbnode.c - keyblock node utility functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "memory.h" +#include "packet.h" +#include "keydb.h" + +#define USE_UNUSED_NODES 1 + +static KBNODE unused_nodes; + +static KBNODE +alloc_node(void) +{ + KBNODE n; + + trace(); + + n = unused_nodes; + if( n ) + unused_nodes = n->next; + else + n = m_alloc( sizeof *n ); + n->next = NULL; + n->pkt = NULL; + n->flag = 0; + n->private_flag=0; + n->recno = 0; + return n; +} + +static void +free_node( KBNODE n ) +{ + trace(); + + if( n ) { + #if USE_UNUSED_NODES + n->next = unused_nodes; + unused_nodes = n; + #else + m_free( n ); + #endif + } +} + + + +KBNODE +new_kbnode( PACKET *pkt ) +{ + KBNODE n = alloc_node(); + trace(); + + n->pkt = pkt; + return n; +} + + +//KBNODE +//clone_kbnode( KBNODE node ) +//{ +// KBNODE n = alloc_node(); +// +// n->pkt = node->pkt; +// n->private_flag = node->private_flag | 2; /* mark cloned */ +// return n; +//} + + +void +release_kbnode( KBNODE n ) +{ + KBNODE n2; + + trace(); + + while( n ) { + n2 = n->next; + if( !is_cloned_kbnode(n) ) { + free_packet( n->pkt ); + m_free( n->pkt ); + } + free_node( n ); + n = n2; + } +} + + +///**************** +// * Delete NODE. +// * Note: This only works with walk_kbnode!! +// */ +//void +//delete_kbnode( KBNODE node ) +//{ +// node->private_flag |= 1; +//} +// + + +/**************** + * Append NODE to ROOT. ROOT must exist! + */ +void +add_kbnode( KBNODE root, KBNODE node ) +{ + KBNODE n1; + + trace(); + + for(n1=root; n1->next; n1 = n1->next) + ; + n1->next = node; +} + +///**************** +// * Insert NODE into the list after root but before a packet which is not of +// * type PKTTYPE +// * (only if PKTTYPE != 0) +// */ +//void +//insert_kbnode( KBNODE root, KBNODE node, int pkttype ) +//{ +// if( !pkttype ) { +// node->next = root->next; +// root->next = node; +// } +// else { +// KBNODE n1; +// +// for(n1=root; n1->next; n1 = n1->next) +// if( pkttype != n1->next->pkt->pkttype ) { +// node->next = n1->next; +// n1->next = node; +// return; +// } +// /* no such packet, append */ +// node->next = NULL; +// n1->next = node; +// } +//} +// + +/**************** + * Find the previous node (if PKTTYPE = 0) or the previous node + * with pkttype PKTTYPE in the list starting with ROOT of NODE. + */ +KBNODE +find_prev_kbnode( KBNODE root, KBNODE node, int pkttype ) +{ + KBNODE n1; + + trace(); + + for(n1=NULL ; root && root != node; root = root->next ) + if( !pkttype || root->pkt->pkttype == pkttype ) + n1 = root; + return n1; +} + +/**************** + * Ditto, but find the next packet. The behaviour is trivial if + * PKTTYPE is 0 but if it is specified, the next node with a packet + * of this type is returned. The function has some knowledge about + * the valid ordering of packets: e.g. if the next signature packet + * is requested, the function will not return one if it encounters + * a user-id. + */ +KBNODE +find_next_kbnode( KBNODE node, int pkttype ) +{ + trace(); + + for( node=node->next ; node; node = node->next ) { + if( !pkttype ) { + dbg (__FUNCTION__":0 returning node"); + return node; + } + else if( pkttype == PKT_USER_ID + && ( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_SECRET_KEY ) ) { + dbg (__FUNCTION__":1 returning NULL"); + return NULL; + } + else if( pkttype == PKT_SIGNATURE + && ( node->pkt->pkttype == PKT_USER_ID + || node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_SECRET_KEY ) ) { + dbg (__FUNCTION__":2 returning NULL"); + return NULL; + } + else if( node->pkt->pkttype == pkttype ) { + dbg (__FUNCTION__":3 returning node"); + return node; + } + } + + dbg (__FUNCTION__":4 returning NULL"); + return NULL; +} + + +KBNODE +find_kbnode( KBNODE node, int pkttype ) +{ + trace(); + + for( ; node; node = node->next ) { + if( node->pkt->pkttype == pkttype ) + return node; + } + return NULL; +} + + +// +///**************** +// * Walk through a list of kbnodes. This function returns +// * the next kbnode for each call; before using the function the first +// * time, the caller must set CONTEXT to NULL (This has simply the effect +// * to start with ROOT). +// */ +//KBNODE +//walk_kbnode( KBNODE root, KBNODE *context, int all ) +//{ +// KBNODE n; +// +// do { +// if( !*context ) { +// *context = root; +// n = root; +// } +// else { +// n = (*context)->next; +// *context = n; +// } +// } while( !all && n && is_deleted_kbnode(n) ); +// +// return n; +//} +// +//void +//clear_kbnode_flags( KBNODE n ) +//{ +// for( ; n; n = n->next ) { +// n->flag = 0; +// } +//} +// +// +///**************** +// * Commit changes made to the kblist at ROOT. Note that ROOT my change, +// * and it is therefore passed by reference. +// * The function has the effect of removing all nodes marked as deleted. +// * returns true if any node has been changed +// */ +//int +//commit_kbnode( KBNODE *root ) +//{ +// KBNODE n, nl; +// int changed = 0; +// +// for( n = *root, nl=NULL; n; n = nl->next ) { +// if( is_deleted_kbnode(n) ) { +// if( n == *root ) +// *root = nl = n->next; +// else +// nl->next = n->next; +// if( !is_cloned_kbnode(n) ) { +// free_packet( n->pkt ); +// m_free( n->pkt ); +// } +// free_node( n ); +// changed = 1; +// } +// else +// nl = n; +// } +// return changed; +//} +// +//void +//remove_kbnode( KBNODE *root, KBNODE node ) +//{ +// KBNODE n, nl; +// +// for( n = *root, nl=NULL; n; n = nl->next ) { +// if( n == node ) { +// if( n == *root ) +// *root = nl = n->next; +// else +// nl->next = n->next; +// if( !is_cloned_kbnode(n) ) { +// free_packet( n->pkt ); +// m_free( n->pkt ); +// } +// free_node( n ); +// } +// else +// nl = n; +// } +//} +// +// +///**************** +// * Move NODE behind right after WHERE or to the beginning if WHERE is NULL. +// */ +//void +//move_kbnode( KBNODE *root, KBNODE node, KBNODE where ) +//{ +// KBNODE tmp, prev; +// +// if( !root || !*root || !node ) +// return; /* sanity check */ +// for( prev = *root; prev && prev->next != node; prev = prev->next ) +// ; +// if( !prev ) +// return; /* node is not in the list */ +// +// if( !where ) { /* move node before root */ +// if( node == *root ) /* move to itself */ +// return; +// prev->next = node->next; +// node->next = *root; +// *root = node; +// return; +// } +// /* move it after where */ +// if( node == where ) +// return; +// tmp = node->next; +// node->next = where->next; +// where->next = node; +// prev->next = tmp; +//} +// +// +// +// +//void +//dump_kbnode( KBNODE node ) +//{ +// for(; node; node = node->next ) { +// const char *s; +// switch( node->pkt->pkttype ) { +// case 0: s="empty"; break; +// case PKT_PUBLIC_KEY: s="public-key"; break; +// case PKT_SECRET_KEY: s="secret-key"; break; +// case PKT_SECRET_SUBKEY: s= "secret-subkey"; break; +// case PKT_PUBKEY_ENC: s="public-enc"; break; +// case PKT_SIGNATURE: s="signature"; break; +// case PKT_ONEPASS_SIG: s="onepass-sig"; break; +// case PKT_USER_ID: s="user-id"; break; +// case PKT_PUBLIC_SUBKEY: s="public-subkey"; break; +// case PKT_COMMENT: s="comment"; break; +// case PKT_RING_TRUST: s="trust"; break; +// case PKT_PLAINTEXT: s="plaintext"; break; +// case PKT_COMPRESSED: s="compressed"; break; +// case PKT_ENCRYPTED: s="encrypted"; break; +// default: s="unknown"; break; +// } +// fprintf(stderr, "node %p %02x/%02x type=%s", +// node, node->flag, node->private_flag, s); +// if( node->pkt->pkttype == PKT_USER_ID ) { +// fputs(" \"", stderr); +// print_string( stderr, node->pkt->pkt.user_id->name, +// node->pkt->pkt.user_id->len, 0 ); +// fputs("\"\n", stderr); +// } +// else if( node->pkt->pkttype == PKT_SIGNATURE ) { +// fprintf(stderr, " class=%02x keyid=%08lX\n", +// node->pkt->pkt.signature->sig_class, +// (ulong)node->pkt->pkt.signature->keyid[1] ); +// } +// else if( node->pkt->pkttype == PKT_PUBLIC_KEY +// || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { +// fprintf(stderr, " keyid=%08lX\n", (ulong) +// keyid_from_pk( node->pkt->pkt.public_key, NULL )); +// } +// else +// fputs("\n", stderr); +// } +//} +// diff -Nru a/security/cryptomark/gnupg/keydb.h b/security/cryptomark/gnupg/keydb.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/keydb.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,221 @@ +/* keydb.h - Key database + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_KEYDB_H +#define G10_KEYDB_H + +#ifdef HAVE_LIBGDBM + #include +#endif + +#include "types.h" +#include "packet.h" +#include "cipher.h" + +#define MAX_FINGERPRINT_LEN 20 + +struct getkey_ctx_s; +typedef struct getkey_ctx_s *GETKEY_CTX; + +/**************** + * A Keyblock is all packets which form an entire certificate; + * i.e. the public key, certificate, trust packets, user ids, + * signatures, and subkey. + * + * This structure is also used to bind arbitrary packets together. + */ + +typedef struct kbnode_struct *KBNODE; +struct kbnode_struct { + KBNODE next; + PACKET *pkt; + int flag; + int private_flag; + ulong recno; /* used while updating the trustdb */ +}; + +#define is_deleted_kbnode(a) ((a)->private_flag & 1) +#define is_cloned_kbnode(a) ((a)->private_flag & 2) + + +enum resource_type { + rt_UNKNOWN = 0, + rt_RING = 1, + rt_GDBM = 2 +}; + + +/**************** + * A data structre to hold information about the external position + * of a keyblock. + */ +struct keyblock_pos_struct { + int resno; /* resource number */ + enum resource_type rt; + ulong offset; /* position information */ + unsigned count; /* length of the keyblock in packets */ + IOBUF fp; /* used by enum_keyblocks */ + int secret; /* working on a secret keyring */ + #ifdef HAVE_LIBGDBM + GDBM_FILE dbf; + byte keybuf[21]; + #endif + PACKET *pkt; /* ditto */ + int valid; +}; +typedef struct keyblock_pos_struct KBPOS; + +/* structure to hold a couple of public key certificates */ +typedef struct pk_list *PK_LIST; +struct pk_list { + PK_LIST next; + PKT_public_key *pk; + int mark; +}; + +/* structure to hold a couple of secret key certificates */ +typedef struct sk_list *SK_LIST; +struct sk_list { + SK_LIST next; + PKT_secret_key *sk; + int mark; +}; + +/* structure to collect all information which can be used to + * identify a public key */ +typedef struct pubkey_find_info *PUBKEY_FIND_INFO; +struct pubkey_find_info { + u32 keyid[2]; + unsigned nbits; + byte pubkey_algo; + byte fingerprint[MAX_FINGERPRINT_LEN]; + char userid[1]; +}; + + + +/*-- pkclist.c --*/ +int check_signatures_trust( PKT_signature *sig ); +void release_pk_list( PK_LIST pk_list ); +int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ); +int select_algo_from_prefs( PK_LIST pk_list, int preftype ); + +/*-- skclist.c --*/ +void release_sk_list( SK_LIST sk_list ); +int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, + int unlock, unsigned use ); + +/*-- passphrase.h --*/ +int have_static_passphrase(void); +void read_passphrase_from_fd( int fd ); +DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo, + int cipher_algo, STRING2KEY *s2k, int mode); +void set_next_passphrase( const char *s ); +char *get_last_passphrase(void); + +/*-- getkey.c --*/ +int classify_user_id( const char *name, u32 *keyid, byte *fprint, + const char **retstr, size_t *retlen ); +void getkey_disable_caches(void); +int get_pubkey( PKT_public_key *pk, u32 *keyid ); +KBNODE get_pubkeyblock( u32 *keyid ); +int get_pubkey_byname( GETKEY_CTX *rx, PKT_public_key *pk, + const char *name, KBNODE *ret_keyblock ); +int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk, + STRLIST names, KBNODE *ret_keyblock ); +int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ); +void get_pubkey_end( GETKEY_CTX ctx ); +int get_seckey( PKT_secret_key *sk, u32 *keyid ); +int get_primary_seckey( PKT_secret_key *sk, u32 *keyid ); +int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, + size_t fprint_len ); +int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ); +int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid ); +int seckey_available( u32 *keyid ); +int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ); +int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk, + STRLIST names, KBNODE *ret_keyblock ); +int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ); +void get_seckey_end( GETKEY_CTX ctx ); +int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ); +void merge_keys_and_selfsig( KBNODE keyblock ); +char*get_user_id_string( u32 *keyid ); +char*get_user_id_string_native( u32 *keyid ); +char*get_long_user_id_string( u32 *keyid ); +char*get_user_id( u32 *keyid, size_t *rn ); + +/*-- keyid.c --*/ +int pubkey_letter( int algo ); +u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid ); +u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ); +u32 keyid_from_sig( PKT_signature *sig, u32 *keyid ); +u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ); +unsigned nbits_from_pk( PKT_public_key *pk ); +unsigned nbits_from_sk( PKT_secret_key *sk ); +const char *datestr_from_pk( PKT_public_key *pk ); +const char *datestr_from_sk( PKT_secret_key *sk ); +const char *datestr_from_sig( PKT_signature *sig ); +const char *expirestr_from_pk( PKT_public_key *pk ); +const char *expirestr_from_sk( PKT_secret_key *sk ); +byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len ); +byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); + +/*-- kbnode.c --*/ +KBNODE new_kbnode( PACKET *pkt ); +KBNODE clone_kbnode( KBNODE node ); +void release_kbnode( KBNODE n ); +void delete_kbnode( KBNODE node ); +void add_kbnode( KBNODE root, KBNODE node ); +void insert_kbnode( KBNODE root, KBNODE node, int pkttype ); +void move_kbnode( KBNODE *root, KBNODE node, KBNODE where ); +void remove_kbnode( KBNODE *root, KBNODE node ); +KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype ); +KBNODE find_next_kbnode( KBNODE node, int pkttype ); +KBNODE find_kbnode( KBNODE node, int pkttype ); +KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all ); +void clear_kbnode_flags( KBNODE n ); +int commit_kbnode( KBNODE *root ); +void dump_kbnode( KBNODE node ); + +/*-- ringedit.c --*/ +const char *enum_keyblock_resources( int *sequence, int secret ); +int add_keyblock_resource( const char *resname, int force, int secret ); +const char *keyblock_resource_name( KBPOS *kbpos ); +int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ); +int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, + int fprlen, int secret ); +int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, + int shortkid, int secret ); +int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos ); +int find_keyblock_byname( KBPOS *kbpos, const char *username ); +int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ); +int find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ); +int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ); +int lock_keyblock( KBPOS *kbpos ); +void unlock_keyblock( KBPOS *kbpos ); +int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); +int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ); +int insert_keyblock( KBPOS *kbpos, KBNODE root ); +int delete_keyblock( KBPOS *kbpos ); +int update_keyblock( KBPOS *kbpos, KBNODE root ); + + +#endif /*G10_KEYDB_H*/ diff -Nru a/security/cryptomark/gnupg/keyid.c b/security/cryptomark/gnupg/keyid.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/keyid.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,442 @@ +/* keyid.c - jeyid and fingerprint handling + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "main.h" +#include "packet.h" +#include "options.h" +#include "mpi.h" +#include "keydb.h" + + +//int +//pubkey_letter( int algo ) +//{ +// switch( algo ) { +// case PUBKEY_ALGO_RSA: return 'R' ; +// case PUBKEY_ALGO_RSA_E: return 'r' ; +// case PUBKEY_ALGO_RSA_S: return 's' ; +// case PUBKEY_ALGO_ELGAMAL_E: return 'g'; +// case PUBKEY_ALGO_ELGAMAL: return 'G' ; +// case PUBKEY_ALGO_DSA: return 'D' ; +// default: return '?'; +// } +//} +// + +static MD_HANDLE +do_fingerprint_md( PKT_public_key *pk ) +{ + MD_HANDLE md; + unsigned n; + unsigned nb[PUBKEY_MAX_NPKEY]; + unsigned nn[PUBKEY_MAX_NPKEY]; + byte *pp[PUBKEY_MAX_NPKEY]; + int i; + int npkey = pubkey_get_npkey( pk->pubkey_algo ); + + trace(); + + md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); + n = pk->version < 4 ? 8 : 6; + for(i=0; i < npkey; i++ ) { + nb[i] = mpi_get_nbits(pk->pkey[i]); + pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL ); + n += 2 + nn[i]; + } + + md_putc( md, 0x99 ); /* ctb */ + md_putc( md, n >> 8 ); /* 2 byte length header */ + md_putc( md, n ); + if( pk->version < 4 ) + md_putc( md, 3 ); + else + md_putc( md, 4 ); + + { u32 a = pk->timestamp; + md_putc( md, a >> 24 ); + md_putc( md, a >> 16 ); + md_putc( md, a >> 8 ); + md_putc( md, a ); + } + if( pk->version < 4 ) { + u16 a; + + if( pk->expiredate ) + a = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + a = 0; + md_putc( md, a >> 8 ); + md_putc( md, a ); + } + md_putc( md, pk->pubkey_algo ); + for(i=0; i < npkey; i++ ) { + md_putc( md, nb[i]>>8); + md_putc( md, nb[i] ); + md_write( md, pp[i], nn[i] ); + m_free(pp[i]); + } + md_final( md ); + + return md; +} + +static MD_HANDLE +do_fingerprint_md_sk( PKT_secret_key *sk ) +{ + PKT_public_key pk; + int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */ + int i; + + trace(); + + pk.pubkey_algo = sk->pubkey_algo; + pk.version = sk->version; + pk.timestamp = sk->timestamp; + pk.expiredate = sk->expiredate; + pk.pubkey_algo = sk->pubkey_algo; + for( i=0; i < npkey; i++ ) + pk.pkey[i] = sk->skey[i]; + return do_fingerprint_md( &pk ); +} + + +/**************** + * Get the keyid from the secret key and put it into keyid + * if this is not NULL. Return the 32 low bits of the keyid. + */ +u32 +keyid_from_sk( PKT_secret_key *sk, u32 *keyid ) +{ + u32 lowbits; + u32 dummy_keyid[2]; + + trace(); + + if( !keyid ) + keyid = dummy_keyid; + + if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { + lowbits = pubkey_get_npkey(sk->pubkey_algo) ? + mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */ + } + else { + const byte *dp; + MD_HANDLE md; + md = do_fingerprint_md_sk(sk); + dp = md_read( md, 0 ); + 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]; + md_close(md); + } + + return lowbits; +} + + +/**************** + * Get the keyid from the public key and put it into keyid + * if this is not NULL. Return the 32 low bits of the keyid. + */ +u32 +keyid_from_pk( PKT_public_key *pk, u32 *keyid ) +{ + u32 lowbits; + u32 dummy_keyid[2]; + + trace(); + + if( !keyid ) + keyid = dummy_keyid; + + if( pk->keyid[0] || pk->keyid[1] ) { + keyid[0] = pk->keyid[0]; + keyid[1] = pk->keyid[1]; + lowbits = keyid[1]; + } + else if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { + lowbits = pubkey_get_npkey(pk->pubkey_algo) ? + mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */ + pk->keyid[0] = keyid[0]; + pk->keyid[1] = keyid[1]; + } + else { + const byte *dp; + MD_HANDLE md; + md = do_fingerprint_md(pk); + dp = md_read( md, 0 ); + 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]; + md_close(md); + pk->keyid[0] = keyid[0]; + pk->keyid[1] = keyid[1]; + } + + return lowbits; +} + + +///**************** +// * Get the keyid from the fingerprint. This function is simple for most +// * keys, but has to do a keylookup for old stayle keys. +// */ +//u32 +//keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid ) +//{ +// u32 dummy_keyid[2]; +// +// if( !keyid ) +// keyid = dummy_keyid; +// +// if( fprint_len != 20 ) { +// /* This is special as we have to lookup the key first */ +// PKT_public_key pk; +// int rc; +// +// memset( &pk, 0, sizeof pk ); +// rc = get_pubkey_byfprint( &pk, fprint, fprint_len ); +// if( rc ) { +// log_error("Oops: keyid_from_fingerprint: no pubkey\n"); +// keyid[0] = 0; +// keyid[1] = 0; +// } +// else +// keyid_from_pk( &pk, keyid ); +// } +// else { +// const byte *dp = fprint; +// 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] ; +// } +// +// return keyid[1]; +//} +// +// +//u32 +//keyid_from_sig( PKT_signature *sig, u32 *keyid ) +//{ +// if( keyid ) { +// keyid[0] = sig->keyid[0]; +// keyid[1] = sig->keyid[1]; +// } +// return sig->keyid[1]; +//} +// +///**************** +// * return the number of bits used in the pk +// */ +//unsigned +//nbits_from_pk( PKT_public_key *pk ) +//{ +// return pubkey_nbits( pk->pubkey_algo, pk->pkey ); +//} +// +///**************** +// * return the number of bits used in the sk +// */ +//unsigned +//nbits_from_sk( PKT_secret_key *sk ) +//{ +// return pubkey_nbits( sk->pubkey_algo, sk->skey ); +//} +// +///**************** +// * return a string with the creation date of the pk +// * Note: this is alloced in a static buffer. +// * Format is: yyyy-mm-dd +// */ +//const char * +//datestr_from_pk( PKT_public_key *pk ) +//{ +// static char buffer[11+5]; +// struct tm *tp; +// time_t atime = pk->timestamp; +// +// tp = gmtime( &atime ); +// sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); +// return buffer; +//} +// +//const char * +//datestr_from_sk( PKT_secret_key *sk ) +//{ +// static char buffer[11+5]; +// struct tm *tp; +// time_t atime = sk->timestamp; +// +// tp = gmtime( &atime ); +// sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); +// return buffer; +//} +// +//const char * +//datestr_from_sig( PKT_signature *sig ) +//{ +// static char buffer[11+5]; +// struct tm *tp; +// time_t atime = sig->timestamp; +// +// tp = gmtime( &atime ); +// sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); +// return buffer; +//} +// +// +//const char * +//expirestr_from_pk( PKT_public_key *pk ) +//{ +// static char buffer[11+5]; +// struct tm *tp; +// time_t atime; +// +// if( !pk->expiredate ) +// return "never "; +// atime = pk->expiredate; +// tp = gmtime( &atime ); +// sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); +// return buffer; +//} +// +//const char * +//expirestr_from_sk( PKT_secret_key *sk ) +//{ +// static char buffer[11+5]; +// struct tm *tp; +// time_t atime; +// +// if( !sk->expiredate ) +// return "never "; +// atime = sk->expiredate; +// tp = gmtime( &atime ); +// sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); +// return buffer; +//} +// + +/**************** . + * Return a byte array with the fingerprint for the given PK/SK + * The length of the array is returned in ret_len. Caller must free + * the array or provide an array of length MAX_FINGERPRINT_LEN. + */ + +byte * +fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) +{ + byte *p, *buf; + const char *dp; + size_t len; + unsigned n; + + trace(); + + if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { + /* RSA in version 3 packets is special */ + MD_HANDLE md; + + md = md_open( DIGEST_ALGO_MD5, 0); + if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) { + p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + } + md_final(md); + if( !array ) + array = m_alloc( 16 ); + len = 16; + memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); + md_close(md); + } + else { + MD_HANDLE md; + md = do_fingerprint_md(pk); + dp = md_read( md, 0 ); + len = md_digest_length( md_get_algo( md ) ); +// assert( len <= MAX_FINGERPRINT_LEN ); + if( !array ) + array = m_alloc( len ); + memcpy(array, dp, len ); + md_close(md); + } + + *ret_len = len; + return array; +} + +//byte * +//fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) +//{ +// byte *p, *buf; +// const char *dp; +// size_t len; +// unsigned n; +// +// if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { +// /* RSA in version 3 packets is special */ +// MD_HANDLE md; +// +// md = md_open( DIGEST_ALGO_MD5, 0); +// if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) { +// p = buf = mpi_get_buffer( sk->skey[1], &n, NULL ); +// md_write( md, p, n ); +// m_free(buf); +// p = buf = mpi_get_buffer( sk->skey[0], &n, NULL ); +// md_write( md, p, n ); +// m_free(buf); +// } +// md_final(md); +// if( !array ) +// array = m_alloc( 16 ); +// len = 16; +// memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); +// md_close(md); +// } +// else { +// MD_HANDLE md; +// md = do_fingerprint_md_sk(sk); +// dp = md_read( md, 0 ); +// len = md_digest_length( md_get_algo( md ) ); +// assert( len <= MAX_FINGERPRINT_LEN ); +// if( !array ) +// array = m_alloc( len ); +// memcpy(array, dp, len ); +// md_close(md); +// } +// +// *ret_len = len; +// return array; +//} + + + diff -Nru a/security/cryptomark/gnupg/main.h b/security/cryptomark/gnupg/main.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/main.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,156 @@ +/* main.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_MAIN_H +#define G10_MAIN_H +#include "types.h" +#include "iobuf.h" +#include "mpi.h" +#include "cipher.h" +#include "keydb.h" + +#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH +#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL +#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_RMD160 + + +typedef struct { + int header_okay; + PK_LIST pk_list; + cipher_filter_context_t cfx; +} encrypt_filter_context_t; + + +/*-- g10.c --*/ +extern int g10_errors_seen; + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) + void g10_exit(int rc) __attribute__ ((noreturn)); +#else + void g10_exit(int rc); +#endif +void print_pubkey_algo_note( int algo ); +void print_cipher_algo_note( int algo ); +void print_digest_algo_note( int algo ); + +/*-- armor.c --*/ +char *make_radix64_string( const byte *data, size_t len ); + +/*-- misc.c --*/ +void trap_unaligned(void); +void disable_core_dumps(void); +u16 checksum_u16( unsigned n ); +u16 checksum( byte *p, unsigned n ); +u16 checksum_mpi( MPI a ); +u16 checksum_mpi_counted_nbits( MPI a ); +u32 buffer_to_u32( const byte *buffer ); + +/*-- helptext.c --*/ +void display_online_help( const char *keyword ); + +/*-- encode.c --*/ +int encode_symmetric( const char *filename ); +int encode_store( const char *filename ); +int encode_crypt( const char *filename, STRLIST remusr ); +int encrypt_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len); + + +/*-- sign.c --*/ +int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ); +int sign_file( STRLIST filenames, int detached, STRLIST locusr, + int do_encrypt, STRLIST remusr, const char *outfile ); +int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ); + +/*-- sig-check.c --*/ +int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); +int check_key_signature2( KBNODE root, KBNODE node, + int *is_selfsig, u32 *r_expire ); + +/*-- delkey.c --*/ +int delete_key( const char *username, int secure ); + +/*-- keyedit.c --*/ +void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds, + int sign_mode ); + +/*-- keygen.c --*/ +u32 ask_expiredate(void); +void generate_keypair(void); +int keygen_add_key_expire( PKT_signature *sig, void *opaque ); +int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); +int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); + +/*-- openfile.c --*/ +int overwrite_filep( const char *fname ); +char *make_outfile_name( const char *iname ); +char *ask_outfile_name( const char *name, size_t namelen ); +int open_outfile( const char *iname, int mode, IOBUF *a ); +IOBUF open_sigfile( const char *iname ); +void try_make_homedir( const char *fname ); + +/*-- seskey.c --*/ +void make_session_key( DEK *dek ); +MPI encode_session_key( DEK *dek, unsigned nbits ); +MPI encode_md_value( int pubkey_algo, MD_HANDLE md, + int hash_algo, unsigned nbits ); + +/*-- comment.c --*/ +KBNODE make_comment_node( const char *s ); +KBNODE make_mpi_comment_node( const char *s, MPI a ); + +/*-- import.c --*/ +void import_keys( char **fnames, int nnames, int fast ); +int import_keys_stream( IOBUF inp, int fast ); +int collapse_uids( KBNODE *keyblock ); + +/*-- export.c --*/ +int export_pubkeys( STRLIST users, int onlyrfc ); +int export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc ); +int export_seckeys( STRLIST users ); + +/* dearmor.c --*/ +int dearmor_file( const char *fname ); +int enarmor_file( const char *fname ); + +/*-- revoke.c --*/ +int gen_revoke( const char *uname ); + +/*-- keylist.c --*/ +void public_key_list( STRLIST list ); +void secret_key_list( STRLIST list ); + +/*-- verify.c --*/ +int verify_signatures( int nfiles, char **files ); +int verify_files( int nfiles, char **files ); + +/*-- decrypt.c --*/ +int decrypt_message( const char *filename ); + +/*-- plaintext.c --*/ +int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, + STRLIST files, const char *sigfilename, int textmode ); + +/*-- signal.c --*/ +//void init_signals(void); +//void pause_on_sigusr( int which ); +//void block_all_signals(void); +//void unblock_all_signals(void); + +#endif /*G10_MAIN_H*/ diff -Nru a/security/cryptomark/gnupg/mainproc.c b/security/cryptomark/gnupg/mainproc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mainproc.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1608 @@ +/* mainproc.c - handle packets + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" +#include + +#include "packet.h" +#include "iobuf.h" +#include "memory.h" +#include "options.h" +#include "util.h" +#include "cipher.h" +#include "keydb.h" +#include "filter.h" +#include "main.h" +#include "status.h" +#include "i18n.h" +#include "trustdb.h" +#include "hkp.h" + + +struct kidlist_item { + struct kidlist_item *next; + u32 kid[2]; + int pubkey_algo; + int reason; +}; + + + +/**************** + * Structure to hold the context + */ +typedef struct mainproc_context *CTX; +struct mainproc_context { + struct mainproc_context *anchor; /* may be useful in the future */ + PKT_public_key *last_pubkey; + PKT_secret_key *last_seckey; + PKT_user_id *last_user_id; + md_filter_context_t mfx; + int sigs_only; /* process only signatures and reject all other stuff */ + int encrypt_only; /* process only encrytion messages */ + STRLIST signed_data; + const char *sigfilename; + DEK *dek; + int last_was_session_key; + KBNODE list; /* the current list of packets */ + int have_data; + IOBUF iobuf; /* used to get the filename etc. */ + int trustletter; /* temp usage in list_node */ + ulong local_id; /* ditto */ + struct kidlist_item *failed_pkenc; /* list of packets for which + we do not have a secret key */ +}; + + +static void dump_ctx (CTX c) +{ + trace(); + + if (c == NULL) { + dbg ("CTX is NULL"); + return; + } + + dbg (__FUNCTION__" - anchor: %p", c->anchor); + dbg (__FUNCTION__" - last_pubkey: %p", c->last_pubkey); + dbg (__FUNCTION__" - last_seckey: %p", c->last_seckey); + dbg (__FUNCTION__" - last_user_id: %p", c->last_user_id); +// dbg (__FUNCTION__" - mfx: %p", c->mfx); + dbg (__FUNCTION__" - sigs_only: %d", c->sigs_only); + dbg (__FUNCTION__" - encrypt_only: %d", c->encrypt_only); +// dbg (__FUNCTION__" - signed_data: %d", c->signed_data); + dbg (__FUNCTION__" - sigfilename: %s", c->sigfilename); +// dbg (__FUNCTION__" - dek: %p", c->dek); + dbg (__FUNCTION__" - last_was_session_key: %d", c->last_was_session_key); + dbg (__FUNCTION__" - list: %p", c->list); + dbg (__FUNCTION__" - have_data: %d", c->have_data); + dbg (__FUNCTION__" - iobuf: %p", c->iobuf); + dbg (__FUNCTION__" - trustletter: %d", c->trustletter); + dbg (__FUNCTION__" - local_id: %ld", c->local_id); + dbg (__FUNCTION__" - failed_pkenc: %p", c->failed_pkenc); + +} + +static void dump_packet (PACKET *pkt) +{ + trace(); + if (pkt == NULL) { + dbg (__FUNCTION__" - PACKET is NULL"); + return; + } + + dbg (__FUNCTION__" - pkttype: %d", pkt->pkttype); + +} + +static void dump_kbnode (KBNODE node) +{ + trace(); + if (node == NULL) { + dbg (__FUNCTION__" - KBNODE is NULL"); + return; + } + + dbg (__FUNCTION__" - next: %p", node->next); + dbg (__FUNCTION__" - pkt: %p", node->pkt); + dump_packet (node->pkt); + dbg (__FUNCTION__" - flag: %x", node->flag); + dbg (__FUNCTION__" - private_flag: %x", node->private_flag); + dbg (__FUNCTION__" - recno: %ld", node->recno); +} + +//static int do_proc_packets( CTX c, IOBUF a ); +// +static void list_node( CTX c, KBNODE node ); +static int proc_tree( CTX c, KBNODE node ); + + +static int +release_list( CTX c ) +{ + int rc = 0; + trace(); + + if( !c->list ) + return rc; + rc = proc_tree(c, c->list ); + release_kbnode( c->list ); + while( c->failed_pkenc ) { + struct kidlist_item *tmp = c->failed_pkenc->next; + m_free( c->failed_pkenc ); + c->failed_pkenc = tmp; + } + c->failed_pkenc = NULL; + c->list = NULL; + return rc; +} + + +static int +add_onepass_sig( CTX c, PACKET *pkt ) +{ + KBNODE node; + + trace(); + + if( c->list ) { /* add another packet */ + if( c->list->pkt->pkttype != PKT_ONEPASS_SIG ) { + log_error("add_onepass_sig: another packet is in the way\n"); + release_list( c ); + c->list = new_kbnode( pkt ); + } + else + add_kbnode( c->list, new_kbnode( pkt )); + } + else /* insert the first one */ + c->list = node = new_kbnode( pkt ); + + return 1; +} + +// +// +//static int +//add_user_id( CTX c, PACKET *pkt ) +//{ +// if( !c->list ) { +// log_error("orphaned user ID\n" ); +// return 0; +// } +// add_kbnode( c->list, new_kbnode( pkt ) ); +// return 1; +//} +// +//static int +//add_subkey( CTX c, PACKET *pkt ) +//{ +// if( !c->list ) { +// log_error("subkey w/o mainkey\n" ); +// return 0; +// } +// add_kbnode( c->list, new_kbnode( pkt ) ); +// return 1; +//} +// +//static int +//add_ring_trust( CTX c, PACKET *pkt ) +//{ +// if( !c->list ) { +// log_error("ring trust w/o key\n" ); +// return 0; +// } +// add_kbnode( c->list, new_kbnode( pkt ) ); +// return 1; +//} +// +// +static int +add_signature( CTX c, PACKET *pkt ) +{ + KBNODE node; + + if( pkt->pkttype == PKT_SIGNATURE && !c->list ) { + /* This is the first signature for the following datafile. + * G10 does not write such packets; instead it always uses + * onepass-sig packets. The drawback of PGP's method + * of prepending the signature to the data is + * that it is not possible to make a signature from data read + * from stdin. (G10 is able to read PGP stuff anyway.) */ + node = new_kbnode( pkt ); + c->list = node; + return 1; + } + else if( !c->list ) + return 0; /* oops (invalid packet sequence)*/ + else if( !c->list->pkt ) + BUG(); /* so nicht */ + + /* add a new signature node id at the end */ + node = new_kbnode( pkt ); + add_kbnode( c->list, node ); + return 1; +} + +// +//static void +//proc_symkey_enc( CTX c, PACKET *pkt ) +//{ +// PKT_symkey_enc *enc; +// +// enc = pkt->pkt.symkey_enc; +// if( enc->seskeylen ) +// log_error( "symkey_enc packet with session keys are not supported!\n"); +// else { +// c->last_was_session_key = 2; +// c->dek = passphrase_to_dek( NULL, 0, enc->cipher_algo, &enc->s2k, 0 ); +// } +// free_packet(pkt); +//} +// +//static void +//proc_pubkey_enc( CTX c, PACKET *pkt ) +//{ +// PKT_pubkey_enc *enc; +// int result = 0; +// +// /* check whether the secret key is available and store in this case */ +// c->last_was_session_key = 1; +// enc = pkt->pkt.pubkey_enc; +// /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ +// /* Hmmm: why do I have this algo check here - anyway there is +// * function to check it. */ +// if( opt.verbose ) +// log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] ); +// +// if( is_status_enabled() ) { +// char buf[50]; +// sprintf(buf, "%08lX%08lX %d 0", +// (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo ); +// write_status_text( STATUS_ENC_TO, buf ); +// } +// +// +// if( is_ELGAMAL(enc->pubkey_algo) +// || enc->pubkey_algo == PUBKEY_ALGO_DSA +// || is_RSA(enc->pubkey_algo) ) { +// if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1]) +// || !seckey_available( enc->keyid )) ) { +// c->dek = m_alloc_secure( sizeof *c->dek ); +// if( (result = get_session_key( enc, c->dek )) ) { +// /* error: delete the DEK */ +// m_free(c->dek); c->dek = NULL; +// } +// } +// else +// result = G10ERR_NO_SECKEY; +// } +// else +// result = G10ERR_PUBKEY_ALGO; +// +// if( result == -1 ) +// ; +// else if( !result ) { +// if( opt.verbose > 1 ) +// log_info( _("public key encrypted data: good DEK\n") ); +// } +// else { /* store it for later display */ +// struct kidlist_item *x = m_alloc( sizeof *x ); +// x->kid[0] = enc->keyid[0]; +// x->kid[1] = enc->keyid[1]; +// x->pubkey_algo = enc->pubkey_algo; +// x->reason = result; +// x->next = c->failed_pkenc; +// c->failed_pkenc = x; +// } +// free_packet(pkt); +//} +// +// +// +///**************** +// * Print the list of public key encrypted packets which we could +// * not decrypt. +// */ +//static void +//print_failed_pkenc( struct kidlist_item *list ) +//{ +// for( ; list; list = list->next ) { +// PKT_public_key *pk = m_alloc_clear( sizeof *pk ); +// const char *algstr = pubkey_algo_to_string( list->pubkey_algo ); +// +// if( !algstr ) +// algstr = "[?]"; +// pk->pubkey_algo = list->pubkey_algo; +// if( !get_pubkey( pk, list->kid ) ) { +// size_t n; +// char *p; +// log_info( _("encrypted with %u-bit %s key, ID %08lX, created %s\n"), +// nbits_from_pk( pk ), algstr, (ulong)list->kid[1], +// strtimestamp(pk->timestamp) ); +// fputs(" \"", log_stream() ); +// p = get_user_id( list->kid, &n ); +// print_string( log_stream(), p, n, '"' ); +// m_free(p); +// fputs("\"\n", log_stream() ); +// } +// else { +// log_info(_("encrypted with %s key, ID %08lX\n"), +// algstr, (ulong) list->kid[1] ); +// } +// free_public_key( pk ); +// +// if( list->reason == G10ERR_NO_SECKEY ) { +// log_info(_("no secret key for decryption available\n")); +// if( is_status_enabled() ) { +// char buf[20]; +// sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], +// (ulong)list->kid[1] ); +// write_status_text( STATUS_NO_SECKEY, buf ); +// } +// } +// else +// log_error(_("public key decryption failed: %s\n"), +// g10_errstr(list->reason)); +// } +//} +// +// +//static void +//proc_encrypted( CTX c, PACKET *pkt ) +//{ +// int result = 0; +// +// print_failed_pkenc( c->failed_pkenc ); +// +// /*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ +// if( !c->dek && !c->last_was_session_key ) { +// /* assume this is old conventional encrypted data +// * Actually we should use IDEA and MD5 in this case, but becuase +// * IDEA is patented we can't do so */ +// c->dek = passphrase_to_dek( NULL, 0, +// opt.def_cipher_algo ? opt.def_cipher_algo +// : DEFAULT_CIPHER_ALGO, NULL, 0 ); +// } +// else if( !c->dek ) +// result = G10ERR_NO_SECKEY; +// if( !result ) +// result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); +// m_free(c->dek); c->dek = NULL; +// if( result == -1 ) +// ; +// else if( !result ) { +// write_status( STATUS_DECRYPTION_OKAY ); +// if( opt.verbose > 1 ) +// log_info(_("decryption okay\n")); +// if( pkt->pkt.encrypted->mdc_method ) +// write_status( STATUS_GOODMDC ); +// } +// else if( result == G10ERR_BAD_SIGN ) { +// log_error(_("WARNING: encrypted message has been manipulated!\n")); +// write_status( STATUS_BADMDC ); +// } +// else { +// write_status( STATUS_DECRYPTION_FAILED ); +// log_error(_("decryption failed: %s\n"), g10_errstr(result)); +// /* Hmmm: does this work when we have encrypted using a multiple +// * ways to specify the session key (symmmetric and PK)*/ +// } +// free_packet(pkt); +// c->last_was_session_key = 0; +//} +// +// +//static void +//proc_plaintext( CTX c, PACKET *pkt ) +//{ +// PKT_plaintext *pt = pkt->pkt.plaintext; +// int any, clearsig, only_md5, rc; +// KBNODE n; +// +// if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) +// log_info(_("NOTE: sender requested \"for-your-eyes-only\"\n")); +// else if( opt.verbose ) +// log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); +// free_md_filter_context( &c->mfx ); +// c->mfx.md = md_open( 0, 0); +// /* fixme: we may need to push the textfilter if we have sigclass 1 +// * and no armoring - Not yet tested +// * Hmmm, why don't we need it at all if we have sigclass 1 +// * Should we assume that plaintext in mode 't' has always sigclass 1?? +// * See: Russ Allbery's mail 1999-02-09 +// */ +// any = clearsig = only_md5 = 0; +// for(n=c->list; n; n = n->next ) { +// if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { +// if( n->pkt->pkt.onepass_sig->digest_algo ) { +// md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); +// if( !any && n->pkt->pkt.onepass_sig->digest_algo +// == DIGEST_ALGO_MD5 ) +// only_md5 = 1; +// else +// only_md5 = 0; +// any = 1; +// } +// if( n->pkt->pkt.onepass_sig->sig_class != 0x01 ) +// only_md5 = 0; +// +// /* Check whether this is a cleartext signature. We assume that +// * we have one if the sig_class is 1 and the keyid is 0, that +// * are the faked packets produced by armor.c. There is a +// * possibility that this fails, but there is no other easy way +// * to do it. (We could use a special packet type to indicate +// * this, but this may also be faked - it simply can't be verified +// * and is _no_ security issue) +// */ +// if( n->pkt->pkt.onepass_sig->sig_class == 0x01 +// && !n->pkt->pkt.onepass_sig->keyid[0] +// && !n->pkt->pkt.onepass_sig->keyid[1] ) +// clearsig = 1; +// } +// } +// +// if( !any && !opt.skip_verify ) { +// /* no onepass sig packet: enable all standard algos */ +// md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); +// md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); +// md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); +// } +// if( only_md5 && !opt.skip_verify ) { +// /* This is a kludge to work around a bug in pgp2. It does only +// * catch those mails which are armored. To catch the non-armored +// * pgp mails we could see whether there is the signature packet +// * in front of the plaintext. If someone needs this, send me a patch. +// */ +// c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0); +// } +// #if 0 +// #warning md_start_debug is enabled +// md_start_debug( c->mfx.md, "verify" ); +// #endif +// rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); +// if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { +// /* can't write output but we hash it anyway to +// * check the signature */ +// rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); +// } +// if( rc ) +// log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); +// free_packet(pkt); +// c->last_was_session_key = 0; +//} + + +/* Immunix copy of proc_plaintext */ +static void +proc_plaintext_data ( CTX c, PACKET *pkt, unsigned char **data ) +{ + PKT_plaintext *pt = pkt->pkt.plaintext; + int any, clearsig, only_md5, rc; + KBNODE n; + + trace(); + +// if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) +// log_info(_("NOTE: sender requested \"for-your-eyes-only\"\n")); +// else if( opt.verbose ) +// log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); + free_md_filter_context( &c->mfx ); + c->mfx.md = md_open( 0, 0); + /* fixme: we may need to push the textfilter if we have sigclass 1 + * and no armoring - Not yet tested + * Hmmm, why don't we need it at all if we have sigclass 1 + * Should we assume that plaintext in mode 't' has always sigclass 1?? + * See: Russ Allbery's mail 1999-02-09 + */ + any = clearsig = only_md5 = 0; + for(n=c->list; n; n = n->next ) { + if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { + if( n->pkt->pkt.onepass_sig->digest_algo ) { + md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); + if( !any && n->pkt->pkt.onepass_sig->digest_algo + == DIGEST_ALGO_MD5 ) + only_md5 = 1; + else + only_md5 = 0; + any = 1; + } + if( n->pkt->pkt.onepass_sig->sig_class != 0x01 ) + only_md5 = 0; + + /* Check whether this is a cleartext signature. We assume that + * we have one if the sig_class is 1 and the keyid is 0, that + * are the faked packets produced by armor.c. There is a + * possibility that this fails, but there is no other easy way + * to do it. (We could use a special packet type to indicate + * this, but this may also be faked - it simply can't be verified + * and is _no_ security issue) + */ + if( n->pkt->pkt.onepass_sig->sig_class == 0x01 + && !n->pkt->pkt.onepass_sig->keyid[0] + && !n->pkt->pkt.onepass_sig->keyid[1] ) + clearsig = 1; + } + } + + if( !any && !opt.skip_verify ) { + /* no onepass sig packet: enable all standard algos */ + md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); + md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); + md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + } + if( only_md5 && !opt.skip_verify ) { + /* This is a kludge to work around a bug in pgp2. It does only + * catch those mails which are armored. To catch the non-armored + * pgp mails we could see whether there is the signature packet + * in front of the plaintext. If someone needs this, send me a patch. + */ + c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0); + } + #if 0 + #warning md_start_debug is enabled + md_start_debug( c->mfx.md, "verify" ); + #endif + rc = handle_plaintext_data( pt, &c->mfx, c->sigs_only, clearsig, data ); + if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { + /* can't write output but we hash it anyway to + * check the signature */ + rc = handle_plaintext_data( pt, &c->mfx, 1, clearsig, data ); + } + if( rc ) +// log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); + log_error( "handle plaintext failed: %d\n", rc); + free_packet(pkt); + c->last_was_session_key = 0; +} + + +//static int +//proc_compressed_cb( IOBUF a, void *info ) +//{ +// return proc_signature_packets( info, a, ((CTX)info)->signed_data, +// ((CTX)info)->sigfilename ); +//} +// +//static int +//proc_encrypt_cb( IOBUF a, void *info ) +//{ +// return proc_encryption_packets( info, a ); +//} +// +//static void +//proc_compressed( CTX c, PACKET *pkt ) +//{ +// PKT_compressed *zd = pkt->pkt.compressed; +// int rc; +// +// /*printf("zip: compressed data packet\n");*/ +// if( c->sigs_only ) +// rc = handle_compressed( c, zd, proc_compressed_cb, c ); +// else if( c->encrypt_only ) +// rc = handle_compressed( c, zd, proc_encrypt_cb, c ); +// else +// rc = handle_compressed( c, zd, NULL, NULL ); +// if( rc ) +// log_error("uncompressing failed: %s\n", g10_errstr(rc)); +// free_packet(pkt); +// c->last_was_session_key = 0; +//} +// +/**************** + * check the signature + * Returns: 0 = valid signature or an error code + */ +static int +do_check_sig( CTX c, KBNODE node, int *is_selfsig ) +{ + PKT_signature *sig; + MD_HANDLE md = NULL, md2 = NULL; + int algo, rc; + + trace(); + +// assert( node->pkt->pkttype == PKT_SIGNATURE ); + if( is_selfsig ) + *is_selfsig = 0; + sig = node->pkt->pkt.signature; + + algo = sig->digest_algo; + if( (rc=check_digest_algo(algo)) ) + return rc; + + if( sig->sig_class == 0x00 ) { + if( c->mfx.md ) + md = md_copy( c->mfx.md ); + else /* detached signature */ + md = md_open( 0, 0 ); /* signature_check() will enable the md*/ + } + else if( sig->sig_class == 0x01 ) { + /* how do we know that we have to hash the (already hashed) text + * in canonical mode ??? (calculating both modes???) */ + if( c->mfx.md ) { + md = md_copy( c->mfx.md ); + if( c->mfx.md2 ) + md2 = md_copy( c->mfx.md2 ); + } + else { /* detached signature */ + log_debug("Do we really need this here?"); + md = md_open( 0, 0 ); /* signature_check() will enable the md*/ + md2 = md_open( 0, 0 ); + } + } + else if( (sig->sig_class&~3) == 0x10 + || sig->sig_class == 0x18 + || sig->sig_class == 0x20 + || sig->sig_class == 0x30 ) { /* classes 0x10..0x17,0x20,0x30 */ + if( c->list->pkt->pkttype == PKT_PUBLIC_KEY + || c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + return check_key_signature( c->list, node, is_selfsig ); + } + else if( sig->sig_class == 0x20 ) { + log_info("standalone revocation - " + "use \"gpg --import\" to apply\n"); + return G10ERR_NOT_PROCESSED; + } + else { + log_error("invalid root packet for sigclass %02x\n", + sig->sig_class); + return G10ERR_SIG_CLASS; + } + } + else + return G10ERR_SIG_CLASS; + rc = signature_check( sig, md ); + if( rc == G10ERR_BAD_SIGN && md2 ) + rc = signature_check( sig, md2 ); + md_close(md); + md_close(md2); + + return rc; +} + + +//static void +//print_userid( PACKET *pkt ) +//{ +// if( !pkt ) +// BUG(); +// if( pkt->pkttype != PKT_USER_ID ) { +// printf("ERROR: unexpected packet type %d", pkt->pkttype ); +// return; +// } +// print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len, +// opt.with_colons ); +//} +// +// +//static void +//print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk ) +//{ +// byte array[MAX_FINGERPRINT_LEN], *p; +// size_t i, n; +// +// if( sk ) +// fingerprint_from_sk( sk, array, &n ); +// else +// fingerprint_from_pk( pk, array, &n ); +// p = array; +// if( opt.with_colons ) { +// printf("fpr:::::::::"); +// for(i=0; i < n ; i++, p++ ) +// printf("%02X", *p ); +// putchar(':'); +// } +// else { +// printf(" Key fingerprint ="); +// if( n == 20 ) { +// for(i=0; i < n ; i++, i++, p += 2 ) { +// if( i == 10 ) +// putchar(' '); +// printf(" %02X%02X", *p, p[1] ); +// } +// } +// else { +// for(i=0; i < n ; i++, p++ ) { +// if( i && !(i%8) ) +// putchar(' '); +// printf(" %02X", *p ); +// } +// } +// } +// putchar('\n'); +//} +// +//static void +//print_notation_data( PKT_signature *sig ) +//{ +// size_t n, n1, n2; +// const byte *p; +// int seq = 0; +// +// while( (p = enum_sig_subpkt( sig->hashed_data, SIGSUBPKT_NOTATION, +// &n, &seq )) ) { +// if( n < 8 ) { +// log_info(_("WARNING: invalid notation data found\n")); +// return; +// } +// if( !(*p & 0x80) ) +// return; /* not human readable */ +// n1 = (p[4] << 8) | p[5]; +// n2 = (p[6] << 8) | p[7]; +// p += 8; +// if( 8+n1+n2 != n ) { +// log_info(_("WARNING: invalid notation data found\n")); +// return; +// } +// log_info(_("Notation: ") ); +// print_string( log_stream(), p, n1, 0 ); +// putc( '=', log_stream() ); +// print_string( log_stream(), p+n1, n2, 0 ); +// putc( '\n', log_stream() ); +// } +// if( (p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_POLICY, &n ) )) { +// log_info(_("Policy: ") ); +// print_string( log_stream(), p, n, 0 ); +// putc( '\n', log_stream() ); +// } +// +// /* Now check wheter the key of this signature has some +// * notation data */ +// +// /* TODO */ +//} +// +// +/**************** + * List the certificate in a user friendly way + */ + +static void +list_node( CTX c, KBNODE node ) +{ + trace(); + +// int any=0; +// int mainkey; +// +// if( !node ) +// ; +// else if( (mainkey = (node->pkt->pkttype == PKT_PUBLIC_KEY) ) +// || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { +// PKT_public_key *pk = node->pkt->pkt.public_key; +// +// if( opt.with_colons ) { +// u32 keyid[2]; +// keyid_from_pk( pk, keyid ); +// if( mainkey ) { +// c->local_id = pk->local_id; +// c->trustletter = opt.fast_list_mode? +// 0 : query_trust_info( pk, NULL ); +// } +// printf("%s:", mainkey? "pub":"sub" ); +// if( c->trustletter ) +// putchar( c->trustletter ); +// printf(":%u:%d:%08lX%08lX:%s:%s:", +// nbits_from_pk( pk ), +// pk->pubkey_algo, +// (ulong)keyid[0],(ulong)keyid[1], +// datestr_from_pk( pk ), +// pk->expiredate? strtimestamp(pk->expiredate):"" ); +// if( c->local_id ) +// printf("%lu", c->local_id ); +// putchar(':'); +// if( c->local_id && !opt.fast_list_mode ) +// putchar( get_ownertrust_info( c->local_id ) ); +// putchar(':'); +// if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) { +// putchar('\n'); any=1; +// if( opt.fingerprint ) +// print_fingerprint( pk, NULL ); +// printf("rtv:1:%u:\n", +// node->next->pkt->pkt.ring_trust->trustval ); +// } +// } +// else +// printf("%s %4u%c/%08lX %s ", +// mainkey? "pub":"sub", +// nbits_from_pk( pk ), +// pubkey_letter( pk->pubkey_algo ), +// (ulong)keyid_from_pk( pk, NULL ), +// datestr_from_pk( pk ) ); +// if( mainkey ) { +// /* and now list all userids with their signatures */ +// for( node = node->next; node; node = node->next ) { +// if( node->pkt->pkttype == PKT_SIGNATURE ) { +// if( !any ) { +// if( node->pkt->pkt.signature->sig_class == 0x20 ) +// puts("[revoked]"); +// else +// putchar('\n'); +// any = 1; +// } +// list_node(c, node ); +// } +// else if( node->pkt->pkttype == PKT_USER_ID ) { +// if( any ) { +// if( opt.with_colons ) +// printf("uid:::::::::"); +// else +// printf( "uid%*s", 28, "" ); +// } +// print_userid( node->pkt ); +// if( opt.with_colons ) +// putchar(':'); +// putchar('\n'); +// if( opt.fingerprint && !any ) +// print_fingerprint( pk, NULL ); +// if( node->next +// && node->next->pkt->pkttype == PKT_RING_TRUST ) { +// printf("rtv:2:%u:\n", +// node->next->pkt->pkt.ring_trust->trustval ); +// } +// any=1; +// } +// else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { +// if( !any ) { +// putchar('\n'); +// any = 1; +// } +// list_node(c, node ); +// } +// } +// } +// if( !any ) +// putchar('\n'); +// if( !mainkey && opt.fingerprint > 1 ) +// print_fingerprint( pk, NULL ); +// } +// else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) ) +// || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { +// PKT_secret_key *sk = node->pkt->pkt.secret_key; +// +// if( opt.with_colons ) { +// u32 keyid[2]; +// keyid_from_sk( sk, keyid ); +// printf("%s::%u:%d:%08lX%08lX:%s:%s:::", +// mainkey? "sec":"ssb", +// nbits_from_sk( sk ), +// sk->pubkey_algo, +// (ulong)keyid[0],(ulong)keyid[1], +// datestr_from_sk( sk ), +// sk->expiredate? strtimestamp(sk->expiredate):"" +// /* fixme: add LID */ ); +// } +// else +// printf("%s %4u%c/%08lX %s ", +// mainkey? "sec":"ssb", +// nbits_from_sk( sk ), +// pubkey_letter( sk->pubkey_algo ), +// (ulong)keyid_from_sk( sk, NULL ), +// datestr_from_sk( sk ) ); +// if( mainkey ) { +// /* and now list all userids with their signatures */ +// for( node = node->next; node; node = node->next ) { +// if( node->pkt->pkttype == PKT_SIGNATURE ) { +// if( !any ) { +// if( node->pkt->pkt.signature->sig_class == 0x20 ) +// puts("[revoked]"); +// else +// putchar('\n'); +// any = 1; +// } +// list_node(c, node ); +// } +// else if( node->pkt->pkttype == PKT_USER_ID ) { +// if( any ) { +// if( opt.with_colons ) +// printf("uid:::::::::"); +// else +// printf( "uid%*s", 28, "" ); +// } +// print_userid( node->pkt ); +// if( opt.with_colons ) +// putchar(':'); +// putchar('\n'); +// if( opt.fingerprint && !any ) +// print_fingerprint( NULL, sk ); +// any=1; +// } +// else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { +// if( !any ) { +// putchar('\n'); +// any = 1; +// } +// list_node(c, node ); +// } +// } +// } +// if( !any ) +// putchar('\n'); +// if( !mainkey && opt.fingerprint > 1 ) +// print_fingerprint( NULL, sk ); +// } +// else if( node->pkt->pkttype == PKT_SIGNATURE ) { +// PKT_signature *sig = node->pkt->pkt.signature; +// int is_selfsig = 0; +// int rc2=0; +// size_t n; +// char *p; +// int sigrc = ' '; +// +// if( !opt.list_sigs ) +// return; +// +// if( sig->sig_class == 0x20 || sig->sig_class == 0x30 ) +// fputs("rev", stdout); +// else +// fputs("sig", stdout); +// if( opt.check_sigs ) { +// fflush(stdout); +// switch( (rc2=do_check_sig( c, node, &is_selfsig )) ) { +// case 0: sigrc = '!'; break; +// case G10ERR_BAD_SIGN: sigrc = '-'; break; +// case G10ERR_NO_PUBKEY: sigrc = '?'; break; +// default: sigrc = '%'; break; +// } +// } +// else { /* check whether this is a self signature */ +// u32 keyid[2]; +// +// if( c->list->pkt->pkttype == PKT_PUBLIC_KEY +// || c->list->pkt->pkttype == PKT_SECRET_KEY ) { +// if( c->list->pkt->pkttype == PKT_PUBLIC_KEY ) +// keyid_from_pk( c->list->pkt->pkt.public_key, keyid ); +// else +// keyid_from_sk( c->list->pkt->pkt.secret_key, keyid ); +// +// if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) +// is_selfsig = 1; +// } +// } +// if( opt.with_colons ) { +// putchar(':'); +// if( sigrc != ' ' ) +// putchar(sigrc); +// printf("::%d:%08lX%08lX:%s::::", sig->pubkey_algo, +// (ulong)sig->keyid[0], +// (ulong)sig->keyid[1], datestr_from_sig(sig)); +// } +// else +// printf("%c %08lX %s ", +// sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig)); +// if( sigrc == '%' ) +// printf("[%s] ", g10_errstr(rc2) ); +// else if( sigrc == '?' ) +// ; +// else if( is_selfsig ) { +// if( opt.with_colons ) +// putchar(':'); +// fputs( sig->sig_class == 0x18? "[keybind]":"[selfsig]", stdout); +// if( opt.with_colons ) +// putchar(':'); +// } +// else if( !opt.fast_list_mode ) { +// p = get_user_id( sig->keyid, &n ); +// print_string( stdout, p, n, opt.with_colons ); +// m_free(p); +// } +// if( opt.with_colons ) +// printf(":%02x:", sig->sig_class ); +// putchar('\n'); +// } +// else +// log_error("invalid node with packet of type %d\n", node->pkt->pkttype); +} + + +//int +//proc_packets( void *anchor, IOBUF a ) +//{ +// int rc; +// CTX c = m_alloc_clear( sizeof *c ); +// +// c->anchor = anchor; +// rc = do_proc_packets( c, a ); +// m_free( c ); +// return rc; +//} +// +//int +//proc_signature_packets( void *anchor, IOBUF a, +// STRLIST signedfiles, const char *sigfilename ) +//{ +// CTX c = m_alloc_clear( sizeof *c ); +// int rc; +// +// c->anchor = anchor; +// c->sigs_only = 1; +// c->signed_data = signedfiles; +// c->sigfilename = sigfilename; +// rc = do_proc_packets( c, a ); +// m_free( c ); +// return rc; +//} +// +//int +//proc_encryption_packets( void *anchor, IOBUF a ) +//{ +// CTX c = m_alloc_clear( sizeof *c ); +// int rc; +// +// c->anchor = anchor; +// c->encrypt_only = 1; +// rc = do_proc_packets( c, a ); +// m_free( c ); +// return rc; +//} +// +// +//int +//do_proc_packets( CTX c, IOBUF a ) +//{ +// PACKET *pkt = m_alloc( sizeof *pkt ); +// int rc=0; +// int any_data=0; +// int newpkt; +// +// c->iobuf = a; +// init_packet(pkt); +// while( (rc=parse_packet(a, pkt)) != -1 ) { +// any_data = 1; +// if( rc ) { +// free_packet(pkt); +// if( rc == G10ERR_INVALID_PACKET ) +// break; +// continue; +// } +// newpkt = -1; +// if( opt.list_packets ) { +// switch( pkt->pkttype ) { +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; +// default: newpkt = 0; break; +// } +// } +// else if( c->sigs_only ) { +// switch( pkt->pkttype ) { +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// case PKT_USER_ID: +// case PKT_SYMKEY_ENC: +// case PKT_PUBKEY_ENC: +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: +// rc = G10ERR_UNEXPECTED; +// goto leave; +// case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; +// case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; +// default: newpkt = 0; break; +// } +// } +// else if( c->encrypt_only ) { +// switch( pkt->pkttype ) { +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// case PKT_USER_ID: +// rc = G10ERR_UNEXPECTED; +// goto leave; +// case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; +// case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; +// case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; +// default: newpkt = 0; break; +// } +// } +// else { +// switch( pkt->pkttype ) { +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// release_list( c ); +// c->list = new_kbnode( pkt ); +// newpkt = 1; +// break; +// case PKT_PUBLIC_SUBKEY: +// case PKT_SECRET_SUBKEY: +// newpkt = add_subkey( c, pkt ); +// break; +// case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break; +// case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; +// case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; +// case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; +// case PKT_RING_TRUST: newpkt = add_ring_trust( c, pkt ); break; +// default: newpkt = 0; break; +// } +// } +// if( pkt->pkttype != PKT_SIGNATURE ) +// c->have_data = pkt->pkttype == PKT_PLAINTEXT; +// +// if( newpkt == -1 ) +// ; +// else if( newpkt ) { +// pkt = m_alloc( sizeof *pkt ); +// init_packet(pkt); +// } +// else +// free_packet(pkt); +// } +// if( rc == G10ERR_INVALID_PACKET ) +// write_status_text( STATUS_NODATA, "3" ); +// if( any_data ) +// rc = 0; +// else if( rc == -1 ) +// write_status_text( STATUS_NODATA, "2" ); +// +// +// leave: +// release_list( c ); +// m_free(c->dek); +// free_packet( pkt ); +// m_free( pkt ); +// free_md_filter_context( &c->mfx ); +// return rc; +//} + +/* Immunix copy of do_proc_packets */ +int +do_proc_packets_data ( CTX c, IOBUF a, unsigned char **data ) +{ + PACKET *pkt = m_alloc( sizeof *pkt ); + int rc=0; + int any_data=0; + int newpkt; + + trace(); + + c->iobuf = a; + init_packet(pkt); + while( (rc=parse_packet(a, pkt)) != -1 ) { + dbg(__FUNCTION__": rc = %d", rc); + + any_data = 1; + if( rc ) { + free_packet(pkt); + if( rc == G10ERR_INVALID_PACKET ) + break; + continue; + } + newpkt = -1; + if( opt.list_packets ) { + switch( pkt->pkttype ) { +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + default: newpkt = 0; break; + } + } + else if( c->sigs_only ) { + switch( pkt->pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_USER_ID: + case PKT_SYMKEY_ENC: + case PKT_PUBKEY_ENC: + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: + rc = G10ERR_UNEXPECTED; + goto leave; +// case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; + default: newpkt = 0; break; + } + } + else if( c->encrypt_only ) { + switch( pkt->pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_USER_ID: + rc = G10ERR_UNEXPECTED; + goto leave; +// case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; +// case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; + default: newpkt = 0; break; + } + } + else { + dbg (__FUNCTION__" - pkt->pkttype = %d", pkt->pkttype); + switch( pkt->pkttype ) { +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// release_list( c ); +// c->list = new_kbnode( pkt ); +// newpkt = 1; +// break; +// case PKT_PUBLIC_SUBKEY: +// case PKT_SECRET_SUBKEY: +// newpkt = add_subkey( c, pkt ); +// break; +// case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break; + case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; +// case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; +// case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; +// case PKT_ENCRYPTED: +// case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; + case PKT_PLAINTEXT: proc_plaintext_data( c, pkt, data ); break; +// case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; +// case PKT_RING_TRUST: newpkt = add_ring_trust( c, pkt ); break; + default: newpkt = 0; break; + } + } + if( pkt->pkttype != PKT_SIGNATURE ) + c->have_data = pkt->pkttype == PKT_PLAINTEXT; + + if( newpkt == -1 ) + ; + else if( newpkt ) { + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + } + else + free_packet(pkt); + } + if( rc == G10ERR_INVALID_PACKET ) + write_status_text( STATUS_NODATA, "3" ); + if( any_data ) + rc = 0; + else if( rc == -1 ) + write_status_text( STATUS_NODATA, "2" ); + + + leave: + rc = release_list( c ); + dbg (__FUNCTION__" - done with release_list, rc = %d", rc); + + m_free(c->dek); + free_packet( pkt ); + m_free( pkt ); + free_md_filter_context( &c->mfx ); + return rc; +} + + +static int +check_sig_and_print( CTX c, KBNODE node ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + const char *astr; +// const char *tstr; + int rc; + + trace(); + + if( opt.skip_verify ) { + log_info("signature verification suppressed\n"); + return 0; + } + +// tstr = asctimestamp(sig->timestamp); + astr = pubkey_algo_to_string( sig->pubkey_algo ); +// log_info("Signature made %.*s using %s key ID %08lX\n", +// (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); + log_info("Signature key ID %08lX\n", (ulong)sig->keyid[1] ); + + rc = do_check_sig(c, node, NULL ); +// if( rc == G10ERR_NO_PUBKEY && opt.keyserver_name ) { +// if( !hkp_ask_import( sig->keyid ) ) +// rc = do_check_sig(c, node, NULL ); +// } + dbg (__FUNCTION__":1 - rc = %d", rc); + if( !rc || rc == G10ERR_BAD_SIGN ) { + KBNODE un, keyblock; + char *us; + int count=0; + + keyblock = get_pubkeyblock( sig->keyid ); + + us = get_long_user_id_string( sig->keyid ); +#ifdef CONFIG_CRYPTOMARK_DEBUG + write_status_text( rc? STATUS_BADSIG : STATUS_GOODSIG, us ); +#endif + m_free(us); + + /* fixme: list only user ids which are valid and add information + * about the trustworthiness of each user id, sort them. + * Integrate this with check_signatures_trust(). */ + for( un=keyblock; un; un = un->next ) { + if( un->pkt->pkttype != PKT_USER_ID ) + continue; +#ifdef CONFIG_CRYPTOMARK_DEBUG + if( !count++ ) { + if (rc) +// log_info("BAD signature from \""); + log_info("BAD signature\n"); + else +// log_info("Good signature from \""); + log_info("Good signature\n"); + } + else + log_info(" aka \""); +#endif +// print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, +// un->pkt->pkt.user_id->len ); +// fputs("\"\n", log_stream() ); + if( rc ) + break; /* print only one id in this case */ + } + if( !count ) { /* just in case that we have no userid */ + if (rc) +// log_info("BAD signature from \""); + log_info("BAD signature\n"); + else +// log_info("Good signature from \""); + log_info("Good signature\n"); +// fputs("[?]\"\n", log_stream() ); + } + release_kbnode( keyblock ); +// if( !rc ) +// print_notation_data( sig ); + +// if( !rc && is_status_enabled() ) { + if( !rc ) { + /* print a status response with the fingerprint */ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + + if( !get_pubkey( pk, sig->keyid ) ) { + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[MAX_FINGERPRINT_LEN*2+61]; + size_t i, n; + + fingerprint_from_pk( pk, array, &n ); + p = array; + for(i=0; i < n ; i++, p++ ) + sprintf(buf+2*i, "%02X", *p ); +// sprintf(buf+strlen(buf), " %s %lu", +// strtimestamp( sig->timestamp ), +// (ulong)sig->timestamp ); + write_status_text( STATUS_VALIDSIG, buf ); + } + free_public_key( pk ); + } + +// if( !rc ) +// rc = check_signatures_trust( sig ); +// if( rc ) +// g10_errors_seen = 1; +// if( opt.batch && rc ) +// g10_exit(1); + } + else { + char buf[50]; + sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + sig->pubkey_algo, sig->digest_algo, + sig->sig_class, (ulong)sig->timestamp, rc ); + write_status_text( STATUS_ERRSIG, buf ); + if( rc == G10ERR_NO_PUBKEY ) { + buf[16] = 0; + write_status_text( STATUS_NO_PUBKEY, buf ); + } + if( rc != G10ERR_NOT_PROCESSED ) + log_error("Can't check signature: %d\n", rc); + } + return rc; +} + + +/**************** + * Process the tree which starts at node + */ +static int +proc_tree( CTX c, KBNODE node ) +{ + KBNODE n1; + int rc = 0; + + trace(); + + dump_ctx (c); + dump_kbnode (node); + + dbg(__FUNCTION__":1"); + + if( opt.list_packets ) + return rc; + + dbg(__FUNCTION__":2"); + + c->local_id = 0; + c->trustletter = ' '; + if( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + dbg(__FUNCTION__":3"); + merge_keys_and_selfsig( node ); + list_node( c, node ); + } + else if( node->pkt->pkttype == PKT_SECRET_KEY ) { + dbg(__FUNCTION__":4"); + merge_keys_and_selfsig( node ); + list_node( c, node ); + } + else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { + dbg(__FUNCTION__":5"); + /* check all signatures */ + if( !c->have_data ) { + dbg(__FUNCTION__":5.5"); + free_md_filter_context( &c->mfx ); + /* prepare to create all requested message digests */ + c->mfx.md = md_open(0, 0); + + /* fixme: why looking for the signature packet and not 1passpacket*/ + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { + md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo); + } + /* ask for file and hash it */ +// if( c->sigs_only ) +// rc = hash_datafiles( c->mfx.md, NULL, +// c->signed_data, c->sigfilename, +// n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); +// else +// rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, +// iobuf_get_fname(c->iobuf), 0 ); + if( rc ) { +// log_error("can't hash datafile: %s\n", g10_errstr(rc)); + log_error("can't hash datafile: %d\n", rc); + return rc; + } + } + + dbg(__FUNCTION__":6"); + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) + rc = check_sig_and_print( c, n1 ); + dbg(__FUNCTION__":11"); + } + else if( node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + + dbg(__FUNCTION__":7"); + if( sig->sig_class != 0x00 && sig->sig_class != 0x01 ) +// log_info(_("standalone signature of class 0x%02x\n"), +// sig->sig_class); + log_info("standalone signature of class 0x%02x\n", sig->sig_class); + else if( !c->have_data ) { + /* detached signature */ + dbg(__FUNCTION__":8"); + free_md_filter_context( &c->mfx ); + c->mfx.md = md_open(sig->digest_algo, 0); + if( sig->digest_algo == DIGEST_ALGO_MD5 + && is_RSA( sig->pubkey_algo ) ) { + /* enable a workaround for a pgp2 bug */ + c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0 ); + } + else if( sig->digest_algo == DIGEST_ALGO_SHA1 + && sig->pubkey_algo == PUBKEY_ALGO_DSA + && sig->sig_class == 0x01 ) { + /* enable the workaround also for pgp5 when the detached + * signature has been created in textmode */ + c->mfx.md2 = md_open( sig->digest_algo, 0 ); + } + /* Here we have another hack to work around a pgp 2 bug + * It works by not using the textmode for detached signatures; + * this will let the first signature check (on md) fail + * but the second one (on md2) which adds an extra CR should + * then produce the "correct" hash. This is very, very ugly + * hack but it may help in some cases (and break others) + */ +// if( c->sigs_only ) +// rc = hash_datafiles( c->mfx.md, c->mfx.md2, +// c->signed_data, c->sigfilename, +// c->mfx.md2? 0 :(sig->sig_class == 0x01) ); +// else +// rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, +// iobuf_get_fname(c->iobuf), +// c->mfx.md2? 0 :(sig->sig_class == 0x01) ); +// if( rc ) { +// log_error("can't hash datafile: %s\n", g10_errstr(rc)); + log_error("can't hash datafile: %d\n", rc); + return rc; +// } + } + else +// log_info(_("old style (PGP 2.x) signature\n")); + log_info("old style (PGP 2.x) signature\n"); + + dbg(__FUNCTION__":9"); + rc = check_sig_and_print( c, node ); + dbg(__FUNCTION__":10"); + + } + else +// log_error(_("invalid root packet detected in proc_tree()\n")); + log_error("invalid root packet detected in proc_tree()\n"); + + return rc; +} + + +/* Immunix Cryptomark main function call */ +int crypto_verify_data (unsigned char * inp, unsigned long size, unsigned char **data) +{ + CTX c = m_alloc_clear (sizeof *c); + int rc ; + IOBUF temp = NULL; + IOBUF input = NULL; + armor_filter_context_t afx ; + + trace(); + + dbg (__FUNCTION__ ": step 0"); + add_keyblock_resource("gerg", 0, 0); + + dbg (__FUNCTION__ ": step 1"); + if (!(temp = iobuf_temp_with_content (inp, size))) { + warn (__FUNCTION__ ":can't create temp IOBUF" ) ; + return -ENOMEM; + } + + dbg (__FUNCTION__ ": step 2"); + input = iobuf_alloc (1, 8192); + iobuf_write_temp (input, temp); + + dbg (__FUNCTION__ ": step 3"); + if (use_armor_filter (input)) { + dbg (__FUNCTION__ ": step 3.5"); + memset (&afx, 0, sizeof(afx)); + iobuf_push_filter (input, armor_filter, &afx); + } + + dbg (__FUNCTION__ ": step 4"); + rc = do_proc_packets_data (c, input, data); + + dbg (__FUNCTION__ ": rc = %d", rc); + + dbg (__FUNCTION__ ": step 5"); + m_free (c); + + dbg (__FUNCTION__ ": done"); + return rc ; +} + + diff -Nru a/security/cryptomark/gnupg/mdfilter.c b/security/cryptomark/gnupg/mdfilter.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mdfilter.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,82 @@ +/* mdfilter.c - filter data and calculate a message digest + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include "errors.h" +#include "iobuf.h" +#include "memory.h" +#include "util.h" +#include "filter.h" + + + +/**************** + * This filter is used to collect a message digest + */ +int +md_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len) +{ + size_t size = *ret_len; + md_filter_context_t *mfx = opaque; + int i, rc=0; + + trace(); + + if( control == IOBUFCTRL_UNDERFLOW ) { + if( mfx->maxbuf_size && size > mfx->maxbuf_size ) + size = mfx->maxbuf_size; + i = iobuf_read( a, buf, size ); + if( i == -1 ) i = 0; + if( i ) { + md_write(mfx->md, buf, i ); + if( mfx->md2 ) + md_write(mfx->md2, buf, i ); + } + else + rc = -1; /* eof */ + *ret_len = i; + } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "md_filter"; + return rc; +} + + +void +free_md_filter_context( md_filter_context_t *mfx ) +{ + trace(); + + md_close(mfx->md); + md_close(mfx->md2); + mfx->md = NULL; + mfx->md2 = NULL; + mfx->maxbuf_size = 0; +} + diff -Nru a/security/cryptomark/gnupg/memory.c b/security/cryptomark/gnupg/memory.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/memory.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,618 @@ +/* memory.c - memory allocation + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * We use our own memory allocation functions instead of plain malloc(), + * so that we can provide some special enhancements: + * a) functions to provide memory from a secure memory. + * b) by looking at the requested allocation size we + * can reuse memory very quickly (e.g. MPI storage) + * (really needed?) + * c) memory usage reporting if compiled with M_DEBUG + * d) memory checking if compiled with M_GUARD + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include + + +#include "types.h" +#include "memory.h" +#include "util.h" + + +#define MAGIC_NOR_BYTE 0x55 +#define MAGIC_SEC_BYTE 0xcc +#define MAGIC_END_BYTE 0xaa + +#if SIZEOF_UNSIGNED_LONG == 8 + #define EXTRA_ALIGN 4 +#else + #define EXTRA_ALIGN 0 +#endif + +//#if defined(M_DEBUG) || defined(M_GUARD) +// static void membug( const char *fmt, ... ); +//#endif +// +//#ifdef M_DEBUG +// +// #ifndef M_GUARD +// #define M_GUARD 1 +// #endif +// #undef m_alloc +// #undef m_alloc_clear +// #undef m_alloc_secure +// #undef m_alloc_secure_clear +// #undef m_realloc +// #undef m_free +// #undef m_check +// #undef m_strdup +// #define FNAME(a) m_debug_ ##a +// #define FNAMEPRT , const char *info +// #define FNAMEARG , info +// #define store_len(p,n,m) do { add_entry(p,n,m, \ +// info, __FUNCTION__); } while(0) +//#else + #define FNAME(a) m_ ##a + #define FNAMEPRT + #define FNAMEARG +// #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \ +// ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \ +// ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \ +// ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \ +// : MAGIC_NOR_BYTE; \ +// } while(0) +//#endif + + +//#ifdef M_GUARD +//static long used_memory; +//#endif +// +//#ifdef M_DEBUG /* stuff used for memory debuging */ +// +//struct info_entry { +// struct info_entry *next; +// unsigned count; /* call count */ +// const char *info; /* the reference to the info string */ +//}; +// +//struct memtbl_entry { +// const void *user_p; /* for reference: the pointer given to the user */ +// size_t user_n; /* length requested by the user */ +// struct memtbl_entry *next; /* to build a list of unused entries */ +// const struct info_entry *info; /* points into the table with */ +// /* the info strings */ +// unsigned inuse:1; /* this entry is in use */ +// unsigned count:31; +//}; +// +// +//#define INFO_BUCKETS 53 +//#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS ) +//static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */ +// +//static struct memtbl_entry *memtbl; /* the table with the memory info */ +//static unsigned memtbl_size; /* number of allocated entries */ +//static unsigned memtbl_len; /* number of used entries */ +//static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */ +// +//static void dump_table_at_exit(void); +//static void dump_table(void); +//static void check_allmem( const char *info ); +// +///**************** +// * Put the new P into the debug table and return a pointer to the table entry. +// * mode is true for security. BY is the name of the function which called us. +// */ +//static void +//add_entry( byte *p, unsigned n, int mode, const char *info, const char *by ) +//{ +// unsigned index; +// struct memtbl_entry *e; +// struct info_entry *ie; +// +// if( memtbl_len < memtbl_size ) +// index = memtbl_len++; +// else { +// struct memtbl_entry *e; +// /* look for a used entry in the table. We take the first one, +// * so that freed entries remain as long as possible in the table +// * (free appends a new one) +// */ +// if( (e = memtbl_unused) ) { +// index = e - memtbl; +// memtbl_unused = e->next; +// e->next = NULL; +// } +// else { /* no free entries in the table: extend the table */ +// if( !memtbl_size ) { /* first time */ +// memtbl_size = 100; +// if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) ) +// membug("memory debug table malloc failed\n"); +// index = 0; +// memtbl_len = 1; +// atexit( dump_table_at_exit ); +// } +// else { /* realloc */ +// unsigned n = memtbl_size / 4; /* enlarge by 25% */ +// if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl))) +// membug("memory debug table realloc failed\n"); +// memset(memtbl+memtbl_size, 0, n*sizeof *memtbl ); +// memtbl_size += n; +// index = memtbl_len++; +// } +// } +// } +// e = memtbl+index; +// if( e->inuse ) +// membug("Ooops: entry %u is flagged as in use\n", index); +// e->user_p = p + 4; +// e->user_n = n; +// e->count++; +// if( e->next ) +// membug("Ooops: entry is in free entry list\n"); +// /* do we already have this info string */ +// for( ie = info_strings[info_hash(info)]; ie; ie = ie->next ) +// if( ie->info == info ) +// break; +// if( !ie ) { /* no: make a new entry */ +// if( !(ie = malloc( sizeof *ie )) ) +// membug("can't allocate info entry\n"); +// ie->next = info_strings[info_hash(info)]; +// info_strings[info_hash(info)] = ie; +// ie->info = info; +// ie->count = 0; +// } +// ie->count++; +// e->info = ie; +// e->inuse = 1; +// +// /* put the index at the start of the memory */ +// p[0] = index; +// p[1] = index >> 8 ; +// p[2] = index >> 16 ; +// p[3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ; +// if( DBG_MEMORY ) +// log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by ); +//} +// +// +// +///**************** +// * Check that the memory block is correct. The magic byte has already been +// * checked. Checks which are done here: +// * - see whether the index points into our memory table +// * - see whether P is the same as the one stored in the table +// * - see whether we have already freed this block. +// */ +//struct memtbl_entry * +//check_mem( const byte *p, const char *info ) +//{ +// unsigned n; +// struct memtbl_entry *e; +// +// n = p[EXTRA_ALIGN+0]; +// n |= p[EXTRA_ALIGN+1] << 8; +// n |= p[EXTRA_ALIGN+2] << 16; +// +// if( n >= memtbl_len ) +// membug("memory at %p corrupted: index=%u table_len=%u (%s)\n", +// p+EXTRA_ALIGN+4, n, memtbl_len, info ); +// e = memtbl+n; +// +// if( e->user_p != p+EXTRA_ALIGN+4 ) +// membug("memory at %p corrupted: reference mismatch (%s)\n", +// p+EXTRA_ALIGN+4, info ); +// if( !e->inuse ) +// membug("memory at %p corrupted: marked as free (%s)\n", +// p+EXTRA_ALIGN+4, info ); +// +// if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE +// || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) ) +// membug("memory at %p corrupted: underflow=%02x (%s)\n", +// p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info ); +// if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE ) +// membug("memory at %p corrupted: overflow=%02x (%s)\n", +// p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info ); +// return e; +//} +// +// +///**************** +// * free the entry and the memory (replaces free) +// */ +//static void +//free_entry( byte *p, const char *info ) +//{ +// struct memtbl_entry *e, *e2; +// +// check_allmem("add_entry"); +// +// e = check_mem(p, info); +// if( DBG_MEMORY ) +// log_debug( "%s frees %u bytes alloced by %s\n", +// info, e->user_n, e->info->info ); +// if( !e->inuse ) { +// if( e->user_p == p + EXTRA_ALIGN+ 4 ) +// membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 ); +// else +// membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 ); +// } +// +// e->inuse = 0; +// e->next = NULL; +// if( !memtbl_unused ) +// memtbl_unused = e; +// else { +// for(e2=memtbl_unused; e2->next; e2 = e2->next ) +// ; +// e2->next = e; +// } +// memset(p,'f', e->user_n+5); +// free(p); +//} +// +//static void +//dump_entry(struct memtbl_entry *e ) +//{ +// unsigned n = e - memtbl; +// +// fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n", +// n, e->inuse?'a':'u', e->count, e->user_p, e->user_n, +// e->info->info, e->info->count ); +// +// +//} +// +// +//static void +//dump_table_at_exit( void) +//{ +// if( DBG_MEMSTAT ) +// dump_table(); +//} +// +//static void +//dump_table( void) +//{ +// unsigned n; +// struct memtbl_entry *e; +// ulong sum = 0, chunks =0; +// +// for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { +// if(e->inuse) { +// dump_entry(e); +// sum += e->user_n; +// chunks++; +// } +// } +// fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n", +// sum, chunks ); +//} +// +// +//static void +//check_allmem( const char *info ) +//{ +// unsigned n; +// struct memtbl_entry *e; +// +// for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) +// if( e->inuse ) +// check_mem(e->user_p-4-EXTRA_ALIGN, info); +//} +// +//#endif /* M_DEBUG */ +// +//#if defined(M_DEBUG) || defined(M_GUARD) +//static void +//membug( const char *fmt, ... ) +//{ +// va_list arg_ptr ; +// +// fprintf(stderr, "\nMemory Error: " ) ; +// va_start( arg_ptr, fmt ) ; +// vfprintf(stderr,fmt,arg_ptr) ; +// va_end(arg_ptr); +// fflush(stderr); +// #ifdef M_DEBUG +// if( DBG_MEMSTAT ) +// dump_table(); +// #endif +// abort(); +//} +//#endif +// +//void +//m_print_stats( const char *prefix ) +//{ +// #ifdef M_DEBUG +// unsigned n; +// struct memtbl_entry *e; +// ulong sum = 0, chunks =0; +// +// for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { +// if(e->inuse) { +// sum += e->user_n; +// chunks++; +// } +// } +// +// log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n", +// prefix? prefix:"", prefix? ": ":"", sum, chunks ); +// #elif defined(M_GUARD) +// log_debug( "%s%smemstat: %8ld bytes\n", +// prefix? prefix:"", prefix? ": ":"", used_memory ); +// #endif +//} +// +//void +//m_dump_table( const char *prefix ) +//{ +// #if M_DEBUG +// fprintf(stderr,"Memory-Table-Dump: %s\n", prefix); +// dump_table(); +// #endif +// m_print_stats( prefix ); +//} +// + +static void +out_of_core(size_t n, int secure) +{ + log_fatal("out of %s memory while allocating %u bytes\n", + secure? "secure":"" ,(unsigned)n ); + +} + +/**************** + * Allocate memory of size n. + * This function gives up if we do not have enough memory + */ +void * +FNAME(alloc)( size_t n FNAMEPRT ) +{ + char *p; + +// #ifdef M_GUARD +// if( !(p = malloc( n + EXTRA_ALIGN+5 )) ) +// out_of_core(n,0); +// store_len(p,n,0); +// used_memory += n; +// p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; +// return p+EXTRA_ALIGN+4; +// #else + if( !(p = kmalloc(n, GFP_KERNEL)) ) + out_of_core(n,0); + return p; +// #endif +} + +/**************** + * Allocate memory of size n from the secure memory pool. + * This function gives up if we do not have enough memory + */ +void * +FNAME(alloc_secure)( size_t n FNAMEPRT ) +{ + /* in the kernel we don't care about secure memory :) */ + return FNAME(alloc)( n FNAMEARG ); +// char *p; +// +// #ifdef M_GUARD +// if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) ) +// out_of_core(n,1); +// store_len(p,n,1); +// p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; +// return p+EXTRA_ALIGN+4; +// #else +// if( !(p = secmem_malloc( n )) ) +// out_of_core(n,1); +// return p; +// #endif +} + +void * +FNAME(alloc_clear)( size_t n FNAMEPRT ) +{ + void *p; + p = FNAME(alloc)( n FNAMEARG ); + memset(p, 0, n ); + return p; +} + +void * +FNAME(alloc_secure_clear)( size_t n FNAMEPRT) +{ + void *p; + p = FNAME(alloc_secure)( n FNAMEARG ); + memset(p, 0, n ); + return p; +} + + +/**************** + * realloc and clear the old space + */ +void * +FNAME(realloc)( void *a, size_t n FNAMEPRT ) +{ + #ifdef M_GUARD + unsigned char *p = a; + void *b; + size_t len = m_size(a); + + if( len >= n ) /* we don't shrink for now */ + return a; + if( p[-1] == MAGIC_SEC_BYTE ) + b = FNAME(alloc_secure_clear)(n FNAMEARG); + else + b = FNAME(alloc_clear)(n FNAMEARG); + FNAME(check)(NULL FNAMEARG); + memcpy(b, a, len ); + FNAME(free)(p FNAMEARG); + #else +// void *b; +// +// if( m_is_secure(a) ) { +// if( !(b = secmem_realloc( a, n )) ) +// out_of_core(n,1); +// } +// else { +// if( !(b = realloc( a, n )) ) +// out_of_core(n,0); +// } + /* */ + void *b; + trace(); + b = kmalloc (n, GFP_KERNEL); + if (b == NULL) { + out_of_core(n,0); + } + memcpy (b, a, n); + kfree(a); + /* */ + + #endif + return b; +} + + + +/**************** + * Free a pointer + */ +void +FNAME(free)( void *a FNAMEPRT ) +{ + byte *p = a; + + if( !p ) + return; +// #ifdef M_DEBUG +// free_entry(p-EXTRA_ALIGN-4, info); +// #elif M_GUARD +// m_check(p); +// if( m_is_secure(a) ) +// secmem_free(p-EXTRA_ALIGN-4); +// else { +// used_memory -= m_size(a); +// free(p-EXTRA_ALIGN-4); +// } +// #else +// if( m_is_secure(a) ) +// secmem_free(p); +// else + kfree(p); +// #endif +} + + +void +FNAME(check)( const void *a FNAMEPRT ) +{ + #ifdef M_GUARD + const byte *p = a; + + #ifdef M_DEBUG + if( p ) + check_mem(p-EXTRA_ALIGN-4, info); + else + check_allmem(info); + #else + if( !p ) + return; + if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) ) + membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] ); + else if( p[m_size(p)] != MAGIC_END_BYTE ) + membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] ); + #endif + #endif +} + + +size_t +m_size( const void *a ) +{ + #ifndef M_GUARD + log_debug("Ooops, m_size called\n"); + return 0; + #else + const byte *p = a; + size_t n; + + #ifdef M_DEBUG + n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n; + #else + n = ((byte*)p)[-4]; + n |= ((byte*)p)[-3] << 8; + n |= ((byte*)p)[-2] << 16; + #endif + return n; + #endif +} + + +#if 0 /* not used */ +/**************** + * Make a copy of the memory block at a + */ +void * +FNAME(copy)( const void *a FNAMEPRT ) +{ + void *b; + size_t n; + + if( !a ) + return NULL; + + n = m_size(a); Aiiiih woher nehmen + if( m_is_secure(a) ) + b = FNAME(alloc_secure)(n FNAMEARG); + else + b = FNAME(alloc)(n FNAMEARG); + memcpy(b, a, n ); + return b; +} +#endif + +char * +FNAME(strdup)( const char *a FNAMEPRT ) +{ + size_t n = strlen(a); + char *p = FNAME(alloc)(n+1 FNAMEARG); + strcpy(p, a); + return p; +} + + +int +m_is_secure( const void *p ) +{ + return 0; /* that's good enough for the kernel :) */ +} + diff -Nru a/security/cryptomark/gnupg/memory.h b/security/cryptomark/gnupg/memory.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/memory.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,86 @@ +/* memory.h - memory allocation + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_MEMORY_H +#define G10_MEMORY_H + +#include "types.h" + +#ifdef M_DEBUG +#ifndef STR + #define STR(v) #v +#endif +#define M_DBGINFO(a) __FUNCTION__ "["__FILE__ ":" STR(a) "]" +#define m_alloc(n) m_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +#define m_alloc_clear(n) m_debug_alloc_clear((n), M_DBGINFO(__LINE__) ) +#define m_alloc_secure(n) m_debug_alloc((n), M_DBGINFO(__LINE__) ) +#define m_alloc_secure_clear(n) m_debug_alloc((n), M_DBGINFO(__LINE__) ) +#define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) ) +#define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) ) +#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) ) +/*#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )*/ +#define m_strdup(a) m_debug_strdup((a), M_DBGINFO(__LINE__) ) + +void *m_debug_alloc( size_t n, const char *info ); +void *m_debug_alloc_clear( size_t n, const char *info ); +void *m_debug_alloc_secure( size_t n, const char *info ); +void *m_debug_alloc_secure_clear( size_t n, const char *info ); +void *m_debug_realloc( void *a, size_t n, const char *info ); +void m_debug_free( void *p, const char *info ); +void m_debug_check( const void *a, const char *info ); +/*void *m_debug_copy( const void *a, const char *info );*/ +char *m_debug_strdup( const char *a, const char *info ); + +#else +void *m_alloc( size_t n ); +void *m_alloc_clear( size_t n ); +void *m_alloc_secure( size_t n ); +void *m_alloc_secure_clear( size_t n ); +void *m_realloc( void *a, size_t n ); +void m_free( void *p ); +void m_check( const void *a ); +/*void *m_copy( const void *a );*/ +char *m_strdup( const char * a); +#endif + +size_t m_size( const void *a ); +void m_print_stats(const char *prefix); + +/*-- secmem.c --*/ +void secmem_init( size_t npool ); +void secmem_term( void ); +void *secmem_malloc( size_t size ); +void *secmem_realloc( void *a, size_t newsize ); +void secmem_free( void *a ); +int m_is_secure( const void *p ); +void secmem_dump_stats(void); +void secmem_set_flags( unsigned flags ); +unsigned secmem_get_flags(void); + + + +#define DBG_MEMORY memory_debug_mode +#define DBG_MEMSTAT memory_stat_debug_mode +int memory_debug_mode; +int memory_stat_debug_mode; + + + +#endif /*G10_MEMORY_H*/ diff -Nru a/security/cryptomark/gnupg/misc.c b/security/cryptomark/gnupg/misc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/misc.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,260 @@ +/* misc.c - miscellaneous functions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 +// #include +// #include +//#endif +//#ifdef HAVE_SETRLIMIT +// #include +// #include +//#endif + + +#include "../cryptomark_log.h" + + +#include "util.h" +#include "main.h" +#include "options.h" +#include "i18n.h" + + +//const char *g10m_revision_string(int); +//const char *g10c_revision_string(int); +//const char *g10u_revision_string(int); +// +//#ifdef __GNUC__ +//volatile +//#endif +// void +//pull_in_libs(void) +//{ +// g10m_revision_string(0); +// g10c_revision_string(0); +// g10u_revision_string(0); +//} +// +// +//#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 +//#warning using trap_unaligned +//static int +//setsysinfo(unsigned long op, void *buffer, unsigned long size, +// int *start, void *arg, unsigned long flag) +//{ +// return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag); +//} +// +//void +//trap_unaligned(void) +//{ +// unsigned int buf[2]; +// +// buf[0] = SSIN_UACPROC; +// buf[1] = UAC_SIGBUS | UAC_NOPRINT; +// setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0); +//} +//#else +//void +//trap_unaligned(void) +//{ /* dummy */ +//} +//#endif +// +// +//void +//disable_core_dumps() +//{ +// #ifndef HAVE_DOSISH_SYSTEM +// #ifdef HAVE_SETRLIMIT +// struct rlimit limit; +// +// limit.rlim_cur = 0; +// limit.rlim_max = 0; +// if( !setrlimit( RLIMIT_CORE, &limit ) ) +// return; +// if( errno != EINVAL ) +// log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) ); +// #endif +// if( !opt.quiet ) +// log_info(_("WARNING: program may create a core file!\n")); +// #endif +//} +// +// +// +//u16 +//checksum_u16( unsigned n ) +//{ +// u16 a; +// +// a = (n >> 8) & 0xff; +// if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) { +// a |= n & 0xff; +// log_debug("csum_u16 emulated for n=%u\n", n); +// } +// else +// a += n & 0xff; +// return a; +//} +// +//static u16 +//checksum_u16_nobug( unsigned n ) +//{ +// u16 a; +// +// a = (n >> 8) & 0xff; +// a += n & 0xff; +// return a; +//} +// +//u16 +//checksum( byte *p, unsigned n ) +//{ +// u16 a; +// +// for(a=0; n; n-- ) +// a += *p++; +// return a; +//} +// +//u16 +//checksum_mpi( MPI a ) +//{ +// u16 csum; +// byte *buffer; +// unsigned nbytes; +// unsigned nbits; +// +// buffer = mpi_get_buffer( a, &nbytes, NULL ); +// /* some versions of gpg encode wrong values for the length of an mpi +// * so that mpi_get_nbits() which counts the mpi yields another (shorter) +// * value than the one store with the mpi. mpi_get_nbit_info() returns +// * this stored value if it is still available. +// */ +// +// if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) +// nbits = 0; +// else +// nbits = mpi_get_nbit_info(a); +// if( !nbits ) +// nbits = mpi_get_nbits(a); +// csum = checksum_u16( nbits ); +// csum += checksum( buffer, nbytes ); +// m_free( buffer ); +// return csum; +//} +// +///**************** +// * This is the correct function +// */ +//u16 +//checksum_mpi_counted_nbits( MPI a ) +//{ +// u16 csum; +// byte *buffer; +// unsigned nbytes; +// unsigned nbits; +// +// buffer = mpi_get_buffer( a, &nbytes, NULL ); +// nbits = mpi_get_nbits(a); +// mpi_set_nbit_info(a,nbits); +// csum = checksum_u16_nobug( nbits ); +// csum += checksum( buffer, nbytes ); +// m_free( buffer ); +// return csum; +//} + + +u32 +buffer_to_u32( const byte *buffer ) +{ + unsigned long a; + a = *buffer << 24; + a |= buffer[1] << 16; + a |= buffer[2] << 8; + a |= buffer[3]; + return a; +} + + +//static void +//no_exp_algo(void) +//{ +// static int did_note = 0; +// +// if( !did_note ) { +// did_note = 1; +// log_info(_("Experimental algorithms should not be used!\n")); +// } +//} +// +//void +//print_pubkey_algo_note( int algo ) +//{ +// if( algo >= 100 && algo <= 110 ) +// no_exp_algo(); +// else if( is_RSA( algo ) ) { +// static int did_note = 0; +// +// if( !did_note ) { +// did_note = 1; +// log_info(_("RSA keys are deprecated; please consider " +// "creating a new key and use this key in the future\n")); +// } +// } +//} +// +//void +//print_cipher_algo_note( int algo ) +//{ +// if( algo >= 100 && algo <= 110 ) +// no_exp_algo(); +// else if( algo == CIPHER_ALGO_3DES +// || algo == CIPHER_ALGO_CAST5 +// || algo == CIPHER_ALGO_BLOWFISH +// || algo == CIPHER_ALGO_TWOFISH +// ) +// ; +// else { +// static int did_note = 0; +// +// if( !did_note ) { +// did_note = 1; +// log_info(_("this cipher algorithm is depreciated; " +// "please use a more standard one!\n")); +// } +// } +//} +// +//void +//print_digest_algo_note( int algo ) +//{ +// if( algo >= 100 && algo <= 110 ) +// no_exp_algo(); +//} +// + + diff -Nru a/security/cryptomark/gnupg/mpi/Makefile b/security/cryptomark/gnupg/mpi/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,120 @@ +# ====================================================================== +# +# Immunix CryptoMark Module +# Copyright 1998, 1999, 2000 Wirex Communications & +# Oregon Graduate Institute +# +# Written by Steve Beattie and +# Greg Kroah-Hartman +# +# ====================================================================== + +# stuff to make a release tarball +VERSION = 0.1 +NAME = cryptomark +MISC_FILES = Makefile BUGS NOTES CHANGELOG README + +# +# Determine if the user is using a StackGuarded compiler, and if so, set +# the switch to turn off the canary death handler option. +# +CANARY_FLAG = $(shell if $(CC) -fno-canary-all-functions -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-canary-all-functions"; fi) +CANARY_FLAG += $(shell if $(CC) -mno-terminator-canary -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-terminator-canary"; fi) + +# Comment/uncomment the following line to enable/disable debugging +#DEBUG = y + +# Change it here or specify it on the "make" commandline +INCLUDEDIR = /usr/include + +ifeq ($(DEBUG),y) + DEBFLAGS = -O -g -DDEBUG_IMMUNIX_MMFS +else + DEBFLAGS = -O2 +endif + +CFLAGS = -malign-loops=2 -malign-jumps=2 -malign-functions=2 -D__KERNEL__ \ + -DMODULE -Wall -Wstrict-prototypes $(CANARY_FLAG) \ + -fomit-frame-pointer $(DEBFLAGS) +CFLAGS += -I$(INCLUDEDIR) +LINKER=ld -r + + +# get the kernel version from the include file +# we need this to determine where to put the module for installation. +KERNEL_VERSION = $(shell grep UTS_RELEASE $(INCLUDEDIR)/linux/version.h | cut -f 2 -d \" ) + +# macro for the immunix header file for us lazy typers +IMMUNIX_H = $(INCLUDEDIR)/linux/immunix.h + + +TARGETS = $(CRYPTOMARK) +CRYPTOMARK = cryptomark.o + +OBJS = \ + mpi-cmp.o \ + mpih-cmp.o \ + mpi-bit.o \ + mpiutil.o \ + mpih-rshift.o \ + mpih-lshift.o \ + mpih-mul1.o \ + mpih-mul2.o \ + mpih-mul3.o \ + mpih-add1.o \ + mpih-sub1.o \ + mpih-div.o \ + mpih-mul.o \ + mpi-mul.o \ + mpi-div.o \ + mpi-add.o \ + mpi-inv.o \ + mpi-pow.o \ + mpi-mpow.o \ + mpicoder.o + + + +all: $(TARGETS) + +mainproc.o: mainproc.c + +main.o: main.c + +iobuf.o: iobuf.c + +armor.o: armor.c + +calc_sig.o: calc_sig.c cryptomark.h $(IMMUNIX_H) + +verify.o: verify.c cryptomark.h $(IMMUNIX_H) + +sysctl.o: sysctl.c subdomain.h + +list.o: list.c subdomain.h info.h + +prefetch.o: prefetch.c subdomain.h + +info.o: info.c info.h info_p.h + + +$(CRYPTOMARK): $(OBJS) + $(LINKER) -o $@ $(OBJS) + +clean: + rm -f *.o *.ver *~ + +install: all + -mkdir /lib/modules/$(KERNEL_VERSION)/ + -mkdir /lib/modules/$(KERNEL_VERSION)/misc/ + cp $(TARGETS) /lib/modules/$(KERNEL_VERSION)/misc/ + +release: + -rm -rf $(NAME)-$(VERSION) + mkdir $(NAME)-$(VERSION) + cp *.c $(NAME)-$(VERSION) + cp *.h $(NAME)-$(VERSION) + cp $(MISC_FILES) $(NAME)-$(VERSION) + tar czv -f $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION) + rm -rf $(NAME)-$(VERSION) + diff -Nru a/security/cryptomark/gnupg/mpi/asm-syntax.h b/security/cryptomark/gnupg/mpi/asm-syntax.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/asm-syntax.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,64 @@ +/* created by config.links - do not edit */ +#define ELF_SYNTAX +/* asm.h -- Definitions for x86 syntax variations. + +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. */ + + +#undef ALIGN + +#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) +#define R(r) %r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)displacement(R(base)) +#define MEM_INDEX(base,index,size)(R(base),R(index),size) +#ifdef __STDC__ +#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst +#else +#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst +#endif +#define TEXT .text +#if defined (BSD_SYNTAX) +#define ALIGN(log) .align log +#endif +#if defined (ELF_SYNTAX) +#define ALIGN(log) .align 1<<(log) +#endif +#define GLOBL .globl +#endif + +#ifdef INTEL_SYNTAX +#define R(r) r +#define MEM(base)[base] +#define MEM_DISP(base,displacement)[base+(displacement)] +#define MEM_INDEX(base,index,size)[base+index*size] +#define INSN1(mnemonic,size_suffix,dst)mnemonic dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef X86_BROKEN_ALIGN +#undef ALIGN +#define ALIGN(log) .align log,0x90 +#endif diff -Nru a/security/cryptomark/gnupg/mpi/longlong.h b/security/cryptomark/gnupg/mpi/longlong.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/longlong.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1483 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with g10 + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file 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. + +This file 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 this file; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + + +/*************************************** + ************** A29K ***************** + ***************************************/ +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5 + addc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5 + subc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((USItype)(xh)) \ + : "r" (__m0), \ + "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" ((USItype)(q)), \ + "=q" ((USItype)(r)) \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#endif /* __alpha */ + +/*************************************** + ************** ARM ****************** + ***************************************/ +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5 + adc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5 + sbc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm + mov %|r0, %2, lsr #16 + mov %|r2, %3, lsr #16 + bic %|r1, %2, %|r0, lsl #16 + bic %|r2, %3, %|r2, lsl #16 + mul %1, %|r1, %|r2 + mul %|r2, %|r0, %|r2 + mul %|r1, %0, %|r1 + mul %0, %|r0, %0 + adds %|r1, %|r2, %|r1 + addcs %0, %0, #65536 + adds %1, %1, %|r1, lsl #16 + adc %0, %0, %|r1, lsr #16" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2") +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +/*************************************** + ************** CLIPPER ************** + ***************************************/ +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((SItype)(u)), \ + "r" ((SItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + + +/*************************************** + ************** GMICRO *************** + ***************************************/ +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1 + addx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1 + subx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%0" ((USItype)(m0)), \ + "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) +#endif + + +/*************************************** + ************** HPPA ***************** + ***************************************/ +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1 + addc %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "%rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1 + subb %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#endif /* LONGLONG_STANDALONE */ +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0 + extru,= %1,15,16,%%r0 ; Bits 31..16 zero? + extru,tr %1,15,16,%1 ; No. Shift down, skip add. + ldo 16(%0),%0 ; Yes. Perform add. + extru,= %1,23,8,%%r0 ; Bits 15..8 zero? + extru,tr %1,23,8,%1 ; No. Shift down, skip add. + ldo 8(%0),%0 ; Yes. Perform add. + extru,= %1,27,4,%%r0 ; Bits 7..4 zero? + extru,tr %1,27,4,%1 ; No. Shift down, skip add. + ldo 4(%0),%0 ; Yes. Perform add. + extru,= %1,29,2,%%r0 ; Bits 3..2 zero? + extru,tr %1,29,2,%1 ; No. Shift down, skip add. + ldo 2(%0),%0 ; Yes. Perform add. + extru %1,30,1,%1 ; Extract bit 1. + sub %0,%1,%0 ; Subtract it. + " : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + + +/*************************************** + ************** I370 ***************** + ***************************************/ +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + + +/*************************************** + ************** I386 ***************** + ***************************************/ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1 + adcl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1 + sbbl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divl %4" \ + : "=a" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#ifndef UMUL_TIME +#define UMUL_TIME 40 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + + +/*************************************** + ************** I860 ***************** + ***************************************/ +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +/*************************************** + ************** I960 ***************** + ***************************************/ +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "%dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) \ + : "dI" (__nn.__ll), \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" \ + : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + + +/*************************************** + ************** 68000 **************** + ***************************************/ +#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1 + addx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1 + subx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#else /* not mc68020 */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm + move%.l %5,%3 + move%.l %2,%0 + move%.w %3,%1 + swap %3 + swap %0 + mulu %2,%1 + mulu %3,%0 + mulu %2,%3 + swap %2 + mulu %5,%2 + add%.l %3,%2 + jcc 1f + add%.l %#0x10000,%0 +1: move%.l %2,%3 + clr%.w %2 + swap %2 + swap %3 + clr%.w %3 + add%.l %3,%1 + addx%.l %2,%0 + | End inlined umul_ppmm" \ + : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + + +/*************************************** + ************** 88000 **************** + ***************************************/ +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5 + addu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5 + subu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x, __q; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ + (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + + +/*************************************** + ************** MIPS ***************** + ***************************************/ +#if defined (__mips__) && W_TYPE_SIZE == 32 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype)(w0)), \ + "=h" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +/*************************************** + ************** MIPS/64 ************** + ***************************************/ +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" ((UDItype)(w0)), \ + "=h" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((UDItype)(w0)), \ + "=d" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips__ */ + + +/*************************************** + ************** 32000 **************** + ***************************************/ +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + + +/*************************************** + ************** PPC ****************** + ***************************************/ +#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" ((USItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" \ + : "=r" ((SItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((USItype)(xh)), \ + "=q" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((SItype)(xh)), \ + "=q" ((SItype)(xl)) \ + : "r" (m0), \ + "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" \ + : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ + : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) +#define UDIV_TIME 100 +#endif +#endif /* Power architecture variants. */ + + +/*************************************** + ************** PYR ****************** + ***************************************/ +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1 + addwc %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1 + subwb %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("movw %1,%R0 + uemul %2,%0" \ + : "=&r" (__xx.__ll) \ + : "g" ((USItype) (u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + + +/*************************************** + ************** RT/ROMP ************** + ***************************************/ +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5 + ae %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5 + se %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 + mts r10,%2 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + cas %0,r2,r0 + mfs r10,%1" \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + + +/*************************************** + ************** SH2 ****************** + ***************************************/ +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3 + sts macl,%1 + sts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/*************************************** + ************** SPARC **************** + ***************************************/ +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1 + addx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1 + subx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" ((USItype)(__q)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* SUPERSPARC */ +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd + wr %%g0,%2,%%y ! Not a delayed write for sparclite + tst %%g0 + divscc %3,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%0 + rd %%y,%1 + bl,a 1f + add %1,%4,%1 +1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,0,%0" \ + : "=r" ((USItype)(x)) \ + : "r" ((USItype)(count))) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm + wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr + sra %3,31,%%g2 ! Don't move this insn + and %2,%%g2,%%g2 ! Don't move this insn + andcc %%g0,0,%%g1 ! Don't move this insn + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,0,%%g1 + add %%g1,%%g2,%0 + rd %%y,%1" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#define UDIV_TIME 140 +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + + +/*************************************** + ************** VAX ****************** + ***************************************/ +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1 + adwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1 + sbwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + + +/*************************************** + ************** Z8000 **************** + ***************************************/ +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + + +/*************************************** + *********** Generic Versions ******** + ***************************************/ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char __clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff -Nru a/security/cryptomark/gnupg/mpi/mpi-add.c b/security/cryptomark/gnupg/mpi/mpi-add.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-add.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,247 @@ +/* mpi-add.c - MPI functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include + +#include "mpi-internal.h" + + +/**************** + * Add the unsigned integer V to the mpi-integer U and store the + * result in W. U and V may be the same. + */ +void +mpi_add_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + } + else if( !usign ) { /* mpi is not negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + wsign = 1; + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +mpi_add(MPI w, MPI u, MPI v) +{ + mpi_ptr_t wp, up, vp; + mpi_size_t usize, vsize, wsize; + int usign, vsign, wsign; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + vsize = u->nlimbs; + vsign = u->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = v->d; + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + vsize = v->nlimbs; + vsign = v->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + } + wp = w->d; + wsign = 0; + + if( !vsize ) { /* simple */ + MPN_COPY(wp, up, usize ); + wsize = usize; + wsign = usign; + } + else if( usign != vsign ) { /* different sign */ + /* This test is right since USIZE >= VSIZE */ + if( usize != vsize ) { + mpihelp_sub(wp, up, usize, vp, vsize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + wsign = usign; + } + else if( mpihelp_cmp(up, vp, usize) < 0 ) { + mpihelp_sub_n(wp, vp, up, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( !usign ) + wsign = 1; + } + else { + mpihelp_sub_n(wp, up, vp, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( usign ) + wsign = 1; + } + } + else { /* U and V have same sign. Add them. */ + mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize); + wp[usize] = cy; + wsize = usize + cy; + if( usign ) + wsign = 1; + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +/**************** + * Subtract the unsigned integer V from the mpi-integer U and store the + * result in W. + */ +void +mpi_sub_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + wsign = 1; + } + else if( usign ) { /* mpi and v are negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + wsign = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + +void +mpi_sub(MPI w, MPI u, MPI v) +{ + if( w == v ) { + MPI vv = mpi_copy(v); + vv->sign = !vv->sign; + mpi_add( w, u, vv ); + mpi_free(vv); + } + else { + /* fixme: this is not thread-save (we temp. modify v) */ + v->sign = !v->sign; + mpi_add( w, u, v ); + v->sign = !v->sign; + } +} + + +void +mpi_addm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_add(w, u, v); + mpi_fdiv_r( w, w, m ); +} + +void +mpi_subm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_sub(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-bit.c b/security/cryptomark/gnupg/mpi/mpi-bit.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-bit.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,262 @@ +/* mpi-bit.c - MPI bit level fucntions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" + + +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +__clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + +#define A_LIMB_1 ((mpi_limb_t)1) + + +/**************** + * Sometimes we have MSL (most significant limbs) which are 0; + * this is for some reasons not good, so this function removes them. + */ +void +mpi_normalize( MPI a ) +{ + if( mpi_is_protected(a) ) + return; + + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) + ; +} + + + +/**************** + * Return the number of bits in A. + */ +unsigned +mpi_get_nbits( MPI a ) +{ + unsigned n; + + if( mpi_is_protected(a) ) { + n = mpi_get_nbit_info(a); + if( !n ) + n = a->nlimbs * BITS_PER_MPI_LIMB; + return n; + } + + mpi_normalize( a ); + if( a->nlimbs ) { + mpi_limb_t alimb = a->d[a->nlimbs-1]; + if( alimb ) + count_leading_zeros( n, alimb ); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; + } + else + n = 0; + return n; +} + + +/**************** + * Test whether bit N is set. + */ +int +mpi_test_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + mpi_limb_t limb; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return 0; /* too far left: this is a 0 */ + limb = a->d[limbno]; + return (limb & (A_LIMB_1 << bitno))? 1: 0; +} + + +/**************** + * Set bit N of A. + */ +void +mpi_set_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * clear bit N of A and all bits above + */ +void +mpi_clear_highbit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* not allocated, so need to clear bits :-) */ + + for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * Clear bit N of A. + */ +void +mpi_clear_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* don't need to clear this bit, it's to far to left */ + a->d[limbno] &= ~(A_LIMB_1 << bitno); +} + + +/**************** + * Shift A by N bits to the right + * FIXME: should use alloc_limb if X and A are same. + */ +void +mpi_rshift( MPI x, MPI a, unsigned n ) +{ + mpi_ptr_t xp; + mpi_size_t xsize; + + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED(x, xsize); + xp = x->d; + + if( xsize ) { + mpihelp_rshift( xp, a->d, xsize, n); + MPN_NORMALIZE( xp, xsize); + } + x->nlimbs = xsize; +} + + +/**************** + * Shift A by COUNT limbs to the left + * This is used only within the MPI library + */ +void +mpi_lshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + int n = a->nlimbs; + int i; + + if( !count || !n ) + return; + + RESIZE_IF_NEEDED( a, n+count ); + + for( i = n-1; i >= 0; i-- ) + ap[i+count] = ap[i]; + for(i=0; i < count; i++ ) + ap[i] = 0; + a->nlimbs += count; +} + + +/**************** + * Shift A by COUNT limbs to the right + * This is used only within the MPI library + */ +void +mpi_rshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + mpi_size_t n = a->nlimbs; + unsigned int i; + + if( count >= n ) { + a->nlimbs = 0; + return; + } + + for( i = 0; i < n - count; i++ ) + ap[i] = ap[i+count]; + ap[i] = 0; + a->nlimbs -= count; +} + + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-cmp.c b/security/cryptomark/gnupg/mpi/mpi-cmp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-cmp.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,74 @@ +/* mpi-cmp.c - MPI functions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +#include "mpi-internal.h" + +int +mpi_cmp_ui( MPI u, unsigned long v ) +{ + mpi_limb_t limb = v; + + mpi_normalize( u ); + if( !u->nlimbs && !limb ) + return 0; + if( u->sign ) + return -1; + if( u->nlimbs > 1 ) + return 1; + + if( u->d[0] == limb ) + return 0; + else if( u->d[0] > limb ) + return 1; + else + return -1; +} + +int +mpi_cmp( MPI u, MPI v ) +{ + mpi_size_t usize, vsize; + int cmp; + + mpi_normalize( u ); + mpi_normalize( v ); + usize = u->nlimbs; + vsize = v->nlimbs; + if( !u->sign && v->sign ) + return 1; + if( u->sign && !v->sign ) + return -1; + if( usize != vsize && !u->sign && !v->sign ) + return usize - vsize; + if( usize != vsize && u->sign && v->sign ) + return vsize + usize; + if( !usize ) + return 0; + if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) ) + return 0; + if( (cmp < 0?1:0) == (u->sign?1:0)) + return 1; + return -1; +} + + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-div.c b/security/cryptomark/gnupg/mpi/mpi-div.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-div.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,322 @@ +/* mpi-div.c - MPI functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" + + + +void +mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + /* We need the original value of the divisor after the remainder has been + * preliminary calculated. We have to copy it to temporary space if it's + * the same variable as REM. */ + if( rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_r( rem, dividend, divisor ); + + if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) + mpi_add( rem, rem, divisor); + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + + +/**************** + * Division rounding the quotient towards -infinity. + * The remainder gets the same sign as the denominator. + * rem is optional + */ + +ulong +mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ) +{ + mpi_limb_t rlimb; + + rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); + if( rlimb && dividend->sign ) + rlimb = divisor - rlimb; + + if( rem ) { + rem->d[0] = rlimb; + rem->nlimbs = rlimb? 1:0; + } + return rlimb; +} + + +void +mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ) +{ + MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) ); + mpi_fdiv_qr( quot, tmp, dividend, divisor); + mpi_free(tmp); +} + +void +mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + if( quot == divisor || rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_qr( quot, rem, dividend, divisor ); + + if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { + mpi_sub_ui( quot, quot, 1 ); + mpi_add( rem, rem, divisor); + } + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + +/* If den == quot, den needs temporary storage. + * If den == rem, den needs temporary storage. + * If num == quot, num needs temporary storage. + * If den has temporary storage, it can be normalized while being copied, + * i.e no extra storage should be allocated. + */ + +void +mpi_tdiv_r( MPI rem, MPI num, MPI den) +{ + mpi_tdiv_qr(NULL, rem, num, den ); +} + +void +mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den) +{ + mpi_ptr_t np, dp; + mpi_ptr_t qp, rp; + mpi_size_t nsize = num->nlimbs; + mpi_size_t dsize = den->nlimbs; + mpi_size_t qsize, rsize; + mpi_size_t sign_remainder = num->sign; + mpi_size_t sign_quotient = num->sign ^ den->sign; + unsigned normalization_steps; + mpi_limb_t q_limb; + mpi_ptr_t marker[5]; + int markidx=0; + + /* Ensure space is enough for quotient and remainder. + * We need space for an extra limb in the remainder, because it's + * up-shifted (normalized) below. */ + rsize = nsize + 1; + mpi_resize( rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if( qsize <= 0 ) { + if( num != rem ) { + rem->nlimbs = num->nlimbs; + rem->sign = num->sign; + MPN_COPY(rem->d, num->d, nsize); + } + if( quot ) { + /* This needs to follow the assignment to rem, in case the + * numerator and quotient are the same. */ + quot->nlimbs = 0; + quot->sign = 0; + } + return; + } + + if( quot ) + mpi_resize( quot, qsize); + + /* Read pointers here, when reallocation is finished. */ + np = num->d; + dp = den->d; + rp = rem->d; + + /* Optimize division by a single-limb divisor. */ + if( dsize == 1 ) { + mpi_limb_t rlimb; + if( quot ) { + qp = quot->d; + rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] ); + qsize -= qp[qsize - 1] == 0; + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + else + rlimb = mpihelp_mod_1( np, nsize, dp[0] ); + rp[0] = rlimb; + rsize = rlimb != 0?1:0; + rem->nlimbs = rsize; + rem->sign = sign_remainder; + return; + } + + + if( quot ) { + qp = quot->d; + /* Make sure QP and NP point to different objects. Otherwise the + * numerator would be gradually overwritten by the quotient limbs. */ + if(qp == np) { /* Copy NP object to temporary space. */ + np = marker[markidx++] = mpi_alloc_limb_space(nsize, + mpi_is_secure(quot)); + MPN_COPY(np, qp, nsize); + } + } + else /* Put quotient at top of remainder. */ + qp = rp + dsize; + + count_leading_zeros( normalization_steps, dp[dsize - 1] ); + + /* Normalize the denominator, i.e. make its most significant bit set by + * shifting it NORMALIZATION_STEPS bits to the left. Also shift the + * numerator the same number of steps (to keep the quotient the same!). + */ + if( normalization_steps ) { + mpi_ptr_t tp; + mpi_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + * the most significant word. Use temporary storage not to clobber + * the original contents of the denominator. */ + tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); + mpihelp_lshift( tp, dp, dsize, normalization_steps ); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + * significant word. Move the shifted numerator in the remainder + * meanwhile. */ + nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps); + if( nlimb ) { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else { + /* The denominator is already normalized, as required. Copy it to + * temporary space if it overlaps with the quotient or remainder. */ + if( dp == rp || (quot && (dp == qp))) { + mpi_ptr_t tp; + + tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den)); + MPN_COPY( tp, dp, dsize ); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if( rp != np ) + MPN_COPY(rp, np, nsize); + + rsize = nsize; + } + + q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize ); + + if( quot ) { + qsize = rsize - dsize; + if(q_limb) { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if( normalization_steps && rsize ) { + mpihelp_rshift(rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0?1:0; + } + + rem->nlimbs = rsize; + rem->sign = sign_remainder; + while( markidx ) + mpi_free_limb_space(marker[--markidx]); +} + +void +mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ) +{ + mpi_size_t usize, wsize; + mpi_size_t limb_cnt; + + usize = u->nlimbs; + limb_cnt = count / BITS_PER_MPI_LIMB; + wsize = usize - limb_cnt; + if( limb_cnt >= usize ) + w->nlimbs = 0; + else { + mpi_ptr_t wp; + mpi_ptr_t up; + + RESIZE_IF_NEEDED( w, wsize ); + wp = w->d; + up = u->d; + + count %= BITS_PER_MPI_LIMB; + if( count ) { + mpihelp_rshift( wp, up + limb_cnt, wsize, count ); + wsize -= !wp[wsize - 1]; + } + else { + MPN_COPY_INCR( wp, up + limb_cnt, wsize); + } + + w->nlimbs = wsize; + } +} + +/**************** + * Check whether dividend is divisible by divisor + * (note: divisor must fit into a limb) + */ +int +mpi_divisible_ui(MPI dividend, ulong divisor ) +{ + return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-inline.h b/security/cryptomark/gnupg/mpi/mpi-inline.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-inline.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,129 @@ +/* mpi-inline.h - Internal to the Multi Precision Integers + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_INLINE_H +#define G10_MPI_INLINE_H + +#ifndef G10_MPI_INLINE_DECL + #define G10_MPI_INLINE_DECL extern __inline__ +#endif + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb += x; + *res_ptr++ = s2_limb; + if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ + while( --s1_size ) { + x = *s1_ptr++ + 1; /* add carry */ + *res_ptr++ = x; /* and store */ + if( x ) /* not 0 (no overflow): we can stop */ + goto leave; + } + return 1; /* return carry (size of s1 to small) */ + } + + leave: + if( res_ptr != s1_ptr ) { /* not the same variable */ + mpi_size_t i; /* copy the rest */ + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; /* no carry */ +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); + + if( s1_size - s2_size ) + cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if( s2_limb > x ) { + while( --s1_size ) { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if( x ) + goto leave; + } + return 1; + } + + leave: + if( res_ptr != s1_ptr ) { + mpi_size_t i; + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); + + if( s1_size - s2_size ) + cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +#endif /*G10_MPI_INLINE_H*/ diff -Nru a/security/cryptomark/gnupg/mpi/mpi-internal.h b/security/cryptomark/gnupg/mpi/mpi-internal.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-internal.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,242 @@ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_INTERNAL_H +#define G10_MPI_INTERNAL_H + +#include "../mpi.h" + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + * value which is good on most machines. */ + +/* tested 4, 16, 32 and 64, where 16 gave the best performance when + * checking a 768 and a 1024 bit ElGamal signature. + * (wk 22.12.97) */ +#ifndef KARATSUBA_THRESHOLD + #define KARATSUBA_THRESHOLD 16 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 + #undef KARATSUBA_THRESHOLD + #define KARATSUBA_THRESHOLD 2 +#endif + + +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ +typedef int mpi_size_t; /* (must be a signed type) */ + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define RESIZE_IF_NEEDED(a,b) \ + do { \ + if( (a)->alloced < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) + +/* Copy N limbs from S to D. */ +#define MPN_COPY( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +#define MPN_COPY_INCR( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (d)[_i]; \ + } while (0) + +#define MPN_COPY_DECR( d, s, n ) \ + do { \ + mpi_size_t _i; \ + for( _i = (n)-1; _i >= 0; _i--) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +/* Zero N limbs at D */ +#define MPN_ZERO(d, n) \ + do { \ + int _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(d, n) \ + do { \ + while( (n) > 0 ) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_NORMALIZE_NOT_ZERO(d, n) \ + do { \ + for(;;) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + * If this would yield overflow, DI should be the largest possible number + * (i.e., only ones). For correct operation, the most significant bit of D + * has to be set. Put the quotient in Q and the remainder in R. + */ +#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ + do { \ + mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if( _xh ) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + if( _xh) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + } \ + } \ + if( _r >= (d) ) { \ + _r -= (d); \ + _q++; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) + + +/*-- mpiutil.c --*/ +#ifdef M_DEBUG + #define mpi_alloc_limb_space(n,f) mpi_debug_alloc_limb_space((n),(f), M_DBGINFO( __LINE__ ) ) + #define mpi_free_limb_space(n) mpi_debug_free_limb_space((n), M_DBGINFO( __LINE__ ) ) + mpi_ptr_t mpi_debug_alloc_limb_space( unsigned nlimbs, int sec, const char *info ); + void mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ); +#else + mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs, int sec ); + void mpi_free_limb_space( mpi_ptr_t a ); +#endif +void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ); + +/*-- mpi-bit.c --*/ +void mpi_rshift_limbs( MPI a, unsigned int count ); +void mpi_lshift_limbs( MPI a, unsigned int count ); + + +/*-- mpihelp-add.c --*/ +mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +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); +mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-sub.c --*/ +mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-cmp.c --*/ +int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); + +/*-- mpihelp-mul.c --*/ +mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +void mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size); +mpi_limb_t mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize); +void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); +void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, + mpi_ptr_t tspace); + +/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/ +mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); + +/*-- mpihelp-div.c --*/ +mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); +mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize); +mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); + +/*-- mpihelp-shift.c --*/ +mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); +mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); + + +/* Define stuff for longlong.h. */ +#define W_TYPE_SIZE BITS_PER_MPI_LIMB + typedef mpi_limb_t UWtype; + typedef unsigned int UHWtype; +#if defined (__GNUC__) + typedef unsigned int UQItype __attribute__ ((mode (QI))); + typedef int SItype __attribute__ ((mode (SI))); + typedef unsigned int USItype __attribute__ ((mode (SI))); + typedef int DItype __attribute__ ((mode (DI))); + typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else + typedef unsigned char UQItype; + typedef long SItype; + typedef unsigned long USItype; +#endif + +#ifdef __GNUC__ + #include "mpi-inline.h" +#endif + +#endif /*G10_MPI_INTERNAL_H*/ diff -Nru a/security/cryptomark/gnupg/mpi/mpi-inv.c b/security/cryptomark/gnupg/mpi/mpi-inv.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-inv.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,270 @@ +/* mpi-inv.c - MPI functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +#include "mpi-internal.h" + + +/**************** + * Calculate the multiplicative inverse X of A mod N + * That is: Find the solution x for + * 1 = (a*x) mod n + */ +void +mpi_invm( MPI x, MPI a, MPI n ) +{ + #if 0 + MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; + MPI ta, tb, tc; + + u = mpi_copy(a); + v = mpi_copy(n); + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_alloc_set_ui(0); + v2 = mpi_alloc_set_ui(1); + v3 = mpi_copy(v); + q = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + while( mpi_cmp_ui( v3, 0 ) ) { + mpi_fdiv_q( q, u3, v3 ); + mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); + mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); + mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); + mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); + } + /* log_debug("result:\n"); + log_mpidump("q =", q ); + log_mpidump("u1=", u1); + log_mpidump("u2=", u2); + log_mpidump("u3=", u3); + log_mpidump("v1=", v1); + log_mpidump("v2=", v2); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(q); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + mpi_free(u); + mpi_free(v); + #elif 0 + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 */ + + /* FIXME: we can simplify this in most cases (see Knuth) */ + MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; + unsigned k; + int sign; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + + + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); /* !-- used as const 1 */ + v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + #else + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 + * with further enhancement */ + MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); + + mpi_free(u); + mpi_free(v); + #endif +} + + + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-mpow.c b/security/cryptomark/gnupg/mpi/mpi-mpow.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-mpow.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,222 @@ +/* mpi-mpow.c - MPI functions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" +//#include + +/* Barrett is slower than the classical way. It can be tweaked by + * using partial multiplications + */ +/*#define USE_BARRETT*/ + + + +#ifdef USE_BARRETT +static void barrett_mulm( MPI w, MPI u, MPI v, MPI m, MPI y, int k, MPI r1, MPI r2 ); +static MPI init_barrett( MPI m, int *k, MPI *r1, MPI *r2 ); +static int calc_barrett( MPI r, MPI x, MPI m, MPI y, int k, MPI r1, MPI r2 ); +#else +#define barrett_mulm( w, u, v, m, y, k, r1, r2 ) mpi_mulm( (w), (u), (v), (m) ) +#endif + + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int index = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/ + return index; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + #ifdef USE_BARRETT + MPI barrett_y, barrett_r1, barrett_r2; + int barrett_k; + #endif + + for(k=0; basearray[k]; k++ ) + ; +// assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ +// assert(i==k); +// assert(t); +// assert( k < 10 ); + + G = m_alloc_clear( (1<= 0 && idx < (1< 3 ? k-3:0; + + mpi_normalize( x ); + if( mpi_get_nlimbs(x) > 2*k ) + return 1; /* can't do it */ + + /* 1. q1 = floor( x / b^k-1) + * q2 = q1 * y + * q3 = floor( q2 / b^k+1 ) + * Actually, we don't need qx, we can work direct on r2 + */ + mpi_set( r2, x ); + mpi_rshift_limbs( r2, k-1 ); + mpi_mul( r2, r2, y ); + mpi_rshift_limbs( r2, k+1 ); + + /* 2. r1 = x mod b^k+1 + * r2 = q3 * m mod b^k+1 + * r = r1 - r2 + * 3. if r < 0 then r = r + b^k+1 + */ + mpi_set( r1, x ); + if( r1->nlimbs > k+1 ) /* quick modulo operation */ + r1->nlimbs = k+1; + mpi_mul( r2, r2, m ); + if( r2->nlimbs > k+1 ) /* quick modulo operation */ + r2->nlimbs = k+1; + mpi_sub( r, r1, r2 ); + + if( mpi_is_neg( r ) ) { + MPI tmp; + + tmp = mpi_alloc( k + 2 ); + mpi_set_ui( tmp, 1 ); + mpi_lshift_limbs( tmp, k+1 ); + mpi_add( r, r, tmp ); + mpi_free(tmp); + } + + /* 4. while r >= m do r = r - m */ + while( mpi_cmp( r, m ) >= 0 ) + mpi_sub( r, r, m ); + + return 0; +} +#endif /* USE_BARRETT */ + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-mul.c b/security/cryptomark/gnupg/mpi/mpi-mul.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-mul.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,198 @@ +/* mpi-mul.c - MPI functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include +#include "mpi-internal.h" + + +void +mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult ) +{ + mpi_size_t size, prod_size; + mpi_ptr_t prod_ptr; + mpi_limb_t cy; + int sign; + + size = mult->nlimbs; + sign = mult->sign; + + if( !size || !small_mult ) { + prod->nlimbs = 0; + prod->sign = 0; + return; + } + + prod_size = size + 1; + if( prod->alloced < prod_size ) + mpi_resize( prod, prod_size ); + prod_ptr = prod->d; + + cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); + if( cy ) + prod_ptr[size++] = cy; + prod->nlimbs = size; + prod->sign = sign; +} + + +void +mpi_mul_2exp( MPI w, MPI u, unsigned long cnt) +{ + mpi_size_t usize, wsize, limb_cnt; + mpi_ptr_t wp; + mpi_limb_t wlimb; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + + if( !usize ) { + w->nlimbs = 0; + w->sign = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MPI_LIMB; + wsize = usize + limb_cnt + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize ); + wp = w->d; + wsize = usize + limb_cnt; + wsign = usign; + + cnt %= BITS_PER_MPI_LIMB; + if( cnt ) { + wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt ); + if( wlimb ) { + wp[wsize] = wlimb; + wsize++; + } + } + else { + MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + * mpn_lshift, not to lose for U == W. */ + MPN_ZERO( wp, limb_cnt ); + + w->nlimbs = wsize; + w->sign = wsign; +} + + + +void +mpi_mul( MPI w, MPI u, MPI v) +{ + mpi_size_t usize, vsize, wsize; + mpi_ptr_t up, vp, wp; + mpi_limb_t cy; + int usign, vsign, usecure, vsecure, sign_product; + int assign_wp=0; + mpi_ptr_t tmp_limb=NULL; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + usecure = mpi_is_secure(v); + up = v->d; + vsize = u->nlimbs; + vsign = u->sign; + vsecure = mpi_is_secure(u); + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + usecure = mpi_is_secure(u); + up = u->d; + vsize = v->nlimbs; + vsign = v->sign; + vsecure = mpi_is_secure(v); + vp = v->d; + } + sign_product = usign ^ vsign; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if( w->alloced < wsize ) { + if( wp == up || wp == vp ) { + wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); + assign_wp = 1; + } + else { + mpi_resize(w, wsize ); + wp = w->d; + } + } + else { /* Make U and V not overlap with W. */ + if( wp == up ) { + /* W and U are identical. Allocate temporary space for U. */ + up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); + /* Is V identical too? Keep it identical with U. */ + if( wp == vp ) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY( up, wp, usize ); + } + else if( wp == vp ) { + /* W and V are identical. Allocate temporary space for V. */ + vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); + /* Copy to the temporary space. */ + MPN_COPY( vp, wp, vsize ); + } + } + + if( !vsize ) + wsize = 0; + else { + cy = mpihelp_mul( wp, up, usize, vp, vsize ); + wsize -= cy? 0:1; + } + + if( assign_wp ) + mpi_assign_limb_space( w, wp, wsize ); + w->nlimbs = wsize; + w->sign = sign_product; + if( tmp_limb ) + mpi_free_limb_space( tmp_limb ); +} + + +void +mpi_mulm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_mul(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpi-pow.c b/security/cryptomark/gnupg/mpi/mpi-pow.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpi-pow.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,282 @@ +/* mpi-pow.c - MPI functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" +//#include + + +/**************** + * RES = BASE ^ EXP mod MOD + */ +void +mpi_powm( MPI res, MPI base, MPI exp, MPI mod) +{ + mpi_ptr_t rp, ep, mp, bp; + mpi_size_t esize, msize, bsize, rsize; + int esign, msign, bsign, rsign; + int esec, msec, bsec, rsec; + mpi_size_t size; + int mod_shift_cnt; + int negative_result; + mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL; + mpi_ptr_t xp_marker=NULL; + int assign_rp=0; + mpi_ptr_t tspace = NULL; + mpi_size_t tsize=0; /* to avoid compiler warning */ + /* fixme: we should check that the warning is void*/ + + esize = exp->nlimbs; + msize = mod->nlimbs; + size = 2 * msize; + esign = exp->sign; + msign = mod->sign; + + esec = mpi_is_secure(exp); + msec = mpi_is_secure(mod); + bsec = mpi_is_secure(base); + rsec = mpi_is_secure(res); + + rp = res->d; + ep = exp->d; + + if( !msize ) + msize = 1 / msize; /* provoke a signal */ + + if( !esize ) { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + * depending on if MOD equals 1. */ + rp[0] = 1; + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + res->sign = 0; + goto leave; + } + + /* Normalize MOD (i.e. make its most significant bit set) as required by + * mpn_divrem. This will make the intermediate values in the calculation + * slightly larger, but the correct result is obtained after a final + * reduction using the original MOD value. */ + mp = mp_marker = mpi_alloc_limb_space(msize, msec); + count_leading_zeros( mod_shift_cnt, mod->d[msize-1] ); + if( mod_shift_cnt ) + mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt ); + else + MPN_COPY( mp, mod->d, msize ); + + bsize = base->nlimbs; + bsign = base->sign; + if( bsize > msize ) { /* The base is larger than the module. Reduce it. */ + /* Allocate (BSIZE + 1) with space for remainder and quotient. + * (The quotient is (bsize - msize + 1) limbs.) */ + bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); + MPN_COPY( bp, base->d, bsize ); + /* We don't care about the quotient, store it above the remainder, + * at BP + MSIZE. */ + mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize ); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + * quite a few times. */ + MPN_NORMALIZE( bp, bsize ); + } + else + bp = base->d; + + if( !bsize ) { + res->nlimbs = 0; + res->sign = 0; + goto leave; + } + + if( res->alloced < size ) { + /* We have to allocate more space for RES. If any of the input + * parameters are identical to RES, defer deallocation of the old + * space. */ + if( rp == ep || rp == mp || rp == bp ) { + rp = mpi_alloc_limb_space( size, rsec ); + assign_rp = 1; + } + else { + mpi_resize( res, size ); + rp = res->d; + } + } + else { /* Make BASE, EXP and MOD not overlap with RES. */ + if( rp == bp ) { + /* RES and BASE are identical. Allocate temp. space for BASE. */ +// assert( !bp_marker ); + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); + } + if( rp == ep ) { + /* RES and EXP are identical. Allocate temp. space for EXP. */ + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if( rp == mp ) { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ +// assert( !mp_marker ); + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + } + + MPN_COPY( rp, bp, bsize ); + rsize = bsize; + rsign = bsign; + + { + mpi_size_t i; + mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); + int c; + mpi_limb_t e; + mpi_limb_t carry_limb; + + negative_result = (ep[0] & 1) && base->sign; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MPI_LIMB - 1 - c; + + /* Main loop. + * + * Make the result be pointed to alternately by XP and RP. This + * helps us avoid block copying, which would otherwise be necessary + * with the overlap restrictions of mpihelp_divmod. With 50% probability + * the result after this loop will be in the area originally pointed + * by RP (==RES->d), and with 50% probability in the area originally + * pointed to by XP. + */ + for(;;) { + while( c ) { + mpi_ptr_t tp; + mpi_size_t xsize; + + /*mpihelp_mul_n(xp, rp, rp, rsize);*/ + if( rsize < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( xp, rp, rsize ); + else { + if( !tspace ) { + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + else if( tsize < (2*rsize) ) { + mpi_free_limb_space( tspace ); + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + + } + mpih_sqr_n( xp, rp, rsize, tspace ); + } + + xsize = 2 * rsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + if( (mpi_limb_signed_t)e < 0 ) { + mpihelp_mul( xp, rp, rsize, bp, bsize ); + xsize = rsize + bsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if( i < 0 ) + break; + e = ep[i]; + c = BITS_PER_MPI_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT + * steps. Adjust the result by reducing it with the original MOD. + * + * Also make sure the result is put in RES->d (where it already + * might be, see above). + */ + if( mod_shift_cnt ) { + carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if( carry_limb ) { + rp[rsize] = carry_limb; + rsize++; + } + } + else { + MPN_COPY( res->d, rp, rsize); + rp = res->d; + } + + if( rsize >= msize ) { + mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if( mod_shift_cnt ) + mpihelp_rshift( rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + } + + if( negative_result && rsize ) { + if( mod_shift_cnt ) + mpihelp_rshift( mp, mp, msize, mod_shift_cnt); + mpihelp_sub( rp, mp, msize, rp, rsize); + rsize = msize; + rsign = msign; + MPN_NORMALIZE(rp, rsize); + } + res->nlimbs = rsize; + res->sign = rsign; + + leave: + if( assign_rp ) mpi_assign_limb_space( res, rp, size ); + if( mp_marker ) mpi_free_limb_space( mp_marker ); + if( bp_marker ) mpi_free_limb_space( bp_marker ); + if( ep_marker ) mpi_free_limb_space( ep_marker ); + if( xp_marker ) mpi_free_limb_space( xp_marker ); + if( tspace ) mpi_free_limb_space( tspace ); +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpicoder.c b/security/cryptomark/gnupg/mpi/mpicoder.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpicoder.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,449 @@ +/* mpicoder.c - Coder for the external representation of MPIs + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include + +#include +#include "../../cryptomark_log.h" + +#include "../mpi.h" +#include "mpi-internal.h" +#include "../iobuf.h" +#include "../memory.h" +#include "../util.h" + +#ifdef M_DEBUG + #undef mpi_read +#endif + +#define MAX_EXTERN_MPI_BITS 16384 + +/**************** + * write an mpi to out. + */ +int +mpi_write( IOBUF out, MPI a ) +{ + int rc; + unsigned nbits = mpi_get_nbits(a); + byte *p, *buf; + unsigned n; + + if( nbits > MAX_EXTERN_MPI_BITS ) + log_bug("mpi_encode: mpi too large (%u bits)\n", nbits); + + iobuf_put(out, (nbits >>8) ); + iobuf_put(out, (nbits) ); + + p = buf = mpi_get_buffer( a, &n, NULL ); + rc = iobuf_write( out, p, n ); + m_free(buf); + return rc; +} + + +/**************** + * Read an external representation of an mpi and return the MPI + * The external format is a 16 bit unsigned value stored in network byte order, + * giving the number of bits for the following integer. The integer is stored + * with MSB first (left padded with zeroes to align on a byte boundary). + */ +MPI +#ifdef M_DEBUG +mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info) +#else +mpi_read(IOBUF inp, unsigned *ret_nread, int secure) +#endif +{ + int c, i, j; + unsigned nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + MPI val = MPI_NULL; + + if( (c = iobuf_get(inp)) == -1 ) + goto leave; + nbits = c << 8; + if( (c = iobuf_get(inp)) == -1 ) + goto leave; + nbits |= c; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + #ifdef M_DEBUG + val = secure? mpi_debug_alloc_secure( nlimbs, info ) + : mpi_debug_alloc( nlimbs, info ); + #else + val = secure? mpi_alloc_secure( nlimbs ) + : mpi_alloc( nlimbs ); + #endif + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + val->nbits = nbits; + j= val->nlimbs = nlimbs; + val->sign = 0; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + a <<= 8; + a |= iobuf_get(inp) & 0xff; nread++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + if( nread > *ret_nread ) + log_bug("mpi crosses packet border"); + else + *ret_nread = nread; + return val; +} + + +//MPI +//mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure) +//{ +// int i, j; +// unsigned nbits, nbytes, nlimbs, nread=0; +// mpi_limb_t a; +// MPI val = MPI_NULL; +// +// if( *ret_nread < 2 ) +// goto leave; +// nbits = buffer[0] << 8 | buffer[1]; +// if( nbits > MAX_EXTERN_MPI_BITS ) { +// log_error("mpi too large (%u bits)\n", nbits); +// goto leave; +// } +// buffer += 2; +// nread = 2; +// +// nbytes = (nbits+7) / 8; +// nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; +// val = secure? mpi_alloc_secure( nlimbs ) +// : mpi_alloc( nlimbs ); +// i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; +// i %= BYTES_PER_MPI_LIMB; +// val->nbits = nbits; +// j= val->nlimbs = nlimbs; +// val->sign = 0; +// for( ; j > 0; j-- ) { +// a = 0; +// for(; i < BYTES_PER_MPI_LIMB; i++ ) { +// if( ++nread > *ret_nread ) +// log_bug("mpi larger than buffer"); +// a <<= 8; +// a |= *buffer++; +// } +// i = 0; +// val->d[j-1] = a; +// } +// +// leave: +// *ret_nread = nread; +// return val; +//} +// + +///**************** +// * Make an mpi from a character string. +// */ +//int +//mpi_fromstr(MPI val, const char *str) +//{ +// int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2; +// unsigned nbits, nbytes, nlimbs; +// mpi_limb_t a; +// +// if( *str == '-' ) { +// sign = 1; +// str++; +// } +// if( *str == '0' && str[1] == 'x' ) +// hexmode = 1; +// else +// return 1; /* other bases are not yet supported */ +// str += 2; +// +// nbits = strlen(str)*4; +// if( nbits % 8 ) +// prepend_zero = 1; +// nbytes = (nbits+7) / 8; +// nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; +// if( val->alloced < nlimbs ) +// mpi_resize(val, nlimbs ); +// i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; +// i %= BYTES_PER_MPI_LIMB; +// j= val->nlimbs = nlimbs; +// val->sign = sign; +// for( ; j > 0; j-- ) { +// a = 0; +// for(; i < BYTES_PER_MPI_LIMB; i++ ) { +// if( prepend_zero ) { +// c1 = '0'; +// prepend_zero = 0; +// } +// else +// c1 = *str++; +//// assert(c1); +// c2 = *str++; +//// assert(c2); +// if( c1 >= '0' && c1 <= '9' ) +// c = c1 - '0'; +// else if( c1 >= 'a' && c1 <= 'f' ) +// c = c1 - 'a' + 10; +// else if( c1 >= 'A' && c1 <= 'F' ) +// c = c1 - 'A' + 10; +// else { +// mpi_clear(val); +// return 1; +// } +// c <<= 4; +// if( c2 >= '0' && c2 <= '9' ) +// c |= c2 - '0'; +// else if( c2 >= 'a' && c2 <= 'f' ) +// c |= c2 - 'a' + 10; +// else if( c2 >= 'A' && c2 <= 'F' ) +// c |= c2 - 'A' + 10; +// else { +// mpi_clear(val); +// return 1; +// } +// a <<= 8; +// a |= c; +// } +// i = 0; +// val->d[j-1] = a; +// } +// +// return 0; +//} +// +// +///**************** +// * print an MPI to the given stream and return the number of characters +// * printed. +// */ +//int +//mpi_print( FILE *fp, MPI a, int mode ) +//{ +// int i, n=0; +// +// if( a == MPI_NULL ) +// return fprintf(fp, "[MPI_NULL]"); +// if( !mode ) { +// unsigned n1, n2; +// n1 = mpi_get_nbits(a); +// n2 = mpi_get_nbit_info(a); +// if( n2 && n2 != n1 ) +// n += fprintf(fp, "[%u bits (%u)]", n1, n2 ); +// else +// n += fprintf(fp, "[%u bits]", n1); +// } +// else { +// if( a->sign ) +// putc('-', fp); +// #if BYTES_PER_MPI_LIMB == 2 +// #define X "4" +// #elif BYTES_PER_MPI_LIMB == 4 +// #define X "8" +// #elif BYTES_PER_MPI_LIMB == 8 +// #define X "16" +// #else +// #error please define the format here +// #endif +// for(i=a->nlimbs; i > 0 ; i-- ) { +// n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); +// #undef X +// } +// if( !a->nlimbs ) +// putc('0', fp ); +// } +// return n; +//} +// +// +//void +//g10_log_mpidump( const char *text, MPI a ) +//{ +// FILE *fp = log_stream(); +// +// g10_log_print_prefix(text); +// mpi_print(fp, a, 1 ); +// fputc('\n', fp); +//} +// +/**************** + * Special function to get the low 8 bytes from an mpi. + * This can be used as a keyid; KEYID is an 2 element array. + * Return the low 4 bytes. + */ +u32 +mpi_get_keyid( MPI a, u32 *keyid ) +{ +#if BYTES_PER_MPI_LIMB == 4 + if( keyid ) { + keyid[0] = a->nlimbs >= 2? a->d[1] : 0; + keyid[1] = a->nlimbs >= 1? a->d[0] : 0; + } + return a->nlimbs >= 1? a->d[0] : 0; +#elif BYTES_PER_MPI_LIMB == 8 + if( keyid ) { + keyid[0] = a->nlimbs? (u32)(a->d[0] >> 32) : 0; + keyid[1] = a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; + } + return a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; +#else + #error Make this function work with other LIMB sizes +#endif +} + + +/**************** + * Return an m_alloced buffer with the MPI (msb first). + * NBYTES receives the length of this buffer. Caller must free the + * return string (This function does return a 0 byte buffer with NBYTES + * set to zero if the value of A is zero. If sign is not NULL, it will + * be set to the sign of the A. + */ +static byte * +do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure ) +{ + byte *p, *buffer; + mpi_limb_t alimb; + int i; + + if( sign ) + *sign = a->sign; + *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB; + p = buffer = force_secure || mpi_is_secure(a) ? m_alloc_secure( *nbytes) + : m_alloc( *nbytes ); + + for(i=a->nlimbs-1; i >= 0; i-- ) { + alimb = a->d[i]; + #if BYTES_PER_MPI_LIMB == 4 + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; + #elif BYTES_PER_MPI_LIMB == 8 + *p++ = alimb >> 56; + *p++ = alimb >> 48; + *p++ = alimb >> 40; + *p++ = alimb >> 32; + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; + #else + #error please implement for this limb size. + #endif + } + + /* this is sub-optimal but we need to do the shift oepration because + * the caller has to free the returned buffer */ + for(p=buffer; !*p && *nbytes; p++, --*nbytes ) + ; + if( p != buffer ) + memmove(buffer,p, *nbytes); + return buffer; +} + + +byte * +mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ) +{ + return do_get_buffer( a, nbytes, sign, 0 ); +} + +//byte * +//mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ) +//{ +// return do_get_buffer( a, nbytes, sign, 1 ); +//} + +/**************** + * Use BUFFER to update MPI. + */ +void +mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ) +{ + const byte *p; + mpi_limb_t alimb; + int nlimbs; + int i; + + nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; + RESIZE_IF_NEEDED(a, nlimbs); + a->sign = sign; + + for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) { + #if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + alimb |= *p-- << 8 ; + alimb |= *p-- << 16 ; + alimb |= *p-- << 24 ; + #elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; + alimb |= (mpi_limb_t)*p-- << 32 ; + alimb |= (mpi_limb_t)*p-- << 40 ; + alimb |= (mpi_limb_t)*p-- << 48 ; + alimb |= (mpi_limb_t)*p-- << 56 ; + #else + #error please implement for this limb size. + #endif + a->d[i++] = alimb; + } + if( p >= buffer ) { + #if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + if( p >= buffer ) alimb |= *p-- << 8 ; + if( p >= buffer ) alimb |= *p-- << 16 ; + if( p >= buffer ) alimb |= *p-- << 24 ; + #elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ; + #else + #error please implement for this limb size. + #endif + a->d[i++] = alimb; + } + a->nlimbs = i; +// assert( i == nlimbs ); +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-add1.S b/security/cryptomark/gnupg/mpi/mpih-add1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-add1.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,134 @@ +/* i80586 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + adcl %ebx,%eax + movl 4(%ebp),%ebx + adcl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + adcl %ebx,%eax + movl 12(%ebp),%ebx + adcl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + adcl %ebx,%eax + movl 20(%ebp),%ebx + adcl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %ebx,%eax + movl 28(%ebp),%ebx + adcl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + adcl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + adcl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-cmp.c b/security/cryptomark/gnupg/mpi/mpih-cmp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-cmp.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,63 @@ +/* mpihelp-sub.c - MPI helper functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +//#include +//#include +//#include + +#include "mpi-internal.h" + +/**************** + * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + * There are no restrictions on the relative sizes of + * the two arguments. + * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. + */ +int +mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t op1_word, op2_word; + + for( i = size - 1; i >= 0 ; i--) { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if( op1_word != op2_word ) + goto diff; + } + return 0; + + diff: + /* This can *not* be simplified to + * op2_word - op2_word + * since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-div.c b/security/cryptomark/gnupg/mpi/mpih-div.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-div.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,537 @@ +/* mpihelp-div.c - MPI helper functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" + +#ifndef UMUL_TIME + #define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME + #define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + * here (not udiv_qrnnd). + */ + +mpi_limb_t +mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV(dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + i--; + + for( ; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if( UDIV_NEEDS_NORMALIZATION ) { + int normalization_steps; + + count_leading_zeros(normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for(i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + i--; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + * the NSIZE-DSIZE least significant quotient limbs at QP + * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + * non-zero, generate that many fraction bits and append them after the + * other quotient limbs. + * Return the most significant limb of the quotient, this is always 0 or 1. + * + * Preconditions: + * 0. NSIZE >= DSIZE. + * 1. The most significant bit of the divisor must be set. + * 2. QP must either not overlap with the input operands at all, or + * QP + DSIZE >= NP must hold true. (This means that it's + * possible to put the quotient in the high part of NUM, right after the + * remainder in NUM. + * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. + */ + +mpi_limb_t +mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize) +{ + mpi_limb_t most_significant_q_limb = 0; + + switch(dsize) { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + return 1 / dsize; + + case 1: + { + mpi_size_t i; + mpi_limb_t n1; + mpi_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if( n1 >= d ) { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for( i = nsize - 2; i >= 0; i--) + udiv_qrnnd( qp[i], n1, n1, np[i], d ); + qp -= qextra_limbs; + + for( i = qextra_limbs - 1; i >= 0; i-- ) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mpi_size_t i; + mpi_limb_t n1, n0, n2; + mpi_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { + mpi_limb_t q; + mpi_limb_t r; + + if( i >= qextra_limbs ) + np--; + else + np[0] = 0; + + if( n1 == d1 ) { + /* Q should be either 111..111 or 111..110. Need special + * treatment of this rare case as normal division would + * give overflow. */ + q = ~(mpi_limb_t)0; + + r = n0 + d1; + if( r < d1 ) { /* Carry in the addition? */ + add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0?1:0); + n0 = -d0; + } + else { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if( n1 > r || (n1 == r && n0 > n2) ) { + /* The estimated Q was too large. */ + q--; + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if( r >= d1 ) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mpi_size_t i; + mpi_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if( n0 >= dX ) { + if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) { + mpihelp_sub_n(np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { + mpi_limb_t q; + mpi_limb_t n1, n2; + mpi_limb_t cy_limb; + + if( i >= qextra_limbs ) { + np--; + n2 = np[dsize]; + } + else { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize - 1); + np[0] = 0; + } + + if( n0 == dX ) { + /* This might over-estimate q, but it's probably not worth + * the extra code here to find out. */ + q = ~(mpi_limb_t)0; + } + else { + mpi_limb_t r; + + udiv_qrnnd(q, r, n0, np[dsize - 1], dX); + umul_ppmm(n1, n0, d1, q); + + while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { + q--; + r += dX; + if( r < dX ) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + * after the calculation of q. Taking advantage of that, we + * could make this loop make two iterations less. */ + cy_limb = mpihelp_submul_1(np, dp, dsize, q); + + if( n2 != cy_limb ) { + mpihelp_add_n(np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} + + +/**************** + * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + * Return the single-limb remainder. + * There are no constraints on the value of the divisor. + * + * QUOT_PTR and DIVIDEND_PTR might point to the same limb. + */ + +mpi_limb_t +mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV( quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t) 0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + quot_ptr[i--] = 0; + + for( ; i >= 0; i-- ) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if(UDIV_NEEDS_NORMALIZATION) { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + quot_ptr[i--] = 0; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); + } + return r; + } +} + + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-lshift.S b/security/cryptomark/gnupg/mpi/mpih-lshift.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-lshift.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,230 @@ +/* i80586 lshift + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_lshift) +C_SYMBOL_NAME(mpihelp_lshift:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%esi),%eax + cmpl %edi,%eax + jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ + leal (%esi,%ebp,4),%eax + cmpl %eax,%edi + jnc Lspecial /* jump if res_ptr >= s_ptr + size */ + +Lnormal: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + xorl %eax,%eax + shldl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + shldl %cl,%ebx,%edx + shldl %cl,%eax,%ebx + movl %edx,-8(%edi) + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + shldl %cl,%edx,%eax + shldl %cl,%ebx,%edx + movl %eax,-16(%edi) + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,-24(%edi) + movl %eax,-28(%edi) + + subl $32,%esi + subl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shldl %cl,%eax,%edx + movl %edx,(%edi) + movl %eax,%edx + subl $4,%esi + subl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shll %cl,%edx /* compute least significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + movl (%esi),%edx + addl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + addl %edx,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + adcl %eax,%eax + movl %ebx,(%edi) + adcl %edx,%edx + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + adcl %ebx,%ebx + movl %edx,8(%edi) + adcl %eax,%eax + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + adcl %edx,%edx + movl %eax,16(%edi) + adcl %ebx,%ebx + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %eax,%eax + movl %ebx,24(%edi) + adcl %edx,%edx + movl %eax,28(%edi) + + leal 32(%esi),%esi /* use leal not to clobber carry */ + leal 32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + adcl %edx,%edx + movl %ebx,(%edi) + + leal 4(%esi),%esi /* use leal not to clobber carry */ + leal 4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-mul.c b/security/cryptomark/gnupg/mpi/mpih-mul.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-mul.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,471 @@ +/* mpihelp-mul.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +//#include +//#include +//#include +#include "mpi-internal.h" +#include "longlong.h" + + + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + mpih_sqr_n_basecase (prodp, up, size); \ + else \ + mpih_sqr_n (prodp, up, size, tspace); \ + } while (0); + + + + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + * always stored. Return the most significant limb. + * + * Argument constraints: + * 1. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + * + * + * Handle simple cases with traditional multiplication. + * + * This is the most critical code of multiplication. All multiplies rely + * on this, both small and huge. Small ones arrive here immediately. Huge + * ones arrive here as this is the base case for Karatsuba's recursive + * algorithm below. + */ + +static mpi_limb_t +mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, + mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t cy; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO( prodp, size ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < size; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy; + prodp++; + } + + return cy; +} + + +static void +mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size, mpi_ptr_t tspace ) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] ); + prodp[esize + size] = cy_limb; + } + else { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + * + * Split U in two pieces, U1 and U0, such that + * U = U0 + U1*(B**n), + * and V in V1 and V0, such that + * V = V0 + V1*(B**n). + * + * UV is then computed recursively using the identity + * + * 2n n n n + * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + * 1 1 1 0 0 1 0 0 + * + * Where B = 2**BITS_PER_MP_LIMB. + */ + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + int negflg; + + /* Product H. ________________ ________________ + * |_____U1 x V1____||____U0 x V0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(V0-V1)_| + */ + if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) { + mpihelp_sub_n(prodp, up + hsize, up, hsize); + negflg = 0; + } + else { + mpihelp_sub_n(prodp, up, up + hsize, hsize); + negflg = 1; + } + if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) { + mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else { + mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); + + /* Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n( prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number) */ + if(negflg) + cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size); + else + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x V0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); + + /* Add/copy Product L (twice) */ + + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1(prodp + size, prodp + size, size, 1); + } +} + + +void +mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t cy_limb; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO(prodp, size); + cy_limb = 0; + } + else + cy_limb = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i=1; i < size; i++) { + v_limb = up[i]; + if( v_limb <= 1 ) { + cy_limb = 0; + if( v_limb == 1 ) + cy_limb = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + + +void +mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] ); + + prodp[esize + size] = cy_limb; + } + else { + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + + /* Product H. ________________ ________________ + * |_____U1 x U1____||____U0 x U0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(U0-U1)_| + */ + if( mpihelp_cmp( up + hsize, up, hsize) >= 0 ) + mpihelp_sub_n( prodp, up + hsize, up, hsize); + else + mpihelp_sub_n (prodp, up, up + hsize, hsize); + + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); + + /* Add/copy product H */ + MPN_COPY(prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n(prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number). */ + cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x U0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /* Add/copy Product L (twice). */ + cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, + hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1 (prodp + size, prodp + size, size, 1); + } +} + + +/* This should be made into an inline function in gmp.h. */ +void +mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + int secure; + + if( up == vp ) { + if( size < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( prodp, up, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mpih_sqr_n( prodp, up, size, tspace ); + mpi_free_limb_space( tspace ); + } + } + else { + if( size < KARATSUBA_THRESHOLD ) + mul_n_basecase( prodp, up, vp, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ) || m_is_secure( vp ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mul_n (prodp, up, vp, size, tspace); + mpi_free_limb_space( tspace ); + } + } +} + + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + * and v (pointed to by VP, with VSIZE limbs), and store the result at + * PRODP. USIZE + VSIZE limbs are always stored, but if the input + * operands are normalized. Return the most significant limb of the + * result. + * + * NOTE: The space pointed to by PRODP is overwritten before finished + * with U and V, so overlap is an error. + * + * Argument constraints: + * 1. USIZE >= VSIZE. + * 2. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + */ + +mpi_limb_t +mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize) +{ + mpi_ptr_t prod_endp = prodp + usize + vsize - 1; + mpi_limb_t cy; + mpi_ptr_t tspace; + + if( vsize < KARATSUBA_THRESHOLD ) { + mpi_size_t i; + mpi_limb_t v_limb; + + if( !vsize ) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, usize ); + else + MPN_ZERO( prodp, usize ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, usize, v_limb ); + + prodp[usize] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < vsize; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, usize); + } + else + cy = mpihelp_addmul_1(prodp, up, usize, v_limb); + + prodp[usize] = cy; + prodp++; + } + + return cy; + } + + tspace = mpi_alloc_limb_space( 2 * vsize, + m_is_secure( up ) || m_is_secure( vp ) ); + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + mpi_ptr_t tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up ) + || m_is_secure( vp ) ); + do { + MPN_MUL_N_RECURSE( tp, up, vp, vsize, tspace ); + cy = mpihelp_add_n( prodp, prodp, tp, vsize ); + mpihelp_add_1( prodp + vsize, tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + mpi_free_limb_space( tp ); + } + + if( usize ) { + mpihelp_mul( tspace, vp, vsize, up, usize ); + cy = mpihelp_add_n( prodp, prodp, tspace, vsize); + mpihelp_add_1( prodp + vsize, tspace + vsize, usize, cy ); + } + + mpi_free_limb_space( tspace ); + return *prod_endp; +} + + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-mul1.S b/security/cryptomark/gnupg/mpi/mpih-mul1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-mul1.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,89 @@ +/* i80586 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-mul2.S b/security/cryptomark/gnupg/mpi/mpih-mul2.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-mul2.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,94 @@ +/* i80586 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-mul3.S b/security/cryptomark/gnupg/mpi/mpih-mul3.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-mul3.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,94 @@ +/* i80586 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-rshift.S b/security/cryptomark/gnupg/mpi/mpih-rshift.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-rshift.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,229 @@ +/* i80586 rshift + * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_rshift) +C_SYMBOL_NAME(mpihelp_rshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Rnormal + leal 4(%edi),%eax + cmpl %esi,%eax + jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */ + leal (%edi,%ebp,4),%eax + cmpl %eax,%esi + jnc Rspecial /* jump if s_ptr >= res_ptr + size */ + +Rnormal: + movl (%esi),%edx + addl $4,%esi + xorl %eax,%eax + shrdl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Rend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Roop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + shrdl %cl,%ebx,%edx + shrdl %cl,%eax,%ebx + movl %edx,8(%edi) + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + shrdl %cl,%edx,%eax + shrdl %cl,%ebx,%edx + movl %eax,16(%edi) + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,24(%edi) + movl %eax,28(%edi) + + addl $32,%esi + addl $32,%edi + decl %ebp + jnz Roop + +Rend: popl %ebp + andl $7,%ebp + jz Rend2 +Roop2: movl (%esi),%eax + shrdl %cl,%eax,%edx /* compute result limb */ + movl %edx,(%edi) + movl %eax,%edx + addl $4,%esi + addl $4,%edi + decl %ebp + jnz Roop2 + +Rend2: shrl %cl,%edx /* compute most significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Rspecial: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + shrl $1,%edx + incl %ebp + decl %ebp + jz RLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +RLoop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + rcrl $1,%eax + movl %ebx,(%edi) + rcrl $1,%edx + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + rcrl $1,%ebx + movl %edx,-8(%edi) + rcrl $1,%eax + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + rcrl $1,%edx + movl %eax,-16(%edi) + rcrl $1,%ebx + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + rcrl $1,%eax + movl %ebx,-24(%edi) + rcrl $1,%edx + movl %eax,-28(%edi) + + leal -32(%esi),%esi /* use leal not to clobber carry */ + leal -32(%edi),%edi + decl %ebp + jnz RLoop + +RLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz RLend2 + addl %eax,%eax /* restore carry from eax */ +RLoop2: movl %edx,%ebx + movl (%esi),%edx + rcrl $1,%edx + movl %ebx,(%edi) + + leal -4(%esi),%esi /* use leal not to clobber carry */ + leal -4(%edi),%edi + decl %ebp + jnz RLoop2 + + jmp RL1 +RLend2: addl %eax,%eax /* restore carry from eax */ +RL1: movl %edx,(%edi) /* store last limb */ + + movl $0,%eax + rcrl $1,%eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff -Nru a/security/cryptomark/gnupg/mpi/mpih-sub1.S b/security/cryptomark/gnupg/mpi/mpih-sub1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpih-sub1.S Mon Feb 2 14:26:23 2004 @@ -0,0 +1,143 @@ +/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_sub_n) +C_SYMBOL_NAME(mpihelp_sub_n:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + sbbl %ebx,%eax + movl 4(%ebp),%ebx + sbbl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + sbbl %ebx,%eax + movl 12(%ebp),%ebx + sbbl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + sbbl %ebx,%eax + movl 20(%ebp),%ebx + sbbl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + sbbl %ebx,%eax + movl 28(%ebp),%ebx + sbbl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + sbbl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + sbbl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff -Nru a/security/cryptomark/gnupg/mpi/mpiutil.c b/security/cryptomark/gnupg/mpi/mpiutil.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/mpiutil.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,464 @@ +/* mpiutil.ac - Utility functions for MPI + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include + +#include "../mpi.h" +#include "mpi-internal.h" +#include "../memory.h" +#include "../util.h" + + +#ifdef M_DEBUG + #undef mpi_alloc + #undef mpi_alloc_secure + #undef mpi_free +#endif + +/**************** + * Note: It was a bad idea to use the number of limbs to allocate + * because on a alpha the limbs are large but we normally need + * integers of n bits - So we should chnage this to bits (or bytes). + * + * But mpi_alloc is used in a lot of places :-) + */ +MPI +#ifdef M_DEBUG +mpi_debug_alloc( unsigned nlimbs, const char *info ) +#else +mpi_alloc( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); + #ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL; + #else + a = m_alloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; + #endif + a->alloced = nlimbs; + a->nlimbs = 0; + a->sign = 0; + a->flags = 0; + a->nbits = 0; + return a; +} + +void +mpi_m_check( MPI a ) +{ + m_check(a); + m_check(a->d); +} + +MPI +#ifdef M_DEBUG +mpi_debug_alloc_secure( unsigned nlimbs, const char *info ) +#else +mpi_alloc_secure( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); + #ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL; + #else + a = m_alloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; + #endif + a->alloced = nlimbs; + a->flags = 1; + a->nlimbs = 0; + a->sign = 0; + a->nbits = 0; + return a; +} + + +#if 0 +static void *unused_limbs_5; +static void *unused_limbs_32; +static void *unused_limbs_64; +#endif + +mpi_ptr_t +#ifdef M_DEBUG +mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info ) +#else +mpi_alloc_limb_space( unsigned nlimbs, int secure ) +#endif +{ + size_t len = nlimbs * sizeof(mpi_limb_t); + mpi_ptr_t p; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 ); + #if 0 + if( !secure ) { + if( nlimbs == 5 && unused_limbs_5 ) { /* DSA 160 bits */ + p = unused_limbs_5; + unused_limbs_5 = *p; + return p; + } + else if( nlimbs == 32 && unused_limbs_32 ) { /* DSA 1024 bits */ + p = unused_limbs_32; + unused_limbs_32 = *p; + return p; + } + else if( nlimbs == 64 && unused_limbs_64 ) { /* DSA 2*1024 bits */ + p = unused_limbs_64; + unused_limbs_64 = *p; + return p; + } + } + #endif + + #ifdef M_DEBUG + p = secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info ); + #else + p = secure? m_alloc_secure( len ):m_alloc( len ); + #endif + + return p; +} + +void +#ifdef M_DEBUG +mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ) +#else +mpi_free_limb_space( mpi_ptr_t a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 ); + + #if 0 + if( !m_is_secure(a) ) { + size_t nlimbs = m_size(a) / 4 ; + void *p = a; + + if( nlimbs == 5 ) { /* DSA 160 bits */ + *a = unused_limbs_5; + unused_limbs_5 = a; + return; + } + else if( nlimbs == 32 ) { /* DSA 1024 bits */ + *a = unused_limbs_32; + unused_limbs_32 = a; + return; + } + else if( nlimbs == 64 ) { /* DSA 2*1024 bits */ + *a = unused_limbs_64; + unused_limbs_64 = a; + return; + } + } + #endif + + + m_free(a); +} + + +void +mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ) +{ + mpi_free_limb_space(a->d); + a->d = ap; + a->alloced = nlimbs; +} + + + +/**************** + * Resize the array of A to NLIMBS. the additional space is cleared + * (set to 0) [done by m_realloc()] + */ +void +#ifdef M_DEBUG +mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ) +#else +mpi_resize( MPI a, unsigned nlimbs ) +#endif +{ + if( nlimbs <= a->alloced ) + return; /* no need to do it */ + /* Note: a->secure is not used - instead the realloc functions + * take care of it. Maybe we should drop a->secure completely + * and rely on a mpi_is_secure function, which would be + * a wrapper around m_is_secure + */ + #ifdef M_DEBUG + if( a->d ) + a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info ); + else + a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info ); + #else + if( a->d ) + a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) ); + else + a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) ); + #endif + a->alloced = nlimbs; +} + +void +mpi_clear( MPI a ) +{ + a->nlimbs = 0; + a->nbits = 0; + a->flags = 0; +} + + +void +#ifdef M_DEBUG +mpi_debug_free( MPI a, const char *info ) +#else +mpi_free( MPI a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free\n" ); + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, info); + #else + mpi_free_limb_space(a->d); + #endif + } + if( a->flags & ~7 ) + log_bug("invalid flag value in mpi\n"); + m_free(a); +} + + +void +mpi_set_secure( MPI a ) +{ + mpi_ptr_t ap, bp; + + if( (a->flags & 1) ) + return; + a->flags |= 1; + ap = a->d; + if( !a->nlimbs ) { +// assert(!ap); + return; + } + #ifdef M_DEBUG + bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" ); + #else + bp = mpi_alloc_limb_space( a->nlimbs, 1 ); + #endif + MPN_COPY( bp, ap, a->nlimbs ); + a->d = bp; + #ifdef M_DEBUG + mpi_debug_free_limb_space(ap, "set_secure"); + #else + mpi_free_limb_space(ap); + #endif +} + + +MPI +mpi_set_opaque( MPI a, void *p, int len ) +{ + if( !a ) { + #ifdef M_DEBUG + a = mpi_debug_alloc(0,"alloc_opaque"); + #else + a = mpi_alloc(0); + #endif + } + + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, "alloc_opaque"); + #else + mpi_free_limb_space(a->d); + #endif + } + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->nbits = len; + a->flags = 4; + return a; +} + + +void * +mpi_get_opaque( MPI a, int *len ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( len ) + *len = a->nbits; + return a->d; +} + + +/**************** + * Note: This copy function should not interpret the MPI + * but copy it transparently. + */ +MPI +#ifdef M_DEBUG +mpi_debug_copy( MPI a, const char *info ) +#else +mpi_copy( MPI a ) +#endif +{ + int i; + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) + : m_alloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { + #ifdef M_DEBUG + b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) + : mpi_debug_alloc( a->nlimbs, info ); + #else + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + #endif + b->nlimbs = a->nlimbs; + b->sign = a->sign; + b->flags = a->flags; + b->nbits = a->nbits; + for(i=0; i < b->nlimbs; i++ ) + b->d[i] = a->d[i]; + } + else + b = NULL; + return b; +} + + +/**************** + * This function allocates an MPI which is optimized to hold + * a value as large as the one given in the arhgument and allocates it + * with the same flags as A. + */ +MPI +mpi_alloc_like( MPI a ) +{ + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) + : m_alloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + b->nlimbs = 0; + b->sign = 0; + b->flags = a->flags; + b->nbits = 0; + } + else + b = NULL; + return b; +} + + +void +mpi_set( MPI w, MPI u) +{ + mpi_ptr_t wp, up; + mpi_size_t usize = u->nlimbs; + int usign = u->sign; + + RESIZE_IF_NEEDED(w, usize); + wp = w->d; + up = u->d; + MPN_COPY( wp, up, usize ); + w->nlimbs = usize; + w->nbits = u->nbits; + w->flags = u->flags; + w->sign = usign; +} + + +void +mpi_set_ui( MPI w, unsigned long u) +{ + RESIZE_IF_NEEDED(w, 1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + w->nbits = 0; + w->flags = 0; +} + + +MPI +mpi_alloc_set_ui( unsigned long u) +{ + #ifdef M_DEBUG + MPI w = mpi_debug_alloc(1,"alloc_set_ui"); + #else + MPI w = mpi_alloc(1); + #endif + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + return w; +} + + +void +mpi_swap( MPI a, MPI b) +{ + struct gcry_mpi tmp; + + tmp = *a; *a = *b; *b = tmp; +} + diff -Nru a/security/cryptomark/gnupg/mpi/sysdep.h b/security/cryptomark/gnupg/mpi/sysdep.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi/sysdep.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,2 @@ +/* created by config.links - do not edit */ +#define C_SYMBOL_NAME(name) name diff -Nru a/security/cryptomark/gnupg/mpi.h b/security/cryptomark/gnupg/mpi.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/mpi.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,178 @@ +/* mpi.h - Multi Precision Integers + * Copyright (C) 1994, 1996, 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_H +#define G10_MPI_H + +//#include +#include "iobuf.h" +#include "types.h" +#include "memory.h" + + +#define DBG_MPI mpi_debug_mode +int mpi_debug_mode; + +#define BITS_PER_MPI_LIMB (8*SIZEOF_UNSIGNED_LONG) +#define BYTES_PER_MPI_LIMB SIZEOF_UNSIGNED_LONG +typedef unsigned long int mpi_limb_t; +typedef signed long int mpi_limb_signed_t; + +struct gcry_mpi { + int alloced; /* array size (# of allocated limbs) */ + int nlimbs; /* number of valid limbs */ + int nbits; /* the real number of valid bits (info only) */ + int sign; /* indicates a negative number */ + unsigned flags; /* bit 0: array must be allocated in secure memory space */ + /* bit 1: the mpi is encrypted */ + /* bit 2: the limb is a pointer to some m_alloced data */ + mpi_limb_t *d; /* array with the limbs */ +}; + +typedef struct gcry_mpi *MPI; + +#define MPI_NULL NULL + +#define mpi_get_nlimbs(a) ((a)->nlimbs) +#define mpi_get_nbit_info(a) ((a)->nbits) +#define mpi_set_nbit_info(a,b) ((a)->nbits = (b)) +#define mpi_is_neg(a) ((a)->sign) + +/*-- mpiutil.c --*/ + +#ifdef M_DEBUG + #define mpi_alloc(n) mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) + #define mpi_alloc_secure(n) mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) + #define mpi_free(a) mpi_debug_free((a), M_DBGINFO(__LINE__) ) + #define mpi_resize(a,b) mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) + #define mpi_copy(a) mpi_debug_copy((a), M_DBGINFO(__LINE__) ) + MPI mpi_debug_alloc( unsigned nlimbs, const char *info ); + MPI mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); + void mpi_debug_free( MPI a, const char *info ); + void mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ); + MPI mpi_debug_copy( MPI a, const char *info ); +#else + MPI mpi_alloc( unsigned nlimbs ); + MPI mpi_alloc_secure( unsigned nlimbs ); + void mpi_free( MPI a ); + void mpi_resize( MPI a, unsigned nlimbs ); + MPI mpi_copy( MPI a ); +#endif +#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) +MPI mpi_set_opaque( MPI a, void *p, int len ); +void *mpi_get_opaque( MPI a, int *len ); +#define mpi_is_protected(a) ((a) && ((a)->flags&2)) +#define mpi_set_protect_flag(a) ((a)->flags |= 2) +#define mpi_clear_protect_flag(a) ((a)->flags &= ~2) +#define mpi_is_secure(a) ((a) && ((a)->flags&1)) +void mpi_set_secure( MPI a ); +void mpi_clear( MPI a ); +MPI mpi_alloc_like( MPI a ); +void mpi_set( MPI w, MPI u); +void mpi_set_ui( MPI w, ulong u); +MPI mpi_alloc_set_ui( unsigned long u); +void mpi_m_check( MPI a ); +void mpi_swap( MPI a, MPI b); + +/*-- mpicoder.c --*/ +int mpi_write( IOBUF out, MPI a ); +#ifdef M_DEBUG + #define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) ) + MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info); +#else + MPI mpi_read(IOBUF inp, unsigned *nread, int secure); +#endif +MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure); +int mpi_fromstr(MPI val, const char *str); +//int mpi_print( FILE *fp, MPI a, int mode ); +void g10_log_mpidump( const char *text, MPI a ); +u32 mpi_get_keyid( MPI a, u32 *keyid ); +byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ); +byte *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ); +void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ); + +#define log_mpidump g10_log_mpidump + +/*-- mpi-add.c --*/ +void mpi_add_ui(MPI w, MPI u, ulong v ); +void mpi_add(MPI w, MPI u, MPI v); +void mpi_addm(MPI w, MPI u, MPI v, MPI m); +void mpi_sub_ui(MPI w, MPI u, ulong v ); +void mpi_sub( MPI w, MPI u, MPI v); +void mpi_subm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-mul.c --*/ +void mpi_mul_ui(MPI w, MPI u, ulong v ); +void mpi_mul_2exp( MPI w, MPI u, ulong cnt); +void mpi_mul( MPI w, MPI u, MPI v); +void mpi_mulm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-div.c --*/ +ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ); +void mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ); +void mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ); +void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ); +void mpi_tdiv_r( MPI rem, MPI num, MPI den); +void mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den); +void mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ); +int mpi_divisible_ui(MPI dividend, ulong divisor ); + +/*-- mpi-gcd.c --*/ +int mpi_gcd( MPI g, MPI a, MPI b ); + +/*-- mpi-pow.c --*/ +void mpi_pow( MPI w, MPI u, MPI v); +void mpi_powm( MPI res, MPI base, MPI exp, MPI mod); + +/*-- mpi-mpow.c --*/ +void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); + +/*-- mpi-cmp.c --*/ +int mpi_cmp_ui( MPI u, ulong v ); +int mpi_cmp( MPI u, MPI v ); + +/*-- mpi-scan.c --*/ +int mpi_getbyte( MPI a, unsigned idx ); +void mpi_putbyte( MPI a, unsigned idx, int value ); +unsigned mpi_trailing_zeros( MPI a ); + +/*-- mpi-bit.c --*/ +void mpi_normalize( MPI a ); +unsigned mpi_get_nbits( MPI a ); +int mpi_test_bit( MPI a, unsigned n ); +void mpi_set_bit( MPI a, unsigned n ); +void mpi_set_highbit( MPI a, unsigned n ); +void mpi_clear_highbit( MPI a, unsigned n ); +void mpi_clear_bit( MPI a, unsigned n ); +void mpi_rshift( MPI x, MPI a, unsigned n ); + +/*-- mpi-inv.c --*/ +void mpi_invm( MPI x, MPI u, MPI v ); + + +#endif /*G10_MPI_H*/ diff -Nru a/security/cryptomark/gnupg/options.h b/security/cryptomark/gnupg/options.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/options.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,112 @@ +/* options.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_OPTIONS_H +#define G10_OPTIONS_H + +#include "types.h" + +#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ + + +struct { + int verbose; + int quiet; + unsigned debug; + int armor; + int compress; + char *outfile; + int dry_run; + int textmode; + int batch; /* run in batch mode */ + int answer_yes; /* answer yes on most questions */ + int answer_no; /* answer no on most questions */ + int check_sigs; /* check key signatures */ + int with_colons; + int with_key_data; + int fingerprint; /* list fingerprints */ + int list_sigs; /* list signatures */ + int no_armor; + int list_packets; /* list-packets mode */ + int def_cipher_algo; + int force_v3_sigs; + int force_mdc; + int def_digest_algo; + int def_compress_algo; + const char *def_secret_key; + char *def_recipient; + int def_recipient_self; + int no_comment; + int no_version; + int marginals_needed; + int completes_needed; + int max_cert_depth; + const char *homedir; + int skip_verify; + int compress_keys; + int compress_sigs; + int always_trust; + int rfc1991; + unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ + int shm_coprocess; + const char *set_filename; + const char *comment_string; + int throw_keyid; + int s2k_mode; + int s2k_digest_algo; + int s2k_cipher_algo; + int not_dash_escaped; + int escape_from; + int lock_once; + const char *keyserver_name; + int no_encrypt_to; + int interactive; + STRLIST notation_data; + const char *set_policy_url; + int use_embedded_filename; + int allow_non_selfsigned_uid; + int no_literal; + ulong set_filesize; + int honor_http_proxy; + int fast_list_mode; +} opt; + + +#define EMUBUG_GPGCHKSUM 1 +#define EMUBUG_3DESS2K 2 + +#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ +#define DBG_MPI_VALUE 2 /* debug mpi details */ +#define DBG_CIPHER_VALUE 4 /* debug cipher handling */ + /* (may reveal sensitive data) */ +#define DBG_FILTER_VALUE 8 /* debug internal filter handling */ +#define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */ +#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ +#define DBG_CACHE_VALUE 64 /* debug the cacheing */ +#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_TRUST_VALUE 256 /* debug the trustdb */ + + +#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) +#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) +#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) + + +#endif /*G10_OPTIONS_H*/ diff -Nru a/security/cryptomark/gnupg/packet.h b/security/cryptomark/gnupg/packet.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/packet.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,359 @@ +/* packet.h - packet read/write stuff + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_PACKET_H +#define G10_PACKET_H + +#include "types.h" +#include "iobuf.h" +#include "mpi.h" +#include "cipher.h" +#include "filter.h" + +#define DEBUG_PARSE_PACKET 1 + +typedef enum { + PKT_NONE =0, + PKT_PUBKEY_ENC =1, /* public key encrypted packet */ + PKT_SIGNATURE =2, /* secret key encrypted packet */ + PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/ + PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/ + PKT_SECRET_KEY =5, /* secret key */ + PKT_PUBLIC_KEY =6, /* public key */ + PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */ + PKT_COMPRESSED =8, /* compressed data packet */ + PKT_ENCRYPTED =9, /* conventional encrypted data */ + PKT_MARKER =10, /* marker packet (OpenPGP) */ + PKT_PLAINTEXT =11, /* plaintext data with filename and mode */ + PKT_RING_TRUST =12, /* keyring trust packet */ + PKT_USER_ID =13, /* user id packet */ + PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ + PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ + PKT_PHOTO_ID =17, /* PGP's photo ID */ + PKT_COMMENT =61, /* new comment packet (private) */ + PKT_ENCRYPTED_MDC =62, /* test: encrypted data with MDC */ +} pkttype_t; + +typedef struct packet_struct PACKET; + +typedef struct { + byte mode; + byte hash_algo; + byte salt[8]; + u32 count; +} STRING2KEY; + +typedef struct { + byte version; + byte cipher_algo; /* cipher algorithm used */ + STRING2KEY s2k; + byte seskeylen; /* keylength in byte or 0 for no seskey */ + byte seskey[1]; +} PKT_symkey_enc; + +typedef struct { + u32 keyid[2]; /* 64 bit keyid */ + byte version; + byte pubkey_algo; /* algorithm used for public key scheme */ + byte throw_keyid; + MPI data[PUBKEY_MAX_NENC]; +} PKT_pubkey_enc; + + +typedef struct { + u32 keyid[2]; /* 64 bit keyid */ + byte sig_class; /* sig classification */ + byte digest_algo; /* algorithm used for digest */ + byte pubkey_algo; /* algorithm used for public key scheme */ + byte last; /* a stupid flag */ +} PKT_onepass_sig; + + +typedef struct { + ulong local_id; /* internal use, valid if > 0 */ + struct { + unsigned checked:1; /* signature has been checked */ + unsigned valid:1; /* signature is good (if checked is set) */ + unsigned unknown_critical:1; + } flags; + u32 keyid[2]; /* 64 bit keyid */ + u32 timestamp; /* signature made */ + byte version; + byte sig_class; /* sig classification, append for MD calculation*/ + byte pubkey_algo; /* algorithm used for public key scheme */ + /* (PUBKEY_ALGO_xxx) */ + byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */ + byte *hashed_data; /* all subpackets with hashed data (v4 only) */ + byte *unhashed_data; /* ditto for unhashed data */ + byte digest_start[2]; /* first 2 bytes of the digest */ + MPI data[PUBKEY_MAX_NSIG]; +} PKT_signature; + + +/**************** + * Note about the pkey/skey elements: We assume that the secret keys + * has the same elemts as the public key at the begin of the array, so + * that npkey < nskey and it is possible to compare the secret and + * public keys by comparing the first npkey elements of pkey againts skey. + */ +typedef struct { + u32 timestamp; /* key made */ + u32 expiredate; /* expires at this date or 0 if not at all */ + byte hdrbytes; /* number of header bytes */ + byte version; + byte pubkey_algo; /* algorithm used for public key scheme */ + byte pubkey_usage; /* for now only used to pass it to getkey() */ + ulong local_id; /* internal use, valid if > 0 */ + u32 keyid[2]; /* calculated by keyid_from_pk() */ + byte *namehash; /* if != NULL: found by this name */ + MPI pkey[PUBKEY_MAX_NPKEY]; +} PKT_public_key; + +typedef struct { + u32 timestamp; /* key made */ + u32 expiredate; /* expires at this date or 0 if not at all */ + byte hdrbytes; /* number of header bytes */ + byte version; + byte pubkey_algo; /* algorithm used for public key scheme */ + byte pubkey_usage; + byte is_primary; + byte is_protected; /* The secret info is protected and must */ + /* be decrypted before use, the protected */ + /* MPIs are simply (void*) pointers to memory */ + /* and should never be passed to a mpi_xxx() */ + struct { + byte algo; /* cipher used to protect the secret information*/ + STRING2KEY s2k; + byte ivlen; /* used length of the iv */ + byte iv[16]; /* initialization vector for CFB mode */ + } protect; + MPI skey[PUBKEY_MAX_NSKEY]; + u16 csum; /* checksum */ +} PKT_secret_key; + + +typedef struct { + int len; /* length of data */ + char data[1]; +} PKT_comment; + +typedef struct { + int len; /* length of the name */ + char *photo; /* if this is not NULL, the packet is a photo ID */ + int photolen; /* and the length of the photo */ + char name[1]; +} PKT_user_id; + +typedef struct { + u32 len; /* reserved */ + byte new_ctb; + byte algorithm; + IOBUF buf; /* IOBUF reference */ +} PKT_compressed; + +typedef struct { + u32 len; /* length of encrypted data */ + byte new_ctb; /* uses a new CTB */ + byte mdc_method; /* test: > 0: this is is an encrypted_mdc packet */ + IOBUF buf; /* IOBUF reference */ +} PKT_encrypted; + +typedef struct { + unsigned int trustval; +} PKT_ring_trust; + +typedef struct { + u32 len; /* length of encrypted data */ + IOBUF buf; /* IOBUF reference */ + byte new_ctb; + int mode; + u32 timestamp; + int namelen; + char name[1]; +} PKT_plaintext; + + +/* combine all packets into a union */ +struct packet_struct { + pkttype_t pkttype; + union { + void *generic; + PKT_symkey_enc *symkey_enc; /* PKT_SYMKEY_ENC */ + PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */ + PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */ + PKT_signature *signature; /* PKT_SIGNATURE */ + PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */ + PKT_secret_key *secret_key; /* PKT_SECRET_[SUB]KEY */ + PKT_comment *comment; /* PKT_COMMENT */ + PKT_user_id *user_id; /* PKT_USER_ID */ + PKT_compressed *compressed; /* PKT_COMPRESSED */ + PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */ + PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */ + PKT_plaintext *plaintext; /* PKT_PLAINTEXT */ + } pkt; +}; + +#define init_packet(a) do { (a)->pkttype = 0; \ + (a)->pkt.generic = NULL; \ + } while(0) + +typedef enum { + SIGSUBPKT_TEST_CRITICAL=-3, + SIGSUBPKT_LIST_UNHASHED=-2, + SIGSUBPKT_LIST_HASHED =-1, + SIGSUBPKT_NONE = 0, + SIGSUBPKT_SIG_CREATED = 2, /* signature creation time */ + SIGSUBPKT_SIG_EXPIRE = 3, /* signature expiration time */ + SIGSUBPKT_EXPORTABLE = 4, /* exportable */ + SIGSUBPKT_TRUST = 5, /* trust signature */ + SIGSUBPKT_REGEXP = 6, /* regular expression */ + SIGSUBPKT_REVOCABLE = 7, /* revocable */ + SIGSUBPKT_KEY_EXPIRE = 9, /* key expiration time */ + SIGSUBPKT_ARR =10, /* additional recipient request */ + SIGSUBPKT_PREF_SYM =11, /* preferred symmetric algorithms */ + SIGSUBPKT_REV_KEY =12, /* revocation key */ + SIGSUBPKT_ISSUER =16, /* issuer key ID */ + SIGSUBPKT_NOTATION =20, /* notation data */ + SIGSUBPKT_PREF_HASH =21, /* preferred hash algorithms */ + SIGSUBPKT_PREF_COMPR =22, /* preferred compression algorithms */ + SIGSUBPKT_KS_FLAGS =23, /* key server preferences */ + SIGSUBPKT_PREF_KS =24, /* preferred key server */ + SIGSUBPKT_PRIMARY_UID =25, /* primary user id */ + SIGSUBPKT_POLICY =26, /* policy URL */ + SIGSUBPKT_KEY_FLAGS =27, /* key flags */ + SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ + SIGSUBPKT_PRIV_ADD_SIG =101,/* signatur is also valid for this uid */ + + SIGSUBPKT_FLAG_CRITICAL=128 +} sigsubpkttype_t; + + +/*-- mainproc.c --*/ +int proc_packets( void *ctx, IOBUF a ); +int proc_signature_packets( void *ctx, IOBUF a, + STRLIST signedfiles, const char *sigfile ); +int proc_encryption_packets( void *ctx, IOBUF a ); +int list_packets( IOBUF a ); + +/*-- parse-packet.c --*/ +int set_packet_list_mode( int mode ); + +#if DEBUG_PARSE_PACKET +int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos, const char* file, int lineno ); +int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, const char* file, int lineno ); +int dbg_copy_all_packets( IOBUF inp, IOBUF out, const char* file, int lineno ); +int dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff, const char* file, int lineno ); +int dbg_skip_some_packets( IOBUF inp, unsigned n, const char* file, int lineno ); +#define search_packet( a,b,c,d ) dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) +#define parse_packet( a, b ) dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) +#define copy_all_packets( a,b ) dbg_copy_all_packets((a),(b), __FILE__, __LINE__ ) +#define copy_some_packets( a,b,c ) dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ ) +#define skip_some_packets( a,b ) dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) +#else +int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ); +int parse_packet( IOBUF inp, PACKET *ret_pkt); +int copy_all_packets( IOBUF inp, IOBUF out ); +int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ); +int skip_some_packets( IOBUF inp, unsigned n ); +#endif + +const byte *enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, + size_t *ret_n, int *start ); +const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, + size_t *ret_n ); +const byte *parse_sig_subpkt2( PKT_signature *sig, + sigsubpkttype_t reqtype, size_t *ret_n ); + +/*-- build-packet.c --*/ +int build_packet( IOBUF inp, PACKET *pkt ); +u32 calc_packet_length( PACKET *pkt ); +void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); +void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, + const byte *buffer, size_t buflen ); +void build_sig_subpkt_from_sig( PKT_signature *sig ); + +/*-- free-packet.c --*/ +void free_symkey_enc( PKT_symkey_enc *enc ); +void free_pubkey_enc( PKT_pubkey_enc *enc ); +void free_seckey_enc( PKT_signature *enc ); +int digest_algo_from_sig( PKT_signature *sig ); +void release_public_key_parts( PKT_public_key *pk ); +void free_public_key( PKT_public_key *key ); +void release_secret_key_parts( PKT_secret_key *sk ); +void free_secret_key( PKT_secret_key *sk ); +void free_user_id( PKT_user_id *uid ); +void free_comment( PKT_comment *rem ); +void free_packet( PACKET *pkt ); +PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); +PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d, + PKT_public_key *s, + const byte *namehash ); +PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ); +PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); +PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s ); +int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); +int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ); +int cmp_signatures( PKT_signature *a, PKT_signature *b ); +int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); +int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); + + +/*-- sig-check.c --*/ +int signature_check( PKT_signature *sig, MD_HANDLE digest ); + +/*-- seckey-cert.c --*/ +int is_secret_key_protected( PKT_secret_key *sk ); +int check_secret_key( PKT_secret_key *sk, int retries ); +int protect_secret_key( PKT_secret_key *sk, DEK *dek ); + +/*-- pubkey-enc.c --*/ +int get_session_key( PKT_pubkey_enc *k, DEK *dek ); + +/*-- compress.c --*/ +int handle_compressed( void *ctx, PKT_compressed *cd, + int (*callback)(IOBUF, void *), void *passthru ); + +/*-- encr-data.c --*/ +int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); +int encrypt_data( PKT_encrypted *ed, DEK *dek ); + +/*-- plaintext.c --*/ +int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, + int nooutput, int clearsig ); +int handle_plaintext_data( PKT_plaintext *pt, md_filter_context_t *mfx, + int nooutput, int clearsig, unsigned char **data ); +int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, + const char *inname, int textmode ); + +/*-- comment.c --*/ +int write_comment( IOBUF out, const char *s ); + +/*-- sign.c --*/ +int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, + PKT_user_id *uid, PKT_public_key *subpk, + PKT_secret_key *sk, + int sigclass, int digest_algo, + int (*mksubpkt)(PKT_signature *, void *), + void *opaque ); + +/*-- keygen.c --*/ +PKT_user_id *generate_user_id(void); + +#endif /*G10_PACKET_H*/ diff -Nru a/security/cryptomark/gnupg/parse-packet.c b/security/cryptomark/gnupg/parse-packet.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/parse-packet.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1769 @@ +/* parse-packet.c - read packets + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include "packet.h" +#include "iobuf.h" +#include "mpi.h" +#include "util.h" +#include "cipher.h" +#include "memory.h" +#include "filter.h" +#include "options.h" +#include "main.h" +#include "i18n.h" + +static int mpi_print_mode = 0; +static int list_mode = 0; + +static int parse( IOBUF inp, PACKET *pkt, int reqtype, + ulong *retpos, int *skip, IOBUF out, int do_skip + #ifdef DEBUG_PARSE_PACKET + ,const char *dbg_w, const char *dbg_f, int dbg_l + #endif + ); +static int copy_packet( IOBUF inp, IOBUF out, int pkttype, + unsigned long pktlen ); +static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); +static void skip_rest( IOBUF inp, unsigned long pktlen ); +static void *read_rest( IOBUF inp, size_t pktlen ); +static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_signature *sig ); +static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_onepass_sig *ops ); +static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, + byte *hdr, int hdrlen, PACKET *packet ); +static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb); +static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb ); +static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb); + +static unsigned short +read_16(IOBUF inp) +{ + unsigned short a; + a = iobuf_get_noeof(inp) << 8; + a |= iobuf_get_noeof(inp); + return a; +} + +static unsigned long +read_32(IOBUF inp) +{ + unsigned long a; + a = iobuf_get_noeof(inp) << 24; + a |= iobuf_get_noeof(inp) << 16; + a |= iobuf_get_noeof(inp) << 8; + a |= iobuf_get_noeof(inp); + return a; +} + + +int +set_packet_list_mode( int mode ) +{ + int old = list_mode; + list_mode = mode; + mpi_print_mode = DBG_MPI; + return old; +} + +static void +unknown_pubkey_warning( int algo ) +{ +// static byte unknown_pubkey_algos[256]; + + warn (__FUNCTION__ ": %d", algo); + +// algo &= 0xff; +// if( !unknown_pubkey_algos[algo] ) { +// if( opt.verbose ) +// log_info(_("can't handle public key algorithm %d\n"), algo ); +// unknown_pubkey_algos[algo] = 1; +// } +} + +/**************** + * Parse a Packet and return it in packet + * Returns: 0 := valid packet in pkt + * -1 := no more packets + * >0 := error + * Note: The function may return an error and a partly valid packet; + * caller must free this packet. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) +{ + int skip, rc; + + trace(); + + do { + rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l ); + } while( skip ); + return rc; +} +#else +int +parse_packet( IOBUF inp, PACKET *pkt ) +{ + int skip, rc; + + trace(); + + do { + rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 ); + } while( skip ); + return rc; +} +#endif + +/**************** + * Like parse packet, but only return packets of the given type. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos, + const char *dbg_f, int dbg_l ) +{ + int skip, rc; + + trace(); + + do { + rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); + } while( skip ); + return rc; +} +#else +int +search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ) +{ + int skip, rc; + + trace(); + + do { + rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 ); + } while( skip ); + return rc; +} +#endif + +/**************** + * Copy all packets from INP to OUT, thereby removing unused spaces. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_copy_all_packets( IOBUF inp, IOBUF out, + const char *dbg_f, int dbg_l ) +{ + PACKET pkt; + int skip, rc=0; + trace(); + + do { + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l ))); + return rc; +} +#else +int +copy_all_packets( IOBUF inp, IOBUF out ) +{ + PACKET pkt; + int skip, rc=0; + trace(); + + do { + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 ))); + return rc; +} +#endif + +/**************** + * Copy some packets from INP to OUT, thereby removing unused spaces. + * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets) + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff, + const char *dbg_f, int dbg_l ) +{ + PACKET pkt; + int skip, rc=0; + trace(); + + do { + if( iobuf_tell(inp) >= stopoff ) + return 0; + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, + "some", dbg_f, dbg_l )) ); + return rc; +} +#else +int +copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ) +{ + PACKET pkt; + int skip, rc=0; + trace(); + + do { + if( iobuf_tell(inp) >= stopoff ) + return 0; + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) ); + return rc; +} +#endif + +/**************** + * Skip over N packets + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_skip_some_packets( IOBUF inp, unsigned n, + const char *dbg_f, int dbg_l ) +{ + int skip, rc=0; + PACKET pkt; + + trace(); + + for( ;n && !rc; n--) { + init_packet(&pkt); + rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l ); + } + return rc; +} +#else +int +skip_some_packets( IOBUF inp, unsigned n ) +{ + int skip, rc=0; + PACKET pkt; + + trace(); + + for( ;n && !rc; n--) { + init_packet(&pkt); + rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 ); + } + return rc; +} +#endif + + +/**************** + * Parse packet. Set the variable skip points to to 1 if the packet + * should be skipped; this is the case if either there is a + * requested packet type and the parsed packet doesn't match or the + * packet-type is 0, indicating deleted stuff. + * if OUT is not NULL, a special copymode is used. + */ +static int +parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, + int *skip, IOBUF out, int do_skip +#ifdef DEBUG_PARSE_PACKET + ,const char *dbg_w, const char *dbg_f, int dbg_l +#endif + ) +{ + int rc=0, c, ctb, pkttype, lenbytes; + unsigned long pktlen; + byte hdr[8]; + int hdrlen; + int new_ctb = 0; + + trace(); + + *skip = 0; +// assert( !pkt->pkt.generic ); + if( retpos ) + *retpos = iobuf_tell(inp); + + if( (ctb = iobuf_get(inp)) == -1 ) { + dbg (__FUNCTION__ ": eof already?"); + rc = -1; + goto leave; + } + hdrlen=0; + hdr[hdrlen++] = ctb; + if( !(ctb & 0x80) ) { + log_error("%s: invalid packet (ctb=%02x) near %lu\n", + iobuf_where(inp), ctb, iobuf_tell(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + pktlen = 0; + new_ctb = !!(ctb & 0x40); + if( new_ctb ) { + pkttype = ctb & 0x3f; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + hdr[hdrlen++] = c; + if( c < 192 ) + pktlen = c; + else if( c < 224 ) { + pktlen = (c - 192) * 256; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 2nd length byte missing\n", iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + hdr[hdrlen++] = c; + pktlen += c + 192; + } + else if( c == 255 ) { + pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 4 byte length invalid\n", iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + pktlen |= (hdr[hdrlen++] = c ); + } + else { /* partial body length */ + iobuf_set_partial_block_mode(inp, c & 0xff); + pktlen = 0;/* to indicate partial length */ + } + } + else { + pkttype = (ctb>>2)&0xf; + lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); + if( !lenbytes ) { + pktlen = 0; /* don't know the value */ + if( pkttype != PKT_COMPRESSED ) + iobuf_set_block_mode(inp, 1); + } + else { + for( ; lenbytes; lenbytes-- ) { + pktlen <<= 8; + pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp); + } + } + } + + if( out && pkttype ) { + if( iobuf_write( out, hdr, hdrlen ) == -1 ) + rc = G10ERR_WRITE_FILE; + else + rc = copy_packet(inp, out, pkttype, pktlen ); + goto leave; + } + + if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) { + skip_rest(inp, pktlen); + *skip = 1; + rc = 0; + goto leave; + } + + if( DBG_PACKET ) { + #ifdef DEBUG_PARSE_PACKET + log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n", + iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"", + dbg_w, dbg_f, dbg_l ); + #else + log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n", + iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" ); + #endif + } + pkt->pkttype = pkttype; + rc = G10ERR_UNKNOWN_PACKET; /* default error */ + switch( pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key ); + rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); + break; + case PKT_SECRET_KEY: + case PKT_SECRET_SUBKEY: + pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key ); + rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); + break; + case PKT_SYMKEY_ENC: + rc = parse_symkeyenc( inp, pkttype, pktlen, pkt ); + break; + case PKT_PUBKEY_ENC: + rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt ); + break; + case PKT_SIGNATURE: + pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); + rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); + break; + case PKT_ONEPASS_SIG: + pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig ); + rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig ); + break; + case PKT_USER_ID: + rc = parse_user_id(inp, pkttype, pktlen, pkt ); + break; + case PKT_PHOTO_ID: + pkt->pkttype = pkttype = PKT_USER_ID; /* must fix it */ + rc = parse_photo_id(inp, pkttype, pktlen, pkt); + break; + case PKT_OLD_COMMENT: + case PKT_COMMENT: + rc = parse_comment(inp, pkttype, pktlen, pkt); + break; + case PKT_RING_TRUST: + parse_trust(inp, pkttype, pktlen, pkt); + rc = 0; + break; + case PKT_PLAINTEXT: + rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_COMPRESSED: + rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: + rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb ); + break; + default: + skip_packet(inp, pkttype, pktlen); + break; + } + + leave: + if( !rc && iobuf_error(inp) ) + rc = G10ERR_INV_KEYRING; + dbg (__FUNCTION__": rc = %d", rc); + return rc; +} + +//static void +//dump_hex_line( int c, int *i ) +//{ +// if( *i && !(*i%8) ) { +// if( *i && !(*i%24) ) +// printf("\n%4d:", *i ); +// else +// putchar(' '); +// } +// if( c == -1 ) +// printf(" EOF" ); +// else +// printf(" %02x", c ); +// ++*i; +//} + + +static int +copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) +{ + int n; + char buf[100]; + + trace(); + + if( iobuf_in_block_mode(inp) ) { + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else if( !pktlen && pkttype == PKT_COMPRESSED ) { + log_debug("copy_packet: compressed!\n"); + /* compressed packet, copy till EOF */ + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else { + for( ; pktlen; pktlen -= n ) { + n = pktlen > 100 ? 100 : pktlen; + n = iobuf_read( inp, buf, n ); + if( n == -1 ) + return G10ERR_READ_FILE; + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + } + return 0; +} + + +static void +skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) +{ +// if( list_mode ) { +// if( pkttype == PKT_MARKER ) +// fputs(":marker packet:\n", stdout ); +// else +// printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen); +// if( pkttype ) { +// int c, i=0 ; +// if( pkttype != PKT_MARKER ) +// fputs("dump:", stdout ); +// if( iobuf_in_block_mode(inp) ) { +// while( (c=iobuf_get(inp)) != -1 ) +// dump_hex_line(c, &i); +// } +// else { +// for( ; pktlen; pktlen-- ) +// dump_hex_line(iobuf_get(inp), &i); +// } +// putchar('\n'); +// return; +// } +// } + skip_rest(inp,pktlen); +} + +static void +skip_rest( IOBUF inp, unsigned long pktlen ) +{ + trace(); + + if( iobuf_in_block_mode(inp) ) { + while( iobuf_get(inp) != -1 ) + ; + } + else { + for( ; pktlen; pktlen-- ) + if( iobuf_get(inp) == -1 ) + break; + } +} + + +static void * +read_rest( IOBUF inp, size_t pktlen ) +{ + byte *p; + int i; + + trace(); + + if( iobuf_in_block_mode(inp) ) { + log_error("read_rest: can't store stream data\n"); + p = NULL; + } + else { + p = m_alloc( pktlen ); + for(i=0; pktlen; pktlen--, i++ ) + p[i] = iobuf_get(inp); + } + return p; +} + + + +static int +parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + PKT_symkey_enc *k; + int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen; + + trace(); + + if( pktlen < 4 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + version = iobuf_get_noeof(inp); pktlen--; + if( version != 4 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, version); + goto leave; + } + if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */ + log_error("packet(%d) too large\n", pkttype); + goto leave; + } + cipher_algo = iobuf_get_noeof(inp); pktlen--; + s2kmode = iobuf_get_noeof(inp); pktlen--; + hash_algo = iobuf_get_noeof(inp); pktlen--; + switch( s2kmode ) { + case 0: /* simple s2k */ + minlen = 0; + break; + case 1: /* salted s2k */ + minlen = 8; + break; + case 3: /* iterated+salted s2k */ + minlen = 9; + break; + default: + log_error("unknown S2K %d\n", s2kmode ); + goto leave; + } + if( minlen > pktlen ) { + log_error("packet with S2K %d too short\n", s2kmode ); + goto leave; + } + seskeylen = pktlen - minlen; + k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc + + seskeylen - 1 ); + k->version = version; + k->cipher_algo = cipher_algo; + k->s2k.mode = s2kmode; + k->s2k.hash_algo = hash_algo; + if( s2kmode == 1 || s2kmode == 3 ) { + for(i=0; i < 8 && pktlen; i++, pktlen-- ) + k->s2k.salt[i] = iobuf_get_noeof(inp); + } + if( s2kmode == 3 ) { + k->s2k.count = iobuf_get(inp); pktlen--; + } + k->seskeylen = seskeylen; + for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) + k->seskey[i] = iobuf_get_noeof(inp); +// assert( !pktlen ); +// +// if( list_mode ) { +// printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", +// version, cipher_algo, s2kmode, hash_algo); +// if( s2kmode == 1 || s2kmode == 3 ) { +// printf("\tsalt "); +// for(i=0; i < 8; i++ ) +// printf("%02x", k->s2k.salt[i]); +// if( s2kmode == 3 ) +// printf(", count %lu\n", (ulong)k->s2k.count ); +// printf("\n"); +// } +// } + + leave: + skip_rest(inp, pktlen); + return 0; +} + +static int +parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + unsigned n; + int i, ndata; + PKT_pubkey_enc *k; + + trace(); + + k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc); + if( pktlen < 12 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + k->version = iobuf_get_noeof(inp); pktlen--; + if( k->version != 2 && k->version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, k->version); + goto leave; + } + k->keyid[0] = read_32(inp); pktlen -= 4; + k->keyid[1] = read_32(inp); pktlen -= 4; + k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + k->throw_keyid = 0; /* only used as flag for build_packet */ +// if( list_mode ) +// printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", +// k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); + + ndata = pubkey_get_nenc(k->pubkey_algo); + if( !ndata ) { +// if( list_mode ) +// printf("\tunsupported algorithm %d\n", k->pubkey_algo ); + unknown_pubkey_warning( k->pubkey_algo ); + k->data[0] = NULL; /* no need to store the encrypted data */ + } + else { + for( i=0; i < ndata; i++ ) { + n = pktlen; + k->data[i] = mpi_read(inp, &n, 0); pktlen -=n; +// if( list_mode ) { +// printf("\tdata: "); +// mpi_print(stdout, k->data[i], mpi_print_mode ); +// putchar('\n'); +// } + } + } + + leave: + skip_rest(inp, pktlen); + return 0; +} + + +static void +dump_sig_subpkt( int hashed, int type, int critical, + const byte *buffer, size_t buflen, size_t length ) +{ + trace(); + +// const char *p=NULL; +// int i; +// +// printf("\t%s%ssubpkt %d len %u (", /*)*/ +// critical ? "critical ":"", +// hashed ? "hashed ":"", type, (unsigned)length ); +// buffer++; +// length--; +// if( length > buflen ) { +// printf("too short: buffer is only %u)\n", (unsigned)buflen ); +// return; +// } +// switch( type ) { +// case SIGSUBPKT_SIG_CREATED: +// if( length >= 4 ) +// printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) ); +// break; +// case SIGSUBPKT_SIG_EXPIRE: +// if( length >= 4 ) +// printf("sig expires after %s", +// strtimevalue( buffer_to_u32(buffer) ) ); +// break; +// case SIGSUBPKT_EXPORTABLE: +// if( length ) +// printf("%sexportable", *buffer? "":"not "); +// break; +// case SIGSUBPKT_TRUST: +// p = "trust signature"; +// break; +// case SIGSUBPKT_REGEXP: +// p = "regular expression"; +// break; +// case SIGSUBPKT_REVOCABLE: +// p = "revocable"; +// break; +// case SIGSUBPKT_KEY_EXPIRE: +// if( length >= 4 ) +// printf("key expires after %s", +// strtimevalue( buffer_to_u32(buffer) ) ); +// break; +// case SIGSUBPKT_ARR: +// p = "additional recipient request"; +// break; +// case SIGSUBPKT_PREF_SYM: +// fputs("pref-sym-algos:", stdout ); +// for( i=0; i < length; i++ ) +// printf(" %d", buffer[i] ); +// break; +// case SIGSUBPKT_REV_KEY: +// fputs("revocation key: ", stdout ); +// if( length < 22 ) +// p = "[too short]"; +// else { +// printf("c=%02x a=%d f=", buffer[0], buffer[1] ); +// for( i=2; i < length; i++ ) +// printf("%02X", buffer[i] ); +// } +// break; +// case SIGSUBPKT_ISSUER: +// if( length >= 8 ) +// printf("issuer key ID %08lX%08lX", +// (ulong)buffer_to_u32(buffer), +// (ulong)buffer_to_u32(buffer+4) ); +// break; +// case SIGSUBPKT_NOTATION: +// { +// fputs("notation: ", stdout ); +// if( length < 8 ) +// p = "[too short]"; +// else if( !(*buffer & 0x80) ) +// p = "[not human readable]"; +// else { +// const byte *s = buffer; +// size_t n1, n2; +// +// n1 = (s[4] << 8) | s[5]; +// n2 = (s[6] << 8) | s[7]; +// s += 8; +// if( 8+n1+n2 != length ) +// p = "[error]"; +// else { +// print_string( stdout, s, n1, ')' ); +// putc( '=', stdout ); +// print_string( stdout, s+n1, n2, ')' ); +// } +// } +// } +// break; +// case SIGSUBPKT_PREF_HASH: +// fputs("pref-hash-algos:", stdout ); +// for( i=0; i < length; i++ ) +// printf(" %d", buffer[i] ); +// break; +// case SIGSUBPKT_PREF_COMPR: +// fputs("pref-zip-algos:", stdout ); +// for( i=0; i < length; i++ ) +// printf(" %d", buffer[i] ); +// break; +// case SIGSUBPKT_KS_FLAGS: +// p = "key server preferences"; +// break; +// case SIGSUBPKT_PREF_KS: +// p = "preferred key server"; +// break; +// case SIGSUBPKT_PRIMARY_UID: +// p = "primary user ID"; +// break; +// case SIGSUBPKT_POLICY: +// fputs("policy: ", stdout ); +// print_string( stdout, buffer, length, ')' ); +// break; +// case SIGSUBPKT_KEY_FLAGS: +// p = "key flags"; +// break; +// case SIGSUBPKT_SIGNERS_UID: +// p = "signer's user ID"; +// break; +// case SIGSUBPKT_PRIV_ADD_SIG: +// p = "signs additional user ID"; +// break; +// default: p = "?"; break; +// } +// +// printf("%s)\n", p? p: ""); +} + +/**************** + * Returns: >= 0 offset into buffer + * -1 unknown type + * -2 unsupported type + * -3 subpacket too short + */ +static int +parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) +{ + trace(); + + switch( type ) { + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + if( n < 4 ) + break; + return 0; + case SIGSUBPKT_EXPORTABLE: + if( !n ) + break; + return 0; + case SIGSUBPKT_ISSUER:/* issuer key ID */ + if( n < 8 ) + break; + return 0; + case SIGSUBPKT_NOTATION: + if( n < 8 ) /* minimum length needed */ + break; + return 0; + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_POLICY: + return 0; + case SIGSUBPKT_PRIV_ADD_SIG: + /* because we use private data, we check the GNUPG marker */ + if( n < 24 ) + break; + if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' ) + return -2; + return 3; + default: return -1; + } + return -3; +} + + +static int +can_handle_critical( const byte *buffer, size_t n, int type ) +{ + trace(); + + switch( type ) { + case SIGSUBPKT_NOTATION: + if( n >= 8 && (*buffer & 0x80) ) + return 1; /* human readable is handled */ + return 0; + + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + case SIGSUBPKT_EXPORTABLE: + case SIGSUBPKT_ISSUER:/* issuer key ID */ + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + return 1; + + case SIGSUBPKT_POLICY: /* Is enough to show the policy? */ + default: + return 0; + } +} + + +const byte * +enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, + size_t *ret_n, int *start ) +{ + int buflen; + int type; + int critical; + int offset; + size_t n; + int seq = 0; + int reqseq = start? *start: 0; + + trace(); + + if( !buffer || reqseq == -1 ) + return NULL; + buflen = (*buffer << 8) | buffer[1]; + buffer += 2; + while( buflen ) { + n = *buffer++; buflen--; + if( n == 255 ) { + if( buflen < 4 ) + goto too_short; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + + } + else if( n >= 192 ) { + if( buflen < 2 ) + goto too_short; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + goto too_short; + type = *buffer; + if( type & 0x80 ) { + type &= 0x7f; + critical = 1; + } + else + critical = 0; + if( !(++seq > reqseq) ) + ; + else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) { + if( critical ) { + if( n-1 > buflen+1 ) + goto too_short; + if( !can_handle_critical(buffer+1, n-1, type ) ) { +// log_info(_("subpacket of type %d has critical bit set\n"), +// type); + log_info("subpacket of type %d has critical bit set\n", + type); + if( start ) + *start = seq; + return NULL; /* this is an error */ + } + } + } + else if( reqtype < 0 ) /* list packets */ + dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED, + type, critical, buffer, buflen, n ); + else if( type == reqtype ) { /* found */ + buffer++; + n--; + if( n > buflen ) + goto too_short; + if( ret_n ) + *ret_n = n; + offset = parse_one_sig_subpkt(buffer, n, type ); + switch( offset ) { + case -3: + log_error("subpacket of type %d too short\n", type); + return NULL; + case -2: + return NULL; + case -1: +// BUG(); /* not yet needed */ + default: + break; + } + if( start ) + *start = seq; + return buffer+offset; + } + buffer += n; buflen -=n; + } + if( reqtype == SIGSUBPKT_TEST_CRITICAL ) + return buffer; /* as value true to indicate that there is no */ + /* critical bit we don't understand */ + if( start ) + *start = -1; + return NULL; /* end of packets; not found */ + + too_short: + log_error("buffer shorter than subpacket\n"); + if( start ) + *start = -1; + return NULL; +} + + +const byte * +parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ) +{ + trace(); + + return enum_sig_subpkt( buffer, reqtype, ret_n, NULL ); +} + +const byte * +parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n ) +{ + const byte *p; + + trace(); + + p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n ); + if( !p ) + p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n ); + return p; +} + + + +static int +parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_signature *sig ) +{ + int md5_len=0; + unsigned n; + int is_v4=0; + int rc=0; + int i, ndata; + + trace(); + + if( pktlen < 16 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + sig->version = iobuf_get_noeof(inp); pktlen--; + if( sig->version == 4 ) + is_v4=1; + else if( sig->version != 2 && sig->version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, sig->version); + goto leave; + } + + if( !is_v4 ) { + md5_len = iobuf_get_noeof(inp); pktlen--; + } + sig->sig_class = iobuf_get_noeof(inp); pktlen--; + if( !is_v4 ) { + sig->timestamp = read_32(inp); pktlen -= 4; + sig->keyid[0] = read_32(inp); pktlen -= 4; + sig->keyid[1] = read_32(inp); pktlen -= 4; + } + sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + sig->digest_algo = iobuf_get_noeof(inp); pktlen--; + if( is_v4 ) { /* read subpackets */ + n = read_16(inp); pktlen -= 2; /* length of hashed data */ + if( n > 10000 ) { + log_error("signature packet: hashed data too long\n"); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if( n ) { + sig->hashed_data = m_alloc( n + 2 ); + sig->hashed_data[0] = n >> 8; + sig->hashed_data[1] = n; + if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) { + log_error("premature eof while reading hashed signature data\n"); + rc = -1; + goto leave; + } + pktlen -= n; + } + n = read_16(inp); pktlen -= 2; /* length of unhashed data */ + if( n > 10000 ) { + log_error("signature packet: unhashed data too long\n"); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if( n ) { + sig->unhashed_data = m_alloc( n + 2 ); + sig->unhashed_data[0] = n >> 8; + sig->unhashed_data[1] = n; + if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) { + log_error("premature eof while reading unhashed signature data\n"); + rc = -1; + goto leave; + } + pktlen -= n; + } + } + + if( pktlen < 5 ) { /* sanity check */ + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--; + sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--; + + if( is_v4 && sig->pubkey_algo ) { /*extract required information */ + const byte *p; + + /* set sig->flags.unknown_critical if there is a + * critical bit set for packets which we do not understand */ + if( !parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_TEST_CRITICAL, NULL) + || !parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_TEST_CRITICAL, + NULL) ) + { + sig->flags.unknown_critical = 1; + } + + p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL ); + if( !p ) + log_error("signature packet without timestamp\n"); + else + sig->timestamp = buffer_to_u32(p); + p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); + if( !p ) + log_error("signature packet without keyid\n"); + else { + sig->keyid[0] = buffer_to_u32(p); + sig->keyid[1] = buffer_to_u32(p+4); + } + } + +// if( list_mode ) { +// printf(":signature packet: algo %d, keyid %08lX%08lX\n" +// "\tversion %d, created %lu, md5len %d, sigclass %02x\n" +// "\tdigest algo %d, begin of digest %02x %02x\n", +// sig->pubkey_algo, +// (ulong)sig->keyid[0], (ulong)sig->keyid[1], +// sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class, +// sig->digest_algo, +// sig->digest_start[0], sig->digest_start[1] ); +// if( is_v4 ) { +// parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_LIST_HASHED, NULL ); +// parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL); +// } +// } + + ndata = pubkey_get_nsig(sig->pubkey_algo); + if( !ndata ) { +// if( list_mode ) +// printf("\tunknown algorithm %d\n", sig->pubkey_algo ); + unknown_pubkey_warning( sig->pubkey_algo ); + /* we store the plain material in data[0], so that we are able + * to write it back with build_packet() */ + sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen ); + pktlen = 0; + } + else { + for( i=0; i < ndata; i++ ) { + n = pktlen; + sig->data[i] = mpi_read(inp, &n, 0 ); + pktlen -=n; +// if( list_mode ) { +// printf("\tdata: "); +// mpi_print(stdout, sig->data[i], mpi_print_mode ); +// putchar('\n'); +// } + } + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + + +static int +parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_onepass_sig *ops ) +{ + int version; + + trace(); + + if( pktlen < 13 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + version = iobuf_get_noeof(inp); pktlen--; + if( version != 3 ) { + log_error("onepass_sig with unknown version %d\n", version); + goto leave; + } + ops->sig_class = iobuf_get_noeof(inp); pktlen--; + ops->digest_algo = iobuf_get_noeof(inp); pktlen--; + ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + ops->keyid[0] = read_32(inp); pktlen -= 4; + ops->keyid[1] = read_32(inp); pktlen -= 4; + ops->last = iobuf_get_noeof(inp); pktlen--; +// if( list_mode ) +// printf(":onepass_sig packet: keyid %08lX%08lX\n" +// "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n", +// (ulong)ops->keyid[0], (ulong)ops->keyid[1], +// version, ops->sig_class, +// ops->digest_algo, ops->pubkey_algo, ops->last ); + + + leave: + skip_rest(inp, pktlen); + return 0; +} + + + + +static int +parse_key( IOBUF inp, int pkttype, unsigned long pktlen, + byte *hdr, int hdrlen, PACKET *pkt ) +{ + int i, version, algorithm; + unsigned n; + unsigned long timestamp, expiredate; + int npkey, nskey; + int is_v4=0; + int rc=0; + + trace(); + + version = iobuf_get_noeof(inp); pktlen--; + if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) { + /* early versions of G10 use old PGP comments packets; + * luckily all those comments are started by a hash */ +// if( list_mode ) { +// printf(":rfc1991 comment packet: \"" ); +// for( ; pktlen; pktlen-- ) { +// int c; +// c = iobuf_get_noeof(inp); +// if( c >= ' ' && c <= 'z' ) +// putchar(c); +// else +// printf("\\x%02x", c ); +// } +// printf("\"\n"); +// } + skip_rest(inp, pktlen); + return 0; + } + else if( version == 4 ) + is_v4=1; + else if( version != 2 && version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, version); + goto leave; + } + + if( pktlen < 11 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + + timestamp = read_32(inp); pktlen -= 4; + if( is_v4 ) + expiredate = 0; /* have to get it from the selfsignature */ + else { + unsigned short ndays; + ndays = read_16(inp); pktlen -= 2; + if( ndays ) + expiredate = timestamp + ndays * 86400L; + else + expiredate = 0; + } + algorithm = iobuf_get_noeof(inp); pktlen--; +// if( list_mode ) +// printf(":%s key packet:\n" +// "\tversion %d, algo %d, created %lu, expires %lu\n", +// pkttype == PKT_PUBLIC_KEY? "public" : +// pkttype == PKT_SECRET_KEY? "secret" : +// pkttype == PKT_PUBLIC_SUBKEY? "public sub" : +// pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??", +// version, algorithm, timestamp, expiredate ); + + if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = pkt->pkt.secret_key; + + sk->timestamp = timestamp; + sk->expiredate = expiredate; + sk->hdrbytes = hdrlen; + sk->version = version; + sk->is_primary = pkttype == PKT_SECRET_KEY; + sk->pubkey_algo = algorithm; + sk->pubkey_usage = 0; /* not yet used */ + } + else { + PKT_public_key *pk = pkt->pkt.public_key; + + pk->timestamp = timestamp; + pk->expiredate = expiredate; + pk->hdrbytes = hdrlen; + pk->version = version; + pk->pubkey_algo = algorithm; + pk->pubkey_usage = 0; /* not yet used */ + pk->keyid[0] = 0; + pk->keyid[1] = 0; + } + nskey = pubkey_get_nskey( algorithm ); + npkey = pubkey_get_npkey( algorithm ); + if( !npkey ) { +// if( list_mode ) +// printf("\tunknown algorithm %d\n", algorithm ); + unknown_pubkey_warning( algorithm ); + } + + + if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = pkt->pkt.secret_key; + byte temp[16]; + + if( !npkey ) { + sk->skey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; + goto leave; + } + + for(i=0; i < npkey; i++ ) { + n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; +// if( list_mode ) { +// printf( "\tskey[%d]: ", i); +// mpi_print(stdout, sk->skey[i], mpi_print_mode ); +// putchar('\n'); +// } + } + sk->protect.algo = iobuf_get_noeof(inp); pktlen--; + if( sk->protect.algo ) { + sk->is_protected = 1; + sk->protect.s2k.count = 0; + if( sk->protect.algo == 255 ) { + if( pktlen < 3 ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + sk->protect.algo = iobuf_get_noeof(inp); pktlen--; + sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--; + sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--; + switch( sk->protect.s2k.mode ) { + case 1: + case 3: + for(i=0; i < 8 && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); + memcpy(sk->protect.s2k.salt, temp, 8 ); + break; + } + switch( sk->protect.s2k.mode ) { + case 0: // if( list_mode ) printf( "\tsimple S2K" ); + break; + case 1: // if( list_mode ) printf( "\tsalted S2K" ); + break; + case 3: // if( list_mode ) printf( "\titer+salt S2K" ); + break; + default: +// if( list_mode ) +// printf( "\tunknown S2K %d\n", +// sk->protect.s2k.mode ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + +// if( list_mode ) { +// printf(", algo: %d, hash: %d", +// sk->protect.algo, +// sk->protect.s2k.hash_algo ); +// if( sk->protect.s2k.mode == 1 +// || sk->protect.s2k.mode == 3 ) { +// printf(", salt: "); +// for(i=0; i < 8; i++ ) +// printf("%02x", sk->protect.s2k.salt[i]); +// } +// putchar('\n'); +// } + + if( sk->protect.s2k.mode == 3 ) { + if( pktlen < 1 ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + sk->protect.s2k.count = iobuf_get(inp); + pktlen--; +// if( list_mode ) +// printf("\tprotect count: %lu\n", +// (ulong)sk->protect.s2k.count); + } + } + else { /* old version; no S2K, so we set mode to 0, hash MD5 */ + sk->protect.s2k.mode = 0; + sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5; +// if( list_mode ) +// printf( "\tprotect algo: %d (hash algo: %d)\n", +// sk->protect.algo, sk->protect.s2k.hash_algo ); + } + /* It is really ugly that we don't know the size + * of the IV here in cases we are not aware of the algorithm. + * so a + * sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo); + * won't work. The only solution I see is to hardwire it here. + * NOTE: if you change the ivlen above 16, don't forget to + * enlarge temp. + */ + switch( sk->protect.algo ) { + case 7: case 8: case 9: /* reserved for AES */ + case 10: /* Twofish */ + sk->protect.ivlen = 16; + break; + default: + sk->protect.ivlen = 8; + } + if( pktlen < sk->protect.ivlen ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); +// if( list_mode ) { +// printf( "\tprotect IV: "); +// for(i=0; i < sk->protect.ivlen; i++ ) +// printf(" %02x", temp[i] ); +// putchar('\n'); +// } + memcpy(sk->protect.iv, temp, sk->protect.ivlen ); + } + else + sk->is_protected = 0; + /* It does not make sense to read it into secure memory. + * If the user is so careless, not to protect his secret key, + * we can assume, that he operates an open system :=(. + * So we put the key into secure memory when we unprotect it. */ + if( is_v4 && sk->is_protected ) { + /* ugly; the length is encrypted too, so we read all + * stuff up to the end of the packet into the first + * skey element */ + sk->skey[npkey] = mpi_set_opaque(NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; +// if( list_mode ) { +// printf("\tencrypted stuff follows\n"); +// } + } + else { /* v3 method: the mpi length is not encrypted */ + for(i=npkey; i < nskey; i++ ) { + n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; + if( sk->is_protected ) + mpi_set_protect_flag(sk->skey[i]); +// if( list_mode ) { +// printf( "\tskey[%d]: ", i); +// if( sk->is_protected ) +// printf( "[encrypted]\n"); +// else { +// mpi_print(stdout, sk->skey[i], mpi_print_mode ); +// putchar('\n'); +// } +// } + } + + sk->csum = read_16(inp); pktlen -= 2; +// if( list_mode ) { +// printf("\tchecksum: %04hx\n", sk->csum); +// } + } + } + else { + PKT_public_key *pk = pkt->pkt.public_key; + + if( !npkey ) { + pk->pkey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; + goto leave; + } + + for(i=0; i < npkey; i++ ) { + n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; +// if( list_mode ) { +// printf( "\tpkey[%d]: ", i); +// mpi_print(stdout, pk->pkey[i], mpi_print_mode ); +// putchar('\n'); +// } + } + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + + +static int +parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + + trace(); + + packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); + packet->pkt.user_id->len = pktlen; + packet->pkt.user_id->photo = NULL; + packet->pkt.user_id->photolen = 0; + p = packet->pkt.user_id->name; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + *p = 0; + +// if( list_mode ) { +// int n = packet->pkt.user_id->len; +// printf(":user ID packet: \""); +// /* fixme: Hey why don't we replace this wioth print_string?? */ +// for(p=packet->pkt.user_id->name; n; p++, n-- ) { +// if( *p >= ' ' && *p <= 'z' ) +// putchar(*p); +// else +// printf("\\x%02x", *p ); +// } +// printf("\"\n"); +// } + return 0; +} + + +/**************** + * PGP generates a packet of type 17. We assume this is a photo ID and + * simply store it here as a comment packet. + */ +static int +parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ +// byte *p; +// +// packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 30); +// sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen ); +// packet->pkt.user_id->len = strlen(packet->pkt.user_id->name); +// +// packet->pkt.user_id->photo = m_alloc(sizeof *packet->pkt.user_id + pktlen); +// packet->pkt.user_id->photolen = pktlen; +// p = packet->pkt.user_id->photo; +// for( ; pktlen; pktlen--, p++ ) +// *p = iobuf_get_noeof(inp); +// +// if( list_mode ) { +// printf(":photo_id packet: %s\n", packet->pkt.user_id->name ); +// } + trace(); + + return 0; +} + + +static int +parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + + trace(); + + packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1); + packet->pkt.comment->len = pktlen; + p = packet->pkt.comment->data; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + +// if( list_mode ) { +// int n = packet->pkt.comment->len; +// printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT? +// "OpenPGP draft " : "" ); +// for(p=packet->pkt.comment->data; n; p++, n-- ) { +// if( *p >= ' ' && *p <= 'z' ) +// putchar(*p); +// else +// printf("\\x%02x", *p ); +// } +// printf("\"\n"); +// } + return 0; +} + + +static void +parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) +{ + int c; + + trace(); + + c = iobuf_get_noeof(inp); + pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust ); + pkt->pkt.ring_trust->trustval = c; +// if( list_mode ) +// printf(":trust packet: flag=%02x\n", c ); +} + + +static int +parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + int mode, namelen; + PKT_plaintext *pt; +// byte *p; + int c, i; + + trace(); + + if( pktlen && pktlen < 6 ) { + log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); + goto leave; + } + mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1); + pt->new_ctb = new_ctb; + pt->mode = mode; + pt->namelen = namelen; + if( pktlen ) { + for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ ) + pt->name[i] = iobuf_get_noeof(inp); + } + else { + for( i=0; i < namelen; i++ ) + if( (c=iobuf_get(inp)) == -1 ) + break; + else + pt->name[i] = c; + } + pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4; + pt->len = pktlen; + pt->buf = inp; + pktlen = 0; + +// if( list_mode ) { +// printf(":literal data packet:\n" +// "\tmode %c, created %lu, name=\"", +// mode >= ' ' && mode <'z'? mode : '?', +// (ulong)pt->timestamp ); +// for(p=pt->name,i=0; i < namelen; p++, i++ ) { +// if( *p >= ' ' && *p <= 'z' ) +// putchar(*p); +// else +// printf("\\x%02x", *p ); +// } +// printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len ); +// } + + leave: + return 0; +} + + +static int +parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + PKT_compressed *zd; + + trace(); + + /* pktlen is here 0, but data follows + * (this should be the last object in a file or + * the compress algorithm should know the length) + */ + zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); + zd->len = 0; /* not yet used */ + zd->algorithm = iobuf_get_noeof(inp); + zd->new_ctb = new_ctb; + zd->buf = inp; +// if( list_mode ) +// printf(":compressed packet: algo=%d\n", zd->algorithm); + return 0; +} + + +static int +parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + PKT_encrypted *ed; + + trace(); + + ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); + ed->len = pktlen; + ed->buf = NULL; + ed->new_ctb = new_ctb; + ed->mdc_method = 0; + if( pkttype == PKT_ENCRYPTED_MDC ) { + /* test: this is the new encrypted_mdc packet */ + /* fixme: add some pktlen sanity checks */ + int version, method; + + version = iobuf_get_noeof(inp); pktlen--; + if( version != 1 ) { + log_error("encrypted_mdc packet with unknown version %d\n", + version); + goto leave; + } + method = iobuf_get_noeof(inp); pktlen--; + if( method != DIGEST_ALGO_SHA1 ) { + log_error("encrypted_mdc does not use SHA1 method\n" ); + goto leave; + } + ed->mdc_method = method; + } + if( pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */ + log_error("packet(%d) too short\n", pkttype); + skip_rest(inp, pktlen); + goto leave; + } +// if( list_mode ) { +// if( pktlen ) +// printf(":encrypted data packet:\n\tlength: %lu\n", pktlen); +// else +// printf(":encrypted data packet:\n\tlength: unknown\n"); +// if( ed->mdc_method ) +// printf("\tmdc_method: %d\n", ed->mdc_method ); +// } + + ed->buf = inp; + pktlen = 0; + + leave: + return 0; +} + diff -Nru a/security/cryptomark/gnupg/pkclist.c b/security/cryptomark/gnupg/pkclist.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/pkclist.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1040 @@ +/* pkclist.c + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" +//#include +//#include +//#include +//#include +//#include +//#include + +#include "options.h" +#include "packet.h" +#include "errors.h" +#include "keydb.h" +#include "memory.h" +#include "util.h" +#include "trustdb.h" +#include "ttyio.h" +#include "status.h" +#include "i18n.h" + + +//#define CONTROL_D ('D' - 'A' + 1) +// +///* fixme: we have nearly the same code in keyedit.c */ +//static void +//print_fpr( PKT_public_key *pk ) +//{ +// byte array[MAX_FINGERPRINT_LEN], *p; +// size_t i, n; +// +// fingerprint_from_pk( pk, array, &n ); +// p = array; +// /* Translators: this shoud fit into 24 bytes to that the fingerprint +// * data is properly aligned with the user ID */ +// tty_printf(_(" Fingerprint:")); +// if( n == 20 ) { +// for(i=0; i < n ; i++, i++, p += 2 ) { +// if( i == 10 ) +// tty_printf(" "); +// tty_printf(" %02X%02X", *p, p[1] ); +// } +// } +// else { +// for(i=0; i < n ; i++, p++ ) { +// if( i && !(i%8) ) +// tty_printf(" "); +// tty_printf(" %02X", *p ); +// } +// } +// tty_printf("\n"); +//} +// +//static void +//fpr_info( PKT_public_key *pk ) +//{ +// byte array[MAX_FINGERPRINT_LEN], *p; +// size_t i, n; +// FILE *fp = log_stream(); +// +// fingerprint_from_pk( pk, array, &n ); +// p = array; +// log_info(_("Fingerprint:")); +// if( n == 20 ) { +// for(i=0; i < n ; i++, i++, p += 2 ) { +// if( i == 10 ) +// putc(' ', fp); +// fprintf(fp, " %02X%02X", *p, p[1] ); +// } +// } +// else { +// for(i=0; i < n ; i++, p++ ) { +// if( i && !(i%8) ) +// putc(' ', fp); +// fprintf(fp, " %02X", *p ); +// } +// } +// putc('\n', fp ); +//} +// +// +// +//static void +//show_paths( ulong lid, int only_first ) +//{ +// void *context = NULL; +// unsigned otrust, validity; +// int last_level, level; +// +// last_level = 0; +// while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){ +// char *p; +// int c, rc; +// size_t n; +// u32 keyid[2]; +// PKT_public_key *pk ; +// +// if( level < last_level && only_first ) +// break; +// last_level = level; +// +// rc = keyid_from_lid( lid, keyid ); +// if( rc ) { +// log_error("ooops: can't get keyid for lid %lu\n", lid); +// return; +// } +// +// pk = m_alloc_clear( sizeof *pk ); +// rc = get_pubkey( pk, keyid ); +// if( rc ) { +// log_error("key %08lX: public key not found: %s\n", +// (ulong)keyid[1], g10_errstr(rc) ); +// return; +// } +// +// tty_printf("%*s%4u%c/%08lX.%lu %s \"", +// level*2, "", +// nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), +// (ulong)keyid[1], lid, datestr_from_pk( pk ) ); +// +// c = trust_letter(otrust); +// if( c ) +// putchar( c ); +// else +// printf( "%02x", otrust ); +// putchar('/'); +// c = trust_letter(validity); +// if( c ) +// putchar( c ); +// else +// printf( "%02x", validity ); +// putchar(' '); +// +// p = get_user_id( keyid, &n ); +// tty_print_utf8_string( p, n ), +// m_free(p); +// tty_printf("\"\n"); +// free_public_key( pk ); +// } +// enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */ +// tty_printf("\n"); +//} +// +// +// +// +///**************** +// * Returns true if an ownertrust has changed. +// */ +//static int +//do_edit_ownertrust( ulong lid, int mode, unsigned *new_trust, int defer_help ) +//{ +// char *p; +// int rc; +// size_t n; +// u32 keyid[2]; +// PKT_public_key *pk ; +// int changed=0; +// int quit=0; +// int show=0; +// int did_help=defer_help; +// +// rc = keyid_from_lid( lid, keyid ); +// if( rc ) { +// log_error("ooops: can't get keyid for lid %lu\n", lid); +// return 0; +// } +// +// pk = m_alloc_clear( sizeof *pk ); +// rc = get_pubkey( pk, keyid ); +// if( rc ) { +// log_error("key %08lX: public key not found: %s\n", +// (ulong)keyid[1], g10_errstr(rc) ); +// return 0; +// } +// +// +// for(;;) { +// /* a string with valid answers */ +// const char *ans = _("sSmMqQ"); +// +// if( !did_help ) { +// if( !mode ) { +// tty_printf(_("No trust value assigned to %lu:\n" +// "%4u%c/%08lX %s \""), lid, +// nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), +// (ulong)keyid[1], datestr_from_pk( pk ) ); +// p = get_user_id( keyid, &n ); +// tty_print_utf8_string( p, n ), +// m_free(p); +// tty_printf("\"\n"); +// print_fpr( pk ); +// tty_printf("\n"); +// } +// tty_printf(_( +//"Please decide how far you trust this user to correctly\n" +//"verify other users' keys (by looking at passports,\n" +//"checking fingerprints from different sources...)?\n\n" +//" 1 = Don't know\n" +//" 2 = I do NOT trust\n" +//" 3 = I trust marginally\n" +//" 4 = I trust fully\n" +//" s = please show me more information\n") ); +// if( mode ) +// tty_printf(_(" m = back to the main menu\n")); +// else +// tty_printf(_(" q = quit\n")); +// tty_printf("\n"); +// did_help = 1; +// } +// if( strlen(ans) != 6 ) +// BUG(); +// p = cpr_get("edit_ownertrust.value",_("Your decision? ")); +// trim_spaces(p); +// cpr_kill_prompt(); +// if( !*p ) +// did_help = 0; +// else if( *p && p[1] ) +// ; +// else if( !p[1] && (*p >= '1' && *p <= '4') ) { +// unsigned trust; +// switch( *p ) { +// case '1': trust = TRUST_UNDEFINED; break; +// case '2': trust = TRUST_NEVER ; break; +// case '3': trust = TRUST_MARGINAL ; break; +// case '4': trust = TRUST_FULLY ; break; +// default: BUG(); +// } +// *new_trust = trust; +// changed = 1; +// break; +// } +// else if( *p == ans[0] || *p == ans[1] ) { +// tty_printf(_( +// "Certificates leading to an ultimately trusted key:\n")); +// show = 1; +// break; +// } +// else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) { +// break ; /* back to the menu */ +// } +// else if( !mode && (*p == ans[4] || *p == ans[5] ) ) { +// quit = 1; +// break ; /* back to the menu */ +// } +// m_free(p); p = NULL; +// } +// m_free(p); +// m_free(pk); +// return show? -2: quit? -1 : changed; +//} +// +// +//int +//edit_ownertrust( ulong lid, int mode ) +//{ +// unsigned int trust; +// int no_help = 0; +// +// for(;;) { +// switch( do_edit_ownertrust( lid, mode, &trust, no_help ) ) { +// case -1: +// return 0; +// case -2: +// show_paths( lid, 1 ); +// no_help = 1; +// break; +// case 1: +// trust &= ~TRUST_FLAG_DISABLED; +// trust |= get_ownertrust( lid ) & TRUST_FLAG_DISABLED; +// if( !update_ownertrust( lid, trust ) ) +// return 1; +// return 0; +// default: +// return 0; +// } +// } +//} +// +//static int +//add_ownertrust_cb( ulong lid ) +//{ +// unsigned trust; +// int rc = do_edit_ownertrust( lid, 0, &trust, 0 ); +// +// if( rc == 1 ) +// return trust & TRUST_MASK; +// return rc > 0? 0 : rc; +//} +// +///**************** +// * Try to add some more owner trusts (interactive) +// * This function presents all the signator in a certificate +// * chain who have no ownertrust value assigned. +// * Returns: -1 if no ownertrust were added. +// */ +//static int +//add_ownertrust( PKT_public_key *pk, int *quit, unsigned *trustlevel ) +//{ +// int rc; +// unsigned flags = 0; +// +// *quit = 0; +// *trustlevel = 0; +// tty_printf("Could not find a valid trust path to the key. Let's see whether we\n" +// "can assign some missing owner trust values.\n\n"); +// +// rc = check_trust( pk, trustlevel, NULL, add_ownertrust_cb, &flags ); +// +// if( !(flags & 1) ) +// tty_printf("No path leading to one of our keys found.\n\n"); +// else if( !(flags & 2) ) +// tty_printf("No certificates with undefined trust found.\n\n"); +// else if( !(flags & 4) ) +// tty_printf("No trust values changed.\n\n"); +// +// return (flags & 4)? 0:-1; +//} +// +///**************** +// * Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL +// * Returns: true if we trust. Might change the trustlevel +// */ +//static int +//do_we_trust( PKT_public_key *pk, int *trustlevel ) +//{ +// int rc; +// int did_add = 0; +// int trustmask = 0; +// +// retry: +// if( (*trustlevel & TRUST_FLAG_REVOKED) ) { +// log_info(_("key %08lX: key has been revoked!\n"), +// (ulong)keyid_from_pk( pk, NULL) ); +// if( opt.batch ) +// return 0; +// +// if( !cpr_get_answer_is_yes("revoked_key.override", +// _("Use this key anyway? ")) ) +// return 0; +// trustmask |= TRUST_FLAG_REVOKED; +// } +// else if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) { +// log_info(_("key %08lX: subkey has been revoked!\n"), +// (ulong)keyid_from_pk( pk, NULL) ); +// if( opt.batch ) +// return 0; +// +// if( !cpr_get_answer_is_yes("revoked_key.override", +// _("Use this key anyway? ")) ) +// return 0; +// trustmask |= TRUST_FLAG_SUB_REVOKED; +// } +// *trustlevel &= ~trustmask; +// +// +// switch( (*trustlevel & TRUST_MASK) ) { +// case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */ +// rc = insert_trust_record_by_pk( pk ); +// if( rc ) { +// log_error("failed to insert it into the trustdb: %s\n", +// g10_errstr(rc) ); +// return 0; /* no */ +// } +// rc = check_trust( pk, trustlevel, NULL, NULL, NULL ); +// *trustlevel &= ~trustmask; +// if( rc ) +// log_fatal("trust check after insert failed: %s\n", +// g10_errstr(rc) ); +// if( *trustlevel == TRUST_UNKNOWN || *trustlevel == TRUST_EXPIRED ) { +// log_debug("do_we_trust: oops at %d\n", __LINE__ ); +// return 0; +// } +// return do_we_trust( pk, trustlevel ); +// +// case TRUST_EXPIRED: +// log_info(_("%08lX: key has expired\n"), +// (ulong)keyid_from_pk( pk, NULL) ); +// return 0; /* no */ +// +// case TRUST_UNDEFINED: +// if( opt.batch || opt.answer_no ) +// log_info(_("%08lX: no info to calculate a trust probability\n"), +// (ulong)keyid_from_pk( pk, NULL) ); +// else { +// int quit; +// +// rc = add_ownertrust( pk, &quit, trustlevel ); +// *trustlevel &= ~trustmask; +// if( !rc && !did_add && !quit ) { +// did_add = 1; +// goto retry; +// } +// } +// return 0; +// +// case TRUST_NEVER: +// log_info(_("%08lX: We do NOT trust this key\n"), +// (ulong)keyid_from_pk( pk, NULL) ); +// return 0; /* no */ +// +// case TRUST_MARGINAL: +// log_info( +// _("%08lX: It is not sure that this key really belongs to the owner\n" +// "but it is accepted anyway\n"), (ulong)keyid_from_pk( pk, NULL) ); +// return 1; /* yes */ +// +// case TRUST_FULLY: +// if( opt.verbose ) +// log_info(_("This key probably belongs to the owner\n")); +// return 1; /* yes */ +// +// case TRUST_ULTIMATE: +// if( opt.verbose ) +// log_info(_("This key belongs to us\n")); +// return 1; /* yes */ +// +// default: BUG(); +// } +// +// return 1; /* yes */ +//} +// +// +// +///**************** +// * wrapper around do_we_trust, so we can ask whether to use the +// * key anyway. +// */ +//static int +//do_we_trust_pre( PKT_public_key *pk, int trustlevel ) +//{ +// int rc; +// +// rc = do_we_trust( pk, &trustlevel ); +// +// if( (trustlevel & TRUST_FLAG_REVOKED) && !rc ) +// return 0; +// if( (trustlevel & TRUST_FLAG_SUB_REVOKED) && !rc ) +// return 0; +// else if( !opt.batch && !rc ) { +// char *p; +// u32 keyid[2]; +// size_t n; +// +// keyid_from_pk( pk, keyid); +// tty_printf( "%4u%c/%08lX %s \"", +// nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), +// (ulong)keyid[1], datestr_from_pk( pk ) ); +// p = get_user_id( keyid, &n ); +// tty_print_utf8_string( p, n ), +// m_free(p); +// tty_printf("\"\n"); +// print_fpr( pk ); +// tty_printf("\n"); +// +// tty_printf(_( +//"It is NOT certain that the key belongs to its owner.\n" +//"If you *really* know what you are doing, you may answer\n" +//"the next question with yes\n\n") ); +// +// if( cpr_get_answer_is_yes("untrusted_key.override", +// _("Use this key anyway? ")) ) +// rc = 1; +// +// /* Hmmm: Should we set a flag to tell the user the user about +// * his decision the next time he encrypts for this recipient? +// */ +// } +// else if( opt.always_trust && !rc ) { +// if( !opt.quiet ) +// log_info(_("WARNING: Using untrusted key!\n")); +// rc = 1; +// } +// return rc; +//} +// + + +/**************** + * Check whether we can trust this signature. + * Returns: Error if we shall not trust this signatures. + */ +int +check_signatures_trust( PKT_signature *sig ) +{ + trace(); + +// PKT_public_key *pk = m_alloc_clear( sizeof *pk ); +// int trustlevel; +// int did_add = 0; +// int rc=0; + + +// if( opt.always_trust ) { +// if( !opt.quiet ) + log_info("WARNING: Using untrusted key!\n"); + return 0; +// } +// +// +// rc = get_pubkey( pk, sig->keyid ); +// if( rc ) { /* this should not happen */ +// log_error("Ooops; the key vanished - can't check the trust\n"); +// rc = G10ERR_NO_PUBKEY; +// goto leave; +// } +// +// rc = check_trust( pk, &trustlevel, NULL, NULL, NULL ); +// if( rc ) { +// log_error("check trust failed: %s\n", g10_errstr(rc)); +// goto leave; +// } +// +// retry: +// if( (trustlevel & TRUST_FLAG_REVOKED) ) { +// write_status( STATUS_KEYREVOKED ); +// log_info("WARNING: This key has been revoked by its owner!\n"); +// log_info(" This could mean that the signature is forgery.\n"); +// } +// else if( (trustlevel & TRUST_FLAG_SUB_REVOKED) ) { +// write_status( STATUS_KEYREVOKED ); +// log_info("WARNING: This subkey has been revoked by its owner!\n"); +// } +// +// +// switch( (trustlevel & TRUST_MASK) ) { +// case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */ +// rc = insert_trust_record_by_pk( pk ); +// if( rc ) { +// log_error("failed to insert it into the trustdb: %s\n", +// g10_errstr(rc) ); +// goto leave; +// } +// rc = check_trust( pk, &trustlevel, NULL, NULL, NULL ); +// if( rc ) +// log_fatal("trust check after insert failed: %s\n", +// g10_errstr(rc) ); +// if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) +// BUG(); +// goto retry; +// +// case TRUST_EXPIRED: +// log_info("Note: This key has expired!\n"); +//// fpr_info( pk ); +// break; +// +// case TRUST_UNDEFINED: +// if( did_add || opt.batch || opt.answer_no ) { +// write_status( STATUS_TRUST_UNDEFINED ); +// log_info( +// "WARNING: This key is not certified with a trusted signature!\n"); +// log_info( +// " There is no indication that the " +// "signature belongs to the owner.\n" ); +//// fpr_info( pk ); +// } +// else { +// int quit; +// rc = add_ownertrust( pk, &quit, &trustlevel ); +// if( rc || quit ) { +// did_add = 1; +// rc = 0; +// } +// goto retry; +// } +// break; +// +// case TRUST_NEVER: +// write_status( STATUS_TRUST_NEVER ); +// log_info("WARNING: We do NOT trust this key!\n"); +// log_info(" The signature is probably a FORGERY.\n"); +// rc = G10ERR_BAD_SIGN; +// break; +// +// case TRUST_MARGINAL: +// write_status( STATUS_TRUST_MARGINAL ); +// log_info( +// "WARNING: This key is not certified with sufficiently trusted signatures!\n" +// ); +// log_info( +// " It is not certain that the signature belongs to the owner.\n" +// ); +//// fpr_info( pk ); +// break; +// +// case TRUST_FULLY: +// write_status( STATUS_TRUST_FULLY ); +// break; +// +// case TRUST_ULTIMATE: +// write_status( STATUS_TRUST_ULTIMATE ); +// break; +// +// default: BUG(); +// } +// +// +// leave: +// free_public_key( pk ); +// return rc; +} + + +//void +//release_pk_list( PK_LIST pk_list ) +//{ +// PK_LIST pk_rover; +// +// for( ; pk_list; pk_list = pk_rover ) { +// pk_rover = pk_list->next; +// free_public_key( pk_list->pk ); +// m_free( pk_list ); +// } +//} +// +// +//static int +//key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk) +//{ +// for( ; pk_list; pk_list = pk_list->next) +// if (cmp_public_keys(pk_list->pk, pk) == 0) +// return 0; +// +// return -1; +//} +// +// +///**************** +// * Return a malloced string with a default reciepient if there is any +// */ +//static char * +//default_recipient(void) +//{ +// PKT_secret_key *sk; +// byte fpr[MAX_FINGERPRINT_LEN+1]; +// size_t n; +// char *p; +// int i; +// +// if( opt.def_recipient ) +// return m_strdup( opt.def_recipient ); +// if( !opt.def_recipient_self ) +// return NULL; +// sk = m_alloc_clear( sizeof *sk ); +// i = get_seckey_byname( sk, NULL, 0 ); +// if( i ) { +// free_secret_key( sk ); +// return NULL; +// } +// n = MAX_FINGERPRINT_LEN; +// fingerprint_from_sk( sk, fpr, &n ); +// free_secret_key( sk ); +// p = m_alloc( 2*n+3 ); +// *p++ = '0'; +// *p++ = 'x'; +// for(i=0; i < n; i++ ) +// sprintf( p+2*i, "%02X", fpr[i] ); +// p -= 2; +// return p; +//} +// +// +//int +//build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) +//{ +// PK_LIST pk_list = NULL; +// PKT_public_key *pk=NULL; +// int rc=0; +// int any_recipients=0; +// STRLIST rov; +// char *def_rec = NULL; +// +// /* check whether there are any recipients in the list and build the +// * list of the encrypt-to ones (we always trust them) */ +// for( rov = remusr; rov; rov = rov->next ) { +// if( !(rov->flags & 1) ) +// any_recipients = 1; +// else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { +// pk = m_alloc_clear( sizeof *pk ); +// pk->pubkey_usage = use; +// if( (rc = get_pubkey_byname( NULL, pk, rov->d, NULL )) ) { +// free_public_key( pk ); pk = NULL; +// log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); +// } +// else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { +// +// /* Skip the actual key if the key is already present +// * in the list */ +// if (key_present_in_pk_list(pk_list, pk) == 0) { +// free_public_key(pk); pk = NULL; +// log_info(_("%s: skipped: public key already present\n"), +// rov->d); +// } +// else { +// PK_LIST r; +// r = m_alloc( sizeof *r ); +// r->pk = pk; pk = NULL; +// r->next = pk_list; +// r->mark = 0; +// pk_list = r; +// } +// } +// else { +// free_public_key( pk ); pk = NULL; +// log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); +// } +// } +// } +// +// if( !any_recipients && !opt.batch ) { /* ask */ +// char *answer=NULL; +// int have_def_rec; +// +// def_rec = default_recipient(); +// have_def_rec = !!def_rec; +// if( !have_def_rec ) +// tty_printf(_( +// "You did not specify a user ID. (you may use \"-r\")\n\n")); +// for(;;) { +// rc = 0; +// m_free(answer); +// if( have_def_rec ) { +// answer = def_rec; +// def_rec = NULL; +// } +// else { +// answer = cpr_get_utf8("pklist.user_id.enter", +// _("Enter the user ID: ")); +// trim_spaces(answer); +// cpr_kill_prompt(); +// } +// if( !*answer ) +// break; +// if( pk ) +// free_public_key( pk ); +// pk = m_alloc_clear( sizeof *pk ); +// pk->pubkey_usage = use; +// rc = get_pubkey_byname( NULL, pk, answer, NULL ); +// if( rc ) +// tty_printf(_("No such user ID.\n")); +// else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { +// if( have_def_rec ) { +// if (key_present_in_pk_list(pk_list, pk) == 0) { +// free_public_key(pk); pk = NULL; +// log_info(_("skipped: public key " +// "already set as default recipient\n") ); +// } +// else { +// PK_LIST r = m_alloc( sizeof *r ); +// r->pk = pk; pk = NULL; +// r->next = pk_list; +// r->mark = 0; +// pk_list = r; +// } +// any_recipients = 1; +// break; +// } +// else { +// int trustlevel; +// +// rc = check_trust( pk, &trustlevel, pk->namehash, +// NULL, NULL ); +// if( rc ) { +// log_error("error checking pk of `%s': %s\n", +// answer, g10_errstr(rc) ); +// } +// else if( (trustlevel & TRUST_FLAG_DISABLED) ) { +// tty_printf(_("Public key is disabled.\n") ); +// } +// else if( do_we_trust_pre( pk, trustlevel ) ) { +// /* Skip the actual key if the key is already present +// * in the list */ +// if (key_present_in_pk_list(pk_list, pk) == 0) { +// free_public_key(pk); pk = NULL; +// log_info(_("skipped: public key " +// "already set with --encrypt-to\n") ); +// } +// else { +// PK_LIST r; +// +// r = m_alloc( sizeof *r ); +// r->pk = pk; pk = NULL; +// r->next = pk_list; +// r->mark = 0; +// pk_list = r; +// } +// any_recipients = 1; +// break; +// } +// } +// } +// m_free(def_rec); def_rec = NULL; +// have_def_rec = 0; +// } +// m_free(answer); +// if( pk ) { +// free_public_key( pk ); +// pk = NULL; +// } +// } +// else if( !any_recipients && (def_rec = default_recipient()) ) { +// pk = m_alloc_clear( sizeof *pk ); +// pk->pubkey_usage = use; +// rc = get_pubkey_byname( NULL, pk, def_rec, NULL ); +// if( rc ) +// log_error(_("unknown default recipient `%s'\n"), def_rec ); +// else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { +// PK_LIST r = m_alloc( sizeof *r ); +// r->pk = pk; pk = NULL; +// r->next = pk_list; +// r->mark = 0; +// pk_list = r; +// any_recipients = 1; +// } +// if( pk ) { +// free_public_key( pk ); +// pk = NULL; +// } +// m_free(def_rec); def_rec = NULL; +// } +// else { +// any_recipients = 0; +// for(; remusr; remusr = remusr->next ) { +// if( (remusr->flags & 1) ) +// continue; /* encrypt-to keys are already handled */ +// +// pk = m_alloc_clear( sizeof *pk ); +// pk->pubkey_usage = use; +// if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) { +// free_public_key( pk ); pk = NULL; +// log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); +// } +// else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { +// int trustlevel; +// +// rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL ); +// if( rc ) { +// free_public_key( pk ); pk = NULL; +// log_error(_("%s: error checking key: %s\n"), +// remusr->d, g10_errstr(rc) ); +// } +// else if( (trustlevel & TRUST_FLAG_DISABLED) ) { +// free_public_key(pk); pk = NULL; +// log_info(_("%s: skipped: public key is disabled\n"), +// remusr->d); +// } +// else if( do_we_trust_pre( pk, trustlevel ) ) { +// /* note: do_we_trust may have changed the trustlevel */ +// +// /* We have at least one valid recipient. It doesn't matters +// * if this recipient is already present. */ +// any_recipients = 1; +// +// /* Skip the actual key if the key is already present +// * in the list */ +// if (key_present_in_pk_list(pk_list, pk) == 0) { +// free_public_key(pk); pk = NULL; +// log_info(_("%s: skipped: public key already present\n"), +// remusr->d); +// } +// else { +// PK_LIST r; +// r = m_alloc( sizeof *r ); +// r->pk = pk; pk = NULL; +// r->next = pk_list; +// r->mark = 0; +// pk_list = r; +// } +// } +// else { /* we don't trust this pk */ +// free_public_key( pk ); pk = NULL; +// } +// } +// else { +// free_public_key( pk ); pk = NULL; +// log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); +// } +// } +// } +// +// if( !rc && !any_recipients ) { +// log_error(_("no valid addressees\n")); +// rc = G10ERR_NO_USER_ID; +// } +// +// if( rc ) +// release_pk_list( pk_list ); +// else +// *ret_pk_list = pk_list; +// return rc; +//} +// +// +// +//static int +//algo_available( int preftype, int algo ) +//{ +// if( preftype == PREFTYPE_SYM ) { +// if( algo == CIPHER_ALGO_TWOFISH ) +// return 0; /* we don't want to generate Twofish messages for now*/ +// return algo && !check_cipher_algo( algo ); +// } +// else if( preftype == PREFTYPE_HASH ) { +// return algo && !check_digest_algo( algo ); +// } +// else if( preftype == PREFTYPE_COMPR ) { +// return !algo || algo == 1 || algo == 2; +// } +// else +// return 0; +//} +// +///**************** +// * Return -1 if we could not find an algorithm. +// */ +//int +//select_algo_from_prefs( PK_LIST pk_list, int preftype ) +//{ +// PK_LIST pkr; +// u32 bits[8]; +// byte *pref = NULL; +// size_t npref; +// int i, j; +// int compr_hack=0; +// int any; +// +// if( !pk_list ) +// return -1; +// +// memset( bits, ~0, 8 * sizeof *bits ); +// for( pkr = pk_list; pkr; pkr = pkr->next ) { +// u32 mask[8]; +// +// memset( mask, 0, 8 * sizeof *mask ); +// if( !pkr->pk->local_id ) { /* try to set the local id */ +// query_trust_info( pkr->pk, NULL ); +// if( !pkr->pk->local_id ) { +// log_debug("select_algo_from_prefs: can't get LID\n"); +// continue; +// } +// } +// if( preftype == PREFTYPE_SYM ) +// mask[0] |= (1<<2); /* 3DES is implicitly there */ +// m_free(pref); +// pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref); +// any = 0; +// if( pref ) { +// #if 0 +// log_hexdump("raw: ", pref, npref ); +// #endif +// for(i=0; i+1 < npref; i+=2 ) { +// if( pref[i] == preftype ) { +// mask[pref[i+1]/32] |= 1 << (pref[i+1]%32); +// any = 1; +// } +// } +// } +// if( (!pref || !any) && preftype == PREFTYPE_COMPR ) { +// mask[0] |= 3; /* asume no_compression and old pgp */ +// compr_hack = 1; +// } +// +// #if 0 +// log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", +// (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4], +// (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]); +// #endif +// for(i=0; i < 8; i++ ) +// bits[i] &= mask[i]; +// #if 0 +// log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", +// (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4], +// (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]); +// #endif +// } +// /* usable algorithms are now in bits +// * We now use the last key from pk_list to select +// * the algorithm we want to use. there are no +// * preferences for the last key, we select the one +// * corresponding to first set bit. +// */ +// i = -1; +// any = 0; +// if( pref ) { +// for(j=0; j+1 < npref; j+=2 ) { +// if( pref[j] == preftype ) { +// if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) { +// if( algo_available( preftype, pref[j+1] ) ) { +// any = 1; +// i = pref[j+1]; +// break; +// } +// } +// } +// } +// } +// if( !pref || !any ) { +// for(j=0; j < 256; j++ ) +// if( (bits[j/32] & (1<<(j%32))) ) { +// if( algo_available( preftype, j ) ) { +// i = j; +// break; +// } +// } +// } +// #if 0 +// log_debug("prefs of type %d: selected %d\n", preftype, i ); +// #endif +// if( compr_hack && !i ) { +// /* selected no compression, but we should check whether +// * algorithm 1 is also available (the ordering is not relevant +// * in this case). */ +// if( bits[0] & (1<<1) ) +// i = 1; /* yep; we can use compression algo 1 */ +// } +// +// m_free(pref); +// return i; +//} +// +// diff -Nru a/security/cryptomark/gnupg/plaintext.c b/security/cryptomark/gnupg/plaintext.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/plaintext.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,431 @@ +/* plaintext.c - process an plaintext packet + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cryptomark_log.h" + +#include + +#include "util.h" +#include "memory.h" +#include "options.h" +#include "packet.h" +#include "ttyio.h" +#include "filter.h" +#include "main.h" +#include "status.h" +#include "i18n.h" + + + +/**************** + * Handle a plaintext packet. If MFX is not NULL, update the MDs + * Note: we should use the filter stuff here, but we have to add some + * easy mimic to set a read limit, so we calculate only the + * bytes from the plaintext. + */ +int +handle_plaintext_data( PKT_plaintext *pt, md_filter_context_t *mfx, + int nooutput, int clearsig, unsigned char **data ) +{ +// char *fname = NULL; +// FILE *fp = NULL; + int rc = 0; + int c; + int convert = pt->mode == 't'; + + trace(); + + /* create the filename as C string */ + if( nooutput ) + ; +// else if( opt.outfile ) { +// fname = m_alloc( strlen( opt.outfile ) + 1); +// strcpy(fname, opt.outfile ); +// } +// else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) { +// log_info(_("data not saved; use option \"--output\" to save it\n")); +// nooutput = 1; +// } +// else if( !opt.use_embedded_filename ) { +// fname = make_outfile_name( iobuf_get_real_fname(pt->buf) ); +// if( !fname ) +// fname = ask_outfile_name( pt->name, pt->namelen ); +// if( !fname ) { +// rc = G10ERR_CREATE_FILE; +// goto leave; +// } +// } +// else { +// fname = make_printable_string( pt->name, pt->namelen, 0 ); +// } +// +// if( nooutput ) +// ; +// else if( !*fname || (*fname=='-' && !fname[1])) { +// /* no filename or "-" given; write to stdout */ +// fp = stdout; +// } +// else if( !overwrite_filep( fname ) ) { +// rc = G10ERR_CREATE_FILE; +// goto leave; +// } +// +// if( fp || nooutput ) +// ; +// else if( !(fp = fopen(fname,"wb")) ) { +// log_error("Error creating `%s': %s\n", fname, strerror(errno) ); +// rc = G10ERR_CREATE_FILE; +// goto leave; +// } + + if( pt->len ) { + long i = 0; + + *data = (unsigned char *)kmalloc (pt->len, GFP_KERNEL); + +// greg's failure... +// for( ; pt->len; pt->len-- ) { +// if( (c = iobuf_get(pt->buf)) == -1 ) { +// log_error("Problem reading source (%u bytes remaining)\n", (unsigned)pt->len); +// rc = G10ERR_READ_FILE; +// goto leave; +// } +// (*data)[i] = (unsigned char)c; +// if( mfx->md ) +// md_putc(mfx->md, c); +// if( convert && c == '\r' ) +// continue; /* fixme: this hack might be too simple */ +// ++i; +// } +// } + + +// assert( !clearsig ); + if( convert ) { /* text mode */ + for( ; pt->len; pt->len-- ) { + if( (c = iobuf_get(pt->buf)) == -1 ) { + log_error("Problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); + rc = G10ERR_READ_FILE; + goto leave; + } + (*data)[i] = (unsigned char)c; + if( mfx->md ) + md_putc(mfx->md, c ); + if( c == '\r' ) + continue; /* fixme: this hack might be too simple */ +// if( fp ) { +// if( putc( c, fp ) == EOF ) { +// log_error("Error writing to `%s': %s\n", +// fname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } + } + } + else { /* binary mode */ + byte *buffer = m_alloc( 32768 ); + while( pt->len ) { + int len = pt->len > 32768 ? 32768 : pt->len; + len = iobuf_read( pt->buf, buffer, len ); + if( len == -1 ) { + log_error("Problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); + rc = G10ERR_READ_FILE; + m_free( buffer ); + goto leave; + } + // + memcpy (&((*data)[i]), buffer, len); + i += len; + // + if( mfx->md ) + md_write( mfx->md, buffer, len ); +// if( fp ) { +// if( fwrite( buffer, 1, len, fp ) != len ) { +// log_error("Error writing to `%s': %s\n", +// fname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// m_free( buffer ); +// goto leave; +// } +// } + pt->len -= len; + } + m_free( buffer ); + } + } +// else if( !clearsig ) { +// if( convert ) { /* text mode */ +// while( (c = iobuf_get(pt->buf)) != -1 ) { +// if( mfx->md ) +// md_putc(mfx->md, c ); +// if( convert && c == '\r' ) +// continue; /* fixme: this hack might be too simple */ +// if( fp ) { +// if( putc( c, fp ) == EOF ) { +// log_error("Error writing to `%s': %s\n", +// fname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// } +// } +// else { /* binary mode */ +// byte *buffer = m_alloc( 32768 ); +// int eof; +// for( eof=0; !eof; ) { +// /* Why do we check for len < 32768: +// * If we won´ we would practically read 2 EOFS but +// * the first one has already popped the block_filter +// * off and therefore we don't catch the boundary. +// * Always assume EOF if iobuf_read returns less bytes +// * then requested */ +// int len = iobuf_read( pt->buf, buffer, 32768 ); +// if( len == -1 ) +// break; +// if( len < 32768 ) +// eof = 1; +// if( mfx->md ) +// md_write( mfx->md, buffer, len ); +// if( fp ) { +// if( fwrite( buffer, 1, len, fp ) != len ) { +// log_error("Error writing to `%s': %s\n", +// fname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// m_free( buffer ); +// goto leave; +// } +// } +// } +// m_free( buffer ); +// } +// pt->buf = NULL; +// } +// else { /* clear text signature - don't hash the last cr,lf */ +// int state = 0; +// +// while( (c = iobuf_get(pt->buf)) != -1 ) { +// if( fp ) { +// if( putc( c, fp ) == EOF ) { +// log_error("Error writing to `%s': %s\n", +// fname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// if( !mfx->md ) +// continue; +// if( state == 2 ) { +// md_putc(mfx->md, '\r' ); +// md_putc(mfx->md, '\n' ); +// state = 0; +// } +// if( !state ) { +// if( c == '\r' ) +// state = 1; +// else +// md_putc(mfx->md, c ); +// } +// else if( state == 1 ) { +// if( c == '\n' ) +// state = 2; +// else { +// md_putc(mfx->md, '\r' ); +// if( c == '\r' ) +// state = 1; +// else { +// state = 0; +// md_putc(mfx->md, c ); +// } +// } +// } +// } +// pt->buf = NULL; +// } +// +// if( fp && fp != stdout && fclose(fp) ) { +// log_error("Error closing `%s': %s\n", fname, strerror(errno) ); +// fp = NULL; +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// fp = NULL; + + leave: +// if( fp && fp != stdout ) +// fclose(fp); +// m_free(fname); + return rc; +} + +//static void +//do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode ) +//{ +// text_filter_context_t tfx; +// int c; +// +// if( textmode ) { +// memset( &tfx, 0, sizeof tfx); +// iobuf_push_filter( fp, text_filter, &tfx ); +// } +// if( md2 ) { /* work around a strange behaviour in pgp2 */ +// /* It seems that at least PGP5 converts a single CR to a CR,LF too */ +// int lc = -1; +// while( (c = iobuf_get(fp)) != -1 ) { +// if( c == '\n' && lc == '\r' ) +// md_putc(md2, c); +// else if( c == '\n' ) { +// md_putc(md2, '\r'); +// md_putc(md2, c); +// } +// else if( c != '\n' && lc == '\r' ) { +// md_putc(md2, '\n'); +// md_putc(md2, c); +// } +// else +// md_putc(md2, c); +// +// if( md ) +// md_putc(md, c ); +// lc = c; +// } +// } +// else { +// while( (c = iobuf_get(fp)) != -1 ) { +// if( md ) +// md_putc(md, c ); +// } +// } +//} +// +// +///**************** +// * Ask for the detached datafile and calculate the digest from it. +// * INFILE is the name of the input file. +// */ +//int +//ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, +// const char *inname, int textmode ) +//{ +// char *answer = NULL; +// IOBUF fp; +// int rc = 0; +// +// fp = open_sigfile( inname ); /* open default file */ +// if( !fp && !opt.batch ) { +// int any=0; +// tty_printf(_("Detached signature.\n")); +// do { +// m_free(answer); +// answer = cpr_get("detached_signature.filename", +// _("Please enter name of data file: ")); +// cpr_kill_prompt(); +// if( any && !*answer ) { +// rc = G10ERR_READ_FILE; +// goto leave; +// } +// fp = iobuf_open(answer); +//// if( !fp && errno == ENOENT ) { +//// tty_printf("No such file, try again or hit enter to quit.\n"); +//// any++; +//// } +//// else if( !fp ) { +// if( !fp ) { +//// log_error("can't open `%s': %s\n", answer, strerror(errno) ); +// log_error("can't open `%s'\n", answer); +// rc = G10ERR_READ_FILE; +// goto leave; +// } +// } while( !fp ); +// } +// +// if( !fp ) { +// if( opt.verbose ) { +//// log_info(_("reading stdin ...\n")); +// log_info("reading stdin ...\n"); +// } +// fp = iobuf_open( NULL ); +//// assert(fp); +// } +// do_hash( md, md2, fp, textmode ); +// iobuf_close(fp); +// +// +// leave: +// m_free(answer); +// return rc; +//} +// +// +// +///**************** +// * Hash the given files and append the hash to hash context md. +// * If FILES is NULL, hash stdin. +// */ +//int +//hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, +// const char *sigfilename, int textmode ) +//{ +// IOBUF fp; +// STRLIST sl=NULL; +// +// if( !files ) { +// /* check whether we can open the signed material */ +// fp = open_sigfile( sigfilename ); +// if( fp ) { +// do_hash( md, md2, fp, textmode ); +// iobuf_close(fp); +// return 0; +// } +// /* no we can't (no sigfile) - read signed stuff from stdin */ +// add_to_strlist( &sl, "-"); +// } +// else +// sl = files; +// +// for( ; sl; sl = sl->next ) { +// fp = iobuf_open( sl->d ); +// if( !fp ) { +// log_error(_("can't open signed data `%s'\n"), +// print_fname_stdin(sl->d)); +// if( !files ) +// free_strlist(sl); +// return G10ERR_OPEN_FILE; +// } +// do_hash( md, md2, fp, textmode ); +// iobuf_close(fp); +// } +// +// if( !files ) +// free_strlist(sl); +// return 0; +//} +// +// diff -Nru a/security/cryptomark/gnupg/ringedit.c b/security/cryptomark/gnupg/ringedit.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/ringedit.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,1842 @@ +/* ringedit.c - Function for key ring editing + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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 + */ + + +/**************** + * This module supplies function for: + * + * - Search for a key block (pubkey and all other stuff) and return a + * handle for it. + * + * - Lock/Unlock a key block + * + * - Read a key block into a tree + * + * - Update a key block + * + * - Insert a new key block + * + * - Delete a key block + * + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include /* for truncate */ +//#include +//#ifdef HAVE_LIBGDBM +// #include +//#endif +#include "util.h" +#include "packet.h" +#include "memory.h" +#include "mpi.h" +#include "iobuf.h" +#include "keydb.h" +#include "host2net.h" +#include "options.h" +#include "main.h" +#include "i18n.h" + + + + +struct resource_table_struct { + int used; + int secret; /* this is a secret keyring */ + char *fname; + IOBUF iobuf; + #ifdef HAVE_LIBGDBM + GDBM_FILE dbf; + #endif + enum resource_type rt; + DOTLOCK lockhd; + int is_locked; +}; +typedef struct resource_table_struct RESTBL; + +#define MAX_RESOURCES 10 +static RESTBL resource_table[MAX_RESOURCES]; +static int default_public_resource; +static int default_secret_resource; + +//static int search( PACKET *pkt, KBPOS *kbpos, int secret ); +// +// +//static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf, +// const char *fname ); +//static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); +static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); +//static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); +// +//#ifdef HAVE_LIBGDBM +//static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ); +//static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, +// const byte *fpr, int fprlen ); +//static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ); +//static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root ); +//static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root ); +//#endif +// + +static RESTBL * +check_pos( KBPOS *kbpos ) +{ + trace(); + + if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES ) + return NULL; + if( !resource_table[kbpos->resno].used ) + return NULL; + return resource_table + kbpos->resno; +} + +//#ifdef HAVE_LIBGDBM +//static void +//fatal_gdbm_error( const char *string ) +//{ +// log_fatal("gdbm failed: %s\n", string); +//} +// +//#endif /* HAVE_LIBGDBM */ +// +// +///**************** +// * Hmmm, how to avoid deadlock? They should not happen if everyone +// * locks the key resources in the same order; but who knows. +// * A solution is to use only one lock file in the gnupg homedir but +// * what will happen with key resources which normally don't belong +// * to the gpg homedir? +// */ +//static void +//lock_rentry( RESTBL *rentry ) +//{ +// if( !rentry->lockhd ) { +// rentry->lockhd = create_dotlock( rentry->fname ); +// if( !rentry->lockhd ) +// log_fatal("can't allocate lock for `%s'\n", rentry->fname ); +// rentry->is_locked = 0; +// } +// if( !rentry->is_locked ) { +// if( make_dotlock( rentry->lockhd, -1 ) ) +// log_fatal("can't lock `%s'\n", rentry->fname ); +// rentry->is_locked = 1; +// } +//} +// +//static void +//unlock_rentry( RESTBL *rentry ) +//{ +// if( opt.lock_once ) +// return; +// if( !release_dotlock( rentry->lockhd ) ) +// rentry->is_locked = 0; +//} +// +// +///**************************************************************** +// ****************** public functions **************************** +// ****************************************************************/ +// +///**************** +// * Get the name of the keyrings, start with a sequence number pointing to a 0. +// */ +//const char * +//enum_keyblock_resources( int *sequence, int secret ) +//{ +// int i = *sequence; +// const char *name = NULL; +// +// for(; i < MAX_RESOURCES; i++ ) +// if( resource_table[i].used && !resource_table[i].secret == !secret ) { +// if( resource_table[i].fname ) { +// name = resource_table[i].fname; +// break; +// } +// } +// *sequence = ++i; +// return name; +//} +// +// +// +/**************** + * Register a resource (which currently may only be a keyring file). + * The first keyring which is added by this function is + * created if it does not exist. + * Note: this function may be called before secure memory is + * available. + */ +int +add_keyblock_resource( const char *url, int force, int secret ) +{ + static int any_secret, any_public; + const char *resname = url; + IOBUF iobuf = NULL; + int i; + char *filename = NULL; + int rc = 0; + enum resource_type rt = rt_UNKNOWN; + + + trace(); + + /* Do we have an URL? + * gnupg-gdbm:filename := this is a GDBM resource + * gnupg-ring:filename := this is a plain keyring + * filename := See what is is, but create as plain keyring. + */ + if( strlen( resname ) > 11 ) { + if( !strncmp( resname, "gnupg-ring:", 11 ) ) { + rt = rt_RING; + resname += 11; + } + else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) { + rt = rt_GDBM; + resname += 11; + } + #ifndef HAVE_DRIVE_LETTERS + else if( strchr( resname, ':' ) ) { + log_error("%s: invalid URL\n", url ); + rc = G10ERR_GENERAL; + goto leave; + } + #endif + } + +// if( *resname != '/' ) { /* do tilde expansion etc */ +// if( strchr(resname, '/') ) +// filename = make_filename(resname, NULL); +// else +// filename = make_filename(opt.homedir, resname, NULL); +// } +// else + filename = m_strdup( resname ); + + if( !force ) + force = secret? !any_secret : !any_public; + + for(i=0; i < MAX_RESOURCES; i++ ) + if( !resource_table[i].used ) + break; + if( i == MAX_RESOURCES ) { + rc = G10ERR_RESOURCE_LIMIT; + goto leave; + } + + /* see whether we can determine the filetype */ +// if( rt == rt_UNKNOWN ) { +// FILE *fp = fopen( filename, "rb" ); +// +// if( fp ) { +// u32 magic; +// +// if( fread( &magic, 4, 1, fp) == 1 ) { +// if( magic == 0x13579ace ) +// rt = rt_GDBM; +// else if( magic == 0xce9a5713 ) +// log_error("%s: endianess does not match\n", url ); +// else + rt = rt_RING; +// } +// else /* maybe empty: assume ring */ + rt = rt_RING; +// fclose( fp ); +// } +// else /* no file yet: create ring */ + rt = rt_RING; +// } + + switch( rt ) { + case rt_UNKNOWN: + log_error("%s: unknown resource type\n", url ); + rc = G10ERR_GENERAL; + goto leave; + + case rt_RING: +// iobuf = iobuf_open( filename ); +// if( !iobuf && !force ) { +// rc = G10ERR_OPEN_FILE; +// goto leave; +// } +// +// if( !iobuf ) { +// char *last_slash_in_filename; +// +// last_slash_in_filename = strrchr(filename, '/'); +// *last_slash_in_filename = 0; +// +// if( access(filename, F_OK) ) { +// /* on the first time we try to create the default homedir and +// * in this case the process will be terminated, so that on the +// * next invocation it can read the options file in on startup +// */ +// try_make_homedir( filename ); +// rc = G10ERR_OPEN_FILE; +// goto leave; +// } +// +// *last_slash_in_filename = '/'; +// +// iobuf = iobuf_create( filename ); +// if( !iobuf ) { +// log_error(_("%s: can't create keyring: %s\n"), +// filename, strerror(errno)); +// rc = G10ERR_OPEN_FILE; +// goto leave; +// } +// else { +// #ifndef HAVE_DOSISH_SYSTEM +// if( secret ) { +// if( chmod( filename, S_IRUSR | S_IWUSR ) ) { +// log_error("%s: chmod failed: %s\n", +// filename, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// #endif +// if( !opt.quiet ) +// log_info(_("%s: keyring created\n"), filename ); +// } +// } +// #if HAVE_DOSISH_SYSTEM || 1 +// iobuf_close( iobuf ); +// iobuf = NULL; +// /* must close it again */ +// #endif + break; + + #ifdef HAVE_LIBGDBM + case rt_GDBM: + resource_table[i].dbf = gdbm_open( filename, 0, + force? GDBM_WRCREAT : GDBM_WRITER, + S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | S_IROTH, + fatal_gdbm_error ); + if( !resource_table[i].dbf ) { + log_error("%s: can't open gdbm file: %s\n", + filename, gdbm_strerror(gdbm_errno)); + rc = G10ERR_OPEN_FILE; + goto leave; + } + break; + #endif + + default: + log_error("%s: unsupported resource type\n", url ); + rc = G10ERR_GENERAL; + goto leave; + } + + #ifndef HAVE_DOSISH_SYSTEM + #if 0 /* fixme: check directory permissions and print a warning */ + if( secret ) { + } + #endif + #endif + + /* fixme: avoid duplicate resources */ + resource_table[i].used = 1; + resource_table[i].secret = !!secret; + resource_table[i].fname = m_strdup(filename); + resource_table[i].iobuf = iobuf; + resource_table[i].rt = rt; + if( secret ) + default_secret_resource = i; + else + default_public_resource = i; + + leave: + if( rc ) + //log_error("keyblock resource `%s': %s\n", filename, g10_errstr(rc) ); + log_error("keyblock resource `%s': %d\n", filename, rc ); + else if( secret ) + any_secret = 1; + else + any_public = 1; + m_free( filename ); + return rc; +} + +///**************** +// * Return the resource name of the keyblock associated with KBPOS. +// */ +//const char * +//keyblock_resource_name( KBPOS *kbpos ) +//{ +// RESTBL *rentry; +// +// if( !(rentry = check_pos( kbpos )) || !rentry->fname ) +// log_bug("no name for keyblock resource %d\n", kbpos->resno ); +// return rentry->fname; +//} +// +// +///**************** +// * Get a keyblock handle KBPOS from a filename. This can be used +// * to get a handle for insert_keyblock for a new keyblock. +// * Using a filename of NULL returns the default resource +// */ +//int +//get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ) +//{ +// int i = 0; +// +// if( !filename ) +// i = secret? default_secret_resource : default_public_resource; +// +// for(; i < MAX_RESOURCES; i++ ) { +// if( resource_table[i].used && !resource_table[i].secret == !secret ) { +// /* fixme: dos needs case insensitive file compare */ +// if( !filename || !strcmp( resource_table[i].fname, filename ) ) { +// memset( kbpos, 0, sizeof *kbpos ); +// kbpos->resno = i; +// kbpos->rt = resource_table[i].rt; +// return 0; +// } +// } +// } +// return -1; /* not found */ +//} +// +// +// +///**************** +// * Search a keyblock which starts with the given packet and puts all +// * information into KBPOS, which can be used later to access this key block. +// * This function looks into all registered keyblock sources. +// * PACKET must be a packet with either a secret_key or a public_key +// * +// * This function is intended to check whether a given certificate +// * is already in a keyring or to prepare it for editing. +// * +// * Returns: 0 if found, -1 if not found or an errorcode. +// */ +//static int +//search( PACKET *pkt, KBPOS *kbpos, int secret ) +//{ +// int i, rc, last_rc=-1; +// +// for(i=0; i < MAX_RESOURCES; i++ ) { +// if( resource_table[i].used && !resource_table[i].secret == !secret ) { +// switch( resource_table[i].rt ) { +// case rt_RING: +// rc = keyring_search( pkt, kbpos, resource_table[i].iobuf, +// resource_table[i].fname ); +// break; +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: { +// PKT_public_key *req_pk = pkt->pkt.public_key; +// byte fpr[20]; +// size_t fprlen; +// +// fingerprint_from_pk( req_pk, fpr, &fprlen ); +// rc = do_gdbm_locate( resource_table[i].dbf, +// kbpos, fpr, fprlen ); +// } +// break; +// #endif +// default: BUG(); +// } +// +// kbpos->rt = resource_table[i].rt; +// if( !rc ) { +// kbpos->resno = i; +// kbpos->fp = NULL; +// return 0; +// } +// if( rc != -1 ) { +// log_error("error searching resource %d: %s\n", +// i, g10_errstr(rc)); +// last_rc = rc; +// } +// } +// } +// return last_rc; +//} +// +// +///**************** +// * Combined function to search for a username and get the position +// * of the keyblock. +// */ +//int +//find_keyblock_byname( KBPOS *kbpos, const char *username ) +//{ +// PACKET pkt; +// PKT_public_key *pk = m_alloc_clear( sizeof *pk ); +// int rc; +// +// rc = get_pubkey_byname( NULL, pk, username, NULL ); +// if( rc ) { +// free_public_key(pk); +// return rc; +// } +// +// init_packet( &pkt ); +// pkt.pkttype = PKT_PUBLIC_KEY; +// pkt.pkt.public_key = pk; +// rc = search( &pkt, kbpos, 0 ); +// free_public_key(pk); +// return rc; +//} +// +// +///**************** +// * Combined function to search for a key and get the position +// * of the keyblock. +// */ +//int +//find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ) +//{ +// PACKET pkt; +// int rc; +// +// init_packet( &pkt ); +// pkt.pkttype = PKT_PUBLIC_KEY; +// pkt.pkt.public_key = pk; +// rc = search( &pkt, kbpos, 0 ); +// return rc; +//} +// +///**************** +// * Combined function to search for a key and get the position +// * of the keyblock. +// */ +//int +//find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) +//{ +// PACKET pkt; +// int rc; +// +// init_packet( &pkt ); +// pkt.pkttype = PKT_SECRET_KEY; +// pkt.pkt.secret_key = sk; +// rc = search( &pkt, kbpos, 0 ); +// return rc; +//} +// +// +///**************** +// * Combined function to search for a username and get the position +// * of the keyblock. This function does not unprotect the secret key. +// */ +//int +//find_secret_keyblock_byname( KBPOS *kbpos, const char *username ) +//{ +// PACKET pkt; +// PKT_secret_key *sk = m_alloc_clear( sizeof *sk ); +// int rc; +// +// rc = get_seckey_byname( sk, username, 0 ); +// if( rc ) { +// free_secret_key(sk); +// return rc; +// } +// +// init_packet( &pkt ); +// pkt.pkttype = PKT_SECRET_KEY; +// pkt.pkt.secret_key = sk; +// rc = search( &pkt, kbpos, 1 ); +// free_secret_key(sk); +// return rc; +//} +// +// +///**************** +// * Locate a keyblock in a database which is capable of direct access +// * Put all information into KBPOS, which can be later be to access this +// * key block. +// * This function looks into all registered keyblock sources. +// * +// * Returns: 0 if found, +// * -1 if not found +// * G10ERR_UNSUPPORTED if no resource is able to handle this +// * or another errorcode. +// */ +//int +//locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) +//{ +// RESTBL *rentry; +// int i, rc, any=0, last_rc=-1; +// +// +// for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { +// if( rentry->used && !rentry->secret == !secret ) { +// kbpos->rt = rentry->rt; +// switch( rentry->rt ) { +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// any = 1; +// rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen ); +// break; +// #endif +// default: +// rc = G10ERR_UNSUPPORTED; +// break; +// } +// +// if( !rc ) { +// kbpos->resno = i; +// kbpos->fp = NULL; +// return 0; +// } +// else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { +// log_error("error searching resource %d: %s\n", +// i, g10_errstr(rc)); +// last_rc = rc; +// } +// } +// } +// +// return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; +//} +// +// +//int +//locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret ) +//{ +// RESTBL *rentry; +// int i, rc, any=0, last_rc=-1; +// +// if( shortkid ) +// return G10ERR_UNSUPPORTED; +// +// for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { +// if( rentry->used && !rentry->secret == !secret ) { +// kbpos->rt = rentry->rt; +// switch( rentry->rt ) { +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// any = 1; +// rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid ); +// break; +// #endif +// default: +// rc = G10ERR_UNSUPPORTED; +// break; +// } +// +// if( !rc ) { +// kbpos->resno = i; +// kbpos->fp = NULL; +// return 0; +// } +// else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { +// log_error("error searching resource %d: %s\n", +// i, g10_errstr(rc)); +// last_rc = rc; +// } +// } +// } +// +// return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; +//} +// +// +// +// +///**************** +// * Lock the keyblock; wait until it's available +// * This function may change the internal data in kbpos, in cases +// * when the keyblock to be locked has been modified. +// * fixme: remove this function and add an option to search()? +// */ +//int +//lock_keyblock( KBPOS *kbpos ) +//{ +// if( !check_pos(kbpos) ) +// return G10ERR_GENERAL; +// return 0; +//} +// +///**************** +// * Release a lock on a keyblock +// */ +//void +//unlock_keyblock( KBPOS *kbpos ) +//{ +// if( !check_pos(kbpos) ) +// BUG(); +//} +// +///**************** +// * Read a complete keyblock and return the root in ret_root. +// */ +//int +//read_keyblock( KBPOS *kbpos, KBNODE *ret_root ) +//{ +// if( !check_pos(kbpos) ) +// return G10ERR_GENERAL; +// +// switch( kbpos->rt ) { +// case rt_RING: +// return keyring_read( kbpos, ret_root ); +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// return do_gdbm_read( kbpos, ret_root ); +// #endif +// default: BUG(); +// } +//} +// + +/**************** + * This functions can be used to read through a complete keyring. + * Mode is: 0 = open + * 1 = read + * 2 = close + * 5 = open secret keyrings + * 11 = read but skip signature and comment packets. + * all others are reserved! + * Note that you do not need a search prior to this function, + * only a handle is needed. + * NOTE: It is not allowed to do an insert/update/delete with this + * keyblock, if you want to do this, use search/read! + */ +int +enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) +{ + int rc = 0; + RESTBL *rentry; + + trace(); + + if( !mode || mode == 5 || mode == 100 ) { + int i; + + kbpos->fp = NULL; + kbpos->rt = rt_UNKNOWN; + if( !mode ) { + kbpos->secret = 0; + i = 0; + } + else if( mode == 5 ) { + kbpos->secret = 1; + mode = 0; + i = 0; + } + else + i = kbpos->resno+1; + for(; i < MAX_RESOURCES; i++ ) + if( resource_table[i].used + && !resource_table[i].secret == !kbpos->secret ) + break; + if( i == MAX_RESOURCES ) + return -1; /* no resources */ + kbpos->resno = i; + rentry = check_pos( kbpos ); + kbpos->rt = resource_table[i].rt; + kbpos->valid = 0; + switch( kbpos->rt ) { + case rt_RING: + kbpos->fp = iobuf_open( rentry->fname ); + if( !kbpos->fp ) { + log_error("can't open `%s'\n", rentry->fname ); + return G10ERR_OPEN_FILE; + } + break; + #ifdef HAVE_LIBGDBM + case rt_GDBM: + /* FIXME: make sure that there is only one enum at a time */ + kbpos->offset = 0; + break; + #endif + default: + err (__FUNCTION__" - kbpos->rt default switch 1"); + //BUG(); + } + kbpos->pkt = NULL; + } + else if( mode == 1 || mode == 11 ) { + int cont; + do { + cont = 0; + switch( kbpos->rt ) { + case rt_RING: + if( !kbpos->fp ) + return G10ERR_GENERAL; + rc = keyring_enum( kbpos, ret_root, mode == 11 ); + break; + #ifdef HAVE_LIBGDBM + case rt_GDBM: + rc = do_gdbm_enum( kbpos, ret_root ); + break; + #endif + default: + err (__FUNCTION__" - kbpos->rt default switch 2"); + //BUG(); + } + + if( rc == -1 ) { +// assert( !kbpos->pkt ); + rentry = check_pos( kbpos ); +// assert(rentry); + /* close */ + enum_keyblocks(2, kbpos, ret_root ); + /* and open the next one */ + rc = enum_keyblocks(100, kbpos, ret_root ); + if( !rc ) + cont = 1; + } + } while(cont); + } + else { + switch( kbpos->rt ) { + case rt_RING: +// if( kbpos->fp ) { +// iobuf_close( kbpos->fp ); +// kbpos->fp = NULL; +// } + break; + case rt_GDBM: + break; + case rt_UNKNOWN: + /* this happens when we have no keyring at all */ + return rc; + + default: + err (__FUNCTION__" - kbpos->rt default switch 3"); + //BUG(); + } + /* release pending packet */ + free_packet( kbpos->pkt ); + m_free( kbpos->pkt ); + } + return rc; +} + + +// +// +///**************** +// * Insert the keyblock described by ROOT into the keyring described +// * by KBPOS. This actually appends the data to the keyfile. +// */ +//int +//insert_keyblock( KBPOS *kbpos, KBNODE root ) +//{ +// int rc; +// +// if( !check_pos(kbpos) ) +// return G10ERR_GENERAL; +// +// switch( kbpos->rt ) { +// case rt_RING: +// rc = keyring_copy( kbpos, 1, root ); +// break; +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// rc = do_gdbm_store( kbpos, root, 0 ); +// break; +// #endif +// default: BUG(); +// } +// +// return rc; +//} +// +///**************** +// * Delete the keyblock described by KBPOS. +// * The current code simply changes the keyblock in the keyring +// * to packet of type 0 with the correct length. To help detect errors, +// * zero bytes are written. +// */ +//int +//delete_keyblock( KBPOS *kbpos ) +//{ +// int rc; +// +// if( !check_pos(kbpos) ) +// return G10ERR_GENERAL; +// +// switch( kbpos->rt ) { +// case rt_RING: +// rc = keyring_copy( kbpos, 2, NULL ); +// break; +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// log_debug("deleting gdbm keyblock is not yet implemented\n"); +// rc = 0; +// break; +// #endif +// default: BUG(); +// } +// +// return rc; +//} +// +// +///**************** +// * Update the keyblock at KBPOS with the one in ROOT. +// */ +//int +//update_keyblock( KBPOS *kbpos, KBNODE root ) +//{ +// int rc; +// +// if( !check_pos(kbpos) ) +// return G10ERR_GENERAL; +// +// switch( kbpos->rt ) { +// case rt_RING: +// rc = keyring_copy( kbpos, 3, root ); +// break; +// #ifdef HAVE_LIBGDBM +// case rt_GDBM: +// rc = do_gdbm_store( kbpos, root, 1 ); +// break; +// #endif +// default: BUG(); +// } +// +// return rc; +//} +// +// +// +///**************************************************************** +// ********** Implemenation of a user ID database ************** +// ****************************************************************/ +//#if 0 +///**************** +// * Layout of the user ID db +// * +// * This user ID DB provides fast lookup of user ID, but the user ids are +// * not in any specific order. +// * +// * A string "GnuPG user db", a \n. +// * user ids of one key, delimited by \t, +// * a # or ^ followed by a 20 byte fingerprint, followed by an \n +// * The literal characters %, \n, \t, #, ^ must be replaced by a percent sign +// * and their hex value. +// * +// * (We use Boyer/Moore pattern matching) +// */ +// +///**************** +// * This compiles pattern to the distance table, the table will be allocate +// * here and must be freed by using free(). +// * Returns: Ptr to new allocated Table +// * Caller must free the table. +// */ +// +//static size_t * +//compile_bm_table( const byte *pattern, size_t len ) +//{ +// ushort *dist; +// int i; +// +// dist = m_alloc_clear( 256 * sizeof *dist ); +// for(i=0; i < 256; i++ ) +// dist[i] = len; +// for(i=0; i < len-1; i++ ) +// dTbl[p[i]] = len-i-1; +// return dist; +//} +// +// +// +// +///**************** +// * Search BUF of BUFLEN for pattern P of length PATLEN. +// * dist is the Boyer/Moore distance table of 256 Elements, +// * case insensitive search is done if IGNCASE is true (In this case +// * the distance table has to compiled from uppercase chacaters and +// * PAT must also be uppercase. +// * Returns: Prt to maching string in BUF, or NULL if not found. +// */ +// +//static const * +//do_bm_search( const byte *buf, size_t buflen, +// const byte *pat, size_t patlen, size_t *dist, int igncase ) +//{ +// int i, j, k; +// +// if( igncase ) { +// int c, c1; +// +// for( i = --patlen; i < buflen; i += dist[c1] ) +// for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j]; +// j--, k--, c=toupper(buf[k]) ) { +// if( !j ) +// return buf+k; +// } +// } +// else { +// for( i = --patlen; i < buflen; i += dist[buf[i]] ) +// for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) { +// if( !j ) +// return buf+k; +// } +// } +// return NULL; +//} +// +// +//typedef struct { +// size_t dist[256]; +//} *SCAN_USER_HANDLE; +// +//static SCAN_USER_HANDLE +//scan_user_file_open( const byte *name ) +//{ +// SCAN_USER_HANDLE hd; +// size_t *dist; +// int i; +// +// hd = m_alloc_clear( sizeof *hd ); +// dist = hd->dist; +// /* compile the distance table */ +// for(i=0; i < 256; i++ ) +// dist[i] = len; +// for(i=0; i < len-1; i++ ) +// dTbl[p[i]] = len-i-1; +// /* setup other things */ +// +// return hd; +//} +// +//static int +//scan_user_file_close( SCAN_USER_HANDLE hd ) +//{ +// m_free( hd ); +//} +// +//static int +//scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr ) +//{ +// char record[1000]; +// +// /* read a record */ +// +// +//} +//#endif +// +// +// +///**************************************************************** +// ********** Functions which operates on regular keyrings ******** +// ****************************************************************/ +// +//static int +//cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk ) +//{ +// int n,i; +// +// assert( req_sk->pubkey_algo == sk->pubkey_algo ); +// +// n = pubkey_get_nskey( req_sk->pubkey_algo ); +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) ) +// return -1; +// } +// return 0; +//} +// +//static int +//cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk ) +//{ +// int n, i; +// +// assert( req_pk->pubkey_algo == pk->pubkey_algo ); +// +// n = pubkey_get_npkey( req_pk->pubkey_algo ); +// for(i=0; i < n; i++ ) { +// if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] ) ) +// return -1; +// } +// return 0; +//} +// +///**************** +// * search one keyring, return 0 if found, -1 if not found or an errorcode. +// */ +//static int +//keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) +//{ +// int rc; +// PACKET pkt; +// int save_mode; +// ulong offset; +// int pkttype = req->pkttype; +// PKT_public_key *req_pk = req->pkt.public_key; +// PKT_secret_key *req_sk = req->pkt.secret_key; +// +// init_packet(&pkt); +// save_mode = set_packet_list_mode(0); +// kbpos->rt = rt_RING; +// kbpos->valid = 0; +// +// #if HAVE_DOSISH_SYSTEM || 1 +// assert(!iobuf); +// iobuf = iobuf_open( fname ); +// if( !iobuf ) { +// log_error("%s: can't open keyring file\n", fname); +// rc = G10ERR_KEYRING_OPEN; +// goto leave; +// } +// #else +// if( iobuf_seek( iobuf, 0 ) ) { +// log_error("can't rewind keyring file\n"); +// rc = G10ERR_KEYRING_OPEN; +// goto leave; +// } +// #endif +// +// while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) { +// if( pkt.pkttype == PKT_SECRET_KEY ) { +// PKT_secret_key *sk = pkt.pkt.secret_key; +// +// if( req_sk->timestamp == sk->timestamp +// && req_sk->pubkey_algo == sk->pubkey_algo +// && !cmp_seckey( req_sk, sk) ) +// break; /* found */ +// } +// else if( pkt.pkttype == PKT_PUBLIC_KEY ) { +// PKT_public_key *pk = pkt.pkt.public_key; +// +// if( req_pk->timestamp == pk->timestamp +// && req_pk->pubkey_algo == pk->pubkey_algo +// && !cmp_pubkey( req_pk, pk ) ) +// break; /* found */ +// } +// else +// BUG(); +// free_packet(&pkt); +// } +// if( !rc ) { +// kbpos->offset = offset; +// kbpos->valid = 1; +// } +// +// leave: +// free_packet(&pkt); +// set_packet_list_mode(save_mode); +// #if HAVE_DOSISH_SYSTEM || 1 +// iobuf_close(iobuf); +// #endif +// return rc; +//} +// +// +//static int +//keyring_read( KBPOS *kbpos, KBNODE *ret_root ) +//{ +// PACKET *pkt; +// int rc; +// RESTBL *rentry; +// KBNODE root = NULL; +// IOBUF a; +// int in_cert = 0; +// +// if( !(rentry=check_pos(kbpos)) ) +// return G10ERR_GENERAL; +// +// a = iobuf_open( rentry->fname ); +// if( !a ) { +// log_error("can't open `%s'\n", rentry->fname ); +// return G10ERR_OPEN_FILE; +// } +// +// if( !kbpos->valid ) +// log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset ); +// if( iobuf_seek( a, kbpos->offset ) ) { +// log_error("can't seek to %lu\n", kbpos->offset); +// iobuf_close(a); +// return G10ERR_KEYRING_OPEN; +// } +// +// pkt = m_alloc( sizeof *pkt ); +// init_packet(pkt); +// kbpos->count=0; +// while( (rc=parse_packet(a, pkt)) != -1 ) { +// if( rc ) { /* ignore errors */ +// if( rc != G10ERR_UNKNOWN_PACKET ) { +// log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); +// rc = G10ERR_INV_KEYRING; +// goto ready; +// } +// kbpos->count++; +// free_packet( pkt ); +// init_packet( pkt ); +// continue; +// } +// /* make a linked list of all packets */ +// switch( pkt->pkttype ) { +// case PKT_COMPRESSED: +// log_error("skipped compressed packet in keyring\n" ); +// free_packet(pkt); +// init_packet(pkt); +// break; +// +// case PKT_PUBLIC_KEY: +// case PKT_SECRET_KEY: +// if( in_cert ) +// goto ready; +// in_cert = 1; +// default: +// kbpos->count++; +// if( !root ) +// root = new_kbnode( pkt ); +// else +// add_kbnode( root, new_kbnode( pkt ) ); +// pkt = m_alloc( sizeof *pkt ); +// init_packet(pkt); +// break; +// } +// } +// ready: +// kbpos->valid = 0; +// if( rc == -1 && root ) +// rc = 0; +// +// if( rc ) +// release_kbnode( root ); +// else +// *ret_root = root; +// free_packet( pkt ); +// m_free( pkt ); +// iobuf_close(a); +// return rc; +//} +// + +static int +keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ) +{ + PACKET *pkt; + int rc; + RESTBL *rentry; + KBNODE root = NULL; + + trace(); + + if( !(rentry=check_pos(kbpos)) ) + return G10ERR_GENERAL; + + if( kbpos->pkt ) { + root = new_kbnode( kbpos->pkt ); + kbpos->pkt = NULL; + } + + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) { + if( rc ) { /* ignore errors */ + if( rc != G10ERR_UNKNOWN_PACKET ) { + log_error("read_keyblock: read error: %d\n", rc); + rc = G10ERR_INV_KEYRING; + goto ready; + } + free_packet( pkt ); + init_packet( pkt ); + continue; + } + /* make a linked list of all packets */ + switch( pkt->pkttype ) { + case PKT_COMPRESSED: + log_error("skipped compressed packet in keyring\n" ); + free_packet(pkt); + init_packet(pkt); + break; + + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + if( root ) { /* store this packet */ + kbpos->pkt = pkt; + pkt = NULL; + goto ready; + } + root = new_kbnode( pkt ); + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + break; + + default: + /* skip pakets at the beginning of a keyring, until we find + * a start packet; issue a warning if it is not a comment */ + if( !root && pkt->pkttype != PKT_COMMENT + && pkt->pkttype != PKT_OLD_COMMENT ) { + break; + } + if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE + ||pkt->pkttype == PKT_COMMENT + ||pkt->pkttype == PKT_OLD_COMMENT )) ) { + init_packet(pkt); + break; + } + add_kbnode( root, new_kbnode( pkt ) ); + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + break; + } + } + ready: + if( rc == -1 && root ) + rc = 0; + + if( rc ) + release_kbnode( root ); + else + *ret_root = root; + free_packet( pkt ); + m_free( pkt ); + + return rc; +} + + +///**************** +// * Perform insert/delete/update operation. +// * mode 1 = insert +// * 2 = delete +// * 3 = update +// */ +//static int +//keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) +//{ +// RESTBL *rentry; +// IOBUF fp, newfp; +// int rc=0; +// char *bakfname = NULL; +// char *tmpfname = NULL; +// +// if( !(rentry = check_pos( kbpos )) ) +// return G10ERR_GENERAL; +// if( kbpos->fp ) +// BUG(); /* not allowed with such a handle */ +// +// if( opt.dry_run ) +// return 0; +// +// lock_rentry( rentry ); +// +// /* open the source file */ +// fp = iobuf_open( rentry->fname ); +// if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */ +// KBNODE kbctx, node; +// +// /* insert: create a new file */ +// newfp = iobuf_create( rentry->fname ); +// if( !newfp ) { +// log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno)); +// unlock_rentry( rentry ); +// return G10ERR_OPEN_FILE; +// } +// else if( !opt.quiet ) +// log_info(_("%s: keyring created\n"), rentry->fname ); +// +// kbctx=NULL; +// while( (node = walk_kbnode( root, &kbctx, 0 )) ) { +// if( (rc = build_packet( newfp, node->pkt )) ) { +// log_error("build_packet(%d) failed: %s\n", +// node->pkt->pkttype, g10_errstr(rc) ); +// iobuf_cancel(newfp); +// unlock_rentry( rentry ); +// return G10ERR_WRITE_FILE; +// } +// } +// if( iobuf_close(newfp) ) { +// log_error("%s: close failed: %s\n", rentry->fname, strerror(errno)); +// unlock_rentry( rentry ); +// return G10ERR_CLOSE_FILE; +// } +// if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) { +// log_error("%s: chmod failed: %s\n", +// rentry->fname, strerror(errno) ); +// unlock_rentry( rentry ); +// return G10ERR_WRITE_FILE; +// } +// return 0; +// } +// if( !fp ) { +// log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) ); +// rc = G10ERR_OPEN_FILE; +// goto leave; +// } +// +// /* create the new file */ +// #ifdef USE_ONLY_8DOT3 +// /* Here is another Windoze bug?: +// * you cant rename("pubring.gpg.tmp", "pubring.gpg"); +// * but rename("pubring.gpg.tmp", "pubring.aaa"); +// * works. So we replace .gpg by .bak or .tmp +// */ +// if( strlen(rentry->fname) > 4 +// && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) { +// bakfname = m_alloc( strlen( rentry->fname ) + 1 ); +// strcpy(bakfname,rentry->fname); +// strcpy(bakfname+strlen(rentry->fname)-4, ".bak"); +// tmpfname = m_alloc( strlen( rentry->fname ) + 1 ); +// strcpy(tmpfname,rentry->fname); +// strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp"); +// } +// else { /* file does not end with gpg; hmmm */ +// bakfname = m_alloc( strlen( rentry->fname ) + 5 ); +// strcpy(stpcpy(bakfname,rentry->fname),".bak"); +// tmpfname = m_alloc( strlen( rentry->fname ) + 5 ); +// strcpy(stpcpy(tmpfname,rentry->fname),".tmp"); +// } +// #else +// bakfname = m_alloc( strlen( rentry->fname ) + 2 ); +// strcpy(stpcpy(bakfname,rentry->fname),"~"); +// tmpfname = m_alloc( strlen( rentry->fname ) + 5 ); +// strcpy(stpcpy(tmpfname,rentry->fname),".tmp"); +// #endif +// newfp = iobuf_create( tmpfname ); +// if( !newfp ) { +// log_error("%s: can't create: %s\n", tmpfname, strerror(errno) ); +// iobuf_close(fp); +// rc = G10ERR_OPEN_FILE; +// goto leave; +// } +// +// if( mode == 1 ) { /* insert */ +// /* copy everything to the new file */ +// rc = copy_all_packets( fp, newfp ); +// if( rc != -1 ) { +// log_error("%s: copy to %s failed: %s\n", +// rentry->fname, tmpfname, g10_errstr(rc) ); +// iobuf_close(fp); +// iobuf_cancel(newfp); +// goto leave; +// } +// rc = 0; +// } +// +// if( mode == 2 || mode == 3 ) { /* delete or update */ +// /* copy first part to the new file */ +// rc = copy_some_packets( fp, newfp, kbpos->offset ); +// if( rc ) { /* should never get EOF here */ +// log_error("%s: copy to %s failed: %s\n", +// rentry->fname, tmpfname, g10_errstr(rc) ); +// iobuf_close(fp); +// iobuf_cancel(newfp); +// goto leave; +// } +// /* skip this keyblock */ +// assert( kbpos->count ); +// rc = skip_some_packets( fp, kbpos->count ); +// if( rc ) { +// log_error("%s: skipping %u packets failed: %s\n", +// rentry->fname, kbpos->count, g10_errstr(rc)); +// iobuf_close(fp); +// iobuf_cancel(newfp); +// goto leave; +// } +// } +// +// if( mode == 1 || mode == 3 ) { /* insert or update */ +// KBNODE kbctx, node; +// +// /* append the new data */ +// kbctx=NULL; +// while( (node = walk_kbnode( root, &kbctx, 0 )) ) { +// if( (rc = build_packet( newfp, node->pkt )) ) { +// log_error("build_packet(%d) failed: %s\n", +// node->pkt->pkttype, g10_errstr(rc) ); +// iobuf_close(fp); +// iobuf_cancel(newfp); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// kbpos->valid = 0; +// } +// +// if( mode == 2 || mode == 3 ) { /* delete or update */ +// /* copy the rest */ +// rc = copy_all_packets( fp, newfp ); +// if( rc != -1 ) { +// log_error("%s: copy to %s failed: %s\n", +// rentry->fname, tmpfname, g10_errstr(rc) ); +// iobuf_close(fp); +// iobuf_cancel(newfp); +// goto leave; +// } +// rc = 0; +// } +// +// /* close both files */ +// if( iobuf_close(fp) ) { +// log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) ); +// rc = G10ERR_CLOSE_FILE; +// goto leave; +// } +// if( iobuf_close(newfp) ) { +// log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); +// rc = G10ERR_CLOSE_FILE; +// goto leave; +// } +// /* if the new file is a secring, restrict the permissions */ +// #ifndef HAVE_DOSISH_SYSTEM +// if( rentry->secret ) { +// if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) { +// log_error("%s: chmod failed: %s\n", +// tmpfname, strerror(errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// #endif +// +// /* rename and make backup file */ +// if( !rentry->secret ) { /* but not for secret keyrings */ +// #ifdef HAVE_DOSISH_SYSTEM +// remove( bakfname ); +// #endif +// if( rename( rentry->fname, bakfname ) ) { +// log_error("%s: rename to %s failed: %s\n", +// rentry->fname, bakfname, strerror(errno) ); +// rc = G10ERR_RENAME_FILE; +// goto leave; +// } +// } +// #ifdef HAVE_DOSISH_SYSTEM +// remove( rentry->fname ); +// #endif +// if( rename( tmpfname, rentry->fname ) ) { +// log_error("%s: rename to %s failed: %s\n", +// tmpfname, rentry->fname,strerror(errno) ); +// rc = G10ERR_RENAME_FILE; +// if( rentry->secret ) { +// log_info(_( +// "WARNING: 2 files with confidential information exists.\n")); +// log_info(_("%s is the unchanged one\n"), rentry->fname ); +// log_info(_("%s is the new one\n"), tmpfname ); +// log_info(_("Please fix this possible security flaw\n")); +// } +// goto leave; +// } +// +// leave: +// unlock_rentry( rentry ); +// m_free(bakfname); +// m_free(tmpfname); +// return rc; +//} +// +// +//#ifdef HAVE_LIBGDBM +///**************************************************************** +// ********** Functions which operates on GDM files *************** +// ****************************************************************/ +// +//#if MAX_FINGERPRINT_LEN > 20 +// #error A GDBM keyring assumes that fingerprints are less than 21 +//#endif +// +///**************** +// * Insert the keyblock into the GDBM database +// */ +// +//static int +//do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ) +//{ +// RESTBL *rentry; +// PKT_public_key *pk; +// KBNODE kbctx, node; +// IOBUF fp = NULL; +// byte fpr[20]; +// byte contbuf[21]; +// byte keybuf[21]; +// size_t fprlen; +// datum key, content; +// int i, rc; +// +// if( !(rentry = check_pos( kbpos )) ) +// return G10ERR_GENERAL; +// +// if( opt.dry_run ) +// return 0; +// +// /* construct the fingerprint which is used as the primary key */ +// node = find_kbnode( root, PKT_PUBLIC_KEY ); +// if( !node ) +// log_bug("a gdbm database can't store secret keys\n"); +// pk = node->pkt->pkt.public_key; +// +// fingerprint_from_pk( pk, fpr, &fprlen ); +// for(i=fprlen; i < DIM(fpr); i++ ) +// fpr[i] = 0; +// +// /* build the keyblock */ +// kbctx=NULL; +// fp = iobuf_temp(); +// iobuf_put( fp, 1 ); /* data is a keyblock */ +// while( (node = walk_kbnode( root, &kbctx, 0 )) ) { +// if( (rc = build_packet( fp, node->pkt )) ) { +// log_error("build_packet(%d) failed: %s\n", +// node->pkt->pkttype, g10_errstr(rc) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// } +// /* store data and key */ +// *keybuf = 1; /* key is a padded fingerprint */ +// memcpy(keybuf+1, fpr, 20 ); +// key.dptr = keybuf; +// key.dsize = 21; +// content.dptr = iobuf_get_temp_buffer( fp ); +// content.dsize = iobuf_get_temp_length( fp ); +// rc = gdbm_store( rentry->dbf, key, content, +// update? GDBM_REPLACE : GDBM_INSERT ); +// if( rc == 1 && !update ) +// rc = gdbm_store( rentry->dbf, key, content, GDBM_REPLACE ); +// +// if( rc ) { +// log_error("%s: gdbm_store failed: %s\n", rentry->fname, +// rc == 1 ? "already stored" +// : gdbm_strerror(gdbm_errno) ); +// rc = G10ERR_WRITE_FILE; +// goto leave; +// } +// /* now store all keyids */ +// *contbuf = 2; /* data is a list of fingerprints */ +// memcpy(contbuf+1, fpr, 20 ); +// content.dptr = contbuf; +// content.dsize= 21; +// kbctx=NULL; +// while( (node = walk_kbnode( root, &kbctx, 0 )) ) { +// if( node->pkt->pkttype == PKT_PUBLIC_KEY +// || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { +// u32 aki[2]; +// +// keyid_from_pk( node->pkt->pkt.public_key, aki ); +// *keybuf = 2; /* key is a 8 byte keyid */ +// u32tobuf( keybuf+1 , aki[0] ); +// u32tobuf( keybuf+5, aki[1] ); +// key.dptr = keybuf; +// key.dsize= 9; +// /* fixme: must be more clever when a insert failed: +// * build a list of fingerprints in this case */ +// rc = gdbm_store( rentry->dbf, key, content, +// update? GDBM_REPLACE : GDBM_INSERT ); +// if( rc ) { +// log_info("%s: gdbm_store keyid failed: %s\n", rentry->fname, +// rc == 1 ? "already stored" +// : gdbm_strerror(gdbm_errno) ); +// rc = 0; +// } +// } +// } +// +// leave: +// iobuf_close(fp); /* don't need a cancel because it is a temp iobuf */ +// return rc; +//} +// +// +// +///**************** +// * search one keybox, return 0 if found, -1 if not found or an errorcode. +// */ +//static int +//do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen ) +//{ +// byte *keybuf = kbpos->keybuf; +// datum key; +// int i; +// +// *keybuf = 1; +// for(i=0; i < fprlen; i++ ) +// keybuf[i+1] = fpr[i]; +// for(; i < 20; i++ ) +// keybuf[i+1] = 0; +// +// /* fetch the data */ +// key.dptr = keybuf; +// key.dsize = 21; +// if( !gdbm_exists( dbf, key ) ) +// return -1; /* not found */ +// return 0; +//} +// +///**************** +// * locate by keyid. +// * FIXME: we must have a way to enumerate thru the list opf fingerprints +// */ +//static int +//do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) +//{ +// byte keybuf[9]; +// datum key, content; +// int rc; +// +// /* construct the fingerprint which is used as the primary key */ +// *keybuf = 2; +// u32tobuf( keybuf+1, keyid[0] ); +// u32tobuf( keybuf+5, keyid[1] ); +// +// /* fetch the data */ +// key.dptr = keybuf; +// key.dsize = 9; +// content = gdbm_fetch( dbf, key ); +// if( !content.dptr ) +// return -1; +// +// if( content.dsize < 2 ) { +// log_error("gdbm_fetch did not return enough data\n" ); +// free( content.dptr ); /* can't use m_free() here */ +// return G10ERR_INV_KEYRING; +// } +// if( *content.dptr != 2 ) { +// log_error("gdbm_fetch returned unexpected type %d\n", +// *(byte*)content.dptr ); +// free( content.dptr ); /* can't use m_free() here */ +// return G10ERR_INV_KEYRING; +// } +// if( content.dsize < 21 ) { +// log_error("gdbm_fetch did not return a complete fingerprint\n" ); +// free( content.dptr ); /* can't use m_free() here */ +// return G10ERR_INV_KEYRING; +// } +// if( content.dsize > 21 ) +// log_info("gdbm_fetch: WARNING: more than one fingerprint\n" ); +// +// rc = do_gdbm_locate( dbf, kbpos, content.dptr+1, 20 ); +// free( content.dptr ); /* can't use m_free() here */ +// return rc; +//} +// +// +// +//static int +//do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root ) +//{ +// PACKET *pkt; +// int rc; +// RESTBL *rentry; +// KBNODE root = NULL; +// IOBUF a; +// datum key, content; +// +// if( !(rentry=check_pos(kbpos)) ) +// return G10ERR_GENERAL; +// +// key.dptr = kbpos->keybuf; +// key.dsize = 21; +// content = gdbm_fetch( rentry->dbf, key ); +// if( !content.dptr ) { +// log_error("gdbm_fetch failed: %s\n", gdbm_strerror(gdbm_errno) ); +// return G10ERR_INV_KEYRING; +// } +// if( content.dsize < 2 ) { +// log_error("gdbm_fetch did not return enough data\n" ); +// free( content.dptr ); /* can't use m_free() here */ +// return G10ERR_INV_KEYRING; +// } +// if( *content.dptr != 1 ) { +// log_error("gdbm_fetch returned unexpected type %d\n", +// *(byte*)content.dptr ); +// free( content.dptr ); /* can't use m_free() here */ +// return G10ERR_INV_KEYRING; +// } +// +// a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 ); +// free( content.dptr ); /* can't use m_free() here */ +// +// pkt = m_alloc( sizeof *pkt ); +// init_packet(pkt); +// kbpos->count=0; +// while( (rc=parse_packet(a, pkt)) != -1 ) { +// if( rc ) { /* ignore errors */ +// if( rc != G10ERR_UNKNOWN_PACKET ) { +// log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); +// rc = G10ERR_INV_KEYRING; +// break; +// } +// kbpos->count++; +// free_packet( pkt ); +// init_packet( pkt ); +// continue; +// } +// /* make a linked list of all packets */ +// kbpos->count++; +// if( !root ) +// root = new_kbnode( pkt ); +// else +// add_kbnode( root, new_kbnode( pkt ) ); +// pkt = m_alloc( sizeof *pkt ); +// init_packet(pkt); +// } +// if( rc == -1 && root ) +// rc = 0; +// if( rc ) +// release_kbnode( root ); +// else +// *ret_root = root; +// free_packet( pkt ); +// m_free( pkt ); +// iobuf_close(a); +// return rc; +//} +// +// +///**************** +// * Enum over keyblok data +// */ +//static int +//do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root ) +//{ +// RESTBL *rentry; +// datum key, helpkey; +// +// if( !(rentry=check_pos(kbpos)) ) +// return G10ERR_GENERAL; +// +// if( !kbpos->offset ) { +// kbpos->offset = 1; +// key = gdbm_firstkey( rentry->dbf ); +// } +// else { +// helpkey.dptr = kbpos->keybuf; +// helpkey.dsize= 21; +// key = gdbm_nextkey( rentry->dbf, helpkey ); +// } +// while( key.dptr && (!key.dsize || *key.dptr != 1) ) { +// helpkey = key; +// key = gdbm_nextkey( rentry->dbf, helpkey ); +// free( helpkey.dptr ); /* free and not m_free() ! */ +// } +// if( !key.dptr ) +// return -1; /* eof */ +// +// if( key.dsize < 21 ) { +// free( key.dptr ); /* free and not m_free() ! */ +// log_error("do_gdm_enum: key is too short\n" ); +// return G10ERR_INV_KEYRING; +// } +// memcpy( kbpos->keybuf, key.dptr, 21 ); +// free( key.dptr ); /* free and not m_free() ! */ +// return do_gdbm_read( kbpos, ret_root ); +//} +// +//#endif /*HAVE_LIBGDBM*/ diff -Nru a/security/cryptomark/gnupg/seskey.c b/security/cryptomark/gnupg/seskey.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/seskey.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,210 @@ +/* seskey.c - make sesssion keys etc. + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "cipher.h" +#include "mpi.h" +#include "main.h" +#include "i18n.h" + + +///**************** +// * Make a session key and put it into DEK +// */ +//void +//make_session_key( DEK *dek ) +//{ +// CIPHER_HANDLE chd; +// int i, rc; +// +// dek->keylen = cipher_get_keylen( dek->algo ) / 8; +// +// chd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 ); +// randomize_buffer( dek->key, dek->keylen, 1 ); +// for(i=0; i < 16; i++ ) { +// rc = cipher_setkey( chd, dek->key, dek->keylen ); +// if( !rc ) { +// cipher_close( chd ); +// return; +// } +// log_info(_("weak key created - retrying\n") ); +// /* Renew the session key until we get a non-weak key. */ +// randomize_buffer( dek->key, dek->keylen, 1 ); +// } +// log_fatal(_( +// "cannot avoid weak key for symmetric cipher; tried %d times!\n"), +// i); +//} +// +// +///**************** +// * Encode the session key. NBITS is the number of bits which should be used +// * for packing the session key. +// * returns: A mpi with the session key (caller must free) +// */ +//MPI +//encode_session_key( DEK *dek, unsigned nbits ) +//{ +// int nframe = (nbits+7) / 8; +// byte *p; +// byte *frame; +// int i,n; +// u16 csum; +// MPI a; +// +// /* the current limitation is that we can only use a session key +// * whose length is a multiple of BITS_PER_MPI_LIMB +// * I think we can live with that. +// */ +// if( dek->keylen + 7 > nframe || !nframe ) +// log_bug("can't encode a %d bit key in a %d bits frame\n", +// dek->keylen*8, nbits ); +// +// /* We encode the session key in this way: +// * +// * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) +// * +// * (But how can we store the leading 0 - the external representaion +// * of MPIs doesn't allow leading zeroes =:-) +// * +// * RND are non-zero random bytes. +// * A is the cipher algorithm +// * DEK is the encryption key (session key) length k depends on the +// * cipher algorithm (20 is used with blowfish160). +// * CSUM is the 16 bit checksum over the DEK +// */ +// csum = 0; +// for( p = dek->key, i=0; i < dek->keylen; i++ ) +// csum += *p++; +// +// frame = m_alloc_secure( nframe ); +// n = 0; +// frame[n++] = 0; +// frame[n++] = 2; +// i = nframe - 6 - dek->keylen; +// assert( i > 0 ); +// p = get_random_bits( i*8, 1, 1 ); +// /* replace zero bytes by new values */ +// for(;;) { +// int j, k; +// byte *pp; +// +// /* count the zero bytes */ +// for(j=k=0; j < i; j++ ) +// if( !p[j] ) +// k++; +// if( !k ) +// break; /* okay: no zero bytes */ +// k += k/128; /* better get some more */ +// pp = get_random_bits( k*8, 1, 1); +// for(j=0; j < i && k ; j++ ) +// if( !p[j] ) +// p[j] = pp[--k]; +// m_free(pp); +// } +// memcpy( frame+n, p, i ); +// m_free(p); +// n += i; +// frame[n++] = 0; +// frame[n++] = dek->algo; +// memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; +// frame[n++] = csum >>8; +// frame[n++] = csum; +// assert( n == nframe ); +// a = mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); +// mpi_set_buffer( a, frame, nframe, 0 ); +// m_free(frame); +// return a; +//} +// + +static MPI +do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, + const byte *asn, size_t asnlen ) +{ + int nframe = (nbits+7) / 8; + byte *frame; + int i,n; + MPI a; + + trace(); + + if( len + asnlen + 4 > nframe ) + log_bug("can't encode a %d bit MD into a %d bits frame\n", + (int)(len*8), (int)nbits); + + /* We encode the MD in this way: + * + * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * + * PAD consists of FF bytes. + */ + frame = md_is_secure(md)? m_alloc_secure( nframe ) : m_alloc( nframe ); + n = 0; + frame[n++] = 0; + frame[n++] = algo; + i = nframe - len - asnlen -3 ; +// assert( i > 1 ); + memset( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy( frame+n, asn, asnlen ); n += asnlen; + memcpy( frame+n, md_read(md, algo), len ); n += len; +// assert( n == nframe ); + a = md_is_secure(md)? + mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ) + : mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); + mpi_set_buffer( a, frame, nframe, 0 ); + m_free(frame); + return a; +} + + +MPI +encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits ) +{ + int algo = hash_algo? hash_algo : md_get_algo(md); + const byte *asn; + size_t asnlen, mdlen; + MPI frame; + + trace(); + + if( pubkey_algo == PUBKEY_ALGO_DSA ) { + frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo) + +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ) + : mpi_alloc((md_digest_length(hash_algo) + +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); + mpi_set_buffer( frame, md_read(md, hash_algo), + md_digest_length(hash_algo), 0 ); + } + else { + asn = md_asn_oid( algo, &asnlen, &mdlen ); + frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen ); + } + return frame; +} + diff -Nru a/security/cryptomark/gnupg/sig-check.c b/security/cryptomark/gnupg/sig-check.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/sig-check.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,540 @@ +/* sig-check.c - Check a signature + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +#include "util.h" +#include "packet.h" +#include "memory.h" +#include "mpi.h" +#include "keydb.h" +#include "cipher.h" +#include "main.h" +#include "status.h" +#include "i18n.h" + +struct cmp_help_context_s { + PKT_signature *sig; + MD_HANDLE md; +}; + + +static int do_signature_check( PKT_signature *sig, MD_HANDLE digest, + u32 *r_expire ); +static int do_check( PKT_public_key *pk, PKT_signature *sig, + MD_HANDLE digest ); + + +/**************** + * Check the signature which is contained in SIG. + * The MD_HANDLE should be currently open, so that this function + * is able to append some data, before finalizing the digest. + */ +int +signature_check( PKT_signature *sig, MD_HANDLE digest ) +{ + u32 dummy; + return do_signature_check( sig, digest, &dummy ); +} + +static int +do_signature_check( PKT_signature *sig, MD_HANDLE digest, u32 *r_expire ) +{ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + int rc=0; + + trace(); + + if( is_RSA(sig->pubkey_algo) ) + write_status(STATUS_RSA_OR_IDEA); + + *r_expire = 0; + if( get_pubkey( pk, sig->keyid ) ) + rc = G10ERR_NO_PUBKEY; + else { + *r_expire = pk->expiredate; + rc = do_check( pk, sig, digest ); + } + + free_public_key( pk ); + +// if( !rc && sig->sig_class < 2 && is_status_enabled() ) { + if( !rc && sig->sig_class < 2 ) { + /* This signature id works best with DLP algorithms because + * they use a random parameter for every signature. Instead of + * this sig-id we could have also used the hash of the document + * and the timestamp, but the drawback of this is, that it is + * not possible to sign more than one identical document within + * one second. Some remote bacth processing applications might + * like this feature here */ + MD_HANDLE md; + u32 a = sig->timestamp; + int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); + byte *p, *buffer; + + md = md_open( DIGEST_ALGO_RMD160, 0); + md_putc( digest, sig->pubkey_algo ); + md_putc( digest, sig->digest_algo ); + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); + for(i=0; i < nsig; i++ ) { + unsigned n = mpi_get_nbits( sig->data[i]); + + md_putc( md, n>>8); + md_putc( md, n ); + p = mpi_get_buffer( sig->data[i], &n, NULL ); + md_write( md, p, n ); + m_free(p); + } + md_final( md ); + p = make_radix64_string( md_read( md, 0 ), 20 ); + buffer = m_alloc( strlen(p) + 60 ); +// sprintf( buffer, "%s %s %lu", +// p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp ); + sprintf( buffer, "%s", p); + write_status_text( STATUS_SIG_ID, buffer ); + dbg(__FUNCTION__); + m_free(buffer); + m_free(p); + md_close(md); + } + + return rc; +} + +// +//#if 0 /* not anymore used */ +///**************** +// * Check the MDC which is contained in SIG. +// * The MD_HANDLE should be currently open, so that this function +// * is able to append some data, before finalizing the digest. +// */ +//int +//mdc_kludge_check( PKT_signature *sig, MD_HANDLE digest ) +//{ +// int rc=0; +// +// if( (rc=check_digest_algo(sig->digest_algo)) ) +// return rc; +// +// /* make sure the digest algo is enabled (in case of a detached mdc??) */ +// md_enable( digest, sig->digest_algo ); +// +// /* complete the digest */ +// if( sig->version >= 4 ) +// md_putc( digest, sig->version ); +// md_putc( digest, sig->sig_class ); +// if( sig->version < 4 ) { +// u32 a = sig->timestamp; +// md_putc( digest, (a >> 24) & 0xff ); +// md_putc( digest, (a >> 16) & 0xff ); +// md_putc( digest, (a >> 8) & 0xff ); +// md_putc( digest, a & 0xff ); +// } +// else { +// byte buf[6]; +// size_t n; +// md_putc( digest, sig->pubkey_algo ); +// md_putc( digest, sig->digest_algo ); +// if( sig->hashed_data ) { +// n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; +// md_write( digest, sig->hashed_data, n+2 ); +// n += 6; +// } +// else +// n = 6; +// /* add some magic */ +// buf[0] = sig->version; +// buf[1] = 0xff; +// buf[2] = n >> 24; +// buf[3] = n >> 16; +// buf[4] = n >> 8; +// buf[5] = n; +// md_write( digest, buf, 6 ); +// } +// md_final( digest ); +// +// rc = G10ERR_BAD_SIGN; +// { const byte *s1 = md_read( digest, sig->digest_algo ); +// int s1len = md_digest_length( sig->digest_algo ); +// +// log_hexdump( "MDC calculated", s1, s1len ); +// +// if( !sig->data[0] ) +// log_debug("sig_data[0] is NULL\n"); +// else { +// unsigned s2len; +// byte *s2; +// s2 = mpi_get_buffer( sig->data[0], &s2len, NULL ); +// log_hexdump( "MDC stored ", s2, s2len ); +// +// if( s2len != s1len ) +// log_debug("MDC check: len differ: %d/%d\n", s1len, s2len); +// else if( memcmp( s1, s2, s1len ) ) +// log_debug("MDC check: hashs differ\n"); +// else +// rc = 0; +// m_free(s2); +// } +// } +// +// if( !rc && sig->flags.unknown_critical ) { +// log_info(_("assuming bad MDC due to an unknown critical bit\n")); +// rc = G10ERR_BAD_SIGN; +// } +// sig->flags.checked = 1; +// sig->flags.valid = !rc; +// +// /* FIXME: check that we are actually in an encrypted packet */ +// +// return rc; +//} +//#endif + +/**************** + * This function gets called by pubkey_verify() if the algorithm needs it. + */ +static int +cmp_help( void *opaque, MPI result ) +{ + trace(); + + #if 0 /* we do not use this anymore */ + int rc=0, i, j, c, old_enc; + byte *dp; + const byte *asn; + size_t mdlen, asnlen; + struct cmp_help_context_s *ctx = opaque; + PKT_signature *sig = ctx->sig; + MD_HANDLE digest = ctx->md; + + old_enc = 0; + for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { + if( !j ) { + if( !i && c != 1 ) + break; + else if( i && c == 0xff ) + ; /* skip the padding */ + else if( i && !c ) + j++; + else + break; + } + else if( ++j == 18 && c != 1 ) + break; + else if( j == 19 && c == 0 ) { + old_enc++; + break; + } + } + if( old_enc ) { + log_error("old encoding scheme is not supported\n"); + return G10ERR_GENERAL; + } + + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; /* unsupported algo */ + asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); + + for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; + i++, j-- ) + if( asn[j] != c ) + break; + if( j != -1 || mpi_getbyte(result, i) ) + return G10ERR_BAD_PUBKEY; /* ASN is wrong */ + for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) + if( c != 0xff ) + break; + i++; + if( c != sig->digest_algo || mpi_getbyte(result, i) ) { + /* Padding or leading bytes in signature is wrong */ + return G10ERR_BAD_PUBKEY; + } + if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] + || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { + /* Wrong key used to check the signature */ + return G10ERR_BAD_PUBKEY; + } + + dp = md_read( digest, sig->digest_algo ); + for(i=mdlen-1; i >= 0; i--, dp++ ) { + if( mpi_getbyte( result, i ) != *dp ) + return G10ERR_BAD_SIGN; + } + return 0; + #else + return -1; + #endif +} + + +static int +do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest ) +{ + MPI result = NULL; + int rc=0; + struct cmp_help_context_s ctx; +// u32 cur_time; + + trace(); + + if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { + log_info("this is a PGP generated " + "ElGamal key which is NOT secure for signatures!\n"); + return G10ERR_PUBKEY_ALGO; + } + + if( pk->timestamp > sig->timestamp ) { + ulong d = pk->timestamp - sig->timestamp; + log_info( "public key is %lu second(s) newer than the signature\n", d ); + return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */ + } + +// cur_time = make_timestamp(); +// if( pk->timestamp > cur_time ) { +// ulong d = pk->timestamp - cur_time; +// log_info("key has been created %lu second(s) " +// "in future (time warp or clock problem)\n", d ); +// return G10ERR_TIME_CONFLICT; +// } +// +// if( pk->expiredate && pk->expiredate < cur_time ) { +// log_info("NOTE: signature key expired %s\n", +// asctimestamp( pk->expiredate ) ); +// write_status(STATUS_SIGEXPIRED); +// } + + + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; + if( (rc=check_pubkey_algo(sig->pubkey_algo)) ) + return rc; + + /* make sure the digest algo is enabled (in case of a detached signature)*/ + md_enable( digest, sig->digest_algo ); + + /* complete the digest */ + if( sig->version >= 4 ) + md_putc( digest, sig->version ); + md_putc( digest, sig->sig_class ); + if( sig->version < 4 ) { + u32 a = sig->timestamp; + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); + } + else { + byte buf[6]; + size_t n; + md_putc( digest, sig->pubkey_algo ); + md_putc( digest, sig->digest_algo ); + if( sig->hashed_data ) { + n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; + md_write( digest, sig->hashed_data, n+2 ); + n += 6; + } + else + n = 6; + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write( digest, buf, 6 ); + } + md_final( digest ); + + result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, + mpi_get_nbits(pk->pkey[0])); + + ctx.sig = sig; + ctx.md = digest; + rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, + cmp_help, &ctx ); + mpi_free( result ); + if( !rc && sig->flags.unknown_critical ) { + log_info("assuming bad signature due to an unknown critical bit\n"); + rc = G10ERR_BAD_SIGN; + } + sig->flags.checked = 1; + sig->flags.valid = !rc; + + return rc; +} + + +static void +hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) +{ + PKT_user_id *uid = unode->pkt->pkt.user_id; + + trace(); + +// assert( unode->pkt->pkttype == PKT_USER_ID ); + if( uid->photo ) { + if( sig->version >=4 ) { + byte buf[5]; + buf[0] = 0xd1; /* packet of type 17 */ + buf[1] = uid->photolen >> 24; /* always use 4 length bytes */ + buf[2] = uid->photolen >> 16; + buf[3] = uid->photolen >> 8; + buf[4] = uid->photolen; + md_write( md, buf, 5 ); + } + md_write( md, uid->photo, uid->photolen ); + } + else { + if( sig->version >=4 ) { + byte buf[5]; + buf[0] = 0xb4; /* indicates a userid packet */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ + buf[2] = uid->len >> 16; + buf[3] = uid->len >> 8; + buf[4] = uid->len; + md_write( md, buf, 5 ); + } + md_write( md, uid->name, uid->len ); + } +} + +/**************** + * check the signature pointed to by NODE. This is a key signature. + * If the function detects a self-signature, it uses the PK from + * ROOT and does not read any public key. + */ +int +check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) +{ + u32 dummy; + return check_key_signature2(root, node, is_selfsig, &dummy ); +} + +int +check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, u32 *r_expire) +{ + MD_HANDLE md; + PKT_public_key *pk; + PKT_signature *sig; + int algo; + int rc; + + trace(); + + if( is_selfsig ) + *is_selfsig = 0; + *r_expire = 0; +// assert( node->pkt->pkttype == PKT_SIGNATURE ); +// assert( root->pkt->pkttype == PKT_PUBLIC_KEY ); + + pk = root->pkt->pkt.public_key; + sig = node->pkt->pkt.signature; + algo = sig->digest_algo; + + #if 0 /* I am not sure whether this is a good thing to do */ + if( sig->flags.checked ) + log_debug("check_key_signature: already checked: %s\n", + sig->flags.valid? "good":"bad" ); + #endif + + if( (rc=check_digest_algo(algo)) ) + return rc; + + if( sig->sig_class == 0x20 ) { + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + rc = do_check( pk, sig, md ); + md_close(md); + } + else if( sig->sig_class == 0x28 ) { /* subkey revocation */ + KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); + + if( snode ) { + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_public_key( md, snode->pkt->pkt.public_key ); + rc = do_check( pk, sig, md ); + md_close(md); + } + else { + log_error("no subkey for subkey revocation packet\n"); + rc = G10ERR_SIG_CLASS; + } + } + else if( sig->sig_class == 0x18 ) { + KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); + + if( snode ) { + if( is_selfsig ) { /* does this make sense????? */ + u32 keyid[2]; /* it should always be a selfsig */ + + keyid_from_pk( pk, keyid ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + *is_selfsig = 1; + } + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_public_key( md, snode->pkt->pkt.public_key ); + rc = do_check( pk, sig, md ); + md_close(md); + } + else { + log_error("no subkey for key signature packet\n"); + rc = G10ERR_SIG_CLASS; + } + } + else { + KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID ); + + if( unode ) { + u32 keyid[2]; + + keyid_from_pk( pk, keyid ); + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_uid_node( unode, md, sig ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { + if( is_selfsig ) + *is_selfsig = 1; + rc = do_check( pk, sig, md ); + } + else + rc = do_signature_check( sig, md, r_expire ); + md_close(md); + } + else { + log_error("no user ID for key signature packet\n"); + rc = G10ERR_SIG_CLASS; + } + } + + return rc; +} + + diff -Nru a/security/cryptomark/gnupg/status.c b/security/cryptomark/gnupg/status.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/status.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,407 @@ +/* status.c + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#ifdef USE_SHM_COPROCESSING +// #ifdef USE_CAPABILITIES +// #include +// #endif +// #ifdef HAVE_SYS_IPC_H +// #include +// #endif +// #ifdef HAVE_SYS_SHM_H +// #include +// #endif +// #if defined(HAVE_MLOCK) +// #include +// #endif +//#endif +#include "util.h" +#include "status.h" +#include "ttyio.h" +#include "options.h" +#include "main.h" +#include "i18n.h" + +//static int fd = -1; +//#ifdef USE_SHM_COPROCESSING +// static int shm_id = -1; +// static volatile char *shm_area; +// static size_t shm_size; +// static int shm_is_locked; +//#endif /*USE_SHM_COPROCESSING*/ +// +//void +//set_status_fd ( int newfd ) +//{ +// fd = newfd; +//} +// +//int +//is_status_enabled() +//{ +// return fd != -1; +//} + +void +write_status ( int no ) +{ + write_status_text( no, NULL ); +} + +void +write_status_text ( int no, const char *text) +{ + const char *s; + +// if( fd == -1 ) +// return; /* not enabled */ + + switch( no ) { + case STATUS_ENTER : s = "ENTER"; break; + case STATUS_LEAVE : s = "LEAVE"; break; + case STATUS_ABORT : s = "ABORT"; break; + case STATUS_GOODSIG: s = "GOODSIG"; break; + case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break; + case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; + case STATUS_BADSIG : s = "BADSIG"; break; + case STATUS_ERRSIG : s = "ERRSIG"; break; + case STATUS_BADARMOR : s = "BADARMOR"; break; + case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; + case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; + case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; + case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; + case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; + case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; + case STATUS_SHM_INFO : s = "SHM_INFO"; break; + case STATUS_SHM_GET : s = "SHM_GET"; break; + case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; + case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; + case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; + case STATUS_VALIDSIG : s = "VALIDSIG"; break; + case STATUS_SIG_ID : s = "SIG_ID"; break; + case STATUS_ENC_TO : s = "ENC_TO"; break; + case STATUS_NODATA : s = "NODATA"; break; + case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; + case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; + case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; + case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; + case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; + case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; + case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; + case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; + case STATUS_GOODMDC : s = "GOODMDC"; break; + case STATUS_BADMDC : s = "BADMDC"; break; + case STATUS_ERRMDC : s = "ERRMDC"; break; + case STATUS_IMPORTED : s = "IMPORTED"; break; + case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; + case STATUS_FILE_START : s = "FILE_START"; break; + case STATUS_FILE_DONE : s = "FILE_DONE"; break; + case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; + default: s = "?"; break; + } + + if (text) { + dbg (__FUNCTION__ ": %s %s", s, text); + } else { + dbg (__FUNCTION__ ": %s", s); + } +// write( fd, "[GNUPG:] ", 9 ); +// if( text ) { +// write( fd, s, strlen(s)-1 ); +// write( fd, " ", 1 ); +// write( fd, text, strlen(text) ); +// write( fd, "\n", 1 ); +// } +// else +// write( fd, s, strlen(s) ); +} + + +//#ifdef USE_SHM_COPROCESSING +// +//#ifndef IPC_RMID_DEFERRED_RELEASE +//static void +//remove_shmid( void ) +//{ +// if( shm_id != -1 ) { +// shmctl ( shm_id, IPC_RMID, 0); +// shm_id = -1; +// } +//} +//#endif +// +//void +//init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ) +//{ +// char buf[100]; +// struct shmid_ds shmds; +// +// #ifndef IPC_RMID_DEFERRED_RELEASE +// atexit( remove_shmid ); +// #endif +// requested_shm_size = (requested_shm_size + 4095) & ~4095; +// if ( requested_shm_size > 2 * 4096 ) +// log_fatal("too much shared memory requested; only 8k are allowed\n"); +// shm_size = 4096 /* one page for us */ + requested_shm_size; +// +// shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 ); +// if ( shm_id == -1 ) +// log_fatal("can't get %uk of shared memory: %s\n", +// (unsigned)shm_size/1024, strerror(errno)); +// shm_area = shmat( shm_id, 0, 0 ); +// if ( shm_area == (char*)-1 ) +// log_fatal("can't attach %uk shared memory: %s\n", +// (unsigned)shm_size/1024, strerror(errno)); +// log_debug("mapped %uk shared memory at %p, id=%d\n", +// (unsigned)shm_size/1024, shm_area, shm_id ); +// if( lock_mem ) { +// #ifdef USE_CAPABILITIES +// cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); +// #endif +// #ifdef IPC_HAVE_SHM_LOCK +// if ( shmctl (shm_id, SHM_LOCK, 0) ) +// log_info("locking shared memory %d failed: %s\n", +// shm_id, strerror(errno)); +// else +// shm_is_locked = 1; +// #elif defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) +// /* (need the cast for Solaris with Sun's workshop compilers) */ +// if ( mlock ( (char*)shm_area, shm_size) ) +// log_info("locking shared memory %d failed: %s\n", +// shm_id, strerror(errno)); +// else +// shm_is_locked = 1; +// #else +// log_info("Locking shared memory %d failed: No way to do it\n", shm_id ); +// #endif +// #ifdef USE_CAPABILITIES +// cap_set_proc( cap_from_text("cap_ipc_lock+p") ); +// #endif +// } +// +// +// +// #ifdef IPC_RMID_DEFERRED_RELEASE +// if( shmctl( shm_id, IPC_RMID, 0) ) +// log_fatal("shmctl IPC_RMDID of %d failed: %s\n", +// shm_id, strerror(errno)); +// #endif +// +// if( shmctl( shm_id, IPC_STAT, &shmds ) ) +// log_fatal("shmctl IPC_STAT of %d failed: %s\n", +// shm_id, strerror(errno)); +// if( shmds.shm_perm.uid != getuid() ) { +// shmds.shm_perm.uid = getuid(); +// if( shmctl( shm_id, IPC_SET, &shmds ) ) +// log_fatal("shmctl IPC_SET of %d failed: %s\n", +// shm_id, strerror(errno)); +// } +// +// /* write info; Protocol version, id, size, locked size */ +// sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(), +// shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 ); +// write_status_text( STATUS_SHM_INFO, buf ); +//} +// +// +///**************** +// * Request a string from client +// * If bool, returns static string on true (do not free) or NULL for false +// */ +//static char * +//do_shm_get( const char *keyword, int hidden, int bool ) +//{ +// size_t n; +// byte *p; +// char *string; +// +// if( !shm_area ) +// BUG(); +// +// shm_area[0] = 0; /* msb of length of control block */ +// shm_area[1] = 32; /* and lsb */ +// shm_area[2] = 1; /* indicate that we are waiting on a reply */ +// shm_area[3] = 0; /* clear data available flag */ +// +// write_status_text( bool? STATUS_SHM_GET_BOOL : +// hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword ); +// +// do { +// pause_on_sigusr(1); +// if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 ) +// log_fatal("client modified shm control block - abort\n"); +// } while( !shm_area[3] ); +// shm_area[2] = 0; /* reset request flag */ +// p = (byte*)shm_area+32; +// n = p[0] << 8 | p[1]; +// p += 2; +// if( n+32+2+1 > 4095 ) +// log_fatal("client returns too large data (%u bytes)\n", (unsigned)n ); +// +// if( bool ) +// return p[0]? "" : NULL; +// +// string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 ); +// memcpy(string, p, n ); +// string[n] = 0; /* make sure it is a string */ +// if( hidden ) /* invalidate the memory */ +// memset( p, 0, n ); +// +// return string; +//} +// +//#endif /* USE_SHM_COPROCESSING */ +// +// +// +//int +//cpr_enabled() +//{ +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return 1; +// #endif +// return 0; +//} +// +//char * +//cpr_get( const char *keyword, const char *prompt ) +//{ +// char *p; +// +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return do_shm_get( keyword, 0, 0 ); +// #endif +// for(;;) { +// p = tty_get( prompt ); +// if( *p=='?' && !p[1] && !(keyword && !*keyword)) { +// m_free(p); +// display_online_help( keyword ); +// } +// else +// return p; +// } +//} +// +//char * +//cpr_get_utf8( const char *keyword, const char *prompt ) +//{ +// char *p; +// p = cpr_get( keyword, prompt ); +// if( p ) { +// char *utf8 = native_to_utf8( p ); +// m_free( p ); +// p = utf8; +// } +// return p; +//} +// +//char * +//cpr_get_hidden( const char *keyword, const char *prompt ) +//{ +// char *p; +// +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return do_shm_get( keyword, 1, 0 ); +// #endif +// for(;;) { +// p = tty_get_hidden( prompt ); +// if( *p == '?' && !p[1] ) { +// m_free(p); +// display_online_help( keyword ); +// } +// else +// return p; +// } +//} +// +//void +//cpr_kill_prompt(void) +//{ +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return; +// #endif +// tty_kill_prompt(); +// return; +//} +// +//int +//cpr_get_answer_is_yes( const char *keyword, const char *prompt ) +//{ +// int yes; +// char *p; +// +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return !!do_shm_get( keyword, 0, 1 ); +// #endif +// for(;;) { +// p = tty_get( prompt ); +// trim_spaces(p); /* it is okay to do this here */ +// if( *p == '?' && !p[1] ) { +// m_free(p); +// display_online_help( keyword ); +// } +// else { +// tty_kill_prompt(); +// yes = answer_is_yes(p); +// m_free(p); +// return yes; +// } +// } +//} +// +//int +//cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) +//{ +// int yes; +// char *p; +// +// #ifdef USE_SHM_COPROCESSING +// if( opt.shm_coprocess ) +// return !!do_shm_get( keyword, 0, 1 ); +// #endif +// for(;;) { +// p = tty_get( prompt ); +// trim_spaces(p); /* it is okay to do this here */ +// if( *p == '?' && !p[1] ) { +// m_free(p); +// display_online_help( keyword ); +// } +// else { +// tty_kill_prompt(); +// yes = answer_is_yes_no_quit(p); +// m_free(p); +// return yes; +// } +// } +//} +// diff -Nru a/security/cryptomark/gnupg/status.h b/security/cryptomark/gnupg/status.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/status.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,92 @@ +/* status.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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_STATUS_H +#define G10_STATUS_H + + +#define STATUS_ENTER 1 +#define STATUS_LEAVE 2 +#define STATUS_ABORT 3 + +#define STATUS_GOODSIG 4 +#define STATUS_BADSIG 5 +#define STATUS_ERRSIG 6 + + +#define STATUS_BADARMOR 7 + +#define STATUS_RSA_OR_IDEA 8 +#define STATUS_SIGEXPIRED 9 +#define STATUS_KEYREVOKED 10 + +#define STATUS_TRUST_UNDEFINED 11 +#define STATUS_TRUST_NEVER 12 +#define STATUS_TRUST_MARGINAL 13 +#define STATUS_TRUST_FULLY 14 +#define STATUS_TRUST_ULTIMATE 15 + +#define STATUS_SHM_INFO 16 +#define STATUS_SHM_GET 17 +#define STATUS_SHM_GET_BOOL 18 +#define STATUS_SHM_GET_HIDDEN 19 + +#define STATUS_NEED_PASSPHRASE 20 +#define STATUS_VALIDSIG 21 +#define STATUS_SIG_ID 22 +#define STATUS_ENC_TO 23 +#define STATUS_NODATA 24 +#define STATUS_BAD_PASSPHRASE 25 +#define STATUS_NO_PUBKEY 26 +#define STATUS_NO_SECKEY 27 +#define STATUS_NEED_PASSPHRASE_SYM 28 +#define STATUS_DECRYPTION_FAILED 29 +#define STATUS_DECRYPTION_OKAY 30 +#define STATUS_MISSING_PASSPHRASE 31 +#define STATUS_GOOD_PASSPHRASE 32 +#define STATUS_GOODMDC 33 +#define STATUS_BADMDC 34 +#define STATUS_ERRMDC 35 +#define STATUS_IMPORTED 36 +#define STATUS_IMPORT_RES 37 +#define STATUS_FILE_START 38 +#define STATUS_FILE_DONE 39 +#define STATUS_FILE_ERROR 40 + + +/*-- status.c --*/ +void set_status_fd ( int fd ); +int is_status_enabled ( void ); +void write_status ( int no ); +void write_status_text ( int no, const char *text ); + +#ifdef USE_SHM_COPROCESSING + void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ); +#endif /*USE_SHM_COPROCESSING*/ + +int cpr_enabled(void); +char *cpr_get( const char *keyword, const char *prompt ); +char *cpr_get_utf8( const char *keyword, const char *prompt ); +char *cpr_get_hidden( const char *keyword, const char *prompt ); +void cpr_kill_prompt(void); +int cpr_get_answer_is_yes( const char *keyword, const char *prompt ); +int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ); + + +#endif /*G10_STATUS_H*/ diff -Nru a/security/cryptomark/gnupg/strgutil.c b/security/cryptomark/gnupg/strgutil.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/strgutil.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,591 @@ +/* strgutil.c - string utilities + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "../cryptomark_log.h" + +#include +//#include +//#include +//#include +//#include +#include "types.h" +#include "util.h" +#include "memory.h" + + +//static ushort koi8_unicode[128] = { +// 0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524, +// 0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590, +// 0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248, +// 0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7, +// 0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556, +// 0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e, +// 0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565, +// 0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9, +// 0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433, +// 0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e, +// 0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432, +// 0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a, +// 0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413, +// 0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e, +// 0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412, +// 0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a +//}; +// +//static ushort latin2_unicode[128] = { +// 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, +// 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, +// 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, +// 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, +// 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7, +// 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B, +// 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7, +// 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C, +// 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7, +// 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E, +// 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7, +// 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF, +// 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7, +// 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F, +// 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7, +// 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9 +//}; +// +//static const char *active_charset_name = "iso-8859-1"; +//static ushort *active_charset = NULL; +// +// +//void +//free_strlist( STRLIST sl ) +//{ +// STRLIST sl2; +// +// for(; sl; sl = sl2 ) { +// sl2 = sl->next; +// m_free(sl); +// } +//} +// +// +//STRLIST +//add_to_strlist( STRLIST *list, const char *string ) +//{ +// STRLIST sl; +// +// sl = m_alloc( sizeof *sl + strlen(string)); +// sl->flags = 0; +// strcpy(sl->d, string); +// sl->next = *list; +// *list = sl; +// return sl; +//} +// +///**************** +// * ame as add_to_strlist() but if is_utf8 is *not* set a conversion +// * to UTF8 is done +// */ +//STRLIST +//add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +//{ +// STRLIST sl; +// +// if( is_utf8 ) +// sl = add_to_strlist( list, string ); +// else { +// char *p = native_to_utf8( string ); +// sl = add_to_strlist( list, p ); +// m_free( p ); +// } +// return sl; +//} +// +//STRLIST +//append_to_strlist( STRLIST *list, const char *string ) +//{ +// STRLIST r, sl; +// +// sl = m_alloc( sizeof *sl + strlen(string)); +// sl->flags = 0; +// strcpy(sl->d, string); +// sl->next = NULL; +// if( !*list ) +// *list = sl; +// else { +// for( r = *list; r->next; r = r->next ) +// ; +// r->next = sl; +// } +// return sl; +//} +// +//STRLIST +//append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +//{ +// STRLIST sl; +// +// if( is_utf8 ) +// sl = append_to_strlist( list, string ); +// else { +// char *p = native_to_utf8( string ); +// sl = append_to_strlist( list, p ); +// m_free( p ); +// } +// return sl; +//} +// +// +//STRLIST +//strlist_prev( STRLIST head, STRLIST node ) +//{ +// STRLIST n; +// +// for(n=NULL; head && head != node; head = head->next ) +// n = head; +// return n; +//} +// +//STRLIST +//strlist_last( STRLIST node ) +//{ +// if( node ) +// for( ; node->next ; node = node->next ) +// ; +// return node; +//} +// +// + +/**************** + * look for the substring SUB in buffer and return a pointer to that + * substring in BUF or NULL if not found. + * Comparison is case-insensitive. + */ +const char * +memistr( const char *buf, size_t buflen, const char *sub ) +{ + const byte *t, *s ; + size_t n; + + for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) + if( toupper(*t) == toupper(*s) ) { + for( buf=t++, buflen = n--, s++; + n && toupper(*t) == toupper(*s); t++, s++, n-- ) + ; + if( !*s ) + return buf; + t = buf; n = buflen; s = sub ; + } + + return NULL ; +} + +///**************** +// * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein +// * '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination +// * gleich NULL, so wird via m_alloc Speicher besorgt, ist dann nicht +// * genügend Speicher vorhanden, so bricht die funktion ab. +// */ +//char * +//mem2str( char *dest , const void *src , size_t n ) +//{ +// char *d; +// const char *s; +// +// if( n ) { +// if( !dest ) +// dest = m_alloc( n ) ; +// d = dest; +// s = src ; +// for(n--; n && *s; n-- ) +// *d++ = *s++; +// *d = '\0' ; +// } +// +// return dest ; +//} +// +// +///**************** +// * remove leading and trailing white spaces +// */ +//char * +//trim_spaces( char *str ) +//{ +// char *string, *p, *mark; +// +// string = str; +// /* find first non space character */ +// for( p=string; *p && isspace( *(byte*)p ) ; p++ ) +// ; +// /* move characters */ +// for( (mark = NULL); (*string = *p); string++, p++ ) +// if( isspace( *(byte*)p ) ) { +// if( !mark ) +// mark = string ; +// } +// else +// mark = NULL ; +// if( mark ) +// *mark = '\0' ; /* remove trailing spaces */ +// +// return str ; +//} +// + + +unsigned +trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) +{ + byte *p, *mark; + unsigned n; + + for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { + if( strchr(trimchars, *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if( mark ) { + *mark = 0; + return mark - line; + } + return len; +} + +/**************** + * remove trailing white spaces and return the length of the buffer + */ +unsigned +trim_trailing_ws( byte *line, unsigned len ) +{ + return trim_trailing_chars( line, len, " \t\r\n" ); +} + + + +//int +//string_count_chr( const char *string, int c ) +//{ +// int count; +// for(count=0; *string; string++ ) +// if( *string == c ) +// count++; +// return count; +//} +// +// +//int +//set_native_charset( const char *newset ) +//{ +// if( !stricmp( newset, "iso-8859-1" ) ) { +// active_charset_name = "iso-8859-1"; +// active_charset = NULL; +// } +// else if( !stricmp( newset, "iso-8859-2" ) ) { +// active_charset_name = "iso-8859-2"; +// active_charset = latin2_unicode; +// } +// else if( !stricmp( newset, "koi8-r" ) ) { +// active_charset_name = "koi8-r"; +// active_charset = koi8_unicode; +// } +// else +// return G10ERR_GENERAL; +// return 0; +//} +// +//const char* +//get_native_charset() +//{ +// return active_charset_name; +//} +// +///**************** +// * Convert string, which is in native encoding to UTF8 and return the +// * new allocated UTF8 string. +// */ +//char * +//native_to_utf8( const char *string ) +//{ +// const byte *s; +// char *buffer; +// byte *p; +// size_t length=0; +// +// if( active_charset ) { +// for(s=string; *s; s++ ) { +// length++; +// if( *s & 0x80 ) +// length += 2; /* we may need 3 bytes */ +// } +// buffer = m_alloc( length + 1 ); +// for(p=buffer, s=string; *s; s++ ) { +// if( *s & 0x80 ) { +// ushort val = active_charset[ *s & 0x7f ]; +// if( val < 0x0800 ) { +// *p++ = 0xc0 | ( (val >> 6) & 0x1f ); +// *p++ = 0x80 | ( val & 0x3f ); +// } +// else { +// *p++ = 0xe0 | ( (val >> 12) & 0x0f ); +// *p++ = 0x80 | ( (val >> 6) & 0x3f ); +// *p++ = 0x80 | ( val & 0x3f ); +// } +// } +// else +// *p++ = *s; +// } +// *p = 0; +// } +// else { +// for(s=string; *s; s++ ) { +// length++; +// if( *s & 0x80 ) +// length++; +// } +// buffer = m_alloc( length + 1 ); +// for(p=buffer, s=string; *s; s++ ) { +// if( *s & 0x80 ) { +// *p++ = 0xc0 | ((*s >> 6) & 3); +// *p++ = 0x80 | ( *s & 0x3f ); +// } +// else +// *p++ = *s; +// } +// *p = 0; +// } +// return buffer; +//} +// +// +///**************** +// * Convert string, which is in UTF8 to native encoding. +// * illegal encodings by some "\xnn" and quote all control characters +// */ +//char * +//utf8_to_native( const char *string, size_t length ) +//{ +// int nleft; +// int i; +// byte encbuf[7]; +// int encidx; +// const byte *s; +// size_t n; +// byte *buffer = NULL, *p = NULL; +// unsigned long val = 0; +// size_t slen; +// int resync = 0; +// +// /* 1. pass (p==NULL): count the extended utf-8 characters */ +// /* 2. pass (p!=NULL): create string */ +// for( ;; ) { +// for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) { +// if( resync ) { +// if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) { +// /* still invalid */ +// if( p ) { +// sprintf(p, "\\x%02x", *s ); +// p += 4; +// } +// n += 4; +// continue; +// } +// resync = 0; +// } +// if( !nleft ) { +// if( !(*s & 0x80) ) { /* plain ascii */ +// if( iscntrl( *s ) ) { +// n++; +// if( p ) +// *p++ = '\\'; +// switch( *s ) { +// case '\n': n++; if( p ) *p++ = 'n'; break; +// case '\r': n++; if( p ) *p++ = 'r'; break; +// case '\f': n++; if( p ) *p++ = 'f'; break; +// case '\v': n++; if( p ) *p++ = 'v'; break; +// case '\b': n++; if( p ) *p++ = 'b'; break; +// case 0 : n++; if( p ) *p++ = '0'; break; +// default: n += 3; +// sprintf( p, "x%02x", *s ); +// p += 3; +// break; +// } +// } +// else { +// if( p ) *p++ = *s; +// n++; +// } +// } +// else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */ +// val = *s & 0x1f; +// nleft = 1; +// encbuf[encidx=0] = *s; +// } +// else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */ +// val = *s & 0x0f; +// nleft = 2; +// encbuf[encidx=0] = *s; +// } +// else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */ +// val = *s & 0x07; +// nleft = 3; +// encbuf[encidx=0] = *s; +// } +// else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */ +// val = *s & 0x03; +// nleft = 4; +// encbuf[encidx=0] = *s; +// } +// else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */ +// val = *s & 0x01; +// nleft = 5; +// encbuf[encidx=0] = *s; +// } +// else { /* invalid encoding: print as \xnn */ +// if( p ) { +// sprintf(p, "\\x%02x", *s ); +// p += 4; +// } +// n += 4; +// resync = 1; +// } +// } +// else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */ +// if( p ) { +// sprintf(p, "\\x%02x", *s ); +// p += 4; +// } +// n += 4; +// nleft = 0; +// resync = 1; +// } +// else { +// encbuf[++encidx] = *s; +// val <<= 6; +// val |= *s & 0x3f; +// if( !--nleft ) { /* ready */ +// if( active_charset ) { /* table lookup */ +// for(i=0; i < 128; i++ ) { +// if( active_charset[i] == val ) +// break; +// } +// if( i < 128 ) { /* we can print this one */ +// if( p ) *p++ = i+128; +// n++; +// } +// else { /* we do not have a translation: print utf8 */ +// if( p ) { +// for(i=0; i < encidx; i++ ) { +// sprintf(p, "\\x%02x", encbuf[i] ); +// p += 4; +// } +// } +// n += encidx*4; +// } +// } +// else { /* native set */ +// if( val >= 0x80 && val < 256 ) { +// n++; /* we can simply print this character */ +// if( p ) *p++ = val; +// } +// else { /* we do not have a translation: print utf8 */ +// if( p ) { +// for(i=0; i < encidx; i++ ) { +// sprintf(p, "\\x%02x", encbuf[i] ); +// p += 4; +// } +// } +// n += encidx*4; +// } +// } +// +// } +// +// } +// } +// if( !buffer ) { /* allocate the buffer after the first pass */ +// buffer = p = m_alloc( n + 1 ); +// } +// else { +// *p = 0; /* make a string */ +// return buffer; +// } +// } +//} +// + + +/********************************************* + ********** missing string functions ********* + *********************************************/ + +//#ifndef HAVE_STPCPY +//char * +//stpcpy(char *a,const char *b) +//{ +// while( *b ) +// *a++ = *b++; +// *a = 0; +// +// return (char*)a; +//} +//#endif +// +//#ifndef HAVE_STRLWR +//char * +//strlwr(char *s) +//{ +// char *p; +// for(p=s; *p; p++ ) +// *p = tolower(*p); +// return s; +//} +//#endif + +#ifndef HAVE_STRCASECMP +int +strcasecmp( const char *a, const char *b ) +{ + for( ; *a && *b; a++, b++ ) { + if( *a != *b && toupper(*a) != toupper(*b) ) + break; + } + return *(const byte*)a - *(const byte*)b; +} +#endif + +/**************** + * mingw32/cpd has a memicmp() + */ +#ifndef HAVE_MEMICMP +int +memicmp( const char *a, const char *b, size_t n ) +{ + for( ; n; n--, a++, b++ ) + if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) ) + return *(const byte *)a - *(const byte*)b; + return 0; +} +#endif + + diff -Nru a/security/cryptomark/gnupg/trustdb.h b/security/cryptomark/gnupg/trustdb.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/trustdb.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,82 @@ +/* trustdb.h - Trust database + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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 + + +/* Trust values must be sorted in ascending order */ +#define TRUST_MASK 15 +#define TRUST_UNKNOWN 0 /* o: not yet calculated */ +#define TRUST_EXPIRED 1 /* e: calculation may be invalid */ +#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */ +#define TRUST_NEVER 3 /* n: never trust this pubkey */ +#define TRUST_MARGINAL 4 /* m: marginally trusted */ +#define TRUST_FULLY 5 /* f: fully trusted */ +#define TRUST_ULTIMATE 6 /* u: ultimately trusted */ +/* trust values not covered by the mask */ +#define TRUST_FLAG_REVOKED 32 /* r: revoked */ +#define TRUST_FLAG_SUB_REVOKED 64 +#define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */ + + +#define PREFTYPE_SYM 1 +#define PREFTYPE_HASH 2 +#define PREFTYPE_COMPR 3 + + +/*-- trustdb.c --*/ +void list_trust_path( const char *username ); +void register_trusted_key( const char *string ); +void check_trustdb( const char *username ); +void update_trustdb( void ); +int setup_trustdb( int level, const char *dbname ); +void init_trustdb( void ); +void sync_trustdb( void ); +int check_trust( PKT_public_key *pk, unsigned *r_trustlevel, + const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs ); +int query_trust_info( PKT_public_key *pk, const byte *nh ); +int enum_cert_paths( void **context, ulong *lid, + unsigned *ownertrust, unsigned *validity ); +//void enum_cert_paths_print( void **context, FILE *fp, +// int refresh, ulong selected_lid ); +unsigned get_ownertrust( ulong lid ); +int get_ownertrust_info( ulong lid ); +byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n ); +int is_algo_in_prefs( ulong lid, int preftype, int algo ); +int keyid_from_lid( ulong lid, u32 *keyid ); +ulong lid_from_keyblock( KBNODE keyblock ); +int query_trust_record( PKT_public_key *pk ); +int clear_trust_checked_flag( PKT_public_key *pk ); +int update_trust_record( KBNODE keyblock, int fast, int *modified ); +int insert_trust_record( KBNODE keyblock ); +int insert_trust_record_by_pk( PKT_public_key *pk ); +int update_ownertrust( ulong lid, unsigned new_trust ); +int trust_letter( unsigned value ); + +/*-- tdbdump.c --*/ +void list_trustdb(const char *username); +void export_ownertrust(void); +void import_ownertrust(const char *fname); + +/*-- pkclist.c --*/ +int edit_ownertrust( ulong lid, int mode ); + +#endif /*G10_TRUSTDB_H*/ diff -Nru a/security/cryptomark/gnupg/ttyio.h b/security/cryptomark/gnupg/ttyio.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/ttyio.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,34 @@ +/* ttyio.h + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_TTYIO_H +#define G10_TTYIO_H + +int tty_batchmode( int onoff ); +void tty_printf( const char *fmt, ... ); +void tty_print_string( byte *p, size_t n ); +void tty_print_utf8_string( byte *p, size_t n ); +char *tty_get( const char *prompt ); +char *tty_get_hidden( const char *prompt ); +void tty_kill_prompt(void); +int tty_get_answer_is_yes( const char *prompt ); +int tty_no_terminal(int onoff); + + +#endif /*G10_TTYIO_H*/ diff -Nru a/security/cryptomark/gnupg/types.h b/security/cryptomark/gnupg/types.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/types.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,119 @@ +/* types.h - some common typedefs + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_TYPES_H +#define G10_TYPES_H + + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT + #undef SIZEOF_UNSIGNED_SHORT + #define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT + #undef SIZEOF_UNSIGNED_INT + #define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG + #undef SIZEOF_UNSIGNED_LONG + #define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include "linux/types.h" + +#ifndef HAVE_BYTE_TYPEDEF + #undef byte /* maybe there is a macro with this name */ + typedef unsigned char byte; + #define HAVE_BYTE_TYPEDEF +#endif + +//#ifndef HAVE_USHORT_TYPEDEF +// #undef ushort /* maybe there is a macro with this name */ +// typedef unsigned short ushort; +// #define HAVE_USHORT_TYPEDEF +//#endif +// +//#ifndef HAVE_ULONG_TYPEDEF +// #undef ulong /* maybe there is a macro with this name */ +// typedef unsigned long ulong; +// #define HAVE_ULONG_TYPEDEF +//#endif +// +//#ifndef HAVE_U16_TYPEDEF +// #undef u16 /* maybe there is a macro with this name */ +// #if SIZEOF_UNSIGNED_INT == 2 +// typedef unsigned int u16; +// #elif SIZEOF_UNSIGNED_SHORT == 2 +// typedef unsigned short u16; +// #else +// #error no typedef for u16 +// #endif +// #define HAVE_U16_TYPEDEF +//#endif +// +//#ifndef HAVE_U32_TYPEDEF +// #undef u32 /* maybe there is a macro with this name */ +// #if SIZEOF_UNSIGNED_INT == 4 +// typedef unsigned int u32; +// #elif SIZEOF_UNSIGNED_LONG == 4 +// typedef unsigned long u32; +// #else +// #error no typedef for u32 +// #endif +// #define HAVE_U32_TYPEDEF +//#endif +// +//#ifndef HAVE_U64_TYPEDEF +// #undef u64 /* maybe there is a macro with this name */ +// #if SIZEOF_UNSIGNED_INT == 8 +// typedef unsigned int u64; +// #define HAVE_U64_TYPEDEF +// #elif SIZEOF_UNSIGNED_LONG == 8 +// typedef unsigned long u64; +// #define HAVE_U64_TYPEDEF +// #elif __GNUC__ >= 2 || defined(__SUNPRO_C) +// typedef unsigned long long u64; +// #define HAVE_U64_TYPEDEF +// #endif +//#endif + + +typedef union { + int a; + short b; + char c[1]; + long d; + #ifdef HAVE_U64_TYPEDEF + u64 e; + #endif + float f; + double g; +} PROPERLY_ALIGNED_TYPE; + +typedef struct string_list { + struct string_list *next; + unsigned int flags; + char d[1]; +} *STRLIST; + + +#endif /*G10_TYPES_H*/ diff -Nru a/security/cryptomark/gnupg/util.h b/security/cryptomark/gnupg/util.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/gnupg/util.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,228 @@ +/* util.h + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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_UTIL_H +#define G10_UTIL_H + +#include "types.h" +#include "errors.h" +#include "types.h" +#include "mpi.h" + + +typedef struct { + int *argc; /* pointer to argc (value subject to change) */ + char ***argv; /* pointer to argv (value subject to change) */ + unsigned flags; /* Global flags (DO NOT CHANGE) */ + int err; /* print error about last option */ + /* 1 = warning, 2 = abort */ + int r_opt; /* return option */ + int r_type; /* type of return value (0 = no argument found)*/ + union { + int ret_int; + long ret_long; + ulong ret_ulong; + char *ret_str; + } r; /* Return values */ + struct { + int idx; + int inarg; + int stopped; + const char *last; + void *aliases; + const void *cur_alias; + } internal; /* DO NOT CHANGE */ +} ARGPARSE_ARGS; + +typedef struct { + int short_opt; + const char *long_opt; + unsigned flags; + const char *description; /* optional option description */ +} ARGPARSE_OPTS; + +///*-- logger.c --*/ +//void log_set_logfile( const char *name, int fd ); +////FILE *log_stream(void); +//void g10_log_print_prefix(const char *text); +//void log_set_name( const char *name ); +//const char *log_get_name(void); +//void log_set_pid( int pid ); +//int log_get_errorcount( int clear ); +//void g10_log_hexdump( const char *text, const char *buf, size_t len ); +// +//#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +// void g10_log_bug( const char *fmt, ... ) +// __attribute__ ((noreturn, format (printf,1,2))); +// void g10_log_bug0( const char *, int, const char * ) __attribute__ ((noreturn)); +// void g10_log_fatal( const char *fmt, ... ) +// __attribute__ ((noreturn, format (printf,1,2))); +// void g10_log_error( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); +// void g10_log_info( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); +// void g10_log_debug( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); +// void g10_log_fatal_f( const char *fname, const char *fmt, ... ) +// __attribute__ ((noreturn, format (printf,2,3))); +// void g10_log_error_f( const char *fname, const char *fmt, ... ) +// __attribute__ ((format (printf,2,3))); +// void g10_log_info_f( const char *fname, const char *fmt, ... ) +// __attribute__ ((format (printf,2,3))); +// void g10_log_debug_f( const char *fname, const char *fmt, ... ) +// __attribute__ ((format (printf,2,3))); +// #define BUG() g10_log_bug0( __FILE__ , __LINE__, __FUNCTION__ ) +//#else +// void g10_log_bug( const char *fmt, ... ); +// void g10_log_bug0( const char *, int ); +// void g10_log_fatal( const char *fmt, ... ); +// void g10_log_error( const char *fmt, ... ); +// void g10_log_info( const char *fmt, ... ); +// void g10_log_debug( const char *fmt, ... ); +// void g10_log_fatal_f( const char *fname, const char *fmt, ... ); +// void g10_log_error_f( const char *fname, const char *fmt, ... ); +// void g10_log_info_f( const char *fname, const char *fmt, ... ); +// void g10_log_debug_f( const char *fname, const char *fmt, ... ); +// #define BUG() g10_log_bug0( __FILE__ , __LINE__ ) + #define BUG() g10_log_bug0( __FILE__ ) +//#endif +// +#define log_hexdump g10_log_hexdump +#define log_bug g10_log_bug +#define log_bug0 g10_log_bug0 +#define log_fatal g10_log_fatal +#define log_error g10_log_error +#define log_info g10_log_info +#define log_debug g10_log_debug +#define log_fatal_f g10_log_fatal_f +#define log_error_f g10_log_error_f +#define log_info_f g10_log_info_f +#define log_debug_f g10_log_debug_f + + +/*-- errors.c --*/ +const char * g10_errstr( int no ); + +/*-- argparse.c --*/ +int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +//int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, +// ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +void usage( int level ); +const char *default_strusage( int level ); + + +/*-- (main program) --*/ +const char *strusage( int level ); + + +/*-- dotlock.c --*/ +struct dotlock_handle; +typedef struct dotlock_handle *DOTLOCK; + +DOTLOCK create_dotlock( const char *file_to_lock ); +int make_dotlock( DOTLOCK h, long timeout ); +int release_dotlock( DOTLOCK h ); + + +/*-- fileutil.c --*/ +char * make_basename(const char *filepath); +char * make_dirname(const char *filepath); +char *make_filename( const char *first_part, ... ); +int compare_filenames( const char *a, const char *b ); +const char *print_fname_stdin( const char *s ); +const char *print_fname_stdout( const char *s ); + + +/*-- miscutil.c --*/ +u32 make_timestamp(void); +u32 scan_isodatestr( const char *string ); +u32 add_days_to_timestamp( u32 stamp, u16 days ); +const char *strtimevalue( u32 stamp ); +const char *strtimestamp( u32 stamp ); /* GMT */ +const char *asctimestamp( u32 stamp ); /* localized */ +//void print_string( FILE *fp, const byte *p, size_t n, int delim ); +//void print_utf8_string( FILE *fp, const byte *p, size_t n ); +char *make_printable_string( const byte *p, size_t n, int delim ); +int answer_is_yes( const char *s ); +int answer_is_yes_no_quit( const char *s ); + +/*-- strgutil.c --*/ +void free_strlist( STRLIST sl ); +#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) +STRLIST add_to_strlist( STRLIST *list, const char *string ); +STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST append_to_strlist( STRLIST *list, const char *string ); +STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST strlist_prev( STRLIST head, STRLIST node ); +STRLIST strlist_last( STRLIST node ); +const char *memistr( const char *buf, size_t buflen, const char *sub ); +char *mem2str( char *, const void *, size_t); +char *trim_spaces( char *string ); +unsigned trim_trailing_chars( byte *line, unsigned len, const char *trimchars); +unsigned trim_trailing_ws( byte *line, unsigned len ); +int string_count_chr( const char *string, int c ); +int set_native_charset( const char *newset ); +const char* get_native_charset(void); +char *native_to_utf8( const char *string ); +char *utf8_to_native( const char *string, size_t length ); +int check_utf8_string( const char *string ); + +#ifndef HAVE_MEMICMP +int memicmp( const char *a, const char *b, size_t n ); +#endif +#ifndef HAVE_STPCPY +char *stpcpy(char *a,const char *b); +#endif +#ifndef HAVE_STRLWR +char *strlwr(char *a); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp( const char *, const char *b); +#endif +#ifndef HAVE_STRTOUL + #define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +//#ifndef HAVE_MEMMOVE +// #define memmove(d, s, n) bcopy((s), (d), (n)) +//#endif +#ifndef HAVE_STRICMP + #define stricmp(a,b) strcasecmp( (a), (b) ) +#endif + +/*-- w32reg.c --*/ +#ifdef __MINGW32__ +char *read_w32_registry_string( const char *root, + const char *dir, const char *name ); +#endif + +/**** other missing stuff ****/ +#ifndef HAVE_ATEXIT /* For SunOS */ + #define atexit(a) (on_exit((a),0)) +#endif + +#ifndef HAVE_RAISE + #define raise(a) kill(getpid(), (a)) +#endif + +/******** some macros ************/ +#ifndef STR + #define STR(v) #v +#endif +#define STR2(v) STR(v) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + +#endif /*G10_UTIL_H*/ diff -Nru a/security/cryptomark/main.c b/security/cryptomark/main.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/main.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,262 @@ +/*======================================================================*/ +/* */ +/* Immunix CryptoMark Module */ +/* Copyright 1998, 1999, 2000 Wirex Communications & */ +/* Oregon Graduate Institute */ +/* */ +/* Written by Greg Kroah-Hartman */ +/* */ +/*======================================================================*/ + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ +#endif + +#ifdef MODVERSIONS + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "cryptomark.h" +#include "cryptomark_log.h" +#include "cryptomark_version.h" + +#include "gnupg/errors.h" + +static struct cryptomark_operations ops = { + version: CRYPTOMARK_INTERFACE_VERSION, + compute_elf_sig: crypto_compute_elf_sig, + compare_elf_sig: crypto_compare_elf_sig, +}; + + +const char *cryptomark_title = "WireX/Immunix CryptoMark module"; +const char *cryptomark_copyright = "Copyright 1998, 1999, 2000 WireX Communications Inc."; + +extern unsigned char *cryptomark_key; + +/*====================================================================== +* +* init_module: +* +*======================================================================*/ +int init_module (void) +{ + int error ; + + dbg (__FUNCTION__); + + error = register_cryptomark (&ops); + if (error) { + warn(__FUNCTION__": Unable to register module, error = %d", error); + return error; + } + + proc_init(); + + printk (KERN_INFO "%s v" CRYPTOMARK_VERSION" initialized\n", cryptomark_title); + + return 0; +} + + +/*====================================================================== +* +* cleanup_module: +* +*======================================================================*/ +int cleanup_module ( void ) +{ + dbg (__FUNCTION__); + + proc_done(); + + unregister_cryptomark(&ops); + + printk (KERN_INFO "%s v" CRYPTOMARK_VERSION" removed\n", cryptomark_title); + + return 0; +} + + + +/*====================================================================== +* +* crypto_compare_elf_sig: +* +*======================================================================*/ +extern int crypto_compare_elf_sig (struct dentry *elf_dentry, struct elfhdr *elf_ex, struct immunix_digital_sig *sig, char * name) +{ + struct elf_shdr *elf_shdata = NULL; + struct elf_shdr *section_header; + int elf_section_size; + int i; + int retval ; + int error = -ENOENT; /* Return value */ + unsigned char *stordigest = NULL; + + if (elf_ex->e_shoff == 0) { + dbg (__FUNCTION__ ": %s has no section header in it's ELF header.", name); + return -ENOENT; + } + if (elf_ex->e_shnum == 0) { + dbg (__FUNCTION__ ": %s has no section header entries in it's ELF header.", name); + return -ENOENT; + } + if (elf_ex->e_shentsize == 0) { + dbg (__FUNCTION__ ": %s has no section header size in it's ELF header.", name); + return -ENOENT; + } + if (sig == NULL) { + dbg (__FUNCTION__ ": %s has no md5 sig?", name); + return -ENOENT; + } + + elf_section_size = elf_ex->e_shentsize * elf_ex->e_shnum; + elf_shdata = (struct elf_shdr *)kmalloc (elf_section_size , GFP_KERNEL); + if (!elf_shdata) { + dbg (__FUNCTION__ ": Unable to allocate memory for section header!"); + return -ENOMEM; + } + + /* read the section header into our structure */ + retval = read_exec (elf_dentry, elf_ex->e_shoff, (char *)elf_shdata, elf_section_size, 1); + if (retval != (elf_section_size)) { + dbg (__FUNCTION__": Error reading elf section %s!", name ); + kfree (elf_shdata); + return -1; + } + + /* loop through the sections, looking for the one we are interested in */ + for (i = 0, section_header = elf_shdata; i < elf_ex->e_shnum; i++, section_header++) { + if (section_header->sh_type == SHT_NOTE) { + unsigned char *buf = NULL; + struct elf_note en; + unsigned char * encdigest = NULL; + + buf = (unsigned char *)kmalloc (section_header->sh_size - sizeof (struct elf_note), GFP_KERNEL); + if (!buf) { + warn (__FUNCTION__ ": Unable to allocate memory!" ); + kfree (elf_shdata); + return -ENOMEM ; + } + + retval = read_exec (elf_dentry, section_header->sh_offset, (char *)&en, sizeof(struct elf_note), GFP_KERNEL); + + retval = read_exec (elf_dentry, section_header->sh_offset + sizeof(struct elf_note),(unsigned char *)buf, section_header->sh_size - sizeof (struct elf_note), GFP_KERNEL); + + if (strncmp (buf, CRYPTOMARK_NAME, strlen(CRYPTOMARK_NAME)) == 0) { + encdigest = (unsigned char *)kmalloc (en.n_descsz + 1, GFP_KERNEL); + if (!encdigest) { + warn (__FUNCTION__ ": Unable to allocate memory!"); + kfree (buf); + kfree (elf_shdata); + return -ENOMEM ; + } + + memcpy (encdigest, &buf[(en.n_namesz + ((4 - (en.n_namesz % 4)) % 4))], en.n_descsz); + encdigest[en.n_descsz] = '\0' ; + + dbg(__FUNCTION__": stored signature is:\n%s", encdigest); + + retval = crypto_verify_data (encdigest, en.n_descsz, &stordigest); + dbg(__FUNCTION__": crypto_verify_data return = %d", retval); + switch (retval) { + case 0: + dbg (__FUNCTION__": Good Signature in file %s", name); + error = 0; + break; + + case G10ERR_NO_PUBKEY: + dbg (__FUNCTION__": Good Sig, but couldn't verify public key in file %s", name); + error = EPERM; + break; + + default: + dbg (__FUNCTION__": Bad Signature in file %s", name); + error = EPERM; + break; + } + } + kfree (buf); + kfree (encdigest); + + if (stordigest) { + dbg (__FUNCTION__": md5 in file is: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x", + stordigest[0], stordigest[1], + stordigest[2], stordigest[3], + stordigest[4], stordigest[5], + stordigest[6], stordigest[7], + stordigest[8], stordigest[9], + stordigest[10], stordigest[11], + stordigest[12], stordigest[13], + stordigest[14], stordigest[15]); + } + } /* if */ + } /* for */ + + if (stordigest) { + if (memcmp (sig->md5, stordigest, 16) != 0 ) { + warn (__FUNCTION__": Digests are different :("); + error = EPERM; + } + else { +// error = 0; + dbg (__FUNCTION__": Digests are the same! md5 is: " + "%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x", + sig->md5[0], sig->md5[1], + sig->md5[2], sig->md5[3], + sig->md5[4], sig->md5[5], + sig->md5[6], sig->md5[7], + sig->md5[8], sig->md5[9], + sig->md5[10], sig->md5[11], + sig->md5[12], sig->md5[13], + sig->md5[14], sig->md5[15]); + } + } else { + dbg (__FUNCTION__": No Signature found in file %s", name); + error = -ENOENT; + } + + if (stordigest) + kfree (stordigest); + if (elf_shdata) + kfree (elf_shdata); + + /* let's impose a bit of policy here, if there is any kind of error, + * and we are root, then we force the error to be a fatal one. + * Need to add better policy management in the future. + */ + if ((capable(CAP_SYS_ADMIN)) && + (error < 0)) { + dbg (__FUNCTION__ ": since we have privilidges, and an error occured, make it a fatal error."); + if (cryptomark_key == NULL) { + dbg (__FUNCTION__ ": our key is null, so don't do anything for now."); + error = 0; + } else { + error = -error; + } + } + + return error ; +} + diff -Nru a/security/cryptomark/proc.c b/security/cryptomark/proc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/proc.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,242 @@ +/*====================================================================== +* +* Immunix CryptoMark module +* Copyright 1998, 1999, 2000 Wirex Communications & +* Oregon Graduate Institute +* +* Greg Kroah-Hartman +* +*======================================================================*/ + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ + #include +#endif + + + +/* __NO_VERSION__ is needed or else symbols get defined multiply */ +#define __NO_VERSION__ +#include +//#include + +#include +#include +#include + +#include "cryptomark.h" +#include "cryptomark_log.h" +#include "cryptomark_version.h" + + +#ifdef CONFIG_PROC_FS +static void __proc_init (void); +static void __proc_done (void); + +static struct proc_dir_entry *root; + + +#endif + + +unsigned char *cryptomark_key; /* loader will set to NULL when module is loaded */ +unsigned long cryptomark_key_length; + +int cryptomark_add_key_data (unsigned char *data, unsigned long length) +{ + unsigned long count; +#ifdef CONFIG_CRYPTOMARK_DEBUG + int i; +#endif + + dbg (__FUNCTION__" - length = %ld", length); + + if (cryptomark_key == NULL) { + cryptomark_key = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!cryptomark_key) { + err (__FUNCTION__" - out of memory."); + return -ENOMEM; + } + cryptomark_key_length = 0; + } + + count = MIN(length, PAGE_SIZE-cryptomark_key_length); + + memcpy (&cryptomark_key[cryptomark_key_length], data, count); + + cryptomark_key_length += count; + +#ifdef CONFIG_CRYPTOMARK_DEBUG + printk (KERN_DEBUG "CryptoMark: "__FUNCTION__" - cryptomark_key_length = %ld, cryptomark_key = ", cryptomark_key_length); + for (i = 0; i < cryptomark_key_length; ++i) { + printk ("%.2x ", cryptomark_key[i]); + } + printk ("\n"); +#endif; + + return count; +} + + +/*====================================================================== +* +* +*======================================================================*/ +void proc_init (void) +{ + dbg (__FUNCTION__); +#ifdef CONFIG_PROC_FS + __proc_init(); +#else + dbg (__FUNCTION__": CONFIG_PROC_FS is not enabled, so no /proc"); +#endif +} + + +/*====================================================================== +* +* +*======================================================================*/ +void proc_done (void) +{ + dbg (__FUNCTION__); +#ifdef CONFIG_PROC_FS + __proc_done(); +#else + dbg (__FUNCTION__": CONFIG_PROC_FS is not enabled, so no /proc"); +#endif +} + +#ifdef CONFIG_PROC_FS + + +/*====================================================================== +* +* +*======================================================================*/ +static int proc_version_read (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf (page + len, + "%s\n" + "Version " CRYPTOMARK_VERSION "\n" + "For the Immunix Scaffold " IMMUNIX_SCAFFOLD_VERSION"\n" + "%s\n" + "Compiled on " __DATE__ " for kernel " UTS_RELEASE +#ifdef __SMP__ + " (SMP)" +#endif +#ifdef MODVERSIONS + " with versioned symbols" +#endif +#ifdef CONFIG_SECURE_STACK + "\n\t\t\tand non-executable stack" +#endif + ".\n", + cryptomark_title, cryptomark_copyright); + + return len; +} + + +/*====================================================================== +* +* +*======================================================================*/ +static int proc_key_read (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf (page + len, "Like I would just give up my key to you that easy...\n"); + return len; +} + + +/*====================================================================== +* +* +*======================================================================*/ +static int proc_key_write (struct file *file, const char *buffer, unsigned long count, void *data) +{ + unsigned char *key; + int result; +#ifdef CONFIG_CRYPTOMARK_DEBUG + int i; +#endif + + dbg (__FUNCTION__" - count = %ld", count); + dbg (__FUNCTION__" - PAGE_SIZE = %ld", PAGE_SIZE); + + if (count == 0) { + return 0; + } + + key = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!key) { + err (__FUNCTION__" - out of memory."); + return -ENOMEM; + } + + copy_from_user(key, buffer, count = MIN(count, PAGE_SIZE)); + +#ifdef CONFIG_CRYPTOMARK_DEBUG + printk (KERN_DEBUG "CryptoMark: "__FUNCTION__" - data = "); + for (i = 0; i < count; ++i) { + printk ("%.2x ", key[i]); + } + printk ("\n"); +#endif + + result = cryptomark_add_key_data (key, count); + if (result != count) { + err(__FUNCTION__" - key too big for internal buffer, things are probably messed up now."); + } + + free_page ((unsigned long)key); + + return count; +} + + +/*====================================================================== +* +* +*======================================================================*/ +static void __proc_init (void) +{ + struct proc_dir_entry *p; + + root = create_proc_entry ("cryptomark", S_IFDIR | S_IRUGO | S_IXUGO, NULL); + p = create_proc_entry ("version", S_IFREG | S_IRUGO, root); + p->read_proc = proc_version_read; + + p = create_proc_entry ("key", S_IFREG | S_IRUGO, root); + p->read_proc = proc_key_read; + p->write_proc = proc_key_write; +} + + +/*====================================================================== +* +* +*======================================================================*/ +static void __proc_done (void) +{ + remove_proc_entry ("version", root); + remove_proc_entry ("cryptomark", NULL); + + /* clean up our key if we have created one */ + if (cryptomark_key != NULL) { + free_page ((unsigned long)cryptomark_key); + cryptomark_key = NULL; + } + +} + + + +#endif /* CONFIG_PROC_FS */ + diff -Nru a/security/cryptomark/rc.cryptomark b/security/cryptomark/rc.cryptomark --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/rc.cryptomark Mon Feb 2 14:26:23 2004 @@ -0,0 +1,86 @@ +#!/bin/sh +# +# $Id: rc.cryptomark,v 1.2 2000/11/29 01:27:37 greg Exp $ +#/* +##include +# +#*/ +# +# rc.cryptomark by Greg Kroah-Hartman +# +# chkconfig: 2345 01 99 +# description: CryptoMark rc file. This rc script inserts the cryptomark \ +# module and loads the public key into the module. + +# source function library +if [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +elif [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +else + exit 0 +fi + +# Some nice defines that we use +KEY_DIR=/etc/cryptomark +KEY_FILE=pubring.gpg +MODULE=cryptomark + +usage() +{ + echo "Usage: $0 {start|stop|restart}" +} + +cleanup() +{ + echo "" +} + +function start() +{ + action "Loading CryptoMark modules" /sbin/modprobe $MODULE + + # load the public key into the kernel + echo -n "Loading CryptoMark public key" + if [ -f "$KEY_DIR/$KEY_FILE" ]; then + /bin/sh -c "cp -f $KEY_DIR/$KEY_FILE /proc/$MODULE/key > /dev/null 2>&1" + success "Loading CryptoMark public key" || \ + failure "Loading CryptoMark public key" + echo + else + echo -n " - CryptoMark public key not found" + failure + echo + exit 1 + fi +} + +function stop() +{ + action "Unloading CryptoMark modules" /sbin/modprobe -r $MODULE +} + +function restart() +{ + stop + start +} + + + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + *) + usage + exit 1 + esac +exit 0 + diff -Nru a/security/cryptomark/verify.c b/security/cryptomark/verify.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/cryptomark/verify.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,57 @@ +/*====================================================================== +* +* Immunix CryptoMark module +* Copyright 1998, 1999, 2000 Wirex Communications +* +* Greg Kroah-Hartman +* +*======================================================================*/ + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ +#endif + +#ifdef MODVERSIONS + #include +#endif + + +/* __NO_VERSION__ is needed or else symbols get defined multiply */ +#define __NO_VERSION__ +#include +#include + +#include +#include + +/* #undef DEBUG_CODOMAIN */ +#define DEBUG_CODOMAIN + +#include "cryptomark.h" + +//int crypto_verify_data (unsigned char * inp, unsigned long size, unsigned char **data ) +//{ +// CTX c = m_alloc_clear (sizeof * c); +// int result; +// IOBUF a = NULL; +// armor_filter_context_t afx; +// +// if (!(a = iobuf_temp_with_content (inp, size))) { +// warn (__FUNCTION__ ": can't create temp IOBUF"); +// return -1; +// } else { +// if (use_armor_filter (a)) { +// memset (&afx , 0, sizeof(afx)); +// iobuf_push_filter (a, armor_filter, &afx); +// } +// result = do_proc_packets_data (c, a, data); +// dbg (__FUNCTION__": rc = %d", rc); +// m_free (c); +// return rc; +// } +// return 0; +//} + + diff -Nru a/security/md5/CHANGELOG b/security/md5/CHANGELOG --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/CHANGELOG Mon Feb 2 14:26:23 2004 @@ -0,0 +1,13 @@ +Version 0.3 + - small debug log message cleanups to make it more like the + CryptoMark module + +Version 0.2 + - Makefile now works properly for SMP + - added version to the kernel log message on insertion and + removal. + +Version 0.1 + - initial creation of the module + + diff -Nru a/security/md5/Makefile b/security/md5/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/Makefile Mon Feb 2 14:26:23 2004 @@ -0,0 +1,13 @@ +O_TARGET := md5.o + +list-multi := immunix-md5.o + +immunix-md5-objs := md5.o calc_sig.o + +obj-$(CONFIG_CRYPTOMARK) += immunix-md5.o + +include $(TOPDIR)/Rules.make + +immunix-md5.o: $(immunix-md5-objs) + $(LD) -r -o $@ $(immunix-md5-objs) + diff -Nru a/security/md5/calc_sig.c b/security/md5/calc_sig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/calc_sig.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,220 @@ +/*======================================================================*/ +/* */ +/* Immunix CoDomain Module */ +/* Copyright 1998, 1999, 2000 Wirex Communications & */ +/* Oregon Graduate Institute */ +/* */ +/* Written by Steve Beattie */ +/* */ +/* codomain-x.x.x/CoDomain/codomain_calc_sig.c: */ +/* */ +/*======================================================================*/ + +/* Module versioning code */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#undef DEBUG +/* #define DEBUG */ + + +/* Debugging and other syslog macros */ +#ifdef DEBUG + #define dbg(fmt, args...) printk(KERN_DEBUG "Immunix: " fmt "\n" , ## args) +#else + #define dbg(fmt, args...) do {} while (0) +#endif + +#define err(format, arg...) printk(KERN_ERR "Immunix: " format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO "Immunix: " format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "Immunix: " format "\n" , ## arg) + + +#include "immunix-md5_version.h" +#include "md5.h" + + +/*======================================================================*/ +/* */ +/* init_module: */ +/* Required by module interface. Performs initialization work -- */ +/* i.e. registering the table of functions that the module */ +/* performs. */ +/* */ +/*======================================================================*/ + +int init_module (void) +{ + printk (KERN_INFO "WireX/Immunix MD5 generation module v"IMMUNIX_MD5_VERSION" initialized.\n"); + return 0; +} + +/*======================================================================*/ +/* */ +/* cleanup_module: */ +/* Required by Linux module interface. Performs cleanup work -- */ +/* since we're removing the codomain code, we should also free any */ +/* existing structures, since nothing will be left to operate on */ +/* them. */ +/* */ +/*======================================================================*/ + +int +cleanup_module (void) +{ + printk (KERN_INFO "WireX/Immunix MD5 generation module "IMMUNIX_MD5_VERSION" removed.\n"); + return 0; +} + + +/*======================================================================*/ +/* */ +/* immunix_compute_elf_sig: */ +/* Computes and returns a digital signature for elf executables. */ +/* */ +/*======================================================================*/ + +struct immunix_digital_sig * immunix_compute_elf_sig (struct elf_phdr *elf_phdata, int elf_e_phnum, char *name) +{ + struct immunix_digital_sig *sig; + MD5_CTX ctx; + int i; + struct elf_phdr * elf_ppnt; + + dbg (__FUNCTION__ ": %s", name); + + sig = kmalloc (sizeof (struct immunix_digital_sig), GFP_KERNEL); + + if (!sig) { + warn (__FUNCTION__ ": couldn't allocate memory"); + return NULL; + } + + MD5Init ( &ctx , 0 ) ; + for (i = 0, elf_ppnt = elf_phdata; i < elf_e_phnum; i++, elf_ppnt++) { + if (elf_ppnt->p_type == PT_LOAD) { + dbg("Found section: addr [%lx] len [%lx]", (unsigned long)elf_ppnt->p_vaddr, (unsigned long)elf_ppnt->p_filesz ); + MD5Update (&ctx , (void *)elf_ppnt->p_vaddr, elf_ppnt->p_filesz, 1); + } + } + + MD5Final (sig->md5, &ctx); + +#ifdef CONFIG_CODOMAIN_SYSLOG_SPAM + info ( "md5 %s (pid %d ppid %d uid %d) is: " + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x", + name, current->pid, + current->p_pptr->pid, + current->uid , + sig->md5[0], sig->md5[1], sig->md5[2], sig->md5[3], + sig->md5[4], sig->md5[5], sig->md5[6], sig->md5[7], + sig->md5[8], sig->md5[9], sig->md5[10], sig->md5[11], + sig->md5[12], sig->md5[13], sig->md5[14], sig->md5[15] + ); +#endif /* CONFIG_CODOMAIN_SYSLOG_SPAM */ + + return sig; +} + +/*======================================================================*/ +/* */ +/* immunix_compute_script_sig: */ +/* Computes and returns a digital signature for scripts. */ +/* */ +/*======================================================================*/ + +struct immunix_digital_sig * immunix_compute_script_sig (struct dentry *script_dentry, char *name) +{ + struct immunix_digital_sig * sig; + MD5_CTX ctx; + int retval; + int amount_read = 0; + int data_to_read = 0; + unsigned char *script_data = NULL; /* Kernel space to load a chunk */ + /* of the script into */ + + dbg ("SCRIPT md5 filename: %s inode->i_size %ld " + "inode->i_blksize %ld inode->i_blocks %ld dentry_name %s", + name, + script_dentry->d_inode->i_size, + script_dentry->d_inode->i_blksize, + script_dentry->d_inode->i_blocks, + script_dentry->d_name.name + ); + + sig = kmalloc (sizeof (struct immunix_digital_sig), GFP_KERNEL); + + if (!sig) { + warn (__FUNCTION__ ": couldn't allocate memory"); + return NULL; + } + + script_data = (unsigned char *) __get_free_page (GFP_KERNEL); + + if ( !script_data ) { + warn (__FUNCTION__ ": couldn't allocate memory"); + kfree (sig); + return NULL; + } + + MD5Init (&ctx , 0); + + while (amount_read < script_dentry->d_inode->i_size) { + data_to_read = ( amount_read + PAGE_SIZE < + script_dentry->d_inode->i_size ) + ? PAGE_SIZE + :(script_dentry->d_inode->i_size - amount_read); + + retval = read_exec (script_dentry, amount_read, + script_data, data_to_read, 1); + + if (retval != data_to_read) + warn ( __FUNCTION__": error doing read_exec: " + "len: %d retval: %d seek: %d" , + data_to_read, + retval, + amount_read); + + MD5Update (&ctx, script_data, data_to_read, 0); + + amount_read += data_to_read; + } + + free_page ((unsigned long)script_data); + + MD5Final (sig->md5, &ctx); + +#ifdef CONFIG_CODOMAIN_SYSLOG_SPAM + info ("SCRIPT md5 %s (pid %d ppid %d uid %d inode->i_size %ld) is: " + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x" , + name, current->pid, current->p_pptr->pid, + current->uid, script_dentry->d_inode->i_size, + sig->md5[0], sig->md5[1], sig->md5[2], sig->md5[3], + sig->md5[4], sig->md5[5], sig->md5[6], sig->md5[7], + sig->md5[8], sig->md5[9], sig->md5[10], sig->md5[11], + sig->md5[12], sig->md5[13], sig->md5[14], sig->md5[15] + ); +#endif /* CONFIG_CODOMAIN_SYSLOG_SPAM */ + + return sig; +} + + + diff -Nru a/security/md5/immunix-md5_version.h b/security/md5/immunix-md5_version.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/immunix-md5_version.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1 @@ +#define IMMUNIX_MD5_VERSION "0.3" diff -Nru a/security/md5/md5.c b/security/md5/md5.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/md5.c Mon Feb 2 14:26:23 2004 @@ -0,0 +1,300 @@ + +/*======================================================================*/ +/* */ +/* Immunix MD5 Module */ +/* This code was taken from RedHat's RPM program source. It's been */ +/* modified to work in the kernel context. */ +/* */ +/*======================================================================*/ + + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* Module versioning code */ +#include /* Retrieve the CONFIG_* macros */ +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) + #define MODVERSIONS /* Force it on */ +#endif + +#ifdef MODVERSIONS + #include +#endif + +#include +// #include +#include "md5.h" +#include +#include +#include + +#define __NO_VERSION__ +#include + +void byteReverse(unsigned char *buf, unsigned longs); + +/* + * Note: this code is harmless on little-endian machines. + */ +void +byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(struct MD5Context *ctx, int brokenEndian) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; + +#ifdef WORDS_BIGENDIAN + if (brokenEndian) { + ctx->doByteReverse = 0; + } else { + ctx->doByteReverse = 1; + } +#else + ctx->doByteReverse = 0; +#endif +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + * + * The from_user parameter should indicate whether buf is a user + * or kernel address. If it is a user address, it *MUST* be valid, + * as this guy does not do checking. + */ +void +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len, + int is_from_user) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + (is_from_user ? ( void * ) copy_from_user (p, buf, len) + : memcpy(p, buf, len)); + return; + } + (is_from_user ? ( void * ) copy_from_user (p, buf, t) + : memcpy(p, buf, t)); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + (is_from_user ? ( void * ) copy_from_user (ctx->in, buf, 64) + : memcpy(ctx->in, buf, 64)); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + (is_from_user ? (void *) copy_from_user (ctx->in, buf, len) + : memcpy(ctx->in, buf, len)); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + if (ctx->doByteReverse) + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + if (ctx->doByteReverse) + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + diff -Nru a/security/md5/md5.h b/security/md5/md5.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/security/md5/md5.h Mon Feb 2 14:26:23 2004 @@ -0,0 +1,52 @@ +/*======================================================================*/ +/* */ +/* Immunix CoDomain Toolkit: */ +/* */ +/* This code was taken from RedHat's RPM program source. It's been */ +/* modified to work in the kernel context. */ +/* */ +/* codomain-x.x.x/CoDomain/codomain_md5.h: */ +/* */ +/*======================================================================*/ + +#ifndef COD_MD5_H +#define COD_MD5_H + +#ifdef __alpha +typedef unsigned int uint32; +#else +typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; + int doByteReverse; +}; + +void MD5Init(struct MD5Context *context, int brokenEndian); +#ifdef __KERNEL__ +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len, int from_user); +#else /* __KERNEL__ */ +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +#endif /* __KERNEL__ */ +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(uint32 buf[4], uint32 const in[16]); + +int mdfile(char *fn, unsigned char *digest); +int mdbinfile(char *fn, unsigned char *bindigest); + +/* These assume a little endian machine and return incorrect results! + They are here for compatibility with old (broken) versions of RPM */ +int mdfileBroken(char *fn, unsigned char *digest); +int mdbinfileBroken(char *fn, unsigned char *bindigest); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !COD_MD5_H */