mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-09 15:27:22 -05:00
RAS MD5 Tweaks; #359
Disable Fist Byte Correction on MD5 password hash following observations based on real world system; Improve BPTC127x77 Decoder Logic; Tweak Debug code to show checksum diff if there is no actual diff;
This commit is contained in:
253
src/bptc.c
253
src/bptc.c
@@ -362,21 +362,15 @@ uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DM
|
||||
|
||||
|
||||
/*
|
||||
* @brief : This function extract the 77 bits of a deinteleaved 128 bits
|
||||
* buffer using BPTC (128,77).
|
||||
* BPTC (128,77) extract with iterative Hamming + parity-guided repair
|
||||
* and diagnostic logging.
|
||||
* See ETSI TS 102 361-1 B.2.1
|
||||
*
|
||||
* @note : See DMR standard ETSI TS 102 361-1 chapter B.2.1 for details
|
||||
*
|
||||
* @param InputDeInteleavedData : Pointer of DMR input data deinterleaved (128 bytes
|
||||
act as a 16 x 8 byte data matrix)
|
||||
*
|
||||
* @param DMRDataExtracted : Pointer where the DMR data will be written (77 bytes)
|
||||
* DMRDataExtracted[0..71] = Util data (hamming corrected)
|
||||
* DMRDataExtracted[72..76] = 5 bit of CRC extracted (to be checked)
|
||||
*
|
||||
* @return 0 = All is OK
|
||||
* Other = Error - Irrecoverable Hamming parity check error number
|
||||
* Enable/disable chatter with BPTC_128x77_DEBUG (1 = on).
|
||||
*/
|
||||
|
||||
// #define BPTC_128x77_DEBUG 1
|
||||
|
||||
uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDataExtracted[77])
|
||||
{
|
||||
uint32_t i, j, k;
|
||||
@@ -387,106 +381,189 @@ uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDat
|
||||
uint32_t ParityCheckErrorNb = 0;
|
||||
uint32_t NbOfOne;
|
||||
|
||||
/* First step : Reconstitute the BPTC 16x8 matrix */
|
||||
for(i = 0; i < 8; i++)
|
||||
uint8_t row_bad[7];
|
||||
uint8_t col_bad[16];
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
for(j = 0; j < 16; j++)
|
||||
{
|
||||
/* Only the LSBit of the byte is stored */
|
||||
for (j = 0; j < 16; j++)
|
||||
DataMatrix[i][j] = (InputDataMatrix[i][j] & 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the the Hamming (16,11,4) code
|
||||
* check on each line.
|
||||
* Do not check the last line (line nb 8) */
|
||||
for(i = 0; i < 7; i++)
|
||||
/* ---------- Pass 1: Hamming (16,11,4) on rows 0..6 ---------- */
|
||||
memset(row_bad, 0, sizeof(row_bad));
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
/* Get a full line */
|
||||
for(j = 0; j < 16; j++)
|
||||
{
|
||||
for (j = 0; j < 16; j++)
|
||||
LineUncorrected[j] = DataMatrix[i][j];
|
||||
}
|
||||
|
||||
/* Apply Hamming (16,11,4) code correction */
|
||||
if(Hamming_16_11_4_decode(LineUncorrected, LineCorrected, 1) == false)
|
||||
if (Hamming_16_11_4_decode(LineUncorrected, LineCorrected, 1) == false)
|
||||
{
|
||||
HammingIrrecoverableErrorNb++;
|
||||
row_bad[i] = 1;
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr, " BPTC128 P1 Hamming FAIL row=%u rx=", (unsigned)i);
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%u", LineUncorrected[j] & 1);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
for (j = 0; j < 11; j++)
|
||||
DataMatrix[i][j] = LineUncorrected[j];
|
||||
}
|
||||
|
||||
/* Re-inject the line in the matrix (only the util data [11 bit],
|
||||
* not the Hamming part [4 bit]) */
|
||||
for(j = 0; j < 11; j++)
|
||||
else
|
||||
{
|
||||
DataMatrix[i][j] = LineCorrected[j];
|
||||
for (j = 0; j < 11; j++)
|
||||
DataMatrix[i][j] = LineCorrected[j];
|
||||
}
|
||||
}
|
||||
#if BPTC_128x77_DEBUG
|
||||
if (HammingIrrecoverableErrorNb)
|
||||
fprintf(stderr, " BPTC128 P1 Hamming irrecoverable rows=%u\n",
|
||||
(unsigned)HammingIrrecoverableErrorNb);
|
||||
#endif
|
||||
|
||||
/* Extract the DMR data (77 bit) from the matrix */
|
||||
k = 0;
|
||||
|
||||
/* 2 first lines */
|
||||
for(i = 0; i < 2; i++)
|
||||
{
|
||||
for(j = 0; j < 11; j++)
|
||||
{
|
||||
DMRDataExtracted[k] = DataMatrix[i][j];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 5 Next lines */
|
||||
for(i = 2; i < 7; i++)
|
||||
{
|
||||
for(j = 0; j < 10; j++)
|
||||
{
|
||||
DMRDataExtracted[k] = DataMatrix[i][j];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 5 bit of CRC */
|
||||
for(i = 2; i < 7; i++)
|
||||
{
|
||||
DMRDataExtracted[k] = DataMatrix[i][10];
|
||||
k++;
|
||||
}
|
||||
|
||||
/* Verify the data integrity by checking
|
||||
* all column parity bit */
|
||||
/* ---------- Column even-parity check (row 7) ---------- */
|
||||
memset(col_bad, 0, sizeof(col_bad));
|
||||
ParityCheckErrorNb = 0;
|
||||
for(i = 0; i < 16; i++)
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
NbOfOne = 0;
|
||||
|
||||
/* Get a full column */
|
||||
for(j = 0; j < 7; j++)
|
||||
{
|
||||
for (j = 0; j < 7; j++)
|
||||
NbOfOne += DataMatrix[j][i];
|
||||
}
|
||||
|
||||
/* Check the parity bit (number of "1"
|
||||
* must be even) */
|
||||
if((NbOfOne % 2) != DataMatrix[7][i])
|
||||
if ((NbOfOne % 2) != DataMatrix[7][i])
|
||||
{
|
||||
ParityCheckErrorNb++;
|
||||
col_bad[i] = 1;
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr,
|
||||
" BPTC128 P1 parity FAIL col=%u sum7=%u parity_bit=%u (expect even)\n",
|
||||
(unsigned)i, (unsigned)NbOfOne, (unsigned)DataMatrix[7][i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if BPTC_128x77_DEBUG
|
||||
if (ParityCheckErrorNb)
|
||||
fprintf(stderr, " BPTC128 P1 parity bad columns=%u\n",
|
||||
(unsigned)ParityCheckErrorNb);
|
||||
#endif
|
||||
|
||||
/* ---------- Parity-guided single-bit repair ---------- */
|
||||
{
|
||||
uint32_t n_bad_rows = 0, n_bad_cols = 0;
|
||||
uint32_t br = 0, bc = 0;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
if (row_bad[i]) { n_bad_rows++; br = i; }
|
||||
for (i = 0; i < 16; i++)
|
||||
if (col_bad[i]) { n_bad_cols++; bc = i; }
|
||||
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr,
|
||||
" BPTC128 repair candidates: bad_rows=%u bad_cols=%u",
|
||||
(unsigned)n_bad_rows, (unsigned)n_bad_cols);
|
||||
if (n_bad_rows == 1)
|
||||
fprintf(stderr, " row=%u", (unsigned)br);
|
||||
if (n_bad_cols == 1)
|
||||
fprintf(stderr, " col=%u", (unsigned)bc);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
if (n_bad_rows == 1 && n_bad_cols == 1 && bc < 11)
|
||||
{
|
||||
DataMatrix[br][bc] ^= 1;
|
||||
row_bad[br] = 0;
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr,
|
||||
" BPTC128 parity-guided FLIP at row=%u col=%u -> %u\n",
|
||||
(unsigned)br, (unsigned)bc, (unsigned)DataMatrix[br][bc]);
|
||||
#endif
|
||||
}
|
||||
#if BPTC_128x77_DEBUG
|
||||
else if (n_bad_rows || n_bad_cols)
|
||||
{
|
||||
fprintf(stderr,
|
||||
" BPTC128 no single-intersection flip "
|
||||
"(need exactly 1 bad row and 1 data col)\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------- Pass 2: Hamming (16,11,4) again ---------- */
|
||||
HammingIrrecoverableErrorNb = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
for (j = 0; j < 16; j++)
|
||||
LineUncorrected[j] = DataMatrix[i][j];
|
||||
|
||||
if (Hamming_16_11_4_decode(LineUncorrected, LineCorrected, 1) == false)
|
||||
{
|
||||
HammingIrrecoverableErrorNb++;
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr, " BPTC128 P2 Hamming FAIL row=%u rx=", (unsigned)i);
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%u", LineUncorrected[j] & 1);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
for (j = 0; j < 11; j++)
|
||||
DataMatrix[i][j] = LineUncorrected[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < 11; j++)
|
||||
DataMatrix[i][j] = LineCorrected[j];
|
||||
}
|
||||
}
|
||||
#if BPTC_128x77_DEBUG
|
||||
if (HammingIrrecoverableErrorNb)
|
||||
fprintf(stderr, " BPTC128 P2 Hamming irrecoverable rows=%u\n",
|
||||
(unsigned)HammingIrrecoverableErrorNb);
|
||||
#endif
|
||||
|
||||
/* ---------- Final column parity recount ---------- */
|
||||
ParityCheckErrorNb = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
NbOfOne = 0;
|
||||
for (j = 0; j < 7; j++)
|
||||
NbOfOne += DataMatrix[j][i];
|
||||
|
||||
if ((NbOfOne % 2) != DataMatrix[7][i])
|
||||
{
|
||||
ParityCheckErrorNb++;
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr,
|
||||
" BPTC128 P2 parity FAIL col=%u sum7=%u parity_bit=%u\n",
|
||||
(unsigned)i, (unsigned)NbOfOne, (unsigned)DataMatrix[7][i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of irrecoverable Hamming errors +
|
||||
* the number of parity check error */
|
||||
#if BPTC_128x77_DEBUG
|
||||
fprintf(stderr,
|
||||
" BPTC128 result: Hamming_err=%u parity_err=%u total=%u\n",
|
||||
(unsigned)HammingIrrecoverableErrorNb,
|
||||
(unsigned)ParityCheckErrorNb,
|
||||
(unsigned)(HammingIrrecoverableErrorNb + ParityCheckErrorNb));
|
||||
#endif
|
||||
|
||||
/* ---------- Extract 77 bits ---------- */
|
||||
k = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
for (j = 0; j < 11; j++)
|
||||
DMRDataExtracted[k++] = DataMatrix[i][j];
|
||||
}
|
||||
for (i = 2; i < 7; i++)
|
||||
{
|
||||
for (j = 0; j < 10; j++)
|
||||
DMRDataExtracted[k++] = DataMatrix[i][j];
|
||||
}
|
||||
for (i = 2; i < 7; i++)
|
||||
DMRDataExtracted[k++] = DataMatrix[i][10];
|
||||
|
||||
return (HammingIrrecoverableErrorNb + ParityCheckErrorNb);
|
||||
|
||||
//observation shows some parity check error is okay,
|
||||
//as long as the hamming is completely okay, may be worth it
|
||||
//to only check parity bits on columns
|
||||
|
||||
if (HammingIrrecoverableErrorNb == 0 && ParityCheckErrorNb < 2)
|
||||
return (HammingIrrecoverableErrorNb);
|
||||
else return (HammingIrrecoverableErrorNb + ParityCheckErrorNb);
|
||||
|
||||
} /* End BPTC_128x77_Extract_Data() */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief : This function extract the 32 bits of a deinteleaved 32 bits
|
||||
|
||||
@@ -432,19 +432,22 @@ void ras_effective_key_creation(dsd_state * state, char * input)
|
||||
ctx.digest[6] += 2;
|
||||
}
|
||||
|
||||
//SEED low5 non-zero value (no change to 5-bit EMB checksum mod 31)
|
||||
if ((ctx.digest[0] & 0x1F) == 0)
|
||||
{
|
||||
fprintf (stderr, " Byte %d: %02X -> %02X; ", 1, ctx.digest[0], ctx.digest[0]+2);
|
||||
ctx.digest[0] += 2;
|
||||
}
|
||||
//UPDATE: I have now observed a system that has a 5-bit differential value of 0
|
||||
//so that means that the low5 effective key value can be either 0, or 0x1F
|
||||
|
||||
//SEED low5 plus 1F (no change to 5-bit EMB checksum mod 31)
|
||||
else if ((ctx.digest[0] & 0x1F) == 0x1F)
|
||||
{
|
||||
fprintf (stderr, " Byte %d: %02X -> %02X; ", 1, ctx.digest[0], ctx.digest[0]+2);
|
||||
ctx.digest[0] += 2;
|
||||
}
|
||||
// //SEED low5 non-zero value (no change to 5-bit EMB checksum mod 31)
|
||||
// if ((ctx.digest[0] & 0x1F) == 0)
|
||||
// {
|
||||
// fprintf (stderr, " Byte %d: %02X -> %02X; ", 1, ctx.digest[0], ctx.digest[0]+2);
|
||||
// ctx.digest[0] += 2;
|
||||
// }
|
||||
|
||||
// //SEED low5 plus 1F (no change to 5-bit EMB checksum mod 31)
|
||||
// else if ((ctx.digest[0] & 0x1F) == 0x1F)
|
||||
// {
|
||||
// fprintf (stderr, " Byte %d: %02X -> %02X; ", 1, ctx.digest[0], ctx.digest[0]+2);
|
||||
// ctx.digest[0] += 2;
|
||||
// }
|
||||
|
||||
unsigned long long int effective_key = 0;
|
||||
for (int i = 0; i < 7; i++)
|
||||
|
||||
@@ -663,7 +663,7 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
|
||||
//calculation should be 5-bit portion of RAS Effective Key's Last byte & 0x1F
|
||||
//5-bit + CRCComputed % 31 = CRCExtracted
|
||||
#ifdef DEBUG_RAS
|
||||
if (opts->payload == 1 && is_emb && is_ras && CRCExtracted != CRCComputed && state->ras_effective_key == 0)
|
||||
if (opts->payload == 1 && is_emb && is_ras)
|
||||
{
|
||||
int32_t diff = ((int32_t)CRCExtracted - (int32_t)CRCComputed + 31) % 31;
|
||||
fprintf (stderr, " CRC CMP: %02X EXT: %02X DIFF: %02X", CRCComputed, CRCExtracted, diff);
|
||||
|
||||
Reference in New Issue
Block a user