Tue, 29 Mar 2011 20:04:34 +0200
Rework package yet again, correcting and introducing new buildconf logic:
Conditionally disable bootstrap stage comparison correctly, correct
english grammar, better find system as(1) and ld(1), indotruce detailed
optimization option messages, more completely guess cpu types, allow
profiled bootstrapping without a preinstalled GCC because many other
compilers have long since implemented 64-bit arithmetic, instruct make
to build sequentially (not in sparallel) when building a profiled
bootstrap as GCC online documents recommend, and generally improve
comment blocks.
The single most important correction in this changeset relates to the
GCC changed optimization policy since at least GCC 4.5, in which -march
is always passed and not always correctly guessed. In the case of this
package, allowing GCC to guess the architecture leads to wild build
errors at various subcomponents (zlib, libgcc, libiberty...) and
bootstrap stages. It seems quite platform specific, and the safest
approach to correcting this seems to be explicitly always specifying the
-march argument when bootstrapping GCC. Because the best choice 'native'
is not available when bootstrapping using a foreign (non GCC) compiler,
a guess is made according to rpmmacros l_platform in that case.
It is questionable as to whether these recent optimization changes
on the part of GCC or this package are compatible with each other,
or if either are complete or correct at all. At least applying these
corrections allows this package to build again in most cases test.
1 #include <config.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h> /* for memcmp() */
5 #include <assert.h>
7 #include "types.h" /* for byte and u32 typedefs */
8 #include "g10lib.h"
9 #include "cipher.h"
11 /* configuration stuff */
12 #ifdef __alpha__
13 #define SIZEOF_UNSIGNED_LONG 8
14 #else
15 #define SIZEOF_UNSIGNED_LONG 4
16 #endif
18 #if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \
19 || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \
20 || defined(__powerpc__) \
21 || defined(__hpux__) /* should be replaced by the Macro for the PA */
22 #define BIG_ENDIAN_HOST 1
23 #else
24 #define LITTLE_ENDIAN_HOST 1
25 #endif
27 #ifndef DIM
28 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
29 #define DIMof(type,member) DIM(((type *)0)->member)
30 #endif
32 /* imports */
33 void g10_log_fatal( const char *fmt, ... );
36 /* local stuff */
38 #define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
39 #define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
41 #define IDEA_KEYSIZE 16
42 #define IDEA_BLOCKSIZE 8
43 #define IDEA_ROUNDS 8
44 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
46 typedef struct {
47 u16 ek[IDEA_KEYLEN];
48 u16 dk[IDEA_KEYLEN];
49 int have_dk;
50 } IDEA_context;
52 static u16
53 mul_inv( u16 x )
54 {
55 u16 t0, t1;
56 u16 q, y;
58 if( x < 2 )
59 return x;
60 t1 = 0x10001L / x;
61 y = 0x10001L % x;
62 if( y == 1 )
63 return (1-t1) & 0xffff;
65 t0 = 1;
66 do {
67 q = x / y;
68 x = x % y;
69 t0 += q * t1;
70 if( x == 1 )
71 return t0;
72 q = y / x;
73 y = y % x;
74 t1 += q * t0;
75 } while( y != 1 );
76 return (1-t1) & 0xffff;
77 }
79 static void
80 cipher( byte *outbuf, const byte *inbuf, u16 *key )
81 {
82 u16 x1, x2, x3,x4, s2, s3;
83 u16 *in, *out;
84 int r = IDEA_ROUNDS;
85 #define MUL(x,y) \
86 do {u16 _t16; u32 _t32; \
87 if( (_t16 = (y)) ) { \
88 if( (x = (x)&0xffff) ) { \
89 _t32 = (u32)x * _t16; \
90 x = _t32 & 0xffff; \
91 _t16 = _t32 >> 16; \
92 x = ((x)-_t16) + (x<_t16?1:0); \
93 } \
94 else { \
95 x = 1 - _t16; \
96 } \
97 } \
98 else { \
99 x = 1 - x; \
100 } \
101 } while(0)
103 in = (u16*)inbuf;
104 x1 = *in++;
105 x2 = *in++;
106 x3 = *in++;
107 x4 = *in;
108 #ifdef LITTLE_ENDIAN_HOST
109 x1 = (x1>>8) | (x1<<8);
110 x2 = (x2>>8) | (x2<<8);
111 x3 = (x3>>8) | (x3<<8);
112 x4 = (x4>>8) | (x4<<8);
113 #endif
114 do {
115 MUL(x1, *key++);
116 x2 += *key++;
117 x3 += *key++;
118 MUL(x4, *key++ );
120 s3 = x3;
121 x3 ^= x1;
122 MUL(x3, *key++);
123 s2 = x2;
124 x2 ^=x4;
125 x2 += x3;
126 MUL(x2, *key++);
127 x3 += x2;
129 x1 ^= x2;
130 x4 ^= x3;
132 x2 ^= s3;
133 x3 ^= s2;
134 } while( --r );
135 MUL(x1, *key++);
136 x3 += *key++;
137 x2 += *key++;
138 MUL(x4, *key);
140 out = (u16*)outbuf;
141 #ifdef LITTLE_ENDIAN_HOST
142 *out++ = (x1>>8) | (x1<<8);
143 *out++ = (x3>>8) | (x3<<8);
144 *out++ = (x2>>8) | (x2<<8);
145 *out = (x4>>8) | (x4<<8);
146 #else
147 *out++ = x1;
148 *out++ = x3;
149 *out++ = x2;
150 *out = x4;
151 #endif
152 #undef MUL
153 }
155 static void
156 expand_key( const byte *userkey, u16 *ek )
157 {
158 int i,j;
160 for(j=0; j < 8; j++ ) {
161 ek[j] = (*userkey << 8) + userkey[1];
162 userkey += 2;
163 }
164 for(i=0; j < IDEA_KEYLEN; j++ ) {
165 i++;
166 ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7;
167 ek += i & 8;
168 i &= 7;
169 }
170 }
172 static void
173 invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] )
174 {
175 int i;
176 u16 t1, t2, t3;
177 u16 temp[IDEA_KEYLEN];
178 u16 *p = temp + IDEA_KEYLEN;
180 t1 = mul_inv( *ek++ );
181 t2 = -*ek++;
182 t3 = -*ek++;
183 *--p = mul_inv( *ek++ );
184 *--p = t3;
185 *--p = t2;
186 *--p = t1;
188 for(i=0; i < IDEA_ROUNDS-1; i++ ) {
189 t1 = *ek++;
190 *--p = *ek++;
191 *--p = t1;
193 t1 = mul_inv( *ek++ );
194 t2 = -*ek++;
195 t3 = -*ek++;
196 *--p = mul_inv( *ek++ );
197 *--p = t2;
198 *--p = t3;
199 *--p = t1;
200 }
201 t1 = *ek++;
202 *--p = *ek++;
203 *--p = t1;
205 t1 = mul_inv( *ek++ );
206 t2 = -*ek++;
207 t3 = -*ek++;
208 *--p = mul_inv( *ek++ );
209 *--p = t3;
210 *--p = t2;
211 *--p = t1;
212 memcpy(dk, temp, sizeof(temp) );
213 memset(temp, 0, sizeof(temp) ); /* burn temp */
214 }
216 static int
217 do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
218 {
219 assert(keylen == 16);
220 c->have_dk = 0;
221 expand_key( key, c->ek );
222 invert_key( c->ek, c->dk );
223 return 0;
224 }
226 static gcry_err_code_t
227 idea_setkey (void *context, const byte *key, unsigned int keylen)
228 {
229 IDEA_context *ctx = context;
230 int rc = do_idea_setkey (ctx, key, keylen);
231 _gcry_burn_stack (23+6*sizeof(void*));
232 return rc;
233 }
235 static void
236 do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
237 {
238 cipher( outbuf, inbuf, c->ek );
239 }
241 static void
242 idea_encrypt (void *context, byte *out, const byte *in)
243 {
244 IDEA_context *ctx = context;
245 do_idea_encrypt (ctx, out, in);
246 _gcry_burn_stack (24+3*sizeof (void*));
247 }
249 static void
250 do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
251 {
252 if( !c->have_dk ) {
253 c->have_dk = 1;
254 invert_key( c->ek, c->dk );
255 }
256 cipher( outbuf, inbuf, c->dk );
257 }
259 static void
260 idea_decrypt (void *context, byte *out, const byte *in)
261 {
262 IDEA_context *ctx = context;
264 do_idea_decrypt (ctx, out, in);
265 _gcry_burn_stack (24+3*sizeof (void*));
266 }
268 gcry_cipher_spec_t _gcry_cipher_spec_idea =
269 {
270 "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context),
271 idea_setkey, idea_encrypt, idea_decrypt,
272 };