Better Trailer Decoder

Fix the decoding of isKeyBReadable
Show every Access Bits
Show isKeyBReadable
Add comment for the decoding process
Better UI
Remove unnecessary debug output
This commit is contained in:
wh201906 2023-02-13 09:27:38 +08:00
parent c2d3248b68
commit a7e112f124
No known key found for this signature in database
4 changed files with 168 additions and 31 deletions

View File

@ -40,36 +40,39 @@ const Mifare::CardType Mifare::card_4k =
const Mifare::AccessType Mifare::dataCondition[8][4] =
{
{ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB},
{ACC_KEY_AB, ACC_KEY_B, ACC_NEVER, ACC_NEVER},
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_AB, ACC_KEY_B, ACC_KEY_B, ACC_KEY_AB},
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_KEY_AB},
{ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER},
{ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER},
// {read, write, increment, decrement/transfer/restore}
{ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB}, // {C3x, C2x, C1x} = 0
{ACC_KEY_AB, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 1
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 2
{ACC_KEY_AB, ACC_KEY_B, ACC_KEY_B, ACC_KEY_AB}, // {C3x, C2x, C1x} = 3
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_KEY_AB}, // {C3x, C2x, C1x} = 4
{ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 5
{ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 6
{ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 7
};
const Mifare::AccessType Mifare::trailerReadCondition[8][3] =
{
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
// {KEYA, Access bits, KEYB}
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 0
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 1
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 2
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 3
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 4
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 5
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 6
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 7
};
const Mifare::AccessType Mifare::trailerWriteCondition[8][3] =
{
{ACC_KEY_A, ACC_NEVER, ACC_KEY_A},
{ACC_KEY_B, ACC_NEVER, ACC_KEY_B},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_A, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_B, ACC_NEVER},
{ACC_KEY_B, ACC_KEY_B, ACC_KEY_B},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
// {KEYA, Access bits, KEYB}
{ACC_KEY_A, ACC_NEVER, ACC_KEY_A}, // {C33, C23, C13} = 0
{ACC_KEY_B, ACC_NEVER, ACC_KEY_B}, // {C33, C23, C13} = 1
{ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 2
{ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 3
{ACC_KEY_A, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 4
{ACC_NEVER, ACC_KEY_B, ACC_NEVER}, // {C33, C23, C13} = 5
{ACC_KEY_B, ACC_KEY_B, ACC_KEY_B}, // {C33, C23, C13} = 6
{ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 7
};
Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
@ -1312,9 +1315,13 @@ bool Mifare::data_isACBitsValid(const QString& text, QList<quint8>* returnHalfBy
QList<quint8> halfBytes;
for(int i = 0; i < 6; i++)
{
// 6 7 8
// AB CD EF->
// {0xA, 0xB, 0xC, 0xD, 0xE, 0xF}
// {~C2x, ~C1x, C1x, ~C3x, C3, C2}
halfBytes.append((val >> ((5 - i) * 4)) & 0xf);
}
qDebug() << val;
// qDebug() << val;
if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4])
{
if(returnHalfBytes != nullptr)
@ -1330,9 +1337,12 @@ QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList i
QList<quint8> halfBytes, result;
if(data_isACBitsValid(text, &halfBytes))
{
// data in halfbits:
// {~C2x, ~C1x, C1x, ~C3x, C3, C2}
for(int i = 0; i < 4; i++)
{
result.append((((halfBytes[4] >> i) & 1) << 2) | (((halfBytes[5] >> i) & 1) << 1) | (((halfBytes[2] >> i) & 1) << 0));
// {Cx0, Cx1, Cx2, Cx3} (Cx0={C30, C20, C10})
}
}
return result;

View File

@ -22,8 +22,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
ui->dataBlockWidget->setRowCount(3);
ui->dataBlockWidget->setColumnCount(4);
ui->dataBlockWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->trailerBlockWidget->setRowCount(2);
ui->trailerBlockWidget->setColumnCount(3);
ui->trailerBlockWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
}
MF_trailerDecoderDialog::~MF_trailerDecoderDialog()
@ -39,23 +41,26 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1)
QList<quint8> ACBits = Mifare::data_getACBits(arg1);
if(ACBits.size() == 0)
{
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)");
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 20, 20)");
ui->isAccessBitsValidLabel->setText(tr("Invalid!\nIt could make the whole sector blocked irreversibly!"));
}
else
{
// if keyB may be read by keyA, it cannot serve for authentication.
// {C33, C23, C13}=3'b000, 3'b010 or 3'b100
bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 2 || ACBits[3] == 4;
ui->C0Box->setValue(ACBits[0]);
ui->C1Box->setValue(ACBits[1]);
ui->C2Box->setValue(ACBits[2]);
ui->C3Box->setValue(ACBits[3]);
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(0, 200, 0)");
ui->isAccessBitsValidLabel->setText(tr("Valid"));
bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 1 || ACBits[3] == 4;
showCBits();
for(int j = 0; j < 3; j++)
{
setTableItem(ui->trailerBlockWidget, 0, j, Mifare::trailerReadCondition[ACBits[3]][j]);
setTableItem(ui->trailerBlockWidget, 1, j, Mifare::trailerWriteCondition[ACBits[3]][j]);
}
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 4; j++)
@ -72,6 +77,18 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1)
setTableItem(ui->dataBlockWidget, i, j, type);
}
}
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(20, 200, 20)");
if(isKeyBReadable)
{
ui->isAccessBitsValidLabel->setText(tr("Valid") + "\n" + tr("KeyB cannot serve for authentication"));
ui->trailerBlockWidget->item(0, 2)->setBackground(QBrush(Qt::lightGray));
}
else
{
ui->isAccessBitsValidLabel->setText(tr("Valid"));
ui->trailerBlockWidget->item(0, 2)->setBackground(QBrush(QColor(1, 0, 0, 0), Qt::NoBrush)); // default Background
}
}
ui->C0Box->blockSignals(false);
ui->C1Box->blockSignals(false);
@ -150,5 +167,27 @@ void MF_trailerDecoderDialog::on_boxChanged()
}
result = result.toUpper();
ui->accessBitsEdit->setText(result);
showCBits();
}
void MF_trailerDecoderDialog::showCBits()
{
const QSpinBox* CxBox[4] =
{
ui->C0Box,
ui->C1Box,
ui->C2Box,
ui->C3Box
};
for(int i = 0; i < 4; i++)
{
quint8 val = CxBox[i]->value();
for(int j = 0; j < 3; j++)
{
if((val >> j) & 0x1)
ui->CBitsGridLayout->itemAtPosition(j, i)->widget()->setStyleSheet("background-color:rgb(20, 200, 20)");
else
ui->CBitsGridLayout->itemAtPosition(j, i)->widget()->setStyleSheet("");
}
}
}

View File

@ -33,7 +33,7 @@ private:
QRegularExpressionValidator* validator;
QButtonGroup* sizeGroup;
void setTableItem(QTableWidget *widget, int row, int column, Mifare::AccessType accessType);
void showCBits();
};
#endif // MF_TRAILERDECODERDIALOG_H

View File

@ -209,6 +209,94 @@
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="CBitsGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="C10Label">
<property name="text">
<string>C10</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="C11Label">
<property name="text">
<string>C11</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="C12Label">
<property name="text">
<string>C12</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="C13Label">
<property name="text">
<string>C13</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="C20Label">
<property name="text">
<string>C20</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="C21Label">
<property name="text">
<string>C21</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="C22Label">
<property name="text">
<string>C22</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="C23Label">
<property name="text">
<string>C23</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="C30Label">
<property name="text">
<string>C30</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="C31Label">
<property name="text">
<string>C31</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="C32Label">
<property name="text">
<string>C32</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="C33Label">
<property name="text">
<string>C33</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">