Conflicts:
	client/cmdhfmf.c
	client/cmdmain.c
This commit is contained in:
iceman 2016-02-10 13:29:23 +01:00
commit 480e2f2394
12 changed files with 249 additions and 121 deletions

View file

@ -141,7 +141,9 @@ CMDSRCS = nonce2key/crapto1.c\
reveng/poly.c\ reveng/poly.c\
reveng/getopt.c\ reveng/getopt.c\
tea.c\ tea.c\
prng.c prng.c\
radixsort.c\
bucketsort.c
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED

View file

@ -63,8 +63,9 @@ start:
} }
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
isOK = resp.arg[0]; isOK = resp.arg[0];
printf("\n\n");
switch (isOK) { switch (isOK) {
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break; case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break; case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
@ -73,7 +74,7 @@ start:
PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break; PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;
default: ; default: ;
} }
uid = (uint32_t)bytes_to_num(resp.d.asBytes, 4); uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4);
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
par_list = bytes_to_num(resp.d.asBytes + 8, 8); par_list = bytes_to_num(resp.d.asBytes + 8, 8);
ks_list = bytes_to_num(resp.d.asBytes + 16, 8); ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
@ -711,6 +712,7 @@ int CmdHF14AMfNested(const char *Cmd)
// nested sectors // nested sectors
iterations = 0; iterations = 0;
PrintAndLog("enter nested...");
bool calibrate = true; bool calibrate = true;
for (i = 0; i < NESTED_SECTOR_RETRY; i++) { for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
@ -731,7 +733,7 @@ int CmdHF14AMfNested(const char *Cmd)
case -5 : case -5 :
calibrate = false; calibrate = false;
iterations++; iterations++;
e_sector[sectorNo].foundKey[trgKeyType] = TRUE; e_sector[sectorNo].foundKey[trgKeyType] = 1;
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
continue; continue;
@ -763,7 +765,7 @@ int CmdHF14AMfNested(const char *Cmd)
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue; if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue;
uint8_t isOK = resp.arg[0] & 0xff; uint8_t isOK = resp.arg[0] & 0xff;
if (!isOK) continue; if (!isOK) continue;
@ -1132,6 +1134,7 @@ int CmdHF14AMfChk(const char *Cmd)
// skip already found keys. // skip already found keys.
if (e_sector[i].foundKey[trgKeyType]) continue; if (e_sector[i].foundKey[trgKeyType]) continue;
for (uint32_t c = 0; c < keycnt; c += max_keys) { for (uint32_t c = 0; c < keycnt; c += max_keys) {
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;

View file

@ -23,6 +23,7 @@
// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks // #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks
#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks #define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks
#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks #define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks
#define T55X7_PYRAMID_CONFIG_BLOCK 0x00107080 // Pyramid 26 bit - compat mode, FSK2a, data rate 50, 4 data blocks
#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2 #define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2
#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7 #define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7
#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks #define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks

View file

@ -81,6 +81,7 @@ int CmdVikingClone(const char *Cmd) {
rawID = getVikingBits(id); rawID = getVikingBits(id);
PrintAndLog("Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFFFFFF, Q5}}; UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFFFFFF, Q5}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
@ -107,9 +108,10 @@ int CmdVikingSim(const char *Cmd) {
arg1 = clk << 8 | encoding; arg1 = clk << 8 | encoding;
arg2 = invert << 8 | separator; arg2 = invert << 8 | separator;
PrintAndLog("Simulating - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
PrintAndLog("preparing to sim ask data: %d bits", size); num_to_bytebits(rawID, size, c.d.asBytes);
num_to_bytebits(rawID, 64, c.d.asBytes);
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;

View file

@ -183,9 +183,10 @@ void UsbCommandReceived(UsbCommand *UC)
case CMD_DEBUG_PRINT_STRING: { case CMD_DEBUG_PRINT_STRING: {
char s[USB_CMD_DATA_SIZE+1]; char s[USB_CMD_DATA_SIZE+1];
memset(s, 0x00, sizeof(s)); memset(s, 0x00, sizeof(s));
size_t len = MIN(UC->arg[0], USB_CMD_DATA_SIZE); size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
memcpy(s, UC->d.asBytes, len); memcpy(s, UC->d.asBytes, len);
PrintAndLog("#db# %s", s); PrintAndLog("#db# %s", s);
return;
} break; } break;
case CMD_DEBUG_PRINT_INTEGERS: case CMD_DEBUG_PRINT_INTEGERS:
@ -201,5 +202,6 @@ void UsbCommandReceived(UsbCommand *UC)
break; break;
} }
} }
} }

View file

@ -31,90 +31,10 @@ static void __attribute__((constructor)) fill_lut()
#define filter(x) (filterlut[(x) & 0xfffff]) #define filter(x) (filterlut[(x) & 0xfffff])
#endif #endif
typedef struct bucket {
uint32_t *head;
uint32_t *bp;
} bucket_t;
typedef bucket_t bucket_array_t[2][0x100];
typedef struct bucket_info {
struct {
uint32_t *head, *tail;
} bucket_info[2][0x100];
uint32_t numbuckets;
} bucket_info_t;
static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
uint32_t* const ostart, uint32_t* const ostop,
bucket_info_t *bucket_info, bucket_array_t bucket)
{
uint32_t *p1, *p2;
uint32_t *start[2];
uint32_t *stop[2];
start[0] = estart;
stop[0] = estop;
start[1] = ostart;
stop[1] = ostop;
// init buckets to be empty
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t j = 0x00; j <= 0xff; j++) {
bucket[i][j].bp = bucket[i][j].head;
}
}
// sort the lists into the buckets based on the MSB (contribution bits)
for (uint32_t i = 0; i < 2; i++) {
for (p1 = start[i]; p1 <= stop[i]; p1++) {
uint32_t bucket_index = (*p1 & 0xff000000) >> 24;
*(bucket[i][bucket_index].bp++) = *p1;
}
}
// write back intersecting buckets as sorted list.
// fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets.
uint32_t nonempty_bucket;
for (uint32_t i = 0; i < 2; i++) {
p1 = start[i];
nonempty_bucket = 0;
for (uint32_t j = 0x00; j <= 0xff; j++) {
if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only
bucket_info->bucket_info[i][nonempty_bucket].head = p1;
for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++);
bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1;
nonempty_bucket++;
}
}
bucket_info->numbuckets = nonempty_bucket;
}
}
/** binsearch
* Binary search for the first occurence of *stop's MSB in sorted [start,stop]
*/
static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop)
{
uint32_t mid, val = *stop & 0xff000000;
while(start != stop)
if(start[mid = (stop - start) >> 1] > val)
stop = &start[mid];
else
start += mid + 1;
return start;
}
/** update_contribution /** update_contribution
* helper, calculates the partial linear feedback contributions and puts in MSB * helper, calculates the partial linear feedback contributions and puts in MSB
*/ */
static inline void static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
{ {
uint32_t p = *item >> 25; uint32_t p = *item >> 25;
@ -126,8 +46,7 @@ update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
/** extend_table /** extend_table
* using a bit of the keystream extend the table of possible lfsr states * using a bit of the keystream extend the table of possible lfsr states
*/ */
static inline void static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)
extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)
{ {
in <<= 24; in <<= 24;
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)
@ -150,14 +69,16 @@ extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in
*/ */
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)
{ {
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) {
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace if(filter(*tbl) ^ filter(*tbl | 1)) { // replace
*tbl |= filter(*tbl) ^ bit; *tbl |= filter(*tbl) ^ bit;
} else if(filter(*tbl) == bit) { // insert } else if(filter(*tbl) == bit) { // insert
*++*end = *++tbl; *++*end = *++tbl;
*tbl = tbl[-1] | 1; *tbl = tbl[-1] | 1;
} else // drop } else { // drop
*tbl-- = *(*end)--; *tbl-- = *(*end)--;
}
}
} }
/** recover /** recover
* recursively narrow down the search space, 4 bits of keystream at a time * recursively narrow down the search space, 4 bits of keystream at a time
@ -186,13 +107,11 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
oks >>= 1; oks >>= 1;
eks >>= 1; eks >>= 1;
in >>= 2; in >>= 2;
extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0);
LF_POLY_ODD << 1, 0);
if(o_head > o_tail) if(o_head > o_tail)
return sl; return sl;
extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3);
LF_POLY_EVEN << 1 | 1, in & 3);
if(e_head > e_tail) if(e_head > e_tail)
return sl; return sl;
} }
@ -238,14 +157,8 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
// allocate memory for out of place bucket_sort // allocate memory for out of place bucket_sort
bucket_array_t bucket; bucket_array_t bucket;
for (uint32_t i = 0; i < 2; i++)
for (uint32_t j = 0; j <= 0xff; j++) {
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);
if (!bucket[i][j].head) {
goto out;
}
}
if ( !bucket_malloc(bucket) ) goto out;
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream
for(i = 1 << 20; i >= 0; --i) { for(i = 1 << 20; i >= 0; --i) {
@ -265,17 +178,12 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"
// parameter into account. // parameter into account.
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping
recover(odd_head, odd_tail, oks, recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);
even_head, even_tail, eks, 11, statelist, in << 1, bucket);
out: out:
free(odd_head); free(odd_head);
free(even_head); free(even_head);
for (uint32_t i = 0; i < 2; i++) bucket_free(bucket);
for (uint32_t j = 0; j <= 0xff; j++)
free(bucket[i][j].head);
return statelist; return statelist;
} }

View file

@ -20,6 +20,7 @@
#ifndef CRAPTO1_H__ #ifndef CRAPTO1_H__
#define CRAPTO1_H__ #define CRAPTO1_H__
#include <stdint.h> #include <stdint.h>
#include "bucketsort.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View file

@ -80,10 +80,7 @@ void ProxGuiQT::MainLoop()
plotapp->exec(); plotapp->exec();
} }
ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), argc(argc), argv(argv) {}
argc(argc), argv(argv)
{
}
ProxGuiQT::~ProxGuiQT(void) ProxGuiQT::~ProxGuiQT(void)
{ {
@ -310,7 +307,6 @@ void ProxWidget::mouseMoveEvent(QMouseEvent *event)
CursorBPos = x; CursorBPos = x;
} }
this->update(); this->update();
} }

65
common/bucketsort.c Normal file
View file

@ -0,0 +1,65 @@
#include "bucketsort.h"
bool bucket_malloc(bucket_array_t bucket) {
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t j = 0; j <= 0xff; j++) {
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);
if (!bucket[i][j].head) {
return false;
}
}
}
return true;
}
void bucket_free(bucket_array_t bucket) {
for (uint8_t i = 0; i < 2; i++)
for (uint8_t j = 0; j <= 0xff; j++)
free(bucket[i][j].head);
}
void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
uint32_t* const ostart, uint32_t* const ostop,
bucket_info_t *bucket_info, bucket_array_t bucket)
{
uint32_t *p1, *p2;
uint32_t *start[2];
uint32_t *stop[2];
start[0] = estart;
stop[0] = estop;
start[1] = ostart;
stop[1] = ostop;
// init buckets to be empty
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t j = 0x00; j <= 0xff; j++) {
bucket[i][j].bp = bucket[i][j].head;
}
}
// sort the lists into the buckets based on the MSB (contribution bits)
for (uint32_t i = 0; i < 2; i++) {
for (p1 = start[i]; p1 <= stop[i]; p1++) {
uint32_t bucket_index = (*p1 & 0xff000000) >> 24;
*(bucket[i][bucket_index].bp++) = *p1;
}
}
// write back intersecting buckets as sorted list.
// fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets.
uint32_t nonempty_bucket;
for (uint32_t i = 0; i < 2; i++) {
p1 = start[i];
nonempty_bucket = 0;
for (uint32_t j = 0x00; j <= 0xff; j++) {
if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only
bucket_info->bucket_info[i][nonempty_bucket].head = p1;
for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++);
bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1;
nonempty_bucket++;
}
}
bucket_info->numbuckets = nonempty_bucket;
}
}

26
common/bucketsort.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef BUCKETSORT_H__
#define BUCKETSORT_H__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct bucket {
uint32_t *head;
uint32_t *bp;
} bucket_t;
typedef bucket_t bucket_array_t[2][0x100];
typedef struct bucket_info {
struct {
uint32_t *head, *tail;
} bucket_info[2][0x100];
uint32_t numbuckets;
} bucket_info_t;
bool bucket_malloc(bucket_array_t bucket);
void bucket_free(bucket_array_t bucket);
void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
uint32_t* const ostart, uint32_t* const ostop,
bucket_info_t *bucket_info, bucket_array_t bucket);
#endif

99
common/radixsort.c Normal file
View file

@ -0,0 +1,99 @@
#include "radixsort.h"
uint64_t * radixSort(uint64_t * array, uint32_t size) {
rscounts_t counts;
memset(&counts, 0, 256 * 8 * sizeof(uint32_t));
uint64_t * cpy = (uint64_t *)malloc(size * sizeof(uint64_t));
uint32_t o8=0, o7=0, o6=0, o5=0, o4=0, o3=0, o2=0, o1=0;
uint32_t t8, t7, t6, t5, t4, t3, t2, t1;
uint32_t x;
// calculate counts
for(x = 0; x < size; ++x) {
t8 = array[x] & 0xff;
t7 = (array[x] >> 8) & 0xff;
t6 = (array[x] >> 16) & 0xff;
t5 = (array[x] >> 24) & 0xff;
t4 = (array[x] >> 32) & 0xff;
t3 = (array[x] >> 40) & 0xff;
t2 = (array[x] >> 48) & 0xff;
t1 = (array[x] >> 56) & 0xff;
counts.c8[t8]++;
counts.c7[t7]++;
counts.c6[t6]++;
counts.c5[t5]++;
counts.c4[t4]++;
counts.c3[t3]++;
counts.c2[t2]++;
counts.c1[t1]++;
}
// convert counts to offsets
for(x = 0; x < 256; ++x) {
t8 = o8 + counts.c8[x];
t7 = o7 + counts.c7[x];
t6 = o6 + counts.c6[x];
t5 = o5 + counts.c5[x];
t4 = o4 + counts.c4[x];
t3 = o3 + counts.c3[x];
t2 = o2 + counts.c2[x];
t1 = o1 + counts.c1[x];
counts.c8[x] = o8;
counts.c7[x] = o7;
counts.c6[x] = o6;
counts.c5[x] = o5;
counts.c4[x] = o4;
counts.c3[x] = o3;
counts.c2[x] = o2;
counts.c1[x] = o1;
o8 = t8;
o7 = t7;
o6 = t6;
o5 = t5;
o4 = t4;
o3 = t3;
o2 = t2;
o1 = t1;
}
// radix
for(x = 0; x < size; ++x) {
t8 = array[x] & 0xff;
cpy[counts.c8[t8]] = array[x];
counts.c8[t8]++;
}
for(x = 0; x < size; ++x) {
t7 = (cpy[x] >> 8) & 0xff;
array[counts.c7[t7]] = cpy[x];
counts.c7[t7]++;
}
for(x = 0; x < size; ++x) {
t6 = (array[x] >> 16) & 0xff;
cpy[counts.c6[t6]] = array[x];
counts.c6[t6]++;
}
for(x = 0; x < size; ++x) {
t5 = (cpy[x] >> 24) & 0xff;
array[counts.c5[t5]] = cpy[x];
counts.c5[t5]++;
}
for(x = 0; x < size; ++x) {
t4 = (array[x] >> 32) & 0xff;
cpy[counts.c4[t4]] = array[x];
counts.c4[t4]++;
}
for(x = 0; x < size; ++x) {
t3 = (cpy[x] >> 40) & 0xff;
array[counts.c3[t3]] = cpy[x];
counts.c3[t3]++;
}
for(x = 0; x < size; ++x) {
t2 = (array[x] >> 48) & 0xff;
cpy[counts.c2[t2]] = array[x];
counts.c2[t2]++;
}
for(x = 0; x < size; ++x) {
t1 = (cpy[x] >> 56) & 0xff;
array[counts.c1[t1]] = cpy[x];
counts.c1[t1]++;
}
free(cpy);
return array;
}

23
common/radixsort.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef RADIXSORT_H__
#define RADIXSORT_H__
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
typedef union {
struct {
uint32_t c8[256];
uint32_t c7[256];
uint32_t c6[256];
uint32_t c5[256];
uint32_t c4[256];
uint32_t c3[256];
uint32_t c2[256];
uint32_t c1[256];
};
uint32_t counts[256 * 8];
} rscounts_t;
uint64_t * radixSort(uint64_t * array, uint32_t size);
#endif // RADIXSORT_H__