Fotis Loukos
Network device
PCI card
Gemalto
Thales
Utimaco
All Certification Authorities (CAs) are required to use HSMs. From the CA/B Forum Baseline requirements:
The CA SHALL protect its Private Key in a system or device that has been validated as meeting at least FIPS 140 level 3 or an appropriate Common Criteria Protection Profile or Security Target, EAL 4 (or higher), which includes requirements to protect the Private Key and other assets against known threats.
Root Zone operators store keys inside HSMs. From the DNSSEC Practice Statement for the Root Zone KSK Operator:
For RZ KSK generation and RZ KSK private component operations and storage, ICANN uses hardware security modules that are validated at FIPS 140-2 level 4 overall.
PCI DSS in some cases requires HSMs to secure cardholder data throughout the transaction process.
The PCI HSM Security Requirements document describes the minimum security requirements for compliant HSMs.
Implement serious crypto
without an HSM
Major standards:
Defines 4 different security levels:
Defines 4 different security levels:
FIPS 140-2 validation happens at the Cryptographic Module Testing Laboratories which are accredited by the National Voluntary Laboratory Accreditation Program as part of the Cryptographic Module Validation Program.
Currently 22 laboratories have been accredited to perform FIPS 140-2 validation.
Interesting fact:
Every PCIe HSM contains:
Every user has:
adm_3.0.18.1_c50.mtc aes_1.3.7.0_c50.mtc asn1_1.0.3.4_c50.mtc bcm_1.0.2.0_c50.mtc cmds_3.5.1.6_c50.mtc cxi_2.1.11.3_c50.mtc db_1.3.1.1_c50.mtc dsa_1.2.2.1_c50.mtc eca_1.1.7.6_c50.mtc ecdsa_1.1.8.7_c50.mtc hash_1.0.10.1_c50.mtc
hce_2.2.2.1_c50.mtc lna_1.2.3.4_c50.mtc mbk_2.2.4.4_c50.mtc ntp_1.2.0.7_c50.mtc pp_1.2.5.1_c50.mtc sc_1.2.0.3_c50.mtc smos_3.3.4.2_c86.mtc util_3.0.3.0_c50.mtc vdes_1.0.9.1_c50.mtc vrsa_1.3.0.6_c50.mtc
Each one of them seems to be associated with a specific function:
Let's use binwalk!
$ binwalk adm_3.0.18.1_c50.mtc DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 53925 0xD2A5 Copyright string: "Copyright (c) 1996-2014 Texas Instruments Incorporated" 54123 0xD36B Copyright string: "Copyright (c) 1996-2014 Texas Instruments Incorporated" 55658 0xD96A Unix path: /tmp/TI_MKLIBqpFZmO/OBJ/memset.asm:$C$L2:1:1398463752 55816 0xDA08 Copyright string: "Copyright (c) 1996-2014 Texas Instruments Incorporated" 55985 0xDAB1 Copyright string: "Copyright (c) 1996-2014 Texas Instruments Incorporated"
Four copyright strings inside and one unix path → WTF guys, use a standard format!
Hexdump to the rescue!
$ hexdump -C adm_3.0.18.1_c50.mtc 00000000 4d 54 43 48 00 01 2d e0 01 00 00 00 01 02 01 00 |MTCH..-.........| 00000010 00 00 00 18 00 00 00 00 4d 4d 43 48 00 01 2d c8 |........MMCH..-.| 00000020 01 01 00 00 a3 07 55 2e d3 44 d5 ba 41 44 4d 00 |......U..D..ADM.| 00000030 00 00 00 00 00 00 00 00 00 00 00 87 03 00 12 01 |................| 00000040 41 64 6d 69 6e 69 73 74 72 61 74 69 6f 6e 20 4d |Administration M| 00000050 6f 64 75 6c 65 00 00 00 00 00 00 00 00 00 00 00 |odule...........| .... 00000110 00 00 2e 74 65 78 74 00 00 00 80 0f 00 00 80 0f |...text.........| 00000120 00 00 e0 bf 00 00 8e 11 00 00 5e e2 00 00 00 00 |..........^.....| 00000130 00 00 b6 03 00 00 00 00 00 00 20 05 00 00 00 00 |.......... .....| 00000140 00 00 2e 64 61 74 61 00 00 00 60 cf 00 00 60 cf |...data...`...`.| 00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000160 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 |................|
Challenge accepted!
Let's reverse the administration tool that extracted the files!
Fast forward many hours...
$ strings csadm | grep COFF CS2-COFF COFF section
Now what???
We can now extract the COFF file!
Now what?
(Insert multiple slides with Picard facepalms and radare2, binutils, etc)
(Ok, actually TI has a disassembler but it's unusable)
Challenge accepted!
Let's write our own disassembler!
Steps to write our own disassembler:
Each data path contains:
There is also one cross path for transfers between data path A and B
Control Register File: Control registers such as:
Sample instructions:
SHR .S1 A1, 10, A2 MV .S1X B0, A0 AND .D1 A0, A1, A2 || AND .D2 B0, B1, B2 [ A0] ADD .L1 A1, A2, A3 || [!A0] ADD .L2 B1, B2, B3
Still wondering why no tools are available???
On-chip memory:
Off-chip memory:
B .S1 func AND .D1 A0, A1, A2 || AND .D2 B0, B1, B2 ADDKPC .S2 returnhere, B3 ADD .D1 A2, 1, A3 MV .D2 B3, B0 || MV .D1 A3, A0 OR .S2X B0, A0, B4 returnhere: MVK .S1 10, A0 ... func: ... B .S1 B3
We know the architecture, the memory layout and the ABI. Now what???
A TableGen (.td) file with the architecture and instructions description helps generate:
But there's more needed!
Let's first generate this and we'll see about the rest...
A file defining:
In our case we don't need:
What we will need is:
Instruction description with:
Simple, we define a register class and then instances for all registers!
class TMS320C64xReg<string n, bits<5> num, bit file, bits<3> condition = 7> : Register<n> { let HWEncoding{15-5} = 0; let HWEncoding{4-0} = num; field bit File = file; field bits<3> Condition = condition; let Namespace = "TMS320C64x"; } def A0 : TMS320C64xReg<"A0", 0, 0, 6>, DwarfRegNum<[0]>; ... def B31 : TMS320C64xReg<"B31", 31, 1>, DwarfRegNum<[63]>;
def memop : Operand<i32>, PatLeaf<(imm), [{ return isInt<15>(N->getZExtValue()); }]> { let DecoderMethod = "DecodeMemOperand"; let EncoderMethod = "EncodeMemOperand"; let PrintMethod = "printMemOperand"; }
For every operand we need to create a decoder, an encoder and maybe a print method!
// Superclass class TMS320C64xInst<dag outops, dag inops, string asmstr, list<dag> pattern> : Instruction { field bits<32> Inst; field bits<32> SoftFail = 0; bits<3> cond; bit condzero; bit side; bit parallel; let OutOperandList = outops; let InOperandList = !con(inops, (ins condreg:$cond, condregzero:$condzero, sideop:$side, parallelop:$parallel)); let AsmString = asmstr; let Pattern = pattern;
let Inst{31-29} = cond; let Inst{28} = condzero; let Inst{1} = side; let Inst{0} = parallel; let Size = 4; let isPredicable = 1; let hasSideEffects = 0; let Namespace = "TMS320C64x"; }
class TMS320C64xInstD1<bits<6> opVal, dag outops, dag inops, string asmstr, list<dag> pattern> : TMS320C64xInst<outops, inops, asmstr, pattern> { bits<5> dst; bits<5> src2; bits<5> src1; bits<6> op = opVal; let Inst{27-23} = dst; let Inst{22-18} = src2; let Inst{17-13} = src1; let Inst{12-7} = op; let Inst{6-2} = 0b10000; }
class TMS320C64xInstD2<bits<4> opVal, dag outops, dag inops, string asmstr, list<dag> pattern> : TMS320C64xInst<outops, !con(inops, (ins crosspathopx2:$crosspath)), asmstr, pattern> { bits<5> dst; bits<5> src2; bits<5> src1; bit crosspath; bits<4> op = opVal; let Inst{27-23} = dst; let Inst{22-18} = src2; let Inst{17-13} = src1; let Inst{12} = crosspath; let Inst{9-6} = op; let Inst{11-10} = 0b10; let Inst{5-2} = 0b1100; }
multiclass TMS320C64xInstD1_ri<bits<6> opVal1, bits<6> opVal2, string asmstr1, string asmstr2> { def _d1_rrr : TMS320C64xInstD1<opVal1, ( outs GPRegs:$dst ), ( ins GPRegs:$src2, GPRegs:$src1 ), asmstr1, []>; def _d1_rir : TMS320C64xInstD1<opVal2, ( outs GPRegs:$dst ), ( ins GPRegs:$src2, ucst5:$src1 ), asmstr2, []>; }
defm ADD : TMS320C64xInstD1_ri<0b010000, 0b010010, "ADD\t$src2, $src1, $dst", "ADD\t$src2, $src1, $dst">; def ADD_d2_rrr : TMS320C64xInstD2<0b1010, ( outs GPRegs:$dst ), ( ins GPRegs:$src2, GPRegs:$src1 ), "ADD\t$src1, $src2, $dst", []>;
The converter was not the LLVM one but a not-disclosed version that produces C code instead of C++
Decoding of all fields must be done manually
Instructions that use PC relative addressing must be handled specially
Branches must be handled with care since they are relative to the first instruction in the fetch packet
The parallel bit is not set at the same instruction but at the previous one
We have a disassembler we can use!
How do we proceed?
Let's check the simulator firmware!
We've got symbols!
The following slide used to have the title 'Extraction of MBK' which is incorrect. The correct title is 'Extraction of MBK database backup'. Within the body of the slides it mentions directly the database VMBK1.db, which is the MBK database. Of course, according to the manuals this database cannot be extracted. This is the reason there is a faulty check over there.
Additionally, in no case is it implied that with this bug you can extract any private keys or CSPs.
This note was added after receiving a mail by Utimaco.
000009d8 00564d42 .word 0x00564d42 // '\x00VMB' 000009dc 4b310073 .word 0x4b310073 // 'K1\x00s' _adm_ext_list_db_search_keys: ... || MVK.S1 0x09d9,A5 || ADD.L1X A4,B4,A3 || ADD.D2 B15,0x17,B4 MVKH.S1 0x0000,A5 SUB.L1 A5,0x1,A4 LDB.D1T1 *++A4[1],A0 LDBU.D2T2 *++B4[1],B5 MVK.L1 0,A1 NOP 2 EXTU.S1 A0,24,24,A5 || [ A0] SUB.L1 A3,0x1,A1 [ A0] SUB.L1 A3,0x1,A3 CMPEQ.L2X B5,A5,B0 [!B0] MVK.L1 0,A1 || [!B0] B.S2 0x003010 ...
What's the argument to this function?
What if we extract FLASH\VMBK1.db?
Sometimes one facepalm is not enough...