saferp.c revision f7fc46c63fdc8f39234fea409b8dbe116d73ebf8
1/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10 */ 11 12/** 13 @file saferp.c 14 SAFER+ Implementation by Tom St Denis 15*/ 16#include "tomcrypt.h" 17 18#ifdef SAFERP 19 20const struct ltc_cipher_descriptor saferp_desc = 21{ 22 "safer+", 23 4, 24 16, 32, 16, 8, 25 &saferp_setup, 26 &saferp_ecb_encrypt, 27 &saferp_ecb_decrypt, 28 &saferp_test, 29 &saferp_done, 30 &saferp_keysize, 31 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 32}; 33 34/* ROUND(b,i) 35 * 36 * This is one forward key application. Note the basic form is 37 * key addition, substitution, key addition. The safer_ebox and safer_lbox 38 * are the exponentiation box and logarithm boxes respectively. 39 * The value of 'i' is the current round number which allows this 40 * function to be unrolled massively. Most of SAFER+'s speed 41 * comes from not having to compute indirect accesses into the 42 * array of 16 bytes b[0..15] which is the block of data 43*/ 44 45extern const unsigned char safer_ebox[], safer_lbox[]; 46 47#define ROUND(b, i) \ 48 b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ 49 b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ 50 b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ 51 b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ 52 b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ 53 b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ 54 b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ 55 b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ 56 b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ 57 b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ 58 b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ 59 b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ 60 b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ 61 b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ 62 b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ 63 b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; 64 65/* This is one inverse key application */ 66#define iROUND(b, i) \ 67 b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \ 68 b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \ 69 b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \ 70 b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \ 71 b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \ 72 b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \ 73 b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \ 74 b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \ 75 b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \ 76 b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \ 77 b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \ 78 b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \ 79 b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \ 80 b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \ 81 b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \ 82 b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; 83 84/* This is a forward single layer PHT transform. */ 85#define PHT(b) \ 86 b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \ 87 b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \ 88 b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \ 89 b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \ 90 b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \ 91 b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \ 92 b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \ 93 b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; 94 95/* This is an inverse single layer PHT transform */ 96#define iPHT(b) \ 97 b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \ 98 b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \ 99 b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \ 100 b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \ 101 b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \ 102 b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \ 103 b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \ 104 b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \ 105 106/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ 107#define SHUF(b, b2) \ 108 b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ 109 b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ 110 b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ 111 b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; 112 113/* This is the inverse shuffle. It takes from b and gives to b2 */ 114#define iSHUF(b, b2) \ 115 b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ 116 b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ 117 b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ 118 b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; 119 120/* The complete forward Linear Transform layer. 121 * Note that alternating usage of b and b2. 122 * Each round of LT starts in 'b' and ends in 'b2'. 123 */ 124#define LT(b, b2) \ 125 PHT(b); SHUF(b, b2); \ 126 PHT(b2); SHUF(b2, b); \ 127 PHT(b); SHUF(b, b2); \ 128 PHT(b2); 129 130/* This is the inverse linear transform layer. */ 131#define iLT(b, b2) \ 132 iPHT(b); \ 133 iSHUF(b, b2); iPHT(b2); \ 134 iSHUF(b2, b); iPHT(b); \ 135 iSHUF(b, b2); iPHT(b2); 136 137#ifdef LTC_SMALL_CODE 138 139static void _round(unsigned char *b, int i, symmetric_key *skey) 140{ 141 ROUND(b, i); 142} 143 144static void _iround(unsigned char *b, int i, symmetric_key *skey) 145{ 146 iROUND(b, i); 147} 148 149static void _lt(unsigned char *b, unsigned char *b2) 150{ 151 LT(b, b2); 152} 153 154static void _ilt(unsigned char *b, unsigned char *b2) 155{ 156 iLT(b, b2); 157} 158 159#undef ROUND 160#define ROUND(b, i) _round(b, i, skey) 161 162#undef iROUND 163#define iROUND(b, i) _iround(b, i, skey) 164 165#undef LT 166#define LT(b, b2) _lt(b, b2) 167 168#undef iLT 169#define iLT(b, b2) _ilt(b, b2) 170 171#endif 172 173/* These are the 33, 128-bit bias words for the key schedule */ 174static const unsigned char safer_bias[33][16] = { 175{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100}, 176{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61}, 177{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160}, 178{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148}, 179{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143}, 180{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202}, 181{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44}, 182{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51}, 183{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56}, 184{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215}, 185{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210}, 186{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53}, 187{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244}, 188{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131}, 189{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241}, 190{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172}, 191{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239}, 192{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202}, 193{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246}, 194{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152}, 195{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236}, 196{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150}, 197{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30}, 198{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6}, 199{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104}, 200{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175}, 201{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35}, 202{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7}, 203{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207}, 204{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247}, 205{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255}, 206{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}}; 207 208 /** 209 Initialize the SAFER+ block cipher 210 @param key The symmetric key you wish to pass 211 @param keylen The key length in bytes 212 @param num_rounds The number of rounds desired (0 for default) 213 @param skey The key in as scheduled by this function. 214 @return CRYPT_OK if successful 215 */ 216int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) 217{ 218 unsigned x, y, z; 219 unsigned char t[33]; 220 static const int rounds[3] = { 8, 12, 16 }; 221 222 LTC_ARGCHK(key != NULL); 223 LTC_ARGCHK(skey != NULL); 224 225 /* check arguments */ 226 if (keylen != 16 && keylen != 24 && keylen != 32) { 227 return CRYPT_INVALID_KEYSIZE; 228 } 229 230 /* Is the number of rounds valid? Either use zero for default or 231 * 8,12,16 rounds for 16,24,32 byte keys 232 */ 233 if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) { 234 return CRYPT_INVALID_ROUNDS; 235 } 236 237 /* 128 bit key version */ 238 if (keylen == 16) { 239 /* copy key into t */ 240 for (x = y = 0; x < 16; x++) { 241 t[x] = key[x]; 242 y ^= key[x]; 243 } 244 t[16] = y; 245 246 /* make round keys */ 247 for (x = 0; x < 16; x++) { 248 skey->saferp.K[0][x] = t[x]; 249 } 250 251 /* make the 16 other keys as a transformation of the first key */ 252 for (x = 1; x < 17; x++) { 253 /* rotate 3 bits each */ 254 for (y = 0; y < 17; y++) { 255 t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; 256 } 257 258 /* select and add */ 259 z = x; 260 for (y = 0; y < 16; y++) { 261 skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; 262 if (++z == 17) { z = 0; } 263 } 264 } 265 skey->saferp.rounds = 8; 266 } else if (keylen == 24) { 267 /* copy key into t */ 268 for (x = y = 0; x < 24; x++) { 269 t[x] = key[x]; 270 y ^= key[x]; 271 } 272 t[24] = y; 273 274 /* make round keys */ 275 for (x = 0; x < 16; x++) { 276 skey->saferp.K[0][x] = t[x]; 277 } 278 279 for (x = 1; x < 25; x++) { 280 /* rotate 3 bits each */ 281 for (y = 0; y < 25; y++) { 282 t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; 283 } 284 285 /* select and add */ 286 z = x; 287 for (y = 0; y < 16; y++) { 288 skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; 289 if (++z == 25) { z = 0; } 290 } 291 } 292 skey->saferp.rounds = 12; 293 } else { 294 /* copy key into t */ 295 for (x = y = 0; x < 32; x++) { 296 t[x] = key[x]; 297 y ^= key[x]; 298 } 299 t[32] = y; 300 301 /* make round keys */ 302 for (x = 0; x < 16; x++) { 303 skey->saferp.K[0][x] = t[x]; 304 } 305 306 for (x = 1; x < 33; x++) { 307 /* rotate 3 bits each */ 308 for (y = 0; y < 33; y++) { 309 t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; 310 } 311 312 /* select and add */ 313 z = x; 314 for (y = 0; y < 16; y++) { 315 skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; 316 if (++z == 33) { z = 0; } 317 } 318 } 319 skey->saferp.rounds = 16; 320 } 321#ifdef LTC_CLEAN_STACK 322 zeromem(t, sizeof(t)); 323#endif 324 return CRYPT_OK; 325} 326 327/** 328 Encrypts a block of text with SAFER+ 329 @param pt The input plaintext (16 bytes) 330 @param ct The output ciphertext (16 bytes) 331 @param skey The key as scheduled 332 @return CRYPT_OK if successful 333*/ 334int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 335{ 336 unsigned char b[16]; 337 int x; 338 339 LTC_ARGCHK(pt != NULL); 340 LTC_ARGCHK(ct != NULL); 341 LTC_ARGCHK(skey != NULL); 342 343 /* do eight rounds */ 344 for (x = 0; x < 16; x++) { 345 b[x] = pt[x]; 346 } 347 ROUND(b, 0); LT(b, ct); 348 ROUND(ct, 2); LT(ct, b); 349 ROUND(b, 4); LT(b, ct); 350 ROUND(ct, 6); LT(ct, b); 351 ROUND(b, 8); LT(b, ct); 352 ROUND(ct, 10); LT(ct, b); 353 ROUND(b, 12); LT(b, ct); 354 ROUND(ct, 14); LT(ct, b); 355 /* 192-bit key? */ 356 if (skey->saferp.rounds > 8) { 357 ROUND(b, 16); LT(b, ct); 358 ROUND(ct, 18); LT(ct, b); 359 ROUND(b, 20); LT(b, ct); 360 ROUND(ct, 22); LT(ct, b); 361 } 362 /* 256-bit key? */ 363 if (skey->saferp.rounds > 12) { 364 ROUND(b, 24); LT(b, ct); 365 ROUND(ct, 26); LT(ct, b); 366 ROUND(b, 28); LT(b, ct); 367 ROUND(ct, 30); LT(ct, b); 368 } 369 ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; 370 ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; 371 ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; 372 ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; 373 ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; 374 ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; 375 ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; 376 ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; 377 ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; 378 ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; 379 ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; 380 ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; 381 ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; 382 ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; 383 ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; 384 ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; 385#ifdef LTC_CLEAN_STACK 386 zeromem(b, sizeof(b)); 387#endif 388 return CRYPT_OK; 389} 390 391/** 392 Decrypts a block of text with SAFER+ 393 @param ct The input ciphertext (16 bytes) 394 @param pt The output plaintext (16 bytes) 395 @param skey The key as scheduled 396 @return CRYPT_OK if successful 397*/ 398int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 399{ 400 unsigned char b[16]; 401 int x; 402 403 LTC_ARGCHK(pt != NULL); 404 LTC_ARGCHK(ct != NULL); 405 LTC_ARGCHK(skey != NULL); 406 407 /* do eight rounds */ 408 b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; 409 b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; 410 b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; 411 b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; 412 b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; 413 b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; 414 b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; 415 b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; 416 b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; 417 b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; 418 b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; 419 b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; 420 b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; 421 b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; 422 b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; 423 b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; 424 /* 256-bit key? */ 425 if (skey->saferp.rounds > 12) { 426 iLT(b, pt); iROUND(pt, 30); 427 iLT(pt, b); iROUND(b, 28); 428 iLT(b, pt); iROUND(pt, 26); 429 iLT(pt, b); iROUND(b, 24); 430 } 431 /* 192-bit key? */ 432 if (skey->saferp.rounds > 8) { 433 iLT(b, pt); iROUND(pt, 22); 434 iLT(pt, b); iROUND(b, 20); 435 iLT(b, pt); iROUND(pt, 18); 436 iLT(pt, b); iROUND(b, 16); 437 } 438 iLT(b, pt); iROUND(pt, 14); 439 iLT(pt, b); iROUND(b, 12); 440 iLT(b, pt); iROUND(pt,10); 441 iLT(pt, b); iROUND(b, 8); 442 iLT(b, pt); iROUND(pt,6); 443 iLT(pt, b); iROUND(b, 4); 444 iLT(b, pt); iROUND(pt,2); 445 iLT(pt, b); iROUND(b, 0); 446 for (x = 0; x < 16; x++) { 447 pt[x] = b[x]; 448 } 449#ifdef LTC_CLEAN_STACK 450 zeromem(b, sizeof(b)); 451#endif 452 return CRYPT_OK; 453} 454 455/** 456 Performs a self-test of the SAFER+ block cipher 457 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled 458*/ 459int saferp_test(void) 460{ 461 #ifndef LTC_TEST 462 return CRYPT_NOP; 463 #else 464 static const struct { 465 int keylen; 466 unsigned char key[32], pt[16], ct[16]; 467 } tests[] = { 468 { 469 16, 470 { 41, 35, 190, 132, 225, 108, 214, 174, 471 82, 144, 73, 241, 241, 187, 233, 235 }, 472 { 179, 166, 219, 60, 135, 12, 62, 153, 473 36, 94, 13, 28, 6, 183, 71, 222 }, 474 { 224, 31, 182, 10, 12, 255, 84, 70, 475 127, 13, 89, 249, 9, 57, 165, 220 } 476 }, { 477 24, 478 { 72, 211, 143, 117, 230, 217, 29, 42, 479 229, 192, 247, 43, 120, 129, 135, 68, 480 14, 95, 80, 0, 212, 97, 141, 190 }, 481 { 123, 5, 21, 7, 59, 51, 130, 31, 482 24, 112, 146, 218, 100, 84, 206, 177 }, 483 { 92, 136, 4, 63, 57, 95, 100, 0, 484 150, 130, 130, 16, 193, 111, 219, 133 } 485 }, { 486 32, 487 { 243, 168, 141, 254, 190, 242, 235, 113, 488 255, 160, 208, 59, 117, 6, 140, 126, 489 135, 120, 115, 77, 208, 190, 130, 190, 490 219, 194, 70, 65, 43, 140, 250, 48 }, 491 { 127, 112, 240, 167, 84, 134, 50, 149, 492 170, 91, 104, 19, 11, 230, 252, 245 }, 493 { 88, 11, 25, 36, 172, 229, 202, 213, 494 170, 65, 105, 153, 220, 104, 153, 138 } 495 } 496 }; 497 498 unsigned char tmp[2][16]; 499 symmetric_key skey; 500 int err, i, y; 501 502 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { 503 if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { 504 return err; 505 } 506 saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); 507 saferp_ecb_decrypt(tmp[0], tmp[1], &skey); 508 509 /* compare */ 510 if (XMEMCMP(tmp[0], tests[i].ct, 16) || XMEMCMP(tmp[1], tests[i].pt, 16)) { 511 return CRYPT_FAIL_TESTVECTOR; 512 } 513 514 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ 515 for (y = 0; y < 16; y++) tmp[0][y] = 0; 516 for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); 517 for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); 518 for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; 519 } 520 521 return CRYPT_OK; 522 #endif 523} 524 525/** Terminate the context 526 @param skey The scheduled key 527*/ 528void saferp_done(symmetric_key *skey) 529{ 530} 531 532/** 533 Gets suitable key size 534 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. 535 @return CRYPT_OK if the input key size is acceptable. 536*/ 537int saferp_keysize(int *keysize) 538{ 539 LTC_ARGCHK(keysize != NULL); 540 541 if (*keysize < 16) 542 return CRYPT_INVALID_KEYSIZE; 543 if (*keysize < 24) { 544 *keysize = 16; 545 } else if (*keysize < 32) { 546 *keysize = 24; 547 } else { 548 *keysize = 32; 549 } 550 return CRYPT_OK; 551} 552 553#endif 554 555 556 557/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/safer/saferp.c,v $ */ 558/* $Revision: 1.12 $ */ 559/* $Date: 2006/11/08 23:01:06 $ */ 560