mirror of
https://github.com/holub/mame
synced 2025-05-05 13:54:42 +03:00
Added code to manage NAOMI's M4 decryption. [Andreas Naive]
This commit is contained in:
parent
fe71f91143
commit
697eff192e
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -3859,6 +3859,8 @@ src/mame/machine/namcos1.c svneol=native#text/plain
|
||||
src/mame/machine/namcos2.c svneol=native#text/plain
|
||||
src/mame/machine/naomi.c svneol=native#text/plain
|
||||
src/mame/machine/naomibd.c svneol=native#text/plain
|
||||
src/mame/machine/naomim4decoder.c svneol=native#text/plain
|
||||
src/mame/machine/naomim4decoder.h svneol=native#text/plain
|
||||
src/mame/machine/nb1413m3.c svneol=native#text/plain
|
||||
src/mame/machine/nb1414m4.c svneol=native#text/plain
|
||||
src/mame/machine/neoboot.c svneol=native#text/plain
|
||||
|
73
src/mame/machine/naomim4decoder.c
Executable file
73
src/mame/machine/naomim4decoder.c
Executable file
@ -0,0 +1,73 @@
|
||||
#include "naomim4decoder.h"
|
||||
|
||||
const UINT8 NaomiM4Decoder::k_sboxes[4][16] = {
|
||||
{13,14,1,11,7,9,10,0,15,6,4,5,8,2,12,3},
|
||||
{12,3,14,6,7,15,2,13,1,4,11,0,9,10,8,5},
|
||||
{6,12,0,10,1,5,14,9,7,2,15,13,4,11,3,8},
|
||||
{9,12,8,7,10,4,0,15,1,11,14,2,13,5,6,3}
|
||||
};
|
||||
|
||||
NaomiM4Decoder::NaomiM4Decoder(UINT32 cart_key)
|
||||
: m_key(cart_key & 0xffff)
|
||||
, m_iv(cart_key >> 16) // initialization vector
|
||||
{
|
||||
m_one_round = global_alloc_array(UINT16,0x10000);
|
||||
|
||||
// populate the lookup table for one of the internal rounds of the cipher
|
||||
for (UINT32 i=0; i<0x10000; ++i)
|
||||
{
|
||||
m_one_round[i] = one_round_core(i);
|
||||
}
|
||||
}
|
||||
|
||||
NaomiM4Decoder::~NaomiM4Decoder()
|
||||
{
|
||||
global_free(m_one_round);
|
||||
}
|
||||
|
||||
void NaomiM4Decoder::init()
|
||||
{
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
UINT16 NaomiM4Decoder::decrypt(UINT16 ciphertext) // decrypt the next 16-bits value in the stream
|
||||
{
|
||||
if (0 == (m_counter++ & 0xf)) // the iv is recovered every 16 values (32 bytes)
|
||||
m_middle_value = m_iv;
|
||||
|
||||
UINT16 output_whitening = m_key ^ m_middle_value;
|
||||
|
||||
m_middle_value = m_one_round[ciphertext ^ m_middle_value];
|
||||
|
||||
return m_one_round[m_middle_value ^ m_key] ^ output_whitening;
|
||||
}
|
||||
|
||||
UINT16 NaomiM4Decoder::one_round_core(UINT16 round_input)
|
||||
{
|
||||
UINT8 input_nibble[4];
|
||||
UINT8 output_nibble[4];
|
||||
UINT8 aux_nibble;
|
||||
UINT8 nibble_idx;
|
||||
UINT8 i;
|
||||
UINT16 result;
|
||||
|
||||
for (nibble_idx = 0; nibble_idx < 4; ++nibble_idx, round_input >>= 4)
|
||||
{
|
||||
input_nibble[nibble_idx] = round_input & 0xf;
|
||||
output_nibble[nibble_idx] = 0;
|
||||
}
|
||||
|
||||
aux_nibble = input_nibble[3];
|
||||
for (nibble_idx = 0; nibble_idx < 4; ++nibble_idx) // 4 s-boxes per round
|
||||
{
|
||||
aux_nibble ^= k_sboxes[nibble_idx][input_nibble[nibble_idx]];
|
||||
for (i = 0; i < 4; ++i) // diffusion of the bits
|
||||
output_nibble[(nibble_idx - i) & 3] |= aux_nibble & (1 << i);
|
||||
}
|
||||
|
||||
for (nibble_idx = 0, result = 0; nibble_idx < 4; ++nibble_idx)
|
||||
result |= (output_nibble[nibble_idx] << (4 * nibble_idx));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
46
src/mame/machine/naomim4decoder.h
Executable file
46
src/mame/machine/naomim4decoder.h
Executable file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __NAOMIM4DECODER_H__
|
||||
#define __NAOMIM4DECODER_H__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
// Decoder for M4-type NAOMI cart encryption
|
||||
|
||||
// In hardware, the decryption is managed by the XC3S50 Xilinx Spartan FPGA (IC2)
|
||||
// and the annexed PIC16C621A PIC MCU (IC3).
|
||||
// - The FPGA control the clock line of the security PIC.
|
||||
// - The protocol between the FPGA and the MCU is nibble-based, though it hasn't been RE for now.
|
||||
// - The decryption algorithm is clearly nibble-based too.
|
||||
|
||||
// The decryption algorithm itself implements a stream cipher built on top of a 16-bits block cipher.
|
||||
// The underlying block-cipher is a SP-network of 2 rounds (both identical in structure). In every
|
||||
// round, the substitution phase is done using 4 fixed 4-to-4 sboxes acting on every nibble. The permutation
|
||||
// phase is indeed a nibble-based linear combination.
|
||||
// With that block cipher, a stream cipher is constructed by feeding the output result of the 1st round
|
||||
// of a certain 16-bits block as a whitening value for the next block. The cart dependent data used by
|
||||
// the algorithm is comprised by a 16-bits "key" and a 16-bits IV (initialization vector) --though they
|
||||
// will be merged in a only 32-bits number in the code--. The hardware auto-reset the feed value
|
||||
// to the cart-based IV every 16 blocks (32 bytes); that reset is not address-based, but index-based.
|
||||
|
||||
class NaomiM4Decoder
|
||||
{
|
||||
public:
|
||||
NaomiM4Decoder(UINT32 cart_key);
|
||||
~NaomiM4Decoder();
|
||||
|
||||
void init(); // initialize the decryption of a new stream (set the IV)
|
||||
UINT16 decrypt(UINT16 ciphertext); // decrypt the next 16-bits value in the stream
|
||||
|
||||
private:
|
||||
UINT16 one_round_core(UINT16 round_input);
|
||||
|
||||
static const UINT8 k_sboxes[4][16];
|
||||
UINT16 *m_one_round;
|
||||
const UINT16 m_key;
|
||||
const UINT16 m_iv;
|
||||
UINT16 m_middle_value; // used by the stream cipher as feeding to the next block
|
||||
UINT8 m_counter;
|
||||
};
|
||||
|
||||
#endif // __NAOMIM4DECODER_H__
|
@ -1176,7 +1176,7 @@ $(MAMEOBJ)/sega.a: \
|
||||
$(DRIVERS)/model1.o $(MACHINE)/model1.o $(VIDEO)/model1.o \
|
||||
$(DRIVERS)/model2.o $(VIDEO)/model2.o \
|
||||
$(DRIVERS)/model3.o $(VIDEO)/model3.o $(MACHINE)/model3.o \
|
||||
$(DRIVERS)/naomi.o $(MACHINE)/dc.o $(VIDEO)/dc.o $(MACHINE)/gdcrypt.o $(MACHINE)/naomibd.o $(MACHINE)/naomi.o \
|
||||
$(DRIVERS)/naomi.o $(MACHINE)/dc.o $(VIDEO)/dc.o $(MACHINE)/gdcrypt.o $(MACHINE)/naomibd.o $(MACHINE)/naomi.o $(MACHINE)/naomim4decoder.o\
|
||||
$(MACHINE)/mie.o $(MACHINE)/maple-dc.o $(MACHINE)/mapledev.o $(MACHINE)/dc-ctrl.o \
|
||||
$(MACHINE)/jvs13551.o \
|
||||
$(DRIVERS)/triforce.o \
|
||||
|
Loading…
Reference in New Issue
Block a user