Mon, 20 Apr 2009 19:22:00 +0200
Change unfortunate but partly useful overreaching security tradeoff.
The principle of allocating each running process an individual system
user and group can have security benefits, however maintining a plethora
of users, groups, processes, file modes, file permissions, and even
nonportable file ACLs on a host serving from a hundred processes has
some security disadvantages. This tradeoff is even worse for systems
like OpenPKG which benefit from administration transparency through the
use of minimal system intrusion and only three usage privilege levels.
michael@107 | 1 | #include <config.h> |
michael@107 | 2 | #include <stdio.h> |
michael@107 | 3 | #include <stdlib.h> |
michael@107 | 4 | #include <string.h> /* for memcmp() */ |
michael@107 | 5 | #include <assert.h> |
michael@107 | 6 | |
michael@107 | 7 | #include "types.h" /* for byte and u32 typedefs */ |
michael@107 | 8 | #include "g10lib.h" |
michael@107 | 9 | #include "cipher.h" |
michael@107 | 10 | |
michael@107 | 11 | /* configuration stuff */ |
michael@107 | 12 | #ifdef __alpha__ |
michael@107 | 13 | #define SIZEOF_UNSIGNED_LONG 8 |
michael@107 | 14 | #else |
michael@107 | 15 | #define SIZEOF_UNSIGNED_LONG 4 |
michael@107 | 16 | #endif |
michael@107 | 17 | |
michael@107 | 18 | #if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \ |
michael@107 | 19 | || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \ |
michael@107 | 20 | || defined(__powerpc__) \ |
michael@107 | 21 | || defined(__hpux__) /* should be replaced by the Macro for the PA */ |
michael@107 | 22 | #define BIG_ENDIAN_HOST 1 |
michael@107 | 23 | #else |
michael@107 | 24 | #define LITTLE_ENDIAN_HOST 1 |
michael@107 | 25 | #endif |
michael@107 | 26 | |
michael@107 | 27 | #ifndef DIM |
michael@107 | 28 | #define DIM(v) (sizeof(v)/sizeof((v)[0])) |
michael@107 | 29 | #define DIMof(type,member) DIM(((type *)0)->member) |
michael@107 | 30 | #endif |
michael@107 | 31 | |
michael@107 | 32 | /* imports */ |
michael@107 | 33 | void g10_log_fatal( const char *fmt, ... ); |
michael@107 | 34 | |
michael@107 | 35 | |
michael@107 | 36 | /* local stuff */ |
michael@107 | 37 | |
michael@107 | 38 | #define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) |
michael@107 | 39 | #define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f)) |
michael@107 | 40 | |
michael@107 | 41 | #define IDEA_KEYSIZE 16 |
michael@107 | 42 | #define IDEA_BLOCKSIZE 8 |
michael@107 | 43 | #define IDEA_ROUNDS 8 |
michael@107 | 44 | #define IDEA_KEYLEN (6*IDEA_ROUNDS+4) |
michael@107 | 45 | |
michael@107 | 46 | typedef struct { |
michael@107 | 47 | u16 ek[IDEA_KEYLEN]; |
michael@107 | 48 | u16 dk[IDEA_KEYLEN]; |
michael@107 | 49 | int have_dk; |
michael@107 | 50 | } IDEA_context; |
michael@107 | 51 | |
michael@107 | 52 | static u16 |
michael@107 | 53 | mul_inv( u16 x ) |
michael@107 | 54 | { |
michael@107 | 55 | u16 t0, t1; |
michael@107 | 56 | u16 q, y; |
michael@107 | 57 | |
michael@107 | 58 | if( x < 2 ) |
michael@107 | 59 | return x; |
michael@107 | 60 | t1 = 0x10001L / x; |
michael@107 | 61 | y = 0x10001L % x; |
michael@107 | 62 | if( y == 1 ) |
michael@107 | 63 | return (1-t1) & 0xffff; |
michael@107 | 64 | |
michael@107 | 65 | t0 = 1; |
michael@107 | 66 | do { |
michael@107 | 67 | q = x / y; |
michael@107 | 68 | x = x % y; |
michael@107 | 69 | t0 += q * t1; |
michael@107 | 70 | if( x == 1 ) |
michael@107 | 71 | return t0; |
michael@107 | 72 | q = y / x; |
michael@107 | 73 | y = y % x; |
michael@107 | 74 | t1 += q * t0; |
michael@107 | 75 | } while( y != 1 ); |
michael@107 | 76 | return (1-t1) & 0xffff; |
michael@107 | 77 | } |
michael@107 | 78 | |
michael@107 | 79 | static void |
michael@107 | 80 | cipher( byte *outbuf, const byte *inbuf, u16 *key ) |
michael@107 | 81 | { |
michael@107 | 82 | u16 x1, x2, x3,x4, s2, s3; |
michael@107 | 83 | u16 *in, *out; |
michael@107 | 84 | int r = IDEA_ROUNDS; |
michael@107 | 85 | #define MUL(x,y) \ |
michael@107 | 86 | do {u16 _t16; u32 _t32; \ |
michael@107 | 87 | if( (_t16 = (y)) ) { \ |
michael@107 | 88 | if( (x = (x)&0xffff) ) { \ |
michael@107 | 89 | _t32 = (u32)x * _t16; \ |
michael@107 | 90 | x = _t32 & 0xffff; \ |
michael@107 | 91 | _t16 = _t32 >> 16; \ |
michael@107 | 92 | x = ((x)-_t16) + (x<_t16?1:0); \ |
michael@107 | 93 | } \ |
michael@107 | 94 | else { \ |
michael@107 | 95 | x = 1 - _t16; \ |
michael@107 | 96 | } \ |
michael@107 | 97 | } \ |
michael@107 | 98 | else { \ |
michael@107 | 99 | x = 1 - x; \ |
michael@107 | 100 | } \ |
michael@107 | 101 | } while(0) |
michael@107 | 102 | |
michael@107 | 103 | in = (u16*)inbuf; |
michael@107 | 104 | x1 = *in++; |
michael@107 | 105 | x2 = *in++; |
michael@107 | 106 | x3 = *in++; |
michael@107 | 107 | x4 = *in; |
michael@107 | 108 | #ifdef LITTLE_ENDIAN_HOST |
michael@107 | 109 | x1 = (x1>>8) | (x1<<8); |
michael@107 | 110 | x2 = (x2>>8) | (x2<<8); |
michael@107 | 111 | x3 = (x3>>8) | (x3<<8); |
michael@107 | 112 | x4 = (x4>>8) | (x4<<8); |
michael@107 | 113 | #endif |
michael@107 | 114 | do { |
michael@107 | 115 | MUL(x1, *key++); |
michael@107 | 116 | x2 += *key++; |
michael@107 | 117 | x3 += *key++; |
michael@107 | 118 | MUL(x4, *key++ ); |
michael@107 | 119 | |
michael@107 | 120 | s3 = x3; |
michael@107 | 121 | x3 ^= x1; |
michael@107 | 122 | MUL(x3, *key++); |
michael@107 | 123 | s2 = x2; |
michael@107 | 124 | x2 ^=x4; |
michael@107 | 125 | x2 += x3; |
michael@107 | 126 | MUL(x2, *key++); |
michael@107 | 127 | x3 += x2; |
michael@107 | 128 | |
michael@107 | 129 | x1 ^= x2; |
michael@107 | 130 | x4 ^= x3; |
michael@107 | 131 | |
michael@107 | 132 | x2 ^= s3; |
michael@107 | 133 | x3 ^= s2; |
michael@107 | 134 | } while( --r ); |
michael@107 | 135 | MUL(x1, *key++); |
michael@107 | 136 | x3 += *key++; |
michael@107 | 137 | x2 += *key++; |
michael@107 | 138 | MUL(x4, *key); |
michael@107 | 139 | |
michael@107 | 140 | out = (u16*)outbuf; |
michael@107 | 141 | #ifdef LITTLE_ENDIAN_HOST |
michael@107 | 142 | *out++ = (x1>>8) | (x1<<8); |
michael@107 | 143 | *out++ = (x3>>8) | (x3<<8); |
michael@107 | 144 | *out++ = (x2>>8) | (x2<<8); |
michael@107 | 145 | *out = (x4>>8) | (x4<<8); |
michael@107 | 146 | #else |
michael@107 | 147 | *out++ = x1; |
michael@107 | 148 | *out++ = x3; |
michael@107 | 149 | *out++ = x2; |
michael@107 | 150 | *out = x4; |
michael@107 | 151 | #endif |
michael@107 | 152 | #undef MUL |
michael@107 | 153 | } |
michael@107 | 154 | |
michael@107 | 155 | static void |
michael@107 | 156 | expand_key( const byte *userkey, u16 *ek ) |
michael@107 | 157 | { |
michael@107 | 158 | int i,j; |
michael@107 | 159 | |
michael@107 | 160 | for(j=0; j < 8; j++ ) { |
michael@107 | 161 | ek[j] = (*userkey << 8) + userkey[1]; |
michael@107 | 162 | userkey += 2; |
michael@107 | 163 | } |
michael@107 | 164 | for(i=0; j < IDEA_KEYLEN; j++ ) { |
michael@107 | 165 | i++; |
michael@107 | 166 | ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; |
michael@107 | 167 | ek += i & 8; |
michael@107 | 168 | i &= 7; |
michael@107 | 169 | } |
michael@107 | 170 | } |
michael@107 | 171 | |
michael@107 | 172 | static void |
michael@107 | 173 | invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) |
michael@107 | 174 | { |
michael@107 | 175 | int i; |
michael@107 | 176 | u16 t1, t2, t3; |
michael@107 | 177 | u16 temp[IDEA_KEYLEN]; |
michael@107 | 178 | u16 *p = temp + IDEA_KEYLEN; |
michael@107 | 179 | |
michael@107 | 180 | t1 = mul_inv( *ek++ ); |
michael@107 | 181 | t2 = -*ek++; |
michael@107 | 182 | t3 = -*ek++; |
michael@107 | 183 | *--p = mul_inv( *ek++ ); |
michael@107 | 184 | *--p = t3; |
michael@107 | 185 | *--p = t2; |
michael@107 | 186 | *--p = t1; |
michael@107 | 187 | |
michael@107 | 188 | for(i=0; i < IDEA_ROUNDS-1; i++ ) { |
michael@107 | 189 | t1 = *ek++; |
michael@107 | 190 | *--p = *ek++; |
michael@107 | 191 | *--p = t1; |
michael@107 | 192 | |
michael@107 | 193 | t1 = mul_inv( *ek++ ); |
michael@107 | 194 | t2 = -*ek++; |
michael@107 | 195 | t3 = -*ek++; |
michael@107 | 196 | *--p = mul_inv( *ek++ ); |
michael@107 | 197 | *--p = t2; |
michael@107 | 198 | *--p = t3; |
michael@107 | 199 | *--p = t1; |
michael@107 | 200 | } |
michael@107 | 201 | t1 = *ek++; |
michael@107 | 202 | *--p = *ek++; |
michael@107 | 203 | *--p = t1; |
michael@107 | 204 | |
michael@107 | 205 | t1 = mul_inv( *ek++ ); |
michael@107 | 206 | t2 = -*ek++; |
michael@107 | 207 | t3 = -*ek++; |
michael@107 | 208 | *--p = mul_inv( *ek++ ); |
michael@107 | 209 | *--p = t3; |
michael@107 | 210 | *--p = t2; |
michael@107 | 211 | *--p = t1; |
michael@107 | 212 | memcpy(dk, temp, sizeof(temp) ); |
michael@107 | 213 | memset(temp, 0, sizeof(temp) ); /* burn temp */ |
michael@107 | 214 | } |
michael@107 | 215 | |
michael@107 | 216 | static int |
michael@107 | 217 | do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) |
michael@107 | 218 | { |
michael@107 | 219 | assert(keylen == 16); |
michael@107 | 220 | c->have_dk = 0; |
michael@107 | 221 | expand_key( key, c->ek ); |
michael@107 | 222 | invert_key( c->ek, c->dk ); |
michael@107 | 223 | return 0; |
michael@107 | 224 | } |
michael@107 | 225 | |
michael@107 | 226 | static gcry_err_code_t |
michael@107 | 227 | idea_setkey (void *context, const byte *key, unsigned int keylen) |
michael@107 | 228 | { |
michael@107 | 229 | IDEA_context *ctx = context; |
michael@107 | 230 | int rc = do_idea_setkey (ctx, key, keylen); |
michael@107 | 231 | _gcry_burn_stack (23+6*sizeof(void*)); |
michael@107 | 232 | return rc; |
michael@107 | 233 | } |
michael@107 | 234 | |
michael@107 | 235 | static void |
michael@107 | 236 | do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) |
michael@107 | 237 | { |
michael@107 | 238 | cipher( outbuf, inbuf, c->ek ); |
michael@107 | 239 | } |
michael@107 | 240 | |
michael@107 | 241 | static void |
michael@107 | 242 | idea_encrypt (void *context, byte *out, const byte *in) |
michael@107 | 243 | { |
michael@107 | 244 | IDEA_context *ctx = context; |
michael@107 | 245 | do_idea_encrypt (ctx, out, in); |
michael@107 | 246 | _gcry_burn_stack (24+3*sizeof (void*)); |
michael@107 | 247 | } |
michael@107 | 248 | |
michael@107 | 249 | static void |
michael@107 | 250 | do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) |
michael@107 | 251 | { |
michael@107 | 252 | if( !c->have_dk ) { |
michael@107 | 253 | c->have_dk = 1; |
michael@107 | 254 | invert_key( c->ek, c->dk ); |
michael@107 | 255 | } |
michael@107 | 256 | cipher( outbuf, inbuf, c->dk ); |
michael@107 | 257 | } |
michael@107 | 258 | |
michael@107 | 259 | static void |
michael@107 | 260 | idea_decrypt (void *context, byte *out, const byte *in) |
michael@107 | 261 | { |
michael@107 | 262 | IDEA_context *ctx = context; |
michael@107 | 263 | |
michael@107 | 264 | do_idea_decrypt (ctx, out, in); |
michael@107 | 265 | _gcry_burn_stack (24+3*sizeof (void*)); |
michael@107 | 266 | } |
michael@107 | 267 | |
michael@107 | 268 | gcry_cipher_spec_t _gcry_cipher_spec_idea = |
michael@107 | 269 | { |
michael@107 | 270 | "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context), |
michael@107 | 271 | idea_setkey, idea_encrypt, idea_decrypt, |
michael@107 | 272 | }; |