diff --git a/common/cryptorf/cryptolib.c b/common/cryptorf/cryptolib.c index 26b07f824..bf597317b 100644 --- a/common/cryptorf/cryptolib.c +++ b/common/cryptorf/cryptolib.c @@ -27,35 +27,32 @@ #include typedef enum { - CA_ENCRYPT = 0x01, - CA_DECRYPT = 0x02 + CA_ENCRYPT = 0x01, + CA_DECRYPT = 0x02 } CryptoAction; int counter = 0; -static uint8_t nibbles_to_byte(nibble b0, nibble b1) -{ - // Combine both nibbles - return ((b0 << 4) | b1); +static uint8_t nibbles_to_byte(nibble b0, nibble b1) { + // Combine both nibbles + return ((b0 << 4) | b1); } -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 - if (a < m) return a; +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 + if (a < m) return a; - // Compute the modular value - a %= m; + // 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; + // Return the funny value, when the output was now zero, return the modular value + return (a == 0) ? m : a; } -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 - uint8_t mask = (1 << n_bits) - 1; - return ((a << 1) | (a >> (n_bits - 1))) & mask; +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 + uint8_t mask = (1 << n_bits) - 1; + return ((a << 1) | (a >> (n_bits - 1))) & mask; } /* @@ -92,276 +89,258 @@ static void reconstruct_nibbles(crypto_state s) s->b1 |= s->b1r & s->b1s; } */ -static void next_left(uint8_t in, crypto_state s) -{ - uint8_t b3, b6, bx; +static void next_left(uint8_t in, crypto_state s) { + uint8_t b3, b6, bx; - // Update the left cipher state with the input byte - s->l ^= ((in & 0x1f) << 20); + // Update the left cipher state with the input byte + s->l ^= ((in & 0x1f) << 20); - // Extract the two (5 bits) values used for modular addtion - b3 = (uint8_t)((s->l >> 15) & 0x1f); - b6 = (uint8_t)(s->l & 0x1f); + // Extract the two (5 bits) values used for modular addtion + b3 = (uint8_t)((s->l >> 15) & 0x1f); + b6 = (uint8_t)(s->l & 0x1f); - // Compute the modular addition - bx = funny_mod(b3 + bit_rotate_left(b6, 5), 0x1f); + // Compute the modular addition + bx = funny_mod(b3 + bit_rotate_left(b6, 5), 0x1f); - // Rotate the left cipher state 5 bits - s->l = ((s->l >> 5) | ((uint64_t)bx << 30)); + // Rotate the left cipher state 5 bits + s->l = ((s->l >> 5) | ((uint64_t)bx << 30)); - // Save the 4 left output bits used for b1 - s->b1l = ((bx ^ b3) & 0x0f); + // Save the 4 left output bits used for b1 + s->b1l = ((bx ^ b3) & 0x0f); } -static void next_right(uint8_t in, crypto_state s) -{ - uint8_t b16, b18, bx; +static void next_right(uint8_t in, crypto_state s) { + uint8_t b16, b18, bx; - // Update the right cipher state with the input byte - s->r ^= ((in & 0xf8) << 12); + // Update the right cipher state with the input byte + s->r ^= ((in & 0xf8) << 12); - // Extract the two (5 bits) values used for modular addtion - b16 = (uint8_t)((s->r >> 10) & 0x1f); - b18 = (uint8_t)(s->r & 0x1f); + // Extract the two (5 bits) values used for modular addtion + b16 = (uint8_t)((s->r >> 10) & 0x1f); + b18 = (uint8_t)(s->r & 0x1f); - // Compute the modular addition - bx = funny_mod(b18 + b16, 0x1f); + // Compute the modular addition + bx = funny_mod(b18 + b16, 0x1f); - // Rotate the right cipher state 5 bits - s->r = ((s->r >> 5) | ((uint64_t)bx << 20)); + // Rotate the right cipher state 5 bits + s->r = ((s->r >> 5) | ((uint64_t)bx << 20)); - // Save the 4 right output bits used for b1 - s->b1r = ((bx ^ b16) & 0x0f); + // Save the 4 right output bits used for b1 + s->b1r = ((bx ^ b16) & 0x0f); } -static void next_middle(uint8_t in, crypto_state s) -{ - uint8_t b12, b13, bx; +static void next_middle(uint8_t in, crypto_state s) { + uint8_t b12, b13, bx; - // Update the middle cipher state with the input byte - s->m ^= (((((uint64_t)in << 3) & 0x7f) | (in >> 5)) << 14); + // Update the middle cipher state with the input byte + s->m ^= (((((uint64_t)in << 3) & 0x7f) | (in >> 5)) << 14); - // Extract the two (7 bits) values used for modular addtion - b12 = (uint8_t)((s->m >> 7) & 0x7f); - b13 = (uint8_t)(s->m & 0x7f); + // Extract the two (7 bits) values used for modular addtion + b12 = (uint8_t)((s->m >> 7) & 0x7f); + b13 = (uint8_t)(s->m & 0x7f); - // Compute the modular addition - bx = (funny_mod(b12 + bit_rotate_left(b13, 7), 0x7f)); + // Compute the modular addition + bx = (funny_mod(b12 + bit_rotate_left(b13, 7), 0x7f)); - // Rotate the middle cipher state 7 bits - s->m = ((s->m >> 7) | ((uint64_t)bx << 42)); + // Rotate the middle cipher state 7 bits + s->m = ((s->m >> 7) | ((uint64_t)bx << 42)); - // Save the 4 middle selector bits used for b1 - s->b1s = bx & 0x0f; + // Save the 4 middle selector bits used for b1 + s->b1s = bx & 0x0f; } -static void next(const bool feedback, uint8_t in, crypto_state s) -{ - // Initialize the (optional) input parameter - uint8_t a = in; +static void next(const bool feedback, uint8_t in, crypto_state s) { + // Initialize the (optional) input parameter + uint8_t a = in; - // Only Cryptomemory uses feedback - if (feedback) { - // Construct the cipher update 'a' from (input ^ feedback) - a = in ^ nibbles_to_byte(s->b0, s->b1); - } - - // Shift the cipher state - next_left(a, s); - next_middle(a, s); - next_right(a, s); - - // For active states we can use the available (previous) 'b1' nibble, - // otherwise use reconstruct_nibbles() to generate them - // reconstruct_nibbles(s) - - // The nible from b1 shifts to b0 - s->b0 = s->b1; - - // Construct the new value of nible b1 - s->b1 = s->b1l & ~(s->b1s); - s->b1 |= s->b1r & s->b1s; -} - -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--) 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) -{ - 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(feedback, n, Ci[2 * pos ], s); - next_n(feedback, n, Ci[2 * pos + 1], s); - next(feedback, 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(feedback, n, Gc[2 * pos ], s); - next_n(feedback, n, Gc[2 * pos + 1], s); - next(feedback, Q[pos + 4], s); - } -} - -static uint8_t cm_byte(crypto_state s) -{ - // Construct keystream byte by combining both nibbles - return nibbles_to_byte(s->b0, s->b1); -} - -static uint8_t sm_byte(crypto_state s) -{ - uint8_t ks; - - // Construct keystream byte by combining 2 parts from 4 nibbles - next_n(false, 2, 0, s); - ks = s->b1 << 4; - next_n(false, 2, 0, s); - ks |= s->b1; - - return ks; -} - -void print_crypto_state(const char *text, crypto_state s) -{ - int pos; - - printf("%s", text); - for (pos = 6; pos >= 0; pos--) - printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f); - - printf(" |"); - for (pos = 6; pos >= 0; pos--) - printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f); - - printf(" |"); - for (pos = 4; pos >= 0; pos--) - printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f); - - printf(" | %02x", cm_byte(s)); - 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) -{ - size_t pos; - - initialize(false, Gc, Ci, Q, 1, s); - - // Generate challange answer for Tag and Reader - for (pos = 0; pos < 8; pos++) { - Ci_1[pos] = sm_byte(s); - Ch[pos] = sm_byte(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; - - initialize(true, Gc, Ci, Q, 3, s); - - // Construct the reader-answer (challange) - next_n(true, 6, 0, s); - Ch[0] = cm_byte(s); - for (pos = 1; pos < 8; pos++) { - next_n(true, 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_n(true, 2, 0, s); - Ci_1[pos] = cm_byte(s); - } - - // Construct the session key (Ci+2) - for (pos = 0; pos < 8; pos++) { - next_n(true, 2, 0, s); - Ci_2[pos] = cm_byte(s); - } - - // Prepare the cipher for encryption by shifting 3 more times - 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) -{ - size_t pos; - uint8_t bt; - - next_n(true, 5, 0, s); - next(true, offset, s); - next_n(true, 5, 0, s); - next(true, 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(true, bt, s); - } else { - next(true, in[pos], s); + // Only Cryptomemory uses feedback + if (feedback) { + // Construct the cipher update 'a' from (input ^ feedback) + a = in ^ nibbles_to_byte(s->b0, s->b1); } - // Shift the cipher state 5 times + // Shift the cipher state + next_left(a, s); + next_middle(a, s); + next_right(a, s); + + // For active states we can use the available (previous) 'b1' nibble, + // otherwise use reconstruct_nibbles() to generate them + // reconstruct_nibbles(s) + + // The nible from b1 shifts to b0 + s->b0 = s->b1; + + // Construct the new value of nible b1 + s->b1 = s->b1l & ~(s->b1s); + s->b1 |= s->b1r & s->b1s; +} + +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--) 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) { + 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(feedback, n, Ci[2 * pos ], s); + next_n(feedback, n, Ci[2 * pos + 1], s); + next(feedback, 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(feedback, n, Gc[2 * pos ], s); + next_n(feedback, n, Gc[2 * pos + 1], s); + next(feedback, Q[pos + 4], s); + } +} + +static uint8_t cm_byte(crypto_state s) { + // Construct keystream byte by combining both nibbles + return nibbles_to_byte(s->b0, s->b1); +} + +static uint8_t sm_byte(crypto_state s) { + uint8_t ks; + + // Construct keystream byte by combining 2 parts from 4 nibbles + next_n(false, 2, 0, s); + ks = s->b1 << 4; + next_n(false, 2, 0, s); + ks |= s->b1; + + return ks; +} + +void print_crypto_state(const char *text, crypto_state s) { + int pos; + + printf("%s", text); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f); + + printf(" |"); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f); + + printf(" |"); + for (pos = 4; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f); + + printf(" | %02x", cm_byte(s)); + 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) { + size_t pos; + + initialize(false, Gc, Ci, Q, 1, s); + + // Generate challange answer for Tag and Reader + for (pos = 0; pos < 8; pos++) { + Ci_1[pos] = sm_byte(s); + Ch[pos] = sm_byte(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; + + initialize(true, Gc, Ci, Q, 3, s); + + // Construct the reader-answer (challange) + next_n(true, 6, 0, s); + Ch[0] = cm_byte(s); + for (pos = 1; pos < 8; pos++) { + next_n(true, 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_n(true, 2, 0, s); + Ci_1[pos] = cm_byte(s); + } + + // Construct the session key (Ci+2) + for (pos = 0; pos < 8; pos++) { + next_n(true, 2, 0, s); + Ci_2[pos] = cm_byte(s); + } + + // Prepare the cipher for encryption by shifting 3 more times + 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) { + size_t pos; + uint8_t bt; + next_n(true, 5, 0, s); - } + next(true, offset, s); + next_n(true, 5, 0, s); + next(true, 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(true, bt, s); + } else { + next(true, in[pos], s); + } + + // Shift the cipher state 5 times + next_n(true, 5, 0, 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(true, 0, s); - cm_crypt(CA_ENCRYPT, offset, len, ct, pt, 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(true, 0, 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) -{ - next_n(true, 5, 0, s); - next(true, 0, s); - cm_crypt(CA_DECRYPT, 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) { + next_n(true, 5, 0, s); + next(true, 0, 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) -{ - cm_crypt(CA_ENCRYPT, offset, len, pt, NULL, 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); } -void cm_grind_set_user_zone(const uint8_t zone, crypto_state s) -{ - next(true, zone, s); +void cm_grind_set_user_zone(const uint8_t zone, crypto_state s) { + next(true, zone, s); } -void cm_mac(uint8_t *mac, crypto_state s) -{ - next_n(true, 10, 0, s); - if (mac) - mac[0] = cm_byte(s); +void cm_mac(uint8_t *mac, crypto_state s) { + next_n(true, 10, 0, s); + if (mac) + mac[0] = cm_byte(s); - next_n(true, 5, 0, s); - if (mac) - mac[1] = cm_byte(s); + next_n(true, 5, 0, s); + if (mac) + mac[1] = cm_byte(s); } -void cm_password(const uint8_t *pt, uint8_t *ct, crypto_state s) -{ - for (size_t pos = 0; pos < 3; pos++) { - next_n(true, 5, pt[pos], s); - ct[pos] = cm_byte(s); - } +void cm_password(const uint8_t *pt, uint8_t *ct, crypto_state s) { + for (size_t pos = 0; pos < 3; pos++) { + next_n(true, 5, pt[pos], s); + ct[pos] = cm_byte(s); + } } diff --git a/common/cryptorf/cryptolib.h b/common/cryptorf/cryptolib.h index 0f31d8870..978afd27b 100644 --- a/common/cryptorf/cryptolib.h +++ b/common/cryptorf/cryptolib.h @@ -33,14 +33,14 @@ extern "C" { typedef uint8_t nibble; typedef struct { - uint64_t l; - uint64_t m; - uint64_t r; - nibble b0; - nibble b1; - nibble b1l; - nibble b1r; - nibble b1s; + 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; diff --git a/common/cryptorf/cryptolib_baloncu.c b/common/cryptorf/cryptolib_baloncu.c new file mode 100644 index 000000000..6a69250d3 --- /dev/null +++ b/common/cryptorf/cryptolib_baloncu.c @@ -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); + } +} diff --git a/common/cryptorf/cryptolib_baloncu.h b/common/cryptorf/cryptolib_baloncu.h new file mode 100644 index 000000000..3140b564c --- /dev/null +++ b/common/cryptorf/cryptolib_baloncu.h @@ -0,0 +1,41 @@ +#ifndef _CRYPTOLIB_H_ +#define _CRYPTOLIB_H_ + +#include +#include +#include +#include +#include +#include + +#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_ diff --git a/tools/cryptorf/cm.c b/tools/cryptorf/cm.c index 87e577b36..be7b79f54 100644 --- a/tools/cryptorf/cm.c +++ b/tools/cryptorf/cm.c @@ -1,9 +1,9 @@ /* - * + * * CryptoMemory simulation * * Copyright (C) 2010, Flavio D. Garcia, Peter van Rossum, Roel Verdult - * and Ronny Wichers Schreur. Radboud University Nijmegen + * and Ronny Wichers Schreur. Radboud University Nijmegen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include @@ -26,71 +26,85 @@ #include "cryptolib.h" #include "util.h" #ifdef _MSC_VER - // avoid scanf warnings in Visual Studio - #define _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_DEPRECATE +// avoid scanf warnings in Visual Studio +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_DEPRECATE #endif -int main(int argc, const char* argv[]) -{ - // Cryptomemory state - crypto_state_t s; +int main(int argc, const char *argv[]) { + // Cryptomemory state + crypto_state_t s; - // Main authentication values - uint8_t Q[8]; // Reader key-auth random - uint8_t Gc[8]; // Secret seed - uint8_t Ci[8]; // Card random (last state) - uint8_t Ch[8]; // Reader answer (challenge) - uint8_t Ci_1[8]; // Card answer - uint8_t Ci_2[8]; // Session key - - // Session authentication values - uint8_t Qs[8]; // Reader session-auth random - uint8_t Chs[8]; // Reader session-answer (challenge) - uint8_t Ci_1s[8]; // Card answer for session - uint8_t Ci_2s[8]; // Is this used? + // Main authentication values + uint8_t Q[8]; // Reader key-auth random + uint8_t Gc[8]; // Secret seed + uint8_t Ci[8]; // Card random (last state) + uint8_t Ch[8]; // Reader answer (challenge) + uint8_t Ci_1[8]; // Card answer + uint8_t Ci_2[8]; // Session key - // Various argument options - uint64_t nGc; // Card secret - uint64_t nCi; // Card random - uint64_t nQ; // Reader main-random - uint64_t nQs; // Reader session-random + // Session authentication values + uint8_t Qs[8]; // Reader session-auth random + uint8_t Chs[8]; // Reader session-answer (challenge) + uint8_t Ci_1s[8]; // Card answer for session + uint8_t Ci_2s[8]; // Is this used? - // Show header and help syntax - printf("CryptoMemory simulator - (c) Radboud University Nijmegen\n"); - if (argc < 5) - { - printf("\nsyntax: cm \n"); - return 1; - } + // Various argument options + uint64_t nGc; // Card secret + uint64_t nCi; // Card random + uint64_t nQ; // Reader main-random + uint64_t nQs; // Reader session-random - // Parse arguments - sscanf(argv[1],"%016" SCNx64,&nGc); num_to_bytes(nGc,8,Gc); - sscanf(argv[2],"%016" SCNx64,&nCi); 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); + // Show header and help syntax + printf("CryptoMemory simulator - (c) Radboud University Nijmegen\n"); + if (argc < 5) { + printf("\nsyntax: cm \n"); + return 1; + } - // Calculate authentication - cm_auth(Gc,Ci,Q,Ch,Ci_1,Ci_2,&s); + // Parse arguments + sscanf(argv[1], "%016" SCNx64, &nGc); + num_to_bytes(nGc, 8, Gc); + sscanf(argv[2], "%016" SCNx64, &nCi); + 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); - printf("\nAuthenticate\n"); - printf(" Gc: "); print_bytes(Gc,8); - printf(" Ci: "); print_bytes(Ci,8); - printf(" Q: "); 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); + // Calculate authentication + cm_auth(Gc, Ci, Q, Ch, Ci_1, Ci_2, &s); - cm_auth(Ci_2,Ci_1,Qs,Chs,Ci_1s,Ci_2s,&s); + printf("\nAuthenticate\n"); + printf(" Gc: "); + print_bytes(Gc, 8); + printf(" Ci: "); + print_bytes(Ci, 8); + printf(" Q: "); + 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); - printf("\nVerify Crypto (Session Key)\n"); - printf(" Gc(s): "); print_bytes(Ci_2,8); - printf(" Ci(s): "); print_bytes(Ci_1,8); - printf(" Q(s): "); 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); + cm_auth(Ci_2, Ci_1, Qs, Chs, Ci_1s, Ci_2s, &s); - printf("\n"); - return 0; + printf("\nVerify Crypto (Session Key)\n"); + printf(" Gc(s): "); + print_bytes(Ci_2, 8); + printf(" Ci(s): "); + print_bytes(Ci_1, 8); + printf(" Q(s): "); + 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"); + return 0; } diff --git a/tools/cryptorf/sm.c b/tools/cryptorf/sm.c index fde70d3a5..b604c9dfa 100644 --- a/tools/cryptorf/sm.c +++ b/tools/cryptorf/sm.c @@ -1,9 +1,9 @@ /* - * + * * SecureMemory simulation * * Copyright (C) 2010, Flavio D. Garcia, Peter van Rossum, Roel Verdult - * and Ronny Wichers Schreur. Radboud University Nijmegen + * and Ronny Wichers Schreur. Radboud University Nijmegen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #include @@ -26,58 +26,63 @@ #include "cryptolib.h" #include "util.h" #ifdef _MSC_VER - // avoid scanf warnings in Visual Studio - #define _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_DEPRECATE +// avoid scanf warnings in Visual Studio +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_DEPRECATE #endif -int main(int argc, const char* argv[]) -{ - // Cryptomemory state - crypto_state_t s; - size_t pos; +int main(int argc, const char *argv[]) { + // Cryptomemory state + crypto_state_t s; + size_t pos; - 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 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 Ci_1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Card answer + 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 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 Ci_1[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Card answer - // Various argument options - uint64_t nGc; // Card secret - uint64_t nCi; // Card random - uint64_t nQ; // Reader main-random + // Various argument options + uint64_t nGc; // Card secret + uint64_t nCi; // Card random + uint64_t nQ; // Reader main-random - // Show header and help syntax - printf("SecureMemory simulator - (c) Radboud University Nijmegen\n"); - if (argc < 4) - { - printf("\nsyntax: sm \n"); - return 1; - } + // Show header and help syntax + printf("SecureMemory simulator - (c) Radboud University Nijmegen\n"); + if (argc < 4) { + printf("\nsyntax: sm \n"); + return 1; + } - // Parse arguments - sscanf(argv[1],"%016" SCNx64,&nGc); num_to_bytes(nGc,8,Gc); - sscanf(argv[2],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); - sscanf(argv[3],"%016" SCNx64,&nQ); num_to_bytes(nQ,8,Q); + // Parse arguments + sscanf(argv[1], "%016" SCNx64, &nGc); + num_to_bytes(nGc, 8, Gc); + 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 - sm_auth(Gc,Ci,Q,Ch,Ci_1,&s); + // Calculate authentication + sm_auth(Gc, Ci, Q, Ch, Ci_1, &s); - printf("\nAuthentication info\n\n"); - printf(" Gc: "); print_bytes(Gc,8); - printf(" Ci: "); print_bytes(Ci,8); - printf(" Q: "); print_bytes(Q,8); - printf(" Ch: "); print_bytes(Ch,8); - printf("Ci+1: "); print_bytes(Ci_1,8); - printf("\n"); - printf(" Ks: "); - for (pos=0; pos<8; pos++) - { - printf("%02x ",Ci_1[pos]); - printf("%02x ",Ch[pos]); - } - printf("\n\n"); + printf("\nAuthentication info\n\n"); + printf(" Gc: "); + print_bytes(Gc, 8); + printf(" Ci: "); + print_bytes(Ci, 8); + printf(" Q: "); + print_bytes(Q, 8); + printf(" Ch: "); + print_bytes(Ch, 8); + printf("Ci+1: "); + print_bytes(Ci_1, 8); + printf("\n"); + printf(" Ks: "); + for (pos = 0; pos < 8; pos++) { + printf("%02x ", Ci_1[pos]); + printf("%02x ", Ch[pos]); + } + printf("\n\n"); - return 0; + return 0; } diff --git a/tools/cryptorf/sma.cpp b/tools/cryptorf/sma.cpp index 705658651..05b9f344f 100644 --- a/tools/cryptorf/sma.cpp +++ b/tools/cryptorf/sma.cpp @@ -1,9 +1,9 @@ /* - * + * * SecureMemory recovery * * Copyright (C) 2010, Flavio D. Garcia, Peter van Rossum, Roel Verdult - * and Ronny Wichers Schreur. Radboud University Nijmegen + * and Ronny Wichers Schreur. Radboud University Nijmegen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * Modified Iceman, 2020 */ @@ -27,7 +27,7 @@ #include #include #include -#include // sort, max_element, random_shuffle, remove_if, lower_bound +#include // sort, max_element, random_shuffle, remove_if, lower_bound #include // greater, bind2nd #include "cryptolib.h" #include "util.h" @@ -35,10 +35,10 @@ using namespace std; #ifdef _MSC_VER - // avoid scanf warnings in Visual Studio - #define _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_DEPRECATE - #define inline __inline +// avoid scanf warnings in Visual Studio +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_DEPRECATE +#define inline __inline #endif /* @@ -53,7 +53,7 @@ Authenticate Ci+1: de c2 ee 1b 1c 92 76 e9 Ks: de 88 c2 c9 ee d4 1b 46 1c 6a 92 50 76 1a e9 87 - + left: 1ddeac626 right: 19aba45 @@ -105,21 +105,21 @@ Ci+1: de c2 ee 1b 1c 92 76 e9 */ const uint64_t left_candidates[43] = { - 0x6221539d9ull, 0x1ddeac626ull, 0x7cc847482ull, 0x0337b8b7dull, - 0x159d1687eull, 0x7bade8a41ull, 0x4c51c6463ull, 0x4e3d88bf9ull, - 0x4e3d88819ull, 0x31c2777e6ull, 0x31c277406ull, 0x0059ff7d5ull, - 0x5fb612b96ull, 0x2049ed469ull, 0x0452175beull, 0x00d2ff4edull, - 0x68918cba9ull, 0x03a6f882aull, 0x7086372b6ull, 0x6c9a11672ull, - 0x60531191aull, 0x4ba9b653full, 0x4ba9b6520ull, 0x1facee6e5ull, - 0x0f79c8d49ull, 0x0b29f2a5bull, 0x032df8b12ull, 0x7c90849f8ull, - 0x48916e84eull, 0x176e73456ull, 0x036f7b607ull, 0x5b2aeb858ull, - 0x51c8755b5ull, 0x4c9432733ull, 0x0f6c834fbull, 0x03b2ff59bull, - 0x0f78aac5bull, 0x3770cdaf3ull, 0x205078bbaull, 0x04445c715ull, - 0x004df8a64ull, 0x6f696e09eull, 0x109691f61ull + 0x6221539d9ull, 0x1ddeac626ull, 0x7cc847482ull, 0x0337b8b7dull, + 0x159d1687eull, 0x7bade8a41ull, 0x4c51c6463ull, 0x4e3d88bf9ull, + 0x4e3d88819ull, 0x31c2777e6ull, 0x31c277406ull, 0x0059ff7d5ull, + 0x5fb612b96ull, 0x2049ed469ull, 0x0452175beull, 0x00d2ff4edull, + 0x68918cba9ull, 0x03a6f882aull, 0x7086372b6ull, 0x6c9a11672ull, + 0x60531191aull, 0x4ba9b653full, 0x4ba9b6520ull, 0x1facee6e5ull, + 0x0f79c8d49ull, 0x0b29f2a5bull, 0x032df8b12ull, 0x7c90849f8ull, + 0x48916e84eull, 0x176e73456ull, 0x036f7b607ull, 0x5b2aeb858ull, + 0x51c8755b5ull, 0x4c9432733ull, 0x0f6c834fbull, 0x03b2ff59bull, + 0x0f78aac5bull, 0x3770cdaf3ull, 0x205078bbaull, 0x04445c715ull, + 0x004df8a64ull, 0x6f696e09eull, 0x109691f61ull }; typedef struct { - uint64_t l; + uint64_t l; uint64_t m; uint64_t r; nibble b0; @@ -127,10 +127,10 @@ typedef struct { nibble b1l; nibble b1r; nibble b1s; - bool invalid; - uint8_t Gc[8]; -}cs_t; -typedef cs_t* pcs; + bool invalid; + uint8_t Gc[8]; +} cs_t; +typedef cs_t *pcs; typedef struct { uint8_t addition; @@ -138,49 +138,45 @@ typedef struct { } lookup_entry; enum cipher_state_side { - CSS_LEFT, - CSS_RIGHT + CSS_LEFT, + CSS_RIGHT }; -void print_cs(const char* text,pcs s) -{ - int pos; - - printf("%s",text); - for(pos=6;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->l>>(pos*5))&0x1f); - printf(" |"); - for(pos=6;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->m>>(pos*7))&0x7f); - printf(" |"); - for(pos=4;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->r>>(pos*5))&0x1f); - - printf("\n"); +void print_cs(const char *text, pcs s) { + int pos; + + printf("%s", text); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f); + printf(" |"); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f); + printf(" |"); + for (pos = 4; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f); + + printf("\n"); } -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 - if (a> (n_bits - 1))) & mask; +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 + uint8_t mask = (1 << n_bits) - 1; + return ((a << 1) | (a >> (n_bits - 1))) & mask; } -static inline uint8_t bit_rotate_r(uint8_t a, uint8_t n_bits) -{ - return ((a >> 1) | ((a&1) << (n_bits - 1))); +static inline uint8_t bit_rotate_r(uint8_t a, uint8_t n_bits) { + return ((a >> 1) | ((a & 1) << (n_bits - 1))); } static uint8_t lookup_left_substraction[0x400]; @@ -189,733 +185,673 @@ static lookup_entry lookup_left[0x100000]; static lookup_entry lookup_right[0x8000]; static uint8_t left_addition[0x100000]; -static inline void init_lookup_left() -{ - uint8_t b3,b6,temp; - int i,index; +static inline void init_lookup_left() { + uint8_t b3, b6, temp; + int i, index; - for(i = 0; i <0x400; i++) - { + for (i = 0; i < 0x400; i++) { b6 = i & 0x1f; b3 = (i >> 5) & 0x1f; index = (b3 << 15) | b6; b6 = bit_rotate_l(b6, 5); - temp = mod(b3 + b6,0x1f); - left_addition[index] = temp; + temp = mod(b3 + b6, 0x1f); + left_addition[index] = 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() -{ - uint8_t b16,b18,temp; - int i,index; +static inline void init_lookup_right() { + uint8_t b16, b18, temp; + int i, index; - for(i = 0; i <0x400; i++) - { + for (i = 0; i < 0x400; i++) { b18 = i & 0x1f; b16 = (i >> 5) & 0x1f; index = (b16 << 10) | b18; - temp = mod(b18 + b16,0x1f); + temp = mod(b18 + b16, 0x1f); 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() -{ - for(int index = 0; index < 0x400 ; index++) - { +static void init_lookup_left_substraction() { + for (int index = 0; index < 0x400 ; index++) { uint8_t b3 = (index >> 5 & 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() -{ - for(int index = 0; index < 0x400 ; index++) - { - int b16 = (index >>5); +static void init_lookup_right_substraction() { + for (int index = 0; index < 0x400 ; index++) { + int b16 = (index >> 5); 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 *candidate_states) -{ - pcs state; - size_t size = candidate_states->size(); - for(size_t pos=0; pos *candidate_states) { + pcs state; + size_t size = candidate_states->size(); + for (size_t pos = 0; pos < size; pos++) { + state = &((*candidate_states)[pos]); - uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); - unsigned b3 = (unsigned)(state->l >> 5) & 0x3e0; - state->l = (state->l << 5); + uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); + unsigned b3 = (unsigned)(state->l >> 5) & 0x3e0; + state->l = (state->l << 5); - //Ignore impossible states - if (bx == 0) - { - // Are we dealing with an impossible state? - if (b3 != 0) - { - state->invalid = true; - } else { - // We only need to consider b6=0 - state->l &= 0x7ffffffe0ull; - state->l ^= (((uint64_t)in & 0x1f) << 20); - } - } else { - uint8_t b6 = lookup_left_substraction[b3|bx]; - state->l = (state->l & 0x7ffffffe0ull) | b6; - state->l ^= (((uint64_t)in & 0x1f) << 20); + //Ignore impossible states + if (bx == 0) { + // Are we dealing with an impossible state? + if (b3 != 0) { + state->invalid = true; + } else { + // We only need to consider b6=0 + state->l &= 0x7ffffffe0ull; + state->l ^= (((uint64_t)in & 0x1f) << 20); + } + } else { + uint8_t b6 = lookup_left_substraction[b3 | bx]; + state->l = (state->l & 0x7ffffffe0ull) | b6; + state->l ^= (((uint64_t)in & 0x1f) << 20); - // Check if we have a second candidate - if (b6 == 0x1f) - { - cs_t nstate = *state; - nstate.l &= 0x7ffffffe0ull; - candidate_states->push_back(nstate); - } - } - } + // Check if we have a second candidate + if (b6 == 0x1f) { + cs_t nstate = *state; + nstate.l &= 0x7ffffffe0ull; + candidate_states->push_back(nstate); + } + } + } } -static inline void previous_right(uint8_t in, vector *candidate_states) -{ - pcs state; - size_t size = candidate_states->size(); - for(size_t pos=0; posr >> 20) & 0x1f); - unsigned b16 = (unsigned)(state->r & 0x3e0);//(state->buffer_r >> 10) & 0x1f; - - state->r = (state->r << 5); - - // Ignore impossible states - if (bx == 0) - { - if (b16 != 0) - { - state->invalid=true; - } else { - // We only need to consider b18=0 - state->r &= 0x1ffffe0ull; - state->r ^= (((uint64_t)in & 0xf8) << 12); - } - } else{ - uint8_t b18 = lookup_right_subtraction[b16|bx]; - state->r = (state->r & 0x1ffffe0ull) | b18; - state->r ^= (((uint64_t)in & 0xf8) << 12); - //state->b_right = ((b14^b17) & 0x0f); - - // Check if we have a second candidate - if (b18 == 0x1f) - { - cs_t nstate = *state; - nstate.r &= 0x1ffffe0ull; - candidate_states->push_back(nstate); - } - } - } +static inline void previous_right(uint8_t in, vector *candidate_states) { + pcs state; + size_t size = candidate_states->size(); + for (size_t pos = 0; pos < size; pos++) { + state = &((*candidate_states)[pos]); + + uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f); + unsigned b16 = (unsigned)(state->r & 0x3e0);//(state->buffer_r >> 10) & 0x1f; + + state->r = (state->r << 5); + + // Ignore impossible states + if (bx == 0) { + if (b16 != 0) { + state->invalid = true; + } else { + // We only need to consider b18=0 + state->r &= 0x1ffffe0ull; + state->r ^= (((uint64_t)in & 0xf8) << 12); + } + } else { + uint8_t b18 = lookup_right_subtraction[b16 | bx]; + state->r = (state->r & 0x1ffffe0ull) | b18; + state->r ^= (((uint64_t)in & 0xf8) << 12); + //state->b_right = ((b14^b17) & 0x0f); + + // Check if we have a second candidate + if (b18 == 0x1f) { + cs_t nstate = *state; + nstate.r &= 0x1ffffe0ull; + candidate_states->push_back(nstate); + } + } + } } -static inline uint8_t next_left_fast(uint8_t in, uint64_t* left) -{ - if (in) *left ^= ((in & 0x1f) << 20); - lookup_entry* lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); +static inline uint8_t next_left_fast(uint8_t in, uint64_t *left) { + if (in) *left ^= ((in & 0x1f) << 20); + lookup_entry *lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); return lookup->out; } -static inline uint8_t next_left_ksbyte(uint64_t* left) -{ - lookup_entry* lookup; - uint8_t bt; - - *left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); - lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); - bt = lookup->out << 4; - *left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); - lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); - bt |= lookup->out; +static inline uint8_t next_left_ksbyte(uint64_t *left) { + lookup_entry *lookup; + uint8_t bt; + + *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); + lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); + bt = lookup->out << 4; + *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); + lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); + bt |= lookup->out; return bt; } -static inline uint8_t next_right_fast(uint8_t in, uint64_t* right) -{ - if (in) *right ^= ((in&0xf8) << 12); - lookup_entry* lookup = &(lookup_right[((*right) & 0x7c1f)]); +static inline uint8_t next_right_fast(uint8_t in, uint64_t *right) { + if (in) *right ^= ((in & 0xf8) << 12); + lookup_entry *lookup = &(lookup_right[((*right) & 0x7c1f)]); *right = (((*right) >> 5) | (lookup->addition << 20)); return lookup->out; } -static inline void sm_left_mask(const uint8_t* ks, uint8_t* mask, uint64_t rstate) -{ - size_t pos; - uint8_t bt; - - for (pos=0; pos<16; pos++) - { - next_right_fast(0,&rstate); - bt = next_right_fast(0,&rstate) << 4; - next_right_fast(0,&rstate); - bt |= next_right_fast(0,&rstate); - - // xor the bits with the keystream and count the "correct" bits - bt ^= ks[pos]; - - // Save the mask for the left produced bits - mask[pos] = bt; - } +static inline void sm_left_mask(const uint8_t *ks, uint8_t *mask, uint64_t rstate) { + size_t pos; + uint8_t bt; + + for (pos = 0; pos < 16; pos++) { + next_right_fast(0, &rstate); + bt = next_right_fast(0, &rstate) << 4; + next_right_fast(0, &rstate); + bt |= next_right_fast(0, &rstate); + + // xor the bits with the keystream and count the "correct" bits + bt ^= ks[pos]; + + // Save the mask for the left produced bits + mask[pos] = bt; + } } -static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector* pcrstates) -{ - uint8_t tmp_mask[16]; - size_t pos,bits,bit,topbits; - uint64_t rstate,counter; - map bincstates; - map::iterator it; - uint8_t bt; +static inline uint32_t sm_right(const uint8_t *ks, uint8_t *mask, vector *pcrstates) { + uint8_t tmp_mask[16]; + size_t pos, bits, bit, topbits; + uint64_t rstate, counter; + map bincstates; + map::iterator it; + uint8_t bt; - topbits = 0; - for (counter=0; counter<0x2000000; counter++) - { - // Reset the current bitcount of correct bits - bits = 0; - - // Copy the state we are going to test - rstate = counter; + topbits = 0; + for (counter = 0; counter < 0x2000000; counter++) { + // Reset the current bitcount of correct bits + bits = 0; - for (pos=0; pos<16; pos++) - { - next_right_fast(0,&rstate); - bt = next_right_fast(0,&rstate) << 4; - next_right_fast(0,&rstate); - bt |= next_right_fast(0,&rstate); - - // xor the bits with the keystream and count the "correct" bits - bt ^= ks[pos]; + // Copy the state we are going to test + rstate = counter; - // Save the mask for the left produced bits - tmp_mask[pos] = bt; + for (pos = 0; pos < 16; pos++) { + next_right_fast(0, &rstate); + bt = next_right_fast(0, &rstate) << 4; + next_right_fast(0, &rstate); + bt |= next_right_fast(0, &rstate); - for (bit=0; bit<8; bit++) - { - // When the bit is xored away (=zero), it was the same, so correct ;) - if ((bt & 0x01) == 0) bits++; - bt >>= 1; - } - } + // xor the bits with the keystream and count the "correct" bits + bt ^= ks[pos]; - if (bits > topbits) - { - topbits = bits; - // Copy the winning mask - memcpy(mask,tmp_mask,16); - } - - // Ignore states under 90 - if (bits >= 90) - { - // Make sure the bits are used for ordering - bincstates[(((uint64_t)bits)<<56) | counter] = counter; - } - - if ((counter&0xfffff) == 0) - { - printf("."); - fflush(stdout); - } - } - printf("\n"); + // Save the mask for the left produced bits + tmp_mask[pos] = bt; - // Clear the candidate state vector - pcrstates->clear(); - - // Copy the order the states from lowest-bin to highest-bin - for(it=bincstates.begin();it!=bincstates.end();++it) - { - pcrstates->push_back(it->second); - } - // Reverse the vector order (so the higest bin comes first) - reverse(pcrstates->begin(),pcrstates->end()); - - return topbits; -} - -static inline void previous_all_input(vector *pcstates, uint32_t gc_byte_index, cipher_state_side css) -{ - uint8_t btGc,in; - vector ncstates; - vector prev_ncstates; - vector::iterator it,itnew; - - // Loop through the complete entryphy of 5 bits for each candidate - // We ignore zero (xor 0x00) to avoid duplicates - for (btGc=0; btGc<0x20; btGc++) - { - // Copy the original candidates that are supplied - ncstates = *pcstates; - - // Rollback the (candidate) cipher states with this input - if (css == CSS_RIGHT) - { - in = btGc << 3; - previous_right(in,&ncstates); - } else { - in = btGc; - previous_left(in,&ncstates); - } - - for(itnew=ncstates.begin();itnew!=ncstates.end();++itnew) - { - // Wipe away the invalid states - if (itnew->invalid == false) - { - itnew->Gc[gc_byte_index] = in; - prev_ncstates.push_back(*itnew); - } - } - } - - // Copy the previous states into the vector - *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* pcstates) -{ - vector::iterator it; - vector csl_cand; - map matchbox; - map::iterator itmatch; - uint64_t rstate; - size_t counter; - cs_t state; - - // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) - for (counter=0; counter<0x100000; counter++) - { - rstate = rstate_before_gc; - next_right_fast((counter >> 12) & 0xf8,&rstate); - next_right_fast((counter >> 7) & 0xf8,&rstate); - next_right_fast(Q[4],&rstate); - next_right_fast((counter >> 2) & 0xf8,&rstate); - next_right_fast((counter << 3) & 0xf8,&rstate); - next_right_fast(Q[5],&rstate); - matchbox[rstate] = counter; - } - - // Reset and initialize the cryptostate and vecctor - memset(&state,0x00,sizeof(cs_t)); - state.invalid = false; - state.r = rstate_after_gc; - csl_cand.clear(); - csl_cand.push_back(state); - - // 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_all_input(&csl_cand,7,CSS_RIGHT); - previous_all_input(&csl_cand,6,CSS_RIGHT); - previous_right(Q[6],&csl_cand); - previous_all_input(&csl_cand,5,CSS_RIGHT); - previous_all_input(&csl_cand,4,CSS_RIGHT); - - pcstates->clear(); - - // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) - for(it=csl_cand.begin();it!=csl_cand.end();++it) - { - itmatch = matchbox.find(it->r); - if (itmatch != matchbox.end()) - { - it->Gc[0] = (itmatch->second >> 12) & 0xf8; - it->Gc[1] = (itmatch->second >> 7) & 0xf8; - it->Gc[2] = (itmatch->second >> 2) & 0xf8; - it->Gc[3] = (itmatch->second << 3) & 0xf8; - /* - printf("%07llx ",it->r); - printf("(%x)\n",itmatch->second); - */ -/* - if (it->r == 0xff459b) - { - print_cs("previous:",&(*it)); - printf("%07llx\n",it->r); - print_bytes(it->Gc,8); - } -*/ - pcstates->push_back(*it); - } - } -} - -static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector* pcstates) -{ - map bincstates; - map::iterator it; - uint64_t counter,lstate; - size_t pos,bits,bit; - uint8_t correct_bits[16]; - uint8_t bt; - cs_t state; - lookup_entry* lookup; - - // Reset and initialize the cryptostate and vecctor - memset(&state,0x00,sizeof(cs_t)); - state.invalid = false; - - for (counter=0; counter<0x800000000ull; counter++) - { - lstate = counter; - - for (pos=0; pos<16; pos++) - { - lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); - lookup = &(lookup_left[((lstate) & 0xf801f)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); - bt = lookup->out << 4; - lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); - lookup = &(lookup_left[((lstate) & 0xf801f)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); - bt |= lookup->out; - - // xor the bits with the keystream and count the "correct" bits - bt ^= ks[pos]; - - // When the REQUIRED bits are NOT xored away (=zero), ignore this wrong state - if ((bt & mask[pos]) != 0) break; - - // Save the correct bits for statistical information - correct_bits[pos] = bt; - } - - // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! - if (pos == 16) - { - // Count the total correct bits - bits=0; - for (pos=0; pos<16; pos++) - { - // Get the next byte-value with correct bits - bt = correct_bits[pos]; - - // Count all the (correct) bits - for (bit=0; bit<8; bit++) - { - // When the bit is xored away (=zero), it was the same, so correct ;) - if ((bt & 0x01) == 0) bits++; - bt >>= 1; + for (bit = 0; bit < 8; bit++) { + // When the bit is xored away (=zero), it was the same, so correct ;) + if ((bt & 0x01) == 0) bits++; + bt >>= 1; + } } - } - // Print the left candidate -// printf("%09llx (%d)\n",counter,bits); - printf("."); - fflush(stdout); + if (bits > topbits) { + topbits = bits; + // Copy the winning mask + memcpy(mask, tmp_mask, 16); + } - state.l = counter; - // Make sure the bits are used for ordering - bincstates[(((uint64_t)bits)<<56) | counter] = state; + // Ignore states under 90 + if (bits >= 90) { + // Make sure the bits are used for ordering + bincstates[(((uint64_t)bits) << 56) | counter] = counter; + } + + if ((counter & 0xfffff) == 0) { + printf("."); + fflush(stdout); + } } - - if ((counter&0xffffffffull) == 0) - { - printf("%02.1f%%.",((float)100/8)*(counter>>32)); - fflush(stdout); - } - } - printf("100%%\n"); - - // Clear the candidate state vector - pcstates->clear(); + printf("\n"); - // Copy the order the states from lowest-bin to highest-bin - for(it=bincstates.begin();it!=bincstates.end();++it) - { - pcstates->push_back(it->second); - } - // Reverse the vector order (so the higest bin comes first) - reverse(pcstates->begin(),pcstates->end()); + // Clear the candidate state vector + pcrstates->clear(); + + // Copy the order the states from lowest-bin to highest-bin + for (it = bincstates.begin(); it != bincstates.end(); ++it) { + pcrstates->push_back(it->second); + } + // Reverse the vector order (so the higest bin comes first) + reverse(pcrstates->begin(), pcrstates->end()); + + return topbits; } -static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t* Q, vector* pcstates) -{ - vector csl_cand,csl_search; - vector::iterator itsearch,itcand; - map matchbox; - map::iterator itmatch; - uint64_t lstate; - size_t counter; - - // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) - for (counter=0; counter<0x100000; counter++) - { - lstate = lstate_before_gc; - next_left_fast((counter >> 15) & 0x1f,&lstate); - next_left_fast((counter >> 10) & 0x1f,&lstate); - next_left_fast(Q[4],&lstate); - next_left_fast((counter >> 5) & 0x1f,&lstate); - next_left_fast(counter & 0x1f,&lstate); - next_left_fast(Q[5],&lstate); - matchbox[lstate] = counter; - } - - // Copy the input candidate states and clean the output vector - csl_cand = *pcstates; - pcstates->clear(); - - for(itcand=csl_cand.begin();itcand!=csl_cand.end();++itcand) - { - csl_search.clear(); - csl_search.push_back(*itcand); - +static inline void previous_all_input(vector *pcstates, uint32_t gc_byte_index, cipher_state_side css) { + uint8_t btGc, in; + vector ncstates; + vector prev_ncstates; + vector::iterator it, itnew; + + // Loop through the complete entryphy of 5 bits for each candidate + // We ignore zero (xor 0x00) to avoid duplicates + for (btGc = 0; btGc < 0x20; btGc++) { + // Copy the original candidates that are supplied + ncstates = *pcstates; + + // Rollback the (candidate) cipher states with this input + if (css == CSS_RIGHT) { + in = btGc << 3; + previous_right(in, &ncstates); + } else { + in = btGc; + previous_left(in, &ncstates); + } + + for (itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) { + // Wipe away the invalid states + if (itnew->invalid == false) { + itnew->Gc[gc_byte_index] = in; + prev_ncstates.push_back(*itnew); + } + } + } + + // Copy the previous states into the vector + *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 *pcstates) { + vector::iterator it; + vector csl_cand; + map matchbox; + map::iterator itmatch; + uint64_t rstate; + size_t counter; + cs_t state; + + // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) + for (counter = 0; counter < 0x100000; counter++) { + rstate = rstate_before_gc; + next_right_fast((counter >> 12) & 0xf8, &rstate); + next_right_fast((counter >> 7) & 0xf8, &rstate); + next_right_fast(Q[4], &rstate); + next_right_fast((counter >> 2) & 0xf8, &rstate); + next_right_fast((counter << 3) & 0xf8, &rstate); + next_right_fast(Q[5], &rstate); + matchbox[rstate] = counter; + } + + // Reset and initialize the cryptostate and vecctor + memset(&state, 0x00, sizeof(cs_t)); + state.invalid = false; + state.r = rstate_after_gc; + csl_cand.clear(); + csl_cand.push_back(state); + // 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_all_input(&csl_search,7,CSS_LEFT); - previous_all_input(&csl_search,6,CSS_LEFT); - previous_left(Q[6],&csl_search); - previous_all_input(&csl_search,5,CSS_LEFT); - previous_all_input(&csl_search,4,CSS_LEFT); - + previous_right(Q[7], &csl_cand); + previous_all_input(&csl_cand, 7, CSS_RIGHT); + previous_all_input(&csl_cand, 6, CSS_RIGHT); + previous_right(Q[6], &csl_cand); + previous_all_input(&csl_cand, 5, CSS_RIGHT); + previous_all_input(&csl_cand, 4, CSS_RIGHT); + + pcstates->clear(); + // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) - for(itsearch=csl_search.begin();itsearch!=csl_search.end();++itsearch) - { - itmatch = matchbox.find(itsearch->l); - if (itmatch != matchbox.end()) - { - itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f; - itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f; - itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f; - itsearch->Gc[3] = itmatch->second & 0x1f; - - /* - printf("%07llx ",it->l); - printf("(%x) ",itmatch->second); - print_cs("",&(*it)); - */ -/* - if (itsearch->l == 0x405162420ull) - { - print_cs("previous:",&(*itsearch)); - printf("%09llx\n",itsearch->l); - print_bytes(itsearch->Gc,8); + for (it = csl_cand.begin(); it != csl_cand.end(); ++it) { + itmatch = matchbox.find(it->r); + if (itmatch != matchbox.end()) { + it->Gc[0] = (itmatch->second >> 12) & 0xf8; + it->Gc[1] = (itmatch->second >> 7) & 0xf8; + it->Gc[2] = (itmatch->second >> 2) & 0xf8; + it->Gc[3] = (itmatch->second << 3) & 0xf8; + /* + printf("%07llx ",it->r); + printf("(%x)\n",itmatch->second); + */ + /* + if (it->r == 0xff459b) + { + print_cs("previous:",&(*it)); + printf("%07llx\n",it->r); + print_bytes(it->Gc,8); + } + */ + pcstates->push_back(*it); } - count++; -*/ - pcstates->push_back(*itsearch); - } } +} + +static inline void sm_left(const uint8_t *ks, uint8_t *mask, vector *pcstates) { + map bincstates; + map::iterator it; + uint64_t counter, lstate; + size_t pos, bits, bit; + uint8_t correct_bits[16]; + uint8_t bt; + cs_t state; + lookup_entry *lookup; + + // Reset and initialize the cryptostate and vecctor + memset(&state, 0x00, sizeof(cs_t)); + state.invalid = false; + + for (counter = 0; counter < 0x800000000ull; counter++) { + lstate = counter; + + for (pos = 0; pos < 16; pos++) { + lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); + lookup = &(lookup_left[((lstate) & 0xf801f)]); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); + bt = lookup->out << 4; + lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); + lookup = &(lookup_left[((lstate) & 0xf801f)]); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); + bt |= lookup->out; + + // xor the bits with the keystream and count the "correct" bits + bt ^= ks[pos]; + + // When the REQUIRED bits are NOT xored away (=zero), ignore this wrong state + if ((bt & mask[pos]) != 0) break; + + // Save the correct bits for statistical information + correct_bits[pos] = bt; + } + + // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! + if (pos == 16) { + // Count the total correct bits + bits = 0; + for (pos = 0; pos < 16; pos++) { + // Get the next byte-value with correct bits + bt = correct_bits[pos]; + + // Count all the (correct) bits + for (bit = 0; bit < 8; bit++) { + // When the bit is xored away (=zero), it was the same, so correct ;) + if ((bt & 0x01) == 0) bits++; + bt >>= 1; + } + } + + // Print the left candidate +// printf("%09llx (%d)\n",counter,bits); + printf("."); + fflush(stdout); + + state.l = counter; + // Make sure the bits are used for ordering + bincstates[(((uint64_t)bits) << 56) | counter] = state; + } + + if ((counter & 0xffffffffull) == 0) { + printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32)); + fflush(stdout); + } + } + printf("100%%\n"); + + // Clear the candidate state vector + pcstates->clear(); + + // Copy the order the states from lowest-bin to highest-bin + for (it = bincstates.begin(); it != bincstates.end(); ++it) { + pcstates->push_back(it->second); + } + // Reverse the vector order (so the higest bin comes first) + reverse(pcstates->begin(), pcstates->end()); +} + +static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t *Q, vector *pcstates) { + vector csl_cand, csl_search; + vector::iterator itsearch, itcand; + map matchbox; + map::iterator itmatch; + uint64_t lstate; + size_t counter; + + // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) + for (counter = 0; counter < 0x100000; counter++) { + lstate = lstate_before_gc; + next_left_fast((counter >> 15) & 0x1f, &lstate); + next_left_fast((counter >> 10) & 0x1f, &lstate); + next_left_fast(Q[4], &lstate); + next_left_fast((counter >> 5) & 0x1f, &lstate); + next_left_fast(counter & 0x1f, &lstate); + next_left_fast(Q[5], &lstate); + matchbox[lstate] = counter; + } + + // Copy the input candidate states and clean the output vector + csl_cand = *pcstates; + pcstates->clear(); + + for (itcand = csl_cand.begin(); itcand != csl_cand.end(); ++itcand) { + csl_search.clear(); + csl_search.push_back(*itcand); + + // 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_all_input(&csl_search, 7, CSS_LEFT); + previous_all_input(&csl_search, 6, CSS_LEFT); + previous_left(Q[6], &csl_search); + previous_all_input(&csl_search, 5, CSS_LEFT); + previous_all_input(&csl_search, 4, CSS_LEFT); + + // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) + for (itsearch = csl_search.begin(); itsearch != csl_search.end(); ++itsearch) { + itmatch = matchbox.find(itsearch->l); + if (itmatch != matchbox.end()) { + itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f; + itsearch->Gc[1] = (itmatch->second >> 10) & 0x1f; + itsearch->Gc[2] = (itmatch->second >> 5) & 0x1f; + itsearch->Gc[3] = itmatch->second & 0x1f; + + /* + printf("%07llx ",it->l); + printf("(%x) ",itmatch->second); + print_cs("",&(*it)); + */ + /* + if (itsearch->l == 0x405162420ull) + { + print_cs("previous:",&(*itsearch)); + printf("%09llx\n",itsearch->l); + print_bytes(itsearch->Gc,8); + } + count++; + */ + pcstates->push_back(*itsearch); + } + } // printf("%09llx: ",itcand->l); // printf("%d - %d\n",csl_search.size(),count); - printf("."); - fflush(stdout); - } - printf("\n"); + printf("."); + fflush(stdout); + } + printf("\n"); } -void combine_valid_left_right_states(vector* plcstates, vector* prcstates, vector* pgc_candidates) -{ +void combine_valid_left_right_states(vector *plcstates, vector *prcstates, vector *pgc_candidates) { vector::iterator itl, itr; - size_t pos,count; - uint64_t gc; - bool valid; + size_t pos, count; + uint64_t gc; + bool valid; - // Clean up the candidate list - pgc_candidates->clear(); - count = 0; - for(itl=plcstates->begin();itl!=plcstates->end();++itl) - { - for(itr=prcstates->begin();itr!=prcstates->end();++itr) - { - valid = true; - // Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc) - for (pos=0; pos<8; pos++) - { - if ((itl->Gc[pos] & 0x18) != (itr->Gc[pos] & 0x18)) - { - valid = false; - break; - } - } - - if (valid) - { - gc = 0; - for (pos=0; pos<8; pos++) - { - gc <<= 8; - gc |= (itl->Gc[pos] | itr->Gc[pos]); - } + // Clean up the candidate list + pgc_candidates->clear(); + count = 0; + for (itl = plcstates->begin(); itl != plcstates->end(); ++itl) { + for (itr = prcstates->begin(); itr != prcstates->end(); ++itr) { + valid = true; + // Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc) + for (pos = 0; pos < 8; pos++) { + if ((itl->Gc[pos] & 0x18) != (itr->Gc[pos] & 0x18)) { + valid = false; + break; + } + } + + if (valid) { + gc = 0; + for (pos = 0; pos < 8; pos++) { + gc <<= 8; + gc |= (itl->Gc[pos] | itr->Gc[pos]); + } // printf("%016llx\n",gc); - pgc_candidates->push_back(gc); + pgc_candidates->push_back(gc); // printf("%09llx - ",itl->l); // printf("%07llx\n",itr->r); - } - count++; + } + count++; + } } - } - 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("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()); } -int main(int argc, const char* argv[]) -{ - size_t pos; - crypto_state_t ostate; - uint64_t rstate_before_gc,rstate_after_gc; - uint64_t lstate_before_gc; - vector rstates,lstates_after_gc,pgc_candidates; - vector::iterator itrstates,itgc; - vector crstates; - vector clcandidates,clstates; +int main(int argc, const char *argv[]) { + size_t pos; + crypto_state_t ostate; + uint64_t rstate_before_gc, rstate_after_gc; + uint64_t lstate_before_gc; + vector rstates, lstates_after_gc, pgc_candidates; + vector::iterator itrstates, itgc; + vector crstates; + vector clcandidates, clstates; vector::iterator it; - uint32_t rbits; - + uint32_t rbits; + // uint8_t Gc[ 8] = {0x4f,0x79,0x4a,0x46,0x3f,0xf8,0x1d,0x81}; // uint8_t Gc[ 8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // uint8_t Ci[ 8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; // uint8_t Q[ 8] = {0x12,0x34,0x56,0x78,0x12,0x34,0x56,0x78}; - uint8_t Gc[ 8]; - uint8_t Ci[ 8]; - uint8_t Q[ 8]; - uint8_t Ch[ 8]; - uint8_t Ci_1[ 8]; + uint8_t Gc[ 8]; + uint8_t Ci[ 8]; + uint8_t Q[ 8]; + uint8_t Ch[ 8]; + uint8_t Ci_1[ 8]; - uint8_t Gc_chk[ 8]; - uint8_t Ch_chk[ 8]; - uint8_t Ci_1_chk[ 8]; + uint8_t Gc_chk[ 8]; + uint8_t Ch_chk[ 8]; + uint8_t Ci_1_chk[ 8]; - // uint8_t ks[16] = {0xde,0x88,0xc2,0xc9,0xee,0xd4,0x1b,0x46,0x1c,0x6a,0x92,0x50,0x76,0x1a,0xe9,0x87}; - // uint8_t mask[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - // uint8_t mask[16] = {0x04,0xb0,0xe1,0x10,0xc0,0x33,0x44,0x20,0x20,0x00,0x70,0x8c,0x22,0x04,0x10,0x80}; + // uint8_t ks[16] = {0xde,0x88,0xc2,0xc9,0xee,0xd4,0x1b,0x46,0x1c,0x6a,0x92,0x50,0x76,0x1a,0xe9,0x87}; + // uint8_t mask[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + // uint8_t mask[16] = {0x04,0xb0,0xe1,0x10,0xc0,0x33,0x44,0x20,0x20,0x00,0x70,0x8c,0x22,0x04,0x10,0x80}; - uint8_t ks[16]; - uint8_t mask[16]; - - uint64_t nCi; // Card random - uint64_t nQ; // Reader random - uint64_t nCh; // Reader challange - uint64_t nCi_1; // Card anwser - - if ((argc != 2) && (argc != 5)) - { - printf("SecureMemory recovery - (c) Radboud University Nijmegen\n\n"); - printf("syntax: sma simulate\n"); - printf(" sma \n\n"); - return 1; - } - - printf(_CYAN_("\nAuthentication info\n\n")); + uint8_t ks[16]; + uint8_t mask[16]; - // Check if this is a simulation - if (argc == 2) - { - // Generate random values for the key and randoms - srand((uint32_t)time(NULL)); - for (pos = 0; pos<8; pos++) - { - Gc[pos] = rand(); - Ci[pos] = rand(); - Q[pos] = rand(); + uint64_t nCi; // Card random + uint64_t nQ; // Reader random + uint64_t nCh; // Reader challange + uint64_t nCi_1; // Card anwser + + if ((argc != 2) && (argc != 5)) { + printf("SecureMemory recovery - (c) Radboud University Nijmegen\n\n"); + printf("syntax: sma simulate\n"); + printf(" sma \n\n"); + return 1; } - sm_auth(Gc,Ci,Q,Ch,Ci_1,&ostate); - printf(" Gc: "); print_bytes(Gc,8); - } else { - sscanf(argv[1],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); - sscanf(argv[2],"%016" SCNx64,&nQ); 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"); - } - - for (pos = 0; pos<8; pos++) - { - ks[2*pos] = Ci_1[pos]; - ks[(2*pos)+1] = Ch[pos]; - } - - printf(" Ci: "); print_bytes(Ci,8); - printf(" Q: "); print_bytes(Q,8); - printf(" Ch: "); print_bytes(Ch,8); - printf("Ci+1: "); print_bytes(Ci_1,8); - printf("\n"); - printf(" Ks: "); print_bytes(ks,16); - printf("\n"); - - printf("Initializing lookup tables for increasing cipher speed\n"); - init_lookup_left(); - init_lookup_right(); - init_lookup_left_substraction(); - init_lookup_right_substraction(); - - // Load in the ci (tag-nonce), together with the first half of Q (reader-nonce) - rstate_before_gc = 0; - lstate_before_gc = 0; - for (pos = 0; pos < 4; pos++) - { - next_right_fast(Ci[2*pos ],&rstate_before_gc); - next_right_fast(Ci[2*pos+1],&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+1],&lstate_before_gc); - next_left_fast(Q[pos],&lstate_before_gc); - } - - printf("Determing the right states that correspond to the keystream\n"); - rbits = sm_right(ks,mask,&rstates); - 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(_CYAN_("\nAuthentication info\n\n")); - if (rbits < 96) - { - 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) - { - rstate_after_gc = *itrstates; - 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); - - 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()); - if (crstates.size() == 0) continue; - - printf("Calculating left states using the (unknown bits) mask from the top-right state\n"); - sm_left(ks,mask,&clstates); - printf("Found a total of " _YELLOW_("%lu")" left cipher states, recovering left candidates...\n",clstates.size()); - if (clstates.size() == 0) continue; - - 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()); - if (clstates.size() == 0) continue; - - printf("Combining left and right states, disposing invalid combinations\n"); - combine_valid_left_right_states(&clstates,&crstates,&pgc_candidates); - - printf("Filtering the correct one using the middle part\n"); - for(itgc=pgc_candidates.begin();itgc!=pgc_candidates.end();++itgc) - { - num_to_bytes(*itgc,8,Gc_chk); - 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)) - { - printf("\nFound valid key: " _GREEN_("%016" PRIx64)"\n\n",*itgc); - return 0; - } + // Check if this is a simulation + if (argc == 2) { + // Generate random values for the key and randoms + srand((uint32_t)time(NULL)); + for (pos = 0; pos < 8; pos++) { + Gc[pos] = rand(); + Ci[pos] = rand(); + Q[pos] = rand(); + } + sm_auth(Gc, Ci, Q, Ch, Ci_1, &ostate); + printf(" Gc: "); + print_bytes(Gc, 8); + } else { + sscanf(argv[1], "%016" SCNx64, &nCi); + num_to_bytes(nCi, 8, Ci); + sscanf(argv[2], "%016" SCNx64, &nQ); + 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(_RED_("Could not find key using this right cipher state.\n\n")); - } - return 0; + + for (pos = 0; pos < 8; pos++) { + ks[2 * pos] = Ci_1[pos]; + ks[(2 * pos) + 1] = Ch[pos]; + } + + printf(" Ci: "); + print_bytes(Ci, 8); + printf(" Q: "); + print_bytes(Q, 8); + printf(" Ch: "); + print_bytes(Ch, 8); + printf("Ci+1: "); + print_bytes(Ci_1, 8); + printf("\n"); + printf(" Ks: "); + print_bytes(ks, 16); + printf("\n"); + + printf("Initializing lookup tables for increasing cipher speed\n"); + init_lookup_left(); + init_lookup_right(); + init_lookup_left_substraction(); + init_lookup_right_substraction(); + + // Load in the ci (tag-nonce), together with the first half of Q (reader-nonce) + rstate_before_gc = 0; + lstate_before_gc = 0; + for (pos = 0; pos < 4; pos++) { + next_right_fast(Ci[2 * pos ], &rstate_before_gc); + next_right_fast(Ci[2 * pos + 1], &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 + 1], &lstate_before_gc); + next_left_fast(Q[pos], &lstate_before_gc); + } + + printf("Determing the right states that correspond to the keystream\n"); + rbits = sm_right(ks, mask, &rstates); + 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()); + + if (rbits < 96) { + 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) { + rstate_after_gc = *itrstates; + 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); + + 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()); + if (crstates.size() == 0) continue; + + printf("Calculating left states using the (unknown bits) mask from the top-right state\n"); + sm_left(ks, mask, &clstates); + printf("Found a total of " _YELLOW_("%lu")" left cipher states, recovering left candidates...\n", clstates.size()); + if (clstates.size() == 0) continue; + + 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()); + if (clstates.size() == 0) continue; + + printf("Combining left and right states, disposing invalid combinations\n"); + combine_valid_left_right_states(&clstates, &crstates, &pgc_candidates); + + printf("Filtering the correct one using the middle part\n"); + for (itgc = pgc_candidates.begin(); itgc != pgc_candidates.end(); ++itgc) { + num_to_bytes(*itgc, 8, Gc_chk); + 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)) { + printf("\nFound valid key: " _GREEN_("%016" PRIx64)"\n\n", *itgc); + return 0; + } + } + printf(_RED_("Could not find key using this right cipher state.\n\n")); + } + return 0; } diff --git a/tools/cryptorf/sma_multi.cpp b/tools/cryptorf/sma_multi.cpp index d3658ff23..5c64ceeb0 100644 --- a/tools/cryptorf/sma_multi.cpp +++ b/tools/cryptorf/sma_multi.cpp @@ -1,9 +1,9 @@ /* - * + * * SecureMemory recovery Multithread * * Copyright (C) 2010, Flavio D. Garcia, Peter van Rossum, Roel Verdult - * and Ronny Wichers Schreur. Radboud University Nijmegen + * and Ronny Wichers Schreur. Radboud University Nijmegen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * Modifed Iceman, 2020 */ @@ -27,7 +27,7 @@ #include #include #include -#include // sort, max_element, random_shuffle, remove_if, lower_bound +#include // sort, max_element, random_shuffle, remove_if, lower_bound #include // greater, bind2nd #include // std::thread #include @@ -38,10 +38,10 @@ using namespace std; #ifdef _MSC_VER - // avoid scanf warnings in Visual Studio - #define _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_DEPRECATE - #define inline __inline +// avoid scanf warnings in Visual Studio +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_DEPRECATE +#define inline __inline #endif /* @@ -56,7 +56,7 @@ Authenticate Ci+1: de c2 ee 1b 1c 92 76 e9 Ks: de 88 c2 c9 ee d4 1b 46 1c 6a 92 50 76 1a e9 87 - + left: 1ddeac626 right: 19aba45 @@ -108,21 +108,21 @@ Ci+1: de c2 ee 1b 1c 92 76 e9 */ const uint64_t left_candidates[43] = { - 0x6221539d9ull, 0x1ddeac626ull, 0x7cc847482ull, 0x0337b8b7dull, - 0x159d1687eull, 0x7bade8a41ull, 0x4c51c6463ull, 0x4e3d88bf9ull, - 0x4e3d88819ull, 0x31c2777e6ull, 0x31c277406ull, 0x0059ff7d5ull, - 0x5fb612b96ull, 0x2049ed469ull, 0x0452175beull, 0x00d2ff4edull, - 0x68918cba9ull, 0x03a6f882aull, 0x7086372b6ull, 0x6c9a11672ull, - 0x60531191aull, 0x4ba9b653full, 0x4ba9b6520ull, 0x1facee6e5ull, - 0x0f79c8d49ull, 0x0b29f2a5bull, 0x032df8b12ull, 0x7c90849f8ull, - 0x48916e84eull, 0x176e73456ull, 0x036f7b607ull, 0x5b2aeb858ull, - 0x51c8755b5ull, 0x4c9432733ull, 0x0f6c834fbull, 0x03b2ff59bull, - 0x0f78aac5bull, 0x3770cdaf3ull, 0x205078bbaull, 0x04445c715ull, - 0x004df8a64ull, 0x6f696e09eull, 0x109691f61ull + 0x6221539d9ull, 0x1ddeac626ull, 0x7cc847482ull, 0x0337b8b7dull, + 0x159d1687eull, 0x7bade8a41ull, 0x4c51c6463ull, 0x4e3d88bf9ull, + 0x4e3d88819ull, 0x31c2777e6ull, 0x31c277406ull, 0x0059ff7d5ull, + 0x5fb612b96ull, 0x2049ed469ull, 0x0452175beull, 0x00d2ff4edull, + 0x68918cba9ull, 0x03a6f882aull, 0x7086372b6ull, 0x6c9a11672ull, + 0x60531191aull, 0x4ba9b653full, 0x4ba9b6520ull, 0x1facee6e5ull, + 0x0f79c8d49ull, 0x0b29f2a5bull, 0x032df8b12ull, 0x7c90849f8ull, + 0x48916e84eull, 0x176e73456ull, 0x036f7b607ull, 0x5b2aeb858ull, + 0x51c8755b5ull, 0x4c9432733ull, 0x0f6c834fbull, 0x03b2ff59bull, + 0x0f78aac5bull, 0x3770cdaf3ull, 0x205078bbaull, 0x04445c715ull, + 0x004df8a64ull, 0x6f696e09eull, 0x109691f61ull }; typedef struct { - uint64_t l; + uint64_t l; uint64_t m; uint64_t r; nibble b0; @@ -130,10 +130,10 @@ typedef struct { nibble b1l; nibble b1r; nibble b1s; - bool invalid; - uint8_t Gc[8]; -}cs_t; -typedef cs_t* pcs; + bool invalid; + uint8_t Gc[8]; +} cs_t; +typedef cs_t *pcs; typedef struct { uint8_t addition; @@ -141,39 +141,39 @@ typedef struct { } lookup_entry; enum cipher_state_side { - CSS_LEFT, - CSS_RIGHT + CSS_LEFT, + CSS_RIGHT }; -void print_cs(const char* text,pcs s) { - int pos; - - printf("%s",text); +void print_cs(const char *text, pcs s) { + int pos; - for(pos=6;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->l>>(pos*5))&0x1f); + printf("%s", text); - printf(" |"); - for(pos=6;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->m>>(pos*7))&0x7f); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->l >> (pos * 5)) & 0x1f); - printf(" |"); + printf(" |"); + for (pos = 6; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->m >> (pos * 7)) & 0x7f); - for(pos=4;pos>=0;pos--) - printf(" %02x",(uint8_t)(s->r>>(pos*5))&0x1f); - - printf("\n"); + printf(" |"); + + for (pos = 4; pos >= 0; pos--) + printf(" %02x", (uint8_t)(s->r >> (pos * 5)) & 0x1f); + + printf("\n"); } 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 - if (a> 5) & 0x1f; index = (b3 << 15) | b6; - + // b6 = bit_rotate_l(b6, 5); b6 = BIT_ROL(b6); - temp = mod(b3 + b6,0x1f); + temp = mod(b3 + b6, 0x1f); left_addition[index] = temp; lookup_left[index].addition = temp; - lookup_left[index].out = ((temp^b3) & 0x0f); + lookup_left[index].out = ((temp ^ b3) & 0x0f); } } @@ -222,143 +222,143 @@ static inline void init_lookup_right() { uint8_t b16, b18, temp; int i, index; - for(i = 0; i <0x400; i++) { + for (i = 0; i < 0x400; i++) { b18 = i & 0x1f; b16 = (i >> 5) & 0x1f; index = (b16 << 10) | b18; - temp = mod(b18 + b16,0x1f); + temp = mod(b18 + b16, 0x1f); 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() { - for(int index = 0; index < 0x400 ; index++) { + for (int index = 0; index < 0x400 ; index++) { uint8_t b3 = (index >> 5 & 0x1f); uint8_t bx = (index & 0x1f); //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() { - for(int index = 0; index < 0x400 ; index++) { - int b16 = (index >>5); + for (int index = 0; index < 0x400 ; index++) { + int b16 = (index >> 5); uint8_t bx = (index & 0x1f); lookup_right_subtraction[index] = mod((bx + 0x1F) - b16, 0x1F); } } static inline void previous_left(uint8_t in, vector *candidate_states) { - pcs state; - size_t size = candidate_states->size(); - for(size_t pos=0; possize(); + for (size_t pos = 0; pos < size; pos++) { + state = &((*candidate_states)[pos]); - uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); - unsigned b3 = (unsigned)(state->l >> 5) & 0x3e0; - state->l = (state->l << 5); + uint8_t bx = (uint8_t)((state->l >> 30) & 0x1f); + unsigned b3 = (unsigned)(state->l >> 5) & 0x3e0; + state->l = (state->l << 5); - //Ignore impossible states - if (bx == 0) { - // Are we dealing with an impossible state? - if (b3 != 0) { - state->invalid = true; - } else { - // We only need to consider b6=0 - state->l &= 0x7ffffffe0ull; - state->l ^= (((uint64_t)in & 0x1f) << 20); - } - } else { - uint8_t b6 = lookup_left_substraction[b3|bx]; - state->l = (state->l & 0x7ffffffe0ull) | b6; - state->l ^= (((uint64_t)in & 0x1f) << 20); + //Ignore impossible states + if (bx == 0) { + // Are we dealing with an impossible state? + if (b3 != 0) { + state->invalid = true; + } else { + // We only need to consider b6=0 + state->l &= 0x7ffffffe0ull; + state->l ^= (((uint64_t)in & 0x1f) << 20); + } + } else { + uint8_t b6 = lookup_left_substraction[b3 | bx]; + state->l = (state->l & 0x7ffffffe0ull) | b6; + state->l ^= (((uint64_t)in & 0x1f) << 20); - // Check if we have a second candidate - if (b6 == 0x1f) { - cs_t nstate = *state; - nstate.l &= 0x7ffffffe0ull; - candidate_states->push_back(nstate); - } + // Check if we have a second candidate + if (b6 == 0x1f) { + cs_t nstate = *state; + nstate.l &= 0x7ffffffe0ull; + candidate_states->push_back(nstate); + } + } } - } } static inline void previous_right(uint8_t in, vector *candidate_states) { - pcs state; - size_t size = candidate_states->size(); - for(size_t pos=0; posr >> 20) & 0x1f); - unsigned b16 = (unsigned)(state->r & 0x3e0);//(state->buffer_r >> 10) & 0x1f; - - state->r = (state->r << 5); - - // Ignore impossible states - if (bx == 0) { - if (b16 != 0) { - state->invalid=true; - } else { - // We only need to consider b18=0 - state->r &= 0x1ffffe0ull; - state->r ^= (((uint64_t)in & 0xf8) << 12); - } - } else { - uint8_t b18 = lookup_right_subtraction[b16|bx]; - state->r = (state->r & 0x1ffffe0ull) | b18; - state->r ^= (((uint64_t)in & 0xf8) << 12); - //state->b_right = ((b14^b17) & 0x0f); - - // Check if we have a second candidate - if (b18 == 0x1f) { - cs_t nstate = *state; - nstate.r &= 0x1ffffe0ull; - candidate_states->push_back(nstate); - } - } - } + pcs state; + size_t size = candidate_states->size(); + for (size_t pos = 0; pos < size; pos++) { + state = &((*candidate_states)[pos]); + + uint8_t bx = (uint8_t)((state->r >> 20) & 0x1f); + unsigned b16 = (unsigned)(state->r & 0x3e0);//(state->buffer_r >> 10) & 0x1f; + + state->r = (state->r << 5); + + // Ignore impossible states + if (bx == 0) { + if (b16 != 0) { + state->invalid = true; + } else { + // We only need to consider b18=0 + state->r &= 0x1ffffe0ull; + state->r ^= (((uint64_t)in & 0xf8) << 12); + } + } else { + uint8_t b18 = lookup_right_subtraction[b16 | bx]; + state->r = (state->r & 0x1ffffe0ull) | b18; + state->r ^= (((uint64_t)in & 0xf8) << 12); + //state->b_right = ((b14^b17) & 0x0f); + + // Check if we have a second candidate + if (b18 == 0x1f) { + cs_t nstate = *state; + nstate.r &= 0x1ffffe0ull; + candidate_states->push_back(nstate); + } + } + } } -static inline uint8_t next_left_fast(uint8_t in, uint64_t* left) { - if (in) +static inline uint8_t next_left_fast(uint8_t in, uint64_t *left) { + if (in) *left ^= ((in & 0x1f) << 20); - lookup_entry* lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); + lookup_entry *lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); return lookup->out; } -static inline uint8_t next_left_ksbyte(uint64_t* left) { - lookup_entry* lookup; - uint8_t bt; - - *left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); - lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); - bt = lookup->out << 4; - *left = (((*left) >> 5)| ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); - lookup = &(lookup_left[((*left) & 0xf801f)]); - *left = (((*left) >> 5)| ((uint64_t)lookup->addition << 30)); - bt |= lookup->out; +static inline uint8_t next_left_ksbyte(uint64_t *left) { + lookup_entry *lookup; + uint8_t bt; + + *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); + lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); + bt = lookup->out << 4; + *left = (((*left) >> 5) | ((uint64_t)left_addition[((*left) & 0xf801f)] << 30)); + lookup = &(lookup_left[((*left) & 0xf801f)]); + *left = (((*left) >> 5) | ((uint64_t)lookup->addition << 30)); + bt |= lookup->out; return bt; } -static inline uint8_t next_right_fast(uint8_t in, uint64_t* right) { - if (in) *right ^= ((in&0xf8) << 12); - lookup_entry* lookup = &(lookup_right[((*right) & 0x7c1f)]); +static inline uint8_t next_right_fast(uint8_t in, uint64_t *right) { + if (in) *right ^= ((in & 0xf8) << 12); + lookup_entry *lookup = &(lookup_right[((*right) & 0x7c1f)]); *right = (((*right) >> 5) | (lookup->addition << 20)); 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++) { - next_right_fast(0,&rstate); - uint8_t bt = next_right_fast(0,&rstate) << 4; - next_right_fast(0,&rstate); - bt |= next_right_fast(0,&rstate); + next_right_fast(0, &rstate); + uint8_t bt = next_right_fast(0, &rstate) << 4; + next_right_fast(0, &rstate); + bt |= next_right_fast(0, &rstate); // xor the bits with the keystream and count the "correct" bits bt ^= ks[pos]; @@ -374,19 +374,19 @@ std::atomic key{0}; std::atomic topbits{0}; std::mutex g_ice_mtx; uint32_t g_num_cpus = std::thread::hardware_concurrency(); - - + + static void ice_sm_right_thread( uint8_t offset, - uint8_t skips, - const uint8_t* ks, - map* bincstates, - uint8_t* mask - ) { - + uint8_t skips, + const uint8_t *ks, + map *bincstates, + uint8_t *mask +) { + uint8_t tmp_mask[16]; uint8_t bt; - + for (uint64_t counter = offset; counter < 0x2000000; counter += skips) { // Reset the current bitcount of correct bits size_t bits = 0; @@ -428,7 +428,7 @@ static void ice_sm_right_thread( memcpy(mask, tmp_mask, 16); } g_ice_mtx.unlock(); - + // Ignore states under 90 if (bits >= 90) { // Make sure the bits are used for ordering @@ -436,39 +436,39 @@ static void ice_sm_right_thread( if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end()) bincstates->at((((uint64_t)bits) << 56) | counter) = counter; else - bincstates->insert( std::pair( (((uint64_t)bits) << 56) | counter, counter)); + bincstates->insert(std::pair((((uint64_t)bits) << 56) | counter, counter)); g_ice_mtx.unlock(); } - + if ((counter & 0xfffff) == 0) { g_ice_mtx.lock(); printf("."); fflush(stdout); g_ice_mtx.unlock(); } - } + } } -static uint32_t ice_sm_right(const uint8_t* ks, uint8_t* mask, vector* pcrstates) { +static uint32_t ice_sm_right(const uint8_t *ks, uint8_t *mask, vector *pcrstates) { uint32_t g_num_cpus = std::thread::hardware_concurrency(); - map bincstates; + map bincstates; topbits = ATOMIC_VAR_INIT(0); std::vector threads(g_num_cpus); 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(); } printf("\n"); - // Clear the candidate state vector + // Clear the candidate state vector pcrstates->clear(); // Copy the order the states from lowest-bin to highest-bin - map::iterator it; + map::iterator it; for (it = bincstates.begin(); it != bincstates.end(); ++it) { pcrstates->push_back(it->second); } @@ -481,35 +481,35 @@ static uint32_t ice_sm_right(const uint8_t* ks, uint8_t* mask, vector* static void ice_sm_left_thread( uint8_t offset, - uint8_t skips, - const uint8_t* ks, - map* bincstates, - uint8_t* mask - ) { + uint8_t skips, + const uint8_t *ks, + map *bincstates, + uint8_t *mask +) { size_t pos, bits; uint8_t correct_bits[16]; - uint8_t bt; - lookup_entry* lookup; + uint8_t bt; + lookup_entry *lookup; // Reset and initialize the cryptostate and vector cs_t state; memset(&state, 0x00, sizeof(cs_t)); state.invalid = false; - + for (uint64_t counter = offset; counter < 0x800000000ull; counter += skips) { uint64_t lstate = counter; 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)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); 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)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); bt |= lookup->out; // xor the bits with the keystream and count the "correct" bits @@ -521,10 +521,10 @@ static void ice_sm_left_thread( // Save the correct bits for statistical information correct_bits[pos] = bt; } - + // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! if (pos == 16) { - // Count the total correct bits + // Count the total correct bits bits = 0; for (pos = 0; pos < 16; pos++) { // Get the next byte-value with correct bits @@ -541,9 +541,9 @@ static void ice_sm_left_thread( if (((bt >> 6) & 0x01) == 0) bits++; if (((bt >> 7) & 0x01) == 0) bits++; } - + state.l = counter; - + // Make sure the bits are used for ordering g_ice_mtx.lock(); printf("."); @@ -551,53 +551,53 @@ static void ice_sm_left_thread( if (bincstates->find((((uint64_t)bits) << 56) | counter) != bincstates->end()) bincstates->at((((uint64_t)bits) << 56) | counter) = state; else - bincstates->insert( std::pair( (((uint64_t)bits) << 56) | counter, state)); + bincstates->insert(std::pair((((uint64_t)bits) << 56) | counter, state)); g_ice_mtx.unlock(); - + } - + if ((counter & 0xffffffffull) == 0) { g_ice_mtx.lock(); - printf("%02.1f%%.", ((float)100/8) * (counter >> 32)); + printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32)); fflush(stdout); g_ice_mtx.unlock(); } } } -static void ice_sm_left(const uint8_t* ks, uint8_t* mask, vector* pcstates) { +static void ice_sm_left(const uint8_t *ks, uint8_t *mask, vector *pcstates) { uint32_t g_num_cpus = std::thread::hardware_concurrency(); map bincstates; std::vector threads(g_num_cpus); 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(); } printf("100%%\n"); - // Clear the candidate state vector + // Clear the candidate state vector pcstates->clear(); // Copy the order the states from lowest-bin to highest-bin map::iterator it; - for(it = bincstates.begin(); it != bincstates.end(); ++it) { + for (it = bincstates.begin(); it != bincstates.end(); ++it) { pcstates->push_back(it->second); } // 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* pcrstates) { +static inline uint32_t sm_right(const uint8_t *ks, uint8_t *mask, vector *pcrstates) { uint8_t tmp_mask[16]; size_t pos, bits, bit, topbits; - map bincstates; - map::iterator it; + map bincstates; + map::iterator it; uint8_t bt; topbits = 0; @@ -624,7 +624,7 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector>= 1; + bt >>= 1; } } @@ -633,13 +633,13 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector= 90) { - // Make sure the bits are used for ordering + // Make sure the bits are used for ordering bincstates[(((uint64_t)bits) << 56) | counter] = counter; } - + if ((counter & 0xfffff) == 0) { printf("."); fflush(stdout); @@ -647,7 +647,7 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vectorclear(); // Copy the order the states from lowest-bin to highest-bin @@ -662,189 +662,189 @@ static inline uint32_t sm_right(const uint8_t* ks, uint8_t* mask, vector *pcstates, uint32_t gc_byte_index, cipher_state_side css) { - uint8_t btGc,in; + uint8_t btGc, in; vector ncstates; vector prev_ncstates; - vector::iterator it,itnew; + vector::iterator it, itnew; - // Loop through the complete entryphy of 5 bits for each candidate - // We ignore zero (xor 0x00) to avoid duplicates - for (btGc=0; btGc<0x20; btGc++) { - // Copy the original candidates that are supplied - ncstates = *pcstates; + // Loop through the complete entryphy of 5 bits for each candidate + // We ignore zero (xor 0x00) to avoid duplicates + for (btGc = 0; btGc < 0x20; btGc++) { + // Copy the original candidates that are supplied + ncstates = *pcstates; - // Rollback the (candidate) cipher states with this input - if (css == CSS_RIGHT) { - in = btGc << 3; - previous_right(in,&ncstates); - } else { - in = btGc; - previous_left(in,&ncstates); - } - - for(itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) { - // Wipe away the invalid states - if (itnew->invalid == false) { - itnew->Gc[gc_byte_index] = in; - prev_ncstates.push_back(*itnew); - } - } - } - - // Copy the previous states into the vector - *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* pcstates) { - vector::iterator it; - vector csl_cand; - map matchbox; - map::iterator itmatch; - uint64_t rstate; - size_t counter; - cs_t state; - - // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) - for (counter=0; counter<0x100000; counter++) { - rstate = rstate_before_gc; - next_right_fast((counter >> 12) & 0xf8,&rstate); - next_right_fast((counter >> 7) & 0xf8,&rstate); - next_right_fast(Q[4],&rstate); - next_right_fast((counter >> 2) & 0xf8,&rstate); - next_right_fast((counter << 3) & 0xf8,&rstate); - next_right_fast(Q[5],&rstate); - matchbox[rstate] = counter; - } - - // Reset and initialize the cryptostate and vecctor - memset(&state,0x00,sizeof(cs_t)); - state.invalid = false; - state.r = rstate_after_gc; - csl_cand.clear(); - csl_cand.push_back(state); - - // 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_all_input(&csl_cand,7,CSS_RIGHT); - previous_all_input(&csl_cand,6,CSS_RIGHT); - previous_right(Q[6],&csl_cand); - previous_all_input(&csl_cand,5,CSS_RIGHT); - previous_all_input(&csl_cand,4,CSS_RIGHT); - - pcstates->clear(); - - // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) - for (it=csl_cand.begin();it!=csl_cand.end();++it) { - itmatch = matchbox.find(it->r); - if (itmatch != matchbox.end()) { - it->Gc[0] = (itmatch->second >> 12) & 0xf8; - it->Gc[1] = (itmatch->second >> 7) & 0xf8; - it->Gc[2] = (itmatch->second >> 2) & 0xf8; - it->Gc[3] = (itmatch->second << 3) & 0xf8; - - pcstates->push_back(*it); - } - } -} - -static inline void sm_left(const uint8_t* ks, uint8_t* mask, vector* pcstates) { - map bincstates; - map::iterator it; - uint64_t counter, lstate; - size_t pos, bits; - uint8_t correct_bits[16]; - uint8_t bt; - cs_t state; - lookup_entry* lookup; - - // Reset and initialize the cryptostate and vecctor - memset(&state, 0x00, sizeof(cs_t)); - state.invalid = false; - - for (counter = 0; counter < 0x800000000ull; counter++) { - lstate = counter; - - for (pos = 0; pos < 16; pos++) { - - lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); - lookup = &(lookup_left[((lstate) & 0xf801f)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); - bt = lookup->out << 4; - lstate = (((lstate) >> 5)| ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); - lookup = &(lookup_left[((lstate) & 0xf801f)]); - lstate = (((lstate) >> 5)| ((uint64_t)lookup->addition << 30)); - bt |= lookup->out; - - // xor the bits with the keystream and count the "correct" bits - bt ^= ks[pos]; - - // When the REQUIRED bits are NOT xored away (=zero), ignore this wrong state - if ((bt & mask[pos]) != 0) break; - - // Save the correct bits for statistical information - correct_bits[pos] = bt; - } - - // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! - if (pos == 16) { - // Count the total correct bits - bits = 0; - for (pos = 0; pos < 16; pos++) { - // Get the next byte-value with correct bits - bt = correct_bits[pos]; - - // Count all the (correct) bits - // When the bit is xored away (=zero), it was the same, so correct ;) - if ((bt & 0x01) == 0) bits++; - if (((bt >> 1) & 0x01) == 0) bits++; - if (((bt >> 2) & 0x01) == 0) bits++; - if (((bt >> 3) & 0x01) == 0) bits++; - if (((bt >> 4) & 0x01) == 0) bits++; - if (((bt >> 5) & 0x01) == 0) bits++; - if (((bt >> 6) & 0x01) == 0) bits++; - if (((bt >> 7) & 0x01) == 0) bits++; - + // Rollback the (candidate) cipher states with this input + if (css == CSS_RIGHT) { + in = btGc << 3; + previous_right(in, &ncstates); + } else { + in = btGc; + previous_left(in, &ncstates); } - // Print the left candidate - // printf("%09llx (%d)\n",counter,bits); - printf("."); - fflush(stdout); - - state.l = counter; - // Make sure the bits are used for ordering - bincstates[(((uint64_t)bits)<<56) | counter] = state; + for (itnew = ncstates.begin(); itnew != ncstates.end(); ++itnew) { + // Wipe away the invalid states + if (itnew->invalid == false) { + itnew->Gc[gc_byte_index] = in; + prev_ncstates.push_back(*itnew); + } + } } - - if ((counter & 0xffffffffull) == 0) { - printf("%02.1f%%.", ((float)100/8)*(counter>>32)); - fflush(stdout); - } - } - printf("100%%\n"); - - // Clear the candidate state vector - pcstates->clear(); - - // Copy the order the states from lowest-bin to highest-bin - for(it = bincstates.begin(); it != bincstates.end(); ++it) { - pcstates->push_back(it->second); - } - // Reverse the vector order (so the higest bin comes first) - reverse(pcstates->begin(), pcstates->end()); + // Copy the previous states into the vector + *pcstates = prev_ncstates; } -static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t* Q, vector* pcstates) { - vector csl_cand,csl_search; - vector::iterator itsearch,itcand; - map matchbox; - map::iterator itmatch; +static inline void search_gc_candidates_right(const uint64_t rstate_before_gc, const uint64_t rstate_after_gc, const uint8_t *Q, vector *pcstates) { + vector::iterator it; + vector csl_cand; + map matchbox; + map::iterator itmatch; + uint64_t rstate; + size_t counter; + cs_t state; + + // Generate 2^20 different (5 bits) values for the first 4 Gc bytes (0,1,2,3) + for (counter = 0; counter < 0x100000; counter++) { + rstate = rstate_before_gc; + next_right_fast((counter >> 12) & 0xf8, &rstate); + next_right_fast((counter >> 7) & 0xf8, &rstate); + next_right_fast(Q[4], &rstate); + next_right_fast((counter >> 2) & 0xf8, &rstate); + next_right_fast((counter << 3) & 0xf8, &rstate); + next_right_fast(Q[5], &rstate); + matchbox[rstate] = counter; + } + + // Reset and initialize the cryptostate and vecctor + memset(&state, 0x00, sizeof(cs_t)); + state.invalid = false; + state.r = rstate_after_gc; + csl_cand.clear(); + csl_cand.push_back(state); + + // 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_all_input(&csl_cand, 7, CSS_RIGHT); + previous_all_input(&csl_cand, 6, CSS_RIGHT); + previous_right(Q[6], &csl_cand); + previous_all_input(&csl_cand, 5, CSS_RIGHT); + previous_all_input(&csl_cand, 4, CSS_RIGHT); + + pcstates->clear(); + + // Take the intersection of the corresponding states ~2^15 values (40-25 = 15 bits) + for (it = csl_cand.begin(); it != csl_cand.end(); ++it) { + itmatch = matchbox.find(it->r); + if (itmatch != matchbox.end()) { + it->Gc[0] = (itmatch->second >> 12) & 0xf8; + it->Gc[1] = (itmatch->second >> 7) & 0xf8; + it->Gc[2] = (itmatch->second >> 2) & 0xf8; + it->Gc[3] = (itmatch->second << 3) & 0xf8; + + pcstates->push_back(*it); + } + } +} + +static inline void sm_left(const uint8_t *ks, uint8_t *mask, vector *pcstates) { + map bincstates; + map::iterator it; + uint64_t counter, lstate; + size_t pos, bits; + uint8_t correct_bits[16]; + uint8_t bt; + cs_t state; + lookup_entry *lookup; + + // Reset and initialize the cryptostate and vecctor + memset(&state, 0x00, sizeof(cs_t)); + state.invalid = false; + + for (counter = 0; counter < 0x800000000ull; counter++) { + lstate = counter; + + for (pos = 0; pos < 16; pos++) { + + lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); + lookup = &(lookup_left[((lstate) & 0xf801f)]); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); + bt = lookup->out << 4; + lstate = (((lstate) >> 5) | ((uint64_t)left_addition[((lstate) & 0xf801f)] << 30)); + lookup = &(lookup_left[((lstate) & 0xf801f)]); + lstate = (((lstate) >> 5) | ((uint64_t)lookup->addition << 30)); + bt |= lookup->out; + + // xor the bits with the keystream and count the "correct" bits + bt ^= ks[pos]; + + // When the REQUIRED bits are NOT xored away (=zero), ignore this wrong state + if ((bt & mask[pos]) != 0) break; + + // Save the correct bits for statistical information + correct_bits[pos] = bt; + } + + // If we have parsed all 16 bytes of keystream, we have a valid CANDIDATE! + if (pos == 16) { + // Count the total correct bits + bits = 0; + for (pos = 0; pos < 16; pos++) { + // Get the next byte-value with correct bits + bt = correct_bits[pos]; + + // Count all the (correct) bits + // When the bit is xored away (=zero), it was the same, so correct ;) + if ((bt & 0x01) == 0) bits++; + if (((bt >> 1) & 0x01) == 0) bits++; + if (((bt >> 2) & 0x01) == 0) bits++; + if (((bt >> 3) & 0x01) == 0) bits++; + if (((bt >> 4) & 0x01) == 0) bits++; + if (((bt >> 5) & 0x01) == 0) bits++; + if (((bt >> 6) & 0x01) == 0) bits++; + if (((bt >> 7) & 0x01) == 0) bits++; + + } + + // Print the left candidate + // printf("%09llx (%d)\n",counter,bits); + printf("."); + fflush(stdout); + + state.l = counter; + // Make sure the bits are used for ordering + bincstates[(((uint64_t)bits) << 56) | counter] = state; + } + + if ((counter & 0xffffffffull) == 0) { + printf("%02.1f%%.", ((float)100 / 8) * (counter >> 32)); + fflush(stdout); + } + } + + printf("100%%\n"); + + // Clear the candidate state vector + pcstates->clear(); + + // Copy the order the states from lowest-bin to highest-bin + for (it = bincstates.begin(); it != bincstates.end(); ++it) { + pcstates->push_back(it->second); + } + // Reverse the vector order (so the higest bin comes first) + reverse(pcstates->begin(), pcstates->end()); +} + +static inline void search_gc_candidates_left(const uint64_t lstate_before_gc, const uint8_t *Q, vector *pcstates) { + vector csl_cand, csl_search; + vector::iterator itsearch, itcand; + map matchbox; + map::iterator itmatch; uint64_t lstate; size_t counter; // 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; next_left_fast((counter >> 15) & 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); // 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); - if (itmatch != matchbox.end()){ + if (itmatch != matchbox.end()) { itsearch->Gc[0] = (itmatch->second >> 15) & 0x1f; itsearch->Gc[1] = (itmatch->second >> 10) & 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"); } -void combine_valid_left_right_states(vector* plcstates, vector* prcstates, vector* pgc_candidates) { +void combine_valid_left_right_states(vector *plcstates, vector *prcstates, vector *pgc_candidates) { vector::iterator itl, itr; - size_t pos,count; + size_t pos, count; uint64_t gc; bool valid; vector outer, inner; - if ( plcstates->size() > prcstates->size()) { + if (plcstates->size() > prcstates->size()) { outer = *plcstates; inner = *prcstates; } else { @@ -909,8 +909,8 @@ void combine_valid_left_right_states(vector* plcstates, vector* prcs // Clean up the candidate list pgc_candidates->clear(); count = 0; - for( itl = outer.begin(); itl != outer.end(); ++itl) { - for(itr = inner.begin(); itr != inner.end(); ++itr) { + for (itl = outer.begin(); itl != outer.end(); ++itl) { + for (itr = inner.begin(); itr != inner.end(); ++itr) { valid = true; // Check for left and right candidates that share the overlapping bits (8 x 2bits of Gc) for (pos = 0; pos < 8; pos++) { @@ -932,26 +932,26 @@ void combine_valid_left_right_states(vector* plcstates, vector* prcs 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()); } static void ice_compare( - uint8_t offset, - uint8_t skips, - vector* candidates, - crypto_state_t* ostate, - uint8_t *Ci, - uint8_t *Q, - uint8_t *Ch, - uint8_t *Ci_1 - ) { + uint8_t offset, + uint8_t skips, + vector *candidates, + crypto_state_t *ostate, + uint8_t *Ci, + uint8_t *Q, + uint8_t *Ch, + uint8_t *Ci_1 +) { uint8_t Gc_chk[8]; - uint8_t Ch_chk[ 8]; + uint8_t Ch_chk[ 8]; uint8_t Ci_1_chk[ 8]; for (std::size_t i = offset; i < candidates->size(); i += skips) { - if (key_found.load(std::memory_order_relaxed)) + if (key_found.load(std::memory_order_relaxed)) break; uint64_t tkey = candidates->at(i); @@ -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; crypto_state_t ostate; uint64_t rstate_before_gc, rstate_after_gc; @@ -984,7 +984,7 @@ int main(int argc, const char* argv[]) { // uint8_t Gc[ 8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // uint8_t Ci[ 8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; // uint8_t Q[ 8] = {0x12,0x34,0x56,0x78,0x12,0x34,0x56,0x78}; - uint8_t Gc[ 8]; + uint8_t Gc[ 8]; uint8_t Ci[ 8]; uint8_t Q[ 8]; uint8_t Ch[ 8]; @@ -1015,32 +1015,42 @@ int main(int argc, const char* argv[]) { if (argc == 2) { // Generate random values for the key and randoms srand((uint32_t)time(NULL)); - for (pos = 0; pos<8; pos++) { + for (pos = 0; pos < 8; pos++) { Gc[pos] = rand(); Ci[pos] = rand(); Q[pos] = rand(); } - sm_auth(Gc,Ci,Q,Ch,Ci_1,&ostate); - printf(" Gc: "); print_bytes(Gc,8); + sm_auth(Gc, Ci, Q, Ch, Ci_1, &ostate); + printf(" Gc: "); + print_bytes(Gc, 8); } else { - sscanf(argv[1],"%016" SCNx64,&nCi); num_to_bytes(nCi,8,Ci); - sscanf(argv[2],"%016" SCNx64,&nQ); 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); + sscanf(argv[1], "%016" SCNx64, &nCi); + num_to_bytes(nCi, 8, Ci); + sscanf(argv[2], "%016" SCNx64, &nQ); + 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"); } - for (pos = 0; pos<8; pos++) { - ks[2*pos] = Ci_1[pos]; - ks[(2*pos)+1] = Ch[pos]; + for (pos = 0; pos < 8; pos++) { + ks[2 * pos] = Ci_1[pos]; + ks[(2 * pos) + 1] = Ch[pos]; } - printf(" Ci: "); print_bytes(Ci,8); - printf(" Q: "); print_bytes(Q,8); - printf(" Ch: "); print_bytes(Ch,8); - printf("Ci+1: "); print_bytes(Ci_1,8); + printf(" Ci: "); + print_bytes(Ci, 8); + printf(" Q: "); + print_bytes(Q, 8); + printf(" Ch: "); + print_bytes(Ch, 8); + printf("Ci+1: "); + print_bytes(Ci_1, 8); printf("\n"); - printf(" Ks: "); print_bytes(ks,16); + printf(" Ks: "); + print_bytes(ks, 16); printf("\n"); printf("\nMultithreaded, will use " _YELLOW_("%u") " threads\n", g_num_cpus); @@ -1061,17 +1071,17 @@ int main(int argc, const char* argv[]) { lstate_before_gc = 0; for (pos = 0; pos < 4; pos++) { - 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 ], &rstate_before_gc); + next_right_fast(Ci[2 * pos + 1], &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+1], &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(Q[pos], &lstate_before_gc); } printf("Determing the right states that correspond to the keystream\n"); - //rbits = sm_right(ks, mask, &rstates); + //rbits = sm_right(ks, mask, &rstates); rbits = ice_sm_right(ks, mask, &rstates); printf("Top-bin for the right state contains " _GREEN_("%d")" correct bits\n", rbits); @@ -1080,7 +1090,7 @@ int main(int argc, const char* argv[]) { if (rbits < 96) { 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) { rstate_after_gc = *itrstates; sm_left_mask(ks, mask, rstate_after_gc); @@ -1097,8 +1107,8 @@ int main(int argc, const char* argv[]) { printf("Found a total of " _YELLOW_("%lu")" left cipher states, recovering left candidates...\n", clstates.size()); if (clstates.size() == 0) continue; 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()); if (clstates.size() == 0) continue; @@ -1106,16 +1116,16 @@ int main(int argc, const char* argv[]) { combine_valid_left_right_states(&clstates, &crstates, &pgc_candidates); printf("Filtering the correct one using the middle part\n"); - + key_found = ATOMIC_VAR_INIT(false); std::vector threads(g_num_cpus); 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(); } @@ -1123,7 +1133,7 @@ int main(int argc, const char* argv[]) { printf("\nFound valid key: " _GREEN_("%016lX")"\n\n", key.load()); break; } - + printf(_RED_("\nCould not find key using this right cipher state.\n\n")); } return 0; diff --git a/tools/cryptorf/util.c b/tools/cryptorf/util.c index 081fb43cf..81db9f6ef 100644 --- a/tools/cryptorf/util.c +++ b/tools/cryptorf/util.c @@ -1,23 +1,21 @@ #include "util.h" #include -void num_to_bytes(uint64_t n, size_t len, uint8_t *dst) -{ - while (len--) { - dst[len] = (uint8_t)n; - n >>= 8; - } +void num_to_bytes(uint64_t n, size_t len, uint8_t *dst) { + while (len--) { + dst[len] = (uint8_t)n; + n >>= 8; + } } -void print_bytes(const uint8_t *pbtData, const size_t szLen) -{ - size_t uiPos; - for (uiPos = 0; uiPos < szLen; uiPos++) { - printf("%02x ", pbtData[uiPos]); - if (uiPos > 20) { - printf("..."); - break; +void print_bytes(const uint8_t *pbtData, const size_t szLen) { + size_t uiPos; + for (uiPos = 0; uiPos < szLen; uiPos++) { + printf("%02x ", pbtData[uiPos]); + if (uiPos > 20) { + printf("..."); + break; + } } - } - printf("\n"); + printf("\n"); }