├── trustedIC ├── __parameters.vh ├── __timescale.v ├── challengeGen.v ├── LFSR_TIC.v ├── SPISlave.v ├── modExp_TIC.v └── top.v ├── untrustedIC ├── __parameters.vh ├── __timescale.v ├── Mem_b.v ├── LFSR_UIC.v ├── res_out_fifo.v ├── Fifo_512_bram.v ├── Fifo_256_feedback.v ├── montgomery_r_c.v ├── primeGen.v ├── noiseFilter.v ├── GCD.v ├── SPIMaster.v ├── privateKeyGen.v ├── modExp_UIC.v ├── cryptoKeyPairGen.v ├── top.v └── primalityTest.v ├── README.md ├── LICENSE.md └── Apache_2.0.md /trustedIC/__parameters.vh: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /untrustedIC/__parameters.vh: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /trustedIC/__timescale.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | -------------------------------------------------------------------------------- /untrustedIC/__timescale.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Split-Chip_authentication 2 | 3 | This repository has the complete RTL description of our chip-to-chip authentication architecture, as described in our research paper "Chip-to-Chip Authentication Method Based on SRAM PUF and Public Key Cryptography", published in the _Journal of Hardware and Systems Security_, Springer, Nov 2019   —   https://doi.org/10.1007/s41635-019-00080-y 4 | -------------------------------------------------------------------------------- /untrustedIC/Mem_b.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Memory wrapper // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Wrapper for one of the memories of the modular exponentiation // 19 | // unit. // 20 | /////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "__timescale.v" 23 | `include "__parameters.vh" 24 | 25 | 26 | module Mem_b ( 27 | input clka, 28 | input wea, 29 | input [5:0] addra, 30 | input [15:0] dina, 31 | output [15:0] douta 32 | ); 33 | 34 | wire wea_sig; 35 | 36 | ARM_sram_16x64 Mem_b_wrapper ( 37 | .QA(douta), 38 | .QB(), 39 | .CLK(clka), 40 | .CENA(1'b0), // active low 41 | .GWENA(wea_sig), 42 | .AA(addra), 43 | .DA(dina), 44 | .CENB(1'b1), // active low 45 | .GWENB(1'b1), // active low 46 | .AB(6'b0), 47 | .DB(16'b0), 48 | .STOV(1'b0), 49 | .STOVAB(1'b0), 50 | .EMA(3'b0), 51 | .EMAP(1'b0), 52 | .EMAW(2'b0), 53 | .EMAS(1'b0), 54 | .RET1N(1'b1) // active low 55 | ); 56 | 57 | 58 | assign wea_sig = ~wea; 59 | 60 | 61 | endmodule -------------------------------------------------------------------------------- /trustedIC/challengeGen.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Challenge generator // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Generates a random challenge to be used in the handshaking // 19 | // routine with the untrusted IC. // 20 | /////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "__timescale.v" 23 | `include "__parameters.vh" 24 | 25 | 26 | module challengeGen #( 27 | parameter CHALLENGE_LENGTH = 32 28 | )( 29 | input clk, 30 | input rst, 31 | input pause, 32 | output [CHALLENGE_LENGTH-1:0] out 33 | ); 34 | 35 | reg LFSR_generateNext; 36 | wire [CHALLENGE_LENGTH-1:0] LFSR_out; 37 | wire [CHALLENGE_LENGTH-1:0] LFSR_seed; 38 | 39 | // in implementation the LFSR should be replaced with a true random number generator 40 | LFSR_TIC #(.CHALLENGE_LENGTH(CHALLENGE_LENGTH)) LFSR_TIC ( 41 | .clk(clk), 42 | .rst(rst), 43 | .generateNext(~pause), 44 | .seed(LFSR_seed), 45 | .out(out) 46 | ); 47 | 48 | always @ (posedge clk) begin 49 | if (!rst) begin 50 | LFSR_generateNext <= 0; 51 | end 52 | else begin 53 | if (pause) begin 54 | LFSR_generateNext <= 0; 55 | end 56 | else begin 57 | LFSR_generateNext <= 1'b1; 58 | end 59 | end 60 | end 61 | 62 | assign LFSR_seed = {{CHALLENGE_LENGTH-32{1'b0}}, 32'h7394_a654}; 63 | 64 | endmodule 65 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## Solderpad Hardware Licence Version 2.0 2 | 3 | This licence (the "Licence") operates as a wraparound licence to the Apache License Version 2.0 (the "Apache License") and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in _italics_ indicate changes from the Apache License, but are indicative and not to be taken into account in interpretation. 4 | 5 | #### 1. The definitions set out in the Apache License are modified as follows: 6 | 7 | **Copyright** any reference to 'copyright' (whether capitalised or not) includes 'Rights' (as defined below). 8 | 9 | **Contribution** also includes any _design_, as well as any work of authorship. 10 | 11 | **Derivative Works** shall not include works that remain _reversibly_ separable from, or merely link (or bind by name) or _physically connect to or interoperate with_ the interfaces of the Work and Derivative Works thereof. 12 | 13 | **Object form** shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, _the instantiation of a hardware design or physical object_ and conversions to other media types, _including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works)_. 14 | 15 | **Rights** means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks). 16 | 17 | **Source form** shall mean the preferred form for making modifications, including but not limited to source code, _net lists, board layouts, CAD files_, documentation source, and configuration files. 18 | 19 | **Work** also includes a _design_ or work of authorship, whether in Source form or _other_ Object form. 20 | 21 | #### 2. Grant of Licence 22 | 23 | 2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license _under the Rights_ to reproduce, prepare Derivative Works of, _make, adapt, repair_, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form _and do anything in relation to the Work as if the Rights did not exist_. 24 | 25 |
26 | 27 | ### APPENDIX 28 | 29 | Find a copy of the Apache License Version 2.0 as "Apache_2.0.md" in the same folder. 30 | -------------------------------------------------------------------------------- /trustedIC/LFSR_TIC.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Linear-Feedback Shift Register // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: The LFSR generates pseudo-random numbers on demand. The // 19 | // pseudo-random number sequence is controlled/altered by // 20 | // setting the initial condition (the 'seed'). The 'seed' is // 21 | // captured at the last clock rising edge before reset signal // 22 | // is asserted // 23 | /////////////////////////////////////////////////////////////////////////////////// 24 | 25 | `include "__timescale.v" 26 | `include "__parameters.vh" 27 | 28 | module LFSR_TIC #( 29 | parameter CHALLENGE_LENGTH = 32 30 | )( 31 | input clk, 32 | input rst, 33 | input generateNext, 34 | input [CHALLENGE_LENGTH-1:0] seed, 35 | output [CHALLENGE_LENGTH-1:0] out 36 | ); 37 | 38 | wire feedback; 39 | reg [CHALLENGE_LENGTH-1:0] out_tmp; 40 | 41 | assign feedback = !(out_tmp[CHALLENGE_LENGTH-1] ^ out_tmp[CHALLENGE_LENGTH-3] ^ out_tmp[CHALLENGE_LENGTH-4] ^ out_tmp[10] ^ out_tmp[0]); 42 | 43 | always @ (posedge clk) begin 44 | if (!rst) begin 45 | out_tmp <= seed; 46 | end 47 | else begin 48 | if (generateNext) begin 49 | out_tmp <= {out_tmp[CHALLENGE_LENGTH-2 : 0], feedback}; 50 | end 51 | else begin 52 | out_tmp <= out_tmp; 53 | end 54 | end 55 | end 56 | 57 | assign out[CHALLENGE_LENGTH-3:0] = out_tmp[CHALLENGE_LENGTH-3:0]; 58 | assign out[CHALLENGE_LENGTH-1:CHALLENGE_LENGTH-2] = 2'b00; // ensures that the challenge has always lower value than public key (RSA requirement) 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /untrustedIC/LFSR_UIC.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Linear-Feedback Shift Register // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: The LFSR generates pseudo-random numbers on demand. The // 19 | // pseudo-random number sequence is controlled/altered by // 20 | // setting the initial condition (the 'seed'). The 'seed' is // 21 | // captured at the last clock rising edge before reset signal // 22 | // is asserted // 23 | /////////////////////////////////////////////////////////////////////////////////// 24 | 25 | `include "__timescale.v" 26 | `include "__parameters.vh" 27 | 28 | module LFSR_UIC #( 29 | parameter HALF_KEY_LENGTH = 16 30 | )( 31 | input clk, 32 | input rst, 33 | input generateNext, 34 | input [HALF_KEY_LENGTH-1:0] seed, 35 | output [HALF_KEY_LENGTH-1:0] out 36 | ); 37 | 38 | wire feedback; 39 | reg [HALF_KEY_LENGTH-1:0] out_tmp; 40 | 41 | assign feedback = !(out_tmp[HALF_KEY_LENGTH-1] ^ out_tmp[HALF_KEY_LENGTH-3] ^ out_tmp[HALF_KEY_LENGTH-4] ^ out_tmp[10] ^ out_tmp[0]); 42 | 43 | always @ (posedge clk) begin 44 | if (!rst) begin 45 | out_tmp <= seed; 46 | end 47 | else begin 48 | if (generateNext) begin 49 | out_tmp <= {out_tmp[HALF_KEY_LENGTH-2 : 0], feedback}; 50 | end 51 | else begin 52 | out_tmp <= out_tmp; 53 | end 54 | end 55 | end 56 | 57 | assign out[HALF_KEY_LENGTH-1] = 1'b1; // ensures big numbers, but also ensures that the public key is always larger than the challenge 58 | assign out[HALF_KEY_LENGTH-2 : 0] = {out_tmp[HALF_KEY_LENGTH-2:1], 1'b1}; // only odd numbers 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /untrustedIC/res_out_fifo.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: FIFO buffer // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: FIFO buffer for the modular exponentiation unit. // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | 25 | module res_out_fifo #( 26 | parameter DATA_WIDTH = 32, 27 | parameter ADDR_WIDTH = 6 28 | )( 29 | input clk, 30 | input rst, 31 | input [DATA_WIDTH-1:0] din, 32 | input wr_en, 33 | input rd_en, 34 | output [DATA_WIDTH-1:0] dout, 35 | output full, 36 | output empty 37 | ); 38 | 39 | localparam DEPTH = (1 << ADDR_WIDTH); 40 | 41 | wire [DATA_WIDTH-1:0] mem_out; 42 | reg rd_en_sig; 43 | reg [ADDR_WIDTH-1:0] wr_pointer; 44 | reg [ADDR_WIDTH-1:0] rd_pointer; 45 | reg [ADDR_WIDTH :0] counter; 46 | 47 | assign full = (counter == DEPTH) ? 1'b1 : 1'b0; 48 | assign empty = (counter == 0) ? 1'b1 : 1'b0; 49 | assign dout = (rd_en_sig) ? mem_out : 1'b0; 50 | 51 | always @ (posedge clk or posedge rst) begin : write_pointer 52 | if (rst) begin 53 | wr_pointer <= 0; 54 | end 55 | 56 | else begin 57 | if (wr_en && (counter != DEPTH)) begin 58 | wr_pointer <= wr_pointer + 1; 59 | end 60 | 61 | else begin 62 | wr_pointer <= wr_pointer; 63 | end 64 | end 65 | end 66 | 67 | always @ (posedge clk or posedge rst) begin : read_pointer 68 | if (rst) begin 69 | rd_en_sig <= 0; 70 | rd_pointer <= 0; 71 | end 72 | 73 | else begin 74 | if (rd_en && (counter != 0)) begin 75 | rd_en_sig <= 1'b1; 76 | rd_pointer <= rd_pointer +1; 77 | end 78 | 79 | else begin 80 | rd_en_sig <= 0; 81 | rd_pointer <= rd_pointer; 82 | end 83 | end 84 | end 85 | 86 | always @ (posedge clk or posedge rst) begin : STATUS_COUNTER 87 | if (rst) begin 88 | counter <= 0; 89 | end 90 | 91 | else begin 92 | if (rd_en && !wr_en && (counter != 0)) begin // only read 93 | counter <= counter - 1; 94 | end 95 | 96 | else if (wr_en && !rd_en && (counter != DEPTH)) begin // only write 97 | counter <= counter + 1; 98 | end 99 | 100 | else begin 101 | counter <= counter; 102 | end 103 | end 104 | end 105 | 106 | wire [DATA_WIDTH-1:0] _unconnected; 107 | 108 | ARM_sram_32x64 ARM_sram_32x64 ( 109 | .QA(mem_out), 110 | .QB(_unconnected), 111 | .CLK(clk), 112 | .CENA(~rd_en), // active low 113 | .GWENA(1'b1), // active low 114 | .AA(rd_pointer), 115 | .DA({DATA_WIDTH{1'b0}}), 116 | .CENB(full), // active low 117 | .GWENB(~wr_en), // active low 118 | .AB(wr_pointer), 119 | .DB(din), 120 | .STOV(1'b0), 121 | .STOVAB(1'b0), 122 | .EMA(3'b0), 123 | .EMAP(1'b0), 124 | .EMAW(2'b0), 125 | .EMAS(1'b0), 126 | .RET1N(1'b1) // active low 127 | ); 128 | 129 | endmodule -------------------------------------------------------------------------------- /untrustedIC/Fifo_512_bram.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: FIFO buffer // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: FIFO buffer for the modular exponentiation unit. // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | 25 | module Fifo_512_bram #( 26 | parameter DATA_WIDTH = 16, 27 | parameter ADDR_WIDTH = 6 28 | )( 29 | input clk, 30 | input rst, 31 | input [DATA_WIDTH-1:0] din, 32 | input wr_en, 33 | input rd_en, 34 | output [DATA_WIDTH-1:0] dout, 35 | output full, 36 | output empty 37 | ); 38 | 39 | localparam DEPTH = (1 << ADDR_WIDTH); 40 | 41 | wire [DATA_WIDTH-1:0] mem_out; 42 | reg rd_en_sig; 43 | reg [ADDR_WIDTH-1:0] wr_pointer; 44 | reg [ADDR_WIDTH-1:0] rd_pointer; 45 | reg [ADDR_WIDTH :0] counter; 46 | 47 | assign full = (counter == DEPTH) ? 1'b1 : 1'b0; 48 | assign empty = (counter == 0) ? 1'b1 : 1'b0; 49 | assign dout = (rd_en_sig) ? mem_out : 1'b0; 50 | 51 | always @ (posedge clk or posedge rst) begin : write_pointer 52 | if (rst) begin 53 | wr_pointer <= 0; 54 | end 55 | 56 | else begin 57 | if (wr_en && (counter != DEPTH)) begin 58 | wr_pointer <= wr_pointer + 1; 59 | end 60 | 61 | else begin 62 | wr_pointer <= wr_pointer; 63 | end 64 | end 65 | end 66 | 67 | always @ (posedge clk or posedge rst) begin : read_pointer 68 | if (rst) begin 69 | rd_en_sig <= 0; 70 | rd_pointer <= 0; 71 | end 72 | 73 | else begin 74 | if (rd_en && (counter != 0)) begin 75 | rd_en_sig <= 1'b1; 76 | rd_pointer <= rd_pointer +1; 77 | end 78 | 79 | else begin 80 | rd_en_sig <= 0; 81 | rd_pointer <= rd_pointer; 82 | end 83 | end 84 | end 85 | 86 | always @ (posedge clk or posedge rst) begin : STATUS_COUNTER 87 | if (rst) begin 88 | counter <= 0; 89 | end 90 | 91 | else begin 92 | if (rd_en && !wr_en && (counter != 0)) begin // only read 93 | counter <= counter - 1; 94 | end 95 | 96 | else if (wr_en && !rd_en && (counter != DEPTH)) begin // only write 97 | counter <= counter + 1; 98 | end 99 | 100 | else begin 101 | counter <= counter; 102 | end 103 | end 104 | end 105 | 106 | wire [DATA_WIDTH-1:0] _unconnected; 107 | 108 | ARM_sram_16x64 ARM_sram_16x64 ( 109 | .QA(mem_out), 110 | .QB(_unconnected), 111 | .CLK(clk), 112 | .CENA(~rd_en), // active low 113 | .GWENA(1'b1), // active low 114 | .AA(rd_pointer), 115 | .DA({DATA_WIDTH{1'b0}}), 116 | .CENB(full), // active low 117 | .GWENB(~wr_en), // active low 118 | .AB(wr_pointer), 119 | .DB(din), 120 | .STOV(1'b0), 121 | .STOVAB(1'b0), 122 | .EMA(3'b0), 123 | .EMAP(1'b0), 124 | .EMAW(2'b0), 125 | .EMAS(1'b0), 126 | .RET1N(1'b1) // active low 127 | ); 128 | 129 | endmodule -------------------------------------------------------------------------------- /untrustedIC/Fifo_256_feedback.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: FIFO buffer // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: FIFO buffer for the modular exponentiation unit. // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | 25 | module Fifo_256_feedback #( 26 | parameter DATA_WIDTH = 49, 27 | parameter ADDR_WIDTH = 6 28 | )( 29 | input clk, 30 | input rst, 31 | input [DATA_WIDTH-1:0] din, 32 | input wr_en, 33 | input rd_en, 34 | output [DATA_WIDTH-1:0] dout, 35 | output full, 36 | output empty 37 | ); 38 | 39 | localparam DEPTH = (1 << ADDR_WIDTH); 40 | 41 | wire [DATA_WIDTH-1:0] mem_out; 42 | reg rd_en_sig; 43 | reg [ADDR_WIDTH-1:0] wr_pointer; 44 | reg [ADDR_WIDTH-1:0] rd_pointer; 45 | reg [ADDR_WIDTH :0] counter; 46 | 47 | assign full = (counter == DEPTH) ? 1'b1 : 1'b0; 48 | assign empty = (counter == 0) ? 1'b1 : 1'b0; 49 | assign dout = (rd_en_sig) ? mem_out : 1'b0; 50 | 51 | always @ (posedge clk or posedge rst) begin : write_pointer 52 | if (rst) begin 53 | wr_pointer <= 0; 54 | end 55 | 56 | else begin 57 | if (wr_en && (counter != DEPTH)) begin 58 | wr_pointer <= wr_pointer + 1; 59 | end 60 | 61 | else begin 62 | wr_pointer <= wr_pointer; 63 | end 64 | end 65 | end 66 | 67 | always @ (posedge clk or posedge rst) begin : read_pointer 68 | if (rst) begin 69 | rd_en_sig <= 0; 70 | rd_pointer <= 0; 71 | end 72 | 73 | else begin 74 | if (rd_en && (counter != 0)) begin 75 | rd_en_sig <= 1'b1; 76 | rd_pointer <= rd_pointer +1; 77 | end 78 | 79 | else begin 80 | rd_en_sig <= 0; 81 | rd_pointer <= rd_pointer; 82 | end 83 | end 84 | end 85 | 86 | always @ (posedge clk or posedge rst) begin : STATUS_COUNTER 87 | if (rst) begin 88 | counter <= 0; 89 | end 90 | 91 | else begin 92 | if (rd_en && !wr_en && (counter != 0)) begin // only read 93 | counter <= counter - 1; 94 | end 95 | 96 | else if (wr_en && !rd_en && (counter != DEPTH)) begin // only write 97 | counter <= counter + 1; 98 | end 99 | 100 | else begin 101 | counter <= counter; 102 | end 103 | end 104 | end 105 | 106 | wire [DATA_WIDTH-1:0] _unconnected; 107 | 108 | ARM_sram_49x64 ARM_sram_49x64 ( 109 | .QA(mem_out), 110 | .QB(_unconnected), 111 | .CLK(clk), 112 | .CENA(~rd_en), // active low 113 | .GWENA(1'b1), // active low 114 | .AA(rd_pointer), 115 | .DA({DATA_WIDTH{1'b0}}), 116 | .CENB(full), // active low 117 | .GWENB(~wr_en), // active low 118 | .AB(wr_pointer), 119 | .DB(din), 120 | .STOV(1'b0), 121 | .STOVAB(1'b0), 122 | .EMA(3'b0), 123 | .EMAP(1'b0), 124 | .EMAW(2'b0), 125 | .EMAS(1'b0), 126 | .RET1N(1'b1) // active low 127 | ); 128 | 129 | endmodule -------------------------------------------------------------------------------- /untrustedIC/montgomery_r_c.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Montgomery constant calculator // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Calculates the montgomery contant (r_c). // 19 | // r_c = r^2 mod n, where r = 2^(word length*(word count+1)) and // 20 | // n is the modulus. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | `include "__timescale.v" 24 | `include "__parameters.vh" 25 | 26 | 27 | module montgomery_r_c #( 28 | parameter MONTGOMERY_MODULE_KEY_LENGTH = 512 29 | )( 30 | input clk, 31 | input rst, 32 | input [MONTGOMERY_MODULE_KEY_LENGTH-1:0] MOD, 33 | input start, 34 | output [MONTGOMERY_MODULE_KEY_LENGTH-1:0] r_c, 35 | output reg ready 36 | ); 37 | 38 | reg divStart; 39 | wire divComplete; 40 | 41 | reg [2:0] state, next_state; 42 | 43 | localparam STATE_IDLE = 3'd0; 44 | localparam STATE_CALC_R_C = 3'd1; 45 | localparam STATE_READY = 3'd2; 46 | 47 | always @(posedge clk) begin 48 | if (rst == 1'b0) begin 49 | state <= STATE_IDLE; 50 | end 51 | else begin 52 | state <= next_state; 53 | end 54 | end 55 | 56 | always @(*) begin 57 | next_state = state; 58 | 59 | case (state) 60 | STATE_IDLE: begin 61 | if (start) begin 62 | next_state = STATE_CALC_R_C; 63 | end 64 | end 65 | 66 | STATE_CALC_R_C: begin 67 | if (divComplete) begin 68 | next_state = STATE_READY; 69 | end 70 | end 71 | 72 | STATE_READY: begin 73 | next_state = STATE_IDLE; 74 | end 75 | 76 | default: begin 77 | if (start) begin 78 | next_state = STATE_CALC_R_C; 79 | end 80 | end 81 | endcase 82 | end 83 | 84 | always @(posedge clk) begin 85 | case (state) 86 | STATE_IDLE: begin 87 | ready <= 0; 88 | if (next_state == STATE_CALC_R_C) begin 89 | divStart <= 1'b1; 90 | end 91 | else begin 92 | divStart <= 0; 93 | end 94 | end 95 | 96 | STATE_CALC_R_C: begin 97 | ready <= 0; 98 | divStart <= 0; 99 | end 100 | 101 | STATE_READY: begin 102 | ready <= 1'b1; 103 | divStart <= 0; 104 | end 105 | 106 | default: begin 107 | ready <= 0; 108 | if (start) begin 109 | divStart <= 1'b1; 110 | end 111 | else begin 112 | divStart <= 0; 113 | end 114 | end 115 | endcase 116 | end 117 | 118 | localparam [1056:0] a = 1'b1 << 1056; 119 | 120 | div_seq #(.a_width(1057), .b_width(MONTGOMERY_MODULE_KEY_LENGTH), .num_cyc(1057)) div_seq ( 121 | .clk(clk), 122 | .rst_n(rst), 123 | .hold(1'b0), 124 | .start(divStart), 125 | .a(a), 126 | .b(MOD), 127 | .complete(divComplete), 128 | .divide_by_0(), 129 | .quotient(), 130 | .remainder(r_c) 131 | ); 132 | 133 | endmodule 134 | -------------------------------------------------------------------------------- /untrustedIC/primeGen.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Prime number generator // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Main FSM for generating prime numbers. Requests a new // 19 | // pseudo-random number from the LFSR and uses the primality // 20 | // tester to determine if it is prime. It keeps requesting new // 21 | // numbers until it finds a prime. // 22 | /////////////////////////////////////////////////////////////////////////////////// 23 | 24 | `include "__timescale.v" 25 | `include "__parameters.vh" 26 | 27 | 28 | module primeGen #( 29 | parameter KEY_LENGTH = 32, 30 | parameter integer HALF_KEY_LENGTH = 0.5 * KEY_LENGTH, 31 | parameter e_WIDTH = 3 32 | )( 33 | input clk, 34 | input rst, 35 | input [HALF_KEY_LENGTH-1:0] seed, 36 | input modExp_ready, 37 | input [511:0] modExp_out, 38 | output modExp_rst, 39 | output [511:0] modExp_x, 40 | output [511+e_WIDTH:0] modExp_y, 41 | output [9:0] modExp_y_size, 42 | output [511:0] modExp_m, 43 | output modExp_start, 44 | output reg [HALF_KEY_LENGTH-1:0] prime, 45 | output reg ready 46 | ); 47 | 48 | wire [HALF_KEY_LENGTH-1:0] primeUnderTest; 49 | reg [HALF_KEY_LENGTH-1:0] primeUnderTest_buf; 50 | wire isPrime, done; 51 | reg generateNext_sig, primalityTest_start, rst_buf; 52 | 53 | LFSR_UIC #(.HALF_KEY_LENGTH(HALF_KEY_LENGTH)) LFSR_UIC ( 54 | .clk(clk), 55 | .rst(rst), 56 | .generateNext(generateNext_sig), 57 | .seed(seed), 58 | .out(primeUnderTest) 59 | ); 60 | 61 | primalityTest #(.KEY_LENGTH(KEY_LENGTH), .e_WIDTH(e_WIDTH)) primalityTest ( 62 | .clk(clk), 63 | .rst(rst), 64 | .in(primeUnderTest), 65 | .start(primalityTest_start), 66 | .modExp_ready(modExp_ready), 67 | .modExp_out(modExp_out), 68 | .modExp_rst(modExp_rst), 69 | .modExp_x(modExp_x), 70 | .modExp_y(modExp_y), 71 | .modExp_y_size(modExp_y_size), 72 | .modExp_m(modExp_m), 73 | .modExp_start(modExp_start), 74 | .done(done), 75 | .isPrime(isPrime) 76 | ); 77 | 78 | always @(*) begin 79 | if (!rst) begin 80 | generateNext_sig = 1'b0; 81 | end 82 | else begin 83 | if (done) begin 84 | generateNext_sig = 1'b1; 85 | end 86 | else begin 87 | generateNext_sig = 1'b0; 88 | end 89 | end 90 | end 91 | 92 | always @ (posedge clk) begin 93 | rst_buf <= rst; 94 | end 95 | 96 | always @ (posedge clk) begin 97 | if (!rst) begin 98 | prime <= 0; 99 | ready <= 0; 100 | primeUnderTest_buf <= 0; 101 | primalityTest_start <= 1'b0; 102 | end 103 | else begin 104 | primeUnderTest_buf <= primeUnderTest; 105 | 106 | if (done || !rst_buf) begin 107 | primalityTest_start <= 1'b1; 108 | end 109 | else begin 110 | primalityTest_start <= 1'b0; 111 | end 112 | 113 | if (done && isPrime) begin 114 | prime <= primeUnderTest_buf; 115 | ready <= 1'b1; 116 | end 117 | else begin 118 | prime <= prime; 119 | ready <= 1'b0; 120 | end 121 | end 122 | end 123 | 124 | endmodule -------------------------------------------------------------------------------- /trustedIC/SPISlave.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: SPI-custom slave // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: This is the slave module of a custom SPI interface, // 19 | // achieving full duplex synchronous serial communication using // 20 | // only 3 wires. In contrast to typical SPI implementation, the // 21 | // slave (this module) can send any amount of data to its paired // 22 | // master at any time — i.e., no predefined slave-to-master time // 23 | // windows, or extra wires are needed. // 24 | /////////////////////////////////////////////////////////////////////////////////// 25 | 26 | `include "__timescale.v" 27 | `include "__parameters.vh" 28 | 29 | module SPISlave #( 30 | parameter KEY_LENGTH = 32 31 | )( 32 | input clk, 33 | input rst, 34 | input [KEY_LENGTH-1:0] dataToSend, 35 | input send, 36 | input MOSI, 37 | input SCLK, 38 | output reg MISO, 39 | output [KEY_LENGTH-1:0] dataReceived, 40 | output reg dataReceived_ready 41 | ); 42 | 43 | reg [KEY_LENGTH:0] dataToSend_buf; 44 | wire [KEY_LENGTH:0] dataReceived_internal; 45 | reg send_buf, send_delayed, send_trigger, sending; 46 | integer SCLK_counter_receive, SCLK_counter_send; 47 | 48 | assign dataReceived = dataReceived_internal[KEY_LENGTH-1:0]; 49 | 50 | // Shift register for capturing input 51 | wire shift_in; 52 | 53 | reg [KEY_LENGTH:0] data; 54 | wire [KEY_LENGTH:0] data_next; 55 | 56 | always @(posedge rst) begin 57 | SCLK_counter_receive <= 0; 58 | dataReceived_ready <= 0; 59 | end 60 | 61 | always @(posedge SCLK) begin 62 | if (!rst) begin 63 | data <= 0; 64 | end 65 | else begin 66 | data <= data_next; 67 | if (SCLK_counter_receive == KEY_LENGTH) begin 68 | SCLK_counter_receive <= 0; 69 | dataReceived_ready <= 1'b1; 70 | end 71 | else begin 72 | SCLK_counter_receive <= SCLK_counter_receive + 1; 73 | dataReceived_ready <= 1'b0; 74 | end 75 | end 76 | end 77 | 78 | assign shift_in = MOSI; 79 | assign dataReceived_internal = data; 80 | 81 | assign data_next = {shift_in, data[KEY_LENGTH:1]}; 82 | // End of shift register 83 | 84 | always @(posedge clk) begin 85 | send_buf <= send; 86 | send_delayed <= send_buf; 87 | if (send_buf && !send_delayed) begin // posedge triggered 88 | send_trigger <= 1'b1; 89 | end 90 | else begin 91 | send_trigger <= 0; 92 | end 93 | end 94 | 95 | always @(posedge rst) begin 96 | send_buf <= 0; 97 | send_delayed <= 0; 98 | dataToSend_buf <= 0; 99 | MISO <= 0; 100 | SCLK_counter_send <= 0; 101 | sending <= 0; 102 | end 103 | 104 | always @(posedge send_trigger or negedge SCLK) begin 105 | if (send_trigger) begin 106 | if (!sending) begin 107 | MISO <= 1'b1; 108 | dataToSend_buf <= dataToSend; 109 | SCLK_counter_send <= 0; 110 | sending <= 1'b1; 111 | end 112 | else begin 113 | MISO <= MISO; 114 | dataToSend_buf <= dataToSend_buf; 115 | SCLK_counter_send <= SCLK_counter_send; 116 | sending <= 1'b1; 117 | end 118 | end 119 | else begin 120 | if (SCLK_counter_send == KEY_LENGTH) begin 121 | SCLK_counter_send <= 0; 122 | sending <= 0; 123 | MISO <= 0; 124 | end 125 | else begin 126 | SCLK_counter_send <= SCLK_counter_send + 1; 127 | sending <= sending; 128 | MISO <= dataToSend_buf[SCLK_counter_send]; 129 | end 130 | dataToSend_buf <= dataToSend_buf; 131 | end 132 | end 133 | 134 | endmodule -------------------------------------------------------------------------------- /untrustedIC/noiseFilter.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Noise filtering module // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Performs filtering of a noisy input 'in', based on // 19 | // quantization and exclusion. Let Z as the outcome of the // 20 | // "filtered" input X (X->Z). If Y is an altered version of X, // 21 | // within a defined range of average "bit-flips", Z will // 22 | // remain the same (Y->Z). // 23 | /////////////////////////////////////////////////////////////////////////////////// 24 | 25 | `include "__timescale.v" 26 | `include "__parameters.vh" 27 | 28 | 29 | module noiseFilter #( 30 | parameter 31 | HALF_KEY_LENGTH = 16 32 | ) ( 33 | input clk, 34 | input rst, 35 | input [(16*HALF_KEY_LENGTH)-1 : 0] in, 36 | output reg [HALF_KEY_LENGTH-1 : 0] out, 37 | output reg ready 38 | ); 39 | 40 | reg [HALF_KEY_LENGTH-1 : 0] validRegions; 41 | reg [(5*HALF_KEY_LENGTH)-1 : 0] quantized; 42 | 43 | reg [2:0] state, next_state; 44 | 45 | localparam STATE_OFF = 3'd0; 46 | localparam STATE_QUANTIZE = 3'd1; 47 | localparam STATE_MARK_VALID = 3'd2; 48 | localparam STATE_FINAL = 3'd3; 49 | localparam STATE_READY = 3'd4; 50 | 51 | localparam EXCLUSION_ZONE_WIDTH = 4; 52 | localparam integer HALF_EXCLUSION_ZONE_WIDTH = EXCLUSION_ZONE_WIDTH * 0.5; 53 | 54 | integer i; 55 | 56 | always @(posedge clk) begin 57 | if (!rst) begin 58 | state <= STATE_OFF; 59 | end 60 | else begin 61 | state <= next_state; 62 | end 63 | end 64 | 65 | always @(*) begin 66 | next_state = state; 67 | 68 | case (state) 69 | STATE_OFF: begin 70 | next_state = STATE_QUANTIZE; 71 | end 72 | 73 | STATE_QUANTIZE: begin 74 | next_state = STATE_MARK_VALID; 75 | end 76 | 77 | STATE_MARK_VALID: begin 78 | next_state = STATE_FINAL; 79 | end 80 | 81 | STATE_FINAL: begin 82 | next_state = STATE_READY; 83 | end 84 | 85 | STATE_READY: begin 86 | next_state = STATE_READY; 87 | end 88 | 89 | default: begin 90 | next_state = STATE_QUANTIZE; 91 | end 92 | endcase 93 | 94 | end 95 | 96 | always @(*) begin 97 | 98 | case (state) 99 | STATE_OFF: begin 100 | quantized = 0; 101 | validRegions = 0; 102 | out = 0; 103 | ready = 0; 104 | end 105 | 106 | STATE_QUANTIZE: begin 107 | for (i=0; i 8+(HALF_EXCLUSION_ZONE_WIDTH-1)) ) begin 122 | validRegions[i] = 1'b1; 123 | end 124 | else begin 125 | validRegions[i] = 1'b0; 126 | end 127 | 128 | if ( quantized[(i*5) +: 5] < 8 ) begin 129 | out[i] = 1'b0; 130 | end 131 | else begin 132 | out[i] = 1'b1; 133 | end 134 | end 135 | ready = 0; 136 | end 137 | 138 | STATE_FINAL: begin 139 | quantized = quantized; 140 | validRegions = validRegions; 141 | out = out & validRegions; 142 | ready = 0; 143 | end 144 | 145 | STATE_READY: begin 146 | quantized = quantized; 147 | validRegions = validRegions; 148 | out = out; 149 | ready = 1'b1; 150 | end 151 | 152 | default: begin 153 | quantized = 0; 154 | validRegions = 0; 155 | out = 0; 156 | ready = 0; 157 | end 158 | endcase 159 | 160 | end 161 | 162 | endmodule -------------------------------------------------------------------------------- /untrustedIC/GCD.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Greatest Common Divisor unit // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Sub-module for the crypto key pair generator. Calculates the // 19 | // GCD (f(n), e), which should equal to 1 for a valid RSA key // 20 | // pair. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | `include "__timescale.v" 24 | `include "__parameters.vh" 25 | 26 | 27 | module GCD #( 28 | parameter HALF_KEY_LENGTH = 16, 29 | parameter e_WIDTH = 3 30 | )( 31 | input clk, 32 | input rst, 33 | input [HALF_KEY_LENGTH-1:0] p1, 34 | input [HALF_KEY_LENGTH-1:0] p2, 35 | input [e_WIDTH-1:0] e, 36 | input start, 37 | output reg areValid, 38 | output [2*HALF_KEY_LENGTH-1:0] MOD, 39 | output [2*HALF_KEY_LENGTH-1:0] f_n, 40 | output reg ready 41 | ); 42 | 43 | wire [2*HALF_KEY_LENGTH-1:0] MOD_sig; 44 | reg [2*HALF_KEY_LENGTH-1:0] f_n_sig; 45 | wire [2:0] modResult; 46 | reg multStart; 47 | wire multComplete; 48 | reg divStart; 49 | wire divComplete; 50 | 51 | assign MOD = MOD_sig; 52 | assign f_n = f_n_sig; 53 | 54 | reg [2:0] state, next_state; 55 | 56 | localparam STATE_IDLE = 3'd0; 57 | localparam STATE_CALC_MOD = 3'd1; 58 | localparam STATE_CALC_FN = 3'd2; 59 | localparam STATE_MODULUS = 3'd3; 60 | localparam STATE_READY = 3'd4; 61 | 62 | always @(posedge clk) begin 63 | if (rst == 1'b0) begin 64 | state <= STATE_IDLE; 65 | end 66 | else begin 67 | state <= next_state; 68 | end 69 | end 70 | 71 | always @(*) begin 72 | next_state = state; 73 | 74 | case (state) 75 | STATE_IDLE: begin 76 | if (start) begin 77 | next_state = STATE_CALC_MOD; 78 | end 79 | end 80 | 81 | STATE_CALC_MOD: begin 82 | if (multComplete) begin 83 | next_state = STATE_CALC_FN; 84 | end 85 | end 86 | 87 | STATE_CALC_FN: begin 88 | next_state = STATE_MODULUS; 89 | end 90 | 91 | STATE_MODULUS: begin 92 | if (divComplete) begin 93 | next_state = STATE_READY; 94 | end 95 | end 96 | 97 | STATE_READY: begin 98 | 99 | end 100 | 101 | default: begin 102 | if (start) begin 103 | next_state = STATE_CALC_MOD; 104 | end 105 | end 106 | endcase 107 | end 108 | 109 | always @(posedge clk) begin 110 | case (state) 111 | STATE_IDLE: begin 112 | ready <= 0; 113 | areValid <= 0; 114 | divStart <= 0; 115 | f_n_sig <= 0; 116 | if (start) begin 117 | multStart <= 1'b1; 118 | end 119 | else begin 120 | multStart <= 0; 121 | end 122 | end 123 | 124 | STATE_CALC_MOD: begin 125 | ready <= 0; 126 | areValid <= 0; 127 | multStart <= 0; 128 | divStart <= 0; 129 | f_n_sig <= 0; 130 | end 131 | 132 | STATE_CALC_FN: begin 133 | ready <= 0; 134 | areValid <= 0; 135 | multStart <= 0; 136 | divStart <= 1'b1; 137 | f_n_sig <= MOD_sig - p1 - p2 + 1; 138 | end 139 | 140 | STATE_MODULUS: begin 141 | ready <= 0; 142 | areValid <= 0; 143 | multStart <= 0; 144 | divStart <= 0; 145 | f_n_sig <= f_n_sig; 146 | end 147 | 148 | STATE_READY: begin 149 | ready <= 1'b1; 150 | multStart <= 0; 151 | divStart <= 0; 152 | f_n_sig <= f_n_sig; 153 | if (modResult != 0) begin 154 | areValid <= 1; 155 | end 156 | else begin 157 | areValid <= 0; 158 | end 159 | end 160 | 161 | default: begin 162 | ready <= 0; 163 | areValid <= 0; 164 | divStart <= 0; 165 | f_n_sig <= 0; 166 | if (start) begin 167 | multStart <= 1'b1; 168 | end 169 | else begin 170 | multStart <= 0; 171 | end 172 | end 173 | endcase 174 | end 175 | 176 | mult_seq #(.a_width(HALF_KEY_LENGTH), .b_width(HALF_KEY_LENGTH), .num_cyc(HALF_KEY_LENGTH)) mult_seq ( 177 | .clk(clk), 178 | .rst_n(rst), 179 | .hold(1'b0), 180 | .start(multStart), 181 | .a(p1), 182 | .b(p2), 183 | .complete(multComplete), 184 | .product(MOD_sig) 185 | ); 186 | 187 | div_seq #(.a_width(2*HALF_KEY_LENGTH), .b_width(e_WIDTH), .num_cyc(2*HALF_KEY_LENGTH)) div_seq ( 188 | .clk(clk), 189 | .rst_n(rst), 190 | .hold(1'b0), 191 | .start(divStart), 192 | .a(f_n_sig), 193 | .b(e), 194 | .complete(divComplete), 195 | .divide_by_0(), 196 | .quotient(), 197 | .remainder(modResult) 198 | ); 199 | 200 | endmodule 201 | -------------------------------------------------------------------------------- /untrustedIC/SPIMaster.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: SPI-custom master // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: This is the master module of a custom SPI interface, // 19 | // achieving full duplex synchronous serial communication using // 20 | // only 3 wires. In contrast to typical SPI implementation, the // 21 | // paired slave of this module can send any amount of data to // 22 | // the master (this module) at any time — i.e., no predefined // 23 | // slave-to-master time windows, or extra wires are needed. // 24 | /////////////////////////////////////////////////////////////////////////////////// 25 | 26 | `include "__timescale.v" 27 | `include "__parameters.vh" 28 | 29 | 30 | module SPIMaster #( 31 | parameter KEY_LENGTH = 32, 32 | parameter SCLK_PERIOD_AS_CLK_MULTIPLE = 10 33 | )( 34 | input clk, 35 | input rst, 36 | input [KEY_LENGTH-1:0] dataToSend, 37 | input start, 38 | input MISO, 39 | output reg SCLK, 40 | output reg MOSI, 41 | output [KEY_LENGTH-1:0] dataReceived 42 | ); 43 | 44 | localparam integer SCLK_SEMI_PERIOD = 0.5 * SCLK_PERIOD_AS_CLK_MULTIPLE; 45 | 46 | reg start_buf, start_delayed, data_interval, done; // done signal for future use 47 | wire [KEY_LENGTH:0] dataToSend_internal, dataReceived_internal; // wires extended by 1 bit and msb set to 0 in to facilitate correct communication with 48 | // slave. Slave expects one extra SCLK pulse after the transmission of the last bit. 49 | integer data_counter; 50 | integer clk_counter; 51 | 52 | assign dataToSend_internal = {1'b0, dataToSend[KEY_LENGTH-1:0]}; 53 | assign dataReceived = dataReceived_internal[KEY_LENGTH-1:0]; 54 | 55 | // Shift register for capturing input 56 | wire shift_in; 57 | 58 | reg [KEY_LENGTH:0] data; 59 | wire [KEY_LENGTH:0] data_next; 60 | 61 | always @(posedge SCLK) begin 62 | if (!rst) begin 63 | data <= 0; 64 | end 65 | else begin 66 | data <= data_next; 67 | end 68 | end 69 | 70 | assign shift_in = MISO; 71 | assign dataReceived_internal = data; 72 | 73 | assign data_next = {shift_in, data[KEY_LENGTH:1]}; 74 | // End of shift register 75 | 76 | always @(posedge clk) begin 77 | if (!rst) begin 78 | start_buf <= 0; 79 | start_delayed <= 0; 80 | end 81 | else begin 82 | start_buf <= start; 83 | start_delayed <= start_buf; 84 | end 85 | end 86 | 87 | reg state, next_state; 88 | localparam STATE_IDLE = 1'd0; 89 | localparam STATE_SEND_RECEIVE = 1'd1; 90 | 91 | always @(posedge clk) begin 92 | if (!rst) begin 93 | state <= STATE_IDLE; 94 | end 95 | else begin 96 | state <= next_state; 97 | end 98 | end 99 | 100 | always @(*) begin 101 | next_state = state; 102 | 103 | case (state) 104 | STATE_IDLE: begin 105 | if (start_buf && !start_delayed) begin // posedge triggered 106 | next_state = STATE_SEND_RECEIVE; 107 | end 108 | end 109 | 110 | STATE_SEND_RECEIVE: begin 111 | if (data_counter == KEY_LENGTH+1 && clk_counter == SCLK_SEMI_PERIOD-1) begin // "KEY_LENGTH+1" because slave expects one 112 | // extra SCLK pulse after the transmission of 113 | // the last bit. 114 | next_state = STATE_IDLE; 115 | end 116 | end 117 | 118 | default: begin 119 | if (start_buf && !start_delayed) begin // posedge triggered 120 | next_state = STATE_SEND_RECEIVE; 121 | end 122 | end 123 | endcase 124 | end 125 | 126 | always @(posedge clk) begin 127 | 128 | case (state) 129 | STATE_IDLE: begin 130 | done <= 0; 131 | clk_counter <= 0; 132 | SCLK <= 1'b1; 133 | MOSI <= MOSI; 134 | data_counter <= 0; 135 | data_interval <= 0; 136 | end 137 | 138 | STATE_SEND_RECEIVE: begin 139 | if (clk_counter == SCLK_SEMI_PERIOD-1) begin 140 | SCLK <= ~SCLK; 141 | data_interval <= ~data_interval; 142 | clk_counter <= 0; 143 | if (!data_interval) begin 144 | MOSI <= dataToSend_internal[data_counter]; 145 | data_counter <= data_counter + 1'b1; 146 | end 147 | else begin 148 | MOSI <= MOSI; 149 | data_counter <= data_counter; 150 | end 151 | end 152 | else begin 153 | SCLK <= SCLK; 154 | data_interval <= data_interval; 155 | clk_counter <= clk_counter + 1'b1; 156 | MOSI <= MOSI; 157 | data_counter <= data_counter; 158 | end 159 | 160 | if (next_state == STATE_IDLE) begin 161 | done <= 1'b1; 162 | end 163 | else begin 164 | done <= 0; 165 | end 166 | end 167 | 168 | default: begin 169 | done <= 0; 170 | clk_counter <= 0; 171 | SCLK <= 1'b1; 172 | MOSI <= 0; 173 | data_counter <= 0; 174 | data_interval <= 0; 175 | end 176 | endcase 177 | end 178 | 179 | endmodule -------------------------------------------------------------------------------- /untrustedIC/privateKeyGen.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Private key generator // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Calculates the modular multiplicative inverse of e(mod f(n)). // 19 | // This is the RSA private key. // 20 | /////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "__timescale.v" 23 | `include "__parameters.vh" 24 | 25 | 26 | module privateKeyGen #( 27 | parameter HALF_KEY_LENGTH = 16, 28 | parameter e_WIDTH = 3 // if e_WIDTH=17 then line 165 should be commented out 29 | )( 30 | input clk, 31 | input rst, 32 | input [2*HALF_KEY_LENGTH-1:0] f_n, 33 | input [e_WIDTH-1:0] e, 34 | input start, 35 | output reg ready, 36 | output [(2*HALF_KEY_LENGTH)+e_WIDTH:0] privateKey 37 | ); 38 | 39 | wire [((2*HALF_KEY_LENGTH)+17)-1:0] f_n_times_X; 40 | reg [(2*HALF_KEY_LENGTH)+e_WIDTH:0] f_n_times_X_plus_one; // has one more bit in case of overflow due to +1 41 | wire [2:0] modResult; 42 | reg multStart; 43 | wire multComplete; 44 | reg divStart; 45 | wire divComplete; 46 | reg [e_WIDTH-1:0] X; 47 | reg [e_WIDTH-1:0] tmpX; 48 | 49 | reg [2:0] state, next_state; 50 | 51 | localparam STATE_IDLE = 3'd0; 52 | localparam STATE_CALC_FN_TIMES_X = 3'd1; 53 | localparam STATE_DIV_BY_E = 3'd2; 54 | localparam STATE_READY = 3'd3; 55 | 56 | always @(posedge clk) begin 57 | if (rst == 1'b0) begin 58 | state <= STATE_IDLE; 59 | end 60 | else begin 61 | state <= next_state; 62 | end 63 | end 64 | 65 | always @(*) begin 66 | next_state = state; 67 | 68 | case (state) 69 | STATE_IDLE: begin 70 | if (start) begin 71 | next_state = STATE_CALC_FN_TIMES_X; 72 | end 73 | end 74 | 75 | STATE_CALC_FN_TIMES_X: begin 76 | if (multComplete) begin 77 | next_state = STATE_DIV_BY_E; 78 | end 79 | end 80 | 81 | STATE_DIV_BY_E: begin 82 | if (divComplete) begin 83 | if (modResult == 0) begin 84 | next_state = STATE_READY; 85 | end 86 | else begin 87 | next_state = STATE_CALC_FN_TIMES_X; 88 | end 89 | end 90 | end 91 | 92 | STATE_READY: begin 93 | 94 | end 95 | 96 | default: begin 97 | if (start) begin 98 | next_state = STATE_CALC_FN_TIMES_X; 99 | end 100 | end 101 | endcase 102 | end 103 | 104 | always @(posedge clk) begin 105 | case (state) 106 | STATE_IDLE: begin 107 | ready <= 0; 108 | divStart <= 0; 109 | tmpX <= 1'b1; 110 | X <= 1'b1; 111 | f_n_times_X_plus_one <= 0; 112 | if (start) begin 113 | multStart <= 1'b1; 114 | end 115 | else begin 116 | multStart <= 0; 117 | end 118 | end 119 | 120 | STATE_CALC_FN_TIMES_X: begin 121 | ready <= 0; 122 | multStart <= 0; 123 | X <= X; 124 | tmpX <= X; 125 | if (multComplete) begin 126 | f_n_times_X_plus_one <= f_n_times_X[0 +: (2*HALF_KEY_LENGTH)+e_WIDTH] + 1; 127 | divStart <= 1'b1; 128 | end 129 | else begin 130 | f_n_times_X_plus_one <= 0; 131 | divStart <= 0; 132 | end 133 | end 134 | 135 | STATE_DIV_BY_E: begin 136 | ready <= 0; 137 | divStart <= 0; 138 | tmpX <= tmpX; 139 | f_n_times_X_plus_one <= f_n_times_X_plus_one; 140 | if (next_state == STATE_CALC_FN_TIMES_X) begin 141 | X <= tmpX + 1'b1; 142 | multStart <= 1'b1; 143 | end 144 | else begin 145 | X <= X; 146 | multStart <= 0; 147 | end 148 | end 149 | 150 | STATE_READY: begin 151 | ready <= 1; 152 | multStart <= 0; 153 | divStart <= 0; 154 | X <= X; 155 | tmpX <= tmpX; 156 | f_n_times_X_plus_one <= f_n_times_X_plus_one; 157 | end 158 | 159 | default: begin 160 | ready <= 0; 161 | divStart <= 0; 162 | tmpX <= 1'b1; 163 | X <= 1'b1; 164 | f_n_times_X_plus_one <= 0; 165 | if (start) begin 166 | multStart <= 1'b1; 167 | end 168 | else begin 169 | multStart <= 0; 170 | end 171 | end 172 | endcase 173 | end 174 | 175 | wire [17-1:0] concatenatedX; 176 | assign concatenatedX[17-1:e_WIDTH] = {17-e_WIDTH{1'b0}}; //if e_WIDTH=17 then this line should be commented out 177 | assign concatenatedX[e_WIDTH-1:0] = X; 178 | 179 | mult_seq #(.a_width(17), .b_width(2*HALF_KEY_LENGTH), .num_cyc(17)) mult_seq ( 180 | .clk(clk), 181 | .rst_n(rst), 182 | .hold(1'b0), 183 | .start(multStart), 184 | .a(concatenatedX), 185 | .b(f_n), 186 | .complete(multComplete), 187 | .product(f_n_times_X) 188 | ); 189 | 190 | div_seq #(.a_width(((2*HALF_KEY_LENGTH)+e_WIDTH)+1), .b_width(e_WIDTH), .num_cyc(((2*HALF_KEY_LENGTH)+e_WIDTH)+1)) div_seq ( 191 | .clk(clk), 192 | .rst_n(rst), 193 | .hold(1'b0), 194 | .start(divStart), 195 | .a(f_n_times_X_plus_one), 196 | .b(e), 197 | .complete(divComplete), 198 | .divide_by_0(), 199 | .quotient(privateKey), 200 | .remainder(modResult) 201 | ); 202 | 203 | endmodule 204 | -------------------------------------------------------------------------------- /untrustedIC/modExp_UIC.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Modular exponentiation FSM // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Main FSM for modular exponentiation. Performs out = x^y mod m // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | module modExp_UIC #( 25 | parameter MONTGOMERY_MODULE_KEY_LENGTH = 512, 26 | parameter e_WIDTH = 3 27 | )( 28 | input clk, 29 | input rst, 30 | input [MONTGOMERY_MODULE_KEY_LENGTH-1:0] x, 31 | input [MONTGOMERY_MODULE_KEY_LENGTH-1+e_WIDTH:0] y, 32 | input [9:0] y_size, 33 | input [MONTGOMERY_MODULE_KEY_LENGTH-1:0] m, 34 | input start, 35 | output reg ready, 36 | output reg [MONTGOMERY_MODULE_KEY_LENGTH-1:0] out 37 | ); 38 | 39 | reg [15:0] rsa_top_x, rsa_top_y, rsa_top_m, rsa_top_r_c; 40 | wire [MONTGOMERY_MODULE_KEY_LENGTH-1:0] r_c_out_sig; 41 | wire [15:0] rsa_top_s; 42 | wire r_c_ready_sig, rsa_top__valid_out_sig; 43 | reg start_in_sig, valid_in_sig, load_done, unload_done, montgomery_r_c_rst; 44 | reg [31:0] load_unload_counter; 45 | 46 | rsa_top rsa_top ( 47 | .clk(clk), 48 | .reset(~rst), 49 | .valid_in(valid_in_sig), 50 | .start_in(start_in_sig), 51 | .x(rsa_top_x), 52 | .y(rsa_top_y), 53 | .m(rsa_top_m), 54 | .r_c(rsa_top_r_c), 55 | .s(rsa_top_s), 56 | .valid_out(rsa_top__valid_out_sig), 57 | .bit_size({{6{1'b0}},y_size}) 58 | ); 59 | 60 | montgomery_r_c #(.MONTGOMERY_MODULE_KEY_LENGTH(MONTGOMERY_MODULE_KEY_LENGTH)) montgomery_r_c ( 61 | .clk(clk), 62 | .rst(rst), 63 | .MOD(m), 64 | .start(start_in_sig), 65 | .r_c(r_c_out_sig), 66 | .ready(r_c_ready_sig) 67 | ); 68 | 69 | reg [2:0] state, next_state; 70 | localparam STATE_IDLE = 3'd0; 71 | localparam STATE_CALCULATE_R_C = 3'd1; 72 | localparam STATE_LOAD_VALUES = 3'd2; 73 | localparam STATE_CALCULATE_OUT = 3'd3; 74 | localparam STATE_UNLOAD_VALUES = 3'd4; 75 | localparam STATE_READY = 3'd5; 76 | 77 | always @(posedge clk) begin 78 | if (rst == 0) begin 79 | state <= STATE_IDLE; 80 | end 81 | else begin 82 | state <= next_state; 83 | end 84 | end 85 | 86 | always @(*) begin 87 | next_state = state; 88 | 89 | case (state) 90 | STATE_IDLE: begin 91 | if ( start ) begin 92 | next_state = STATE_CALCULATE_R_C; 93 | end 94 | end 95 | 96 | STATE_CALCULATE_R_C: begin 97 | if ( r_c_ready_sig ) begin 98 | next_state = STATE_LOAD_VALUES; 99 | end 100 | end 101 | 102 | STATE_LOAD_VALUES: begin 103 | if ( load_done ) begin 104 | next_state = STATE_CALCULATE_OUT; 105 | end 106 | end 107 | 108 | STATE_CALCULATE_OUT: begin 109 | next_state = STATE_UNLOAD_VALUES; 110 | end 111 | 112 | STATE_UNLOAD_VALUES: begin 113 | if ( unload_done ) begin 114 | next_state = STATE_READY; 115 | end 116 | end 117 | 118 | STATE_READY: begin 119 | next_state = STATE_IDLE; 120 | end 121 | 122 | default: begin 123 | if ( start ) begin 124 | next_state = STATE_CALCULATE_R_C; 125 | end 126 | end 127 | endcase 128 | end 129 | 130 | always @(posedge clk) begin 131 | 132 | case (state) 133 | STATE_IDLE: begin 134 | ready <= 0; 135 | valid_in_sig <= 0; 136 | out <= out; 137 | load_done <= 0; 138 | unload_done <= 0; 139 | load_unload_counter <= 0; 140 | rsa_top_x <= 0; 141 | rsa_top_y <= 0; 142 | rsa_top_r_c <= 0; 143 | rsa_top_m <= m[15:0]; 144 | 145 | if (start) begin 146 | start_in_sig <= 1'b1; 147 | end 148 | else begin 149 | start_in_sig <= 0; 150 | end 151 | end 152 | 153 | STATE_CALCULATE_R_C: begin 154 | start_in_sig <= 1'b0; 155 | rsa_top_m <= rsa_top_m; 156 | end 157 | 158 | STATE_LOAD_VALUES: begin 159 | valid_in_sig <= 1'b1; 160 | if (next_state == STATE_CALCULATE_OUT) begin 161 | valid_in_sig <= 0; 162 | end 163 | 164 | if (load_unload_counter == 31) begin 165 | load_done <= 1'b1; 166 | load_unload_counter <= load_unload_counter; 167 | end 168 | else begin 169 | load_done <= 0; 170 | load_unload_counter <= load_unload_counter+1'b1; 171 | end 172 | 173 | rsa_top_x <= x[(load_unload_counter*16) +: 16]; 174 | rsa_top_y <= y[(load_unload_counter*16) +: 16]; 175 | rsa_top_m <= m[(load_unload_counter*16) +: 16]; 176 | rsa_top_r_c <= r_c_out_sig[(load_unload_counter*16) +: 16]; 177 | end 178 | 179 | STATE_CALCULATE_OUT: begin 180 | load_done <= 0; 181 | load_unload_counter <= 0; 182 | end 183 | 184 | STATE_UNLOAD_VALUES: begin 185 | if ( rsa_top__valid_out_sig ) begin 186 | out[(load_unload_counter*16) +: 16] <= rsa_top_s; 187 | if (load_unload_counter == 31) begin 188 | unload_done <= 1'b1; 189 | load_unload_counter <= 0; 190 | end 191 | else begin 192 | unload_done <= 0; 193 | load_unload_counter <= load_unload_counter+1'b1; 194 | end 195 | end 196 | end 197 | 198 | STATE_READY: begin 199 | unload_done <= 0; 200 | ready <= 1'b1; 201 | end 202 | 203 | default: begin 204 | ready <= 0; 205 | valid_in_sig <= 0; 206 | out <= 0; 207 | load_done <= 0; 208 | unload_done <= 0; 209 | load_unload_counter <= 0; 210 | rsa_top_x <= 0; 211 | rsa_top_y <= 0; 212 | rsa_top_r_c <= 0; 213 | 214 | if (start) begin 215 | start_in_sig <= 1'b1; 216 | rsa_top_m <= m[15:0]; 217 | end 218 | else begin 219 | start_in_sig <= 0; 220 | rsa_top_m <= 0; 221 | end 222 | end 223 | endcase 224 | end 225 | 226 | endmodule -------------------------------------------------------------------------------- /trustedIC/modExp_TIC.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Modular exponentiation FSM // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Main FSM for modular exponentiation. Performs out = x^y mod m // 19 | // In the trusted IC it is required only for encryption, thus // 20 | // 'y' has a fixed width. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | `include "__timescale.v" 24 | `include "__parameters.vh" 25 | 26 | module modExp_TIC #( 27 | parameter MONTGOMERY_MODULE_KEY_LENGTH = 512, 28 | parameter e_WIDTH = 3 29 | )( 30 | input clk, 31 | input rst, 32 | input [MONTGOMERY_MODULE_KEY_LENGTH-1:0] x, 33 | input [e_WIDTH-1:0] y, 34 | input [MONTGOMERY_MODULE_KEY_LENGTH-1:0] m, 35 | input start, 36 | output reg ready, 37 | output reg [MONTGOMERY_MODULE_KEY_LENGTH-1:0] out 38 | ); 39 | 40 | reg [15:0] rsa_top_x, rsa_top_y, rsa_top_m, rsa_top_r_c; 41 | wire [MONTGOMERY_MODULE_KEY_LENGTH-1:0] r_c_out_sig; 42 | wire [15:0] rsa_top_s; 43 | wire r_c_ready_sig, rsa_top__valid_out_sig; 44 | reg start_in_sig, valid_in_sig, load_done, unload_done, montgomery_r_c_rst; 45 | reg [31:0] load_unload_counter; 46 | wire [4:0] y_size; 47 | 48 | assign y_size = e_WIDTH; 49 | 50 | rsa_top rsa_top ( 51 | .clk(clk), 52 | .reset(~rst), 53 | .valid_in(valid_in_sig), 54 | .start_in(start_in_sig), 55 | .x(rsa_top_x), 56 | .y(rsa_top_y), 57 | .m(rsa_top_m), 58 | .r_c(rsa_top_r_c), 59 | .s(rsa_top_s), 60 | .valid_out(rsa_top__valid_out_sig), 61 | .bit_size({{11{1'b0}},y_size}) 62 | ); 63 | 64 | montgomery_r_c #(.MONTGOMERY_MODULE_KEY_LENGTH(MONTGOMERY_MODULE_KEY_LENGTH)) montgomery_r_c ( 65 | .clk(clk), 66 | .rst(rst), 67 | .MOD(m), 68 | .start(start_in_sig), 69 | .r_c(r_c_out_sig), 70 | .ready(r_c_ready_sig) 71 | ); 72 | 73 | reg [2:0] state, next_state; 74 | localparam STATE_IDLE = 3'd0; 75 | localparam STATE_CALCULATE_R_C = 3'd1; 76 | localparam STATE_LOAD_VALUES = 3'd2; 77 | localparam STATE_CALCULATE_OUT = 3'd3; 78 | localparam STATE_UNLOAD_VALUES = 3'd4; 79 | localparam STATE_READY = 3'd5; 80 | 81 | always @(posedge clk) begin 82 | if (rst == 0) begin 83 | state <= STATE_IDLE; 84 | end 85 | else begin 86 | state <= next_state; 87 | end 88 | end 89 | 90 | always @(*) begin 91 | next_state = state; 92 | 93 | case (state) 94 | STATE_IDLE: begin 95 | if ( start ) begin 96 | next_state = STATE_CALCULATE_R_C; 97 | end 98 | end 99 | 100 | STATE_CALCULATE_R_C: begin 101 | if ( r_c_ready_sig ) begin 102 | next_state = STATE_LOAD_VALUES; 103 | end 104 | end 105 | 106 | STATE_LOAD_VALUES: begin 107 | if ( load_done ) begin 108 | next_state = STATE_CALCULATE_OUT; 109 | end 110 | end 111 | 112 | STATE_CALCULATE_OUT: begin 113 | next_state = STATE_UNLOAD_VALUES; 114 | end 115 | 116 | STATE_UNLOAD_VALUES: begin 117 | if ( unload_done ) begin 118 | next_state = STATE_READY; 119 | end 120 | end 121 | 122 | STATE_READY: begin 123 | next_state = STATE_IDLE; 124 | end 125 | 126 | default: begin 127 | if ( start ) begin 128 | next_state = STATE_CALCULATE_R_C; 129 | end 130 | end 131 | endcase 132 | end 133 | 134 | always @(posedge clk) begin 135 | 136 | case (state) 137 | STATE_IDLE: begin 138 | ready <= 0; 139 | valid_in_sig <= 0; 140 | out <= out; 141 | load_done <= 0; 142 | unload_done <= 0; 143 | load_unload_counter <= 0; 144 | rsa_top_x <= 0; 145 | rsa_top_y <= 0; 146 | rsa_top_r_c <= 0; 147 | rsa_top_m <= m[15:0]; 148 | 149 | if (start) begin 150 | start_in_sig <= 1'b1; 151 | end 152 | else begin 153 | start_in_sig <= 0; 154 | end 155 | end 156 | 157 | STATE_CALCULATE_R_C: begin 158 | start_in_sig <= 1'b0; 159 | rsa_top_m <= rsa_top_m; 160 | end 161 | 162 | STATE_LOAD_VALUES: begin 163 | valid_in_sig <= 1'b1; 164 | if (next_state == STATE_CALCULATE_OUT) begin 165 | valid_in_sig <= 0; 166 | end 167 | 168 | if (load_unload_counter == 31) begin 169 | load_done <= 1'b1; 170 | load_unload_counter <= load_unload_counter; 171 | end 172 | else begin 173 | load_done <= 0; 174 | load_unload_counter <= load_unload_counter+1'b1; 175 | end 176 | 177 | rsa_top_x <= x[(load_unload_counter*16) +: 16]; 178 | rsa_top_y <= y[(load_unload_counter*16) +: 16]; 179 | rsa_top_m <= m[(load_unload_counter*16) +: 16]; 180 | rsa_top_r_c <= r_c_out_sig[(load_unload_counter*16) +: 16]; 181 | end 182 | 183 | STATE_CALCULATE_OUT: begin 184 | load_done <= 0; 185 | load_unload_counter <= 0; 186 | end 187 | 188 | STATE_UNLOAD_VALUES: begin 189 | if ( rsa_top__valid_out_sig ) begin 190 | out[(load_unload_counter*16) +: 16] <= rsa_top_s; 191 | if (load_unload_counter == 31) begin 192 | unload_done <= 1'b1; 193 | load_unload_counter <= 0; 194 | end 195 | else begin 196 | unload_done <= 0; 197 | load_unload_counter <= load_unload_counter+1'b1; 198 | end 199 | end 200 | end 201 | 202 | STATE_READY: begin 203 | unload_done <= 0; 204 | ready <= 1'b1; 205 | end 206 | 207 | default: begin 208 | ready <= 0; 209 | valid_in_sig <= 0; 210 | out <= 0; 211 | load_done <= 0; 212 | unload_done <= 0; 213 | load_unload_counter <= 0; 214 | rsa_top_x <= 0; 215 | rsa_top_y <= 0; 216 | rsa_top_r_c <= 0; 217 | 218 | if (start) begin 219 | start_in_sig <= 1'b1; 220 | rsa_top_m <= m[15:0]; 221 | end 222 | else begin 223 | start_in_sig <= 0; 224 | rsa_top_m <= 0; 225 | end 226 | end 227 | endcase 228 | end 229 | 230 | endmodule -------------------------------------------------------------------------------- /Apache_2.0.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | ============== 3 | 4 | _Version 2.0, January 2004_ 5 | _<>_ 6 | 7 | ### Terms and Conditions for use, reproduction, and distribution 8 | 9 | #### 1. Definitions 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, and 12 | distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 15 | owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all other entities 18 | that control, are controlled by, or are under common control with that entity. 19 | For the purposes of this definition, "control" means **(i)** the power, direct or 20 | indirect, to cause the direction or management of such entity, whether by 21 | contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the 22 | outstanding shares, or **(iii)** beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity exercising 25 | permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, including 28 | but not limited to software source code, documentation source, and configuration 29 | files. 30 | 31 | "Object" form shall mean any form resulting from mechanical transformation or 32 | translation of a Source form, including but not limited to compiled object code, 33 | generated documentation, and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or Object form, made 36 | available under the License, as indicated by a copyright notice that is included 37 | in or attached to the work (an example is provided in the Appendix below). 38 | 39 | "Derivative Works" shall mean any work, whether in Source or Object form, that 40 | is based on (or derived from) the Work and for which the editorial revisions, 41 | annotations, elaborations, or other modifications represent, as a whole, an 42 | original work of authorship. For the purposes of this License, Derivative Works 43 | shall not include works that remain separable from, or merely link (or bind by 44 | name) to the interfaces of, the Work and Derivative Works thereof. 45 | 46 | "Contribution" shall mean any work of authorship, including the original version 47 | of the Work and any modifications or additions to that Work or Derivative Works 48 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 49 | by the copyright owner or by an individual or Legal Entity authorized to submit 50 | on behalf of the copyright owner. For the purposes of this definition, 51 | "submitted" means any form of electronic, verbal, or written communication sent 52 | to the Licensor or its representatives, including but not limited to 53 | communication on electronic mailing lists, source code control systems, and 54 | issue tracking systems that are managed by, or on behalf of, the Licensor for 55 | the purpose of discussing and improving the Work, but excluding communication 56 | that is conspicuously marked or otherwise designated in writing by the copyright 57 | owner as "Not a Contribution." 58 | 59 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 60 | of whom a Contribution has been received by Licensor and subsequently 61 | incorporated within the Work. 62 | 63 | #### 2. Grant of Copyright License 64 | 65 | Subject to the terms and conditions of this License, each Contributor hereby 66 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 67 | irrevocable copyright license to reproduce, prepare Derivative Works of, 68 | publicly display, publicly perform, sublicense, and distribute the Work and such 69 | Derivative Works in Source or Object form. 70 | 71 | #### 3. Grant of Patent License 72 | 73 | Subject to the terms and conditions of this License, each Contributor hereby 74 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 75 | irrevocable (except as stated in this section) patent license to make, have 76 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 77 | such license applies only to those patent claims licensable by such Contributor 78 | that are necessarily infringed by their Contribution(s) alone or by combination 79 | of their Contribution(s) with the Work to which such Contribution(s) was 80 | submitted. If You institute patent litigation against any entity (including a 81 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 82 | Contribution incorporated within the Work constitutes direct or contributory 83 | patent infringement, then any patent licenses granted to You under this License 84 | for that Work shall terminate as of the date such litigation is filed. 85 | 86 | #### 4. Redistribution 87 | 88 | You may reproduce and distribute copies of the Work or Derivative Works thereof 89 | in any medium, with or without modifications, and in Source or Object form, 90 | provided that You meet the following conditions: 91 | 92 | * **(a)** You must give any other recipients of the Work or Derivative Works a copy of 93 | this License; and 94 | * **(b)** You must cause any modified files to carry prominent notices stating that You 95 | changed the files; and 96 | * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, 97 | all copyright, patent, trademark, and attribution notices from the Source form 98 | of the Work, excluding those notices that do not pertain to any part of the 99 | Derivative Works; and 100 | * **(d)** If the Work includes a "NOTICE" text file as part of its distribution, then any 101 | Derivative Works that You distribute must include a readable copy of the 102 | attribution notices contained within such NOTICE file, excluding those notices 103 | that do not pertain to any part of the Derivative Works, in at least one of the 104 | following places: within a NOTICE text file distributed as part of the 105 | Derivative Works; within the Source form or documentation, if provided along 106 | with the Derivative Works; or, within a display generated by the Derivative 107 | Works, if and wherever such third-party notices normally appear. The contents of 108 | the NOTICE file are for informational purposes only and do not modify the 109 | License. You may add Your own attribution notices within Derivative Works that 110 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 111 | provided that such additional attribution notices cannot be construed as 112 | modifying the License. 113 | 114 | You may add Your own copyright statement to Your modifications and may provide 115 | additional or different license terms and conditions for use, reproduction, or 116 | distribution of Your modifications, or for any such Derivative Works as a whole, 117 | provided Your use, reproduction, and distribution of the Work otherwise complies 118 | with the conditions stated in this License. 119 | 120 | #### 5. Submission of Contributions 121 | 122 | Unless You explicitly state otherwise, any Contribution intentionally submitted 123 | for inclusion in the Work by You to the Licensor shall be under the terms and 124 | conditions of this License, without any additional terms or conditions. 125 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 126 | any separate license agreement you may have executed with Licensor regarding 127 | such Contributions. 128 | 129 | #### 6. Trademarks 130 | 131 | This License does not grant permission to use the trade names, trademarks, 132 | service marks, or product names of the Licensor, except as required for 133 | reasonable and customary use in describing the origin of the Work and 134 | reproducing the content of the NOTICE file. 135 | 136 | #### 7. Disclaimer of Warranty 137 | 138 | Unless required by applicable law or agreed to in writing, Licensor provides the 139 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 140 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 141 | including, without limitation, any warranties or conditions of TITLE, 142 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 143 | solely responsible for determining the appropriateness of using or 144 | redistributing the Work and assume any risks associated with Your exercise of 145 | permissions under this License. 146 | 147 | #### 8. Limitation of Liability 148 | 149 | In no event and under no legal theory, whether in tort (including negligence), 150 | contract, or otherwise, unless required by applicable law (such as deliberate 151 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 152 | liable to You for damages, including any direct, indirect, special, incidental, 153 | or consequential damages of any character arising as a result of this License or 154 | out of the use or inability to use the Work (including but not limited to 155 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 156 | any and all other commercial damages or losses), even if such Contributor has 157 | been advised of the possibility of such damages. 158 | 159 | #### 9. Accepting Warranty or Additional Liability 160 | 161 | While redistributing the Work or Derivative Works thereof, You may choose to 162 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 163 | other liability obligations and/or rights consistent with this License. However, 164 | in accepting such obligations, You may act only on Your own behalf and on Your 165 | sole responsibility, not on behalf of any other Contributor, and only if You 166 | agree to indemnify, defend, and hold each Contributor harmless for any liability 167 | incurred by, or claims asserted against, such Contributor by reason of your 168 | accepting any such warranty or additional liability. 169 | 170 | END OF TERMS AND CONDITIONS 171 | 172 | ### APPENDIX: How to apply the Apache License to your work 173 | 174 | To apply the Apache License to your work, attach the following boilerplate 175 | notice, with the fields enclosed by brackets `[]` replaced with your own 176 | identifying information. (Don't include the brackets!) The text should be 177 | enclosed in the appropriate comment syntax for the file format. We also 178 | recommend that a file or class name and description of purpose be included on 179 | the same "printed page" as the copyright notice for easier identification within 180 | third-party archives. 181 | 182 | Copyright [yyyy] [name of copyright owner] 183 | 184 | Licensed under the Apache License, Version 2.0 (the "License"); 185 | you may not use this file except in compliance with the License. 186 | You may obtain a copy of the License at 187 | 188 | http://www.apache.org/licenses/LICENSE-2.0 189 | 190 | Unless required by applicable law or agreed to in writing, software 191 | distributed under the License is distributed on an "AS IS" BASIS, 192 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 193 | See the License for the specific language governing permissions and 194 | limitations under the License. 195 | 196 | -------------------------------------------------------------------------------- /untrustedIC/cryptoKeyPairGen.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Crypto key pair generator // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Top level module of the RSA key pair generation mechanism. // 19 | // When 'ready' output gets high, 'MOD' holds the modulus (n) // 20 | // and 'privateKey' holds the modular multiplicative inverse of // 21 | // e(mod f(n)), which is the private key. // 22 | /////////////////////////////////////////////////////////////////////////////////// 23 | 24 | `include "__timescale.v" 25 | `include "__parameters.vh" 26 | 27 | 28 | module cryptoKeyPairGen #( 29 | parameter KEY_LENGTH = 32, 30 | parameter integer HALF_KEY_LENGTH = 0.5 * KEY_LENGTH, 31 | parameter e_WIDTH = 3 // set minimum of 3 32 | )( 33 | input clk, 34 | input rst, 35 | input [(8*KEY_LENGTH)-1 : 0] noisyIn, // 16*HALF_KEY_LENGTH 36 | input [e_WIDTH-1:0] e, 37 | input modExp_ready, 38 | input [511:0] modExp_out, 39 | output modExp_rst, 40 | output [511:0] modExp_x, 41 | output [511+e_WIDTH:0] modExp_y, 42 | output [9:0] modExp_y_size, 43 | output [511:0] modExp_m, 44 | output modExp_start, 45 | output reg ready, 46 | output reg [KEY_LENGTH-1:0] MOD, 47 | output reg [KEY_LENGTH+e_WIDTH:0] privateKey 48 | ); 49 | 50 | wire [HALF_KEY_LENGTH-1:0] prime; 51 | reg [HALF_KEY_LENGTH-1:0] p1_sig, p2_sig; 52 | wire [KEY_LENGTH+e_WIDTH:0] privateKey_sig; 53 | wire newPrimeReady; 54 | reg primesReady; 55 | reg GCDStart; 56 | wire GCDReady; 57 | wire [KEY_LENGTH-1:0] GCDMODOut; 58 | wire [KEY_LENGTH-1:0] GCDF_nOut; 59 | reg [KEY_LENGTH-1:0] f_n_sig; 60 | reg privateKeyGenStart; 61 | wire privateKeyGenReady; 62 | wire primesValid_sig; 63 | reg noiseFilter_rst; 64 | reg primeGen_rst; 65 | reg GCD_rst; 66 | reg privateKeyGen_rst; 67 | wire [HALF_KEY_LENGTH-1:0] noiseFilterOut; 68 | wire noiseFilterReady; 69 | 70 | noiseFilter #(.HALF_KEY_LENGTH(HALF_KEY_LENGTH)) noiseFilter ( 71 | .clk(clk), 72 | .rst(noiseFilter_rst), 73 | .in(noisyIn), 74 | .out(noiseFilterOut), 75 | .ready(noiseFilterReady) 76 | ); 77 | 78 | primeGen #(.KEY_LENGTH(KEY_LENGTH), .e_WIDTH(e_WIDTH)) primeGen ( 79 | .clk(clk), 80 | .rst(primeGen_rst), 81 | .seed(noiseFilterOut), 82 | .modExp_ready(modExp_ready), 83 | .modExp_out(modExp_out), 84 | .modExp_rst(modExp_rst), 85 | .modExp_x(modExp_x), 86 | .modExp_y(modExp_y), 87 | .modExp_y_size(modExp_y_size), 88 | .modExp_m(modExp_m), 89 | .modExp_start(modExp_start), 90 | .prime(prime), 91 | .ready(newPrimeReady) 92 | ); 93 | 94 | GCD #(.HALF_KEY_LENGTH(HALF_KEY_LENGTH), .e_WIDTH(e_WIDTH)) GCD ( 95 | .clk(clk), 96 | .rst(GCD_rst), 97 | .p1(p1_sig), 98 | .p2(p2_sig), 99 | .e(e), 100 | .start(GCDStart), 101 | .areValid(primesValid_sig), 102 | .MOD(GCDMODOut), 103 | .f_n(GCDF_nOut), 104 | .ready(GCDReady) 105 | ); 106 | 107 | privateKeyGen #(.HALF_KEY_LENGTH(HALF_KEY_LENGTH), .e_WIDTH(e_WIDTH)) privateKeyGen ( 108 | .clk(clk), 109 | .rst(privateKeyGen_rst), 110 | .f_n(f_n_sig), 111 | .e(e), 112 | .start(privateKeyGenStart), 113 | .ready(privateKeyGenReady), 114 | .privateKey(privateKey_sig) 115 | ); 116 | 117 | reg [2:0] state, next_state; 118 | localparam STATE_OFF = 3'd0; 119 | localparam STATE_NOISE_FILTER = 3'd1; 120 | localparam STATE_PRIME_GENERATOR = 3'd2; 121 | localparam STATE_GCD = 3'd3; 122 | localparam STATE_PRIVATE_KEY_GENERATOR = 3'd4; 123 | localparam STATE_READY = 3'd5; 124 | 125 | always @(posedge clk) begin 126 | if (rst == 0) begin 127 | state <= STATE_OFF; 128 | end 129 | else begin 130 | state <= next_state; 131 | end 132 | end 133 | 134 | always @(*) begin 135 | next_state = state; 136 | 137 | case (state) 138 | STATE_OFF: begin 139 | next_state = STATE_NOISE_FILTER; 140 | end 141 | 142 | STATE_NOISE_FILTER: begin 143 | if ( noiseFilterReady ) begin 144 | next_state = STATE_PRIME_GENERATOR; 145 | end 146 | end 147 | 148 | STATE_PRIME_GENERATOR: begin 149 | if ( primesReady ) begin 150 | next_state = STATE_GCD; 151 | end 152 | end 153 | 154 | STATE_GCD: begin 155 | if (GCDReady) begin 156 | if (primesValid_sig) begin 157 | next_state = STATE_PRIVATE_KEY_GENERATOR; 158 | end 159 | else begin 160 | next_state = STATE_PRIME_GENERATOR; 161 | end 162 | end 163 | end 164 | 165 | STATE_PRIVATE_KEY_GENERATOR: begin 166 | if (privateKeyGenReady) begin 167 | next_state = STATE_READY; 168 | end 169 | end 170 | 171 | STATE_READY: begin 172 | 173 | end 174 | 175 | default: begin 176 | next_state = STATE_NOISE_FILTER; 177 | end 178 | endcase 179 | end 180 | 181 | always @(posedge clk) begin 182 | case (state) 183 | STATE_OFF: begin 184 | ready <= 0; 185 | MOD <= 0; 186 | privateKey <= 0; 187 | 188 | p1_sig <= 0; 189 | p2_sig <= 0; 190 | primesReady <= 0; 191 | GCDStart <= 0; 192 | privateKeyGenStart <= 0; 193 | f_n_sig <= 0; 194 | 195 | noiseFilter_rst <= 0; 196 | primeGen_rst <= 0; 197 | GCD_rst <= 0; 198 | privateKeyGen_rst <= 0; 199 | end 200 | 201 | STATE_NOISE_FILTER: begin 202 | ready <= 0; 203 | MOD <= 0; 204 | privateKey <= 0; 205 | 206 | p1_sig <= 0; 207 | p2_sig <= 0; 208 | primesReady <= 0; 209 | GCDStart <= 0; 210 | privateKeyGenStart <= 0; 211 | f_n_sig <= 0; 212 | 213 | noiseFilter_rst <= 1'b1; 214 | primeGen_rst <= 0; 215 | GCD_rst <= 0; 216 | privateKeyGen_rst <= 0; 217 | end 218 | 219 | STATE_PRIME_GENERATOR: begin 220 | if (newPrimeReady) begin 221 | p1_sig <= prime; 222 | p2_sig <= p1_sig; 223 | if (|p1_sig) begin 224 | primesReady <= 1'b1; 225 | end 226 | else begin 227 | primesReady <= primesReady; 228 | end 229 | end 230 | else begin 231 | p1_sig <= p1_sig; 232 | p2_sig <= p2_sig; 233 | primesReady <= 0; 234 | end 235 | 236 | if (next_state == STATE_GCD) begin 237 | GCDStart <= 1'b1; 238 | GCD_rst <= 1'b1; 239 | end 240 | else begin 241 | GCDStart <= 0; 242 | GCD_rst <= 0; 243 | end 244 | 245 | ready <= 0; 246 | MOD <= 0; 247 | privateKey <= 0; 248 | 249 | privateKeyGenStart <= 0; 250 | f_n_sig <= 0; 251 | 252 | noiseFilter_rst <= 1'b1; 253 | primeGen_rst <= 1'b1; 254 | privateKeyGen_rst <= 0; 255 | end 256 | 257 | STATE_GCD: begin 258 | ready <= 0; 259 | MOD <= GCDMODOut; 260 | privateKey <= 0; 261 | 262 | p1_sig <= p1_sig; 263 | p2_sig <= p2_sig; 264 | primesReady <= primesReady; 265 | GCDStart <= 0; 266 | f_n_sig <= GCDF_nOut; 267 | 268 | noiseFilter_rst <= 1'b1; 269 | primeGen_rst <= 1'b1; 270 | GCD_rst <= 1'b1; 271 | 272 | if (next_state == STATE_PRIVATE_KEY_GENERATOR) begin 273 | privateKeyGenStart <= 1'b1; 274 | privateKeyGen_rst <= 1'b1; 275 | end 276 | else begin 277 | privateKeyGenStart <= 0; 278 | privateKeyGen_rst <= 0; 279 | end 280 | end 281 | 282 | STATE_PRIVATE_KEY_GENERATOR: begin 283 | ready <= 0; 284 | MOD <= MOD; 285 | privateKey <= privateKey_sig; 286 | 287 | p1_sig <= 0; 288 | p2_sig <= 0; 289 | primesReady <= 0; 290 | GCDStart <= 0; 291 | privateKeyGenStart <= 0; 292 | f_n_sig <= f_n_sig; 293 | 294 | noiseFilter_rst <= 0; 295 | primeGen_rst <= 0; 296 | GCD_rst <= 1'b1; 297 | privateKeyGen_rst <= 1'b1; 298 | end 299 | 300 | STATE_READY: begin 301 | ready <= 1'b1; 302 | MOD <= MOD; 303 | privateKey <= privateKey; 304 | 305 | p1_sig <= 0; 306 | p2_sig <= 0; 307 | primesReady <= 0; 308 | GCDStart <= 0; 309 | privateKeyGenStart <= 0; 310 | f_n_sig <= 0; 311 | 312 | noiseFilter_rst <= 0; 313 | primeGen_rst <= 0; 314 | GCD_rst <= 0; 315 | privateKeyGen_rst <= 0; 316 | end 317 | 318 | default: begin 319 | ready <= 0; 320 | MOD <= 0; 321 | privateKey <= 0; 322 | 323 | p1_sig <= 0; 324 | p2_sig <= 0; 325 | primesReady <= 0; 326 | GCDStart <= 0; 327 | privateKeyGenStart <= 0; 328 | f_n_sig <= 0; 329 | 330 | noiseFilter_rst <= 0; 331 | primeGen_rst <= 0; 332 | GCD_rst <= 0; 333 | privateKeyGen_rst <= 0; 334 | end 335 | endcase 336 | end 337 | 338 | endmodule 339 | -------------------------------------------------------------------------------- /untrustedIC/top.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Top level module // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Top level module of the untrusted IC. // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | 25 | module top_untrustedIC #( 26 | parameter KEY_LENGTH = 512, 27 | parameter integer e_WIDTH = 3 // set minimum of 3 28 | )( 29 | input clk, 30 | input rst, 31 | input [(8*KEY_LENGTH)-1:0] cryptoKeyPairGen_noisyIn, 32 | input SPI_MISO, 33 | output SPI_SCLK, 34 | output SPI_MOSI 35 | ); 36 | 37 | wire modExp_rst, cryptoKeyPairGen_modExp_rst, modExp_start, cryptoKeyPairGen_modExp_start, modExp_ready, cryptoKeyPairGen_modExp_ready; 38 | reg decrypt_modExp_rst, decryptionStart; 39 | wire [511:0] modExp_x, cryptoKeyPairGen_modExp_x, modExp_m, cryptoKeyPairGen_modExp_m, modExp_out, cryptoKeyPairGen_modExp_out; 40 | wire [511+e_WIDTH:0] modExp_y, cryptoKeyPairGen_modExp_y; 41 | wire [9:0] modExp_y_size, cryptoKeyPairGen_modExp_y_size; 42 | wire [KEY_LENGTH-1 : 0] publicKey, encryptedIn; 43 | reg [KEY_LENGTH-1 : 0] SPIMaster_dataToSend; 44 | 45 | reg dataArrived, dataArrived_delayed; // edge triggered logic 46 | reg SPIMaster_start; 47 | wire cryptoKeyPairGen_ready; 48 | wire [KEY_LENGTH+e_WIDTH:0] privateKey; 49 | 50 | localparam integer SCLK_PERIOD_AS_CLK_MULTIPLE = 10; 51 | localparam SPI_counter_WIDTH = $clog2((KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2); 52 | reg [SPI_counter_WIDTH-1:0] SPI_counter; 53 | 54 | wire [e_WIDTH-1:0] publicExponent; 55 | 56 | cryptoKeyPairGen #(.KEY_LENGTH(KEY_LENGTH), .e_WIDTH(e_WIDTH)) cryptoKeyPairGen ( 57 | .clk(clk), 58 | .rst(rst), 59 | .noisyIn(cryptoKeyPairGen_noisyIn), 60 | .e(publicExponent), 61 | .modExp_ready(cryptoKeyPairGen_modExp_ready), 62 | .modExp_out(cryptoKeyPairGen_modExp_out), 63 | .modExp_rst(cryptoKeyPairGen_modExp_rst), 64 | .modExp_x(cryptoKeyPairGen_modExp_x), 65 | .modExp_y(cryptoKeyPairGen_modExp_y), 66 | .modExp_y_size(cryptoKeyPairGen_modExp_y_size), 67 | .modExp_m(cryptoKeyPairGen_modExp_m), 68 | .modExp_start(cryptoKeyPairGen_modExp_start), 69 | .ready(cryptoKeyPairGen_ready), 70 | .MOD(publicKey), 71 | .privateKey(privateKey) 72 | ); 73 | 74 | modExp_UIC #(.MONTGOMERY_MODULE_KEY_LENGTH(512), .e_WIDTH(e_WIDTH)) modExp_UIC ( // designed to work only for 512 75 | .clk(clk), 76 | .rst(modExp_rst), 77 | .x(modExp_x), 78 | .y(modExp_y), 79 | .y_size(modExp_y_size), 80 | .m(modExp_m), 81 | .start(modExp_start), 82 | .ready(modExp_ready), 83 | .out(modExp_out) 84 | ); 85 | 86 | SPIMaster #(.KEY_LENGTH(KEY_LENGTH), .SCLK_PERIOD_AS_CLK_MULTIPLE(SCLK_PERIOD_AS_CLK_MULTIPLE)) SPIMaster ( 87 | .clk(clk), 88 | .rst(rst), 89 | .dataToSend(SPIMaster_dataToSend), 90 | .start(SPIMaster_start), 91 | .MISO(SPI_MISO), 92 | .SCLK(SPI_SCLK), 93 | .MOSI(SPI_MOSI), 94 | .dataReceived(encryptedIn) 95 | ); 96 | 97 | 98 | assign publicExponent = 3'b011; 99 | // assign publicExponent[e_WIDTH-1:0] = 'b10000000000000001; // we can choose a small e, such as 3, to reduce the exponentiation 100 | // effort for encryption/decryption at later stages. However the search 101 | // space for finding correct primes will increase and we have to try 102 | // several prime pairs in order to find a valid pair (f_n % e != 0). 103 | 104 | // SPI receive 105 | always @(posedge clk) begin // make request signals posedge triggered 106 | if (!rst) begin 107 | dataArrived <= 0; 108 | dataArrived_delayed <= 0; 109 | end 110 | else begin 111 | dataArrived_delayed <= dataArrived; 112 | if (SPI_MISO == 1'b1) begin 113 | dataArrived <= 1'b1; 114 | end 115 | else begin 116 | dataArrived <= 0; 117 | end 118 | end 119 | end 120 | // end of SPI receive 121 | 122 | reg [2:0] state, next_state; 123 | localparam STATE_IDLE = 3'd0; 124 | localparam STATE_CRYPTO_KEY_GEN = 3'd1; 125 | localparam STATE_READY = 3'd2; 126 | localparam STATE_DECRYPT = 3'd3; 127 | 128 | always @(*) begin 129 | case (state) 130 | STATE_CRYPTO_KEY_GEN: begin 131 | SPIMaster_dataToSend = publicKey; 132 | end 133 | 134 | STATE_DECRYPT: begin 135 | SPIMaster_dataToSend = modExp_out; 136 | end 137 | 138 | default: begin 139 | SPIMaster_dataToSend = 0; 140 | end 141 | endcase 142 | end 143 | 144 | always @(posedge clk) begin 145 | if (!rst) begin 146 | state <= STATE_IDLE; 147 | end 148 | else begin 149 | state <= next_state; 150 | end 151 | end 152 | 153 | always @(*) begin 154 | next_state = state; 155 | 156 | case (state) 157 | STATE_IDLE: begin 158 | next_state = STATE_CRYPTO_KEY_GEN; 159 | end 160 | 161 | STATE_CRYPTO_KEY_GEN: begin 162 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 163 | next_state = STATE_READY; 164 | end 165 | end 166 | 167 | STATE_READY: begin 168 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 169 | next_state = STATE_DECRYPT; 170 | end 171 | end 172 | 173 | STATE_DECRYPT: begin 174 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 175 | next_state = STATE_READY; 176 | end 177 | end 178 | 179 | default: begin 180 | next_state = STATE_CRYPTO_KEY_GEN; 181 | end 182 | endcase 183 | end 184 | 185 | always @(posedge clk) begin 186 | 187 | case (state) 188 | STATE_IDLE: begin 189 | decrypt_modExp_rst <= 0; 190 | decryptionStart <= 0; 191 | SPIMaster_start <= 0; 192 | SPI_counter <= 0; 193 | end 194 | 195 | STATE_CRYPTO_KEY_GEN: begin 196 | decrypt_modExp_rst <= 0; 197 | decryptionStart <= 0; 198 | if (cryptoKeyPairGen_ready) begin 199 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 200 | SPIMaster_start <= 1'b0; 201 | SPI_counter <= 0; 202 | end 203 | else begin 204 | SPIMaster_start <= 1'b1; 205 | SPI_counter <= SPI_counter + 1'b1; 206 | end 207 | end 208 | else begin 209 | SPIMaster_start <= 0; 210 | SPI_counter <= 0; 211 | end 212 | end 213 | 214 | STATE_READY: begin 215 | decrypt_modExp_rst <= 1'b1; 216 | decryptionStart <= 0; 217 | if (dataArrived && !dataArrived_delayed) begin 218 | SPIMaster_start <= 1'b1; 219 | end 220 | else begin 221 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 222 | SPIMaster_start <= 0; 223 | end 224 | else begin 225 | SPIMaster_start <= SPIMaster_start; 226 | end 227 | end 228 | 229 | if (SPIMaster_start) begin 230 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 231 | SPI_counter <= 0; 232 | decryptionStart <= 1'b1; 233 | end 234 | else begin 235 | SPI_counter <= SPI_counter + 1'b1; 236 | decryptionStart <= 0; 237 | end 238 | end 239 | end 240 | 241 | STATE_DECRYPT: begin 242 | decrypt_modExp_rst <= 1'b1; 243 | decryptionStart <= 0; 244 | if (modExp_ready) begin 245 | SPIMaster_start <= 1'b1; 246 | end 247 | else begin 248 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 249 | SPIMaster_start <= 0; 250 | end 251 | else begin 252 | SPIMaster_start <= SPIMaster_start; 253 | end 254 | end 255 | 256 | if (SPIMaster_start) begin 257 | if (SPI_counter == (KEY_LENGTH+1) * SCLK_PERIOD_AS_CLK_MULTIPLE + 2) begin 258 | SPI_counter <= 0; 259 | end 260 | else begin 261 | SPI_counter <= SPI_counter + 1'b1; 262 | end 263 | end 264 | end 265 | 266 | default: begin 267 | decrypt_modExp_rst <= 0; 268 | decryptionStart <= 0; 269 | SPIMaster_start <= 0; 270 | SPI_counter <= 0; 271 | end 272 | endcase 273 | end 274 | 275 | localparam [9:0] MODEXP_Y_SIZE = KEY_LENGTH+e_WIDTH; 276 | 277 | assign modExp_rst = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_rst : decrypt_modExp_rst; 278 | assign modExp_x = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_x : encryptedIn; 279 | assign modExp_y = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_y : privateKey; 280 | assign modExp_y_size = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_y_size : MODEXP_Y_SIZE; 281 | assign modExp_m = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_m : publicKey; 282 | assign modExp_start = (state == STATE_CRYPTO_KEY_GEN) ? cryptoKeyPairGen_modExp_start : decryptionStart; 283 | assign cryptoKeyPairGen_modExp_ready = (state == STATE_CRYPTO_KEY_GEN) ? modExp_ready : 0; 284 | assign cryptoKeyPairGen_modExp_out = (state == STATE_CRYPTO_KEY_GEN) ? modExp_out : 0; 285 | 286 | endmodule 287 | -------------------------------------------------------------------------------- /trustedIC/top.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Top level module // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Top level module of the trusted IC. // 19 | /////////////////////////////////////////////////////////////////////////////////// 20 | 21 | `include "__timescale.v" 22 | `include "__parameters.vh" 23 | 24 | 25 | module top_trustedIC #( 26 | parameter KEY_LENGTH = 512, 27 | parameter e_WIDTH = 3 28 | )( 29 | input clk, 30 | input rst, 31 | input SPI_SCLK, 32 | input SPI_MOSI, 33 | output SPI_MISO 34 | ); 35 | 36 | reg readPK_ready, challengeGen_pause, modExp_rst, modExp_start, SPI_send, SPI_dataReceived_ready_buf, SPI_dataReceived_ready_delayed, sent_done; 37 | reg [511:0] modExp_x, modExp_m; 38 | reg [e_WIDTH-1:0] modExp_y; 39 | wire [511:0] modExp_out; 40 | reg [KEY_LENGTH-1:0] SPI_dataToSend, publicKeyReceived, challenge; 41 | wire SPI_dataReceived_ready, SPI_dataReceived_ready_sync_pulse, modExp_ready; 42 | wire [KEY_LENGTH-1:0] storedPK, SPI_dataReceived, challengeGen_out; 43 | 44 | wire [e_WIDTH-1:0] publicExponent; 45 | 46 | challengeGen #(.CHALLENGE_LENGTH(KEY_LENGTH)) challengeGen ( 47 | .clk(clk), 48 | .rst(rst), 49 | .pause(challengeGen_pause), 50 | .out(challengeGen_out) 51 | ); 52 | 53 | SPISlave #(.KEY_LENGTH(KEY_LENGTH)) SPISlave ( 54 | .clk(clk), 55 | .rst(rst), 56 | .dataToSend(SPI_dataToSend), 57 | .send(SPI_send), 58 | .MOSI(SPI_MOSI), 59 | .SCLK(SPI_SCLK), 60 | .MISO(SPI_MISO), 61 | .dataReceived(SPI_dataReceived), 62 | .dataReceived_ready(SPI_dataReceived_ready) 63 | ); 64 | 65 | modExp_TIC #(.MONTGOMERY_MODULE_KEY_LENGTH(512), .e_WIDTH(e_WIDTH)) modExp_TIC ( // designed to work only for 512 66 | .clk(clk), 67 | .rst(modExp_rst), 68 | .x(modExp_x), 69 | .y(modExp_y), 70 | .m(modExp_m), 71 | .start(modExp_start), 72 | .ready(modExp_ready), 73 | .out(modExp_out) 74 | ); 75 | 76 | // set stored public key with 'assign' for simulations; a one-time programmable non volatile memory should be considered in implementation. 77 | assign storedPK = 512'ha6653a5134cbc8421844d78b27c226206c6e7e77cadd58d9123bb5d2f09599e5a21b1199295eeaa53a9e47a3db992c0142e550f54e6fad2d8859d9307047d97b; // 512 bit 78 | // assign storedPK = 32'h67b98cd1; //32 bit 79 | assign publicExponent = 3'b011; 80 | 81 | assign SPI_dataReceived_ready_sync_pulse = SPI_dataReceived_ready_buf && !SPI_dataReceived_ready_delayed; 82 | 83 | reg [3:0] state, next_state; 84 | localparam STATE_IDLE = 4'd0; 85 | localparam STATE_READ_STORED_PK = 4'd1; 86 | localparam STATE_READY = 4'd2; 87 | localparam STATE_COMPARE_RECEIVED_PK = 4'd3; 88 | localparam STATE_ENCRYPT_CHALLENGE = 4'd4; 89 | localparam STATE_SEND_CHALLENGE = 4'd5; 90 | localparam STATE_COMPARE_RESPONSE = 4'd6; 91 | localparam STATE_LOCK = 4'd7; 92 | localparam STATE_AUTHENTICATED = 4'd8; 93 | localparam STATE_RESERVED = 4'd9; 94 | 95 | always @(posedge clk) begin 96 | if (!rst) begin 97 | readPK_ready = 1'b1; 98 | SPI_dataReceived_ready_buf <= 0; 99 | SPI_dataReceived_ready_delayed = 0; 100 | end 101 | else begin 102 | readPK_ready = 1'b1; 103 | SPI_dataReceived_ready_buf <= SPI_dataReceived_ready; 104 | SPI_dataReceived_ready_delayed = SPI_dataReceived_ready_buf; 105 | end 106 | end 107 | 108 | always @(posedge clk) begin 109 | if (!rst) begin 110 | state <= STATE_IDLE; 111 | end 112 | else begin 113 | state <= next_state; 114 | end 115 | end 116 | 117 | always @(*) begin 118 | next_state = state; 119 | 120 | case (state) 121 | STATE_IDLE: begin 122 | next_state = STATE_READ_STORED_PK; 123 | end 124 | 125 | STATE_READ_STORED_PK: begin 126 | if (readPK_ready) begin 127 | next_state = STATE_READY; 128 | end 129 | end 130 | 131 | STATE_READY: begin 132 | if (SPI_dataReceived_ready) begin 133 | next_state = STATE_COMPARE_RECEIVED_PK; 134 | end 135 | end 136 | 137 | STATE_COMPARE_RECEIVED_PK: begin 138 | if (SPI_dataReceived == storedPK) begin 139 | next_state = STATE_ENCRYPT_CHALLENGE; 140 | end 141 | else begin 142 | next_state = STATE_LOCK; 143 | end 144 | end 145 | 146 | STATE_ENCRYPT_CHALLENGE: begin 147 | if (modExp_ready) begin 148 | next_state = STATE_SEND_CHALLENGE; 149 | end 150 | end 151 | 152 | STATE_SEND_CHALLENGE: begin 153 | if (SPI_dataReceived_ready_sync_pulse && sent_done) begin 154 | next_state = STATE_COMPARE_RESPONSE; 155 | end 156 | end 157 | 158 | STATE_COMPARE_RESPONSE: begin 159 | if (SPI_dataReceived == challenge) begin 160 | next_state = STATE_AUTHENTICATED; 161 | end 162 | else begin 163 | next_state = STATE_LOCK; 164 | end 165 | end 166 | 167 | STATE_LOCK: begin 168 | end 169 | 170 | STATE_AUTHENTICATED: begin 171 | end 172 | 173 | STATE_RESERVED: begin 174 | end 175 | 176 | default: begin 177 | next_state = STATE_READ_STORED_PK; 178 | end 179 | endcase 180 | end 181 | 182 | always @(posedge clk) begin 183 | 184 | case (state) 185 | STATE_IDLE: begin 186 | challengeGen_pause <= 0; 187 | publicKeyReceived <= 0; 188 | challenge <= 0; 189 | modExp_rst <= 0; 190 | modExp_start <= 0; 191 | modExp_x <= 0; 192 | modExp_y <= 0; 193 | modExp_m <= 0; 194 | SPI_dataToSend <= 0; 195 | SPI_send <= 0; 196 | sent_done <= 0; 197 | end 198 | 199 | STATE_READ_STORED_PK: begin 200 | challengeGen_pause <= 0; 201 | publicKeyReceived <= 0; 202 | challenge <= 0; 203 | modExp_rst <= 0; 204 | modExp_start <= 0; 205 | modExp_x <= 0; 206 | modExp_y <= 0; 207 | modExp_m <= 0; 208 | SPI_dataToSend <= 0; 209 | SPI_send <= 0; 210 | sent_done <= 0; 211 | end 212 | 213 | STATE_READY: begin 214 | challengeGen_pause <= 0; 215 | publicKeyReceived <= 0; 216 | challenge <= 0; 217 | modExp_rst <= 1'b1; 218 | modExp_start <= 0; 219 | modExp_x <= 0; 220 | modExp_y <= 0; 221 | modExp_m <= 0; 222 | SPI_dataToSend <= 0; 223 | SPI_send <= 0; 224 | sent_done <= 0; 225 | end 226 | 227 | STATE_COMPARE_RECEIVED_PK: begin 228 | if (SPI_dataReceived == storedPK) begin 229 | challengeGen_pause <= 1'b1; 230 | challenge <= challengeGen_out; 231 | modExp_start <= 1'b1; 232 | end 233 | else begin 234 | challengeGen_pause <= 0; 235 | challenge <= 0; 236 | modExp_start <= 0; 237 | end 238 | 239 | modExp_x <= challengeGen_out; 240 | modExp_y <= publicExponent; 241 | modExp_m <= SPI_dataReceived; 242 | 243 | publicKeyReceived <= SPI_dataReceived; 244 | modExp_rst <= 1'b1; 245 | SPI_dataToSend <= 0; 246 | SPI_send <= 0; 247 | sent_done <= 0; 248 | end 249 | 250 | STATE_ENCRYPT_CHALLENGE: begin 251 | challengeGen_pause <= 1'b1; 252 | publicKeyReceived <= publicKeyReceived; 253 | challenge <= challenge; 254 | modExp_rst <= 1'b1; 255 | modExp_start <= 0; 256 | modExp_x <= challenge; 257 | modExp_y <= publicExponent; 258 | modExp_m <= publicKeyReceived; 259 | if (modExp_ready) begin 260 | SPI_dataToSend <= modExp_out; 261 | end 262 | else begin 263 | SPI_dataToSend <= 0; 264 | end 265 | SPI_send <= 0; 266 | sent_done <= 0; 267 | end 268 | 269 | STATE_SEND_CHALLENGE: begin 270 | challengeGen_pause <= 1'b1; 271 | publicKeyReceived <= publicKeyReceived; 272 | challenge <= challenge; 273 | modExp_rst <= 0; 274 | modExp_start <= 0; 275 | modExp_x <= 0; 276 | modExp_y <= 0; 277 | modExp_m <= 0; 278 | SPI_dataToSend <= SPI_dataToSend; 279 | SPI_send <= 1'b1; 280 | if (SPI_dataReceived_ready_sync_pulse) begin 281 | sent_done <= 1'b1; 282 | end 283 | else begin 284 | sent_done <= sent_done; 285 | end 286 | end 287 | 288 | STATE_COMPARE_RESPONSE: begin 289 | challengeGen_pause <= 1'b1; 290 | publicKeyReceived <= publicKeyReceived; 291 | challenge <= challenge; 292 | modExp_rst <= 0; 293 | modExp_start <= 0; 294 | modExp_x <= 0; 295 | modExp_y <= 0; 296 | modExp_m <= 0; 297 | SPI_dataToSend <= 0; 298 | SPI_send <= 0; 299 | sent_done <= 0; 300 | end 301 | 302 | STATE_LOCK: begin 303 | challengeGen_pause <= 1'b1; 304 | publicKeyReceived <= publicKeyReceived; 305 | challenge <= 0; 306 | modExp_rst <= 0; 307 | modExp_start <= 0; 308 | modExp_x <= 0; 309 | modExp_y <= 0; 310 | modExp_m <= 0; 311 | SPI_dataToSend <= 0; 312 | SPI_send <= 0; 313 | sent_done <= 0; 314 | end 315 | 316 | STATE_AUTHENTICATED: begin 317 | challengeGen_pause <= 1'b1; 318 | publicKeyReceived <= publicKeyReceived; 319 | challenge <= challenge; 320 | modExp_rst <= 0; 321 | modExp_start <= 0; 322 | modExp_x <= 0; 323 | modExp_y <= 0; 324 | modExp_m <= 0; 325 | SPI_dataToSend <= 0; 326 | SPI_send <= 0; 327 | sent_done <= 0; 328 | end 329 | 330 | STATE_RESERVED: begin 331 | challengeGen_pause <= 1'b1; 332 | publicKeyReceived <= publicKeyReceived; 333 | challenge <= challenge; 334 | modExp_rst <= 0; 335 | modExp_start <= 0; 336 | modExp_x <= 0; 337 | modExp_y <= 0; 338 | modExp_m <= 0; 339 | SPI_dataToSend <= 0; 340 | SPI_send <= 0; 341 | sent_done <= 0; 342 | end 343 | 344 | default: begin 345 | challengeGen_pause <= 0; 346 | publicKeyReceived <= 0; 347 | challenge <= 0; 348 | modExp_rst <= 0; 349 | modExp_start <= 0; 350 | modExp_x <= 0; 351 | modExp_y <= 0; 352 | modExp_m <= 0; 353 | SPI_dataToSend <= 0; 354 | SPI_send <= 0; 355 | sent_done <= 0; 356 | end 357 | endcase 358 | end 359 | 360 | endmodule -------------------------------------------------------------------------------- /untrustedIC/primalityTest.v: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ioannis Karageorgos, Carnegie Mellon University. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 2.0 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // . Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | /////////////////////////////////////////////////////////////////////////////////// 12 | // Engineer: Ioannis Karageorgos // 13 | // // 14 | // Design Name: Primality tester // 15 | // Project Name: Split-Chip_authentication // 16 | // Language: Verilog // 17 | // // 18 | // Description: Tests if a given input number is a prime number. The test is // 19 | // based on the Miller-Rabin algorithm. The upper probability // 20 | // bound of error is defined by the number of repetitions and // 21 | // can be modified by adding or removing test states. // 22 | /////////////////////////////////////////////////////////////////////////////////// 23 | 24 | `include "__timescale.v" 25 | `include "__parameters.vh" 26 | 27 | 28 | module primalityTest #( 29 | parameter KEY_LENGTH = 32, 30 | parameter integer HALF_KEY_LENGTH = 0.5 * KEY_LENGTH, 31 | parameter e_WIDTH = 3 32 | )( 33 | input clk, 34 | input rst, 35 | input [HALF_KEY_LENGTH-1:0] in, 36 | input start, 37 | input modExp_ready, 38 | input [511:0] modExp_out, 39 | output reg modExp_rst, 40 | output [511:0] modExp_x, 41 | output [511+e_WIDTH:0] modExp_y, 42 | output [9:0] modExp_y_size, 43 | output [511:0] modExp_m, 44 | output reg modExp_start, 45 | output reg done, 46 | output reg isPrime 47 | ); 48 | 49 | // Miller and Rabin algorithm 50 | reg k; //we set k=1 so it can be ignored (it is not used in calculations) 51 | reg [7:0] a; 52 | reg [HALF_KEY_LENGTH-1:0] q; 53 | reg [HALF_KEY_LENGTH-1:0] in_minus1; 54 | reg qIsOdd; //intermediate signal used only for algorithm debugging (not needed in implementation) 55 | 56 | reg [3:0] count; 57 | reg [9:0] isPrime_tmp; 58 | wire [HALF_KEY_LENGTH-1 : 0] MRResult; // Miller-Rabin result: register that will take the result of a^q mod in 59 | 60 | localparam [9:0] MODEXP_Y_SIZE = HALF_KEY_LENGTH; 61 | 62 | assign modExp_x = {{504{1'b0}},a}; 63 | assign modExp_y = {{511+e_WIDTH+1-HALF_KEY_LENGTH{1'b0}},q}; 64 | assign modExp_y_size = MODEXP_Y_SIZE; 65 | assign modExp_m = {{512-HALF_KEY_LENGTH{1'b0}},in}; 66 | assign MRResult = modExp_out[HALF_KEY_LENGTH-1:0]; 67 | 68 | always @* begin 69 | in_minus1 = in - 1; 70 | q = in_minus1 >> 1; 71 | 72 | if (q[0] == 0) begin 73 | qIsOdd = 1'b1; 74 | end 75 | else begin 76 | qIsOdd = 1'b0; 77 | end 78 | end 79 | 80 | reg [3:0] state, next_state; 81 | localparam STATE_IDLE = 4'd0; 82 | localparam STATE_TEST01 = 4'd1; 83 | localparam STATE_TEST02 = 4'd2; 84 | localparam STATE_TEST03 = 4'd3; 85 | localparam STATE_TEST04 = 4'd4; 86 | localparam STATE_TEST05 = 4'd5; 87 | localparam STATE_TEST06 = 4'd6; 88 | localparam STATE_TEST07 = 4'd7; 89 | localparam STATE_TEST08 = 4'd8; 90 | localparam STATE_TEST09 = 4'd9; 91 | localparam STATE_TEST10 = 4'd10; 92 | localparam STATE_SUCCESS = 4'd11; 93 | 94 | always @(posedge clk) begin 95 | if (rst == 0) begin 96 | state <= STATE_IDLE; 97 | end 98 | else begin 99 | state <= next_state; 100 | end 101 | end 102 | 103 | always @(*) begin 104 | next_state = state; 105 | 106 | case (state) 107 | STATE_IDLE: begin 108 | if ( start ) begin 109 | next_state = STATE_TEST01; 110 | end 111 | end 112 | 113 | STATE_TEST01: begin 114 | if ( modExp_ready ) begin 115 | if (MRResult==1 || MRResult==in_minus1) begin 116 | next_state = STATE_TEST02; 117 | end 118 | else begin 119 | next_state = STATE_IDLE; 120 | end 121 | end 122 | end 123 | 124 | STATE_TEST02: begin 125 | if ( modExp_ready ) begin 126 | if (MRResult==1 || MRResult==in_minus1) begin 127 | next_state = STATE_TEST03; 128 | end 129 | else begin 130 | next_state = STATE_IDLE; 131 | end 132 | end 133 | end 134 | 135 | STATE_TEST03: begin 136 | if ( modExp_ready ) begin 137 | if (MRResult==1 || MRResult==in_minus1) begin 138 | next_state = STATE_TEST04; 139 | end 140 | else begin 141 | next_state = STATE_IDLE; 142 | end 143 | end 144 | end 145 | 146 | STATE_TEST04: begin 147 | if ( modExp_ready ) begin 148 | if (MRResult==1 || MRResult==in_minus1) begin 149 | next_state = STATE_TEST05; 150 | end 151 | else begin 152 | next_state = STATE_IDLE; 153 | end 154 | end 155 | end 156 | 157 | STATE_TEST05: begin 158 | if ( modExp_ready ) begin 159 | if (MRResult==1 || MRResult==in_minus1) begin 160 | next_state = STATE_TEST06; 161 | end 162 | else begin 163 | next_state = STATE_IDLE; 164 | end 165 | end 166 | end 167 | 168 | STATE_TEST06: begin 169 | if ( modExp_ready ) begin 170 | if (MRResult==1 || MRResult==in_minus1) begin 171 | next_state = STATE_TEST07; 172 | end 173 | else begin 174 | next_state = STATE_IDLE; 175 | end 176 | end 177 | end 178 | 179 | STATE_TEST07: begin 180 | if ( modExp_ready ) begin 181 | if (MRResult==1 || MRResult==in_minus1) begin 182 | next_state = STATE_TEST08; 183 | end 184 | else begin 185 | next_state = STATE_IDLE; 186 | end 187 | end 188 | end 189 | 190 | STATE_TEST08: begin 191 | if ( modExp_ready ) begin 192 | if (MRResult==1 || MRResult==in_minus1) begin 193 | next_state = STATE_TEST09; 194 | end 195 | else begin 196 | next_state = STATE_IDLE; 197 | end 198 | end 199 | end 200 | 201 | STATE_TEST09: begin 202 | if ( modExp_ready ) begin 203 | if (MRResult==1 || MRResult==in_minus1) begin 204 | next_state = STATE_TEST10; 205 | end 206 | else begin 207 | next_state = STATE_IDLE; 208 | end 209 | end 210 | end 211 | 212 | STATE_TEST10: begin 213 | if ( modExp_ready ) begin 214 | if (MRResult==1 || MRResult==in_minus1) begin 215 | next_state = STATE_SUCCESS; 216 | end 217 | else begin 218 | next_state = STATE_IDLE; 219 | end 220 | end 221 | end 222 | 223 | STATE_SUCCESS: begin 224 | next_state = STATE_IDLE; 225 | end 226 | 227 | default: begin 228 | if ( start ) begin 229 | next_state = STATE_TEST01; 230 | end 231 | end 232 | endcase 233 | end 234 | 235 | 236 | always @(posedge clk) begin 237 | 238 | case (state) 239 | STATE_IDLE: begin 240 | a <= 8'h40; 241 | done <= 0; 242 | isPrime <= 0; 243 | modExp_start <= 0; 244 | modExp_rst <= 0; 245 | 246 | if (next_state == STATE_TEST01) begin 247 | modExp_start <= 1'b1; 248 | modExp_rst <= 1'b1; 249 | end 250 | end 251 | 252 | STATE_TEST01: begin 253 | a <= 8'h40; 254 | modExp_start <= 0; 255 | 256 | if (next_state == STATE_IDLE) begin 257 | done <= 1'b1; 258 | end 259 | else if (next_state == STATE_TEST02) begin 260 | done <= 0; 261 | modExp_start <= 1'b1; 262 | end 263 | else begin 264 | done <= 0; 265 | end 266 | end 267 | 268 | STATE_TEST02: begin 269 | a <= 8'h73; 270 | modExp_start <= 0; 271 | 272 | if (next_state == STATE_IDLE) begin 273 | done <= 1'b1; 274 | end 275 | else if (next_state == STATE_TEST03) begin 276 | done <= 0; 277 | modExp_start <= 1'b1; 278 | end 279 | else begin 280 | done <= 0; 281 | end 282 | end 283 | 284 | STATE_TEST03: begin 285 | a <= 8'h6c; 286 | modExp_start <= 0; 287 | 288 | if (next_state == STATE_IDLE) begin 289 | done <= 1'b1; 290 | end 291 | else if (next_state == STATE_TEST04) begin 292 | done <= 0; 293 | modExp_start <= 1'b1; 294 | end 295 | else begin 296 | done <= 0; 297 | end 298 | end 299 | 300 | STATE_TEST04: begin 301 | a <= 8'h57; 302 | modExp_start <= 0; 303 | 304 | if (next_state == STATE_IDLE) begin 305 | done <= 1'b1; 306 | end 307 | else if (next_state == STATE_TEST05) begin 308 | done <= 0; 309 | modExp_start <= 1'b1; 310 | end 311 | else begin 312 | done <= 0; 313 | end 314 | end 315 | 316 | STATE_TEST05: begin 317 | a <= 8'hcd; 318 | modExp_start <= 0; 319 | 320 | if (next_state == STATE_IDLE) begin 321 | done <= 1'b1; 322 | end 323 | else if (next_state == STATE_TEST06) begin 324 | done <= 0; 325 | modExp_start <= 1'b1; 326 | end 327 | else begin 328 | done <= 0; 329 | end 330 | end 331 | 332 | STATE_TEST06: begin 333 | a <= 8'hdc; 334 | modExp_start <= 0; 335 | 336 | if (next_state == STATE_IDLE) begin 337 | done <= 1'b1; 338 | end 339 | else if (next_state == STATE_TEST07) begin 340 | done <= 0; 341 | modExp_start <= 1'b1; 342 | end 343 | else begin 344 | done <= 0; 345 | end 346 | end 347 | 348 | STATE_TEST07: begin 349 | a <= 8'h15; 350 | modExp_start <= 0; 351 | 352 | if (next_state == STATE_IDLE) begin 353 | done <= 1'b1; 354 | end 355 | else if (next_state == STATE_TEST08) begin 356 | done <= 0; 357 | modExp_start <= 1'b1; 358 | end 359 | else begin 360 | done <= 0; 361 | end 362 | end 363 | 364 | STATE_TEST08: begin 365 | a <= 8'h4e; 366 | modExp_start <= 0; 367 | 368 | if (next_state == STATE_IDLE) begin 369 | done <= 1'b1; 370 | end 371 | else if (next_state == STATE_TEST09) begin 372 | done <= 0; 373 | modExp_start <= 1'b1; 374 | end 375 | else begin 376 | done <= 0; 377 | end 378 | end 379 | 380 | STATE_TEST09: begin 381 | a <= 8'hed; 382 | modExp_start <= 0; 383 | 384 | if (next_state == STATE_IDLE) begin 385 | done <= 1'b1; 386 | end 387 | else if (next_state == STATE_TEST10) begin 388 | done <= 0; 389 | modExp_start <= 1'b1; 390 | end 391 | else begin 392 | done <= 0; 393 | end 394 | end 395 | 396 | STATE_TEST10: begin 397 | a <= 8'hdb; 398 | modExp_start <= 0; 399 | 400 | if (next_state == STATE_IDLE) begin 401 | done <= 1'b1; 402 | end 403 | else begin 404 | done <= 0; 405 | end 406 | end 407 | 408 | STATE_SUCCESS: begin 409 | done <= 1'b1; 410 | isPrime <= 1'b1; 411 | modExp_rst <= 0; 412 | end 413 | 414 | default: begin 415 | a <= 8'h40; 416 | done <= 0; 417 | isPrime <= 0; 418 | modExp_start <= 0; 419 | modExp_rst <= 0; 420 | 421 | if (next_state == STATE_TEST01) begin 422 | modExp_start <= 1'b1; 423 | modExp_rst <= 1'b1; 424 | end 425 | end 426 | endcase 427 | end 428 | 429 | `ifdef J_SIMULATION 430 | reg [1024:0] clk_counter, numbersTested_counter; 431 | integer output_file1, numbersTested_pass_counter; 432 | initial begin 433 | clk_counter = 0; 434 | numbersTested_counter = 0; 435 | numbersTested_pass_counter = 0; 436 | end 437 | 438 | always @(posedge clk) begin 439 | clk_counter = clk_counter + 1'd1; 440 | end 441 | 442 | always @(posedge done) begin 443 | numbersTested_counter = numbersTested_counter + 1'd1; 444 | if (isPrime) begin 445 | numbersTested_pass_counter = numbersTested_pass_counter + 1'd1; 446 | output_file1 = $fopen("numbersTested_pass.txt","a"); 447 | $fwrite(output_file1, "numbers tested: %0d\n", numbersTested_counter); 448 | $fwrite(output_file1, "pass: %0d\n", numbersTested_pass_counter); 449 | $fwrite(output_file1, "clock counter: %0d\n\n", clk_counter); 450 | $fclose(output_file1); 451 | end 452 | end 453 | `endif 454 | 455 | 456 | endmodule 457 | --------------------------------------------------------------------------------