Module Name: src Committed By: agc Date: Sat Oct 20 04:42:42 UTC 2012
Modified Files: src/crypto/external/bsd/netpgp/lib/cipher [agc-netpgp-standalone]: Makefile Added Files: src/crypto/external/bsd/netpgp/dist/src/libcipher [agc-netpgp-standalone]: idea.c idea.h Log Message: Now that idea is out of jail, add it as a cipher - requested by christos. For all intents and purposes, AES will be used these days, but idea may be used in legacy things, so mainly for completeness. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1.2.1 \ src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.c \ src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.h cvs rdiff -u -r1.1.2.1 -r1.1.2.2 \ src/crypto/external/bsd/netpgp/lib/cipher/Makefile Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/crypto/external/bsd/netpgp/lib/cipher/Makefile diff -u src/crypto/external/bsd/netpgp/lib/cipher/Makefile:1.1.2.1 src/crypto/external/bsd/netpgp/lib/cipher/Makefile:1.1.2.2 --- src/crypto/external/bsd/netpgp/lib/cipher/Makefile:1.1.2.1 Sun May 6 18:07:01 2012 +++ src/crypto/external/bsd/netpgp/lib/cipher/Makefile Sat Oct 20 04:42:42 2012 @@ -1,6 +1,7 @@ LIB=netpgpcipher SRCS= rijndael-alg-fst.c rijndael-api-fst.c rijndael.c SRCS+= cast.c +SRCS+= idea.c SRCS+= modes.c SRCS+= camellia.c MAN=libnetpgpcipher.3 @@ -9,7 +10,7 @@ WARNS=4 EXTDIST= ${.CURDIR}/../../dist .PATH: ${EXTDIST}/src/libcipher -INCS=aes.h rijndael.h cast.h camellia.h +INCS=aes.h rijndael.h cast.h camellia.h idea.h INCSDIR=/usr/include/netpgp .include <bsd.lib.mk> Added files: Index: src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.c diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.c:1.1.2.1 --- /dev/null Sat Oct 20 04:42:42 2012 +++ src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.c Sat Oct 20 04:42:42 2012 @@ -0,0 +1,529 @@ +/* Paulo Barreto <pbarr...@unisys.com.br> 1996.01.17 */ +/* + * idea.c - C source code for IDEA block cipher. + * IDEA (International Data Encryption Algorithm), formerly known as + * IPES (Improved Proposed Encryption Standard). + * Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich. + * This implementation modified and derived from original C code + * developed by Xuejia Lai. + * Zero-based indexing added, names changed from IPES to IDEA. + * CFB functions added. Random number routines added. + * + * Extensively optimized and restructured by Colin Plumb. + * + * The IDEA(tm) block cipher is covered by patents held by ETH and a + * Swiss company called Ascom-Tech AG. The Swiss patent number is + * PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and + * the U.S. patent number is US005214703. IDEA(tm) is a trademark of + * Ascom-Tech AG. There is no license fee required for noncommercial + * use. Commercial users may obtain licensing details from Dieter + * Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn, + * Switzerland, Tel +41 65 242885, Fax +41 65 235761. + * + * The IDEA block cipher uses a 64-bit block size, and a 128-bit key + * size. It breaks the 64-bit cipher block into four 16-bit words + * because all of the primitive inner operations are done with 16-bit + * arithmetic. It likewise breaks the 128-bit cipher key into eight + * 16-bit words. + * + * For further information on the IDEA cipher, see the book: + * Xuejia Lai, "On the Design and Security of Block Ciphers", + * ETH Series on Information Processing (ed. J.L. Massey) Vol 1, + * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. ISBN + * 3-89191-573-X. + * + * This code runs on arrays of bytes by taking pairs in big-endian + * order to make the 16-bit words that IDEA uses internally. This + * produces the same result regardless of the byte order of the + * native CPU. + */ +#include <inttypes.h> +#include <string.h> + +#include "idea.h" + +#define OPTIMIZE + +#define LOW16(x) ((x) & 0xFFFF) + +/* + * Compute the multiplicative inverse of x, modulo 65537, using Euclid's + * algorithm. It is unrolled twice to avoid swapping the registers each + * iteration, and some subtracts of t have been changed to adds. + */ +static __inline uint16_t +mulInv(uint16_t x) +{ + uint16_t t0, t1; + uint16_t q, y; + + if (x <= 1) + return x; /* 0 and 1 are self-inverse */ + t1 = 0x10001 / x; /* Since x >= 2, this fits into 16 bits */ + y = 0x10001 % x; + if (y == 1) + return ( uint16_t ) LOW16(1-t1); + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if (x == 1) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while (y != 1); + return ( uint16_t ) LOW16(1-t1); +} + +/* + * Expand a 128-bit user key to a working encryption key EK + */ +static void +ideaExpandKey(const uint8_t *userkey, uint16_t *EK) +{ + unsigned i,j; + + for (j=0; j<8; j++) { + EK[j] = (userkey[0]<<8) + userkey[1]; + userkey += 2; + } + for (i=0; j < IDEA_KEYLEN; j++) { + i++; + EK[i+7] = (EK[i & 7] << 9) | (EK[(i + 1) & 7] >> 7); + EK += i & 8; + i &= 7; + } +} + +#define NEG(x) (- (int) (x)) + +/* + * Compute IDEA decryption key DK from an expanded IDEA encryption key EK + * Note that the input and output may be the same. Thus, the key is + * inverted into an internal buffer, and then copied to the output. + */ +static void +ideaInvertKey(const uint16_t *EK, uint16_t DK[IDEA_KEYLEN]) +{ + uint16_t temp[IDEA_KEYLEN]; +#ifdef OPTIMIZE + register int k, p, r; + + p = IDEA_KEYLEN; + temp [p-1] = mulInv (EK [3]); + temp [p-2] = NEG (EK [2]); + temp [p-3] = NEG (EK [1]); + temp [p-4] = mulInv (EK [0]); + + k = 4; p -= 4; + for (r = IDEA_ROUNDS - 1; r > 0; r--) { + temp [p-1] = EK [k+1]; + temp [p-2] = EK [k]; + temp [p-3] = mulInv (EK [k+5]); + temp [p-4] = NEG (EK [k+3]); + temp [p-5] = NEG (EK [k+4]); + temp [p-6] = mulInv (EK [k+2]); + k += 6; p -= 6; + } + temp [p-1] = EK [k+1]; + temp [p-2] = EK [k]; + temp [p-3] = mulInv (EK [k+5]); + temp [p-4] = NEG (EK [k+4]); + temp [p-5] = NEG (EK [k+3]); + temp [p-6] = mulInv (EK [k+2]); +#else /* !OPTIMIZE */ + int i; + uint16_t t1, t2, t3; + uint16_t *p = temp + IDEA_KEYLEN; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t3; + *--p = t2; + *--p = t1; + + for (i = 0; i < IDEA_ROUNDS-1; i++) { + t1 = *EK++; + *--p = *EK++; + *--p = t1; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *EK++; + *--p = *EK++; + *--p = t1; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t3; + *--p = t2; + *--p = t1; +#endif /* ?OPTIMIZE */ +/* Copy and destroy temp copy */ + memcpy(DK, temp, sizeof(temp)); + memset(temp, 0x0, sizeof(temp)); +} + +/* + * MUL(x,y) computes x = x*y, modulo 0x10001. Requires two temps, + * t16 and t32. x is modified, and must me a side-effect-free lvalue. + * y may be anything, but unlike x, must be strictly 16 bits even if + * LOW16() is #defined. + * All of these are equivalent - see which is faster on your machine + */ +#define MUL(x,y) \ + ((t16 = (y)) ? \ + (x=LOW16(x)) ? \ + t32 = (uint32_t)x*t16, \ + x = LOW16(t32), \ + t16 = t32>>16, \ + x = (x-t16)+(x<t16) \ + : \ + (x = 1-t16) \ + : \ + (x = 1-x)) + +/* IDEA encryption/decryption algorithm */ +/* Note that in and out can be the same buffer */ +static void +ideaCipher(const uint8_t inbuf[8], uint8_t outbuf[8], const uint16_t *key) +{ + register uint16_t x1, x2, x3, x4, s2, s3; + const uint16_t *in; + uint16_t *out; + register uint16_t t16; /* Temporaries needed by MUL macro */ + register uint32_t t32; +#ifndef OPTIMIZE + int r = IDEA_ROUNDS; +#endif /* ?OPTIMIZE */ + int indian = 1; + + in = (const uint16_t *)(const void *)inbuf; +#ifdef OPTIMIZE + x1 = in[0]; x2 = in[1]; + x3 = in[2]; x4 = in[3]; +#else /* !OPTIMIZE */ + x1 = *in++; x2 = *in++; + x3 = *in++; x4 = *in; +#endif /* ?OPTIMIZE */ + if (*(char *)(void *)&indian) { + /* little endian */ + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); + } + +#ifdef OPTIMIZE + /* round 1: */ + MUL(x1,key[0]); + x2 += key[1]; + x3 += key[2]; + MUL(x4, key[3]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[4]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[5]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 2: */ + MUL(x1,key[6]); + x2 += key[7]; + x3 += key[8]; + MUL(x4, key[9]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[10]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[11]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 3: */ + MUL(x1,key[12]); + x2 += key[13]; + x3 += key[14]; + MUL(x4, key[15]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[16]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[17]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 4: */ + MUL(x1,key[18]); + x2 += key[19]; + x3 += key[20]; + MUL(x4, key[21]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[22]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[23]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 5: */ + MUL(x1,key[24]); + x2 += key[25]; + x3 += key[26]; + MUL(x4, key[27]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[28]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[29]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 6: */ + MUL(x1,key[30]); + x2 += key[31]; + x3 += key[32]; + MUL(x4, key[33]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[34]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[35]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 7: */ + MUL(x1,key[36]); + x2 += key[37]; + x3 += key[38]; + MUL(x4, key[39]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[40]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[41]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* round 8: */ + MUL(x1,key[42]); + x2 += key[43]; + x3 += key[44]; + MUL(x4, key[45]); + + s3 = x3; + x3 ^= x1; + MUL(x3, key[46]); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, key[47]); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + x2 ^= s3; x3 ^= s2; + + /* final semiround: */ + MUL(x1, key[48]); + x3 += key[49]; + x2 += key[50]; + MUL(x4, key[51]); + +#else /* !OPTIMIZE */ + do { + MUL(x1,*key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + + x2 ^= s3; x3 ^= s2; + } while (--r); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); +#endif /* ?OPTIMIZE */ + + out = (uint16_t *)outbuf; + if (*(char *)(void *)&indian) { + /* little endian */ +#ifdef OPTIMIZE + out[0] = (x1>>8) | (x1<<8); + out[1] = (x3>>8) | (x3<<8); + out[2] = (x2>>8) | (x2<<8); + out[3] = (x4>>8) | (x4<<8); +#else /* !OPTIMIZE */ + x1 = LOW16(x1); + x2 = LOW16(x2); + x3 = LOW16(x3); + x4 = LOW16(x4); + *out++ = (x1>>8) | (x1<<8); + *out++ = (x3>>8) | (x3<<8); + *out++ = (x2>>8) | (x2<<8); + *out = (x4>>8) | (x4<<8); +#endif /* ?OPTIMIZE */ + } else { + /* big endian */ + *out++ = x1; + *out++ = x3; + *out++ = x2; + *out = x4; + } +} + +int +idea_set_key(idea_context_t *ctx, uint8_t *key, unsigned keylen) +{ + ctx->have_decrypt_key = 0; + ideaExpandKey(key, ctx->enckey); + ideaInvertKey(ctx->enckey, ctx->deckey); + return 0; +} + +void +idea_encrypt_block(idea_context_t *ctx, uint8_t *out, uint8_t *in) +{ + ideaCipher(out, in, ctx->enckey); +} + +void +idea_decrypt_block(idea_context_t *ctx, uint8_t *out, uint8_t *in) +{ + if (!ctx->have_decrypt_key) { + ctx->have_decrypt_key = 1; + ideaInvertKey(ctx->enckey, ctx->deckey); + } + ideaCipher(out, in, ctx->deckey); +} + +/*-------------------------------------------------------------*/ + +#ifdef TEST + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +/* + * This is the number of Kbytes of test data to encrypt. + * It defaults to 1 MByte. + */ +#ifndef BLOCKS + #ifndef KBYTES + #define KBYTES 1024L + #endif + #define BLOCKS (64*KBYTES) +#endif + +int +main(void) +{ /* Test driver for IDEA cipher */ + idea_context_t ctx; + int i, k; + uint8_t userkey[16]; + uint8_t XX[8], YY[8], ZZ[8]; + clock_t start, end; + long l; + float secs; + + memset(&ctx, 0x0, sizeof(ctx)); + /* Make a sample user key for testing... */ + for(i=0; i<16; i++) + userkey[i] = i+1; + + idea_set_key(&ctx, userkey, sizeof(userkey)); + + /* Make a sample plaintext pattern for testing... */ + for (k=0; k<8; k++) + XX[k] = k; + + printf("\nEncrypting %ld bytes (%ld blocks)...", BLOCKS*16, BLOCKS); + fflush(stdout); + start = clock(); + memcpy(YY, XX, sizeof(YY)); + for (l = 0; l < BLOCKS; l++) + idea_encrypt_block(&ctx, YY, YY); /* repeated encryption */ + memcpy(ZZ, YY, sizeof(ZZ)); + for (l = 0; l < BLOCKS; l++) + idea_decrypt_block(&ctx, ZZ, ZZ); /* repeated decryption */ + end = clock() - start; + secs = (float) end / CLOCKS_PER_SEC; + printf("%.2f sec = %.0f bytes/sec.\n", + secs, (float) BLOCKS*16 / secs); + + printf("\nX %3u %3u %3u %3u %3u %3u %3u %3u\n", + XX[0], XX[1], XX[2], XX[3], XX[4], XX[5], XX[6], XX[7]); + printf("\nY %3u %3u %3u %3u %3u %3u %3u %3u\n", + YY[0], YY[1], YY[2], YY[3], YY[4], YY[5], YY[6], YY[7]); + printf("\nZ %3u %3u %3u %3u %3u %3u %3u %3u\n", + ZZ[0], ZZ[1], ZZ[2], ZZ[3], ZZ[4], ZZ[5], ZZ[6], ZZ[7]); + + /* Now decrypted ZZ should be same as original XX */ + for (k=0; k<8; k++) + if (XX[k] != ZZ[k]) { + printf("\n\07Error! Noninvertable encryption.\n"); + exit(1); /* error exit */ + } + printf("\nNormal exit.\n"); + return 0; /* normal exit */ +} + +#endif /* TEST */ \ No newline at end of file Index: src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.h diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.h:1.1.2.1 --- /dev/null Sat Oct 20 04:42:42 2012 +++ src/crypto/external/bsd/netpgp/dist/src/libcipher/idea.h Sat Oct 20 04:42:42 2012 @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2012 Alistair Crooks <a...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IDEA_H_ +#define IDEA_H_ + +#include <inttypes.h> + +#define IDEA_KEYSIZE 16 +#define IDEA_BLOCKSIZE 8 +#define IDEA_ROUNDS 8 +#define IDEA_KEYLEN ((6 * IDEA_ROUNDS) + 4) + +typedef struct idea_context_t { + uint16_t enckey[IDEA_KEYLEN]; + uint16_t deckey[IDEA_KEYLEN]; + uint8_t have_decrypt_key; +} idea_context_t; + +#ifndef __BEGIN_DECLS +# if defined(__cplusplus) +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +# else +# define __BEGIN_DECLS +# define __END_DECLS +# endif +#endif + +__BEGIN_DECLS + +int idea_set_key(idea_context_t */*ctx*/, uint8_t *key, unsigned /*size*/); +void idea_encrypt_block(idea_context_t */*ctx*/, uint8_t */*out*/, uint8_t */*in*/); +void idea_decrypt_block(idea_context_t */*ctx*/, uint8_t */*out*/, uint8_t */*in*/); + +__END_DECLS + +#endif