/ attacks / bruteforce.c
bruteforce.c
  1  // run with gcc -Wall -g -o bruteforce ../sbt.c bruteforce.c && ./bruteforce
  2  
  3  #include "../sbt.h"
  4  #include <stdint.h>
  5  #include <string.h>
  6  #include <stdio.h>
  7  #include <stdarg.h>
  8  
  9  void dump(const uint8_t *p, const size_t len, const char* msg, ...) {
 10    va_list args;
 11    va_start(args, msg);
 12    vfprintf(stdout,msg, args);
 13    va_end(args);
 14    fprintf(stdout," ");
 15    for(size_t i=0;i<len;i++)
 16      fprintf(stdout,"%02x", p[i]);
 17    fprintf(stdout,"\n");
 18  }
 19  
 20  static int check(const uint8_t *ct, const size_t len, const int last, const uint8_t *cb) {
 21    const uint8_t validchars[0x40] = {
 22      0, 1, 1, 1, 1, 1, 1, 1,
 23      1, 1, 1, 1, 1, 1, 1, 1,
 24      1, 1, 1, 1, 1, 1, 1, 1,
 25      1, 1, 1, 0, 0, 0, 0, 0,
 26      1, 0, 0, 0, 0, 0, 0, 0,
 27      0, 0, 0, 0, 1, 1, 1, 0,
 28      1, 1, 1, 1, 1, 1, 1, 1,
 29      1, 1, 0, 0, 0, 0, 0, 0};
 30    for(unsigned i=0;i<8 && i<len;i++) {
 31      uint8_t pt=(ct[i]^cb[i]) & 0x3f;
 32      if(!validchars[pt] && !(last && i>=len-2 && pt==0x1f)) return 0;
 33    }
 34    return 1;
 35  }
 36  
 37  void test_enc(void) {
 38    const uint8_t __attribute__((nonstring)) key[15]="\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
 39    uint8_t __attribute__((nonstring)) plaintext[11]="2PADDING..\xfe";
 40    uint8_t out[((sizeof(plaintext) / 3) + 1) * 6 + 6 + 1]={0};
 41    int i;
 42    for(i=0;plaintext[i]!=0xfe;i++) {
 43      plaintext[i]=(plaintext[i] & 0x3f);
 44    }
 45    //uint8_t prevcb0[5]={0xe6, 0x3c, 0x32, 0x65, 0x9a};
 46    uint8_t prevcb0[5]={0x24, 0x40, 0xe3, 0x5e, 0x2f};
 47    sbt_encrypt(plaintext, key, prevcb0, out);
 48    printf("%s\n",out);
 49  
 50    for(i=0;out[i]!=0xfe;i++) {
 51      out[i]=(out[i] & 0x3f);
 52    }
 53    sbt_decrypt(out, key);
 54  }
 55  
 56  int main(void) {
 57    // known test vector validation
 58    const uint8_t __attribute__((nonstring)) key[15]="\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
 59    const uint8_t __attribute__((nonstring)) tv[]="BAMLK GAFFJ EOBCP EEIMP CDAFP\xfe";
 60    uint8_t ctx[sizeof tv-1]={0};
 61    int i;
 62    for(i=0;tv[i]!=0xfe;i++) {
 63      ctx[i]=(tv[i] & 0x3f);
 64    }
 65    ctx[i]=tv[i];
 66    dump(ctx, sizeof ctx, "ct");
 67    sbt_decrypt(ctx, key);
 68  
 69    test_enc();
 70    // testing ct length 1..16, how it decrypts, due to the scrambling,
 71    // it gets always padded to multiples of 3 by appending 1 or 2 '_'
 72    //for(int i=1;i<17;i++) {
 73    //   uint8_t plaintext[17]="\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe";
 74    //   for(int j=0;j<i;j++) plaintext[j]=(j+1);
 75    //   uint8_t out[((i / 3) + 1) * 6 + 6 + 2];
 76    //   dump(plaintext, i+1, "pt");
 77    //   encrypt(plaintext, key, out);
 78    //   out[sizeof out -1] = 0;
 79    //   fprintf(stderr,"ct: %s\n", out);
 80    //   for(int j=0;out[j]!=0xfe;j++) {
 81    //     out[j]=(out[j] & 0x3f);
 82    //   }
 83    //   decrypt(out, key);
 84    //}
 85    //return 0;
 86  
 87    const uint8_t nonce[3]={2,1,0xd};
 88    const uint8_t ciphertext[] = {40, 49, 9, 4, 35, 58, 16, 49,
 89                                  38, 36, 52, 33};
 90    unsigned long finds=0;
 91    for(unsigned long long candidate=0;candidate < (1UL<<32);candidate++) {
 92      if(candidate % (1UL<<24) == 0) {
 93        fprintf(stderr, "candidate %llx found so far: %ld\n", candidate, finds);
 94      }
 95      uint8_t state[8] = { 0xf5, 0xc0, 0x7a, 0x10, 0x8a, 0xaf, 0x17, 0xcf },
 96        msgkey[7] = {0x19, 0xbe, 0xa3, 0x03, 0x59, 0x51, 0xf5},
 97        cipherblock[8];
 98  
 99      uint8_t pt[sizeof ciphertext + 1]={0};
100  
101      //msgkey[0] = candidate & 0xff;
102      msgkey[0] = candidate >> 24;
103      msgkey[1] = candidate >> 16;
104      msgkey[2] = candidate >> 8;
105      msgkey[3] = candidate & 0xff;
106  
107      unsigned blockctr = 0;
108      int found=1;
109      do {
110         sbt_core(state,msgkey,cipherblock);
111         if(check(ciphertext + (blockctr*8), sizeof(ciphertext) - (8*blockctr), blockctr == sizeof(ciphertext)/8, cipherblock)==0) {
112           found=0;
113           break;
114         }
115         //dump(state, sizeof state, "state");
116         //dump(msgkey, sizeof msgkey, "msgkey is valid");
117         //state bfb7b6ef1a8c5090
118         //msgkey f5c07a108aaf17
119         for(unsigned i=0;i<8 && i < (sizeof(ciphertext) - (8*blockctr));i++) {
120           uint8_t tmp = ((ciphertext[i+blockctr*8]^cipherblock[i]) & 0x3f);
121           //fprintf(stderr, "%c", (tmp<32)?(0x40|tmp):tmp);
122           pt[blockctr*8 + i]=(tmp<32)?(0x40|tmp):tmp;
123         }
124         if(blockctr==0) {
125           memcpy(state + 5, nonce, 3);
126         }
127      } while(blockctr++ < sizeof(ciphertext)/8);
128      if(found) {
129        finds++;
130        printf("%s", pt);
131        dump(msgkey,7, " cv");
132      }
133    }
134    fprintf(stderr, "total finds %ld\n", finds);
135    return 0;
136  }