diff -rNu linux.orig-2.6.19/security/digsig/digsig.c linux-2.6.19/security/digsig/digsig.c --- linux.orig-2.6.19/security/digsig/digsig.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,760 @@ +/* + * Digital Signature (DigSig) + * + * This file contains the digsig hook to the kernel. + * The set of function was defined by the LSM interface. + * + * Copyright (C) 2002-2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: David Gordon Aug 2003 + * modifs: Makan Pourzandi Nov 2003 - Sept 2004: fixes - Feb 2005: bug fix + * Vincent Roy Nov 2003: add functionality for mmap + * Serge Hallyn Jan 2004: add caching of signature validation + * Chris Wright Sept 2004: many fixes + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "digsig_sig_verify.h" +#include "digsig_debug.h" +#include "digsig.h" +#include "digsig_sysfs.h" +#include "digsig_cache.h" +#include "digsig_revocation.h" + +#include "gnupg/mpi/mpi.h" +#include "gnupg/cipher/rsa-verify.h" + +#ifdef DIGSIG_DEBUG +#define DIGSIG_MODE 0 /*permissive mode */ +#define DIGSIG_BENCH 1 +#else +#define DIGSIG_MODE -EPERM /*restrictive mode */ +#define DIGSIG_BENCH 0 +#endif + +#define get_inode_security(ino) ((unsigned long)(ino->i_security)) +#define set_inode_security(ino,val) (ino->i_security = (void *)val) + +#define get_file_security(file) ((unsigned long)(file->f_security)) +#define set_file_security(file,val) (file->f_security = (void *)val) + +unsigned long int total_jiffies = 0; + +/* Allocate and free functions for each kind of security blob. */ +static DECLARE_MUTEX(digsig_sem); + +/* Indicate if module as key or not */ +int g_init = 0; + +/* Keep track of how we are registered */ +static int secondary; + +#ifdef DIGSIG_LOG +int DigsigDebugLevel = DEBUG_INIT | DEBUG_SIGN; +#else +int DigsigDebugLevel = DEBUG_INIT; +#endif + +int dsi_cache_buckets = 128; +module_param(dsi_cache_buckets, int, 0); +MODULE_PARM_DESC(dsi_cache_buckets, "Number of cache buckets for signatures validations.\n"); + + +/****************************************************************************** +Description : + * For a file being opened for write, check: + * 1. whether it is a library currently being dlopen'ed. If it is, then + * inode->i_security > 0. + * 2. whether the file being opened is an executable or library with a + * cached signature validation. If it is, remove the signature validation + * entry so that on the next load, the signature will be recomputed. + * + * We the write to happen and check the signature when loading to + * decide about the validity of the action. Not because the hacker + * can modify the file that he could compromise the system. Because, + * the new library needs to have a valid signature (i.e. the admin + * must use the right private key to sign his library) to get loaded. +Parameters : +Return value: +******************************************************************************/ +static int +digsig_inode_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + if (!g_init) + return 0; + + if (inode && mask & MAY_WRITE) { + unsigned long isec = get_inode_security(inode); + if (isec > 0) + return -EPERM; + if (is_cached_signature(inode)) + remove_signature(inode); + } + + return 0; +} + +/****************************************************************************** +Description : + * If an inode is unlinked, we don't want to hang onto it's + * signature validation ticket +Parameters : +Return value: +******************************************************************************/ +static int +digsig_inode_unlink(struct inode *dir, struct dentry *dentry) +{ + if (!g_init) + return 0; + + if (!is_cached_signature(dentry->d_inode)) + return 0; + + remove_signature(dentry->d_inode); + return 0; +} + +static char *digsig_read_signature(struct file *file, unsigned long offset) +{ + int retval; + char *buffer = kmalloc(DIGSIG_ELF_SIG_SIZE, DIGSIG_SAFE_ALLOC); + + if (!buffer) { + DSM_ERROR ("kmalloc failed in %s for buffer.\n", __FUNCTION__); + return NULL; + } + retval = kernel_read(file, offset, (char *) buffer, + DIGSIG_ELF_SIG_SIZE); + if (retval != DIGSIG_ELF_SIG_SIZE) { + DSM_PRINT(DEBUG_SIGN, "%s: Unable to read signature: %d\n", + __FUNCTION__, retval); + kfree(buffer); + buffer = NULL; + } + + return buffer; +} + +/****************************************************************************** +Description : find signature section in elf binary + caller is responsible for deallocating memory of buffer returned +Parameters : + elf_ex is elf header + elf_shdata is all entries in section header table of elf + file contains file handle of binary + sh_offset is offset of signature section in elf. sh_offset is set to offset + of signature section in elf +Return value: Upon suscess: buffer containing signature (size of signature is fixed + depending on algorithm used) + Failure: null pointer +******************************************************************************/ +static char *digsig_find_signature32(struct elf32_hdr *elf_ex, + Elf32_Shdr * elf_shdata, struct file *file, + unsigned long *sh_offset) +{ + int i = 0; + char *buffer; + + while (i < elf_ex->e_shnum + && elf_shdata[i].sh_type != DIGSIG_ELF_SIG_SECTION) { + i++; + } + + if (i == elf_ex->e_shnum) + return NULL; + if (elf_shdata[i].sh_type != DIGSIG_ELF_SIG_SECTION) + return NULL; + if (elf_shdata[i].sh_size != DIGSIG_ELF_SIG_SIZE) + return NULL; + + buffer = digsig_read_signature(file, elf_shdata[i].sh_offset); + if (!buffer) + return NULL; + + *sh_offset = elf_shdata[i].sh_offset; + + return buffer; +} + +static char *digsig_find_signature64(struct elf64_hdr *elf_ex, + Elf64_Shdr * elf_shdata, struct file *file, + unsigned long *sh_offset) +{ + int i = 0; + char *buffer; + + while (i < elf_ex->e_shnum + && elf_shdata[i].sh_type != DIGSIG_ELF_SIG_SECTION) { + i++; + } + + if (i == elf_ex->e_shnum) + return NULL; + if (elf_shdata[i].sh_type != DIGSIG_ELF_SIG_SECTION) + return NULL; + if (elf_shdata[i].sh_size != DIGSIG_ELF_SIG_SIZE) + return NULL; + + buffer = digsig_read_signature(file, elf_shdata[i].sh_offset); + if (!buffer) + return NULL; + + *sh_offset = elf_shdata[i].sh_offset; + + return buffer; +} + +/****************************************************************************** +Description : verify if signature matches binary's signature +Parameters : + filename of elf executable + elf_shdata is the data of the signature section + sig_orig is the original signature of the binary + file is the file handle of the binary + sh_offset is offset of signature section in elf +Return value: 0 for false or 1 for true or -1 for error +******************************************************************************/ +static int +digsig_verify_signature(char *sig_orig, struct file *file, + unsigned long sh_offset) +{ + char *read_blocks = NULL; + int retval = -EPERM; + unsigned int lower, upper, offset; + loff_t i_size; + SIGCTX *ctx = NULL; + + down (&digsig_sem); + if (digsig_is_revoked_sig(sig_orig)) { + DSM_ERROR("%s: Refusing attempt to load an ELF file with" + " a revoked signature.\n", __FUNCTION__); + goto out; + } + + retval = -ENOMEM; + ctx = digsig_sign_verify_init(HASH_SHA1, SIGN_RSA); + if (!ctx ) { + DSM_PRINT(DEBUG_SIGN, + "%s: Cannot allocate crypto context.\n", __FUNCTION__); + goto out; + } + + read_blocks = kmalloc(DIGSIG_ELF_READ_BLOCK_SIZE, DIGSIG_SAFE_ALLOC); + if (!read_blocks) { + DSM_ERROR ("kmalloc failed in %s for read_block.\n", __FUNCTION__); + goto out; + } + + i_size = i_size_read(file->f_dentry->d_inode); + for (offset = 0; offset < i_size; offset += DIGSIG_ELF_READ_BLOCK_SIZE){ + + retval = kernel_read(file, offset, (char *) read_blocks, + DIGSIG_ELF_READ_BLOCK_SIZE); + if (retval <= 0) { + DSM_PRINT(DEBUG_SIGN, + "%s: Unable to read signature in blocks: %d\n", + __FUNCTION__, retval); + goto out; + } + + /* Makan: This is in order to avoid building a buffer + inside the kernel. At each read we check to be sure + that the parts of the signature read are set to 0 */ + /* Must zero out signature section to match bsign mechanism */ + lower = sh_offset; /* lower bound of memset */ + upper = sh_offset + DIGSIG_ELF_SIG_SIZE; /* upper bound */ + + if ((lower < offset + DIGSIG_ELF_READ_BLOCK_SIZE) && + (offset < upper)) { + lower = (offset > lower) ? offset : lower; + upper = (offset + DIGSIG_ELF_READ_BLOCK_SIZE < + upper) ? offset + + DIGSIG_ELF_READ_BLOCK_SIZE : upper; + + memset(read_blocks + (lower - offset), 0, + upper - lower); + } + + /* continue verification loop */ + retval = digsig_sign_verify_update(ctx, read_blocks, retval); + if (retval < 0) { + DSM_PRINT(DEBUG_SIGN, + "%s: Error updating crypto verification\n", __FUNCTION__); + goto out; + } + } + + /* A bit of bsign formatting else hashes won't match, works with bsign v0.4.4 */ + retval = digsig_sign_verify_final(ctx, DIGSIG_ELF_SIG_SIZE, + sig_orig + DIGSIG_BSIGN_INFOS); + if (retval != 0) { + DSM_PRINT(DEBUG_SIGN, + "%s: Error calculating final crypto verification\n", __FUNCTION__); + retval = -EPERM; + goto out; + } + + // retval = 0; + +out: + kfree(read_blocks); + if (ctx) { + kfree(ctx->tvmem); + kfree(ctx); + } + up (&digsig_sem); + return retval; +} + +/* + * If the file is opened for writing, deny mmap(PROT_EXEC) access. + * Otherwise, increment the inode->i_security, which is our own + * writecount. When the file is closed, f->f_security will be 1, + * and so we will decrement the inode->i_security. + * Just to be clear: file->f_security is 1 or 0. inode->i_security + * is the *number* of processes which have this file mmapped(PROT_EXEC), + * so it can be >1. + */ +static int digsig_deny_write_access(struct file *file) +{ + struct inode *inode = file->f_dentry->d_inode; + unsigned long isec; + + spin_lock(&inode->i_lock); + isec = get_inode_security(inode); + if (atomic_read(&inode->i_writecount) > 0) { + spin_unlock(&inode->i_lock); + return -ETXTBSY; + } + set_inode_security(inode, (isec+1)); + set_file_security(file, 1); + spin_unlock(&inode->i_lock); + + return 0; +} + +/* + * decrement our writer count on the inode. When it hits 0, we will + * again allow opening the inode for writing. + */ +static void digsig_allow_write_access(struct file *file) +{ + struct inode *inode = file->f_dentry->d_inode; + unsigned long isec; + + spin_lock(&inode->i_lock); + isec = get_inode_security(inode); + set_inode_security(inode, (isec-1)); + set_file_security(file, 0); + spin_unlock(&inode->i_lock); +} + +/* + * the file is being closed. If we ever mmaped it for exec, then + * file->f_security>0, and we decrement the inode usage count to + * show that we are done with it. + */ +static void digsig_file_free_security(struct file *file) +{ + if (file->f_security) { + digsig_allow_write_access(file); + } +} + +/** + * Basic verification of an ELF header + * + * @param elf_hdr pointer to an elfhdr + * @return 0 if header ok, -2 if non-elf, -1 otherwise + */ +static inline int elf_sanity_check32(struct elf32_hdr *elf_hdr) +{ + if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) { + DSM_PRINT(DEBUG_SIGN, "%s: Binary is not elf format\n", + __FUNCTION__); + return -2; + } + + if (!elf_hdr->e_shoff) { + DSM_ERROR("%s: No section header!\n", __FUNCTION__); + return -1; + } + + if (elf_hdr->e_shentsize != sizeof(Elf32_Shdr)) { + DSM_ERROR("%s: Section header is wrong size!\n", __FUNCTION__); + return -1; + } + + if (elf_hdr->e_shnum > 65536U / sizeof(Elf32_Shdr)) { + DSM_ERROR("%s: Too many entries in Section Header!\n", + __FUNCTION__); + return -1; + } + + return 0; +} + +static inline int elf_sanity_check64(struct elf64_hdr *elf_hdr) +{ + if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) { + DSM_PRINT(DEBUG_SIGN, "%s: Binary is not elf format\n", + __FUNCTION__); + return -2; + } + + if (!elf_hdr->e_shoff) { + DSM_ERROR("%s: No section header!\n", __FUNCTION__); + return -1; + } + + if (elf_hdr->e_shentsize != sizeof(Elf64_Shdr)) { + DSM_ERROR("%s: Section header is wrong size!\n", __FUNCTION__); + return -1; + } + + if (elf_hdr->e_shnum > 65536U / sizeof(Elf64_Shdr)) { + DSM_ERROR("%s: Too many entries in Section Header!\n", + __FUNCTION__); + return -1; + } + + return 0; +} + +/* + * If we decide mmap of nonelf is bad, we can make this -EPERM. + * However, note that bsign does mmap of SYSV shmem, so we can't + * run bsign under digsig... that's just funny :) + */ +#define NONELF_PERM NULL + +static inline struct elf64_hdr *read_elf_header(struct file *file) +{ + struct elf64_hdr *elf_ex; + int retval; + + elf_ex = kmalloc(sizeof(struct elf64_hdr), DIGSIG_SAFE_ALLOC); + if (!elf_ex) { + DSM_ERROR ("%s: kmalloc failed for elf_ex\n", __FUNCTION__); + return ERR_PTR(-ENOMEM); + } + + kernel_read(file, 0, (char *)elf_ex, sizeof(struct elf64_hdr)); + + if (elf_ex->e_ident[EI_CLASS] == ELFCLASS32) + retval = elf_sanity_check32((struct elf32_hdr *) elf_ex); + else + retval = elf_sanity_check64(elf_ex); + if (retval) { + kfree(elf_ex); + if (retval == -1) + return ERR_PTR(-EINVAL); + else + return NONELF_PERM; + } + + return elf_ex; +} + +static inline Elf64_Shdr * +read_section_header(struct file *file, unsigned long sh_size, + unsigned long sh_off) +{ + Elf64_Shdr *elf_shdata; + int retval; + + elf_shdata = kmalloc(sh_size, DIGSIG_SAFE_ALLOC); + if (!elf_shdata) { + DSM_ERROR("%s: Cannot allocate memory to read Section Header\n", + __FUNCTION__); + return ERR_PTR(-ENOMEM); + } + + retval = kernel_read(file, sh_off, (char *)elf_shdata, sh_size); + + if (retval < 0 || (unsigned long)retval != sh_size) { + DSM_ERROR("%s: Unable to read binary %s (offset %lu size %lu): %d\n", __FUNCTION__, + file->f_dentry->d_name.name, sh_off, sh_size, retval); + kfree(elf_shdata); + return ERR_PTR(-EINVAL); + } + return elf_shdata; +} + +/** + * We don't want to validate files which can be written while they are + * being executed. + * This means NFS. + */ +static inline int is_unprotected_file(struct file *file) +{ + if (strcmp(file->f_dentry->d_inode->i_sb->s_type->name, "nfs") == 0) + return 1; + return 0; +} + + +#define start_digsig_bench \ + if (DIGSIG_BENCH) \ + exec_time = jiffies; + +#define end_digsig_bench \ + if (DIGSIG_BENCH) { \ + exec_time = jiffies - exec_time; \ + total_jiffies += exec_time; \ + DSM_PRINT(DEBUG_TIME, \ + "Time to execute %s on %s is %li\n", \ + __FUNCTION__, file->f_dentry->d_name.name, exec_time); \ + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +static int digsig_file_mmap(struct file * file, + unsigned long reqprot, + unsigned long calcprot, + unsigned long flags) +{ + unsigned long prot = reqprot; +#else +static int digsig_file_mmap(struct file * file, + unsigned long prot, + unsigned long flags) +{ +#endif + struct elf64_hdr *elf64_ex; + struct elf32_hdr *elf32_ex; + int retval, die_if_elf = 0; + /* allow_write_on_exit: 1 if we've revoked write access, but the + * signature ended up bad (ie we won't allow execute access anyway) */ + int allow_write_on_exit = 0; + unsigned long size, sh_offset; + Elf64_Shdr *elf64_shdata; + char *sig_orig; + long exec_time = 0; + int arch32 = 0; + + if (!g_init) + return 0; + + if (!(prot & VM_EXEC)) + return 0; + if (!file) + return 0; + if (!file->f_dentry) + return 0; + if (!file->f_dentry->d_name.name) + return 0; + + if (is_unprotected_file(file)) + return DIGSIG_MODE; + + start_digsig_bench; + + DSM_PRINT(DEBUG_SIGN, "binary is %s\n", file->f_dentry->d_name.name); + + /* + * if file_security is set, then this process has already + * incremented the writer count on this inode, don't do + * it again. + */ + if (get_file_security(file) == 0) { + allow_write_on_exit = 1; + retval = digsig_deny_write_access(file); + if (retval) { + die_if_elf = retval; + allow_write_on_exit = 0; + } + } + + retval = 0; + if (is_cached_signature(file->f_dentry->d_inode)) { + DSM_PRINT(DEBUG_SIGN, "Binary %s had a cached signature validation.\n", + file->f_dentry->d_name.name); + allow_write_on_exit = 0; + goto out_file_no_buf; + } + + elf64_ex = read_elf_header(file); + if (elf64_ex == NULL) /* non-ELF, perhaps SYSV shmem */ + goto out_file_no_buf; + if (IS_ERR(elf64_ex)) { + retval = PTR_ERR(elf64_ex); + goto out_file_no_buf; + } + if (die_if_elf) { + /* this ELF file is being written to, can't mmap(EXEC) it! */ + retval = die_if_elf; + goto out_with_file; + } + + retval = DIGSIG_MODE; + + arch32 = (elf64_ex->e_ident[EI_CLASS] == ELFCLASS32); + + elf32_ex = (struct elf32_hdr *) elf64_ex; + if (arch32) { + size = elf32_ex->e_shnum * sizeof(Elf32_Shdr); + elf64_shdata = read_section_header(file, size, + elf32_ex->e_shoff); + } else { + size = elf64_ex->e_shnum * sizeof(Elf64_Shdr); + elf64_shdata = read_section_header(file, size, elf64_ex->e_shoff); + } + + if (IS_ERR(elf64_shdata)) { + retval = -EINVAL; + goto out_with_file; + } + + /* Find signature section */ + if (arch32) + sig_orig = digsig_find_signature32( + elf32_ex, (Elf32_Shdr *) elf64_shdata, + file, &sh_offset); + else + sig_orig = digsig_find_signature64( + elf64_ex, elf64_shdata, file, &sh_offset); + + if (sig_orig == NULL) { + DSM_PRINT(DEBUG_SIGN, + "%s: Signature not found for the binary: %s !\n", + __FUNCTION__, file->f_dentry->d_name.name); + goto out_free_shdata; + } + + /* Verify binary's signature */ + retval = digsig_verify_signature(sig_orig, file, sh_offset); + + if (!retval) { + DSM_PRINT(DEBUG_SIGN, + "%s: Signature verification successful\n", __FUNCTION__); + digsig_cache_signature(file->f_dentry->d_inode); + allow_write_on_exit = 0; + } else if (retval > 0) { + DSM_ERROR("%s: Signature do not match for %s\n", + __FUNCTION__, file->f_dentry->d_name.name); + retval = -EPERM; + } else { + DSM_PRINT(DEBUG_SIGN, + "%s: Signature verification failed because of errors: %d for %s\n", + __FUNCTION__, retval, file->f_dentry->d_name.name); + retval = -EPERM; + } + + kfree (sig_orig); + out_free_shdata: + kfree (elf64_shdata); + out_with_file: + kfree (elf64_ex); + out_file_no_buf: + if (allow_write_on_exit) + digsig_allow_write_access(file); + + end_digsig_bench; + + return retval; +} + +static void digsig_inode_free_security(struct inode *inode) +{ + if (is_cached_signature(inode)) + remove_signature(inode); +} + +static struct security_operations digsig_security_ops = { + .file_mmap = digsig_file_mmap, + .file_free_security = digsig_file_free_security, + .inode_permission = digsig_inode_permission, + .inode_unlink = digsig_inode_unlink, + .inode_free_security = digsig_inode_free_security, +}; + +static int __init digsig_init_module(void) +{ + int ret = -ENOMEM; + DSM_PRINT(DEBUG_INIT, "Initializing module\n"); + + /* initialize caching mechanisms */ + + if (digsig_init_caching()) + goto out; + + ret = -EINVAL; + if (digsig_init_sysfs()) { + DSM_ERROR("Error setting up sysfs for DigSig\n"); + goto out_cache; + } + + /* register */ + if (register_security(&digsig_security_ops)) { + DSM_ERROR("%s: Failure registering DigSig as primairy security module\n", __FUNCTION__); + if (mod_reg_security("digsig_verif", &digsig_security_ops)) { + DSM_ERROR("%s: Failure registering DigSig as secondary module\n", __FUNCTION__); + goto out_sysfs; + } + DSM_PRINT(DEBUG_INIT, "Registered as secondary module\n"); + secondary = 1; + } + return 0; +out_sysfs: + digsig_cleanup_sysfs(); +out_cache: + digsig_cache_cleanup(); +out: + return ret; +} + +static void __exit digsig_exit_module(void) +{ + DSM_PRINT (DEBUG_INIT, "Deinitializing module\n"); + g_init = 0; + if (secondary) { + DSM_PRINT (DEBUG_INIT, "Attempting to unregister from primary module\n"); + if (mod_unreg_security ("digsig_verif", &digsig_security_ops)) { + DSM_ERROR (KERN_INFO "Failure unregistering DigSig with primary module\n"); + } + } else { + if (unregister_security (&digsig_security_ops)) { + DSM_ERROR (KERN_INFO "Failure unregistering DigSig with the kernel\n"); + } + } + + digsig_sign_verify_free(); + digsig_cleanup_sysfs(); + digsig_cleanup_revocation(); + digsig_cache_cleanup(); + mpi_free(digsig_public_key[0]); + mpi_free(digsig_public_key[1]); +} + +security_initcall(digsig_init_module); +module_exit(digsig_exit_module); + +/* see linux/module.h */ +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Distributed Security Infrastructure Module"); +MODULE_AUTHOR("DIGSIG Team sourceforge.net/projects/disec"); +MODULE_SUPPORTED_DEVICE("DIGSIG_module"); diff -rNu linux.orig-2.6.19/security/digsig/digsig_cache.c linux-2.6.16/security/digsig/digsig_cache.c --- linux.orig-2.6.19/security/digsig/digsig_cache.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_cache.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,249 @@ +/* + * Digital Signature (DigSig) + * + * This file contains the signature caching code. + * + * Copyright (C) 2002-2003 Ericsson, Inc + * Copyright (c) 2003-2004 International Business Machines + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Serge Hallyn Nov 2003, Jan 2004: add caching of signature validation + * modifs: Makan Pourzandi Mar 2004 + * Chris Wright Sep 2004 + * Serge Hallyn Sep 2004: moved to smp-scalable seqlock-based design. + * + */ + +#include +#include +#include +#include +#include +#include "digsig.h" +#include "digsig_cache.h" +#include "digsig_sig_verify.h" +#include +#include + +#ifdef DIGSIG_DEBUG +#define DIGSIG_MODE 0 /*permissive mode */ +#define DIGSIG_BENCH 1 +#else +#define DIGSIG_MODE -EPERM /*restrictive mode */ +#define DIGSIG_BENCH 0 +#endif + +extern int dsi_cache_buckets; + +/* + * digsig_hash_line: seqlock_t = 28 bytes; next_evicted=2; + * Assuming 128 byte cache line, this leaves 98 bytes for + * the entry structs. Each of those is 12 bytes, so we'll + * use 8 entries per bucket (96 bytes) + * + * We will default to 128 buckets, taking 16384 bytes, and + * giving between 128 and 1024 (depending on # collisions) + * entries. + */ +#define ENTRIES_PER_BUCKET 8 + +/* + * digsig_hash_entry: a single inode signature validation cache + * entry. Since we don't clear these on file unload, we check the + * inode number and i_sb to ensure the inode was not cleared since + * we cached the validation. + * + * 12 bytes + */ +struct digsig_hash_entry { + struct inode *inode; + unsigned long i_ino; + struct super_block *i_sb; +}; + +/* + * digsig_hash_line: this is a cache entry bucket. hash(inode) + * will index to a hash bucket, which contains ENTRIES_PER_BUCKET + * entries for collisions. In this way a lookup should be write-less, + * and entirely contained within one cache line. + * + * When a bucket is full, we evict in a round-robin fashion (unless + * the next_evicted happened to be the last allocated) + */ +struct digsig_hash_line { + seqlock_t sequence; + struct digsig_hash_entry entry[ENTRIES_PER_BUCKET]; + short next_evicted; +}; + +static struct digsig_hash_line *sig_cache; +static int digsig_hash_bits; + +#define hash(inode) hash_long((unsigned long)inode, digsig_hash_bits) + +/****************************************************************************** +Description : does the cache validation entry describe this inode? + If the inode * is the same value, but i_ino or i_sb has changed, then + the inode has been unloaded since we saved the validation, so we must + clear the entry. +Parameters : + @p: a cached signature validation entry + @inode: an inode +Return value: 1 if the sig entry is for the given inode, 0 otherwise +******************************************************************************/ +static inline int +is_same_inode(struct digsig_hash_entry *e, struct inode *inode) +{ + if (e->inode != inode) + return 0; + if (e->i_ino != inode->i_ino || e->i_sb != inode->i_sb) { + e->inode = NULL; + return 0; + } + + return 1; +} + +/****************************************************************************** +Description : Define if the inode is already in the list. +Parameters : @inode the one we search for +Return value: 1 if found, 0 otherwise +******************************************************************************/ +int is_cached_signature(struct inode *inode) +{ + struct digsig_hash_line *l; + unsigned seq; + int i, h, found; + + h = hash(inode); + l = &sig_cache[h]; + do { + found = 0; + seq = read_seqbegin(&l->sequence); + for (i=0; ientry[i], inode)) + found = 1; + } while (read_seqretry(&l->sequence, seq)); + + return found; +} + +/****************************************************************************** +Description : remove_signature +Parameters : @inode to be removed +Return value: none +******************************************************************************/ +void remove_signature(struct inode *inode) +{ + struct digsig_hash_line *l; + int i, h; + + h = hash(inode); + l = &sig_cache[h]; + write_seqlock(&l->sequence); + for (i=0; ientry[i], inode)) + l->entry[i].inode = 0; + write_sequnlock(&l->sequence); +} + +static inline short inc_evicted(struct digsig_hash_line *l) +{ + short ret = l->next_evicted++; + if (l->next_evicted == ENTRIES_PER_BUCKET) + l->next_evicted = 0; + return ret; +} + +/****************************************************************************** +Description : + * We've validated the signature on inode. Cache that decision. + * If the hash bucket is full, we pick the next evicted entry in a round-robin + * fashion. Otherwise, we make sure that the next evicted entry will not be + * the one we just inserted. +Parameters : + @inode: inode whose signature validation to cache +Return value: none +******************************************************************************/ +void digsig_cache_signature(struct inode *inode) +{ + struct digsig_hash_line *l; + int i, h; + + if (!inode) + panic("digsig:%s:asked to cache null inode\n", __FUNCTION__); + + h = hash(inode); + + l = &sig_cache[h]; + + DSM_PRINT(DEBUG_SIGN, + "%s: adding cache entry at %d\n", __FUNCTION__, h); + + if (!write_tryseqlock(&l->sequence)) + return; + + for (i=0; ientry[i].inode; i++); + + + if (i == ENTRIES_PER_BUCKET) + i = inc_evicted(l); + else if (i == l->next_evicted) + inc_evicted(l); + + l->entry[i].inode = inode; + l->entry[i].i_ino = inode->i_ino; + l->entry[i].i_sb = inode->i_sb; + write_sequnlock(&l->sequence); +} + +/****************************************************************************** +Description : Initialize caching +Parameters : none +Return value: 0 on success, 1 on failure. +******************************************************************************/ +int __init digsig_init_caching(void) +{ + int i, j; + + /* dsi_cache_buckets must be a power of two */ + digsig_hash_bits = long_log2(dsi_cache_buckets); + if (dsi_cache_buckets != (1 << digsig_hash_bits)) { + digsig_hash_bits++; + dsi_cache_buckets = 1 << digsig_hash_bits; + DSM_PRINT (DEBUG_INIT, + "%s: dsi_cache_buckets set to %d (bits %d)\n", + __FUNCTION__, dsi_cache_buckets, digsig_hash_bits); + } + + sig_cache = kmalloc(dsi_cache_buckets * + sizeof(struct digsig_hash_line), GFP_KERNEL); + + + if (!sig_cache) { + DSM_PRINT(DEBUG_ERROR, "No memory to initialize digsig cache.\n"); + return 1; + } + + for (i=0; i + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Serge Hallyn Jan 2004 + * + */ + +#ifndef _DSI_CACHE_H +#define _DSI_CACHE_H + +#include +#include "gnupg/mpi/mpi.h" + +int is_cached_signature(struct inode *inode); +void remove_signature(struct inode *inode); +void digsig_cache_signature(struct inode *inode); +int digsig_init_caching(void); +void digsig_cache_cleanup(void); + +#endif /* _DSI_CACHE_H */ + diff -rNu linux.orig-2.6.19/security/digsig/digsig_debug.h linux-2.6.16/security/digsig/digsig_debug.h --- linux.orig-2.6.19/security/digsig/digsig_debug.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_debug.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,66 @@ +/* + * Digital Signature (DigSig) + * + * dsi_debug.h + * + * This file contains the DSM access control implementation + * + * + * Copyright (C) 2002-2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: David Gordon + * Modifications: Axelle Apvrille - TRACEFUNC level. + */ + + +#ifndef _DSI_DEBUG_H +#define _DSI_DEBUG_H + +#define DIGSIG_MODULE_NAME "DIGSIG MODULE" + + + +#define DEBUG_ALL 0xFFFFFFFF +#define DEBUG_INIT 0x00000001 /* 1 */ +#define DEBUG_BINPRM 0x00000002 /* 2 */ +#define DEBUG_SUPER_BLOCK 0x00000004 /* 4 */ +#define DEBUG_INODE 0x00000008 /* 8 */ +#define DEBUG_FILE 0x00000010 /* 16 */ +#define DEBUG_TASK 0x00000020 /* 32 */ +#define DEBUG_SOCKET 0x00000040 /* 64 */ +#define DEBUG_SOCKET_ANNOYING 0x00000080 /* 128 */ +#define DEBUG_SKB 0x00000100 /* 256 */ +#define DEBUG_IP 0x00000200 /* 512 */ +#define DEBUG_NETDEV 0x00000400 /* 1024 */ +#define DEBUG_IPC 0x00000800 /* 2048 */ +#define DEBUG_MSG 0x00001000 /* 4096 */ +#define DEBUG_SHM 0x00002000 /* 8192 */ +#define DEBUG_SEM 0x00004000 /* 16384 */ +#define DEBUG_ACCESS_CONTROL 0x00008000 /* 32768 */ +#define DEBUG_CACHE 0x00010000 /* 65536 */ +#define DEBUG_WARNING 0x00020000 /* 131072 */ +#define DEBUG_ERROR 0x00040000 /* never used, use DSM_ERROR */ +#define DEBUG_SYS_SECURITY 0x00080000 /* 524288 */ +#define DEBUG_DCI 0x00100000 /* 1048576 */ +#define DEBUG_CALL 0x00200000 +#define DEBUG_DEV 0x00400000 +#define DEBUG_TESTS 0x00800000 +#define DEBUG_TRACEFUNC 0x01000000 /* 16777216 */ +#define DEBUG_SIGN 0x02000000 +#define DEBUG_TIME 0x04000000 + +extern int DigsigDebugLevel; + +/* This is a hack to avoid using va_lists */ +#define DSM_PRINT(dbg,fmt,arg...) \ + if (dbg & DigsigDebugLevel) printk(DIGSIG_MODULE_NAME" - " fmt,##arg) + +#define DSM_PRINT_NO_PREFIX(dbg,fmt,arg...) \ + if (dbg & DigsigDebugLevel) printk(fmt,##arg) + +#endif /* _DSI_DEBUG_H */ diff -rNu linux.orig-2.6.19/security/digsig/digsig.h linux-2.6.16/security/digsig/digsig.h --- linux.orig-2.6.19/security/digsig/digsig.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,54 @@ +/* + * Digital Security Module (DigSig) + * + * digsig.h + * + * The main header file for Digsig + * + * Copyright (c) 2002-2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Miroslaw Zakrzewski + * David Gordon + * Alain Patrick Medenou + * Gabriel Ivascu + * Makan Pourzandi: modifs, fixes, march 2003, August 2004, Apr 2005 + */ + + +#ifndef _DIGSIG_H +#define _DIGSIG_H + +#ifdef MODULE +#include +#include +#include +#include +#endif + + +/* DSM-DIGSIG error types */ +#define DSM_SUCCESS 1 +#define DSM_FAILURE 2 + + +#ifdef MODULE /* This prevents user programs that include dsi.h to inherit kernel stuff */ + +#define DIGSIG_SAFE_ALLOC (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL) + +/* This is a hack to avoid using va_lists */ +#define DSM_ERROR(fmt,arg...) printk(DIGSIG_MODULE_NAME" Error - " fmt,##arg) + + +#include "digsig_debug.h" /* Include this file first since it contains DSM_PRINT macro */ + + +#endif /* MODULE */ + +extern int g_init; + +#endif /* _DSI_H */ diff -rNu linux.orig-2.6.19/security/digsig/digsig_revocation.c linux-2.6.16/security/digsig/digsig_revocation.c --- linux.orig-2.6.19/security/digsig/digsig_revocation.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_revocation.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,123 @@ +/* + * Digital Signature (DigSig) + * + * This file implements a list of revoked signatures, and checks each loaded + * library or binary against the list. If its signature has been revoked, + * execution will be halted. + * + * Copyright (C) 2002-2003 Ericsson, Inc + * Copyright (c) 2003-2004 International Business Machines + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Serge Hallyn Mar 2004 + * modifs: Chris Wright Sept 2004 + * Serge Hallyn Sep 2004: added a hash table (keyed on the first 4 + + bytes of the hash) for quicker revocation lookup. + */ + +#include +#include +#include +#include +#include +#include "digsig.h" +#include "digsig_cache.h" +#include "digsig_revocation.h" +#include "digsig_sig_verify.h" +#include + +#ifdef DIGSIG_DEBUG +#define DIGSIG_MODE 0 /*permissive mode */ +#define DIGSIG_BENCH 1 +#else +#define DIGSIG_MODE -EPERM /*restrictive mode */ +#define DIGSIG_BENCH 0 +#endif + +static spinlock_t revoked_list_wlock = SPIN_LOCK_UNLOCKED; + +#define REVOKE_BITS 6 +#define REVOKE_BUCKETS 64 + +static struct hlist_head dsi_revoked_sigs[REVOKE_BUCKETS]; + +/* + * Description: Called at exec (digsig_verify_signature) to check whether the + * signature has been revoked. If it has, exec permission is outright + * denied. + */ +#ifdef DIGSIG_REVOCATION +int digsig_is_revoked_sig(char *buffer) +{ + struct hlist_node *tmp; + char *tmp1 = buffer + DIGSIG_BSIGN_INFOS + DIGSIG_RSA_DATA_OFFSET; + int count = DIGSIG_ELF_SIG_SIZE - DIGSIG_BSIGN_INFOS - DIGSIG_RSA_DATA_OFFSET; + int h, ret = 0; + MPI file_sig = mpi_read_from_buffer(tmp1, &count, 0); + + h = hash_long(*(unsigned long *)tmp1, REVOKE_BITS); + + hlist_for_each(tmp, &dsi_revoked_sigs[h]) { + struct revoked_sig *e = hlist_entry(tmp, struct revoked_sig, next); + if (mpi_cmp(file_sig, e->sig) == 0) { + ret = 1; + goto out; + } + } + +out: + mpi_free(file_sig); + return ret; +} +#endif + +int digsig_add_revoked_sig(const char *buffer) { + int rcount = DIGSIG_ELF_SIG_SIZE - DIGSIG_BSIGN_INFOS - DIGSIG_RSA_DATA_OFFSET; + const char *tmp1 = buffer + DIGSIG_BSIGN_INFOS + DIGSIG_RSA_DATA_OFFSET; + struct revoked_sig *s; + int h; + + s = kmalloc(sizeof(struct revoked_sig), GFP_ATOMIC); + + if (!s) + return -ENOMEM; + + INIT_HLIST_NODE(&s->next); + + h = hash_long(*(unsigned long*)tmp1, REVOKE_BITS); + s->sig = mpi_read_from_buffer(tmp1, &rcount, 0); + spin_lock(&revoked_list_wlock); + hlist_add_head(&s->next, &dsi_revoked_sigs[h]); + spin_unlock(&revoked_list_wlock); + + return 0; +} + +inline void digsig_init_revocation(void) +{ + int i; + + for (i=0; isig); + kfree(e); + } + } +} diff -rNu linux.orig-2.6.19/security/digsig/digsig_revocation.h linux-2.6.16/security/digsig/digsig_revocation.h --- linux.orig-2.6.19/security/digsig/digsig_revocation.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_revocation.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,44 @@ +/* + * Digital Signature (DigSig) + * + * This file contains the signature caching code. + * + * Copyright (C) 2002-2003 Ericsson, Inc + * Copyright (c) 2003-2004 International Business Machines + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Serge Hallyn Mar 2004 + * + */ + +#ifndef _DSI_REVOKE_H +#define _DSI_REVOKE_H + +#include +#include "gnupg/mpi/mpi.h" + +/* + * A linear array of revoked signatures. + * + * If performance is a concern, this could be changed to a hash + * table. + */ +struct revoked_sig { + struct hlist_node next; + MPI sig; +}; + +void digsig_init_revocation(void); +void digsig_cleanup_revocation(void); +int digsig_add_revoked_sig(const char *buffer); +#ifdef DIGSIG_REVOCATION +int digsig_is_revoked_sig(char *buffer); +#else +#define digsig_is_revoked_sig(x) 0 +#endif + +#endif /* _DSI_REVOKE_H */ diff -rNu linux.orig-2.6.19/security/digsig/digsig_sig_verify.c linux-2.6.16/security/digsig/digsig_sig_verify.c --- linux.orig-2.6.19/security/digsig/digsig_sig_verify.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_sig_verify.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,401 @@ +/* + * Digital Signature (DigSig) + * + * digsig_sig_verify.c + * + * Copyright (C) 2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Authors: Axelle Apvrille + * David Gordon Aug 2003 + * modifs: Makan Pourzandi Sep 2003, Apr 2005 + * Chris Wright Sep 2004 + */ + +#include +#include +#include +#include + +#include "digsig.h" +#include "digsig_debug.h" +#include "digsig_sig_verify.h" +#include "gnupg/cipher/rsa-verify.h" + +/* + * Public key format: 2 MPIs + * 2 bytes: length of 1st MPI (ie. 0x0400) + * n bytes: MPI + * 2 bytes: length of 2nd MPI (ie. 0x0006) + * n bytes: MPI (ie. 0x29) + */ + +#define TVMEMSIZE 4096 + +int gDigestLength[] = { /* SHA-1 */ 0x14 }; +static struct crypto_tfm *sha1_tfm; +MPI digsig_public_key[] = {MPI_NULL, MPI_NULL}; + + +/****************************************************************************** + Internal functions +******************************************************************************/ + +static int +digsig_rsa_bsign_verify(unsigned char *sha_cat, int length, + unsigned char *signed_hash); + +static int digsig_sha1_init(SIGCTX * ctx); + +static void digsig_sha1_update(SIGCTX * ctx, char *buf, int buflen); + +static int digsig_sha1_final(SIGCTX * ctx, char *digest); + + +/****************************************************************************** +Description : +Parameters : + hashalgo the identifier of the hash algorithm to use (HASH_SHA1 for instance) + signalgo sign algorithm identifier. Ex. SIGN_RSA +Return value: a signature context valid for this signature only +******************************************************************************/ + +SIGCTX *digsig_sign_verify_init(int hashalgo, int signalgo) +{ + SIGCTX *ctx; + + /* allocating signature context */ + ctx = kmalloc(sizeof(SIGCTX), GFP_KERNEL); + if (!ctx) { + DSM_ERROR("Cannot allocate ctx\n"); + goto err; + } + + ctx->tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); + if (!ctx->tvmem) { + DSM_ERROR("Cannot allocate plaintext buffer\n"); + goto err; + } + + /* checking hash algorithm is known */ + switch (hashalgo) { + case HASH_SHA1: + if (digsig_sha1_init(ctx)) { + DSM_ERROR("Initializing SHA1 failed\n"); + goto err; + } + break; + default: + DSM_ERROR("Unknown hash algo\n"); + goto err; + } + + /* checking sign algo is known */ + switch (signalgo) { + case SIGN_RSA: + break; + default: + DSM_ERROR("Unknown sign algo\n"); + goto err; + } + ctx->digestAlgo = hashalgo; + ctx->signAlgo = signalgo; + return ctx; + +err: + if (ctx) { + kfree(ctx->tvmem); + kfree(ctx); + } + return NULL; +} + +/****************************************************************************** +Description : +Parameters : + ctx + buf data to sign (part of a bigger buffer) + buflen length of buf +Return value: 0 normally +******************************************************************************/ +int digsig_sign_verify_update(SIGCTX * ctx, char *buf, int buflen) +{ + if (ctx == NULL) + return -EINVAL; + + switch (ctx->digestAlgo) { + case HASH_SHA1: + digsig_sha1_update(ctx, buf, buflen); + break; + default: + DSM_ERROR("%s: Unknown hash algo\n", __FUNCTION__); + return -EINVAL; + } + + return 0; +} + +/****************************************************************************** +Description : This is where the RSA signature verification actually takes place +Parameters : +Return value: +******************************************************************************/ +int +digsig_sign_verify_final(SIGCTX * ctx, int siglen /* PublicKey */ , + unsigned char *signed_hash) +{ + char *digest; + int rc = -ENOMEM; + + digest = kmalloc (gDigestLength[ctx->digestAlgo], DIGSIG_SAFE_ALLOC); + if (!digest) { + DSM_ERROR ("kmalloc failed in %s for digest\n", __FUNCTION__); + goto err; + } + /* TO DO: check the length of the signature: it should be equal to the length + of the modulus */ + if ((rc = digsig_sha1_final(ctx, digest)) < 0) { + DSM_ERROR + ("%s: Cannot finalize hash algorithm\n", __FUNCTION__); + goto err; + } + + rc = -EINVAL; + if (siglen < gDigestLength[ctx->digestAlgo]) + goto err; + + switch (ctx->digestAlgo) { + case SIGN_RSA: + rc = digsig_rsa_bsign_verify(digest, + gDigestLength[ctx->digestAlgo], + signed_hash); + break; + default: + DSM_ERROR + ("Unsupported cipher algorithm in binary digital signature verification\n"); + } + + /* free everything */ + /* do not free SHA1-TFM. For optimization, we choose always to use the same one */ +err: + kfree (digest); + return rc; +} + +/****************************************************************************** +Description : + Call this only at the end of the whole program when you do not want to use + signature verification again. +Parameters : +Return value: +******************************************************************************/ +void digsig_sign_verify_free(void) +{ + if (sha1_tfm) { + crypto_free_tfm(sha1_tfm); + sha1_tfm = NULL; + } + /* this might cause unpredictable behavior if structures are refering to this, + their pointer might suddenly become NULL, might need a usage count associated */ +} + +/****************************************************************************** +Description : + Initialize public key +Parameters : +Return value: +******************************************************************************/ + +int digsig_init_pkey(const char read_par, unsigned char *raw_public_key, int mpi_size) +{ + int nread; + + switch (read_par) { + + case 'n': + DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_n!\n"); + nread = mpi_size; + digsig_public_key[0] = + mpi_read_from_buffer(raw_public_key, &nread, 0); + break; + case 'e': + DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_e!\n"); + nread = mpi_size; + digsig_public_key[1] = + mpi_read_from_buffer(raw_public_key, &nread, 0); + break; + } + + return 0; +} + +/****************************************************************************** +Description : + Performs RSA verification of signature contained in binary +Parameters : +Return value: 0 - RSA signature is valid + 1 - RSA signature is invalid + -1 - an error occured +******************************************************************************/ + +static int digsig_rsa_bsign_verify(unsigned char *hash_format, int length, + unsigned char *signed_hash) +{ + int rc = 0, cmp; + MPI hash, data; + unsigned nread = DIGSIG_ELF_SIG_SIZE; + int nframe; + unsigned char sig_class; + unsigned char sig_timestamp[SIZEOF_UNSIGNED_INT]; + int i; + SIGCTX *ctx = NULL; + unsigned char *new_sig; + + new_sig = kmalloc(gDigestLength[HASH_SHA1], DIGSIG_SAFE_ALLOC); + if (!new_sig) { + DSM_ERROR ("kmalloc failed in %s for new_sig\n", __FUNCTION__); + return -ENOMEM; + } + + /* Get MPI of signed data from .sig file/section */ + nread = DIGSIG_ELF_SIG_SIZE; + + data = mpi_read_from_buffer(signed_hash + DIGSIG_RSA_DATA_OFFSET, + &nread, 0); + if (!data) { + kfree(new_sig); + return -EINVAL; + } + + /* Get MPI for hash */ + /* bsign modif - file hash - gpg modif */ + /* bsign modif: add bsign greet at beginning */ + /* gpg modif: add class and timestamp at end */ + + ctx = kmalloc(sizeof(SIGCTX), GFP_KERNEL); + if (!ctx) { + DSM_ERROR("Cannot allocate ctx\n"); + mpi_free (data); + kfree (new_sig); + return -ENOMEM; + } + + ctx->tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); + if (!ctx->tvmem) { + kfree (ctx); + mpi_free(data); + kfree (new_sig); + DSM_ERROR("Cannot allocate plaintext buffer\n"); + return -ENOMEM; + } + + digsig_sha1_init(ctx); + + sig_class = signed_hash[DIGSIG_RSA_CLASS_OFFSET]; + sig_class &= 0xff; + + for (i = 0; i < SIZEOF_UNSIGNED_INT; i++) { + sig_timestamp[i] = + signed_hash[DIGSIG_RSA_TIMESTAMP_OFFSET + i] & 0xff; + } + + digsig_sha1_update(ctx, DIGSIG_BSIGN_STRING, DIGSIG_BSIGN_GREET_SIZE); + digsig_sha1_update(ctx, hash_format, SHA1_DIGEST_LENGTH); + digsig_sha1_update(ctx, &sig_class, 1); + digsig_sha1_update(ctx, sig_timestamp, SIZEOF_UNSIGNED_INT); + + if ((rc = digsig_sha1_final(ctx, new_sig)) < 0) { + DSM_ERROR + ("internal_rsa_verify_final Cannot finalize hash algorithm\n"); + mpi_free(data); + kfree(ctx->tvmem); + kfree(ctx); + return rc; + } + + nframe = mpi_get_nbits(digsig_public_key[0]); + hash = do_encode_md(new_sig, nframe); + + if (hash == MPI_NULL) { + DSM_PRINT(DEBUG_SIGN, "mpi creation failed\\n"); + } + + /* Do RSA verification */ + cmp = rsa_verify(hash, &data, digsig_public_key); + rc = cmp ? -EPERM : 0; + + mpi_free(hash); + mpi_free(data); + kfree(ctx->tvmem); + kfree(ctx); + kfree (new_sig); + return rc; +} + + +/****************************************************************************** +Description : + initialisation of hash with sha1 +Parameters : +Return value: 0 for successful allocation, -1 for failed +******************************************************************************/ + +static int digsig_sha1_init(SIGCTX * ctx) +{ + if (ctx == NULL) + return -1; + + if (sha1_tfm == NULL) + sha1_tfm = crypto_alloc_tfm("sha1", 0); + ctx->tfm = sha1_tfm; + if (ctx->tfm == NULL) { + DSM_ERROR("tfm allocation failed\n"); + return -1; + } + + crypto_digest_init(ctx->tfm); + return 0; +} + + +/****************************************************************************** +Description : Portability layer function. +Parameters : +Return value: void. +******************************************************************************/ + +static void digsig_sha1_update(SIGCTX * ctx, char *buf, int buflen) +{ + char *plaintext; + + memcpy(ctx->tvmem, buf, buflen); + plaintext = (void *) ctx->tvmem; + + ctx->sg[0].page = virt_to_page(plaintext); + ctx->sg[0].offset = ((long) plaintext & ~PAGE_MASK); + ctx->sg[0].length = buflen; + + crypto_digest_update(ctx->tfm, ctx->sg, 1); +} + +/****************************************************************************** +Description : Portability layer function. +Parameters : +Return value: 0 for successful allocation, -EINVAL for failed +******************************************************************************/ + +static int digsig_sha1_final(SIGCTX * ctx, char *digest) +{ + /* TO DO: check the length of the signature: it should be equal to the length + of the modulus */ + + if (ctx == NULL) + return -EINVAL; + + crypto_digest_final(ctx->tfm, digest); + return 0; +} diff -rNu linux.orig-2.6.19/security/digsig/digsig_sig_verify.h linux-2.6.16/security/digsig/digsig_sig_verify.h --- linux.orig-2.6.19/security/digsig/digsig_sig_verify.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_sig_verify.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,93 @@ +/* + * Distributed Security Module (DSM) + * + * digsig_sig_verify.h + * + * Copyright (C) 2002-2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Axelle Apvrille + * David Gordon + */ + +#ifndef _DIGSIG_SIG_VERIFY_H +#define _DIGSIG_SIG_VERIFY_H + +#include +#include +#include "gnupg/mpi/mpi.h" + + +#define DIGSIG_ELF_SIG_SECTION 0x80736967 /* ((0x80 << 24)|('s' << 16)|('i' << 8)|'g') */ +#define DIGSIG_ELF_SIG_SIZE 512 /* Total signature size */ +#define DIGSIG_ELF_READ_BLOCK_SIZE 1024 /* Signature will be done in chunks of n bytes */ + +/* + * Format of digital signature done by bsign: + * - "#1; bsign v%s\n" + * - hash of file with sig section zerod (crypto class and timestamp not added to hash) + * - length of digsig (2 bytes) + * - digsig + */ + +#define DIGSIG_BSIGN_VERSION "0.4.5" +#define DIGSIG_BSIGN_STRING "#1; bsign v" DIGSIG_BSIGN_VERSION "\n" +#define DIGSIG_BSIGN_GREET_SIZE sizeof(DIGSIG_BSIGN_STRING)-1 +#define DIGSIG_BSIGN_HASH 20 /* sha1 hash */ +#define DIGSIG_BSIGN_LEN_OFFSET 2 /* length of digsig added by bsign */ +#define DIGSIG_BSIGN_INFOS DIGSIG_BSIGN_GREET_SIZE+DIGSIG_BSIGN_HASH+DIGSIG_BSIGN_LEN_OFFSET + +/* GPG .sig file/section structure: + * 89 00 95 03 05 00 3F293CEB + * hdrlen sig version md5 len class timestamp + * + * D39C2077 C307562E 01 02 29 + * keyid[0] keyid[1] pubkey algo digest algo digest start[0] + * + * C2 03FF Rest of .sig + * digest start[1] nbits of MPI MPI (as read by mpi_read) + */ + +#define DIGSIG_RSA_CLASS_OFFSET 5 +#define DIGSIG_RSA_TIMESTAMP_OFFSET 6 +#define DIGSIG_RSA_DATA_OFFSET 22 + + +/*ToDO: makan: this is a constraint, we suppose that the max size of a + big integer is 1024 bytes. This needs to be modified in order to + have a dynamic way of allocating memory. */ + +#define DIGSIG_MPI_MAX_SIZE_N 1024 +#define DIGSIG_MPI_MAX_SIZE_E 128 + +/** + * Supported algorithms + */ +#define HASH_SHA1 0 +#define SIGN_RSA 0 + +typedef struct sig_ctx_st { + struct crypto_tfm *tfm; + struct scatterlist sg[1]; + int digestAlgo; + int signAlgo; + char *tvmem; +} SIGCTX; + +extern int gDigestLength[1]; +extern MPI digsig_public_key[]; + +SIGCTX *digsig_sign_verify_init(int hashalgo, int signalgo); +int digsig_sign_verify_update(SIGCTX * ctx, char *buf, int buflen); +int digsig_sign_verify_final(SIGCTX * ctx, int siglen /* PublicKey */ , + unsigned char *signed_hash); +void digsig_sign_verify_free(void); +int digsig_init_pkey(const char read_par, unsigned char *raw_public_key, int mpi_size); + + + +#endif /* _DSI_SIG_VERIFY_H */ diff -rNu linux.orig-2.6.19/security/digsig/digsig_sysfs.c linux-2.6.16/security/digsig/digsig_sysfs.c --- linux.orig-2.6.19/security/digsig/digsig_sysfs.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_sysfs.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,283 @@ +/* + * Digital Signature (DigSig) + * + * digsig_sysfs.c + * + * This file contains the sysfs interface to userspace. + * + * Copyright (C) 2002-2003 Ericsson, Inc + * Copyright (c) 2003-2004 International Business Machines + * + * 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 of the License, or + * (at your option) any later version. + * + * Author: Vincent Roy + * modifs: Serge Hallyn Mar 2003: separate into own file, add revocation + * interface. + * Chris Wright Sept 2004: change names of sysfs files + * digsig_interface -> key, digsig_revoke -> revoke + * M Pourzandi Apr 2005: minor changes + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "digsig_sysfs.h" +#include "digsig.h" +#include "digsig_debug.h" +#include "digsig_sig_verify.h" +#include "digsig_cache.h" +#include "digsig_revocation.h" + + +/* For use with LTM, we copy everything except the first three bytes + which are 'n' or 'e' + size. + For use with GnuPG, we should copy everything except the first byte +*/ +#ifdef DIGSIG_LTM +#define DIGSIG_KEY_OFFSET 3 +#else +#define DIGSIG_KEY_OFFSET 1 +#endif + +extern long int total_jiffies; /* digsig.c */ + +struct digsig_attribute { + struct attribute attr; + ssize_t (*show)(struct kobject *, struct attribute *attr, char *); + ssize_t (*store)(struct kobject *, struct attribute *attr, const char *, size_t); +}; + +#ifndef __ATTR +#define __ATTR(_name,_mode,_show,_store) { \ + .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .show = _show, \ + .store = _store, \ +} +#endif + +#define DIGSIG_ATTR(_name, _mode, _show, _store) \ +struct digsig_attribute digsig_attr_##_name = __ATTR(_name,_mode,_show,_store) + +/* + * These are the show/hide prototypes and attribute for the + * /sys/digsig/key file, which is used to tell digsig the + * public key to use to verify ELF file signatures. + */ +static ssize_t digsig_key_show (struct kobject *obj, struct attribute *attr, + char *buff); +static ssize_t digsig_key_store (struct kobject *obj, struct attribute *attr, + const char *buff, size_t count); +/* + * For the curious, notice what's going on: We create a structure which + * contains .attr . This .attr is what we pass into sysfs_create_file + * in digsig_init_sysfs . In turn, sysfs will pass this back to us for read and + * write operations ( digsig_key_store and digsig_key_show above). We can + * then get our digsig_attribute variable, which contains the .attr whose + * address we are sent, back by calculating the offset of .attr and + * subtracting that from the address we were sent, which is what container_of + * in digsig_store and digsig_show (just a few definitions below) do. + */ +static DIGSIG_ATTR(key, 0600, digsig_key_show, digsig_key_store); + +/* + * These are the show/hide prototypes and attribute for the + * /sys/digsig/revoke file, which is used to tell digsig the + * ELF file signatures which are revoked. Digsig will not allow + * loading any files which carry one of these signatures. + */ +static ssize_t digsig_revoked_show (struct kobject *obj, + struct attribute *attr, char *buff); +static ssize_t digsig_revoked_store (struct kobject *obj, + struct attribute *attr, const char *buff, size_t count); +static DIGSIG_ATTR(revoke, 0600, digsig_revoked_show, digsig_revoked_store); + +/* + * Next are the digsig sysfs file operations. These are assigned to + * the files under /sys/digsig. They will use the digsig_attribute + * struct defined above to find the function which should actually be + * called for read/write. The attr argument to these functions is a + * member of the digsig_attribute struct we defined, so we use its + * offset to find our structure, which in turn contains the read and + * write operations we actually want to perform. + */ +static ssize_t +digsig_store(struct kobject *kobj, struct attribute *attr, const char *buf, + size_t len) +{ + struct digsig_attribute *attribute = container_of(attr, + struct digsig_attribute, attr); + + return attribute->store ? attribute->store(kobj, attr, buf, len) : 0; +} + +static ssize_t +digsig_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct digsig_attribute *attribute = container_of(attr, + struct digsig_attribute, attr); + + return attribute->show ? attribute->show(kobj, attr, buf) : 0; +} + +/* + * digsig_sysfs_ops: The operations structure (containing file read/write + * functions) for our sysfs files + */ +static struct sysfs_ops digsig_sysfs_ops = { + .show = digsig_show, + .store = digsig_store +}; + +/* digsig_kobj_type: A kobject to attach to our sysfs directory */ +static struct kobj_type digsig_kobj_type = { + .sysfs_ops = &digsig_sysfs_ops, +}; + +/* digsig_kobject: a kobject for our /sys/digsig directory */ +static struct kobject digsig_kobject = { + .name = "digsig", + .ktype = &digsig_kobj_type +}; + + +/* + * init and cleanup functions for the /sys/digsig directory. + */ +int __init digsig_init_sysfs(void) +{ + if (kobject_register (&digsig_kobject) != 0) { + DSM_ERROR ("Digsig key failed to register properly\n"); + goto err; + } + if (sysfs_create_file(&digsig_kobject, &digsig_attr_key.attr) != 0) { + DSM_ERROR ("Create file failed\n"); + goto create_key; + } + if (sysfs_create_file(&digsig_kobject, &digsig_attr_revoke.attr) != 0) { + DSM_ERROR ("Create revocation file failed\n"); + goto create_revoke; + } + return 0; + +create_revoke: + sysfs_remove_file (&digsig_kobject, &digsig_attr_key.attr); +create_key: + kobject_unregister (&digsig_kobject); +err: + return -1; +} + +void digsig_cleanup_sysfs(void) +{ + sysfs_remove_file (&digsig_kobject, &digsig_attr_key.attr); + sysfs_remove_file (&digsig_kobject, &digsig_attr_revoke.attr); + kobject_unregister (&digsig_kobject); +} + +/******************************************************************************** +Description : This function reads the public key parts +We receive first n (the modulus) and then e (public exponent). They follow +this format: + - 1 byte : character 'n' or 'e' + - 2 bytes: length of MPI in BITS + - MPI +Parameters : +Return value: +*********************************************************************************/ +static ssize_t +digsig_key_store (struct kobject *obj, struct attribute *attr, const char *buff, size_t count) +{ + unsigned char *raw_public_key; + int mpi_size; + + switch (buff[0]) { + case 'i': + total_jiffies = 0; + break; + case 'p': + printk ("total jiffies = %li\n", total_jiffies); + break; + } + + /* do not accept to re-initialize the module with + new public key. This avoids many coherency + problem when updating keys while checking the + signatures.*/ + if (g_init) + return -1; + + switch (buff[0]) { + case 'n': + case 'e': + raw_public_key = + kmalloc(count - DIGSIG_KEY_OFFSET, DIGSIG_SAFE_ALLOC); + if (!raw_public_key) { + DSM_ERROR("kmalloc fail for %c in %s\n", buff[0], __FUNCTION__); + return -ENOMEM; + } + memcpy(raw_public_key, &buff[DIGSIG_KEY_OFFSET], count - DIGSIG_KEY_OFFSET); + mpi_size = count - DIGSIG_KEY_OFFSET; + DSM_PRINT(DEBUG_DEV, "pkey->%c size is %i\n", buff[0], mpi_size); + break; + default: + return -EINVAL; + } + + digsig_init_pkey(buff[0], raw_public_key, mpi_size); + + if (digsig_public_key[0] && digsig_public_key[1]) { + g_init = 1; + } + kfree(raw_public_key); + + return count; +} + + +static ssize_t +digsig_key_show (struct kobject *obj, struct attribute *attr, char *buff) +{ + + return 0; +} + +/* + * callbacks for read/write to /sys/digsig/revoke file + */ +static ssize_t +digsig_revoked_store (struct kobject *obj, struct attribute *attr, const char *buff, size_t count) +{ + if (g_init) + return -EPERM; + + if (count != DIGSIG_ELF_SIG_SIZE) { + DSM_ERROR("digsig_revoked_list_store: Oops - count=%d, " + "sig size is %d\n", count, DIGSIG_ELF_SIG_SIZE); + return -EINVAL; + } + + digsig_add_revoked_sig(buff); + + DSM_PRINT(DEBUG_SIGN, "Added a revoked sig.\n"); + return count; +} + +static ssize_t +digsig_revoked_show (struct kobject *obj, struct attribute *attr, char *buff) +{ + + return 0; +} diff -rNu linux.orig-2.6.19/security/digsig/digsig_sysfs.h linux-2.6.16/security/digsig/digsig_sysfs.h --- linux.orig-2.6.19/security/digsig/digsig_sysfs.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/digsig_sysfs.h 2006-04-28 11:06:05.000000000 -0400 @@ -0,0 +1,30 @@ +/* + * Digital Signature (DigSig) + * + * digsig_sysfs.h + * + * This file contains the header file access control functions + * + * Copyright (C) 2002-2003 Ericsson, Inc + * + * 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 of the License, or + * (at your option) any later version. + * + * Vincent Roy + * Modifs: M Pourzandi Apr 2005 + */ +#ifndef _DIGSIG_SYSFS_H +#define _DIGSIG_SYSFS_H + +//ssize_t digsig_store (struct kobject *obj, struct attribute *attr, const char *buff, size_t count); +//ssize_t digsig_show (struct kobject *obj, struct attribute *attr, char *buff); + +ssize_t digsig_rev_list_store (struct kobject *obj, struct attribute *attr, const char *buff, size_t count); +ssize_t digsig_rev_list_show (struct kobject *obj, struct attribute *attr, char *buff); + +int digsig_init_sysfs(void); +void digsig_cleanup_sysfs(void); + +#endif /* _DSI_SYSFS_H */ diff -rNu linux.orig-2.6.19/security/digsig/Documentation/digsig.txt linux-2.6.16/security/digsig/Documentation/digsig.txt --- linux.orig-2.6.19/security/digsig/Documentation/digsig.txt 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/Documentation/digsig.txt 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,282 @@ +Release of digsig 1.5 +======================= + +Overview +======== + +This kernel module checks signature of a binary before running it. +The main functionality is to insert digital signatures inside the ELF +binary and verify this signature before loading the binary. It is +based on the LSM hooks. + + +Our approach has been to use existing solutions like GPG and bsign +rather than reinventing from scratch. + +In order to reduce the overhead in the kernel, we took only the minimum +code necessary from GPG. We took only the MPI (Multi Precision Integer) +source code and the RSA cryptography source code. This greatly helped to +reduce the amount of code imported into the kernel. Only one-tenth of +the original gnupg 1.2.2 source code has been imported to the kernel +module. We avoided using the OpenSSL source code due to unclear +licensing. We did some tests at the userspace level and determined that +OpenSSL performs RSA verification four times faster than GPG. Due to +this performance advantage, we plan to clarify the licensing issue and, +if possible, use OpenSSL instead of GPG. + + +Requirements +============ + +To compile: + You need a Linux kernel 2.6.8 or greater. + Your kernel must be compiled with: + CONFIG_SECURITY=Y + CONFIG_SHA1=Y (or m, but then load the sha1 module first + before DigSig !). + You do NOT need DSI: DigSig is an independent project, + though it historically uses DSI's CVS. + +To run, you need: + bsign 0.4.5 - see http://packages.qa.debian.org/b/bsign.html + + GPG : a version that supports RSA key generation (for instance, + greater than 1.2.2) - see http://www.gnupg.org + + module-init-tools: For some old distros you may require + module-init-tools for 2.6.x kernels. + See: + http://www.kernel.org/pub/linuxkernel/people/rusty/modules + + +Compiling +========= + +You can set different compilation arguments in Makefile: + + -DIGSIG_DEBUG: When this variable is set Digsig will run in debug + mode. In debug mode, DigSig lets unsigned binaries run. This state + is ideal to test DigSig, and also list the binaries you need to sign + to get a fully operational system. + + -DDSI_EXEC_ONLY: DigSig normally verifies the signatures for + executable binaries and shared libraries. If you wish for + performance reason or whatever other reason to only verify the + signatures for executable binaries set this variable. + These options have been removed due to insecurity. + + -DDIGSIG_LOG: This activates the logging. Be careful about the + size of logs generated at run time. + + +Module Parameters +================= + +DigSig currently accepts a single optional parameter. If it is loaded +with digsig_max_cached_sigs=, then it will cache up to +signature validations. The default value is 512. + +To enable this parameter using digsig.init, you would change the module +insertion line from: + + /sbin/insmod -f ./digsig_verif.ko || exit 1 + +to: + + /sbin/insmod -f ./digsig_verif.ko digsig_max_cached_sigs=1024 || exit 1 + + +Caching Support +=============== + +From release 1.2 onward, the caching of signatures at kernel level is +supported. Once the signature of a binary is verified, its signature is +cached in kernel memory. Therefore, there is no need for signature +verification in subsequent calls to that binary. When a binary file is +modified, the corresponding cache entry in the memory is invalidated. + + +Revocation Support +================== + +As of release 1.3, revocation of signatures is supported. If a library +or binary is found to have a vulnerability, you no longer want DigSig to +allow that file to be loaded. By revoking the signature, you tell digsig +that although the file's signature was in fact calculated with the valid +private key, it should nevertheless refuse to load this binary. + +You can revoke a signature as follows: Assume we want to revoke the +signatures for sshd and ftpd. Use tools/extract_sig (use a patched +version of bsign for now) to extract the signature of each file into +separate files under /etc/digsig_revoked_keys/. For instance: + +$ ./tools/extract_sig /usr/sbin/sshd \ + /etc/digsig_revoked_keys/sshd_v3.5p1 + +$ ./tools/extract_sig /usr/sbin/in.ftpd /etc/digsig_revoked_keys/ftpd + +Now the startup script ./digsig.init will automatically copy these files +into /sys/digsig/digsig_revoke after module insertion and before the +public key is committed. Once digsig starts enforcing, no more signature +revocations are accepted. Any attempts to execute the revoked versions +of /usr/sbin/sshd or /usr/sbin/in.ftpd will be refused. + +To disable revocation, remove the "-DREVOCATION" flag from EXTRA_CFLAGS +in ./Makefile. + + +A Very simple scenario to show how to use DigSig +================================================ + +1) Generate an GPG key and export the public key in order to use it for +signature verification: + +$ gpg --gen-key + +*Carefully* generate an RSA key: + +$ gpg --export >> my_public_key.pub + +2) Sign your binaries using bsign: + +Before using bsign to sign all your binaries, experiment with a simple +example. + +$ cp `which ps` ps-test +$ bsign -s ps-test // sign the binary +$ bsign -V ps-test // be sure that the signature is valid + +Provided that these commands work, sign all your binaries and libraries +using bsign. Consult section 2 ("Usage") of the bsign README for helpful +hints. + +3) Make the DigSig module: + +From ./digsig, do make -C /usr/src/linux-2.5.66 SUBDIRS=$PWD modules. +You need readwrite (rw) access to /usr/src/linux-2.5.66. + +CAREFUL: We advice you to compile the module in debug mode at your first +attempt (see -DDIGSIG_DEBUG in the Makefile). In this mode, the module +verifies the signatures but does not enforce the security. If there are +not any signature present in your binary, you'll have a message in +/var/log/messages, but the execution is not aborted. However, the +execution of the binaries with invalid signatures is aborted. Once +you're sure of your binary signature procedure you can recompile in +non-debug mode. + +4) Load DigSig, using the public key exported in step 1 as the argument. + +Be sure that sysfs is mounted in /sys or the key won't be loaded. You +can mount sysfs with the command: + +root@colby digsig-dev]# mount -t sysfs sysfs /sys + +Now start DigSig: + +root@colby digsig-dev]# ./digsig.init start pubkey.pub +Loading Digsig module. +Making device for communication with the module. +Loading public key. +Done. + +5) In debug mode: +$ ps +$ ./ps-test + +$ tail -f /var/log/messages +Sep 16 15:49:13 colby kernel: DIGSIG MODULE - binary is /bin/ps +Sep 16 15:49:16 colby kernel: DIGSIG MODULE - binary is ./ps-makan +Sep 16 15:49:16 colby kernel: DIGSIG MODULE - dsi_bprm_compute_creds: Found signature section +Sep 16 15:49:16 colby kernel: DIGSIG MODULE - dsi_bprm_compute_creds: Signature verification successful + +6) In restrictive mode, normal mode: + +You must use bsign to sign all binaries that you want to run in normal +mode: + +// signed binary: + +[lmcmpou@reblochon lmcmpou]$ ps + PID TTY TIME CMD + 6897 pts/2 00:00:00 bash + 6941 pts/2 00:00:00 ps + +// unsigned binary: + +[lmcmpou@reblochon lmcmpou]$ ./ps-makan-1 +bash: ./ps-makan: cannot execute binary file + +// binary with wrong signature: + +[lmcmpou@reblochon lmcmpou]$ ./ps-makan-2 +bash: ./ps-makan-colby: Operation not permitted + +7) Unload the module. + +[root@colby digsig-dev]# ./digsig.init stop +Unloading Digsig. + + +Performance +=========== + +We have done some benchmarks without caching. The performance impact is +small after the first load of the binary, as the signature of the file +is cached in the memory. + +Macro tests: + +We ran lmbench on a Pentium IV, 2.4 GHz with 500 megabytes of memory, +running Linux 2.5.66. Our benchmarks show that the execution time (exec +function call) multiplies by a factor of four when the module is loaded +(no changes for fork call, as the binary is not loaded into memory). + +Micro tests with gnupg: + +See the table below for the overhead at kernel-level for checking the +signature. + +We show the performance of DigSig running with the variable +DSI_EXEC_ONLY set. This means that we only measure the time for +verifying the signature of the executable binary and do not take into +account the time necessary to verify the signatures for the shared +libraries. + +The hardware is the same, namely a 2.4 GHz Pentium IV with 500 Megabytes +of memory, running Linux 2.5.66: + ++-----------+---------+----------+ +| Binaries | Size | GnuPG | ++-----------+---------+----------+ +| ls | 68230 | 1.61765 | +| ps | 70337 | 1.67742 | +| busybox | 248801 | 4.66666 | +| cvs | 672532 | 11.53571 | +| vim | 1894305 | 31.25000 | +| emacs | 4093614 | 67.41176 | ++-----------+---------+----------+ + +Time is in jiffies. 1 jiffies = 1ms + +Linear regression time = 1.393899E-5 * size + 0.815081 + + +Acknowledgments +=============== + +This work has been done by (alphabetical order) + +A Apvrille (axellec@miscmag.com), +D Gordon (davidgordonca@yahoo.ca), +S Hallyn (serue@us.ibm.com), +M Pourzandi (makan.pourzandi@ericsson.com), +V Roy (vincent.r.roy@gmail.com). + +Thanks to Radu Filip who has done the initial analysis. +Thanks to Marc Springer who helped us with the use of Bsign. +Thanks to Chris Wright for his helpful input and comments on DigSig. +Thanks to benoit.hamet@mist-technologies.com for his first +patch to include digsig in the kernel. + +For more detailed documentaiton, see: +http://disec.sourceforge.net \ No newline at end of file diff -rNu linux.orig-2.6.19/security/digsig/gnupg/cipher/Makefile linux-2.6.16/security/digsig/gnupg/cipher/Makefile --- linux.orig-2.6.19/security/digsig/gnupg/cipher/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/cipher/Makefile 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,2 @@ +obj-m := rsa-verify.o +clean-files := *.o *.ko dsm.mod.* .*.o.cmd .*.cmd diff -rNu linux.orig-2.6.19/security/digsig/gnupg/cipher/rsa-verify.c linux-2.6.16/security/digsig/gnupg/cipher/rsa-verify.c --- linux.orig-2.6.19/security/digsig/gnupg/cipher/rsa-verify.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/cipher/rsa-verify.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,101 @@ +/* rsa.c - RSA function + * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) + * Copyright (C) 2000, 2001 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 code uses an algorithm protected by U.S. Patent #4,405,829 + which expires on September 20, 2000. The patent holder placed that + patent into the public domain on Sep 6th, 2000. +*/ + +#include "../mpi/mpi.h" +#include "rsa-verify.h" + +#define G10ERR_PUBKEY_ALGO 4 /* Unknown pubkey algorithm */ +#define G10ERR_BAD_SIGN 8 /* Bad signature */ +#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ +#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ + + +typedef struct { + MPI n; /* modulus */ + MPI e; /* exponent */ +} RSA_public_key; + + +typedef struct { + MPI n; /* public modulus */ + MPI e; /* public exponent */ + MPI d; /* exponent */ + MPI p; /* prime p. */ + MPI q; /* prime q. */ + MPI u; /* inverse of p mod q. */ +} RSA_secret_key; + + +static void public(MPI output, MPI input, RSA_public_key *skey ); + + +/**************** + * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT. + * + * c = m^e mod n + * + * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY. + */ +static void +public(MPI output, MPI input, RSA_public_key *pkey ) +{ + if( output == input ) { /* powm doesn't like output and input the same */ + MPI x = mpi_alloc( mpi_get_nlimbs(input)*2 ); + mpi_powm( x, input, pkey->e, pkey->n ); + mpi_set(output, x); + mpi_free(x); + } + else + mpi_powm( output, input, pkey->e, pkey->n ); +} + + +/********************************************* + ************** interface ****************** + *********************************************/ + +int +rsa_verify( MPI hash, MPI *data, MPI *pkey) +{ + RSA_public_key pk; + MPI result; + int rc; + + pk.n = pkey[0]; + pk.e = pkey[1]; + result = mpi_alloc( (160+(BITS_PER_MPI_LIMB-1))/BITS_PER_MPI_LIMB); + public( result, data[0], &pk ); + rc = mpi_cmp( result, hash )? G10ERR_BAD_SIGN:0; + mpi_free(result); + + return rc; +} + + + + + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/cipher/rsa-verify.h linux-2.6.16/security/digsig/gnupg/cipher/rsa-verify.h --- linux.orig-2.6.19/security/digsig/gnupg/cipher/rsa-verify.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/cipher/rsa-verify.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,29 @@ +/* rsa.h + * Copyright (C) 1997,1998 by Werner Koch (dd9jn) + * Copyright (C) 2000, 2001 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_RSA_H +#define G10_RSA_H + +#include "../mpi/mpi.h" + +int rsa_verify( MPI hash, MPI *data, MPI *pkey); + +#endif /*G10_RSA_H*/ diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/ChangeLog linux-2.6.16/security/digsig/gnupg/mpi/ChangeLog --- linux.orig-2.6.19/security/digsig/gnupg/mpi/ChangeLog 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/ChangeLog 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,411 @@ +2003-04-23 David Shaw + + * config.links: Put back proper copyright line. + + * config.links: Re-disable assembler on Darwin. Darwin 6.5 broke + it again. + +2003-04-15 Werner Koch + + * longlong.h (umul_ppmm): Support SH3 and SH4. Thanks to + kazuya.s@jp.yokogawa.com. + +2003-03-24 Werner Koch + + * Makefile.am: Make use of AM_CFLAGS. + +2002-11-16 David Shaw + + * config.links: Use OpenBSD/NetBSD powerpc assembler code for + Darwin. Successfully tested by Gordon Worley. + +2002-10-17 Werner Koch + + * config.links (powerpc-apple-darwin6.1): Disable assembler + due to non-working modules/as. Suggested by Gordon Worley. + +2002-10-02 David Shaw + + * longlong.h: Some whitespace changes in HPPA to fix assembler + problems on HP-UX. From David Ellement. + +2002-09-20 Werner Koch + + * mpicoder.c (do_get_buffer): Avoid zero length allocation. + Checked that all callers behave properly when NBYTES returns 0 as + the length of the allocated buffer. + +2002-09-10 Werner Koch + + * mpi-bit.c (mpi_normalize): Replaced the check for protected by + is_opaque. + (mpi_get_nbits): Removed the special case for protected MPIs. + * mpicoder.c (do_get_buffer): Likewise. + (mpi_print): Removed the nbit_info printing. + +2002-09-03 Werner Koch + + * mpicoder.c (mpi_set_buffer): Cast all left operands of a shift + to a larger type so that 16 bit CPUs don't suffer from an + overflow. Suggested by TOGAWA Satoshi. + +2002-08-24 David Shaw + + * longlong.h: Remove space between \ and newline. gcc is + complaining. + +2002-08-13 Werner Koch + + * mpicoder.c (do_get_buffer): Don't remove leading zeros if the + MPI is marked as protected. + +2002-08-02 Timo Schulz + + * mpicoder.c: Add a '\n' to all log_bug functions. + +2002-08-01 Werner Koch + + * config.links: Added case for sparc64-netbsd. Suggested by + ww@styx.org. + +2002-07-25 David Shaw + + * config.links: Add special rule for OpenBSD on x86 to use special + i386-openbsd files. OpenBSD (at least until version 3.1) has an + older assembler that won't work with the files in i386. + +2002-07-24 Stefan Bellon + + * longlong.h [__riscos__]: Removed #pragma which is not needed + anymore since the K&R multiline strings are gone. + +2002-07-24 Werner Koch + + * longlong.h: Replaced all K&R multiline strings by ISO ones for + the sake of modern compilers. Suggested by Marco Parrone. + +2002-05-10 Stefan Bellon + + * mpiutil.c (mpi_alloc_like/mpi_debug_alloc_like): Added code + for M_DEBUG. + +2002-04-18 Werner Koch + + * i386/syntax.h (ALIGN): Removed parens from definition + * i386/mpih-add1.S, i386/mpih-sub1.S, i386/mpih-rshift.S, + i386/mpih-lshift.S: Minor syntax changes suggested by Mark Pettit + after comparing the files with those for GMP 4. + +2001-11-08 Werner Koch + + * config.links (mpi_sflags): Add extra rule for sparc64-sun-solaris2. + +2001-08-20 Werner Koch + + * longlong.h [__riscos__]: Need a special pragma here. + +2001-08-09 Werner Koch + + * config.links: Added configuraton for powerpc-openbsd. By Peter + Valchev + +2001-07-09 Werner Koch + + * config.links: Changed the way the list of files to be + symlinked is returned. + +2001-05-27 Werner Koch + + * hppa/, hppa1.1/, pa7100/ : Use .label command instead of labels + because there syntax changed. By Matthew Wilcox. + +2001-05-06 Werner Koch + + * longlong.h: Fixes for ARM by Phil Blundell. + +2001-04-17 Werner Koch + + Updated copyright notices. + +2001-03-24 Werner Koch + + * mpi-mul.c (mpi_mul): Make sure that secret temporary results are + not stored in w. Suggested by Florian Weimer. + +2001-03-18 Werner Koch + + * config.links: Use i386 code for i386. According to tests by + Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto for i786. + +2000-10-24 Werner Koch + + * mips3/: Changed a few comments to C-style. By Jeff Long. + +2000-10-13 Werner Koch + + * mpi.h: Removed the inclusion of mpi-asm-defs.h because this + makes some trouble when doing a VPATH build. configure now + takes care of it. + +2000-10-12 Werner Koch + + * generic/mpi-asm-defs.h: New. + * mips3/mpi-asm-defs.h: New. + * config.links: Create a link to one of the above files. + +Wed Jul 19 11:26:43 CEST 2000 Werner Koch + + * config.links: Support for powerpc--netbsd by Gabriel Rosenkoetter. + +Wed Mar 22 13:50:24 CET 2000 Werner Koch + + * config.links: Add support for FreeBSD 5 and made the case stmt + looking nicer. From Jun Kuriyama. + +Fri Mar 17 17:50:25 CET 2000 Werner Koch + + * config.links (sparc64-unknown-linux-gnu): use udic module. + From Adam Mitchell. + +2000-03-14 12:03:56 Werner Koch (wk@habibti.openit.de) + + * Makefile.am: Do not use .s and .S files but a temp names, so that + OSes with caseinsensitive filenames do work. From Frank Donahoe. + +Tue Mar 7 18:45:31 CET 2000 Werner Koch + + * mpih-mul.c (mpihelp_mul_karatsuba_case): It seems that the + untested part works fine. Removed the debugging message. + + * longlong.h (umul_ppmm): Fixes for ARM-4. By Sean MacLennan. + + * config.links: Add support for NetBSD. + +Thu Jan 13 19:31:58 CET 2000 Werner Koch + + * mpi-internal.h (karatsuba_ctx): New. + * mpih-mul.c (mpihelp_release_karatsuba_ctx): New. + (mpihelp_mul_karatsuba_case): New. + (mpihelp_mul): Splitted to make use of the new functions. + * mpi-pow.c (mpi_powm): Make use of the new splitted function + to avoid multiple allocation of temporary memory during the + karatsuba operations. + + * mpi_mpow.c: Removed the unused Barrett code. + +Sun Dec 19 15:22:26 CET 1999 Werner Koch + + * power/ : Converted more comments to C comments because some AS + complain about ' in comments. + +Thu Dec 16 10:07:58 CET 1999 Werner Koch + + * Makefile.am: c/SFLAGS/ASFLAGS/. This has only been used by the + powerpc and actually never passed the -Wa,foo to the cc. + +Thu Dec 9 10:31:05 CET 1999 Werner Koch + + * power/: Add all files from GMP for this CPU. + + * config.links: Support for BSDI 4.x. By Wayne Chapeskie. + (sparc8): Made the search path the same as sparc9 + + * mpih-div.c (mpihelp_divrem): The MPN_COPY_DECR copied one + elemnat too many. This is gmp2.0.2p9.txt patch. + +Sat Oct 9 20:34:41 CEST 1999 Werner Koch + + * Makefile.am: Removed libtool. + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch + + * config.links: Add case label for DJGPP + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch + + + * Makefile.am: Use .s files as temporaries, disabled other .S rules. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch + + + * mpicoder.c (g10_log_mpidump): New. + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch + + + * mpi-bit.c (mpi_lshift_limbs,mpi_rshift_limbs): New. + * mpi-mpow.c (barrett_mulm): New but diabled. + +Tue Jun 1 16:01:46 CEST 1999 Werner Koch + + * config.links (i[56]86*-*-freebsdelf*): New. + +Sun May 23 14:20:22 CEST 1999 Werner Koch + + * config.links (sysdep.h): Not any more conditionally created. + +Tue May 4 15:47:53 CEST 1999 Werner Koch + + * mpiutil.c (mpi_alloc_like): New. + +Mon Apr 26 17:48:15 CEST 1999 Werner Koch + + * mpih-add.c, mpih-sub.c: Removed + * mpi-inline.c: New. + * mpi-inline.h: Make it usable by mpi-inline.c. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch + + * mpih-mul.c (mpihelp_mul_n): Fixed use of memory region. + (mpihelp_mul): Ditto. + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch + + * Makefile.am: Explicit rules to invoke cpp on *.S + +Mon Mar 8 20:47:17 CET 1999 Werner Koch + + * config.links: Take advantage of the with_symbol_underscore macro. + Add support for freebsd 4. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch + + * mips3/mpih-sub1.S: Removed left over junk in last line. (Should I + blame me or my editor?). + +Sat Feb 13 12:04:43 CET 1999 Werner Koch + + * Makefile.am: Removed the +=. Add MPI_OPT_FLAGS. + +Sat Jan 9 16:02:23 CET 1999 Werner Koch + + * mpi-cmp.c (mpi_cmp_ui): Normalized the arg. + +Thu Jan 7 18:00:58 CET 1999 Werner Koch + + * mpi-bit.c (mpi_normalize): New. + (mpi_get_nbits): Normalize the MPI. + * mpi-bit.c (mpi_cmp): Normalize the MPI before the compare. + + +Tue Dec 8 13:15:16 CET 1998 Werner Koch + + * config.links: Moved the case for powerpc*linux + * powerpcp32/*.S: Removed some underscores. + +Thu Nov 26 07:27:52 1998 Werner Koch + + * config.links: Support for ppc with ELF + * powerpc32/syntax.h: New. + * powerpc32/*.S: Applied ELF patches (glibc patches) + +Tue Nov 10 19:31:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * power*/ : Started with stuff for PPC + * config.links: Some stuff for PPC. + * generic/udiv-w-sdiv.c: New but disabled. + +Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): Fixes for FreeBSD 3.0 + +Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): ELF patches from Jun Kuriyama. + +Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free). + +Thu Sep 17 18:08:50 1998 Werner Koch (wk@(none)) + + * hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20 + +Thu Aug 6 16:39:28 1998 Werner Koch,mobil,,, (wk@tobold) + + * mpi-bit.c (mpi_set_bytes): Removed. + +Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none)) + + * mpicoder.c (mpi_read_from_buffer): New. + + * mpiutil.c (mpi_set_opaque): New. + (mpi_get_opaque): New. + (mpi_copy): Changed to support opauqe flag + (mpi_free): Ditto. + +Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_clear): Reset flags. + (mpi_set): Ditto. + (mpi_alloc_secure): Set flag to 1 and not ored the 1 in, tsss.. + +Fri Jun 26 11:19:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_alloc): set nbits to 0. + (mpi_alloc_secure): Ditto. + (mpi_clear): Ditto. + +Thu Jun 25 11:50:01 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mips3/*.S: New + +Mon May 18 13:47:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: split mpih-shift into mpih-[lr]shift and + changed all implementations. + * mpi/alpha: add some new assembler stuff. + +Wed May 13 11:04:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Add support for MIPS + +Thu Apr 9 11:31:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_secure_buffer): New. + +Wed Apr 8 09:44:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Applied small fix from Ulf Möller. + +Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_buffer): Removed returned leading zeroes + and changed all callers. + +Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-bit.c (mpi_clear_highbit): New. + +Mon Mar 2 19:29:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (DISTCLEANFILES): New + +Thu Feb 26 06:48:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (X86_BROKEN_ALIGN): Added for some systems. + +Mon Feb 23 12:21:40 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi/m68k/mpih-shift.S (Lspecial): Changed duplicate symbol. + +Mon Feb 16 13:00:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links : Add detection of m68k cpus + + + + Copyright 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/config.h linux-2.6.16/security/digsig/gnupg/mpi/config.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/config.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/config.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,540 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Defined if the host has big endian byte ordering */ +/* #undef BIG_ENDIAN_HOST */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* define to disable keyserver helpers */ +/* #undef DISABLE_KEYSERVER_HELPERS */ + +/* define to disable exec-path for keyserver helpers */ +/* #undef DISABLE_KEYSERVER_PATH */ + +/* define to disable photo viewing */ +/* #undef DISABLE_PHOTO_VIEWER */ + +/* Define if you don't want the default EGD socket name. For details see + cipher/rndegd.c */ +#define EGD_SOCKET_NAME "" + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#define ENABLE_NLS 1 + +/* if set, restrict photo-viewer to this */ +/* #undef FIXED_PHOTO_VIEWER */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARGZ_H 1 + +/* Define to 1 if you have the `atexit' function. */ +#define HAVE_ATEXIT 1 + +/* Define if `gethrtime(2)' does not work correctly i.e. issues a SIGILL. */ +/* #undef HAVE_BROKEN_GETHRTIME */ + +/* Defined if the mlock() call does not work */ +/* #undef HAVE_BROKEN_MLOCK */ + +/* Defined if a `byte' is typedef'd */ +/* #undef HAVE_BYTE_TYPEDEF */ + +/* Define to 1 if you have the `clock_gettime' function. */ +/* #undef HAVE_CLOCK_GETTIME */ + +/* Define to 1 if you have the `ctermid' function. */ +#define HAVE_CTERMID 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGLIST 0 + +/* defined if the system supports a random device */ +#define HAVE_DEV_RANDOM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `dlopen' function. */ +/* #undef HAVE_DLOPEN */ + +/* Defined when the dlopen function family is available */ +#define HAVE_DL_DLOPEN 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) + with special properties like no file modes */ +/* #undef HAVE_DOSISH_SYSTEM */ + +/* defined if we must run on a stupid file system */ +/* #undef HAVE_DRIVE_LETTERS */ + +/* Define to 1 if you have the `feof_unlocked' function. */ +#define HAVE_FEOF_UNLOCKED 1 + +/* Define to 1 if you have the `fgets_unlocked' function. */ +#define HAVE_FGETS_UNLOCKED 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getc_unlocked' function. */ +#define HAVE_GETC_UNLOCKED 1 + +/* Define to 1 if you have the `getegid' function. */ +#define HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define if you have the `gethrtime(2)' function. */ +/* #undef HAVE_GETHRTIME */ + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define if you have the iconv() function. */ +#define HAVE_ICONV 1 + +/* Define if exists and doesn't clash with . */ +#define HAVE_INTTYPES_H 1 + +/* Define if exists, doesn't clash with , and + declares uintmax_t. */ +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define if your file defines LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +#define HAVE_LIBDL 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +/* #undef HAVE_LIBRT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have the `mkdtemp' function. */ +#define HAVE_MKDTEMP 1 + +/* Defined if the system supports an mlock() call */ +#define HAVE_MLOCK 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `plock' function. */ +/* #undef HAVE_PLOCK */ + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `raise' function. */ +#define HAVE_RAISE 1 + +/* Define to 1 if you have the `rand' function. */ +#define HAVE_RAND 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `sigprocmask' function. */ +#define HAVE_SIGPROCMASK 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if exists, doesn't clash with , and declares + uintmax_t. */ +#define HAVE_STDINT_H_WITH_UINTMAX 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlwr' function. */ +/* #undef HAVE_STRLWR */ + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_CAPABILITY_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IPC_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SHM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `tcgetattr' function. */ +#define HAVE_TCGETATTR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the `tsearch' function. */ +#define HAVE_TSEARCH 1 + +/* Defined if a `u16' is typedef'd */ +/* #undef HAVE_U16_TYPEDEF */ + +/* Defined if a `u32' is typedef'd */ +/* #undef HAVE_U32_TYPEDEF */ + +/* Defined if a `ulong' is typedef'd */ +#define HAVE_ULONG_TYPEDEF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the unsigned long long type. */ +#define HAVE_UNSIGNED_LONG_LONG 1 + +/* Defined if a `ushort' is typedef'd */ +#define HAVE_USHORT_TYPEDEF 1 + +/* Define to 1 if you have the `vfork' function. */ +#define HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VFORK_H */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the `wait4' function. */ +#define HAVE_WAIT4 1 + +/* Define to 1 if you have the `waitpid' function. */ +#define HAVE_WAITPID 1 + +/* Define to 1 if `fork' works. */ +#define HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#define HAVE_WORKING_VFORK 1 + +/* Define to 1 if you have the `__argz_count' function. */ +#define HAVE___ARGZ_COUNT 1 + +/* Define to 1 if you have the `__argz_next' function. */ +#define HAVE___ARGZ_NEXT 1 + +/* Define to 1 if you have the `__argz_stringify' function. */ +#define HAVE___ARGZ_STRINGIFY 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Define if integer division by zero raises signal SIGFPE. */ +#define INTDIV0_RAISES_SIGFPE 1 + +/* Defined if a SysV shared memory supports the LOCK flag */ +#define IPC_HAVE_SHM_LOCK 1 + +/* Defined if we can do a deferred shm release */ +#define IPC_RMID_DEFERRED_RELEASE 1 + +/* Defined if this is not a regular release */ +/* #undef IS_DEVELOPMENT_VERSION */ + +/* Defined if the host has little endian byte ordering */ +#define LITTLE_ENDIAN_HOST 1 + +/* Defined if mkdir() does not take permission flags */ +/* #undef MKDIR_TAKES_ONE_ARG */ + +/* Define to use the (obsolete) malloc guarding feature */ +/* #undef M_GUARD */ + +/* defined to the name of the strong random device */ +#define NAME_OF_DEV_RANDOM "/dev/random" + +/* defined to the name of the weaker random device */ +#define NAME_OF_DEV_URANDOM "/dev/urandom" + +/* Define if the LDAP library requires including lber.h before ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to disable all external program execution */ +/* #undef NO_EXEC */ + +/* Name of this package */ +#define PACKAGE "gnupg" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-gnupg@gnu.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "gnupg" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "gnupg 1.2.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "gnupg" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.2" + +/* A human readable text with the name of the OS */ +#define PRINTABLE_OS_NAME "GNU/Linux" + +/* Define if exists and defines unusable PRI* macros. */ +/* #undef PRI_MACROS_BROKEN */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of a `unsigned int', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The size of a `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The size of a `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* The size of a `unsigned short', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Allow to select random modules at runtime. */ +/* #undef USE_ALL_RANDOM_MODULES */ + +/* define if capabilities should be used */ +/* #undef USE_CAPABILITIES */ + +/* define to enable the use of extensions */ +#define USE_DYNAMIC_LINKING 1 + +/* define to use the experimental external HKP keyserver interface */ +/* #undef USE_EXTERNAL_HKP */ + +/* Define to use the old fake OID for TIGER/192 digest support */ +/* #undef USE_OLD_TIGER */ + +/* set this to limit filenames to the 8.3 format */ +/* #undef USE_ONLY_8DOT3 */ + +/* Defined if the EGD based RNG should be used. */ +/* #undef USE_RNDEGD */ + +/* Defined if the /dev/random based RNG should be used. */ +#define USE_RNDLINUX 1 + +/* Defined if the default Unix RNG should be used. */ +/* #undef USE_RNDUNIX */ + +/* Defined if the Windows specific RNG should be used. */ +/* #undef USE_RNDW32 */ + +/* Define to include read-only SHA-384 and SHA-512 digest support */ +/* #undef USE_SHA512 */ + +/* define if the shared memory interface should be made available */ +#define USE_SHM_COPROCESSING 1 + +/* because the Unix gettext has too much overhead on MingW32 systems and these + systems lack Posix functions, we use a simplified version of gettext */ +/* #undef USE_SIMPLE_GETTEXT */ + +/* Define to include experimental TIGER/192 digest support */ +/* #undef USE_TIGER */ + +/* Version of this package */ +#define VERSION "1.2.2" + +/* Defined if compiled symbols have a leading underscore */ +/* #undef WITH_SYMBOL_UNDERSCORE */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Some tests rely on this (stpcpy) and it should be used for new programs + anyway */ +#define _GNU_SOURCE 1 + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +/* #undef inline */ + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to unsigned long or unsigned long long if and + don't define. */ +/* #undef uintmax_t */ + +/* Define as `fork' if `vfork' does not work. */ +/* #undef vfork */ + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ + + +#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) +#define EXEC_TEMPFILE_ONLY +#endif + +#include "g10defs.h" + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/config.links linux-2.6.16/security/digsig/gnupg/mpi/config.links --- linux.orig-2.6.19/security/digsig/gnupg/mpi/config.links 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/config.links 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,327 @@ +# config.links - helper for ../configure +# Copyright (C) 1998,1999,2000,2001,2002,2003 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 + +# sourced by ../configure to get the list of files to link +# this should set $mpi_ln_list. +# Note: this is called from the above directory. + + +mpi_extra_modules= +mpi_sflags= + +test -d ./mpi || mkdir ./mpi + +echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h + +if test "$try_asm_modules" = "yes" ; then +case "${target}" in + powerpc-apple-darwin*) + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + i[3467]86*-*-freebsd*-elf | \ + i[3467]86*-*-freebsd[3-9]* | \ + i[3467]86*-*-freebsdelf* | \ + i[3467]86*-*-netbsd* ) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-freebsd*-elf | \ + i586*-*-freebsd[3-9]* | \ + i586*-*-freebsdelf* | \ + i586*-*-netbsd* | \ + pentium-*-netbsd* | \ + pentiumpro-*-netbsd*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[34]86*-*-bsdi4*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; +# Use old assembler syntax for OpenBSD as their assembler is really old. + i[34567]86*-*-openbsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386-openbsd/syntax.h >>./mpi/asm-syntax.h + path="i386-openbsd" + ;; + i[3467]86*-*-linuxaout* | \ + i[3467]86*-*-linuxoldld* | \ + i[3467]86*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-linuxaout* | \ + i586*-*-linuxoldld* | \ + i586*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-msdosdjgpp*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-msdosdjgpp*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-* | \ + pentium-*-* | \ + pentiumpro-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + alpha*-*-*) + echo '/* configured for alpha */' >>./mpi/asm-syntax.h + path="alpha" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa7000*-*-*) + echo '/* configured for HPPA (pa7000) */' >>./mpi/asm-syntax.h + path="hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa1.0*-*-*) + echo '/* configured for HPPA 1.0 */' >>./mpi/asm-syntax.h + path="hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa*-*-*) # assume pa7100 + echo '/* configured for HPPA (pa7100) */' >>./mpi/asm-syntax.h + path="pa7100 hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + sparc64-*-linux-gnu) + # An extra rule because we have an report for this one only. + # Should be compared against the next GMP version + echo '/* configured for sparc64-*-linux-gnu */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc64-sun-solaris2*) + # Got a report that udiv is missing, so we try this one + echo '/* configured for sparc64-sun-solaris2 */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc64-*-netbsd) + # There are no sparc64 assembler modules that work, so + # just use generic C functions + echo '/* configured for sparc64-*netbsd */' >>./mpi/asm-syntax.h + path="" + ;; + sparc9*-*-* | \ + sparc64*-*-* | \ + ultrasparc*-*-* ) + echo '/* configured for sparc9 or higher */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + sparc8*-*-* | \ + microsparc*-*-*) + echo '/* configured for sparc8 */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + supersparc*-*-*) + echo '/* configured for supersparc */' >>./mpi/asm-syntax.h + path="supersparc sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc*-*-*) + echo '/* configured for sparc */' >>./mpi/asm-syntax.h + path="sparc32" + mpi_extra_modules="udiv" + ;; + mips[34]*-*-* | \ + mips*-*-irix6*) + echo '/* configured for MIPS3 */' >>./mpi/asm-syntax.h + path="mips3" + ;; + mips*-*-*) + echo '/* configured for MIPS2 */' >>./mpi/asm-syntax.h + path="mips2" + ;; + + # Motorola 68k configurations. Let m68k mean 68020-68040. + # mc68000 or mc68060 configurations need to be specified explicitly + m680[234]0*-*-linuxaout* | \ + m68k*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68060*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m680[234]0*-*-linux* | \ + m68k*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + ;; + m68060*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m68k-atari-mint) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68000*-*-* | \ + m68060*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68000" + ;; + m680[234]0*-*-* | \ + m68k*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + + powerpc*-*-linux*) + echo '/* configured for powerpc/ELF */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + path="powerpc32" + ;; + + powerpc*-*-netbsd* | powerpc*-*-openbsd*) + echo '/* configured for {Open,Net}BSD on powerpc */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + + rs6000-*-aix[456789]* | \ + rs6000-*-aix3.2.[456789]) + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + rs6000-*-* | \ + power-*-* | \ + power2-*-*) + mpi_sflags="-Wa,-mppc" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + powerpc-ibm-aix4.2.* ) + # I am not sure about this one but a machine identified by + # powerpc-ibm-aix4.2.1.0 cannot use the powerpc32 code. + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + ppc601-*-*) + mpi_sflags="-Wa,-mppc" + path="power powerpc32" + ;; + ppc60[234]*-*-* | \ + powerpc*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + ppc620-*-* | \ + powerpc64*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc64" + ;; + + *) + echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h + path="" + ;; +esac +else + echo '/* Assembler modules disabled on request */' >>./mpi/asm-syntax.h + path="" +fi + + +# Make sysdep.h +echo '/* created by config.links - do not edit */' >./mpi/sysdep.h +if test x$ac_cv_sys_symbol_underscore = xyes; then + cat <>./mpi/sysdep.h +#if __STDC__ +#define C_SYMBOL_NAME(name) _##name +#else +#define C_SYMBOL_NAME(name) _/**/name +#endif +EOF +else + cat <>./mpi/sysdep.h +#define C_SYMBOL_NAME(name) name +EOF +fi + + +# fixme: grep these modules from Makefile.in +mpi_ln_modules="${mpi_extra_modules} mpih-add1 mpih-mul1 mpih-mul2 mpih-mul3 \ + mpih-lshift mpih-rshift mpih-sub1" + +mpi_ln_objects= +mpi_ln_list= + +# try to get file to link from the assembler subdirectory and +# if this fails get it from the generic subdirectory. +path="$path generic" +for fn in $mpi_ln_modules ; do + mpi_ln_objects="$mpi_ln_objects $fn.o" + for dir in $path ; do + rm -f $srcdir/mpi/$fn.[Sc] + if test -f $srcdir/mpi/$dir/$fn.S ; then + mpi_ln_list="$mpi_ln_list mpi/$fn.S:mpi/$dir/$fn.S" + break; + elif test -f $srcdir/mpi/$dir/$fn.c ; then + mpi_ln_list="$mpi_ln_list mpi/$fn.c:mpi/$dir/$fn.c" + break; + fi + done +done + +# Same thing for the file which defines the limb size +path="$path generic" +for dir in $path ; do + rm -f $srcdir/mpi/mpi-asm-defs.h + if test -f $srcdir/mpi/$dir/mpi-asm-defs.h ; then + mpi_ln_list="$mpi_ln_list mpi/mpi-asm-defs.h:mpi/$dir/mpi-asm-defs.h" + break; + fi +done diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/g10defs.h linux-2.6.16/security/digsig/gnupg/mpi/g10defs.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/g10defs.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/g10defs.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,41 @@ +/* Generated automatically by configure */ +#ifdef HAVE_DRIVE_LETTERS + #define G10_LOCALEDIR "c:\\lib\\gnupg\\locale" + #define GNUPG_LIBDIR "c:\\lib\\gnupg" + #define GNUPG_LIBEXECDIR "c:\\lib\\gnupg" + #define GNUPG_DATADIR "c:\\lib\\gnupg" + #define GNUPG_HOMEDIR "c:\\gnupg" +#else + #define G10_LOCALEDIR "/usr/local/share/locale" + #define GNUPG_LIBDIR "/usr/local/lib/gnupg" + #define GNUPG_DATADIR "/usr/local/share/gnupg" + #ifdef __VMS + #define GNUPG_HOMEDIR "/SYS$LOGIN/gnupg" + #else + #define GNUPG_HOMEDIR "~/.gnupg" + #endif +#endif +/* those are here to be redefined by handcrafted g10defs.h. + Please note that the string version must not contain more + than one character because the using code assumes strlen()==1 */ +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/g10m.c linux-2.6.16/security/digsig/gnupg/mpi/g10m.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/g10m.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/g10m.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,91 @@ +/* g10m.c - Wrapper 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 "mpi.h" + +/* FIXME: The modules should use functions from libgcrypt */ + +const char *g10m_revision_string(int dummy) { return "$Revision: 1.1 $"; } + +MPI +g10m_new( unsigned nbits ) +{ + return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI +g10m_new_secure( unsigned nbits ) +{ + return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +void +g10m_release( MPI a ) +{ + mpi_free(a); +} + +void +g10m_resize( MPI a, unsigned nbits ) +{ + mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI g10m_copy( MPI a ) { return mpi_copy( a ); } +void g10m_swap( MPI a, MPI b) { mpi_swap( a, b ); } +void g10m_set( MPI w, MPI u) { mpi_set( w, u ); } +void g10m_set_ui( MPI w, ulong u ) { mpi_set_ui( w, u ); } + +int g10m_cmp( MPI u, MPI v ) { return mpi_cmp( u, v ); } +int g10m_cmp_ui( MPI u, ulong v ) { return mpi_cmp_ui( u, v ); } + +void g10m_add(MPI w, MPI u, MPI v) { mpi_add( w, u, v ); } +void g10m_add_ui(MPI w, MPI u, ulong v ) { mpi_add_ui( w, u, v ); } +void g10m_sub( MPI w, MPI u, MPI v) { mpi_sub( w, u, v ); } +void g10m_sub_ui(MPI w, MPI u, ulong v ) { mpi_sub_ui( w, u, v ); } + +void g10m_mul( MPI w, MPI u, MPI v) { mpi_mul( w, u, v ); } +void g10m_mulm( MPI w, MPI u, MPI v, MPI m) { mpi_mulm( w, u, v, m ); } +void g10m_mul_2exp( MPI w, MPI u, ulong cnt) { mpi_mul_2exp( w, u, cnt ); } +void g10m_mul_ui(MPI w, MPI u, ulong v ) { mpi_mul_ui( w, u, v ); } + +void g10m_fdiv_q( MPI q, MPI d, MPI r ) { mpi_fdiv_q( q, d, r ); } + +void g10m_powm( MPI r, MPI b, MPI e, MPI m) { mpi_powm( r, b, e, m ); } + +int g10m_gcd( MPI g, MPI a, MPI b ) { return mpi_gcd( g, a, b ); } +int g10m_invm( MPI x, MPI u, MPI v ) { mpi_invm( x, u, v ); return 0; } + +unsigned g10m_get_nbits( MPI a ) { return mpi_get_nbits( a ); } + +unsigned +g10m_get_size( MPI a ) +{ + return mpi_get_nlimbs( a ) * BITS_PER_MPI_LIMB; +} + + +void +g10m_set_buffer( MPI a, const char *buffer, unsigned nbytes, int sign ) +{ + mpi_set_buffer( a, buffer, nbytes, sign ); +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/distfiles linux-2.6.16/security/digsig/gnupg/mpi/generic/distfiles --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/distfiles 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/distfiles 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,10 @@ +mpih-add1.c +mpih-mul1.c +mpih-mul2.c +mpih-mul3.c +mpih-lshift.c +mpih-rshift.c +mpih-sub1.c +udiv-w-sdiv.c +mpi-asm-defs.h + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/Makefile linux-2.6.16/security/digsig/gnupg/mpi/generic/Makefile --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/Makefile 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,15 @@ +all: obj + +CFLAGS= -DHAVE_CONFIG_H + +INCLUDS= -I. -I.. -I../../include + +%.o: %.c + gcc $(INCLUDS) $(CFLAGS) -c $< -o $@ + +OBJ= mpih-add1.o mpih-lshift.o mpih-mul1.o mpih-mul2.o mpih-mul3.o mpih-rshift.o mpih-sub1.o udiv-w-sdiv.o + +obj: $(OBJ) + +clean: + rm *.o *.a diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpi-asm-defs.h linux-2.6.16/security/digsig/gnupg/mpi/generic/mpi-asm-defs.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpi-asm-defs.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpi-asm-defs.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-add1.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-add1.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-add1.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-add1.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,62 @@ +/* mpihelp-add_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, + * 2000 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 "../mpi-internal.h" +#include "../longlong.h" + +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 x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-lshift.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-lshift.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-lshift.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-lshift.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,66 @@ +/* mpihelp-lshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2001 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 "../mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while( --i >= 0 ) { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul1.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-mul1.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul1.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul1.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,58 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 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 "../mpi-internal.h" +#include "../longlong.h" + +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) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul2.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-mul2.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul2.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul2.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,63 @@ +/* mpihelp-mul_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 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 "../mpi-internal.h" +#include "../longlong.h" + + +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 cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } while ( ++j ); + return cy_limb; +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul3.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-mul3.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul3.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-mul3.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,64 @@ +/* mpihelp-mul_3.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 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 "../mpi-internal.h" +#include "../longlong.h" + + +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) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-rshift.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-rshift.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-rshift.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-rshift.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,65 @@ +/* mpih-rshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001 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 "../mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for( i=1; i < usize; i++) { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-sub1.c linux-2.6.16/security/digsig/gnupg/mpi/generic/mpih-sub1.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/mpih-sub1.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/mpih-sub1.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,62 @@ +/* mpihelp-add_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 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 "../mpi-internal.h" +#include "../longlong.h" + +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 x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/udiv-w-sdiv.c linux-2.6.16/security/digsig/gnupg/mpi/generic/udiv-w-sdiv.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/generic/udiv-w-sdiv.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/generic/udiv-w-sdiv.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,130 @@ +/* mpihelp_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed + * division. + * Copyright (C) 1992, 1994, 1996, 1998 Free Software Foundation, Inc. + * Contributed by Peter L. Montgomery. + * + * 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 "../mpi-internal.h" +#include "../longlong.h" + + +#if 0 /* not yet ported to MPI */ + +mpi_limb_t +mpihelp_udiv_w_sdiv( mpi_limp_t *rp, + mpi_limp_t *a1, + mpi_limp_t *a0, + mpi_limp_t *d ) +{ + mp_limb_t q, r; + mp_limb_t c0, c1, b1; + + if ((mpi_limb_signed_t) d >= 0) + { + if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; +} + +#endif + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/longlong.h linux-2.6.16/security/digsig/gnupg/mpi/longlong.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/longlong.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/longlong.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,1503 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with gnupg + +Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998, + 2000, 2001, 2002, 2003 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\n" \ + "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\n" \ + "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\n" \ + "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\n" \ + "sbc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + "mov %|r0, %2, lsr #16 @ AAAA\n" \ + "mov %|r2, %3, lsr #16 @ BBBB\n" \ + "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \ + "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \ + "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \ + "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \ + "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \ + "mul %0, %|r0, %0 @ AAAA * bbbb\n" \ + "adds %|r0, %1, %0 @ central sum\n" \ + "addcs %|r2, %|r2, #65536\n" \ + "adds %1, %|r1, %|r0, lsl #16\n" \ + "adc %0, %|r2, %|r0, lsr #16" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2") +#else +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + "umull %r1, %r0, %r2, %r3" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1") +#endif +#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\n" \ + "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\n" \ + "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\n" \ + " 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\n" \ + " 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 \n" \ + " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \ + " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ + " ldo 16(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \ + " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ + " ldo 8(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \ + " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ + " ldo 4(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \ + " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ + " ldo 2(%0),%0 ; Yes. Perform add. \n" \ + " extru %1,30,1,%1 ; Extract bit 1. \n" \ + " 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 ***************** + ***************************************/ +#undef __i386__ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n" \ + "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\n" \ + "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\n" \ + "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\n" \ + "addc %5,%4,%1\n" \ + "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\n" \ + "subc %5,%4,%1\n" \ + "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\n" \ + "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\n" \ + "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 \n" \ + " move%.l %5,%3 \n" \ + " move%.l %2,%0 \n" \ + " move%.w %3,%1 \n" \ + " swap %3 \n" \ + " swap %0 \n" \ + " mulu %2,%1 \n" \ + " mulu %3,%0 \n" \ + " mulu %2,%3 \n" \ + " swap %2 \n" \ + " mulu %5,%2 \n" \ + " add%.l %3,%2 \n" \ + " jcc 1f \n" \ + " add%.l %#0x10000,%0 \n" \ + "1: move%.l %2,%3 \n" \ + " clr%.w %2 \n" \ + " swap %2 \n" \ + " swap %3 \n" \ + " clr%.w %3 \n" \ + " add%.l %3,%1 \n" \ + " addx%.l %2,%0 \n" \ + " | 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\n" \ + "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\n" \ + "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 \n" \ + "mflo %0 \n" \ + "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 \n" \ + "mflo %0 \n" \ + "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 \n" \ + "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 \n" \ + "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 \n" \ + "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 \n" \ + "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\n" \ + "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 \n" \ + "mts r10,%2 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "cas %0,r2,r0 \n" \ + "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__) || defined(__sh3__) || defined(__SH4__) ) \ + && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n" \ + "sts macl,%1\n" \ + "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\n" \ + "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\n" \ + "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 \n" \ + " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \ + " tst %%g0 \n" \ + " divscc %3,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%0 \n" \ + " rd %%y,%1 \n" \ + " bl,a 1f \n" \ + " add %1,%4,%1 \n" \ + "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 \n" \ + " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \ + " sra %3,31,%%g2 ! Don't move this insn \n" \ + " and %2,%%g2,%%g2 ! Don't move this insn \n" \ + " andcc %%g0,0,%%g1 ! Don't move this insn \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,0,%%g1 \n" \ + " add %%g1,%%g2,%0 \n" \ + " 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\n" \ + "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\n" \ + "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 + +#undef count_leading_zeros +#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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile linux-2.6.16/security/digsig/gnupg/mpi/Makefile --- linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/Makefile 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,20 @@ +all: generic obj lib + +CFLAGS= -g -DHAVE_CONFIG_H + +INCLUDS= -I. + +%.o: %.c + gcc $(INCLUDS) $(CFLAGS) -c $< -o $@ + +OBJ= mpi-add.o mpi-bit.o mpi-cmp.o mpi-div.o mpi-gcd.o mpih-cmp.o mpih-div.o mpih-mul.o mpi-inline.o mpi-inv.o mpi-mpow.o mpi-mul.o mpi-pow.o mpi-scan.o mpiutil.o mpicoder.o + +generic: + make -C generic all + +obj: $(OBJ) + +lib: $(OBJ) + ar cru libMPI.a $(OBJ) generic/*.o +clean: + rm generic/*.o *.o *.a diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.am linux-2.6.16/security/digsig/gnupg/mpi/Makefile.am --- linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.am 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/Makefile.am 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,79 @@ +# Copyright (C) 1998, 1999, 2000, 2001, 2003 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 + +## Process this file with automake to produce Makefile.in + + +INCLUDES = -I.. -I$(top_srcdir)/include +AM_CFLAGS = @MPI_OPT_FLAGS@ +ASFLAGS = @MPI_SFLAGS@ + +EXTRA_DIST = config.links +DISTCLEANFILES = mpi-asm-defs.h \ + mpih-add1.S mpih-mul1.S mpih-mul2.S mpih-mul3.S \ + mpih-lshift.S mpih-rshift.S mpih-sub1.S asm-syntax.h sysdep.h +# Note: we only use .S files so we should delete all left over .s +CLEANFILES = _*.s + +noinst_LIBRARIES = libmpi.a + +# libmpi_a_LDFLAGS = +libmpi_a_SOURCES = longlong.h \ + mpi-add.c \ + mpi-bit.c \ + mpi-cmp.c \ + mpi-div.c \ + mpi-gcd.c \ + mpi-internal.h \ + mpi-inline.h \ + mpi-inline.c \ + mpi-inv.c \ + mpi-mul.c \ + mpi-pow.c \ + mpi-mpow.c \ + mpi-scan.c \ + mpicoder.c \ + mpih-cmp.c \ + mpih-div.c \ + mpih-mul.c \ + mpiutil.c \ + g10m.c + +# Note this objects are actually links, the sourcefiles are +# distributed by special code in dist-hook +common_asm_objects = mpih-mul1.o \ + mpih-mul2.o \ + mpih-mul3.o \ + mpih-add1.o \ + mpih-sub1.o \ + mpih-lshift.o \ + mpih-rshift.o + +libmpi_a_DEPENDENCIES = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ +libmpi_a_LIBADD = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ + +# cancel the default rules used by libtool which do not really +# work and add one to cpp .S files +.S.o: + $(CPP) $(INCLUDES) $(DEFS) $< | grep -v '^#' > _$*.s + $(COMPILE) -c _$*.s + mv -f _$*.o $*.o + +.S.lo: + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.in linux-2.6.16/security/digsig/gnupg/mpi/Makefile.in --- linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.in 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/Makefile.in 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,536 @@ +# Makefile.in generated by automake 1.7.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 1998, 1999, 2000, 2001, 2003 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 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CAPLIBS = @CAPLIBS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CROSS_COMPILING_FALSE = @CROSS_COMPILING_FALSE@ +CROSS_COMPILING_TRUE = @CROSS_COMPILING_TRUE@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOCBOOK_TO_MAN = @DOCBOOK_TO_MAN@ +DOCBOOK_TO_TEXI = @DOCBOOK_TO_TEXI@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGDLIBS = @EGDLIBS@ +EGREP = @EGREP@ +ENABLE_LOCAL_ZLIB_FALSE = @ENABLE_LOCAL_ZLIB_FALSE@ +ENABLE_LOCAL_ZLIB_TRUE = @ENABLE_LOCAL_ZLIB_TRUE@ +EXEEXT = @EXEEXT@ +FAQPROG = @FAQPROG@ +GENCAT = @GENCAT@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GPGKEYS_HKP = @GPGKEYS_HKP@ +GPGKEYS_LDAP = @GPGKEYS_LDAP@ +GPGKEYS_MAILTO = @GPGKEYS_MAILTO@ +HAVE_DOCBOOK_TO_MAN_FALSE = @HAVE_DOCBOOK_TO_MAN_FALSE@ +HAVE_DOCBOOK_TO_MAN_TRUE = @HAVE_DOCBOOK_TO_MAN_TRUE@ +HAVE_DOCBOOK_TO_TEXI_FALSE = @HAVE_DOCBOOK_TO_TEXI_FALSE@ +HAVE_DOCBOOK_TO_TEXI_TRUE = @HAVE_DOCBOOK_TO_TEXI_TRUE@ +HAVE_DOSISH_SYSTEM_FALSE = @HAVE_DOSISH_SYSTEM_FALSE@ +HAVE_DOSISH_SYSTEM_TRUE = @HAVE_DOSISH_SYSTEM_TRUE@ +IDEA_O = @IDEA_O@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LDAPLIBS = @LDAPLIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MPI_EXTRA_ASM_OBJS = @MPI_EXTRA_ASM_OBJS@ +MPI_OPT_FLAGS = @MPI_OPT_FLAGS@ +MPI_SFLAGS = @MPI_SFLAGS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NETLIBS = @NETLIBS@ +NM = @NM@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHA512_O = @SHA512_O@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TIGER_O = @TIGER_O@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WORKING_FAQPROG_FALSE = @WORKING_FAQPROG_FALSE@ +WORKING_FAQPROG_TRUE = @WORKING_FAQPROG_TRUE@ +XGETTEXT = @XGETTEXT@ +ZLIBS = @ZLIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ + +INCLUDES = -I.. -I$(top_srcdir)/include +AM_CFLAGS = @MPI_OPT_FLAGS@ +ASFLAGS = @MPI_SFLAGS@ + +EXTRA_DIST = config.links +DISTCLEANFILES = mpi-asm-defs.h \ + mpih-add1.S mpih-mul1.S mpih-mul2.S mpih-mul3.S \ + mpih-lshift.S mpih-rshift.S mpih-sub1.S asm-syntax.h sysdep.h + +# Note: we only use .S files so we should delete all left over .s +CLEANFILES = _*.s + +noinst_LIBRARIES = libmpi.a + +# libmpi_a_LDFLAGS = +libmpi_a_SOURCES = longlong.h \ + mpi-add.c \ + mpi-bit.c \ + mpi-cmp.c \ + mpi-div.c \ + mpi-gcd.c \ + mpi-internal.h \ + mpi-inline.h \ + mpi-inline.c \ + mpi-inv.c \ + mpi-mul.c \ + mpi-pow.c \ + mpi-mpow.c \ + mpi-scan.c \ + mpicoder.c \ + mpih-cmp.c \ + mpih-div.c \ + mpih-mul.c \ + mpiutil.c \ + g10m.c + + +# Note this objects are actually links, the sourcefiles are +# distributed by special code in dist-hook +common_asm_objects = mpih-mul1.o \ + mpih-mul2.o \ + mpih-mul3.o \ + mpih-add1.o \ + mpih-sub1.o \ + mpih-lshift.o \ + mpih-rshift.o + + +libmpi_a_DEPENDENCIES = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ +libmpi_a_LIBADD = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ +subdir = mpi +mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libmpi_a_AR = $(AR) cru +am_libmpi_a_OBJECTS = mpi-add.$(OBJEXT) mpi-bit.$(OBJEXT) \ + mpi-cmp.$(OBJEXT) mpi-div.$(OBJEXT) mpi-gcd.$(OBJEXT) \ + mpi-inline.$(OBJEXT) mpi-inv.$(OBJEXT) mpi-mul.$(OBJEXT) \ + mpi-pow.$(OBJEXT) mpi-mpow.$(OBJEXT) mpi-scan.$(OBJEXT) \ + mpicoder.$(OBJEXT) mpih-cmp.$(OBJEXT) mpih-div.$(OBJEXT) \ + mpih-mul.$(OBJEXT) mpiutil.$(OBJEXT) g10m.$(OBJEXT) +libmpi_a_OBJECTS = $(am_libmpi_a_OBJECTS) + +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/scripts/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/g10m.Po ./$(DEPDIR)/mpi-add.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpi-bit.Po ./$(DEPDIR)/mpi-cmp.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpi-div.Po ./$(DEPDIR)/mpi-gcd.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpi-inline.Po ./$(DEPDIR)/mpi-inv.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpi-mpow.Po ./$(DEPDIR)/mpi-mul.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpi-pow.Po ./$(DEPDIR)/mpi-scan.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpicoder.Po ./$(DEPDIR)/mpih-cmp.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpih-div.Po ./$(DEPDIR)/mpih-mul.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mpiutil.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libmpi_a_SOURCES) +DIST_COMMON = ChangeLog Makefile.am Makefile.in +SOURCES = $(libmpi_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu mpi/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libmpi.a: $(libmpi_a_OBJECTS) $(libmpi_a_DEPENDENCIES) + -rm -f libmpi.a + $(libmpi_a_AR) libmpi.a $(libmpi_a_OBJECTS) $(libmpi_a_LIBADD) + $(RANLIB) libmpi.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g10m.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-bit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-cmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-div.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-gcd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-inline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-inv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-mpow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-mul.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-pow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-scan.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpicoder.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-cmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-div.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpiutil.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + + +# cancel the default rules used by libtool which do not really +# work and add one to cpp .S files +.S.o: + $(CPP) $(INCLUDES) $(DEFS) $< | grep -v '^#' > _$*.s + $(COMPILE) -c _$*.s + mv -f _$*.o $*.o + +.S.lo: +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.orig linux-2.6.16/security/digsig/gnupg/mpi/Makefile.orig --- linux.orig-2.6.19/security/digsig/gnupg/mpi/Makefile.orig 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/Makefile.orig 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,20 @@ +all: obj lib + +CFLAGS= -g -DHAVE_CONFIG_H + +INCLUDS= -I. -I../include + +# mpi-add.o: mpi-add.c +# gcc $(INCLUDS) $(CFLAGS) -c mpi-add.c + +%.o: %.c + gcc $(INCLUDS) $(CFLAGS) -c $< -o $@ + +OBJ= mpi-add.o mpi-bit.o mpi-cmp.o mpi-div.o mpi-gcd.o mpih-cmp.o mpih-div.o mpih-mul.o mpi-inline.o mpi-inv.o mpi-mpow.o mpi-mul.o mpi-pow.o mpi-scan.o mpiutil.o mpicoder.o + +obj: $(OBJ) + +lib: $(OBJ) + ar cru libMPI.a $(OBJ) generic/*.o +clean: + rm *.o *.a diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/memory.h linux-2.6.16/security/digsig/gnupg/mpi/memory.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/memory.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/memory.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,60 @@ +/* memory.h - memory allocation + * Copyright (C) 1998, 1999, 2000, 2001 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 + + +#define m_alloc(n) kmalloc(n, GFP_KERNEL) +#define m_alloc_clear(n) kmalloc(n, GFP_KERNEL) /* can't memset, no size or don't know how to get it */ +#define m_alloc_secure(n) kmalloc(n, GFP_KERNEL) +#define m_alloc_secure_clear(n) kmalloc(n, GFP_KERNEL) /* can't memset, no size or don't know how to get it */ +#define m_free(n) kfree(n) +#define m_check(n) /* nothing to do here */ +#define m_size(n) sizeof(n) +#define m_is_secure(n) 1 + +/* &&&& realloc kernel hack, should check this */ +#define m_realloc(n,m,o) krealloc((n),(m),(o)) + +static inline void * +krealloc(void *ptr, size_t size, int to_copy) +{ + void *tmp = NULL; + if (size) { + tmp = kmalloc(size,GFP_KERNEL); + if (ptr) memcpy(tmp,ptr,to_copy); + } + kfree(ptr); + return tmp; +} + +#define DBG_MEMORY memory_debug_mode +#define DBG_MEMSTAT memory_stat_debug_mode + +#define EXTERN_UNLESS_MAIN_MODULE extern + +EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode; +EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; + + +#endif /*G10_MEMORY_H*/ diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-add.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-add.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-add.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-add.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,243 @@ +/* mpi-add.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 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 "config.h" +#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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-bit.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-bit.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-bit.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-bit.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,252 @@ +/* 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 "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_opaque (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; + + 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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-cmp.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-cmp.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-cmp.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-cmp.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,71 @@ +/* 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 "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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpicoder.c linux-2.6.16/security/digsig/gnupg/mpi/mpicoder.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpicoder.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpicoder.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,363 @@ +/* mpicoder.c - Coder for the external representation of MPIs + * 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 "mpi.h" +#include "mpi-internal.h" + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define MAX_EXTERN_MPI_BITS 16384 + + +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 }; + + + +MPI +do_encode_md(const byte *sha_buffer, unsigned nbits) +{ + int nframe = (nbits+7) / 8; + byte *frame, *fr_pt; + int i = 0, n; + size_t asnlen = DIM(asn); + MPI a = MPI_NULL; + + if(SHA1_DIGEST_LENGTH + asnlen + 4 > nframe ) + log_bug("can't encode a %d bit MD into a %d bits frame\n", + (int)(SHA1_DIGEST_LENGTH*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 = (byte*)m_alloc(nframe); + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - SHA1_DIGEST_LENGTH - asnlen -3 ; + + if(i <= 1) { + log_bug("message digest encoding failed\n"); + m_free(frame); + return a; + } + + memset( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy( frame+n, &asn, asnlen ); n += asnlen; + memcpy( frame+n, sha_buffer, SHA1_DIGEST_LENGTH ); n += SHA1_DIGEST_LENGTH; + + i = nframe; + fr_pt = frame; + + if (n != nframe) { + log_bug("message digest encoding failed, frame length is wrong\n"); + m_free(frame); + return a; + } + + a = 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 +mpi_read_from_buffer(const 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_bug("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 nread=%d ret_nread=%d\n", nread, *ret_nread); + goto leave; + } + 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; +} + + +/**************** + * 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; + unsigned int n; + + if( sign ) + *sign = a->sign; + *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB; + if (!n) + n++; /* avoid zero length allocation */ + p = buffer = force_secure || mpi_is_secure(a) ? m_alloc_secure(n) + : m_alloc(n); + + 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 operation + * 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 = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*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 |= (mpi_limb_t)*p-- << 8 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-div.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-div.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-div.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-div.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,318 @@ +/* mpi-div.c - MPI functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 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 "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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-gcd.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-gcd.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-gcd.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-gcd.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,51 @@ +/* mpi-gcd.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 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 "mpi-internal.h" + +/**************** + * Find the greatest common divisor G of A and B. + * Return: true if this 1, false in all other cases + */ +int +mpi_gcd( MPI g, MPI xa, MPI xb ) +{ + MPI a, b; + + a = mpi_copy(xa); + b = mpi_copy(xb); + + /* TAOCP Vol II, 4.5.2, Algorithm A */ + a->sign = 0; + b->sign = 0; + while( mpi_cmp_ui( b, 0 ) ) { + mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ + mpi_set(a,b); + mpi_set(b,g); + } + mpi_set(g, a); + + mpi_free(a); + mpi_free(b); + return !mpi_cmp_ui( g, 1); +} + + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi.h linux-2.6.16/security/digsig/gnupg/mpi/mpi.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,185 @@ +/* mpi.h - Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001 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 "config.h" +#include "types.h" +#include "memory.h" + +/* DIGSIG defines */ + +#define SHA1_DIGEST_LENGTH 20 + +/*end of DIGSIG defines */ + +#define log_debug printk +#define log_bug printk + +#define assert(x) do { \ + if (!x) log_bug("failed assertion\n"); \ + } while(0); + +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else + #error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) + +#ifndef EXTERN_UNLESS_MAIN_MODULE + #if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE) + #define EXTERN_UNLESS_MAIN_MODULE extern + #else + #define EXTERN_UNLESS_MAIN_MODULE + #endif +#endif + +#define DBG_MPI mpi_debug_mode +EXTERN_UNLESS_MAIN_MODULE int mpi_debug_mode; + + +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: not used */ + /* 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_is_neg(a) ((a)->sign) + +/*-- mpiutil.c --*/ + +MPI mpi_alloc( unsigned nlimbs ); +MPI mpi_alloc_secure( unsigned nlimbs ); +MPI mpi_alloc_like( MPI a ); +void mpi_free( MPI a ); +void mpi_resize( MPI a, unsigned nlimbs ); +MPI mpi_copy( MPI a ); +#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_secure(a) ((a) && ((a)->flags&1)) +void mpi_set_secure( MPI a ); +void mpi_clear( 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 --*/ +MPI do_encode_md(const byte *sha_buffer, unsigned nbits); +MPI mpi_read_from_buffer(const byte *buffer, unsigned *ret_nread, int secure); +int mpi_fromstr(MPI val, const char *str); +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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-cmp.c linux-2.6.16/security/digsig/gnupg/mpi/mpih-cmp.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-cmp.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpih-cmp.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,58 @@ +/* mpihelp-sub.c - MPI helper functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 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 "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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-div.c linux-2.6.16/security/digsig/gnupg/mpi/mpih-div.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-div.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpih-div.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,534 @@ +/* mpihelp-div.c - MPI helper functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * 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 + * + * 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 "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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-mul.c linux-2.6.16/security/digsig/gnupg/mpi/mpih-mul.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpih-mul.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpih-mul.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,525 @@ +/* mpihelp-mul.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000 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 "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 ); + } + } +} + + + +void +mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ) +{ + mpi_limb_t cy; + + if( !ctx->tspace || ctx->tspace_size < vsize ) { + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + ctx->tspace = mpi_alloc_limb_space( 2 * vsize, + m_is_secure( up ) || m_is_secure( vp ) ); + ctx->tspace_size = vsize; + } + + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + if( !ctx->tp || ctx->tp_size < vsize ) { + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + ctx->tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up ) + || m_is_secure( vp ) ); + ctx->tp_size = vsize; + } + + do { + MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); + cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize ); + mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + } + + if( usize ) { + if( usize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( ctx->tspace, vp, vsize, up, usize ); + } + else { + if( !ctx->next ) { + ctx->next = m_alloc_clear( sizeof *ctx ); + } + mpihelp_mul_karatsuba_case( ctx->tspace, + vp, vsize, + up, usize, + ctx->next ); + } + + cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize); + mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); + } +} + + +void +mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) +{ + struct karatsuba_ctx *ctx2; + + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + for( ctx=ctx->next; ctx; ctx = ctx2 ) { + ctx2 = ctx->next; + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + m_free( ctx ); + } +} + +/* 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; + struct karatsuba_ctx ctx; + + 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; + } + + memset( &ctx, 0, sizeof ctx ); + mpihelp_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); + mpihelp_release_karatsuba_ctx( &ctx ); + return *prod_endp; +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inline.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-inline.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inline.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-inline.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,33 @@ +/* mpi-inline.c + * Copyright (C) 1999, 2000, 2001 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 + */ + + +/* put the inline functions as real functions into the lib */ +#define G10_MPI_INLINE_DECL + +#include "mpi-internal.h" + +/* always include the header becuase it is only + * included by mpi-internal if __GCC__ is defined but we + * need it here in all cases and the above definition of + * of the macro allows us to do so + */ +#include "mpi-inline.h" + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inline.h linux-2.6.16/security/digsig/gnupg/mpi/mpi-inline.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inline.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-inline.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,128 @@ +/* mpi-inline.h - Internal to the Multi Precision Integers + * 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. + */ + +#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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-internal.h linux-2.6.16/security/digsig/gnupg/mpi/mpi-internal.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-internal.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-internal.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,259 @@ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000 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 --*/ + +struct karatsuba_ctx { + struct karatsuba_ctx *next; + mpi_ptr_t tspace; + mpi_size_t tspace_size; + mpi_ptr_t tp; + mpi_size_t tp_size; +}; + +void mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); + +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); + +void mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ); + + +/*-- 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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inv.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-inv.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-inv.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-inv.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,267 @@ +/* mpi-inv.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 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 "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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-mpow.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-mpow.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-mpow.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-mpow.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,98 @@ +/* mpi-mpow.c - MPI functions + * Copyright (C) 1998, 1999, 2000 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 "mpi-internal.h" +#include "longlong.h" + + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int index = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + return index; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + + for(k=0; basearray[k]; k++ ) + ; + assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + assert(i==k); + assert(t); + assert( k < 10 ); + + G = m_alloc_clear( (1<= 0 && idx < (1<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 ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { + /* w is not allocated in secure space but u or v is. To make sure + * that no temporray results are stored in w, we temporary use + * a newly allocated limb space for w */ + wp = mpi_alloc_limb_space( wsize, 1 ); + assign_wp = 2; /* mark it as 2 so that we can later copy it back to + * mormal memory */ + } + else 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 ) { + if (assign_wp == 2) { + /* copy the temp wp from secure memory back to normal memory */ + mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); + MPN_COPY (tmp_wp, wp, wsize); + mpi_free_limb_space (wp); + wp = tmp_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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-pow.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-pow.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-pow.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-pow.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,290 @@ +/* mpi-pow.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2000 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 "mpi-internal.h" +#include "longlong.h" + + +/**************** + * 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; + struct karatsuba_ctx karactx; + + memset( &karactx, 0, sizeof karactx ); + 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 );*/ + if( bsize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( xp, rp, rsize, bp, bsize ); + } + else { + mpihelp_mul_karatsuba_case( + xp, rp, rsize, bp, bsize, &karactx ); + } + + 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); + + mpihelp_release_karatsuba_ctx( &karactx ); + } + + 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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-scan.c linux-2.6.16/security/digsig/gnupg/mpi/mpi-scan.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpi-scan.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpi-scan.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,129 @@ +/* mpi-scan.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 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 "mpi-internal.h" +#include "longlong.h" + +/**************** + * Scan through an mpi and return byte for byte. a -1 is returned to indicate + * the end of the mpi. Scanning is done from the lsb to the msb, returned + * values are in the range of 0 .. 255. + * + * FIXME: This code is VERY ugly! + */ +int +mpi_getbyte( MPI a, unsigned idx ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb; + + ap = a->d; + for(n=0,i=0; i < a->nlimbs; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) + return (limb >> j*8) & 0xff; + } + return -1; +} + + +/**************** + * Put a value at position IDX into A. idx counts from lsb to msb + */ +void +mpi_putbyte( MPI a, unsigned idx, int xc ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb, c; + + c = xc & 0xff; + ap = a->d; + for(n=0,i=0; i < a->alloced; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) { + #if BYTES_PER_MPI_LIMB == 4 + if( j == 0 ) + limb = (limb & 0xffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xff00ffff) | (c<<16); + else + limb = (limb & 0x00ffffff) | (c<<24); + #elif BYTES_PER_MPI_LIMB == 8 + if( j == 0 ) + limb = (limb & 0xffffffffffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffffffffffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xffffffffff00ffff) | (c<<16); + else if( j == 3 ) + limb = (limb & 0xffffffff00ffffff) | (c<<24); + else if( j == 4 ) + limb = (limb & 0xffffff00ffffffff) | (c<<32); + else if( j == 5 ) + limb = (limb & 0xffff00ffffffffff) | (c<<40); + else if( j == 6 ) + limb = (limb & 0xff00ffffffffffff) | (c<<48); + else + limb = (limb & 0x00ffffffffffffff) | (c<<56); + #else + #error please enhance this function, its ugly - i know. + #endif + if( a->nlimbs <= i ) + a->nlimbs = i+1; + ap[i] = limb; + return; + } + } + log_bug("index out of range\n"); +} + + +/**************** + * Count the number of zerobits at the low end of A + */ +unsigned +mpi_trailing_zeros( MPI a ) +{ + unsigned n, count = 0; + + for(n=0; n < a->nlimbs; n++ ) { + if( a->d[n] ) { + unsigned nn; + mpi_limb_t alimb = a->d[n]; + + count_trailing_zeros( nn, alimb ); + count += nn; + break; + } + count += BITS_PER_MPI_LIMB; + } + return count; + +} + + diff -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/mpiutil.c linux-2.6.16/security/digsig/gnupg/mpi/mpiutil.c --- linux.orig-2.6.19/security/digsig/gnupg/mpi/mpiutil.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/mpiutil.c 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,468 @@ +/* mpiutil.ac - Utility functions for MPI + * 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 "mpi.h" +#include "mpi-internal.h" +#include "memory.h" + + +int DBG_MEMORY = 0; + +#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), a->alloced ); + 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 +#ifdef M_DEBUG +mpi_debug_alloc_like( MPI a, const char *info ) +#else +mpi_alloc_like( MPI a ) +#endif +{ + 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 = 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 -rNu linux.orig-2.6.19/security/digsig/gnupg/mpi/types.h linux-2.6.16/security/digsig/gnupg/mpi/types.h --- linux.orig-2.6.19/security/digsig/gnupg/mpi/types.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/gnupg/mpi/types.h 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,88 @@ +/* types.h - some common typedefs + * Copyright (C) 1998, 1999, 2000, 2001 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 + + +#ifndef HAVE_BYTE_TYPEDEF + #undef byte /* maybe there is a macro with this name */ + #ifndef __riscos__ + typedef unsigned char byte; + #else + /* Norcroft treats char = unsigned char as legal assignment + but char* = unsigned char* as illegal assignment + and the same applies to the signed variants as well */ + typedef char byte; + #endif + #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 + +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 -rNu linux.orig-2.6.19/security/digsig/Kconfig linux-2.6.16/security/digsig/Kconfig --- linux.orig-2.6.19/security/digsig/Kconfig 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/Kconfig 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,77 @@ +config SECURITY_DIGSIG + tristate "DigSig support (SEE HELP FOR WARNINGS !)" + depends on SECURITY + depends on !SECURITY_SELINUX + depends on !SECURITY_CAPABILITIES + select CRYPTO_SHA1 + default n + help + This kernel module checks signature of a binary before running it. + The main functionality is to insert digital signatures inside the ELF + binary and verify this signature before loading the binary. It is + based on the LSM hooks. + + Please notice that you need to use a user land program + (extract_pkey) to load the keys into kernel space user. + bsign user land tool is used for signing binaries + (http://packages.debian.org/unstable/admin/bsign.html). + + More infos at http://disec.sourceforge.net/ + + If you are unsure how to answer this question, answer N. + +config SECURITY_DIGSIG_CACHE_SIZE + int "DigSig cache boot parameter" + depends on SECURITY_DIGSIG + range 512 4096 + default 512 + help + From release 1.2, the caching of signatures at kernel level is supported. + Once the signature of a binary is verified, its signature is cached in the + kernel memory. Therefore, there is no need for signature verification in + subsequent calls to this binary. + When a binary file is modified, the corresponding cache entry in the memory + is invalidated. + + If you are unsure how to answer this question, let the default. + +config SECURITY_DIGSIG_DEBUG + bool "Permissive mode debug" + depends on SECURITY_DIGSIG + default y + help + If this is your first try, the debug mode let you check which + executables are used, and let them executed even if there is no + signature. + + If you are unsure how to answer this question, let the default. + +config SECURITY_DIGSIG_LOG + bool "Verbose Logging" + depends on SECURITY_DIGSIG + default n + help + This let you know a lot's of output for each tested executeable. + + It's very very verbose, you are warned + + If you are unsure how to answer this question, let the default. + +config SECURITY_DIGSIG_REVOCATION + bool "Key Revocation" + depends on SECURITY_DIGSIG + default y + help + As of release 1.3, revocation of signatures is supported. If a library + or binary is found to have a vulnerability, you no longer want digsig to + allow that file to be loaded. By revoking the signature, you tell + digsig that although the file's signature was in fact calculated with + the valid private key, it should nevertheless refuse to load this + binary. + + This permit to load a list of revoked key to avoid the execution + of their binaries. + + If you are unsure how to answer this question, let the default. + + diff -rNu linux.orig-2.6.19/security/digsig/Makefile linux-2.6.16/security/digsig/Makefile --- linux.orig-2.6.19/security/digsig/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/Makefile 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,48 @@ + + +ifndef CONFIG_SECURITY_DIGSIG + obj-m := digsig_verif.o +else + obj-$(CONFIG_SECURITY_DIGSIG) := digsig_verif.o +endif + +digsig_verif-objs := digsig.o digsig_sysfs.o digsig_cache.o digsig_revocation.o digsig_sig_verify.o + + +digsig_verif-objs += ./gnupg/mpi/generic/mpih-lshift.o \ + ./gnupg/mpi/generic/mpih-mul1.o ./gnupg/mpi/generic/mpih-mul2.o \ + ./gnupg/mpi/generic/mpih-mul3.o ./gnupg/mpi/generic/mpih-rshift.o \ + ./gnupg/mpi/generic/mpih-sub1.o ./gnupg/mpi/generic/udiv-w-sdiv.o \ + ./gnupg/mpi/generic/mpih-add1.o ./gnupg/mpi/mpicoder.o ./gnupg/mpi/mpi-add.o \ + ./gnupg/mpi/mpi-bit.o ./gnupg/mpi/mpi-div.o ./gnupg/mpi/mpi-cmp.o ./gnupg/mpi/mpi-gcd.o \ + ./gnupg/mpi/mpih-cmp.o ./gnupg/mpi/mpih-div.o ./gnupg/mpi/mpih-mul.o ./gnupg/mpi/mpi-inline.o \ + ./gnupg/mpi/mpi-inv.o ./gnupg/mpi/mpi-mpow.o ./gnupg/mpi/mpi-mul.o ./gnupg/mpi/mpi-pow.o \ + ./gnupg/mpi/mpi-scan.o ./gnupg/mpi/mpiutil.o ./gnupg/cipher/rsa-verify.o +# EXTRA_CFLAGS += -DDIGSIG_DEBUG -DDIGSIG_LOG -DDIGSIG_REVOCATION + +ifndef CONFIG_SECURITY_DIGSIG + EXTRA_CFLAGS += -DDIGSIG_DEBUG -DDIGSIG_LOG -DDIGSIG_REVOCATION +else + ifdef CONFIG_SECURITY_DIGSIG_DEBUG + EXTRA_CFLAGS += -DDIGSIG_DEBUG + endif + ifdef CONFIG_SECURITY_DIGSIG_LOG + EXTRA_CFLAGS += -DDIGSIG_LOG + endif + ifdef CONFIG_SECURITY_DIGSIG_REVOCATION + EXTRA_CFLAGS += -DDIGSIG_REVOCATION + endif + EXTRA_CFLAGS += -Wall -Werror +endif + + + +clean: + @find . \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' -o -name '*~'\ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ + -type f -print | xargs rm -f + +tags: + rm -f TAGS + @find . -name \*.[ch] | xargs etags -a diff -rNu linux.orig-2.6.19/security/digsig/.tmp_versions/digsig_verif.mod linux-2.6.16/security/digsig/.tmp_versions/digsig_verif.mod --- linux.orig-2.6.19/security/digsig/.tmp_versions/digsig_verif.mod 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.19/security/digsig/.tmp_versions/digsig_verif.mod 2006-04-28 11:03:51.000000000 -0400 @@ -0,0 +1,2 @@ +security/digsig/digsig_verif.ko +security/digsig/digsig.o security/digsig/digsig_sysfs.o security/digsig/digsig_cache.o security/digsig/digsig_revocation.o security/digsig/digsig_sig_verify.o security/digsig/./gnupg/mpi/generic/mpih-lshift.o security/digsig/./gnupg/mpi/generic/mpih-mul1.o security/digsig/./gnupg/mpi/generic/mpih-mul2.o security/digsig/./gnupg/mpi/generic/mpih-mul3.o security/digsig/./gnupg/mpi/generic/mpih-rshift.o security/digsig/./gnupg/mpi/generic/mpih-sub1.o security/digsig/./gnupg/mpi/generic/udiv-w-sdiv.o security/digsig/./gnupg/mpi/generic/mpih-add1.o security/digsig/./gnupg/mpi/mpicoder.o security/digsig/./gnupg/mpi/mpi-add.o security/digsig/./gnupg/mpi/mpi-bit.o security/digsig/./gnupg/mpi/mpi-div.o security/digsig/./gnupg/mpi/mpi-cmp.o security/digsig/./gnupg/mpi/mpi-gcd.o security/digsig/./gnupg/mpi/mpih-cmp.o security/digsig/./gnupg/mpi/mpih-div.o security/digsig/./gnupg/mpi/mpih-mul.o security/digsig/./gnupg/mpi/mpi-inline.o security/digsig/./gnupg/mpi/mpi-inv.o security/digsig/./gnupg/mpi/mpi-mpow.o security/digsig/./gnupg/mpi/mpi-mul.o security/digsig/./gnupg/mpi/mpi-pow.o security/digsig/./gnupg/mpi/mpi-scan.o security/digsig/./gnupg/mpi/mpiutil.o security/digsig/./gnupg/cipher/rsa-verify.o diff -rNu linux.orig-2.6.19/security/Kconfig linux-2.6.16/security/Kconfig --- linux.orig-2.6.19/security/Kconfig 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.19/security/Kconfig 2006-04-28 11:03:32.000000000 -0400 @@ -101,5 +101,7 @@ source security/selinux/Kconfig +source security/digsig/Kconfig + endmenu diff -rNu linux.orig-2.6.19/security/Makefile linux-2.6.16/security/Makefile --- linux.orig-2.6.19/security/Makefile 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.19/security/Makefile 2006-04-28 11:03:37.000000000 -0400 @@ -14,6 +14,7 @@ obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o # Must precede capability.o in order to stack properly. obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o +obj-$(CONFIG_SECURITY_DIGSIG) += digsig/ obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o obj-$(CONFIG_SECURITY_SECLVL) += seclvl.o