/ sbt.c
sbt.c
1 #include <string.h> 2 #include <stdio.h> 3 #include <stdint.h> 4 #include <stdarg.h> 5 #include "sbt.h" 6 7 // Addresses 8 // 0x25 [8] copy of LFSR/cryptovariable 9 // 0x25 is set to 0x9c at the beginning of the mainloop. 10 // 0x2d [8] LFSR/crypto variable 11 // 0x35 [7] effective crypto variable 12 // 0x3f [1] index into cipherblock for next byte to xor with, 0x2c..0x34 13 // 0x7f41 [8] = cryptovariable/state 14 // 0x72d7 [15] crypto key - keyed in via keyboard 15 16 static const uint8_t SBOX[128] = {0xF4, 0xAF, 0x8A, 0xD1, 0x3B, 0x02, 0xE8, 0x20, 17 0xCD, 0x65, 0x96, 0x1C, 0x47, 0xB3, 0x79, 0x5E, 18 0x18, 0x8B, 0xE3, 0xAE, 0x7D, 0x4A, 0x94, 0xDF, 19 0x69, 0x30, 0xBC, 0x56, 0xF5, 0x07, 0x21, 0xC2, 20 0xBD, 0x72, 0x9C, 0x59, 0xAE, 0x17, 0xF3, 0x61, 21 0x24, 0xC8, 0x40, 0xDF, 0xE6, 0x8A, 0x35, 0x0B, 22 0x27, 0x4D, 0x56, 0xC8, 0x91, 0xB3, 0x70, 0x84, 23 0xF5, 0xEF, 0xD2, 0xAE, 0x3A, 0x1C, 0x0B, 0x69, 24 0x47, 0x9F, 0x80, 0x5C, 0x0A, 0x68, 0xA1, 0xEB, 25 0xB9, 0x2D, 0x75, 0xF3, 0x1E, 0x32, 0xD6, 0xC4, 26 0xB3, 0xAE, 0xED, 0x09, 0x91, 0xD4, 0x38, 0x26, 27 0x6A, 0xC0, 0xFB, 0x75, 0x82, 0x5F, 0x4C, 0x17, 28 0x59, 0x27, 0x16, 0x4D, 0xDB, 0xEF, 0x04, 0x9C, 29 0xF0, 0xB8, 0x62, 0xCE, 0x3A, 0xA1, 0x73, 0x85, 30 0x18, 0x5D, 0x47, 0x6E, 0xC5, 0xA0, 0x9B, 0xFA, 31 0x32, 0xE3, 0x8C, 0x01, 0xDF, 0x74, 0x29, 0xB6}; 32 33 #define BITv(B,n) ((B >> n) & 1) 34 #define BYTE(B7,B6,B5,B4,B3,B2,B1,B0) ((B7 << 7) | (B6 << 6) | (B5 << 5) | (B4 << 4) | (B3 << 3) | (B2 << 2) | (B1 << 1) | B0) 35 36 #ifdef DO_TRACE 37 #define TRACE(pc) if(trace) { \ 38 printf("PC: %04x ", pc); \ 39 for(int iter=0;iter<8;iter++) { \ 40 if(iter>0 && iter%4==0) \ 41 printf(" "); \ 42 printf("%02x", ctx->state[iter]); } \ 43 printf(" "); \ 44 for(int iter=0;iter<8;iter++) { \ 45 if(iter>0 && iter%4==0) \ 46 printf(" "); \ 47 printf("%02x", ctx->cipherblock[iter]); } \ 48 printf(" "); \ 49 for(int iter=0;iter<7;iter++) { \ 50 if(iter>0 && iter%4==0) \ 51 printf(" "); \ 52 printf("%02x", ctx->ctrlvar[iter]); } \ 53 printf("\n");} 54 #else 55 #define TRACE(pc) ; 56 #endif // DO_TRACE 57 58 static uint8_t assign_bit(const uint8_t dst, const int bit, const int pos) { 59 return (dst & ~(1U << pos)) | (bit << pos); 60 } 61 62 static inline uint8_t map_sbox(const int i, const uint8_t in, const uint8_t hi_nibble) { 63 return SBOX[(i*16) + (in & 0xf)] & (0xf << (4 * hi_nibble)); 64 } 65 66 static inline uint8_t rrc(const uint8_t val, const uint8_t cf_in, uint8_t *cf_out) { 67 *cf_out = val & 1; 68 return (cf_in << 7) | (val >> 1); 69 } 70 71 void sbt_core(uint8_t state[8], uint8_t msgkey[7], uint8_t cipherblock[8]) { // fn_1d20 72 // main function doing the dance called only from sbt_full() and sbt_short() 73 // short: sbt(0x7f44, 0x30); 74 // full: sbt(0x7f41, 0x2d); 75 76 uint8_t cf = 0; 77 uint8_t tmp, tmp1; 78 79 // step 1 - initial fill - LFSR (1 + x^32 + x^63) 64 steps 80 for(int i = 0; i<8; i++) { 81 tmp = (state[0] ^ state[4]) >> 1 | (state[1] ^ state[5]) << 7; 82 memmove(state,state+1, 7); 83 state[7]=tmp; 84 } // 1d3c 85 86 // step 2 - fixed bit permutation 87 cipherblock[0] = BYTE(BITv(state[4],4),BITv(state[1],5),BITv(state[3],1),BITv(state[7],6),BITv(state[0],5),BITv(state[6],0),BITv(state[5],7),BITv(state[2],3)); 88 cipherblock[1] = BYTE(BITv(state[3],2),BITv(state[0],7),BITv(state[7],1),BITv(state[1],0),BITv(state[6],3),BITv(state[4],5),BITv(state[5],4),BITv(state[2],0)); 89 cipherblock[2] = BYTE(BITv(state[7],5),BITv(state[3],3),BITv(state[1],3),BITv(state[5],1),BITv(state[0],3),BITv(state[2],4),BITv(state[6],2),BITv(state[4],1)); 90 cipherblock[3] = BYTE(BITv(state[5],5),BITv(state[3],0),BITv(state[0],1),BITv(state[4],3),BITv(state[1],6),BITv(state[6],7),BITv(state[2],2),BITv(state[7],3)); 91 cipherblock[4] = BYTE(BITv(state[2],5),BITv(state[6],4),BITv(state[4],7),BITv(state[0],6),BITv(state[5],6),BITv(state[7],7),BITv(state[3],5),BITv(state[1],2)); 92 cipherblock[5] = BYTE(BITv(state[6],5),BITv(state[4],2),BITv(state[3],6),BITv(state[5],2),BITv(state[1],7),BITv(state[2],6),BITv(state[7],4),BITv(state[0],2)); 93 cipherblock[6] = BYTE(BITv(state[5],0),BITv(state[7],2),BITv(state[1],4),BITv(state[3],4),BITv(state[4],6),BITv(state[6],1),BITv(state[0],0),BITv(state[2],1)); 94 cipherblock[7] = BYTE(BITv(state[6],6),BITv(state[0],4),BITv(state[1],1),BITv(state[7],0),BITv(state[3],7),BITv(state[2],7),BITv(state[4],0),BITv(state[5],3)); 95 96 // 1e30 97 // main loop 98 uint8_t msgkey_iter_ctrl = 0x9c; // 1e32 99 for(int round = 0; round < 8; round++) { 100 // update control variable 101 for(int i=(msgkey_iter_ctrl & 0x80)?5:2;i!=0; i--) { // 1e35, 1e3b, 1e59 102 // msgkey_iter_ctrl has this binary value: 10011100 so 4x2 103 // and 4x5 iterations 104 cf = BITv(msgkey[3],4); // 1e44 105 for(int j=0; j<7; j++) { 106 msgkey[j] = rrc(msgkey[j], cf, &cf); // 1e4a 107 } // 1e4e 108 msgkey[3] = assign_bit(msgkey[3],cf,3); // 1e57 109 } 110 // rotate msgkey_iter_ctrl left 111 msgkey_iter_ctrl = msgkey_iter_ctrl << 1; // 1e5c .. 1e5f 112 113 // 1e61 .. 1e8e 114 uint8_t box_perm_ctrl_words[4]; 115 for(int i=0;i<4;i++) box_perm_ctrl_words[i] = state[3-i]; 116 // rotate state right 8x 117 tmp = state[7]; 118 memmove(state+1,state,7); 119 state[0]=tmp; 120 121 // 1f1c 122 box_perm_ctrl_words[0] ^= BYTE(BITv(msgkey[1], 5), BITv(msgkey[4], 1), BITv(msgkey[1], 2), BITv(msgkey[5], 6), BITv(msgkey[2], 7), BITv(msgkey[5], 3), BITv(msgkey[2], 4), BITv(msgkey[5], 0)); 123 box_perm_ctrl_words[1] ^= BYTE(BITv(msgkey[2], 1), BITv(msgkey[6], 5), BITv(msgkey[3], 6), BITv(msgkey[6], 2), BITv(msgkey[0], 7), BITv(msgkey[3], 3), BITv(msgkey[0], 4), BITv(msgkey[3], 0)); 124 box_perm_ctrl_words[2] ^= BYTE(BITv(msgkey[0], 1), BITv(msgkey[4], 5), BITv(msgkey[1], 6), BITv(msgkey[4], 2), BITv(msgkey[1], 3), BITv(msgkey[5], 7), BITv(msgkey[1], 0), BITv(msgkey[5], 4)); 125 box_perm_ctrl_words[3] ^= BYTE(BITv(msgkey[2], 5), BITv(msgkey[5], 1), BITv(msgkey[2], 2), BITv(msgkey[6], 6), BITv(msgkey[3], 7), BITv(msgkey[6], 3), BITv(msgkey[3], 4), BITv(msgkey[6], 0)); // 1f2c 126 int box_perm_index = 0; // INTMEM[0x28] 127 128 uint8_t nib, nib2; 129 for(int i = 0; i < 4; i++) { // 1f34 130 uint8_t box_perm_ctrl = box_perm_ctrl_words[i]; // 1f36 131 do { 132 nib = cipherblock[box_perm_index >> 1]; 133 if(!(box_perm_index & 1)) { 134 nib >>= 4; 135 } 136 nib &= 0xf; 137 138 switch(box_perm_ctrl >> 6) { 139 case(0): { 140 if((nib & 0xc) == 0) { // 1f52 141 nib2 = cipherblock[(box_perm_index ^ 8) >> 1]; // 1f60 .. 1f64 142 if(!(box_perm_index & 1)) { 143 // swap nibbles 144 nib2 >>= 4; // 1f6b 145 } 146 nib2 &= 0xf; // 1f6c 147 148 nib = nib + (nib2 & 3); // 1f6f 149 nib = ((nib + (nib2 >> 2)) & 3) | 0xc; // 1f78 .. 1f7e 150 } else { 151 nib -= 4; 152 } 153 break; 154 } 155 case(1): { 156 if((nib & 0x3) == 0) { // 1f94 .. 1f96 157 nib2 = cipherblock[(box_perm_index ^ 2) >> 1]; 158 if(!(box_perm_index & 1)) { 159 nib2 >>= 4; // 1fb3 160 } 161 nib2 &= 0xf; // 1fb4 162 163 nib >>= 2; // 1fa2 .. 1fa6 164 nib = nib + (nib2 & 3); // 1fb7, 1fbb 165 nib = (((nib + (nib2>>2)) & 3) << 2) | 3; // .. 1fc8 166 } else { 167 nib-=1; // 1f98 .. 1f9d 168 } 169 break; 170 } 171 case(2): { 172 if((nib & 0xc) == 0xc) { // 1fde .. 1fe0 173 nib2 = cipherblock[(box_perm_index ^ 4) >> 1]; // 1fe9 .. 1ff1 174 if(!(box_perm_index & 1)) { 175 nib2 >>= 4; // 1ff4 176 } 177 nib2 &= 0xf; // 1ff5 178 179 nib &= 3; // 1fe3 .. 1fe7 180 nib = nib + (nib2 & 3); // 1ff8, 1fbb 181 nib = (((nib + (nib2>> 2))) & 3); // 1ffe .. 2005 182 } else { 183 nib += 4; // 200a .. 200e 184 } 185 break; 186 } 187 default: { 188 if((nib & 3) == 3) { // 2021 .. 2023 189 nib2 = cipherblock[(box_perm_index ^ 1) >> 1]; // .. 202e..2036 190 if(box_perm_index & 1) { 191 nib2 >>= 4; // 2039 192 } 193 nib2 &= 0xf; // 203a 194 195 nib >>= 2; // 202c 196 nib = nib + (nib2 & 3); // 203d, 2041 197 nib = ((nib + (nib2>>2)) & 3) << 2; // 2043 .. 204c 198 } else { 199 nib++; 200 } 201 break; 202 } 203 } 204 tmp = cipherblock[box_perm_index >> 1]; // 2058 205 if(!(box_perm_index & 1)) { 206 tmp &= 0xf; 207 nib <<= 4; 208 } else { 209 tmp &= 0xf0; // 2063 .. 210 } 211 tmp |= nib; 212 cipherblock[box_perm_index >> 1] = tmp; // 2068 .. 2069 213 box_perm_ctrl = (box_perm_ctrl << 2) | (box_perm_ctrl >> 6); // 2072 .. 2076 214 } while((++box_perm_index & 3) != 0); 215 } 216 217 // step 6. fix byte permutation 218 tmp = cipherblock[0]; // 2087 .. 219 cipherblock[0] = cipherblock[3]; 220 cipherblock[3] = cipherblock[4]; 221 cipherblock[4] = cipherblock[6]; 222 cipherblock[6] = cipherblock[7]; 223 cipherblock[7] = cipherblock[2]; 224 cipherblock[2] = cipherblock[1]; 225 cipherblock[1] = cipherblock[5]; 226 cipherblock[5] = tmp; // .. 2097 227 228 // step 8 nibble switch 229 tmp = BYTE(BITv(msgkey[3], 5), BITv(msgkey[6], 1), BITv(msgkey[0], 6), BITv(msgkey[3], 2), 230 BITv(msgkey[0], 3), BITv(msgkey[4], 7), BITv(msgkey[0], 0), BITv(msgkey[4], 4)); 231 for(int i = 0; i < 8; i++, tmp >>= 1) { // 20c3, 20cc, 20cb 232 if(tmp & 1) { 233 // swap nibbles 234 cipherblock[i] = (cipherblock[i] << 4) | (cipherblock[i] >> 4); // 20c9 235 } 236 } 237 // step 10. SBOXes 238 for(int i = 0; i < 8; i++) { 239 tmp1 = map_sbox(i,cipherblock[i],0); 240 tmp = cipherblock[i]; 241 cipherblock[i] = tmp1; // 20da 242 cipherblock[i] |= map_sbox(i,tmp >> 4,1); 243 } 244 } 245 } 246 247 uint8_t sbt_crypt_byte(sbt_ctx *ctx, uint8_t res) { // 1cf5 248 // entry point 249 // called from: 1b77 1bea 2368 247a 261b 2731 250 //printf("\t%02x ^ %02x(%d) = %02x\n", res, cipherblock[cipherblock_idx], cipherblock_idx, res ^ cipherblock[/*r1*/cipherblock_idx]); 251 res ^= ctx->cipherblock[/*r1*/ctx->cipherblock_idx++]; 252 if(ctx->cipherblock_idx == 8) { 253 sbt_core(ctx->state, ctx->ctrlvar, ctx->cipherblock); 254 //dump(ctx->cipherblock, sizeof(ctx->cipherblock), "cb: "); 255 ctx->cipherblock_idx=0; 256 } 257 return res; 258 } 259 260 static void sbt_init(sbt_ctx *ctx, const uint8_t *nonce, const uint8_t *key) { 261 // only called from sbt_set_key() 262 // preliminary fill = key[:8] ^ intmem[0x2d:0x30] 263 //for(i=0x2d;i<0x35;i++, ptr++) { 264 for(int i=0;i<8;i++) { 265 if(i<3) { 266 ctx->cipherblock[i] ^= key[i]; // 1c91 267 } else { 268 ctx->cipherblock[i]= key[i]; 269 } 270 } // 1c98 271 272 // preliminary control (56 bits) = key[8:] 273 memcpy(ctx->ctrlvar, key+8, 7); // 1c9f 274 TRACE(0x1ca2); 275 276 // preserve preliminary fill 277 memcpy(ctx->state, ctx->cipherblock, 8); // 1cab 278 TRACE(0x1cae); 279 280 sbt_core(ctx->state, ctx->ctrlvar, ctx->cipherblock); 281 TRACE(0x1cb1); 282 283 // hard coded fixed fill at 0x2c5c 284 uint8_t fixed_fill[8] = { 0xf5, 0xc0, 0x7a, 0x10, 0x8a, 0xaf, 0x17, 0xcf }; 285 286 // output of sbt_full becomes control variable 287 memcpy(ctx->ctrlvar, ctx->cipherblock, 7); 288 // initial fill becomes fixed_fill 289 memcpy(ctx->cipherblock, fixed_fill, 8); // 1cbf, 1cc4 290 TRACE(0x1cc2); 291 292 // 0x7f41 also becomes fixed fill 293 memcpy(ctx->state, ctx->cipherblock, 8); 294 TRACE(0x1cd1) 295 296 //dump(ctx->ctrlvar, sizeof(ctx->ctrlvar), "cv: "); 297 sbt_core(ctx->state, ctx->ctrlvar, ctx->cipherblock); 298 //dump(ctx->cipherblock, sizeof(ctx->cipherblock), "cb: "); 299 TRACE(0x1cd4); 300 301 //memcpy(INTMEM + 0x25, nonce,3); 302 ctx->cipherblock_idx=0; 303 memcpy(ctx->state + 5, nonce, 3); 304 TRACE(0x1cf4) 305 } 306 307 void sbt_set_key(sbt_ctx *ctx, uint8_t *nonce, const uint8_t *key) { // 1c6f 308 // entry point 309 // called from 1b42, 1bc3, 2362, 25d6 310 // input is dptr, flag is passed in the carry flag of the psw 311 // push input // 1c6f .. 1c71 312 memcpy(ctx->cipherblock, nonce, 3); 313 sbt_init(ctx, nonce, key); 314 } 315 316 void sbt_decrypt(uint8_t *ct, const uint8_t *key) { 317 sbt_ctx ctx; 318 319 uint8_t tmp, r2, r3; 320 uint8_t tbit, CY; 321 int dptr = 0; 322 do { 323 for(int i=6;i>0;i--) { 324 tmp = ct[dptr]; 325 if(tmp == 0xfe) continue; 326 dptr++; 327 if(i==1 && tmp!=' ') { 328 printf("ERROR IN TEXT, PRESS LEFT ARROW!\n"); 329 printf("dptr: %x, %c (%02x)\n", dptr, 0x40 | tmp, tmp); 330 return; 331 } 332 } 333 } while(ct[dptr]!=0xfe); 334 335 sbt_set_key(&ctx, ct, key); 336 337 dptr = 6; // skip first block which is a nonce 338 // see scramble.py for how the bits of *dptr and *intmem[4a..4c] are processed before output 339 // unscrambles bits 340 uint8_t buf[3]; 341 do { 342 uint8_t r0 = 0; 343 for(r2 = 5; r2>0; r2--) { 344 tmp = ct[dptr]; // 1b58 345 CY=tmp<0xfe; // set carry due to CJNE at 1b59 346 if(tmp!=0xfe) dptr++; 347 tmp--; // 1b5f dec a 348 tmp = (tmp << 4) | (tmp >> 4); // 1b60 swap a 349 for(r3 = 4;r3>0;r3--) { 350 // 1b61 rlc a 351 tbit=CY; 352 CY=tmp & 0x80; 353 tmp=(tmp<<1) | tbit; 354 // 1b62 xchg A, INTMEM[r0] 355 uint8_t tmp1 = tmp; 356 tmp=buf[r0]; 357 buf[r0]=tmp1; 358 // 1b63 rrc a 359 tbit = CY; 360 CY = tmp & 1; 361 tmp = tbit | (tmp >> 1); 362 // 1b64 xchg a, intmem[r0] 363 tmp1 = tmp; 364 tmp=buf[r0]; 365 buf[r0]=tmp1; 366 r0++; 367 CY=r0<3; 368 if(r0==3) r0=0; 369 } 370 } 371 for(r0 = 0;r0!=3;r0++) { 372 tmp = buf[r0]; // 1b71 373 CY=r0<2; 374 if(r0==2) { 375 // 1b75 rrc a 376 tbit=CY; 377 CY=tmp&1; 378 tmp = (tbit << 7) | (tmp >> 1); 379 } 380 381 // 1b76 rrc a 382 tbit=CY; 383 CY=tmp&1; 384 tmp = (tbit << 7) | (tmp >> 1); 385 //printf("%d, ", tmp & 0x3f); 386 tmp = sbt_crypt_byte(&ctx, tmp); 387 388 tmp &= 0x3f; // 1b7a 389 printf("%c", (tmp<32)?(0x40|tmp):tmp); 390 } 391 } while (ct[dptr++]!=0xfe && ct[dptr]!=' ' && ct[dptr]!=0xfe); 392 printf("\n"); 393 } 394 395 void sbt_encrypt(const uint8_t *plaintext, const uint8_t *key, const uint8_t prevcb0[5], uint8_t *output) { 396 sbt_ctx ctx; 397 // skip_print = print_output_query(); 398 uint8_t tmp; 399 int optr=0; 400 401 // get 5 values [1..16] by xoring what is in ram 402 // with the value of the 8bit reloading TL0 timer 403 // this is like a "nonce/iv" but quite predictable 404 // since this loop is static, if there are no interrupts 405 // then TL0 increases by 11 in each iteration. 406 // unless there are interrupts... 407 // see also emu-timer-1ba8.py 408 409 // the following are "nonces" from original hw 410 // BAMLK HCAMM EGLLA LEEIC JDMNJ 411 // only the bottom nibble is "random" the top nibble is all zero 412 413 uint8_t nonce[5]={0}; 414 uint16_t dptr = 0; 415 uint8_t TL0 = 0; 416 if(prevcb0 != NULL) { 417 memcpy(nonce, prevcb0, 5); 418 } 419 for(int i = 0; i < 5; i++, dptr++, TL0+=15) { 420 tmp = TL0; 421 tmp = (nonce[dptr] ^ tmp) & 0xf; 422 tmp = tmp + 1; 423 nonce[dptr] = tmp; 424 //printf("%c", 0x40|tmp); //putc_maybe_print(tmp,skip_print); 425 output[optr++]=0x40|tmp; 426 } 427 //printf(" "); //putc_maybe_print(' ',skip_print); 428 output[optr++]=' '; 429 sbt_set_key(&ctx, nonce,key); 430 //dump(ctx.cipherblock, 8, "cb0"); 431 432 //copy result of sbt_set_key to 0x72d2 433 memcpy(nonce, ctx.cipherblock, 5); //1bc6..1bcf 434 435 uint8_t tbit, CY; 436 dptr = 0; 437 // see sketchy.py for how the bits of *dptr and *intmem[4a..4c] are processed before ouptut 438 uint8_t buf[3]={0}; 439 while(plaintext[dptr]!=0xfe) { 440 for(uint8_t r0 = 0;r0<3;r0++) { 441 tmp = plaintext[dptr]; 442 if(tmp == 0xfe) { 443 tmp = 0x5f; 444 } else { 445 dptr++; 446 } 447 tmp = sbt_crypt_byte(&ctx,tmp); 448 buf[r0] = tmp; 449 } 450 // scramble output for transmission 451 // expands every 3 "bytes" - really only the lower 6 bits / byte 452 // into 5 char groups also using only 6 bits 453 uint8_t r0 = 0; 454 CY = 0; // the cjne at 1bef clears CY due to r0==0x4d 455 for(uint8_t r2 = 5; r2>0; r2--) { 456 tmp = 0; // 1bf8 457 for(uint8_t r3 = 4;r3>0;r3--) { 458 // 1bf9 xchg a, intmem[r0] 459 uint8_t tmp1 = tmp; 460 tmp=buf[r0]; 461 buf[r0]=tmp1; 462 463 // 1bfa rrc a 464 tbit = CY; 465 CY = tmp & 1; 466 tmp = tbit | (tmp >> 1); 467 468 // 1bfb xchg a, intmem[r0] 469 tmp1 = tmp; 470 tmp=buf[r0]; 471 buf[r0]=tmp1; 472 473 // 1bfc rlc a 474 tbit=CY; 475 CY=tmp & 0x80; 476 tmp=(tmp<<1) | tbit; 477 478 if(++r0 == 3) r0 = 0; 479 } 480 tmp++; 481 //printf("%c", 0x40|tmp); // really putc_maybe_print() 482 output[optr++]=0x40|tmp; 483 //output[optr++]=tmp; 484 } 485 //printf(" "); // really putc_maybe_print(' ') 486 output[optr++]=' '; 487 } 488 output[optr++]=0xfe; 489 }