cryptorf: style

This commit is contained in:
Philippe Teuwen 2020-08-19 22:19:46 +02:00
parent a76596c3fe
commit b134753a08
9 changed files with 1703 additions and 1498 deletions

View file

@ -33,14 +33,12 @@ typedef enum {
int counter = 0; int counter = 0;
static uint8_t nibbles_to_byte(nibble b0, nibble b1) static uint8_t nibbles_to_byte(nibble b0, nibble b1) {
{
// Combine both nibbles // Combine both nibbles
return ((b0 << 4) | b1); return ((b0 << 4) | b1);
} }
static uint8_t funny_mod(uint8_t a, uint8_t m) static uint8_t funny_mod(uint8_t a, uint8_t m) {
{
// Just return the input when this is less or equal than the modular value // Just return the input when this is less or equal than the modular value
if (a < m) return a; if (a < m) return a;
@ -51,8 +49,7 @@ static uint8_t funny_mod(uint8_t a, uint8_t m)
return (a == 0) ? m : a; return (a == 0) ? m : a;
} }
static uint8_t bit_rotate_left(uint8_t a, uint8_t n_bits) static uint8_t bit_rotate_left(uint8_t a, uint8_t n_bits) {
{
// Rotate value a with the length of n_bits only 1 time // Rotate value a with the length of n_bits only 1 time
uint8_t mask = (1 << n_bits) - 1; uint8_t mask = (1 << n_bits) - 1;
return ((a << 1) | (a >> (n_bits - 1))) & mask; return ((a << 1) | (a >> (n_bits - 1))) & mask;
@ -92,8 +89,7 @@ static void reconstruct_nibbles(crypto_state s)
s->b1 |= s->b1r & s->b1s; s->b1 |= s->b1r & s->b1s;
} }
*/ */
static void next_left(uint8_t in, crypto_state s) static void next_left(uint8_t in, crypto_state s) {
{
uint8_t b3, b6, bx; uint8_t b3, b6, bx;
// Update the left cipher state with the input byte // Update the left cipher state with the input byte
@ -113,8 +109,7 @@ static void next_left(uint8_t in, crypto_state s)
s->b1l = ((bx ^ b3) & 0x0f); s->b1l = ((bx ^ b3) & 0x0f);
} }
static void next_right(uint8_t in, crypto_state s) static void next_right(uint8_t in, crypto_state s) {
{
uint8_t b16, b18, bx; uint8_t b16, b18, bx;
// Update the right cipher state with the input byte // Update the right cipher state with the input byte
@ -134,8 +129,7 @@ static void next_right(uint8_t in, crypto_state s)
s->b1r = ((bx ^ b16) & 0x0f); s->b1r = ((bx ^ b16) & 0x0f);
} }
static void next_middle(uint8_t in, crypto_state s) static void next_middle(uint8_t in, crypto_state s) {
{
uint8_t b12, b13, bx; uint8_t b12, b13, bx;
// Update the middle cipher state with the input byte // Update the middle cipher state with the input byte
@ -155,8 +149,7 @@ static void next_middle(uint8_t in, crypto_state s)
s->b1s = bx & 0x0f; s->b1s = bx & 0x0f;
} }
static void next(const bool feedback, uint8_t in, crypto_state s) static void next(const bool feedback, uint8_t in, crypto_state s) {
{
// Initialize the (optional) input parameter // Initialize the (optional) input parameter
uint8_t a = in; uint8_t a = in;
@ -183,14 +176,12 @@ static void next(const bool feedback, uint8_t in, crypto_state s)
s->b1 |= s->b1r & s->b1s; s->b1 |= s->b1r & s->b1s;
} }
static void next_n(const bool feedback, size_t n, uint8_t in, crypto_state s) static void next_n(const bool feedback, size_t n, uint8_t in, crypto_state s) {
{
// While n-rounds left, shift the cipher // While n-rounds left, shift the cipher
while (n--) next(feedback, in, s); while (n--) next(feedback, in, s);
} }
static void initialize(const bool feedback, const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, const size_t n, crypto_state s) static void initialize(const bool feedback, const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, const size_t n, crypto_state s) {
{
size_t pos; size_t pos;
// Reset the cipher state // Reset the cipher state
@ -211,14 +202,12 @@ static void initialize(const bool feedback, const uint8_t *Gc, const uint8_t *Ci
} }
} }
static uint8_t cm_byte(crypto_state s) static uint8_t cm_byte(crypto_state s) {
{
// Construct keystream byte by combining both nibbles // Construct keystream byte by combining both nibbles
return nibbles_to_byte(s->b0, s->b1); return nibbles_to_byte(s->b0, s->b1);
} }
static uint8_t sm_byte(crypto_state s) static uint8_t sm_byte(crypto_state s) {
{
uint8_t ks; uint8_t ks;
// Construct keystream byte by combining 2 parts from 4 nibbles // Construct keystream byte by combining 2 parts from 4 nibbles
@ -230,8 +219,7 @@ static uint8_t sm_byte(crypto_state s)
return ks; return ks;
} }
void print_crypto_state(const char *text, crypto_state s) void print_crypto_state(const char *text, crypto_state s) {
{
int pos; int pos;
printf("%s", text); printf("%s", text);
@ -250,8 +238,7 @@ void print_crypto_state(const char *text, crypto_state s)
printf("\n"); printf("\n");
} }
void sm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch, uint8_t *Ci_1, crypto_state s) void sm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch, uint8_t *Ci_1, crypto_state s) {
{
size_t pos; size_t pos;
initialize(false, Gc, Ci, Q, 1, s); initialize(false, Gc, Ci, Q, 1, s);
@ -263,8 +250,7 @@ void sm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch
} }
} }
void cm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch, uint8_t *Ci_1, uint8_t *Ci_2, crypto_state s) void cm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch, uint8_t *Ci_1, uint8_t *Ci_2, crypto_state s) {
{
size_t pos; size_t pos;
initialize(true, Gc, Ci, Q, 3, s); initialize(true, Gc, Ci, Q, 3, s);
@ -294,8 +280,7 @@ void cm_auth(const uint8_t *Gc, const uint8_t *Ci, const uint8_t *Q, uint8_t *Ch
next_n(true, 3, 0, s); next_n(true, 3, 0, s);
} }
static void cm_crypt(const CryptoAction ca, const uint8_t offset, const uint8_t len, const uint8_t *in, uint8_t *out, crypto_state s) static void cm_crypt(const CryptoAction ca, const uint8_t offset, const uint8_t len, const uint8_t *in, uint8_t *out, crypto_state s) {
{
size_t pos; size_t pos;
uint8_t bt; uint8_t bt;
@ -322,32 +307,27 @@ static void cm_crypt(const CryptoAction ca, const uint8_t offset, const uint8_t
} }
} }
void cm_encrypt(const uint8_t offset, const uint8_t len, const uint8_t *ct, uint8_t *pt, crypto_state s) void cm_encrypt(const uint8_t offset, const uint8_t len, const uint8_t *ct, uint8_t *pt, crypto_state s) {
{
next_n(true, 5, 0, s); next_n(true, 5, 0, s);
next(true, 0, s); next(true, 0, s);
cm_crypt(CA_ENCRYPT, offset, len, ct, pt, s); cm_crypt(CA_ENCRYPT, offset, len, ct, pt, s);
} }
void cm_decrypt(const uint8_t offset, const uint8_t len, const uint8_t *ct, uint8_t *pt, crypto_state s) void cm_decrypt(const uint8_t offset, const uint8_t len, const uint8_t *ct, uint8_t *pt, crypto_state s) {
{
next_n(true, 5, 0, s); next_n(true, 5, 0, s);
next(true, 0, s); next(true, 0, s);
cm_crypt(CA_DECRYPT, offset, len, ct, pt, s); cm_crypt(CA_DECRYPT, offset, len, ct, pt, s);
} }
void cm_grind_read_system_zone(const uint8_t offset, const uint8_t len, const uint8_t *pt, crypto_state s) void cm_grind_read_system_zone(const uint8_t offset, const uint8_t len, const uint8_t *pt, crypto_state s) {
{
cm_crypt(CA_ENCRYPT, offset, len, pt, NULL, s); cm_crypt(CA_ENCRYPT, offset, len, pt, NULL, s);
} }
void cm_grind_set_user_zone(const uint8_t zone, crypto_state s) void cm_grind_set_user_zone(const uint8_t zone, crypto_state s) {
{
next(true, zone, s); next(true, zone, s);
} }
void cm_mac(uint8_t *mac, crypto_state s) void cm_mac(uint8_t *mac, crypto_state s) {
{
next_n(true, 10, 0, s); next_n(true, 10, 0, s);
if (mac) if (mac)
mac[0] = cm_byte(s); mac[0] = cm_byte(s);
@ -357,8 +337,7 @@ void cm_mac(uint8_t *mac, crypto_state s)
mac[1] = cm_byte(s); mac[1] = cm_byte(s);
} }
void cm_password(const uint8_t *pt, uint8_t *ct, crypto_state s) void cm_password(const uint8_t *pt, uint8_t *ct, crypto_state s) {
{
for (size_t pos = 0; pos < 3; pos++) { for (size_t pos = 0; pos < 3; pos++) {
next_n(true, 5, pt[pos], s); next_n(true, 5, pt[pos], s);
ct[pos] = cm_byte(s); ct[pos] = cm_byte(s);

View file

@ -0,0 +1,222 @@
#include "cryptolib.h"
static byte_t rotate5_lut[] = {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f, 0x02, 0x02, 0x06, 0x06, 0x0a, 0x0a, 0x0e, 0x0e, 0x12, 0x12, 0x16, 0x16, 0x1a, 0x1a, 0x1e, 0x1e, 0x03, 0x03, 0x07, 0x07, 0x0b, 0x0b, 0x0f, 0x0f, 0x13, 0x13, 0x17, 0x17, 0x1b, 0x1b, 0x1f, 0x1f, 0x04, 0x06, 0x04, 0x06, 0x0c, 0x0e, 0x0c, 0x0e, 0x14, 0x16, 0x14, 0x16, 0x1c, 0x1e, 0x1c, 0x1e, 0x05, 0x07, 0x05, 0x07, 0x0d, 0x0f, 0x0d, 0x0f, 0x15, 0x17, 0x15, 0x17, 0x1d, 0x1f, 0x1d, 0x1f, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x16, 0x16, 0x16, 0x16, 0x1e, 0x1e, 0x1e, 0x1e, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x1f, 0x1f, 0x1f, 0x1f, 0x08, 0x0a, 0x0c, 0x0e, 0x08, 0x0a, 0x0c, 0x0e, 0x18, 0x1a, 0x1c, 0x1e, 0x18, 0x1a, 0x1c, 0x1e, 0x09, 0x0b, 0x0d, 0x0f, 0x09, 0x0b, 0x0d, 0x0f, 0x19, 0x1b, 0x1d, 0x1f, 0x19, 0x1b, 0x1d, 0x1f, 0x0a, 0x0a, 0x0e, 0x0e, 0x0a, 0x0a, 0x0e, 0x0e, 0x1a, 0x1a, 0x1e, 0x1e, 0x1a, 0x1a, 0x1e, 0x1e, 0x0b, 0x0b, 0x0f, 0x0f, 0x0b, 0x0b, 0x0f, 0x0f, 0x1b, 0x1b, 0x1f, 0x1f, 0x1b, 0x1b, 0x1f, 0x1f, 0x0c, 0x0e, 0x0c, 0x0e, 0x0c, 0x0e, 0x0c, 0x0e, 0x1c, 0x1e, 0x1c, 0x1e, 0x1c, 0x1e, 0x1c, 0x1e, 0x0d, 0x0f, 0x0d, 0x0f, 0x0d, 0x0f, 0x0d, 0x0f, 0x1d, 0x1f, 0x1d, 0x1f, 0x1d, 0x1f, 0x1d, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f};
static byte_t rotate7_lut[] = {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x3d, 0x3f, 0x41, 0x43, 0x45, 0x47, 0x49, 0x4b, 0x4d, 0x4f, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65, 0x67, 0x69, 0x6b, 0x6d, 0x6f, 0x71, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, 0x7f, 0x02, 0x02, 0x06, 0x06, 0x0a, 0x0a, 0x0e, 0x0e, 0x12, 0x12, 0x16, 0x16, 0x1a, 0x1a, 0x1e, 0x1e, 0x22, 0x22, 0x26, 0x26, 0x2a, 0x2a, 0x2e, 0x2e, 0x32, 0x32, 0x36, 0x36, 0x3a, 0x3a, 0x3e, 0x3e, 0x42, 0x42, 0x46, 0x46, 0x4a, 0x4a, 0x4e, 0x4e, 0x52, 0x52, 0x56, 0x56, 0x5a, 0x5a, 0x5e, 0x5e, 0x62, 0x62, 0x66, 0x66, 0x6a, 0x6a, 0x6e, 0x6e, 0x72, 0x72, 0x76, 0x76, 0x7a, 0x7a, 0x7e, 0x7e, 0x03, 0x03, 0x07, 0x07, 0x0b, 0x0b, 0x0f, 0x0f, 0x13, 0x13, 0x17, 0x17, 0x1b, 0x1b, 0x1f, 0x1f, 0x23, 0x23, 0x27, 0x27, 0x2b, 0x2b, 0x2f, 0x2f, 0x33, 0x33, 0x37, 0x37, 0x3b, 0x3b, 0x3f, 0x3f, 0x43, 0x43, 0x47, 0x47, 0x4b, 0x4b, 0x4f, 0x4f, 0x53, 0x53, 0x57, 0x57, 0x5b, 0x5b, 0x5f, 0x5f, 0x63, 0x63, 0x67, 0x67, 0x6b, 0x6b, 0x6f, 0x6f, 0x73, 0x73, 0x77, 0x77, 0x7b, 0x7b, 0x7f, 0x7f};
static byte_t funny_mod1f_lut[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
static byte_t funny_mod7f_lut[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x01};
typedef enum {
CA_ENCRYPT = 0x01,
CA_DECRYPT = 0x02
} CryptoAction;
int counter = 0;
byte_t nibbles_to_byte(nibble b0, nibble b1) {
// Combine both nibbles
return ((b0 << 4) | b1);
}
byte_t funny_mod(byte_t a, byte_t m) {
// Just return the input when this is less or equal than the modular value
if (a < m) return a;
// Compute the modular value
a %= m;
// Return the funny value, when the output was now zero, return the modular value
return (a == 0) ? m : a;
}
byte_t bit_rotate_left(byte_t a, byte_t n_bits) {
// Rotate value a with the length of n_bits only 1 time
byte_t mask = (1 << n_bits) - 1;
return ((a << 1) | (a >> (n_bits - 1))) & mask;
}
//meltem changed this function to make it perform faster
//to get a better idea of the algorithm check out cryptorf inside the tools directory
void RAMFUNC next(size_t repeat, byte_t in, crypto_state s) {
size_t i = repeat;
byte_t a;
byte_t *cipher_p;
do {
// Construct the cipher update 'a' from (input ^ feedback)
a = in ^ ((s->b0 << 4) | s->b1);
// Shift the cipher state
//left
cipher_p = (byte_t *) &s->l;
cipher_p[5] = cipher_p[5] ^ (a & 0x1f);
s->l = (s->l >> 8);
cipher_p[7] = funny_mod1f_lut[cipher_p[3] + rotate5_lut[cipher_p[0]]];
s->b1l = cipher_p[7] ^ cipher_p[3];
//middle
cipher_p = (byte_t *) &s->m;
cipher_p[3] = cipher_p[3] ^ ((a << 3) | (a >> 5));
s->m = (s->m >> 8);
cipher_p[7] = funny_mod7f_lut[(cipher_p[1] & 0x7f) + rotate7_lut[(cipher_p[0] & 0x7f)]];
s->b1s = cipher_p[7] & 0x0f;
//right
cipher_p = (byte_t *) &s->r;
cipher_p[6] = cipher_p[6] ^ (a >> 3);
s->r = (s->r >> 8);
cipher_p[7] = funny_mod1f_lut[cipher_p[4] + cipher_p[2]];
s->b1r = cipher_p[7] ^ cipher_p[4];
// The nible from b1 shifts to b0
s->b0 = s->b1;
// Construct the new value of nible b1
s->b1 = (s->b1l & 0x0f) & ~(s->b1s);
s->b1 |= s->b1r & s->b1s;
} while (--i);
}
void next_n(size_t n, byte_t in, crypto_state s) {
// While n-rounds left, shift the cipher
while (n--) next(1, in, s);
}
void initialize(const byte_t *Gc, const byte_t *Ci, const byte_t *Q, const size_t n, crypto_state s) {
size_t pos;
// Reset the cipher state
memset(s, 0x00, sizeof(crypto_state_t));
// Load in the ci (tag-nonce), together with the first half of Q (reader-nonce)
for (pos = 0; pos < 4; pos++) {
next(n, Ci[2 * pos ], s);
next(n, Ci[2 * pos + 1], s);
next(1, Q[pos], s);
}
// Load in the diversified key (Gc), together with the second half of Q (reader-nonce)
for (pos = 0; pos < 4; pos++) {
next(n, Gc[2 * pos ], s);
next(n, Gc[2 * pos + 1], s);
next(1, Q[pos + 4], s);
}
}
byte_t cm_byte(crypto_state s) {
// Construct keystream byte by combining both nibbles
return nibbles_to_byte(s->b0, s->b1);
}
void print_crypto_state(const char *text, crypto_state s) {
int pos;
printf("%s", text);
for (pos = 6; pos >= 0; pos--)
printf(" %02x", (byte_t)(s->l >> (pos * 5)) & 0x1f);
printf(" |");
for (pos = 6; pos >= 0; pos--)
printf(" %02x", (byte_t)(s->m >> (pos * 7)) & 0x7f);
printf(" |");
for (pos = 4; pos >= 0; pos--)
printf(" %02x", (byte_t)(s->r >> (pos * 5)) & 0x1f);
printf(" | %02x", cm_byte(s));
printf("\n");
}
void cm_auth(const byte_t *Gc, const byte_t *Ci, const byte_t *Q, byte_t *Ch, byte_t *Ci_1, byte_t *Ci_2, crypto_state s) {
size_t pos;
initialize(Gc, Ci, Q, 3, s);
// Construct the reader-answer (challange)
next(6, 0, s);
Ch[0] = cm_byte(s);
for (pos = 1; pos < 8; pos++) {
next(7, 0, s);
Ch [pos] = cm_byte(s);
}
// Construct the tag-answer (Ci+1 = ff .. .. .. .. .. .. ..)
Ci_1[0] = 0xff;
for (pos = 1; pos < 8; pos++) {
next(2, 0, s);
Ci_1[pos] = cm_byte(s);
}
// Construct the session key (Ci+2)
for (pos = 0; pos < 8; pos++) {
next(2, 0, s);
Ci_2[pos] = cm_byte(s);
}
// Prepare the cipher for encryption by shifting 3 more times
next(3, 0, s);
}
void cm_crypt(const CryptoAction ca, const byte_t offset, const byte_t len, const byte_t *in, byte_t *out, crypto_state s) {
size_t pos;
byte_t bt;
next(5, 0, s);
next(1, offset, s);
next(5, 0, s);
next(1, len, s);
for (pos = 0; pos < len; pos++) {
// Perform the crypto operation
bt = in[pos] ^ cm_byte(s);
// Generate output
if (out) out[pos] = bt;
// Detect where to find the plaintext for loading into cipher state
if (ca == CA_DECRYPT) {
next(1, bt, s);
} else {
next(1, in[pos], s);
}
// Shift the cipher state 5 times
next(5, 0, s);
}
}
void cm_encrypt(const byte_t offset, const byte_t len, const byte_t *ct, byte_t *pt, crypto_state s) {
next(5, 0, s);
next(1, 0, s);
cm_crypt(CA_ENCRYPT, offset, len, ct, pt, s);
}
void cm_decrypt(const byte_t offset, const byte_t len, const byte_t *ct, byte_t *pt, crypto_state s) {
next(5, 0, s);
next(1, 0, s);
cm_crypt(CA_DECRYPT, offset, len, ct, pt, s);
}
void cm_grind_read_system_zone(const byte_t offset, const byte_t len, const byte_t *pt, crypto_state s) {
cm_crypt(CA_ENCRYPT, offset, len, pt, null, s);
}
void cm_grind_set_user_zone(const byte_t zone, crypto_state s) {
next(1, zone, s);
}
void cm_mac(byte_t *mac, crypto_state s) {
next(10, 0, s);
if (mac) mac[0] = cm_byte(s);
next(5, 0, s);
if (mac) mac[1] = cm_byte(s);
}
void cm_password(const byte_t *pt, byte_t *ct, crypto_state s) {
size_t pos;
for (pos = 0; pos < 3; pos++) {
next(5, pt[pos], s);
ct[pos] = cm_byte(s);
}
}

View file

@ -0,0 +1,41 @@
#ifndef _CRYPTOLIB_H_
#define _CRYPTOLIB_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define null 0
typedef unsigned char byte_t;
typedef long long unsigned int ui64;
// A nibble is actually only 4 bits, but there is no such type ;)
typedef byte_t nibble;
typedef struct {
uint64_t l;
uint64_t m;
uint64_t r;
nibble b0;
nibble b1;
nibble b1l;
nibble b1r;
nibble b1s;
} crypto_state_t;
typedef crypto_state_t *crypto_state;
void print_crypto_state(const char *text, crypto_state s);
void cm_auth(const byte_t *Gc, const byte_t *Ci, const byte_t *Q, byte_t *Ch, byte_t *Ci_1, byte_t *Ci_2, crypto_state s);
void cm_encrypt(const byte_t offset, const byte_t len, const byte_t *pt, byte_t *ct, crypto_state s);
void cm_decrypt(const byte_t offset, const byte_t len, const byte_t *ct, byte_t *pt, crypto_state s);
void cm_grind_read_system_zone(const byte_t offset, const byte_t len, const byte_t *pt, crypto_state s);
void cm_grind_set_user_zone(const byte_t zone, crypto_state s);
void cm_mac(byte_t *mac, crypto_state s);
void cm_password(const byte_t *pt, byte_t *ct, crypto_state s);
void RAMFUNC next(size_t repeat, byte_t in, crypto_state s);
#endif // _CRYPTOLIB_H_

View file

@ -26,13 +26,12 @@
#include "cryptolib.h" #include "cryptolib.h"
#include "util.h" #include "util.h"
#ifdef _MSC_VER #ifdef _MSC_VER
// avoid scanf warnings in Visual Studio // avoid scanf warnings in Visual Studio
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#endif #endif
int main(int argc, const char* argv[]) int main(int argc, const char *argv[]) {
{
// Cryptomemory state // Cryptomemory state
crypto_state_t s; crypto_state_t s;
@ -58,38 +57,53 @@ int main(int argc, const char* argv[])
// Show header and help syntax // Show header and help syntax
printf("CryptoMemory simulator - (c) Radboud University Nijmegen\n"); printf("CryptoMemory simulator - (c) Radboud University Nijmegen\n");
if (argc < 5) if (argc < 5) {
{
printf("\nsyntax: cm <Gc> <Ci> <Q> <Q(s)>\n"); printf("\nsyntax: cm <Gc> <Ci> <Q> <Q(s)>\n");
return 1; return 1;
} }
// Parse arguments // Parse arguments
sscanf(argv[1],"%016" SCNx64,&nGc); num_to_bytes(nGc,8,Gc); sscanf(argv[1], "%016" SCNx64, &nGc);
sscanf(argv[2],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); num_to_bytes(nGc, 8, Gc);
sscanf(argv[3],"%016" SCNx64,&nQ); num_to_bytes(nQ,8,Q); sscanf(argv[2], "%016" SCNx64, &nCi);
sscanf(argv[4],"%016" SCNx64,&nQs); num_to_bytes(nQs,8,Qs); num_to_bytes(nCi, 8, Ci);
sscanf(argv[3], "%016" SCNx64, &nQ);
num_to_bytes(nQ, 8, Q);
sscanf(argv[4], "%016" SCNx64, &nQs);
num_to_bytes(nQs, 8, Qs);
// Calculate authentication // Calculate authentication
cm_auth(Gc,Ci,Q,Ch,Ci_1,Ci_2,&s); cm_auth(Gc, Ci, Q, Ch, Ci_1, Ci_2, &s);
printf("\nAuthenticate\n"); printf("\nAuthenticate\n");
printf(" Gc: "); print_bytes(Gc,8); printf(" Gc: ");
printf(" Ci: "); print_bytes(Ci,8); print_bytes(Gc, 8);
printf(" Q: "); print_bytes(Q,8); printf(" Ci: ");
printf(" Ch: "); print_bytes(Ch,8); print_bytes(Ci, 8);
printf(" Ci+1: "); print_bytes(Ci_1,8); printf(" Q: ");
printf(" Ci+2: "); print_bytes(Ci_2,8); print_bytes(Q, 8);
printf(" Ch: ");
print_bytes(Ch, 8);
printf(" Ci+1: ");
print_bytes(Ci_1, 8);
printf(" Ci+2: ");
print_bytes(Ci_2, 8);
cm_auth(Ci_2,Ci_1,Qs,Chs,Ci_1s,Ci_2s,&s); cm_auth(Ci_2, Ci_1, Qs, Chs, Ci_1s, Ci_2s, &s);
printf("\nVerify Crypto (Session Key)\n"); printf("\nVerify Crypto (Session Key)\n");
printf(" Gc(s): "); print_bytes(Ci_2,8); printf(" Gc(s): ");
printf(" Ci(s): "); print_bytes(Ci_1,8); print_bytes(Ci_2, 8);
printf(" Q(s): "); print_bytes(Qs,8); printf(" Ci(s): ");
printf(" Ch(s): "); print_bytes(Chs,8); print_bytes(Ci_1, 8);
printf("Ci+1(s): "); print_bytes(Ci_1s,8); printf(" Q(s): ");
printf("Ci+2(s): "); print_bytes(Ci_2s,8); print_bytes(Qs, 8);
printf(" Ch(s): ");
print_bytes(Chs, 8);
printf("Ci+1(s): ");
print_bytes(Ci_1s, 8);
printf("Ci+2(s): ");
print_bytes(Ci_2s, 8);
printf("\n"); printf("\n");
return 0; return 0;

View file

@ -26,22 +26,21 @@
#include "cryptolib.h" #include "cryptolib.h"
#include "util.h" #include "util.h"
#ifdef _MSC_VER #ifdef _MSC_VER
// avoid scanf warnings in Visual Studio // avoid scanf warnings in Visual Studio
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#endif #endif
int main(int argc, const char* argv[]) int main(int argc, const char *argv[]) {
{
// Cryptomemory state // Cryptomemory state
crypto_state_t s; crypto_state_t s;
size_t pos; size_t pos;
uint8_t Q[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Reader random uint8_t Q[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Reader random
uint8_t Gc[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Secret seed uint8_t Gc[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Secret seed
uint8_t Ci[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Card random (last state) uint8_t Ci[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Card random (last state)
uint8_t Ch[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Reader answer uint8_t Ch[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Reader answer
uint8_t Ci_1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Card answer uint8_t Ci_1[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Card answer
// Various argument options // Various argument options
uint64_t nGc; // Card secret uint64_t nGc; // Card secret
@ -50,32 +49,38 @@ int main(int argc, const char* argv[])
// Show header and help syntax // Show header and help syntax
printf("SecureMemory simulator - (c) Radboud University Nijmegen\n"); printf("SecureMemory simulator - (c) Radboud University Nijmegen\n");
if (argc < 4) if (argc < 4) {
{
printf("\nsyntax: sm <Gc> <Ci> <Q>\n"); printf("\nsyntax: sm <Gc> <Ci> <Q>\n");
return 1; return 1;
} }
// Parse arguments // Parse arguments
sscanf(argv[1],"%016" SCNx64,&nGc); num_to_bytes(nGc,8,Gc); sscanf(argv[1], "%016" SCNx64, &nGc);
sscanf(argv[2],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); num_to_bytes(nGc, 8, Gc);
sscanf(argv[3],"%016" SCNx64,&nQ); num_to_bytes(nQ,8,Q); sscanf(argv[2], "%016" SCNx64, &nCi);
num_to_bytes(nCi, 8, Ci);
sscanf(argv[3], "%016" SCNx64, &nQ);
num_to_bytes(nQ, 8, Q);
// Calculate authentication // Calculate authentication
sm_auth(Gc,Ci,Q,Ch,Ci_1,&s); sm_auth(Gc, Ci, Q, Ch, Ci_1, &s);
printf("\nAuthentication info\n\n"); printf("\nAuthentication info\n\n");
printf(" Gc: "); print_bytes(Gc,8); printf(" Gc: ");
printf(" Ci: "); print_bytes(Ci,8); print_bytes(Gc, 8);
printf(" Q: "); print_bytes(Q,8); printf(" Ci: ");
printf(" Ch: "); print_bytes(Ch,8); print_bytes(Ci, 8);
printf("Ci+1: "); print_bytes(Ci_1,8); printf(" Q: ");
print_bytes(Q, 8);
printf(" Ch: ");
print_bytes(Ch, 8);
printf("Ci+1: ");
print_bytes(Ci_1, 8);
printf("\n"); printf("\n");
printf(" Ks: "); printf(" Ks: ");
for (pos=0; pos<8; pos++) for (pos = 0; pos < 8; pos++) {
{ printf("%02x ", Ci_1[pos]);
printf("%02x ",Ci_1[pos]); printf("%02x ", Ch[pos]);
printf("%02x ",Ch[pos]);
} }
printf("\n\n"); printf("\n\n");

View file

@ -35,10 +35,10 @@
using namespace std; using namespace std;
#ifdef _MSC_VER #ifdef _MSC_VER
// avoid scanf warnings in Visual Studio // avoid scanf warnings in Visual Studio
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#define inline __inline #define inline __inline
#endif #endif
/* /*
@ -129,8 +129,8 @@ typedef struct {
nibble b1s; nibble b1s;
bool invalid; bool invalid;
uint8_t Gc[8]; uint8_t Gc[8];
}cs_t; } cs_t;
typedef cs_t* pcs; typedef cs_t *pcs;
typedef struct { typedef struct {
uint8_t addition; uint8_t addition;
@ -142,27 +142,25 @@ enum cipher_state_side {
CSS_RIGHT CSS_RIGHT
}; };
void print_cs(const char* text,pcs s) void print_cs(const char *text, pcs s) {
{
int pos; int pos;
printf("%s",text); printf("%s", text);
for(pos=6;pos>=0;pos--) for (pos = 6; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->l>>(pos*5))&0x1f); printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f);
printf(" |"); printf(" |");
for(pos=6;pos>=0;pos--) for (pos = 6; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->m>>(pos*7))&0x7f); printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f);
printf(" |"); printf(" |");
for(pos=4;pos>=0;pos--) for (pos = 4; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->r>>(pos*5))&0x1f); printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f);
printf("\n"); printf("\n");
} }
static inline uint8_t mod(uint8_t a, uint8_t m) static inline uint8_t mod(uint8_t a, uint8_t m) {
{
// Just return the input when this is less or equal than the modular value // Just return the input when this is less or equal than the modular value
if (a<m) return a; if (a < m) return a;
// Compute the modular value // Compute the modular value
a %= m; a %= m;
@ -171,16 +169,14 @@ static inline uint8_t mod(uint8_t a, uint8_t m)
return (a == 0) ? m : a; return (a == 0) ? m : a;
} }
static inline uint8_t bit_rotate_l(uint8_t a, uint8_t n_bits) static inline uint8_t bit_rotate_l(uint8_t a, uint8_t n_bits) {
{
// Rotate value a with the length of n_bits only 1 time // Rotate value a with the length of n_bits only 1 time
uint8_t mask = (1 << n_bits) - 1; uint8_t mask = (1 << n_bits) - 1;
return ((a << 1) | (a >> (n_bits - 1))) & mask; return ((a << 1) | (a >> (n_bits - 1))) & mask;
} }
static inline uint8_t bit_rotate_r(uint8_t a, uint8_t n_bits) static inline uint8_t bit_rotate_r(uint8_t a, uint8_t n_bits) {
{ return ((a >> 1) | ((a & 1) << (n_bits - 1)));
return ((a >> 1) | ((a&1) << (n_bits - 1)));
} }
static uint8_t lookup_left_substraction[0x400]; static uint8_t lookup_left_substraction[0x400];
@ -189,68 +185,58 @@ static lookup_entry lookup_left[0x100000];
static lookup_entry lookup_right[0x8000]; static lookup_entry lookup_right[0x8000];
static uint8_t left_addition[0x100000]; static uint8_t left_addition[0x100000];
static inline void init_lookup_left() static inline void init_lookup_left() {
{ uint8_t b3, b6, temp;
uint8_t b3,b6,temp; int i, index;
int i,index;
for(i = 0; i <0x400; i++) for (i = 0; i < 0x400; i++) {
{
b6 = i & 0x1f; b6 = i & 0x1f;
b3 = (i >> 5) & 0x1f; b3 = (i >> 5) & 0x1f;
index = (b3 << 15) | b6; index = (b3 << 15) | b6;
b6 = bit_rotate_l(b6, 5); b6 = bit_rotate_l(b6, 5);
temp = mod(b3 + b6,0x1f); temp = mod(b3 + b6, 0x1f);
left_addition[index] = temp; left_addition[index] = temp;
lookup_left[index].addition = temp; lookup_left[index].addition = temp;
lookup_left[index].out = ((temp^b3) & 0x0f); lookup_left[index].out = ((temp ^ b3) & 0x0f);
} }
} }
static inline void init_lookup_right() static inline void init_lookup_right() {
{ uint8_t b16, b18, temp;
uint8_t b16,b18,temp; int i, index;
int i,index;
for(i = 0; i <0x400; i++) for (i = 0; i < 0x400; i++) {
{
b18 = i & 0x1f; b18 = i & 0x1f;
b16 = (i >> 5) & 0x1f; b16 = (i >> 5) & 0x1f;
index = (b16 << 10) | b18; index = (b16 << 10) | b18;
temp = mod(b18 + b16,0x1f); temp = mod(b18 + b16, 0x1f);
lookup_right[index].addition = temp; lookup_right[index].addition = temp;
lookup_right[index].out = ((temp^b16) & 0x0f); lookup_right[index].out = ((temp ^ b16) & 0x0f);
} }
} }
static void init_lookup_left_substraction() static void init_lookup_left_substraction() {
{ for (int index = 0; index < 0x400 ; index++) {
for(int index = 0; index < 0x400 ; index++)
{
uint8_t b3 = (index >> 5 & 0x1f); uint8_t b3 = (index >> 5 & 0x1f);
uint8_t bx = (index & 0x1f); uint8_t bx = (index & 0x1f);
lookup_left_substraction[index] = bit_rotate_r(mod((bx+0x1f)-b3,0x1f),5); lookup_left_substraction[index] = bit_rotate_r(mod((bx + 0x1f) - b3, 0x1f), 5);
} }
} }
static void init_lookup_right_substraction() static void init_lookup_right_substraction() {
{ for (int index = 0; index < 0x400 ; index++) {
for(int index = 0; index < 0x400 ; index++) int b16 = (index >> 5);
{
int b16 = (index >>5);
uint8_t bx = (index & 0x1f); uint8_t bx = (index & 0x1f);
lookup_right_subtraction[index] = mod((bx+0x1f)-b16,0x1f); lookup_right_subtraction[index] = mod((bx + 0x1f) - b16, 0x1f);
} }
} }
static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) {
{
pcs state; pcs state;
size_t size = candidate_states->size(); size_t size = candidate_states->size();
for(size_t pos=0; pos<size; pos++) for (size_t pos = 0; pos < size; pos++) {
{
state = &((*candidate_states)[pos]); state = &((*candidate_states)[pos]);
uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f);
@ -258,11 +244,9 @@ static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states)
state->l = (state->l << 5); state->l = (state->l << 5);
//Ignore impossible states //Ignore impossible states
if (bx == 0) if (bx == 0) {
{
// Are we dealing with an impossible state? // Are we dealing with an impossible state?
if (b3 != 0) if (b3 != 0) {
{
state->invalid = true; state->invalid = true;
} else { } else {
// We only need to consider b6=0 // We only need to consider b6=0
@ -270,13 +254,12 @@ static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states)
state->l ^= (((uint64_t)in & 0x1f) << 20); state->l ^= (((uint64_t)in & 0x1f) << 20);
} }
} else { } else {
uint8_t b6 = lookup_left_substraction[b3|bx]; uint8_t b6 = lookup_left_substraction[b3 | bx];
state->l = (state->l & 0x7ffffffe0ull) | b6; state->l = (state->l & 0x7ffffffe0ull) | b6;
state->l ^= (((uint64_t)in & 0x1f) << 20); state->l ^= (((uint64_t)in & 0x1f) << 20);
// Check if we have a second candidate // Check if we have a second candidate
if (b6 == 0x1f) if (b6 == 0x1f) {
{
cs_t nstate = *state; cs_t nstate = *state;
nstate.l &= 0x7ffffffe0ull; nstate.l &= 0x7ffffffe0ull;
candidate_states->push_back(nstate); candidate_states->push_back(nstate);
@ -285,12 +268,10 @@ static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states)
} }
} }
static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) {
{
pcs state; pcs state;
size_t size = candidate_states->size(); size_t size = candidate_states->size();
for(size_t pos=0; pos<size; pos++) for (size_t pos = 0; pos < size; pos++) {
{
state = &((*candidate_states)[pos]); state = &((*candidate_states)[pos]);
uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f); uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f);
@ -299,25 +280,22 @@ static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states)
state->r = (state->r << 5); state->r = (state->r << 5);
// Ignore impossible states // Ignore impossible states
if (bx == 0) if (bx == 0) {
{ if (b16 != 0) {
if (b16 != 0) state->invalid = true;
{
state->invalid=true;
} else { } else {
// We only need to consider b18=0 // We only need to consider b18=0
state->r &= 0x1ffffe0ull; state->r &= 0x1ffffe0ull;
state->r ^= (((uint64_t)in & 0xf8) << 12); state->r ^= (((uint64_t)in & 0xf8) << 12);
} }
} else{ } else {
uint8_t b18 = lookup_right_subtraction[b16|bx]; uint8_t b18 = lookup_right_subtraction[b16 | bx];
state->r = (state->r & 0x1ffffe0ull) | b18; state->r = (state->r & 0x1ffffe0ull) | b18;
state->r ^= (((uint64_t)in & 0xf8) << 12); state->r ^= (((uint64_t)in & 0xf8) << 12);
//state->b_right = ((b14^b17) & 0x0f); //state->b_right = ((b14^b17) & 0x0f);
// Check if we have a second candidate // Check if we have a second candidate
if (b18 == 0x1f) if (b18 == 0x1f) {
{
cs_t nstate = *state; cs_t nstate = *state;
nstate.r &= 0x1ffffe0ull; nstate.r &= 0x1ffffe0ull;
candidate_states->push_back(nstate); candidate_states->push_back(nstate);
@ -326,49 +304,44 @@ static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states)
} }
} }
static inline uint8_t next_left_fast(uint8_t in, uint64_t* left) static inline uint8_t next_left_fast(uint8_t in, uint64_t *left) {
{
if (in) *left ^= ((in & 0x1f) << 20); if (in) *left ^= ((in & 0x1f) << 20);
lookup_entry* lookup = &(lookup_left[((*left) & 0xf801f)]); lookup_entry *lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
return lookup->out; return lookup->out;
} }
static inline uint8_t next_left_ksbyte(uint64_t* left) static inline uint8_t next_left_ksbyte(uint64_t *left) {
{ lookup_entry *lookup;
lookup_entry* lookup;
uint8_t bt; uint8_t bt;
*left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30));
lookup = &(lookup_left[((*left) & 0xf801f)]); lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
bt = lookup->out << 4; bt = lookup->out << 4;
*left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30));
lookup = &(lookup_left[((*left) & 0xf801f)]); lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
bt |= lookup->out; bt |= lookup->out;
return bt; return bt;
} }
static inline uint8_t next_right_fast(uint8_t in, uint64_t* right) static inline uint8_t next_right_fast(uint8_t in, uint64_t *right) {
{ if (in) *right ^= ((in & 0xf8) << 12);
if (in) *right ^= ((in&0xf8) << 12); lookup_entry *lookup = &(lookup_right[((*right) & 0x7c1f)]);
lookup_entry* lookup = &(lookup_right[((*right) & 0x7c1f)]);
*right = (((*right) >> 5) | (lookup->addition << 20)); *right = (((*right) >> 5) | (lookup->addition << 20));
return lookup->out; return lookup->out;
} }
static inline void sm_left_mask(const uint8_t* ks, uint8_t* mask, uint64_t rstate) static inline void sm_left_mask(const uint8_t *ks, uint8_t *mask, uint64_t rstate) {
{
size_t pos; size_t pos;
uint8_t bt; uint8_t bt;
for (pos=0; pos<16; pos++) for (pos = 0; pos < 16; pos++) {
{ next_right_fast(0, &rstate);
next_right_fast(0,&rstate); bt = next_right_fast(0, &rstate) << 4;
bt = next_right_fast(0,&rstate) << 4; next_right_fast(0, &rstate);
next_right_fast(0,&rstate); bt |= next_right_fast(0, &rstate);
bt |= next_right_fast(0,&rstate);
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
bt ^= ks[pos]; bt ^= ks[pos];
@ -378,30 +351,27 @@ static inline void sm_left_mask(const uint8_t* ks, uint8_t* mask, uint64_t rstat
} }
} }
static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_t>* pcrstates) static inline uint32_t sm_right(const uint8_t *ks, uint8_t *mask, vector<uint64_t> *pcrstates) {
{
uint8_t tmp_mask[16]; uint8_t tmp_mask[16];
size_t pos,bits,bit,topbits; size_t pos, bits, bit, topbits;
uint64_t rstate,counter; uint64_t rstate, counter;
map<uint64_t,uint64_t> bincstates; map<uint64_t, uint64_t> bincstates;
map<uint64_t,uint64_t>::iterator it; map<uint64_t, uint64_t>::iterator it;
uint8_t bt; uint8_t bt;
topbits = 0; topbits = 0;
for (counter=0; counter<0x2000000; counter++) for (counter = 0; counter < 0x2000000; counter++) {
{
// Reset the current bitcount of correct bits // Reset the current bitcount of correct bits
bits = 0; bits = 0;
// Copy the state we are going to test // Copy the state we are going to test
rstate = counter; rstate = counter;
for (pos=0; pos<16; pos++) for (pos = 0; pos < 16; pos++) {
{ next_right_fast(0, &rstate);
next_right_fast(0,&rstate); bt = next_right_fast(0, &rstate) << 4;
bt = next_right_fast(0,&rstate) << 4; next_right_fast(0, &rstate);
next_right_fast(0,&rstate); bt |= next_right_fast(0, &rstate);
bt |= next_right_fast(0,&rstate);
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
bt ^= ks[pos]; bt ^= ks[pos];
@ -409,30 +379,26 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_
// Save the mask for the left produced bits // Save the mask for the left produced bits
tmp_mask[pos] = bt; tmp_mask[pos] = bt;
for (bit=0; bit<8; bit++) for (bit = 0; bit < 8; bit++) {
{
// When the bit is xored away (=zero), it was the same, so correct ;) // When the bit is xored away (=zero), it was the same, so correct ;)
if ((bt & 0x01) == 0) bits++; if ((bt & 0x01) == 0) bits++;
bt >>= 1; bt >>= 1;
} }
} }
if (bits > topbits) if (bits > topbits) {
{
topbits = bits; topbits = bits;
// Copy the winning mask // Copy the winning mask
memcpy(mask,tmp_mask,16); memcpy(mask, tmp_mask, 16);
} }
// Ignore states under 90 // Ignore states under 90
if (bits >= 90) if (bits >= 90) {
{
// Make sure the bits are used for ordering // Make sure the bits are used for ordering
bincstates[(((uint64_t)bits)<<56) | counter] = counter; bincstates[(((uint64_t)bits) << 56) | counter] = counter;
} }
if ((counter&0xfffff) == 0) if ((counter & 0xfffff) == 0) {
{
printf("."); printf(".");
fflush(stdout); fflush(stdout);
} }
@ -443,45 +409,39 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_
pcrstates->clear(); pcrstates->clear();
// Copy the order the states from lowest-bin to highest-bin // Copy the order the states from lowest-bin to highest-bin
for(it=bincstates.begin();it!=bincstates.end();++it) for (it = bincstates.begin(); it != bincstates.end(); ++it) {
{
pcrstates->push_back(it->second); pcrstates->push_back(it->second);
} }
// Reverse the vector order (so the higest bin comes first) // Reverse the vector order (so the higest bin comes first)
reverse(pcrstates->begin(),pcrstates->end()); reverse(pcrstates->begin(), pcrstates->end());
return topbits; return topbits;
} }
static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_index, cipher_state_side css) static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_index, cipher_state_side css) {
{ uint8_t btGc, in;
uint8_t btGc,in;
vector<cs_t> ncstates; vector<cs_t> ncstates;
vector<cs_t> prev_ncstates; vector<cs_t> prev_ncstates;
vector<cs_t>::iterator it,itnew; vector<cs_t>::iterator it, itnew;
// Loop through the complete entryphy of 5 bits for each candidate // Loop through the complete entryphy of 5 bits for each candidate
// We ignore zero (xor 0x00) to avoid duplicates // We ignore zero (xor 0x00) to avoid duplicates
for (btGc=0; btGc<0x20; btGc++) for (btGc = 0; btGc < 0x20; btGc++) {
{
// Copy the original candidates that are supplied // Copy the original candidates that are supplied
ncstates = *pcstates; ncstates = *pcstates;
// Rollback the (candidate) cipher states with this input // Rollback the (candidate) cipher states with this input
if (css == CSS_RIGHT) if (css == CSS_RIGHT) {
{
in = btGc << 3; in = btGc << 3;
previous_right(in,&ncstates); previous_right(in, &ncstates);
} else { } else {
in = btGc; in = btGc;
previous_left(in,&ncstates); previous_left(in, &ncstates);
} }
for(itnew=ncstates.begin();itnew!=ncstates.end();++itnew) for (itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) {
{
// Wipe away the invalid states // Wipe away the invalid states
if (itnew->invalid == false) if (itnew->invalid == false) {
{
itnew->Gc[gc_byte_index] = in; itnew->Gc[gc_byte_index] = in;
prev_ncstates.push_back(*itnew); prev_ncstates.push_back(*itnew);
} }
@ -492,52 +452,48 @@ static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_i
*pcstates = prev_ncstates; *pcstates = prev_ncstates;
} }
static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, const uint64_t rstate_after_gc, const uint8_t* Q, vector<cs_t>* pcstates) static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, const uint64_t rstate_after_gc, const uint8_t *Q, vector<cs_t> *pcstates) {
{
vector<cs_t>::iterator it; vector<cs_t>::iterator it;
vector<cs_t> csl_cand; vector<cs_t> csl_cand;
map<uint64_t,uint64_t> matchbox; map<uint64_t, uint64_t> matchbox;
map<uint64_t,uint64_t>::iterator itmatch; map<uint64_t, uint64_t>::iterator itmatch;
uint64_t rstate; uint64_t rstate;
size_t counter; size_t counter;
cs_t state; cs_t state;
// Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3)
for (counter=0; counter<0x100000; counter++) for (counter = 0; counter < 0x100000; counter++) {
{
rstate = rstate_before_gc; rstate = rstate_before_gc;
next_right_fast((counter >> 12) & 0xf8,&rstate); next_right_fast((counter >> 12) & 0xf8, &rstate);
next_right_fast((counter >> 7) & 0xf8,&rstate); next_right_fast((counter >> 7) & 0xf8, &rstate);
next_right_fast(Q[4],&rstate); next_right_fast(Q[4], &rstate);
next_right_fast((counter >> 2) & 0xf8,&rstate); next_right_fast((counter >> 2) & 0xf8, &rstate);
next_right_fast((counter << 3) & 0xf8,&rstate); next_right_fast((counter << 3) & 0xf8, &rstate);
next_right_fast(Q[5],&rstate); next_right_fast(Q[5], &rstate);
matchbox[rstate] = counter; matchbox[rstate] = counter;
} }
// Reset and initialize the cryptostate and vecctor // Reset and initialize the cryptostate and vecctor
memset(&state,0x00,sizeof(cs_t)); memset(&state, 0x00, sizeof(cs_t));
state.invalid = false; state.invalid = false;
state.r = rstate_after_gc; state.r = rstate_after_gc;
csl_cand.clear(); csl_cand.clear();
csl_cand.push_back(state); csl_cand.push_back(state);
// Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7) // Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7)
previous_right(Q[7],&csl_cand); previous_right(Q[7], &csl_cand);
previous_all_input(&csl_cand,7,CSS_RIGHT); previous_all_input(&csl_cand, 7, CSS_RIGHT);
previous_all_input(&csl_cand,6,CSS_RIGHT); previous_all_input(&csl_cand, 6, CSS_RIGHT);
previous_right(Q[6],&csl_cand); previous_right(Q[6], &csl_cand);
previous_all_input(&csl_cand,5,CSS_RIGHT); previous_all_input(&csl_cand, 5, CSS_RIGHT);
previous_all_input(&csl_cand,4,CSS_RIGHT); previous_all_input(&csl_cand, 4, CSS_RIGHT);
pcstates->clear(); pcstates->clear();
// Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits)
for(it=csl_cand.begin();it!=csl_cand.end();++it) for (it = csl_cand.begin(); it != csl_cand.end(); ++it) {
{
itmatch = matchbox.find(it->r); itmatch = matchbox.find(it->r);
if (itmatch != matchbox.end()) if (itmatch != matchbox.end()) {
{
it->Gc[0] = (itmatch->second >> 12) & 0xf8; it->Gc[0] = (itmatch->second >> 12) & 0xf8;
it->Gc[1] = (itmatch->second >> 7) & 0xf8; it->Gc[1] = (itmatch->second >> 7) & 0xf8;
it->Gc[2] = (itmatch->second >> 2) & 0xf8; it->Gc[2] = (itmatch->second >> 2) & 0xf8;
@ -546,47 +502,44 @@ static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, c
printf("%07llx ",it->r); printf("%07llx ",it->r);
printf("(%x)\n",itmatch->second); printf("(%x)\n",itmatch->second);
*/ */
/* /*
if (it->r == 0xff459b) if (it->r == 0xff459b)
{ {
print_cs("previous:",&(*it)); print_cs("previous:",&(*it));
printf("%07llx\n",it->r); printf("%07llx\n",it->r);
print_bytes(it->Gc,8); print_bytes(it->Gc,8);
} }
*/ */
pcstates->push_back(*it); pcstates->push_back(*it);
} }
} }
} }
static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcstates) static inline void sm_left(const uint8_t *ks, uint8_t *mask, vector<cs_t> *pcstates) {
{ map<uint64_t, cs_t> bincstates;
map<uint64_t,cs_t> bincstates; map<uint64_t, cs_t>::iterator it;
map<uint64_t,cs_t>::iterator it; uint64_t counter, lstate;
uint64_t counter,lstate; size_t pos, bits, bit;
size_t pos,bits,bit;
uint8_t correct_bits[16]; uint8_t correct_bits[16];
uint8_t bt; uint8_t bt;
cs_t state; cs_t state;
lookup_entry* lookup; lookup_entry *lookup;
// Reset and initialize the cryptostate and vecctor // Reset and initialize the cryptostate and vecctor
memset(&state,0x00,sizeof(cs_t)); memset(&state, 0x00, sizeof(cs_t));
state.invalid = false; state.invalid = false;
for (counter=0; counter<0x800000000ull; counter++) for (counter = 0; counter < 0x800000000ull; counter++) {
{
lstate = counter; lstate = counter;
for (pos=0; pos<16; pos++) for (pos = 0; pos < 16; pos++) {
{ lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt = lookup->out << 4; bt = lookup->out << 4;
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt |= lookup->out; bt |= lookup->out;
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
@ -600,18 +553,15 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
} }
// If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE!
if (pos == 16) if (pos == 16) {
{
// Count the total correct bits // Count the total correct bits
bits=0; bits = 0;
for (pos=0; pos<16; pos++) for (pos = 0; pos < 16; pos++) {
{
// Get the next byte-value with correct bits // Get the next byte-value with correct bits
bt = correct_bits[pos]; bt = correct_bits[pos];
// Count all the (correct) bits // Count all the (correct) bits
for (bit=0; bit<8; bit++) for (bit = 0; bit < 8; bit++) {
{
// When the bit is xored away (=zero), it was the same, so correct ;) // When the bit is xored away (=zero), it was the same, so correct ;)
if ((bt & 0x01) == 0) bits++; if ((bt & 0x01) == 0) bits++;
bt >>= 1; bt >>= 1;
@ -625,12 +575,11 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
state.l = counter; state.l = counter;
// Make sure the bits are used for ordering // Make sure the bits are used for ordering
bincstates[(((uint64_t)bits)<<56) | counter] = state; bincstates[(((uint64_t)bits) << 56) | counter] = state;
} }
if ((counter&0xffffffffull) == 0) if ((counter & 0xffffffffull) == 0) {
{ printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32));
printf("%02.1f%%.",((float)100/8)*(counter>>32));
fflush(stdout); fflush(stdout);
} }
} }
@ -640,33 +589,30 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
pcstates->clear(); pcstates->clear();
// Copy the order the states from lowest-bin to highest-bin // Copy the order the states from lowest-bin to highest-bin
for(it=bincstates.begin();it!=bincstates.end();++it) for (it = bincstates.begin(); it != bincstates.end(); ++it) {
{
pcstates->push_back(it->second); pcstates->push_back(it->second);
} }
// Reverse the vector order (so the higest bin comes first) // Reverse the vector order (so the higest bin comes first)
reverse(pcstates->begin(),pcstates->end()); reverse(pcstates->begin(), pcstates->end());
} }
static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t* Q, vector<cs_t>* pcstates) static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t *Q, vector<cs_t> *pcstates) {
{ vector<cs_t> csl_cand, csl_search;
vector<cs_t> csl_cand,csl_search; vector<cs_t>::iterator itsearch, itcand;
vector<cs_t>::iterator itsearch,itcand; map<uint64_t, uint64_t> matchbox;
map<uint64_t,uint64_t> matchbox; map<uint64_t, uint64_t>::iterator itmatch;
map<uint64_t,uint64_t>::iterator itmatch;
uint64_t lstate; uint64_t lstate;
size_t counter; size_t counter;
// Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3)
for (counter=0; counter<0x100000; counter++) for (counter = 0; counter < 0x100000; counter++) {
{
lstate = lstate_before_gc; lstate = lstate_before_gc;
next_left_fast((counter >> 15) & 0x1f,&lstate); next_left_fast((counter >> 15) & 0x1f, &lstate);
next_left_fast((counter >> 10) & 0x1f,&lstate); next_left_fast((counter >> 10) & 0x1f, &lstate);
next_left_fast(Q[4],&lstate); next_left_fast(Q[4], &lstate);
next_left_fast((counter >> 5) & 0x1f,&lstate); next_left_fast((counter >> 5) & 0x1f, &lstate);
next_left_fast(counter & 0x1f,&lstate); next_left_fast(counter & 0x1f, &lstate);
next_left_fast(Q[5],&lstate); next_left_fast(Q[5], &lstate);
matchbox[lstate] = counter; matchbox[lstate] = counter;
} }
@ -674,25 +620,22 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
csl_cand = *pcstates; csl_cand = *pcstates;
pcstates->clear(); pcstates->clear();
for(itcand=csl_cand.begin();itcand!=csl_cand.end();++itcand) for (itcand = csl_cand.begin(); itcand != csl_cand.end(); ++itcand) {
{
csl_search.clear(); csl_search.clear();
csl_search.push_back(*itcand); csl_search.push_back(*itcand);
// Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7) // Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7)
previous_left(Q[7],&csl_search); previous_left(Q[7], &csl_search);
previous_all_input(&csl_search,7,CSS_LEFT); previous_all_input(&csl_search, 7, CSS_LEFT);
previous_all_input(&csl_search,6,CSS_LEFT); previous_all_input(&csl_search, 6, CSS_LEFT);
previous_left(Q[6],&csl_search); previous_left(Q[6], &csl_search);
previous_all_input(&csl_search,5,CSS_LEFT); previous_all_input(&csl_search, 5, CSS_LEFT);
previous_all_input(&csl_search,4,CSS_LEFT); previous_all_input(&csl_search, 4, CSS_LEFT);
// Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits)
for(itsearch=csl_search.begin();itsearch!=csl_search.end();++itsearch) for (itsearch = csl_search.begin(); itsearch != csl_search.end(); ++itsearch) {
{
itmatch = matchbox.find(itsearch->l); itmatch = matchbox.find(itsearch->l);
if (itmatch != matchbox.end()) if (itmatch != matchbox.end()) {
{
itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f; itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f;
itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f; itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f;
itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f; itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f;
@ -703,7 +646,7 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
printf("(%x) ",itmatch->second); printf("(%x) ",itmatch->second);
print_cs("",&(*it)); print_cs("",&(*it));
*/ */
/* /*
if (itsearch->l == 0x405162420ull) if (itsearch->l == 0x405162420ull)
{ {
print_cs("previous:",&(*itsearch)); print_cs("previous:",&(*itsearch));
@ -711,7 +654,7 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
print_bytes(itsearch->Gc,8); print_bytes(itsearch->Gc,8);
} }
count++; count++;
*/ */
pcstates->push_back(*itsearch); pcstates->push_back(*itsearch);
} }
} }
@ -723,36 +666,29 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
printf("\n"); printf("\n");
} }
void combine_valid_left_right_states(vector<cs_t>* plcstates, vector<cs_t>* prcstates, vector<uint64_t>* pgc_candidates) void combine_valid_left_right_states(vector<cs_t> *plcstates, vector<cs_t> *prcstates, vector<uint64_t> *pgc_candidates) {
{
vector<cs_t>::iterator itl, itr; vector<cs_t>::iterator itl, itr;
size_t pos,count; size_t pos, count;
uint64_t gc; uint64_t gc;
bool valid; bool valid;
// Clean up the candidate list // Clean up the candidate list
pgc_candidates->clear(); pgc_candidates->clear();
count = 0; count = 0;
for(itl=plcstates->begin();itl!=plcstates->end();++itl) for (itl = plcstates->begin(); itl != plcstates->end(); ++itl) {
{ for (itr = prcstates->begin(); itr != prcstates->end(); ++itr) {
for(itr=prcstates->begin();itr!=prcstates->end();++itr)
{
valid = true; valid = true;
// Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc) // Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc)
for (pos=0; pos<8; pos++) for (pos = 0; pos < 8; pos++) {
{ if ((itl->Gc[pos] & 0x18) != (itr->Gc[pos] & 0x18)) {
if ((itl->Gc[pos] & 0x18) != (itr->Gc[pos] & 0x18))
{
valid = false; valid = false;
break; break;
} }
} }
if (valid) if (valid) {
{
gc = 0; gc = 0;
for (pos=0; pos<8; pos++) for (pos = 0; pos < 8; pos++) {
{
gc <<= 8; gc <<= 8;
gc |= (itl->Gc[pos] | itr->Gc[pos]); gc |= (itl->Gc[pos] | itr->Gc[pos]);
} }
@ -764,20 +700,19 @@ void combine_valid_left_right_states(vector<cs_t>* plcstates, vector<cs_t>* prcs
count++; count++;
} }
} }
printf("Found a total of " _YELLOW_("%llu")" combinations, ",((unsigned long long)plcstates->size()) * prcstates->size()); printf("Found a total of " _YELLOW_("%llu")" combinations, ", ((unsigned long long)plcstates->size()) * prcstates->size());
printf("but only " _GREEN_("%lu")" were valid!\n", pgc_candidates->size()); printf("but only " _GREEN_("%lu")" were valid!\n", pgc_candidates->size());
} }
int main(int argc, const char* argv[]) int main(int argc, const char *argv[]) {
{
size_t pos; size_t pos;
crypto_state_t ostate; crypto_state_t ostate;
uint64_t rstate_before_gc,rstate_after_gc; uint64_t rstate_before_gc, rstate_after_gc;
uint64_t lstate_before_gc; uint64_t lstate_before_gc;
vector<uint64_t> rstates,lstates_after_gc,pgc_candidates; vector<uint64_t> rstates, lstates_after_gc, pgc_candidates;
vector<uint64_t>::iterator itrstates,itgc; vector<uint64_t>::iterator itrstates, itgc;
vector<cs_t> crstates; vector<cs_t> crstates;
vector<cs_t> clcandidates,clstates; vector<cs_t> clcandidates, clstates;
vector<cs_t>::iterator it; vector<cs_t>::iterator it;
uint32_t rbits; uint32_t rbits;
@ -807,8 +742,7 @@ int main(int argc, const char* argv[])
uint64_t nCh; // Reader challange uint64_t nCh; // Reader challange
uint64_t nCi_1; // Card anwser uint64_t nCi_1; // Card anwser
if ((argc != 2) && (argc != 5)) if ((argc != 2) && (argc != 5)) {
{
printf("SecureMemory recovery - (c) Radboud University Nijmegen\n\n"); printf("SecureMemory recovery - (c) Radboud University Nijmegen\n\n");
printf("syntax: sma simulate\n"); printf("syntax: sma simulate\n");
printf(" sma <Ci> <Q> <Ch> <Ci+1>\n\n"); printf(" sma <Ci> <Q> <Ch> <Ci+1>\n\n");
@ -818,38 +752,45 @@ int main(int argc, const char* argv[])
printf(_CYAN_("\nAuthentication info\n\n")); printf(_CYAN_("\nAuthentication info\n\n"));
// Check if this is a simulation // Check if this is a simulation
if (argc == 2) if (argc == 2) {
{
// Generate random values for the key and randoms // Generate random values for the key and randoms
srand((uint32_t)time(NULL)); srand((uint32_t)time(NULL));
for (pos = 0; pos<8; pos++) for (pos = 0; pos < 8; pos++) {
{
Gc[pos] = rand(); Gc[pos] = rand();
Ci[pos] = rand(); Ci[pos] = rand();
Q[pos] = rand(); Q[pos] = rand();
} }
sm_auth(Gc,Ci,Q,Ch,Ci_1,&ostate); sm_auth(Gc, Ci, Q, Ch, Ci_1, &ostate);
printf(" Gc: "); print_bytes(Gc,8); printf(" Gc: ");
print_bytes(Gc, 8);
} else { } else {
sscanf(argv[1],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); sscanf(argv[1], "%016" SCNx64, &nCi);
sscanf(argv[2],"%016" SCNx64,&nQ); num_to_bytes(nQ,8,Q); num_to_bytes(nCi, 8, Ci);
sscanf(argv[3],"%016" SCNx64,&nCh); num_to_bytes(nCh,8,Ch); sscanf(argv[2], "%016" SCNx64, &nQ);
sscanf(argv[4],"%016" SCNx64,&nCi_1); num_to_bytes(nCi_1,8,Ci_1); num_to_bytes(nQ, 8, Q);
sscanf(argv[3], "%016" SCNx64, &nCh);
num_to_bytes(nCh, 8, Ch);
sscanf(argv[4], "%016" SCNx64, &nCi_1);
num_to_bytes(nCi_1, 8, Ci_1);
printf(" Gc: unknown\n"); printf(" Gc: unknown\n");
} }
for (pos = 0; pos<8; pos++) for (pos = 0; pos < 8; pos++) {
{ ks[2 * pos] = Ci_1[pos];
ks[2*pos] = Ci_1[pos]; ks[(2 * pos) + 1] = Ch[pos];
ks[(2*pos)+1] = Ch[pos];
} }
printf(" Ci: "); print_bytes(Ci,8); printf(" Ci: ");
printf(" Q: "); print_bytes(Q,8); print_bytes(Ci, 8);
printf(" Ch: "); print_bytes(Ch,8); printf(" Q: ");
printf("Ci+1: "); print_bytes(Ci_1,8); print_bytes(Q, 8);
printf(" Ch: ");
print_bytes(Ch, 8);
printf("Ci+1: ");
print_bytes(Ci_1, 8);
printf("\n"); printf("\n");
printf(" Ks: "); print_bytes(ks,16); printf(" Ks: ");
print_bytes(ks, 16);
printf("\n"); printf("\n");
printf("Initializing lookup tables for increasing cipher speed\n"); printf("Initializing lookup tables for increasing cipher speed\n");
@ -861,57 +802,52 @@ int main(int argc, const char* argv[])
// Load in the ci (tag-nonce), together with the first half of Q (reader-nonce) // Load in the ci (tag-nonce), together with the first half of Q (reader-nonce)
rstate_before_gc = 0; rstate_before_gc = 0;
lstate_before_gc = 0; lstate_before_gc = 0;
for (pos = 0; pos < 4; pos++) for (pos = 0; pos < 4; pos++) {
{ next_right_fast(Ci[2 * pos ], &rstate_before_gc);
next_right_fast(Ci[2*pos ],&rstate_before_gc); next_right_fast(Ci[2 * pos + 1], &rstate_before_gc);
next_right_fast(Ci[2*pos+1],&rstate_before_gc); next_right_fast(Q[pos], &rstate_before_gc);
next_right_fast(Q[pos],&rstate_before_gc);
next_left_fast(Ci[2*pos ],&lstate_before_gc); next_left_fast(Ci[2 * pos ], &lstate_before_gc);
next_left_fast(Ci[2*pos+1],&lstate_before_gc); next_left_fast(Ci[2 * pos + 1], &lstate_before_gc);
next_left_fast(Q[pos],&lstate_before_gc); next_left_fast(Q[pos], &lstate_before_gc);
} }
printf("Determing the right states that correspond to the keystream\n"); printf("Determing the right states that correspond to the keystream\n");
rbits = sm_right(ks,mask,&rstates); rbits = sm_right(ks, mask, &rstates);
printf("Top-bin for the right state contains " _GREEN_("%d")" correct bits\n",rbits); printf("Top-bin for the right state contains " _GREEN_("%d")" correct bits\n", rbits);
printf("Total count of right bins: " _YELLOW_("%lu") "\n",(unsigned long)rstates.size()); printf("Total count of right bins: " _YELLOW_("%lu") "\n", (unsigned long)rstates.size());
if (rbits < 96) if (rbits < 96) {
{
printf(_RED_("\n WARNING!!! Better find another trace, the right top-bin is < 96 bits\n\n")); printf(_RED_("\n WARNING!!! Better find another trace, the right top-bin is < 96 bits\n\n"));
} }
for(itrstates=rstates.begin();itrstates!=rstates.end();++itrstates) for (itrstates = rstates.begin(); itrstates != rstates.end(); ++itrstates) {
{
rstate_after_gc = *itrstates; rstate_after_gc = *itrstates;
sm_left_mask(ks,mask,rstate_after_gc); sm_left_mask(ks, mask, rstate_after_gc);
printf("Using the state from the top-right bin: " _YELLOW_("0x%07" PRIx64)"\n",rstate_after_gc); printf("Using the state from the top-right bin: " _YELLOW_("0x%07" PRIx64)"\n", rstate_after_gc);
search_gc_candidates_right(rstate_before_gc,rstate_after_gc,Q,&crstates); search_gc_candidates_right(rstate_before_gc, rstate_after_gc, Q, &crstates);
printf("Found " _YELLOW_("%lu")" right candidates using the meet-in-the-middle attack\n",crstates.size()); printf("Found " _YELLOW_("%lu")" right candidates using the meet-in-the-middle attack\n", crstates.size());
if (crstates.size() == 0) continue; if (crstates.size() == 0) continue;
printf("Calculating left states using the (unknown bits) mask from the top-right state\n"); printf("Calculating left states using the (unknown bits) mask from the top-right state\n");
sm_left(ks,mask,&clstates); sm_left(ks, mask, &clstates);
printf("Found a total of " _YELLOW_("%lu")" left cipher states, recovering left candidates...\n",clstates.size()); printf("Found a total of " _YELLOW_("%lu")" left cipher states, recovering left candidates...\n", clstates.size());
if (clstates.size() == 0) continue; if (clstates.size() == 0) continue;
search_gc_candidates_left(lstate_before_gc,Q,&clstates); search_gc_candidates_left(lstate_before_gc, Q, &clstates);
printf("The meet-in-the-middle attack returned " _YELLOW_("%lu")" left cipher candidates\n",clstates.size()); printf("The meet-in-the-middle attack returned " _YELLOW_("%lu")" left cipher candidates\n", clstates.size());
if (clstates.size() == 0) continue; if (clstates.size() == 0) continue;
printf("Combining left and right states, disposing invalid combinations\n"); printf("Combining left and right states, disposing invalid combinations\n");
combine_valid_left_right_states(&clstates,&crstates,&pgc_candidates); combine_valid_left_right_states(&clstates, &crstates, &pgc_candidates);
printf("Filtering the correct one using the middle part\n"); printf("Filtering the correct one using the middle part\n");
for(itgc=pgc_candidates.begin();itgc!=pgc_candidates.end();++itgc) for (itgc = pgc_candidates.begin(); itgc != pgc_candidates.end(); ++itgc) {
{ num_to_bytes(*itgc, 8, Gc_chk);
num_to_bytes(*itgc,8,Gc_chk); sm_auth(Gc_chk, Ci, Q, Ch_chk, Ci_1_chk, &ostate);
sm_auth(Gc_chk,Ci,Q,Ch_chk,Ci_1_chk,&ostate); if ((memcmp(Ch_chk, Ch, 8) == 0) && (memcmp(Ci_1_chk, Ci_1, 8) == 0)) {
if ((memcmp(Ch_chk,Ch,8) == 0) && (memcmp(Ci_1_chk,Ci_1,8) == 0)) printf("\nFound valid key: " _GREEN_("%016" PRIx64)"\n\n", *itgc);
{
printf("\nFound valid key: " _GREEN_("%016" PRIx64)"\n\n",*itgc);
return 0; return 0;
} }
} }

View file

@ -38,10 +38,10 @@
using namespace std; using namespace std;
#ifdef _MSC_VER #ifdef _MSC_VER
// avoid scanf warnings in Visual Studio // avoid scanf warnings in Visual Studio
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#define inline __inline #define inline __inline
#endif #endif
/* /*
@ -132,8 +132,8 @@ typedef struct {
nibble b1s; nibble b1s;
bool invalid; bool invalid;
uint8_t Gc[8]; uint8_t Gc[8];
}cs_t; } cs_t;
typedef cs_t* pcs; typedef cs_t *pcs;
typedef struct { typedef struct {
uint8_t addition; uint8_t addition;
@ -145,29 +145,29 @@ enum cipher_state_side {
CSS_RIGHT CSS_RIGHT
}; };
void print_cs(const char* text,pcs s) { void print_cs(const char *text, pcs s) {
int pos; int pos;
printf("%s",text); printf("%s", text);
for(pos=6;pos>=0;pos--) for (pos = 6; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->l>>(pos*5))&0x1f); printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f);
printf(" |"); printf(" |");
for(pos=6;pos>=0;pos--) for (pos = 6; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->m>>(pos*7))&0x7f); printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f);
printf(" |"); printf(" |");
for(pos=4;pos>=0;pos--) for (pos = 4; pos >= 0; pos--)
printf(" %02x",(uint8_t)(s->r>>(pos*5))&0x1f); printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f);
printf("\n"); printf("\n");
} }
static inline uint8_t mod(uint8_t a, uint8_t m) { static inline uint8_t mod(uint8_t a, uint8_t m) {
// Just return the input when this is less or equal than the modular value // Just return the input when this is less or equal than the modular value
if (a<m) return a; if (a < m) return a;
// Compute the modular value // Compute the modular value
a %= m; a %= m;
@ -203,7 +203,7 @@ static inline void init_lookup_left() {
uint8_t b3, b6, temp; uint8_t b3, b6, temp;
int i, index; int i, index;
for (i = 0; i <0x400; i++){ for (i = 0; i < 0x400; i++) {
b6 = i & 0x1f; b6 = i & 0x1f;
b3 = (i >> 5) & 0x1f; b3 = (i >> 5) & 0x1f;
index = (b3 << 15) | b6; index = (b3 << 15) | b6;
@ -211,10 +211,10 @@ static inline void init_lookup_left() {
// b6 = bit_rotate_l(b6, 5); // b6 = bit_rotate_l(b6, 5);
b6 = BIT_ROL(b6); b6 = BIT_ROL(b6);
temp = mod(b3 + b6,0x1f); temp = mod(b3 + b6, 0x1f);
left_addition[index] = temp; left_addition[index] = temp;
lookup_left[index].addition = temp; lookup_left[index].addition = temp;
lookup_left[index].out = ((temp^b3) & 0x0f); lookup_left[index].out = ((temp ^ b3) & 0x0f);
} }
} }
@ -222,30 +222,30 @@ static inline void init_lookup_right() {
uint8_t b16, b18, temp; uint8_t b16, b18, temp;
int i, index; int i, index;
for(i = 0; i <0x400; i++) { for (i = 0; i < 0x400; i++) {
b18 = i & 0x1f; b18 = i & 0x1f;
b16 = (i >> 5) & 0x1f; b16 = (i >> 5) & 0x1f;
index = (b16 << 10) | b18; index = (b16 << 10) | b18;
temp = mod(b18 + b16,0x1f); temp = mod(b18 + b16, 0x1f);
lookup_right[index].addition = temp; lookup_right[index].addition = temp;
lookup_right[index].out = ((temp^b16) & 0x0f); lookup_right[index].out = ((temp ^ b16) & 0x0f);
} }
} }
static void init_lookup_left_substraction() { static void init_lookup_left_substraction() {
for(int index = 0; index < 0x400 ; index++) { for (int index = 0; index < 0x400 ; index++) {
uint8_t b3 = (index >> 5 & 0x1f); uint8_t b3 = (index >> 5 & 0x1f);
uint8_t bx = (index & 0x1f); uint8_t bx = (index & 0x1f);
//lookup_left_substraction[index] = bit_rotate_r(mod((bx+0x1f)-b3,0x1f),5); //lookup_left_substraction[index] = bit_rotate_r(mod((bx+0x1f)-b3,0x1f),5);
lookup_left_substraction[index] = BIT_ROR( mod((bx + 0x1F) - b3, 0x1F)); lookup_left_substraction[index] = BIT_ROR(mod((bx + 0x1F) - b3, 0x1F));
} }
} }
static void init_lookup_right_substraction() { static void init_lookup_right_substraction() {
for(int index = 0; index < 0x400 ; index++) { for (int index = 0; index < 0x400 ; index++) {
int b16 = (index >>5); int b16 = (index >> 5);
uint8_t bx = (index & 0x1f); uint8_t bx = (index & 0x1f);
lookup_right_subtraction[index] = mod((bx + 0x1F) - b16, 0x1F); lookup_right_subtraction[index] = mod((bx + 0x1F) - b16, 0x1F);
} }
@ -254,7 +254,7 @@ static void init_lookup_right_substraction() {
static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) { static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) {
pcs state; pcs state;
size_t size = candidate_states->size(); size_t size = candidate_states->size();
for(size_t pos=0; pos<size; pos++) { for (size_t pos = 0; pos < size; pos++) {
state = &((*candidate_states)[pos]); state = &((*candidate_states)[pos]);
uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f);
@ -272,7 +272,7 @@ static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) {
state->l ^= (((uint64_t)in & 0x1f) << 20); state->l ^= (((uint64_t)in & 0x1f) << 20);
} }
} else { } else {
uint8_t b6 = lookup_left_substraction[b3|bx]; uint8_t b6 = lookup_left_substraction[b3 | bx];
state->l = (state->l & 0x7ffffffe0ull) | b6; state->l = (state->l & 0x7ffffffe0ull) | b6;
state->l ^= (((uint64_t)in & 0x1f) << 20); state->l ^= (((uint64_t)in & 0x1f) << 20);
@ -289,7 +289,7 @@ static inline void previous_left(uint8_t in, vector<cs_t> *candidate_states) {
static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) { static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) {
pcs state; pcs state;
size_t size = candidate_states->size(); size_t size = candidate_states->size();
for(size_t pos=0; pos<size; pos++) { for (size_t pos = 0; pos < size; pos++) {
state = &((*candidate_states)[pos]); state = &((*candidate_states)[pos]);
uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f); uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f);
@ -300,14 +300,14 @@ static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) {
// Ignore impossible states // Ignore impossible states
if (bx == 0) { if (bx == 0) {
if (b16 != 0) { if (b16 != 0) {
state->invalid=true; state->invalid = true;
} else { } else {
// We only need to consider b18=0 // We only need to consider b18=0
state->r &= 0x1ffffe0ull; state->r &= 0x1ffffe0ull;
state->r ^= (((uint64_t)in & 0xf8) << 12); state->r ^= (((uint64_t)in & 0xf8) << 12);
} }
} else { } else {
uint8_t b18 = lookup_right_subtraction[b16|bx]; uint8_t b18 = lookup_right_subtraction[b16 | bx];
state->r = (state->r & 0x1ffffe0ull) | b18; state->r = (state->r & 0x1ffffe0ull) | b18;
state->r ^= (((uint64_t)in & 0xf8) << 12); state->r ^= (((uint64_t)in & 0xf8) << 12);
//state->b_right = ((b14^b17) & 0x0f); //state->b_right = ((b14^b17) & 0x0f);
@ -322,43 +322,43 @@ static inline void previous_right(uint8_t in, vector<cs_t> *candidate_states) {
} }
} }
static inline uint8_t next_left_fast(uint8_t in, uint64_t* left) { static inline uint8_t next_left_fast(uint8_t in, uint64_t *left) {
if (in) if (in)
*left ^= ((in & 0x1f) << 20); *left ^= ((in & 0x1f) << 20);
lookup_entry* lookup = &(lookup_left[((*left) & 0xf801f)]); lookup_entry *lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
return lookup->out; return lookup->out;
} }
static inline uint8_t next_left_ksbyte(uint64_t* left) { static inline uint8_t next_left_ksbyte(uint64_t *left) {
lookup_entry* lookup; lookup_entry *lookup;
uint8_t bt; uint8_t bt;
*left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30));
lookup = &(lookup_left[((*left) & 0xf801f)]); lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
bt = lookup->out << 4; bt = lookup->out << 4;
*left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30));
lookup = &(lookup_left[((*left) & 0xf801f)]); lookup = &(lookup_left[((*left) & 0xf801f)]);
*left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30));
bt |= lookup->out; bt |= lookup->out;
return bt; return bt;
} }
static inline uint8_t next_right_fast(uint8_t in, uint64_t* right) { static inline uint8_t next_right_fast(uint8_t in, uint64_t *right) {
if (in) *right ^= ((in&0xf8) << 12); if (in) *right ^= ((in & 0xf8) << 12);
lookup_entry* lookup = &(lookup_right[((*right) & 0x7c1f)]); lookup_entry *lookup = &(lookup_right[((*right) & 0x7c1f)]);
*right = (((*right) >> 5) | (lookup->addition << 20)); *right = (((*right) >> 5) | (lookup->addition << 20));
return lookup->out; return lookup->out;
} }
static inline void sm_left_mask(const uint8_t* ks, uint8_t* mask, uint64_t rstate) { static inline void sm_left_mask(const uint8_t *ks, uint8_t *mask, uint64_t rstate) {
for (uint8_t pos = 0; pos < 16; pos++) { for (uint8_t pos = 0; pos < 16; pos++) {
next_right_fast(0,&rstate); next_right_fast(0, &rstate);
uint8_t bt = next_right_fast(0,&rstate) << 4; uint8_t bt = next_right_fast(0, &rstate) << 4;
next_right_fast(0,&rstate); next_right_fast(0, &rstate);
bt |= next_right_fast(0,&rstate); bt |= next_right_fast(0, &rstate);
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
bt ^= ks[pos]; bt ^= ks[pos];
@ -379,10 +379,10 @@ uint32_t g_num_cpus = std::thread::hardware_concurrency();
static void ice_sm_right_thread( static void ice_sm_right_thread(
uint8_t offset, uint8_t offset,
uint8_t skips, uint8_t skips,
const uint8_t* ks, const uint8_t *ks,
map<uint64_t,uint64_t>* bincstates, map<uint64_t, uint64_t> *bincstates,
uint8_t* mask uint8_t *mask
) { ) {
uint8_t tmp_mask[16]; uint8_t tmp_mask[16];
uint8_t bt; uint8_t bt;
@ -436,7 +436,7 @@ static void ice_sm_right_thread(
if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end()) if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end())
bincstates->at((((uint64_t)bits) << 56) | counter) = counter; bincstates->at((((uint64_t)bits) << 56) | counter) = counter;
else else
bincstates->insert( std::pair<uint64_t,uint64_t>( (((uint64_t)bits) << 56) | counter, counter)); bincstates->insert(std::pair<uint64_t, uint64_t>((((uint64_t)bits) << 56) | counter, counter));
g_ice_mtx.unlock(); g_ice_mtx.unlock();
} }
@ -448,17 +448,17 @@ static void ice_sm_right_thread(
} }
} }
} }
static uint32_t ice_sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_t>* pcrstates) { static uint32_t ice_sm_right(const uint8_t *ks, uint8_t *mask, vector<uint64_t> *pcrstates) {
uint32_t g_num_cpus = std::thread::hardware_concurrency(); uint32_t g_num_cpus = std::thread::hardware_concurrency();
map<uint64_t,uint64_t> bincstates; map<uint64_t, uint64_t> bincstates;
topbits = ATOMIC_VAR_INIT(0); topbits = ATOMIC_VAR_INIT(0);
std::vector<std::thread> threads(g_num_cpus); std::vector<std::thread> threads(g_num_cpus);
for (uint8_t m = 0; m < g_num_cpus; m++) { for (uint8_t m = 0; m < g_num_cpus; m++) {
threads[m] = std::thread( ice_sm_right_thread, m, g_num_cpus, ks, &bincstates, mask); threads[m] = std::thread(ice_sm_right_thread, m, g_num_cpus, ks, &bincstates, mask);
} }
for (auto& t : threads) { for (auto &t : threads) {
t.join(); t.join();
} }
@ -468,7 +468,7 @@ static uint32_t ice_sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_t>*
pcrstates->clear(); pcrstates->clear();
// Copy the order the states from lowest-bin to highest-bin // Copy the order the states from lowest-bin to highest-bin
map<uint64_t,uint64_t>::iterator it; map<uint64_t, uint64_t>::iterator it;
for (it = bincstates.begin(); it != bincstates.end(); ++it) { for (it = bincstates.begin(); it != bincstates.end(); ++it) {
pcrstates->push_back(it->second); pcrstates->push_back(it->second);
} }
@ -482,15 +482,15 @@ static uint32_t ice_sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_t>*
static void ice_sm_left_thread( static void ice_sm_left_thread(
uint8_t offset, uint8_t offset,
uint8_t skips, uint8_t skips,
const uint8_t* ks, const uint8_t *ks,
map<uint64_t, cs_t>* bincstates, map<uint64_t, cs_t> *bincstates,
uint8_t* mask uint8_t *mask
) { ) {
size_t pos, bits; size_t pos, bits;
uint8_t correct_bits[16]; uint8_t correct_bits[16];
uint8_t bt; uint8_t bt;
lookup_entry* lookup; lookup_entry *lookup;
// Reset and initialize the cryptostate and vector // Reset and initialize the cryptostate and vector
cs_t state; cs_t state;
@ -503,13 +503,13 @@ static void ice_sm_left_thread(
for (pos = 0; pos < 16; pos++) { for (pos = 0; pos < 16; pos++) {
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt = lookup->out << 4; bt = lookup->out << 4;
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt |= lookup->out; bt |= lookup->out;
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
@ -551,31 +551,31 @@ static void ice_sm_left_thread(
if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end()) if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end())
bincstates->at((((uint64_t)bits) << 56) | counter) = state; bincstates->at((((uint64_t)bits) << 56) | counter) = state;
else else
bincstates->insert( std::pair<uint64_t,cs_t>( (((uint64_t)bits) << 56) | counter, state)); bincstates->insert(std::pair<uint64_t, cs_t>((((uint64_t)bits) << 56) | counter, state));
g_ice_mtx.unlock(); g_ice_mtx.unlock();
} }
if ((counter & 0xffffffffull) == 0) { if ((counter & 0xffffffffull) == 0) {
g_ice_mtx.lock(); g_ice_mtx.lock();
printf("%02.1f%%.", ((float)100/8) * (counter >> 32)); printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32));
fflush(stdout); fflush(stdout);
g_ice_mtx.unlock(); g_ice_mtx.unlock();
} }
} }
} }
static void ice_sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcstates) { static void ice_sm_left(const uint8_t *ks, uint8_t *mask, vector<cs_t> *pcstates) {
uint32_t g_num_cpus = std::thread::hardware_concurrency(); uint32_t g_num_cpus = std::thread::hardware_concurrency();
map<uint64_t, cs_t> bincstates; map<uint64_t, cs_t> bincstates;
std::vector<std::thread> threads(g_num_cpus); std::vector<std::thread> threads(g_num_cpus);
for (uint8_t m = 0; m < g_num_cpus; m++) { for (uint8_t m = 0; m < g_num_cpus; m++) {
threads[m] = std::thread( ice_sm_left_thread, m, g_num_cpus, ks, &bincstates, mask); threads[m] = std::thread(ice_sm_left_thread, m, g_num_cpus, ks, &bincstates, mask);
} }
for (auto& t : threads) { for (auto &t : threads) {
t.join(); t.join();
} }
@ -586,18 +586,18 @@ static void ice_sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcstates
// Copy the order the states from lowest-bin to highest-bin // Copy the order the states from lowest-bin to highest-bin
map<uint64_t, cs_t>::iterator it; map<uint64_t, cs_t>::iterator it;
for(it = bincstates.begin(); it != bincstates.end(); ++it) { for (it = bincstates.begin(); it != bincstates.end(); ++it) {
pcstates->push_back(it->second); pcstates->push_back(it->second);
} }
// Reverse the vector order (so the higest bin comes first) // Reverse the vector order (so the higest bin comes first)
reverse(pcstates->begin(), pcstates->end()); reverse(pcstates->begin(), pcstates->end());
} }
static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_t>* pcrstates) { static inline uint32_t sm_right(const uint8_t *ks, uint8_t *mask, vector<uint64_t> *pcrstates) {
uint8_t tmp_mask[16]; uint8_t tmp_mask[16];
size_t pos, bits, bit, topbits; size_t pos, bits, bit, topbits;
map<uint64_t,uint64_t> bincstates; map<uint64_t, uint64_t> bincstates;
map<uint64_t,uint64_t>::iterator it; map<uint64_t, uint64_t>::iterator it;
uint8_t bt; uint8_t bt;
topbits = 0; topbits = 0;
@ -662,27 +662,27 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector<uint64_
} }
static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_index, cipher_state_side css) { static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_index, cipher_state_side css) {
uint8_t btGc,in; uint8_t btGc, in;
vector<cs_t> ncstates; vector<cs_t> ncstates;
vector<cs_t> prev_ncstates; vector<cs_t> prev_ncstates;
vector<cs_t>::iterator it,itnew; vector<cs_t>::iterator it, itnew;
// Loop through the complete entryphy of 5 bits for each candidate // Loop through the complete entryphy of 5 bits for each candidate
// We ignore zero (xor 0x00) to avoid duplicates // We ignore zero (xor 0x00) to avoid duplicates
for (btGc=0; btGc<0x20; btGc++) { for (btGc = 0; btGc < 0x20; btGc++) {
// Copy the original candidates that are supplied // Copy the original candidates that are supplied
ncstates = *pcstates; ncstates = *pcstates;
// Rollback the (candidate) cipher states with this input // Rollback the (candidate) cipher states with this input
if (css == CSS_RIGHT) { if (css == CSS_RIGHT) {
in = btGc << 3; in = btGc << 3;
previous_right(in,&ncstates); previous_right(in, &ncstates);
} else { } else {
in = btGc; in = btGc;
previous_left(in,&ncstates); previous_left(in, &ncstates);
} }
for(itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) { for (itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) {
// Wipe away the invalid states // Wipe away the invalid states
if (itnew->invalid == false) { if (itnew->invalid == false) {
itnew->Gc[gc_byte_index] = in; itnew->Gc[gc_byte_index] = in;
@ -695,46 +695,46 @@ static inline void previous_all_input(vector<cs_t> *pcstates, uint32_t gc_byte_i
*pcstates = prev_ncstates; *pcstates = prev_ncstates;
} }
static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, const uint64_t rstate_after_gc, const uint8_t* Q, vector<cs_t>* pcstates) { static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, const uint64_t rstate_after_gc, const uint8_t *Q, vector<cs_t> *pcstates) {
vector<cs_t>::iterator it; vector<cs_t>::iterator it;
vector<cs_t> csl_cand; vector<cs_t> csl_cand;
map<uint64_t,uint64_t> matchbox; map<uint64_t, uint64_t> matchbox;
map<uint64_t,uint64_t>::iterator itmatch; map<uint64_t, uint64_t>::iterator itmatch;
uint64_t rstate; uint64_t rstate;
size_t counter; size_t counter;
cs_t state; cs_t state;
// Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3)
for (counter=0; counter<0x100000; counter++) { for (counter = 0; counter < 0x100000; counter++) {
rstate = rstate_before_gc; rstate = rstate_before_gc;
next_right_fast((counter >> 12) & 0xf8,&rstate); next_right_fast((counter >> 12) & 0xf8, &rstate);
next_right_fast((counter >> 7) & 0xf8,&rstate); next_right_fast((counter >> 7) & 0xf8, &rstate);
next_right_fast(Q[4],&rstate); next_right_fast(Q[4], &rstate);
next_right_fast((counter >> 2) & 0xf8,&rstate); next_right_fast((counter >> 2) & 0xf8, &rstate);
next_right_fast((counter << 3) & 0xf8,&rstate); next_right_fast((counter << 3) & 0xf8, &rstate);
next_right_fast(Q[5],&rstate); next_right_fast(Q[5], &rstate);
matchbox[rstate] = counter; matchbox[rstate] = counter;
} }
// Reset and initialize the cryptostate and vecctor // Reset and initialize the cryptostate and vecctor
memset(&state,0x00,sizeof(cs_t)); memset(&state, 0x00, sizeof(cs_t));
state.invalid = false; state.invalid = false;
state.r = rstate_after_gc; state.r = rstate_after_gc;
csl_cand.clear(); csl_cand.clear();
csl_cand.push_back(state); csl_cand.push_back(state);
// Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7) // Generate 2^20(+splitting) different (5 bits) values for the last 4 Gc bytes (4,5,6,7)
previous_right(Q[7],&csl_cand); previous_right(Q[7], &csl_cand);
previous_all_input(&csl_cand,7,CSS_RIGHT); previous_all_input(&csl_cand, 7, CSS_RIGHT);
previous_all_input(&csl_cand,6,CSS_RIGHT); previous_all_input(&csl_cand, 6, CSS_RIGHT);
previous_right(Q[6],&csl_cand); previous_right(Q[6], &csl_cand);
previous_all_input(&csl_cand,5,CSS_RIGHT); previous_all_input(&csl_cand, 5, CSS_RIGHT);
previous_all_input(&csl_cand,4,CSS_RIGHT); previous_all_input(&csl_cand, 4, CSS_RIGHT);
pcstates->clear(); pcstates->clear();
// Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits)
for (it=csl_cand.begin();it!=csl_cand.end();++it) { for (it = csl_cand.begin(); it != csl_cand.end(); ++it) {
itmatch = matchbox.find(it->r); itmatch = matchbox.find(it->r);
if (itmatch != matchbox.end()) { if (itmatch != matchbox.end()) {
it->Gc[0] = (itmatch->second >> 12) & 0xf8; it->Gc[0] = (itmatch->second >> 12) & 0xf8;
@ -747,7 +747,7 @@ static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, c
} }
} }
static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcstates) { static inline void sm_left(const uint8_t *ks, uint8_t *mask, vector<cs_t> *pcstates) {
map<uint64_t, cs_t> bincstates; map<uint64_t, cs_t> bincstates;
map<uint64_t, cs_t>::iterator it; map<uint64_t, cs_t>::iterator it;
uint64_t counter, lstate; uint64_t counter, lstate;
@ -755,7 +755,7 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
uint8_t correct_bits[16]; uint8_t correct_bits[16];
uint8_t bt; uint8_t bt;
cs_t state; cs_t state;
lookup_entry* lookup; lookup_entry *lookup;
// Reset and initialize the cryptostate and vecctor // Reset and initialize the cryptostate and vecctor
memset(&state, 0x00, sizeof(cs_t)); memset(&state, 0x00, sizeof(cs_t));
@ -766,13 +766,13 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
for (pos = 0; pos < 16; pos++) { for (pos = 0; pos < 16; pos++) {
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt = lookup->out << 4; bt = lookup->out << 4;
lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30));
lookup = &(lookup_left[((lstate) & 0xf801f)]); lookup = &(lookup_left[((lstate) & 0xf801f)]);
lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30));
bt |= lookup->out; bt |= lookup->out;
// xor the bits with the keystream and count the "correct" bits // xor the bits with the keystream and count the "correct" bits
@ -813,11 +813,11 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
state.l = counter; state.l = counter;
// Make sure the bits are used for ordering // Make sure the bits are used for ordering
bincstates[(((uint64_t)bits)<<56) | counter] = state; bincstates[(((uint64_t)bits) << 56) | counter] = state;
} }
if ((counter & 0xffffffffull) == 0) { if ((counter & 0xffffffffull) == 0) {
printf("%02.1f%%.", ((float)100/8)*(counter>>32)); printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32));
fflush(stdout); fflush(stdout);
} }
} }
@ -828,23 +828,23 @@ static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector<cs_t>* pcsta
pcstates->clear(); pcstates->clear();
// Copy the order the states from lowest-bin to highest-bin // Copy the order the states from lowest-bin to highest-bin
for(it = bincstates.begin(); it != bincstates.end(); ++it) { for (it = bincstates.begin(); it != bincstates.end(); ++it) {
pcstates->push_back(it->second); pcstates->push_back(it->second);
} }
// Reverse the vector order (so the higest bin comes first) // Reverse the vector order (so the higest bin comes first)
reverse(pcstates->begin(), pcstates->end()); reverse(pcstates->begin(), pcstates->end());
} }
static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t* Q, vector<cs_t>* pcstates) { static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t *Q, vector<cs_t> *pcstates) {
vector<cs_t> csl_cand,csl_search; vector<cs_t> csl_cand, csl_search;
vector<cs_t>::iterator itsearch,itcand; vector<cs_t>::iterator itsearch, itcand;
map<uint64_t,uint64_t> matchbox; map<uint64_t, uint64_t> matchbox;
map<uint64_t,uint64_t>::iterator itmatch; map<uint64_t, uint64_t>::iterator itmatch;
uint64_t lstate; uint64_t lstate;
size_t counter; size_t counter;
// Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3)
for (counter=0; counter < 0x100000; counter++) { for (counter = 0; counter < 0x100000; counter++) {
lstate = lstate_before_gc; lstate = lstate_before_gc;
next_left_fast((counter >> 15) & 0x1f, &lstate); next_left_fast((counter >> 15) & 0x1f, &lstate);
next_left_fast((counter >> 10) & 0x1f, &lstate); next_left_fast((counter >> 10) & 0x1f, &lstate);
@ -872,9 +872,9 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
previous_all_input(&csl_search, 4, CSS_LEFT); previous_all_input(&csl_search, 4, CSS_LEFT);
// Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits)
for(itsearch = csl_search.begin(); itsearch != csl_search.end(); ++itsearch) { for (itsearch = csl_search.begin(); itsearch != csl_search.end(); ++itsearch) {
itmatch = matchbox.find(itsearch->l); itmatch = matchbox.find(itsearch->l);
if (itmatch != matchbox.end()){ if (itmatch != matchbox.end()) {
itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f; itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f;
itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f; itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f;
itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f; itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f;
@ -889,14 +889,14 @@ static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, co
printf("\n"); printf("\n");
} }
void combine_valid_left_right_states(vector<cs_t>* plcstates, vector<cs_t>* prcstates, vector<uint64_t>* pgc_candidates) { void combine_valid_left_right_states(vector<cs_t> *plcstates, vector<cs_t> *prcstates, vector<uint64_t> *pgc_candidates) {
vector<cs_t>::iterator itl, itr; vector<cs_t>::iterator itl, itr;
size_t pos,count; size_t pos, count;
uint64_t gc; uint64_t gc;
bool valid; bool valid;
vector<cs_t> outer, inner; vector<cs_t> outer, inner;
if ( plcstates->size() > prcstates->size()) { if (plcstates->size() > prcstates->size()) {
outer = *plcstates; outer = *plcstates;
inner = *prcstates; inner = *prcstates;
} else { } else {
@ -909,8 +909,8 @@ void combine_valid_left_right_states(vector<cs_t>* plcstates, vector<cs_t>* prcs
// Clean up the candidate list // Clean up the candidate list
pgc_candidates->clear(); pgc_candidates->clear();
count = 0; count = 0;
for( itl = outer.begin(); itl != outer.end(); ++itl) { for (itl = outer.begin(); itl != outer.end(); ++itl) {
for(itr = inner.begin(); itr != inner.end(); ++itr) { for (itr = inner.begin(); itr != inner.end(); ++itr) {
valid = true; valid = true;
// Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc) // Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc)
for (pos = 0; pos < 8; pos++) { for (pos = 0; pos < 8; pos++) {
@ -932,20 +932,20 @@ void combine_valid_left_right_states(vector<cs_t>* plcstates, vector<cs_t>* prcs
count++; count++;
} }
} }
printf("Found a total of " _YELLOW_("%llu")" combinations, ",((unsigned long long)plcstates->size()) * prcstates->size()); printf("Found a total of " _YELLOW_("%llu")" combinations, ", ((unsigned long long)plcstates->size()) * prcstates->size());
printf("but only " _GREEN_("%lu")" were valid!\n", pgc_candidates->size()); printf("but only " _GREEN_("%lu")" were valid!\n", pgc_candidates->size());
} }
static void ice_compare( static void ice_compare(
uint8_t offset, uint8_t offset,
uint8_t skips, uint8_t skips,
vector<uint64_t>* candidates, vector<uint64_t> *candidates,
crypto_state_t* ostate, crypto_state_t *ostate,
uint8_t *Ci, uint8_t *Ci,
uint8_t *Q, uint8_t *Q,
uint8_t *Ch, uint8_t *Ch,
uint8_t *Ci_1 uint8_t *Ci_1
) { ) {
uint8_t Gc_chk[8]; uint8_t Gc_chk[8];
uint8_t Ch_chk[ 8]; uint8_t Ch_chk[ 8];
uint8_t Ci_1_chk[ 8]; uint8_t Ci_1_chk[ 8];
@ -968,7 +968,7 @@ static void ice_compare(
} }
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
size_t pos; size_t pos;
crypto_state_t ostate; crypto_state_t ostate;
uint64_t rstate_before_gc, rstate_after_gc; uint64_t rstate_before_gc, rstate_after_gc;
@ -1015,32 +1015,42 @@ int main(int argc, const char* argv[]) {
if (argc == 2) { if (argc == 2) {
// Generate random values for the key and randoms // Generate random values for the key and randoms
srand((uint32_t)time(NULL)); srand((uint32_t)time(NULL));
for (pos = 0; pos<8; pos++) { for (pos = 0; pos < 8; pos++) {
Gc[pos] = rand(); Gc[pos] = rand();
Ci[pos] = rand(); Ci[pos] = rand();
Q[pos] = rand(); Q[pos] = rand();
} }
sm_auth(Gc,Ci,Q,Ch,Ci_1,&ostate); sm_auth(Gc, Ci, Q, Ch, Ci_1, &ostate);
printf(" Gc: "); print_bytes(Gc,8); printf(" Gc: ");
print_bytes(Gc, 8);
} else { } else {
sscanf(argv[1],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); sscanf(argv[1], "%016" SCNx64, &nCi);
sscanf(argv[2],"%016" SCNx64,&nQ); num_to_bytes(nQ,8,Q); num_to_bytes(nCi, 8, Ci);
sscanf(argv[3],"%016" SCNx64,&nCh); num_to_bytes(nCh,8,Ch); sscanf(argv[2], "%016" SCNx64, &nQ);
sscanf(argv[4],"%016" SCNx64,&nCi_1); num_to_bytes(nCi_1,8,Ci_1); num_to_bytes(nQ, 8, Q);
sscanf(argv[3], "%016" SCNx64, &nCh);
num_to_bytes(nCh, 8, Ch);
sscanf(argv[4], "%016" SCNx64, &nCi_1);
num_to_bytes(nCi_1, 8, Ci_1);
printf(" Gc: unknown\n"); printf(" Gc: unknown\n");
} }
for (pos = 0; pos<8; pos++) { for (pos = 0; pos < 8; pos++) {
ks[2*pos] = Ci_1[pos]; ks[2 * pos] = Ci_1[pos];
ks[(2*pos)+1] = Ch[pos]; ks[(2 * pos) + 1] = Ch[pos];
} }
printf(" Ci: "); print_bytes(Ci,8); printf(" Ci: ");
printf(" Q: "); print_bytes(Q,8); print_bytes(Ci, 8);
printf(" Ch: "); print_bytes(Ch,8); printf(" Q: ");
printf("Ci+1: "); print_bytes(Ci_1,8); print_bytes(Q, 8);
printf(" Ch: ");
print_bytes(Ch, 8);
printf("Ci+1: ");
print_bytes(Ci_1, 8);
printf("\n"); printf("\n");
printf(" Ks: "); print_bytes(ks,16); printf(" Ks: ");
print_bytes(ks, 16);
printf("\n"); printf("\n");
printf("\nMultithreaded, will use " _YELLOW_("%u") " threads\n", g_num_cpus); printf("\nMultithreaded, will use " _YELLOW_("%u") " threads\n", g_num_cpus);
@ -1061,12 +1071,12 @@ int main(int argc, const char* argv[]) {
lstate_before_gc = 0; lstate_before_gc = 0;
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
next_right_fast(Ci[2*pos ], &rstate_before_gc); next_right_fast(Ci[2 * pos ], &rstate_before_gc);
next_right_fast(Ci[2*pos+1], &rstate_before_gc); next_right_fast(Ci[2 * pos + 1], &rstate_before_gc);
next_right_fast(Q[pos], &rstate_before_gc); next_right_fast(Q[pos], &rstate_before_gc);
next_left_fast(Ci[2*pos ], &lstate_before_gc); next_left_fast(Ci[2 * pos ], &lstate_before_gc);
next_left_fast(Ci[2*pos+1], &lstate_before_gc); next_left_fast(Ci[2 * pos + 1], &lstate_before_gc);
next_left_fast(Q[pos], &lstate_before_gc); next_left_fast(Q[pos], &lstate_before_gc);
} }
@ -1112,10 +1122,10 @@ int main(int argc, const char* argv[]) {
std::vector<std::thread> threads(g_num_cpus); std::vector<std::thread> threads(g_num_cpus);
for (uint8_t m = 0; m < g_num_cpus; m++) { for (uint8_t m = 0; m < g_num_cpus; m++) {
threads[m] = std::thread( ice_compare, m, g_num_cpus, &pgc_candidates, &ostate, ref(Ci), ref(Q), ref(Ch), ref(Ci_1) ); threads[m] = std::thread(ice_compare, m, g_num_cpus, &pgc_candidates, &ostate, ref(Ci), ref(Q), ref(Ch), ref(Ci_1));
} }
for (auto& t : threads) { for (auto &t : threads) {
t.join(); t.join();
} }

View file

@ -1,16 +1,14 @@
#include "util.h" #include "util.h"
#include <stdio.h> #include <stdio.h>
void num_to_bytes(uint64_t n, size_t len, uint8_t *dst) void num_to_bytes(uint64_t n, size_t len, uint8_t *dst) {
{
while (len--) { while (len--) {
dst[len] = (uint8_t)n; dst[len] = (uint8_t)n;
n >>= 8; n >>= 8;
} }
} }
void print_bytes(const uint8_t *pbtData, const size_t szLen) void print_bytes(const uint8_t *pbtData, const size_t szLen) {
{
size_t uiPos; size_t uiPos;
for (uiPos = 0; uiPos < szLen; uiPos++) { for (uiPos = 0; uiPos < szLen; uiPos++) {
printf("%02x ", pbtData[uiPos]); printf("%02x ", pbtData[uiPos]);