Skip to content

Commit

Permalink
Add SS2-style iCE40 AES FPGA target.
Browse files Browse the repository at this point in the history
This allows iCE40 to be treated as a pseudo-CW305 target (see CW305 AES
notebook).
  • Loading branch information
jpcrypt committed Aug 15, 2023
1 parent d65a779 commit dbc3e49
Show file tree
Hide file tree
Showing 17 changed files with 390 additions and 44 deletions.
30 changes: 26 additions & 4 deletions hardware/victims/cw305_artixtarget/fpga/common/cw305_reg_aes.v
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,36 @@ module cw305_reg_aes #(
(* ASYNC_REG = "TRUE" *) reg [1:0] busy_pipe;


always @(posedge crypto_clk) begin
always @(posedge crypto_clk)
done_r <= I_done & pDONE_EDGE_SENSITIVE;
end
assign done_pulse = I_done & ~done_r;

always @(posedge crypto_clk) begin
if (done_pulse) begin
reg_crypt_cipherout <= I_cipherout;
reg_crypt_textout <= I_textout;
end
reg_crypt_key_crypt <= reg_crypt_key;
reg_crypt_textin_crypt <= reg_crypt_textin;
end

`ifdef ICE40
// iCE40 target has just one clock domain, so there's no CDC to worry
// about; it also can't afford to spare the extra registers:
always @(*) begin
reg_crypt_cipherout_usb = reg_crypt_cipherout;
reg_crypt_textout_usb = reg_crypt_textout;
reg_crypt_key_crypt = reg_crypt_key;
reg_crypt_textin_crypt = reg_crypt_textin;
end
`else
always @(posedge usb_clk) begin
reg_crypt_cipherout_usb <= reg_crypt_cipherout;
reg_crypt_textout_usb <= reg_crypt_textout;
end
always @(posedge crypto_clk) begin
reg_crypt_key_crypt <= reg_crypt_key;
reg_crypt_textin_crypt <= reg_crypt_textin;
end
`endif

assign O_textin = reg_crypt_textin_crypt;
assign O_key = reg_crypt_key_crypt;
Expand Down Expand Up @@ -180,6 +192,7 @@ module cw305_reg_aes #(
reg_crypt_go_pulse <= 1'b1;
else
reg_crypt_go_pulse <= 1'b0;

end
end

Expand All @@ -196,8 +209,12 @@ module cw305_reg_aes #(
.dst_pulse (reg_crypt_go_pulse_crypt)
);

`ifdef ICE40
always @(*) busy_usb = I_busy;
`else
always @(posedge usb_clk)
{busy_usb, busy_pipe} <= {busy_pipe, I_busy};
`endif


`ifdef ILA_REG
Expand Down Expand Up @@ -228,6 +245,10 @@ module cw305_reg_aes #(
);
`endif

`ifdef ICE40
// dynamically generated by build process:
`include "timestamp.v"
`else
`ifndef __ICARUS__
USR_ACCESSE2 U_buildtime (
.CFGCLK(),
Expand All @@ -237,6 +258,7 @@ module cw305_reg_aes #(
`else
assign buildtime = 0;
`endif
`endif


endmodule
Expand Down
6 changes: 6 additions & 0 deletions hardware/victims/cw305_artixtarget/fpga/common/cw305_top.v
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ module cw305_top #(
assign usb_data = isout? usb_dout : 8'bZ;


`ifdef ICE40
assign usb_clk_buf = usb_clk;
assign crypt_clk = usb_clk;
assign tio_clkout = usb_clk;
`else
clocks U_clocks (
.usb_clk (usb_clk),
.usb_clk_buf (usb_clk_buf),
Expand All @@ -194,6 +199,7 @@ module cw305_top #(
.O_cw_clkout (tio_clkout),
.O_cryptoclk (crypt_clk)
);
`endif



Expand Down
123 changes: 123 additions & 0 deletions hardware/victims/cw308_ufo_target/ice40up5k/hdl/iCE40UP5K_SS2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
`timescale 1 ns / 1 ps
`default_nettype none

/***********************************************************************
This file is part of the ChipWhisperer Project. See www.newae.com for more
details, or the codebase at http://www.chipwhisperer.com
Copyright (c) 2023, NewAE Technology Inc. All rights reserved.
Author: Jean-Pierre Thibault <[email protected]>
chipwhisperer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chipwhisperer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with chipwhisperer. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/

module iCE40UP5K_SS2 #(
parameter pBIT_RATE = 32 // number of clocks per UART bit; 230400 bps @ 7.37 MHz
)(
input wire clk,
input wire RxD,
output wire TxD,

output wire IO3, // routes to LED
output wire IO4,
output wire clock_alive // routes to LED
);

wire [7:0] dut_data;
wire [31:0] dut_address;
wire dut_rdn;
wire dut_wrn;
wire dut_cen;
wire ss2_error;
wire clk_buf;

assign IO3 = ss2_error | IO4; // double duty LED

//wire ss2_resetn = resetn & ~ss2_reset;
wire resetn = ~ss2_reset;

// fifo_sync.v requires a reset to work properly; unless we give up IO3 or clock_alive,
// there's no way to feed a reset on an input pin, so let's synthesize one upon startup:
// (one may think to reset via a register write, but since ss2 is what needs to get reset,
// this would be tricky... another option would be to hold RxD low for a "very long" time,
// and detecting this to trigger the reset)
reg ss2_reset = 1'b0;
reg ss2_reset_counter_stop = 1'b0;
localparam pRESET_COUNTER_WIDTH = 10;
reg [pRESET_COUNTER_WIDTH-1:0] ss2_reset_counter = 0;
always @ (posedge clk_buf) begin
if (ss2_reset)
ss2_reset <= 1'b0;
else if (ss2_reset_counter < {pRESET_COUNTER_WIDTH{1'b1}})
ss2_reset_counter <= ss2_reset_counter + 1;
else if (~ss2_reset_counter_stop) begin
ss2_reset_counter_stop <= 1'b1;
ss2_reset <= 1'b1;
end
end

ss2 #(
.pBIT_RATE (pBIT_RATE),
.pDATA_BITS (8),
.pSTOP_BITS (1),
.pPARITY_BITS (0),
.pPARITY_ENABLED (0)
) U_ss2 (
.clk (clk_buf ),
.resetn (resetn ),
.rxd (RxD ),
.txd (TxD ),

.dut_data (dut_data ),
.dut_address (dut_address ),
.dut_rdn (dut_rdn ),
.dut_wrn (dut_wrn ),
.dut_cen (dut_cen ),
.error (ss2_error )
);


cw305_top #(
.pBYTECNT_SIZE (8),
.pADDR_WIDTH (32)
) U_cw305_dut (
.usb_clk (clk),
.usb_clk_buf (clk_buf),
.usb_data (dut_data),
.usb_addr (dut_address),
.usb_rdn (dut_rdn ),
.usb_wrn (dut_wrn ),
.usb_cen (dut_cen ),
.usb_trigger (1'b0),

.j16_sel (1'b0),
.k16_sel (1'b0),
.k15_sel (1'b0),
.l14_sel (1'b0),
.pushbutton (resetn),

.led1 (),
.led2 (clock_alive),
.led3 (),

.pll_clk1 (clk_buf),
.tio_trigger (IO4),
//.tio_trigger (),
.tio_clkout (),
.tio_clkin (clk_buf)
);

endmodule
`default_nettype wire

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Implements the same AES engine as [ss\_aes\_icestorm](../ss\_aes\_icestorm),
but uses the SS2 wrapper described [here](../../xc7a35/README.md) in order
to provide CW305-style register reads and writes.

This makes the iCE40 target look and feel like a CW305 target! (minus all the
extras found on the CW305 board, like PLLs, etc...). So you can do things like
`target.fpga_write(address, data)` and `target.fpga_read(address, bytes)` for
arbitrary addresses and number of bytes, and it all gets automagically
carried over UART and translated into reads and writes, thanks to the [SS2
wrapper](https://github.com/newaetech/fpga-common/tree/main#notes-regarding-ss2-wrapper).

For example usage, including programming the target and communicating with
it, refer to the [CW305 AES
notebook](https://github.com/newaetech/chipwhisperer-jupyter/blob/master/demos/PA_HW_CW305_1-Attacking_AES_on_an_FPGA.ipynb).
The target is intended to be clocked at 7.37 MHz (via HS2); all of the setup
is provided in the notebook.

Note that the overhead of the SS2 wrapper is not insignificant on this very
small FPGA: the example AES target provided here uses 96% of the iCE40's
logic cells (compared to 76% for the [more basic AES
target](../ss_aes_icestorm)). It's all about tradeoffs... with the SS2
wrapper it's really easy to add registers or port existing CW305 designs;
but if you need that extra 20% logic cells, then do something along [these
lines](../ss\_aes\_icestorm) (or roll your own).

To rebuild the bitfile, install
[nextpnr](https://github.com/YosysHQ/nextpnr) and its prerequisites, with
iCE40 support; then `make bitfile`.

LED1 is a "clock alive" indicator (LED3 on CW308 version).

LED2 has dual roles: it is connected to both GPIO4 and an internal SS2 error
detector. If it remains on, outside of captures, it indicates that an error
occured in the SS2 communications protocol; recovery from this usually
requires a reset, which on this target means re-programming the bitfile. If
it flashed quickly during captures, then it's just the trigger line and
there is no cause for concern.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import datetime

d = datetime.datetime.now()
xapp1232_date = d.second + (d.minute<<6) + (d.hour<<12) + ((d.year-2000)<<17) + (d.month<<23) + (d.day<<27)

ofile = open("timestamp.v", "w")
ofile.write("// dynamically generated at buildtime; timestamp as per Xilinx XAPP1232\n")
ofile.write("assign buildtime = 32'd%d;\n" % xapp1232_date)
ofile.close()

Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
TOP=iCE40UP5K_SS2
FREQ=20

all: time synth pnr pack prog
bitfile: time synth pnr pack

time:
python ./generate_timestamp.py

synth:
yosys -p 'synth_ice40 -top $(TOP) -json $(TOP).json' \
-D ICE40 \
-D SBOX_GF \
-D SS2_WRAPPER \
-D GOOGLE_VAULT_AES \
../hdl/iCE40UP5K_SS2.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_ks.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_sbox.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_core.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_newae/aes_sbox_lut.v \
../../../cw305_artixtarget/fpga/common/cdc_pulse.v \
../../../cw305_artixtarget/fpga/common/cw305_reg_aes.v \
../../../cw305_artixtarget/fpga/common/cw305_top.v \
../../../cw305_artixtarget/fpga/common/cw305_usb_reg_fe.v \
../../xc7a35/fpga-common/hdl/fifo_sync.v \
../../xc7a35/fpga-common/hdl/uart_core.v \
../../xc7a35/fpga-common/hdl/crc_ss2.v \
../../xc7a35/fpga-common/hdl/ss2.v \
-l yosys.log

pnr:
nextpnr-ice40 --up5k --package uwg30 \
--asc $(TOP).asc \
--pcf up5k.pcf \
--json $(TOP).json \
--freq $(FREQ) \
-l pnr.log

pack:
icepack $(TOP).asc $(TOP).bin

prog:
iceprog -S $(TOP).bin

lint:
verilator --lint-only -Wall \
-Wno-PINCONNECTEMPTY \
-D__ICARUS__ \
-DICE40 \
-DSBOX_GF \
-DSS2_WRAPPER \
-DGOOGLE_VAULT_AES \
-I../../../cw305_artixtarget/fpga/common/ \
../hdl/iCE40UP5K_SS2.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_ks.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_sbox.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_googlevault/aes_core.v \
../../../cw305_artixtarget/fpga/cryptosrc/aes_newae/aes_sbox_lut.v \
../../../cw305_artixtarget/fpga/common/cdc_pulse.v \
../../xc7a35/hdl/crc.v \
../../xc7a35/hdl/ss2.v \
../../../cw305_artixtarget/fpga/common/cw305_reg_aes.v \
../../../cw305_artixtarget/fpga/common/cw305_top.v \
../../../cw305_artixtarget/fpga/common/cw305_usb_reg_fe.v \
../../xc7a35/fpga-common/hdl/fifo_sync.v \
../../xc7a35/fpga-common/hdl/uart_core.v \
--top-module $(TOP) \
2>&1 | tee lint.out \

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set_io --warn-no-port clk B3
set_io --warn-no-port IO3 A5
set_io --warn-no-port IO4 A1
set_io --warn-no-port TxD E5
set_io --warn-no-port RxD D5
set_io --warn-no-port clock_alive D3

This file was deleted.

Loading

0 comments on commit dbc3e49

Please sign in to comment.