From 889a5a5395872eeb3740d5d3281b56c7afa47a6f Mon Sep 17 00:00:00 2001 From: bnewbold Date: Fri, 20 Jan 2012 19:14:58 -0500 Subject: initial import from NeTV archive This repository is simply a mirror of the file fpga/hdmi_overlay_0xD_src.tgz downloaded from http://www.kosagi.com/netv_hardware/ on Jan 19th, 2011. It seems to contain all the verilog and scripts required to build FPGA firmware for the NeTV HDMI device from Chumby/Sutajio Ko-Usagi; see http://www.kosagi.com/blog/ for more information. Licensing is vague; see ip/license.txt --- hdcp/diff_network.v | 41 +++ hdcp/hdcp_block.v | 728 +++++++++++++++++++++++++++++++++++++++++++++++++ hdcp/hdcp_cipher.v | 411 ++++++++++++++++++++++++++++ hdcp/hdcp_lfsr.v | 196 +++++++++++++ hdcp/shuffle_network.v | 59 ++++ 5 files changed, 1435 insertions(+) create mode 100755 hdcp/diff_network.v create mode 100755 hdcp/hdcp_block.v create mode 100755 hdcp/hdcp_cipher.v create mode 100755 hdcp/hdcp_lfsr.v create mode 100755 hdcp/shuffle_network.v (limited to 'hdcp') diff --git a/hdcp/diff_network.v b/hdcp/diff_network.v new file mode 100755 index 0000000..1763a30 --- /dev/null +++ b/hdcp/diff_network.v @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011, Andrew "bunnie" Huang +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +module diff_network ( + input wire [6:0] i, + output wire [6:0] o, + input wire [6:0] k + ); + + assign o[0] = k[0] ^ ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6]; + assign o[1] = k[1] ^ i[0] ^ ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6]; + assign o[2] = k[2] ^ i[0] ^ i[1] ^ ^ i[3] ^ i[4] ^ i[5] ^ i[6]; + assign o[3] = k[3] ^ i[0] ^ i[1] ^ i[2] ^ ^ i[4] ^ i[5] ^ i[6]; + assign o[4] = k[4] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ ^ i[5] ^ i[6]; + assign o[5] = k[5] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ ^ i[6]; + assign o[6] = k[6] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6]; + +endmodule // diff_network diff --git a/hdcp/hdcp_block.v b/hdcp/hdcp_block.v new file mode 100755 index 0000000..5f81279 --- /dev/null +++ b/hdcp/hdcp_block.v @@ -0,0 +1,728 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011, Andrew "bunnie" Huang +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +module hdcp_block ( + input wire clk, + input wire reset, + + input wire load, + input wire [83:0] B, + input wire [83:0] K, + + output wire [83:0] Bo, + input wire rekey, + input wire lfsr_in, + + output reg [23:0] ostream, + + input wire advance + ); + + reg [27:0] Bx; + reg [27:0] By; + reg [27:0] Bz; + wire [27:0] o_Bx; + wire [27:0] o_By; + wire [27:0] o_Bz; + + reg [27:0] Kx; + reg [27:0] Ky; + reg [27:0] Kz; + wire [27:0] o_Kx; + wire [27:0] o_Ky; + wire o_Ky13; // bit 13 comes from lfsr_in when rekey is active + wire [27:0] o_Kz; + + wire [23:0] ostream_r; + + // semi-auto generated with a perl script + wire [3:0] SK0_in; + wire [3:0] SK1_in; + wire [3:0] SK2_in; + wire [3:0] SK3_in; + wire [3:0] SK4_in; + wire [3:0] SK5_in; + wire [3:0] SK6_in; + + reg [3:0] SK0; + reg [3:0] SK1; + reg [3:0] SK2; + reg [3:0] SK3; + reg [3:0] SK4; + reg [3:0] SK5; + reg [3:0] SK6; + + wire [3:0] SB0_in; + wire [3:0] SB1_in; + wire [3:0] SB2_in; + wire [3:0] SB3_in; + wire [3:0] SB4_in; + wire [3:0] SB5_in; + wire [3:0] SB6_in; + + reg [3:0] SB0; + reg [3:0] SB1; + reg [3:0] SB2; + reg [3:0] SB3; + reg [3:0] SB4; + reg [3:0] SB5; + reg [3:0] SB6; + + assign Bo = {Bz[27:0],By[27:0],Bx[27:0]}; + always @(posedge clk or posedge reset) begin + if( reset ) begin + Bx <= 28'b0; + By <= 28'b0; + Bz <= 28'b0; + Kx <= 28'b0; + Ky <= 28'b0; + Kz <= 28'b0; + ostream <= 24'b0; + end else begin + if( load ) begin +// Bz <= B[83:56]; + Bz <= {19'b0,1'b0,B[63:56]}; // repeater is fixed to zero + By <= B[55:28]; + Bx <= B[27:0]; + + Kz <= K[83:56]; + Ky <= K[55:28]; + Kx <= K[27:0]; + ostream <= 24'b0; + end else if( advance ) begin + Bx <= o_Bx; + By <= o_By; + Bz <= o_Bz; + + Kx <= o_Kx; + Ky <= o_Ky; + Kz <= o_Kz; + ostream <= ostream_r; + end else begin + Bx <= Bx; + By <= By; + Bz <= Bz; + + Kx <= Kx; + Ky <= Ky; + Kz <= Kz; + ostream <= ostream; + end + end // else: !if( reset ) + end // always @ (posedge clk or posedge reset) + + + //////////// + // bround linear transformation + // generated using perl script makebround.pl bround.csv > bround_code.txt + //////////// + diff_network bround1 ( .o({o_Bx[24],o_Bx[20],o_Bx[16],o_Bx[12],o_Bx[8],o_Bx[4],o_Bx[0]}), + .k({Ky[6],Ky[5],Ky[4],Ky[3],Ky[2],Ky[1],Ky[0]}), + .i({Bz[6],Bz[5],Bz[4],Bz[3],Bz[2],Bz[1],Bz[0]}) ); + + diff_network bround2 ( .o({o_By[24],o_By[20],o_By[16],o_By[12],o_By[8],o_By[4],o_By[0]}), + .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), + .i({By[12],By[2],By[1],By[0],Bz[9],Bz[8],Bz[7]}) ); + + diff_network bround3 ( .o({o_By[25],o_By[21],o_By[17],o_By[13],o_By[9],o_By[5],o_By[1]}), + .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), + .i({By[13],By[5],By[4],By[3],Bz[12],Bz[11],Bz[10]}) ); + + diff_network bround4 ( .o({o_By[26],o_By[22],o_By[18],o_By[14],o_By[10],o_By[6],o_By[2]}), + .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), + .i({By[14],By[8],By[7],By[6],Bz[15],Bz[14],Bz[13]}) ); + + diff_network bround5 ( .o({o_By[27],o_By[23],o_By[19],o_By[15],o_By[11],o_By[7],o_By[3]}), + .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), + .i({By[15],By[11],By[10],By[9],Bz[18],Bz[17],Bz[16]}) ); + + diff_network bround6 ( .o({o_Bx[25],o_Bx[21],o_Bx[17],o_Bx[13],o_Bx[9],o_Bx[5],o_Bx[1]}), + .k({Ky[13],Ky[12],Ky[11],Ky[10],Ky[9],Ky[8],Ky[7]}), + .i({Bz[21],Bz[20],Bz[19],By[19],By[18],By[17],By[16]}) ); + + diff_network bround7 ( .o({o_Bx[26],o_Bx[22],o_Bx[18],o_Bx[14],o_Bx[10],o_Bx[6],o_Bx[2]}), + .k({Ky[20],Ky[19],Ky[18],Ky[17],Ky[16],Ky[15],Ky[14]}), + .i({Bz[24],Bz[23],Bz[22],By[23],By[22],By[21],By[20]}) ); + + diff_network bround8 ( .o({o_Bx[27],o_Bx[23],o_Bx[19],o_Bx[15],o_Bx[11],o_Bx[7],o_Bx[3]}), + .k({Ky[27],Ky[26],Ky[25],Ky[24],Ky[23],Ky[22],Ky[21]}), + .i({Bz[27],Bz[26],Bz[25],By[27],By[26],By[25],By[24]}) ); + + + //////////// + // kround linear transform + // generated using perl script makelinx.pl kround.csv > kround + //////////// + + diff_network kround1 ( .o({o_Kx[24],o_Kx[20],o_Kx[16],o_Kx[12],o_Kx[8],o_Kx[4],o_Kx[0]}), + .i({Kz[6],Kz[5],Kz[4],Kz[3],Kz[2],Kz[1],Kz[0]}), + .k(7'b0) ); + + diff_network kround2 ( .o({o_Ky[24],o_Ky[20],o_Ky[16],o_Ky[12],o_Ky[8],o_Ky[4],o_Ky[0]}), + .i({Ky[12],Ky[2],Ky[1],Ky[0],Kz[9],Kz[8],Kz[7]}), + .k(7'b0) ); + + diff_network kround3 ( .o({o_Ky[25],o_Ky[21],o_Ky[17],o_Ky13,o_Ky[9],o_Ky[5],o_Ky[1]}), + .i({Ky[13],Ky[5],Ky[4],Ky[3],Kz[12],Kz[11],Kz[10]}), + .k(7'b0) ); + assign o_Ky[13] = rekey ? lfsr_in : o_Ky13; + + diff_network kround4 ( .o({o_Ky[26],o_Ky[22],o_Ky[18],o_Ky[14],o_Ky[10],o_Ky[6],o_Ky[2]}), + .i({Ky[14],Ky[8],Ky[7],Ky[6],Kz[15],Kz[14],Kz[13]}), + .k(7'b0) ); + + diff_network kround5 ( .o({o_Ky[27],o_Ky[23],o_Ky[19],o_Ky[15],o_Ky[11],o_Ky[7],o_Ky[3]}), + .i({Ky[15],Ky[11],Ky[10],Ky[9],Kz[18],Kz[17],Kz[16]}), + .k(7'b0) ); + + diff_network kround6 ( .o({o_Kx[25],o_Kx[21],o_Kx[17],o_Kx[13],o_Kx[9],o_Kx[5],o_Kx[1]}), + .i({Kz[21],Kz[20],Kz[19],Ky[19],Ky[18],Ky[17],Ky[16]}), + .k(7'b0) ); + + diff_network kround7 ( .o({o_Kx[26],o_Kx[22],o_Kx[18],o_Kx[14],o_Kx[10],o_Kx[6],o_Kx[2]}), + .i({Kz[24],Kz[23],Kz[22],Ky[23],Ky[22],Ky[21],Ky[20]}), + .k(7'b0) ); + + diff_network kround8 ( .o({o_Kx[27],o_Kx[23],o_Kx[19],o_Kx[15],o_Kx[11],o_Kx[7],o_Kx[3]}), + .i({Kz[27],Kz[26],Kz[25],Ky[27],Ky[26],Ky[25],Ky[24]}), + .k(7'b0) ); + + ///////////// + // sboxes + // generated using script makeblock.pl sbox_src.txt > sbox_code.txt + ///////////// + always @(SK0_in[3:0]) begin + case (SK0_in[3:0]) + 4'h0: SK0 = 4'd8; + 4'h1: SK0 = 4'd14; + 4'h2: SK0 = 4'd5; + 4'h3: SK0 = 4'd9; + 4'h4: SK0 = 4'd3; + 4'h5: SK0 = 4'd0; + 4'h6: SK0 = 4'd12; + 4'h7: SK0 = 4'd6; + 4'h8: SK0 = 4'd1; + 4'h9: SK0 = 4'd11; + 4'hA: SK0 = 4'd15; + 4'hB: SK0 = 4'd2; + 4'hC: SK0 = 4'd4; + 4'hD: SK0 = 4'd7; + 4'hE: SK0 = 4'd10; + 4'hF: SK0 = 4'd13; + endcase // case (SK0_in[3:0]) + end // always @ (SK0_in[3:0]) + + always @(SK0_in[3:0]) begin + case (SK0_in[3:0]) + 4'h0: SK0 = 4'd8; + 4'h1: SK0 = 4'd14; + 4'h2: SK0 = 4'd5; + 4'h3: SK0 = 4'd9; + 4'h4: SK0 = 4'd3; + 4'h5: SK0 = 4'd0; + 4'h6: SK0 = 4'd12; + 4'h7: SK0 = 4'd6; + 4'h8: SK0 = 4'd1; + 4'h9: SK0 = 4'd11; + 4'hA: SK0 = 4'd15; + 4'hB: SK0 = 4'd2; + 4'hC: SK0 = 4'd4; + 4'hD: SK0 = 4'd7; + 4'hE: SK0 = 4'd10; + 4'hF: SK0 = 4'd13; + endcase // case (SK0_in[3:0]) + end // always @ (SK0_in[3:0]) + + always @(SK1_in[3:0]) begin + case (SK1_in[3:0]) + 4'h0: SK1 = 4'd1; + 4'h1: SK1 = 4'd6; + 4'h2: SK1 = 4'd4; + 4'h3: SK1 = 4'd15; + 4'h4: SK1 = 4'd8; + 4'h5: SK1 = 4'd3; + 4'h6: SK1 = 4'd11; + 4'h7: SK1 = 4'd5; + 4'h8: SK1 = 4'd10; + 4'h9: SK1 = 4'd0; + 4'hA: SK1 = 4'd9; + 4'hB: SK1 = 4'd12; + 4'hC: SK1 = 4'd7; + 4'hD: SK1 = 4'd13; + 4'hE: SK1 = 4'd14; + 4'hF: SK1 = 4'd2; + endcase // case (SK1_in[3:0]) + end // always @ (SK1_in[3:0]) + + always @(SK2_in[3:0]) begin + case (SK2_in[3:0]) + 4'h0: SK2 = 4'd13; + 4'h1: SK2 = 4'd11; + 4'h2: SK2 = 4'd8; + 4'h3: SK2 = 4'd6; + 4'h4: SK2 = 4'd7; + 4'h5: SK2 = 4'd4; + 4'h6: SK2 = 4'd2; + 4'h7: SK2 = 4'd15; + 4'h8: SK2 = 4'd1; + 4'h9: SK2 = 4'd12; + 4'hA: SK2 = 4'd14; + 4'hB: SK2 = 4'd0; + 4'hC: SK2 = 4'd10; + 4'hD: SK2 = 4'd3; + 4'hE: SK2 = 4'd9; + 4'hF: SK2 = 4'd5; + endcase // case (SK2_in[3:0]) + end // always @ (SK2_in[3:0]) + + always @(SK3_in[3:0]) begin + case (SK3_in[3:0]) + 4'h0: SK3 = 4'd0; + 4'h1: SK3 = 4'd14; + 4'h2: SK3 = 4'd11; + 4'h3: SK3 = 4'd7; + 4'h4: SK3 = 4'd12; + 4'h5: SK3 = 4'd3; + 4'h6: SK3 = 4'd2; + 4'h7: SK3 = 4'd13; + 4'h8: SK3 = 4'd15; + 4'h9: SK3 = 4'd4; + 4'hA: SK3 = 4'd8; + 4'hB: SK3 = 4'd1; + 4'hC: SK3 = 4'd9; + 4'hD: SK3 = 4'd10; + 4'hE: SK3 = 4'd5; + 4'hF: SK3 = 4'd6; + endcase // case (SK3_in[3:0]) + end // always @ (SK3_in[3:0]) + + always @(SK4_in[3:0]) begin + case (SK4_in[3:0]) + 4'h0: SK4 = 4'd12; + 4'h1: SK4 = 4'd7; + 4'h2: SK4 = 4'd15; + 4'h3: SK4 = 4'd8; + 4'h4: SK4 = 4'd11; + 4'h5: SK4 = 4'd14; + 4'h6: SK4 = 4'd1; + 4'h7: SK4 = 4'd4; + 4'h8: SK4 = 4'd6; + 4'h9: SK4 = 4'd10; + 4'hA: SK4 = 4'd3; + 4'hB: SK4 = 4'd5; + 4'hC: SK4 = 4'd0; + 4'hD: SK4 = 4'd9; + 4'hE: SK4 = 4'd13; + 4'hF: SK4 = 4'd2; + endcase // case (SK4_in[3:0]) + end // always @ (SK4_in[3:0]) + + always @(SK5_in[3:0]) begin + case (SK5_in[3:0]) + 4'h0: SK5 = 4'd1; + 4'h1: SK5 = 4'd12; + 4'h2: SK5 = 4'd7; + 4'h3: SK5 = 4'd2; + 4'h4: SK5 = 4'd8; + 4'h5: SK5 = 4'd3; + 4'h6: SK5 = 4'd4; + 4'h7: SK5 = 4'd14; + 4'h8: SK5 = 4'd11; + 4'h9: SK5 = 4'd5; + 4'hA: SK5 = 4'd0; + 4'hB: SK5 = 4'd15; + 4'hC: SK5 = 4'd13; + 4'hD: SK5 = 4'd6; + 4'hE: SK5 = 4'd10; + 4'hF: SK5 = 4'd9; + endcase // case (SK5_in[3:0]) + end // always @ (SK5_in[3:0]) + + always @(SK6_in[3:0]) begin + case (SK6_in[3:0]) + 4'h0: SK6 = 4'd10; + 4'h1: SK6 = 4'd7; + 4'h2: SK6 = 4'd6; + 4'h3: SK6 = 4'd1; + 4'h4: SK6 = 4'd0; + 4'h5: SK6 = 4'd14; + 4'h6: SK6 = 4'd3; + 4'h7: SK6 = 4'd13; + 4'h8: SK6 = 4'd12; + 4'h9: SK6 = 4'd9; + 4'hA: SK6 = 4'd11; + 4'hB: SK6 = 4'd2; + 4'hC: SK6 = 4'd15; + 4'hD: SK6 = 4'd5; + 4'hE: SK6 = 4'd4; + 4'hF: SK6 = 4'd8; + endcase // case (SK6_in[3:0]) + end // always @ (SK6_in[3:0]) + + always @(SB0_in[3:0]) begin + case (SB0_in[3:0]) + 4'h0: SB0 = 4'd12; + 4'h1: SB0 = 4'd9; + 4'h2: SB0 = 4'd3; + 4'h3: SB0 = 4'd0; + 4'h4: SB0 = 4'd11; + 4'h5: SB0 = 4'd5; + 4'h6: SB0 = 4'd13; + 4'h7: SB0 = 4'd6; + 4'h8: SB0 = 4'd2; + 4'h9: SB0 = 4'd4; + 4'hA: SB0 = 4'd14; + 4'hB: SB0 = 4'd7; + 4'hC: SB0 = 4'd8; + 4'hD: SB0 = 4'd15; + 4'hE: SB0 = 4'd1; + 4'hF: SB0 = 4'd10; + endcase // case (SB0_in[3:0]) + end // always @ (SB0_in[3:0]) + + always @(SB1_in[3:0]) begin + case (SB1_in[3:0]) + 4'h0: SB1 = 4'd3; + 4'h1: SB1 = 4'd8; + 4'h2: SB1 = 4'd14; + 4'h3: SB1 = 4'd1; + 4'h4: SB1 = 4'd5; + 4'h5: SB1 = 4'd2; + 4'h6: SB1 = 4'd11; + 4'h7: SB1 = 4'd13; + 4'h8: SB1 = 4'd10; + 4'h9: SB1 = 4'd4; + 4'hA: SB1 = 4'd9; + 4'hB: SB1 = 4'd7; + 4'hC: SB1 = 4'd6; + 4'hD: SB1 = 4'd15; + 4'hE: SB1 = 4'd12; + 4'hF: SB1 = 4'd0; + endcase // case (SB1_in[3:0]) + end // always @ (SB1_in[3:0]) + + always @(SB2_in[3:0]) begin + case (SB2_in[3:0]) + 4'h0: SB2 = 4'd7; + 4'h1: SB2 = 4'd4; + 4'h2: SB2 = 4'd1; + 4'h3: SB2 = 4'd10; + 4'h4: SB2 = 4'd11; + 4'h5: SB2 = 4'd13; + 4'h6: SB2 = 4'd14; + 4'h7: SB2 = 4'd3; + 4'h8: SB2 = 4'd12; + 4'h9: SB2 = 4'd15; + 4'hA: SB2 = 4'd6; + 4'hB: SB2 = 4'd0; + 4'hC: SB2 = 4'd2; + 4'hD: SB2 = 4'd8; + 4'hE: SB2 = 4'd9; + 4'hF: SB2 = 4'd5; + endcase // case (SB2_in[3:0]) + end // always @ (SB2_in[3:0]) + + always @(SB3_in[3:0]) begin + case (SB3_in[3:0]) + 4'h0: SB3 = 4'd6; + 4'h1: SB3 = 4'd3; + 4'h2: SB3 = 4'd1; + 4'h3: SB3 = 4'd4; + 4'h4: SB3 = 4'd10; + 4'h5: SB3 = 4'd12; + 4'h6: SB3 = 4'd15; + 4'h7: SB3 = 4'd2; + 4'h8: SB3 = 4'd5; + 4'h9: SB3 = 4'd14; + 4'hA: SB3 = 4'd11; + 4'hB: SB3 = 4'd8; + 4'hC: SB3 = 4'd9; + 4'hD: SB3 = 4'd7; + 4'hE: SB3 = 4'd0; + 4'hF: SB3 = 4'd13; + endcase // case (SB3_in[3:0]) + end // always @ (SB3_in[3:0]) + + always @(SB4_in[3:0]) begin + case (SB4_in[3:0]) + 4'h0: SB4 = 4'd3; + 4'h1: SB4 = 4'd6; + 4'h2: SB4 = 4'd15; + 4'h3: SB4 = 4'd12; + 4'h4: SB4 = 4'd4; + 4'h5: SB4 = 4'd1; + 4'h6: SB4 = 4'd9; + 4'h7: SB4 = 4'd2; + 4'h8: SB4 = 4'd5; + 4'h9: SB4 = 4'd8; + 4'hA: SB4 = 4'd10; + 4'hB: SB4 = 4'd7; + 4'hC: SB4 = 4'd11; + 4'hD: SB4 = 4'd13; + 4'hE: SB4 = 4'd0; + 4'hF: SB4 = 4'd14; + endcase // case (SB4_in[3:0]) + end // always @ (SB4_in[3:0]) + + always @(SB5_in[3:0]) begin + case (SB5_in[3:0]) + 4'h0: SB5 = 4'd11; + 4'h1: SB5 = 4'd14; + 4'h2: SB5 = 4'd6; + 4'h3: SB5 = 4'd8; + 4'h4: SB5 = 4'd5; + 4'h5: SB5 = 4'd2; + 4'h6: SB5 = 4'd12; + 4'h7: SB5 = 4'd7; + 4'h8: SB5 = 4'd1; + 4'h9: SB5 = 4'd4; + 4'hA: SB5 = 4'd15; + 4'hB: SB5 = 4'd3; + 4'hC: SB5 = 4'd10; + 4'hD: SB5 = 4'd13; + 4'hE: SB5 = 4'd9; + 4'hF: SB5 = 4'd0; + endcase // case (SB5_in[3:0]) + end // always @ (SB5_in[3:0]) + + always @(SB6_in[3:0]) begin + case (SB6_in[3:0]) + 4'h0: SB6 = 4'd1; + 4'h1: SB6 = 4'd11; + 4'h2: SB6 = 4'd7; + 4'h3: SB6 = 4'd4; + 4'h4: SB6 = 4'd2; + 4'h5: SB6 = 4'd5; + 4'h6: SB6 = 4'd12; + 4'h7: SB6 = 4'd9; + 4'h8: SB6 = 4'd13; + 4'h9: SB6 = 4'd6; + 4'hA: SB6 = 4'd8; + 4'hB: SB6 = 4'd15; + 4'hC: SB6 = 4'd14; + 4'hD: SB6 = 4'd0; + 4'hE: SB6 = 4'd3; + 4'hF: SB6 = 4'd10; + endcase // case (SB6_in[3:0]) + end // always @ (SB6_in[3:0]) + + ////// + /// Sbox wiring + /// generated by perl script ./make_sboxwires.pl + ////// + assign SB0_in[0] = Bx[0]; + assign SB0_in[1] = Bx[7]; + assign SB0_in[2] = Bx[14]; + assign SB0_in[3] = Bx[21]; + + assign SK0_in[0] = Kx[0]; + assign SK0_in[1] = Kx[7]; + assign SK0_in[2] = Kx[14]; + assign SK0_in[3] = Kx[21]; + + assign o_Bz[0] = SB0[0]; + assign o_Bz[7] = SB0[1]; + assign o_Bz[14] = SB0[2]; + assign o_Bz[21] = SB0[3]; + + assign o_Kz[0] = SK0[0]; + assign o_Kz[7] = SK0[1]; + assign o_Kz[14] = SK0[2]; + assign o_Kz[21] = SK0[3]; + + assign SB1_in[0] = Bx[1]; + assign SB1_in[1] = Bx[8]; + assign SB1_in[2] = Bx[15]; + assign SB1_in[3] = Bx[22]; + + assign SK1_in[0] = Kx[1]; + assign SK1_in[1] = Kx[8]; + assign SK1_in[2] = Kx[15]; + assign SK1_in[3] = Kx[22]; + + assign o_Bz[1] = SB1[0]; + assign o_Bz[8] = SB1[1]; + assign o_Bz[15] = SB1[2]; + assign o_Bz[22] = SB1[3]; + + assign o_Kz[1] = SK1[0]; + assign o_Kz[8] = SK1[1]; + assign o_Kz[15] = SK1[2]; + assign o_Kz[22] = SK1[3]; + + assign SB2_in[0] = Bx[2]; + assign SB2_in[1] = Bx[9]; + assign SB2_in[2] = Bx[16]; + assign SB2_in[3] = Bx[23]; + + assign SK2_in[0] = Kx[2]; + assign SK2_in[1] = Kx[9]; + assign SK2_in[2] = Kx[16]; + assign SK2_in[3] = Kx[23]; + + assign o_Bz[2] = SB2[0]; + assign o_Bz[9] = SB2[1]; + assign o_Bz[16] = SB2[2]; + assign o_Bz[23] = SB2[3]; + + assign o_Kz[2] = SK2[0]; + assign o_Kz[9] = SK2[1]; + assign o_Kz[16] = SK2[2]; + assign o_Kz[23] = SK2[3]; + + assign SB3_in[0] = Bx[3]; + assign SB3_in[1] = Bx[10]; + assign SB3_in[2] = Bx[17]; + assign SB3_in[3] = Bx[24]; + + assign SK3_in[0] = Kx[3]; + assign SK3_in[1] = Kx[10]; + assign SK3_in[2] = Kx[17]; + assign SK3_in[3] = Kx[24]; + + assign o_Bz[3] = SB3[0]; + assign o_Bz[10] = SB3[1]; + assign o_Bz[17] = SB3[2]; + assign o_Bz[24] = SB3[3]; + + assign o_Kz[3] = SK3[0]; + assign o_Kz[10] = SK3[1]; + assign o_Kz[17] = SK3[2]; + assign o_Kz[24] = SK3[3]; + + assign SB4_in[0] = Bx[4]; + assign SB4_in[1] = Bx[11]; + assign SB4_in[2] = Bx[18]; + assign SB4_in[3] = Bx[25]; + + assign SK4_in[0] = Kx[4]; + assign SK4_in[1] = Kx[11]; + assign SK4_in[2] = Kx[18]; + assign SK4_in[3] = Kx[25]; + + assign o_Bz[4] = SB4[0]; + assign o_Bz[11] = SB4[1]; + assign o_Bz[18] = SB4[2]; + assign o_Bz[25] = SB4[3]; + + assign o_Kz[4] = SK4[0]; + assign o_Kz[11] = SK4[1]; + assign o_Kz[18] = SK4[2]; + assign o_Kz[25] = SK4[3]; + + assign SB5_in[0] = Bx[5]; + assign SB5_in[1] = Bx[12]; + assign SB5_in[2] = Bx[19]; + assign SB5_in[3] = Bx[26]; + + assign SK5_in[0] = Kx[5]; + assign SK5_in[1] = Kx[12]; + assign SK5_in[2] = Kx[19]; + assign SK5_in[3] = Kx[26]; + + assign o_Bz[5] = SB5[0]; + assign o_Bz[12] = SB5[1]; + assign o_Bz[19] = SB5[2]; + assign o_Bz[26] = SB5[3]; + + assign o_Kz[5] = SK5[0]; + assign o_Kz[12] = SK5[1]; + assign o_Kz[19] = SK5[2]; + assign o_Kz[26] = SK5[3]; + + assign SB6_in[0] = Bx[6]; + assign SB6_in[1] = Bx[13]; + assign SB6_in[2] = Bx[20]; + assign SB6_in[3] = Bx[27]; + + assign SK6_in[0] = Kx[6]; + assign SK6_in[1] = Kx[13]; + assign SK6_in[2] = Kx[20]; + assign SK6_in[3] = Kx[27]; + + assign o_Bz[6] = SB6[0]; + assign o_Bz[13] = SB6[1]; + assign o_Bz[20] = SB6[2]; + assign o_Bz[27] = SB6[3]; + + assign o_Kz[6] = SK6[0]; + assign o_Kz[13] = SK6[1]; + assign o_Kz[20] = SK6[2]; + assign o_Kz[27] = SK6[3]; + + ////// + // output function + // generated by perl script ./makeofunc.pl ofunc.txt > ostream_code.txt + ////// +assign ostream_r[0] = (Bz[17] & Kz[3]) ^ (Bz[26] & Kz[6]) ^ (Bz[22] & Kz[0]) ^ (Bz[27] & Kz[9]) ^ (Bz[21] & Kz[4]) ^ (Bz[18] & Kz[22]) ^ (Bz[2] & Kz[5]) ^ By[5] ^ Ky[10]; + +assign ostream_r[1] = (Bz[5] & Kz[20]) ^ (Bz[20] & Kz[18]) ^ (Bz[15] & Kz[7]) ^ (Bz[24] & Kz[23]) ^ (Bz[2] & Kz[15]) ^ (Bz[25] & Kz[5]) ^ (Bz[0] & Kz[3]) ^ By[16] ^ Ky[25]; + +assign ostream_r[2] = (Bz[22] & Kz[7]) ^ (Bz[5] & Kz[19]) ^ (Bz[14] & Kz[2]) ^ (Bz[16] & Kz[10]) ^ (Bz[25] & Kz[22]) ^ (Bz[17] & Kz[4]) ^ (Bz[20] & Kz[13]) ^ By[11] ^ Ky[21]; + +assign ostream_r[3] = (Bz[19] & Kz[6]) ^ (Bz[3] & Kz[14]) ^ (Bz[15] & Kz[9]) ^ (Bz[11] & Kz[8]) ^ (Bz[21] & Kz[17]) ^ (Bz[16] & Kz[18]) ^ (Bz[27] & Kz[12]) ^ By[1] ^ Ky[24]; + +assign ostream_r[4] = (Bz[19] & Kz[25]) ^ (Bz[6] & Kz[6]) ^ (Bz[17] & Kz[5]) ^ (Bz[18] & Kz[2]) ^ (Bz[22] & Kz[10]) ^ (Bz[7] & Kz[15]) ^ (Bz[9] & Kz[21]) ^ By[12] ^ Ky[8]; + +assign ostream_r[5] = (Bz[3] & Kz[27]) ^ (Bz[7] & Kz[14]) ^ (Bz[4] & Kz[2]) ^ (Bz[8] & Kz[4]) ^ (Bz[16] & Kz[24]) ^ (Bz[6] & Kz[19]) ^ (Bz[5] & Kz[1]) ^ By[17] ^ Ky[12]; + +assign ostream_r[6] = (Bz[8] & Kz[17]) ^ (Bz[21] & Kz[26]) ^ (Bz[27] & Kz[4]) ^ (Bz[2] & Kz[16]) ^ (Bz[11] & Kz[27]) ^ (Bz[24] & Kz[7]) ^ (Bz[12] & Kz[22]) ^ By[3] ^ Ky[11]; + +assign ostream_r[7] = (Bz[9] & Kz[9]) ^ (Bz[5] & Kz[10]) ^ (Bz[7] & Kz[19]) ^ (Bz[4] & Kz[11]) ^ (Bz[8] & Kz[7]) ^ (Bz[13] & Kz[6]) ^ (Bz[3] & Kz[8]) ^ By[15] ^ Ky[23]; + +assign ostream_r[8] = (Bz[26] & Kz[13]) ^ (Bz[13] & Kz[12]) ^ (Bz[23] & Kz[18]) ^ (Bz[10] & Kz[24]) ^ (Bz[11] & Kz[15]) ^ (Bz[7] & Kz[23]) ^ (Bz[15] & Kz[7]) ^ By[19] ^ Ky[16]; + +assign ostream_r[9] = (Bz[1] & Kz[0]) ^ (Bz[0] & Kz[5]) ^ (Bz[19] & Kz[20]) ^ (Bz[11] & Kz[25]) ^ (Bz[13] & Kz[1]) ^ (Bz[16] & Kz[24]) ^ (Bz[24] & Kz[9]) ^ By[18] ^ Ky[27]; + +assign ostream_r[10] = (Bz[26] & Kz[14]) ^ (Bz[13] & Kz[23]) ^ (Bz[9] & Kz[27]) ^ (Bz[14] & Kz[25]) ^ (Bz[10] & Kz[17]) ^ (Bz[4] & Kz[19]) ^ (Bz[1] & Kz[1]) ^ By[2] ^ Ky[22]; + +assign ostream_r[11] = (Bz[21] & Kz[6]) ^ (Bz[15] & Kz[21]) ^ (Bz[5] & Kz[17]) ^ (Bz[3] & Kz[15]) ^ (Bz[13] & Kz[26]) ^ (Bz[25] & Kz[11]) ^ (Bz[16] & Kz[16]) ^ By[27] ^ Ky[7]; + +assign ostream_r[12] = (Bz[20] & Kz[11]) ^ (Bz[7] & Kz[22]) ^ (Bz[18] & Kz[20]) ^ (Bz[12] & Kz[0]) ^ (Bz[17] & Kz[26]) ^ (Bz[1] & Kz[23]) ^ (Bz[16] & Kz[17]) ^ By[0] ^ Ky[2]; + +assign ostream_r[13] = (Bz[14] & Kz[8]) ^ (Bz[23] & Kz[4]) ^ (Bz[1] & Kz[3]) ^ (Bz[12] & Kz[14]) ^ (Bz[24] & Kz[20]) ^ (Bz[6] & Kz[26]) ^ (Bz[18] & Kz[23]) ^ By[9] ^ Ky[15]; + +assign ostream_r[14] = (Bz[19] & Kz[19]) ^ (Bz[6] & Kz[0]) ^ (Bz[21] & Kz[18]) ^ (Bz[25] & Kz[2]) ^ (Bz[23] & Kz[13]) ^ (Bz[1] & Kz[8]) ^ (Bz[10] & Kz[24]) ^ By[8] ^ Ky[14]; + +assign ostream_r[15] = (Bz[3] & Kz[16]) ^ (Bz[0] & Kz[21]) ^ (Bz[27] & Kz[24]) ^ (Bz[23] & Kz[25]) ^ (Bz[19] & Kz[12]) ^ (Bz[8] & Kz[27]) ^ (Bz[4] & Kz[15]) ^ By[7] ^ Ky[18]; + +assign ostream_r[16] = (Bz[6] & Kz[3]) ^ (Bz[5] & Kz[5]) ^ (Bz[14] & Kz[8]) ^ (Bz[22] & Kz[25]) ^ (Bz[24] & Kz[7]) ^ (Bz[18] & Kz[27]) ^ (Bz[2] & Kz[2]) ^ By[21] ^ Ky[26]; + +assign ostream_r[17] = (Bz[3] & Kz[11]) ^ (Bz[4] & Kz[14]) ^ (Bz[2] & Kz[23]) ^ (Bz[6] & Kz[17]) ^ (Bz[22] & Kz[22]) ^ (Bz[14] & Kz[13]) ^ (Bz[12] & Kz[19]) ^ By[26] ^ Ky[4]; + +assign ostream_r[18] = (Bz[25] & Kz[1]) ^ (Bz[21] & Kz[16]) ^ (Bz[19] & Kz[14]) ^ (Bz[9] & Kz[11]) ^ (Bz[10] & Kz[12]) ^ (Bz[15] & Kz[6]) ^ (Bz[13] & Kz[10]) ^ By[22] ^ Ky[19]; + +assign ostream_r[19] = (Bz[23] & Kz[21]) ^ (Bz[11] & Kz[1]) ^ (Bz[10] & Kz[10]) ^ (Bz[20] & Kz[20]) ^ (Bz[1] & Kz[18]) ^ (Bz[12] & Kz[26]) ^ (Bz[14] & Kz[9]) ^ By[4] ^ Ky[13]; + +assign ostream_r[20] = (Bz[11] & Kz[20]) ^ (Bz[26] & Kz[21]) ^ (Bz[20] & Kz[9]) ^ (Bz[17] & Kz[25]) ^ (Bz[8] & Kz[12]) ^ (Bz[23] & Kz[3]) ^ (Bz[0] & Kz[15]) ^ By[24] ^ Ky[0]; + +assign ostream_r[21] = (Bz[9] & Kz[18]) ^ (Bz[17] & Kz[12]) ^ (Bz[26] & Kz[21]) ^ (Bz[4] & Kz[27]) ^ (Bz[27] & Kz[1]) ^ (Bz[0] & Kz[16]) ^ (Bz[15] & Kz[24]) ^ By[6] ^ Ky[20]; + +assign ostream_r[22] = (Bz[22] & Kz[13]) ^ (Bz[12] & Kz[0]) ^ (Bz[2] & Kz[3]) ^ (Bz[10] & Kz[16]) ^ (Bz[7] & Kz[22]) ^ (Bz[20] & Kz[11]) ^ (Bz[25] & Kz[26]) ^ By[13] ^ Ky[9]; + +assign ostream_r[23] = (Bz[27] & Kz[2]) ^ (Bz[24] & Kz[0]) ^ (Bz[26] & Kz[13]) ^ (Bz[8] & Kz[5]) ^ (Bz[0] & Kz[4]) ^ (Bz[9] & Kz[8]) ^ (Bz[18] & Kz[10]) ^ By[23] ^ Ky[3]; + +endmodule // hdcp_block diff --git a/hdcp/hdcp_cipher.v b/hdcp/hdcp_cipher.v new file mode 100755 index 0000000..9804d10 --- /dev/null +++ b/hdcp/hdcp_cipher.v @@ -0,0 +1,411 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011, Andrew "bunnie" Huang +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +// generates a stream of hdcp cipher data +module hdcp_cipher( + input wire clk, + input reset, + + input [55:0] Km, // shared secret value + input [63:0] An, // session random number + + input hdcpBlockCipher_init, // pulsed only one cycle + input authentication, // pulsed one cycle same time as above + input hdcpRekeyCipher, // pulsed one cycle to initiate rekey + input hdcpStreamCipher,// advance cipher state one clock + output [23:0] pr_data, // pseudorandom data output + output reg stream_ready // asserted when stream is ready (after init seq) + ); + + wire lfsr_out; + wire [23:0] ostream; + wire [83:0] Bo_wire; + + parameter INIT = 12'b1 << 0; + parameter BLOCK_1 = 12'b1 << 1; + parameter BLOCK_2 = 12'b1 << 2; + parameter BLOCK_3 = 12'b1 << 3; + parameter BLOCK_4 = 12'b1 << 4; + parameter BLOCK_5 = 12'b1 << 5; + parameter BLOCK_6 = 12'b1 << 6; + parameter BLOCK_7 = 12'b1 << 7; + parameter BLOCK_8 = 12'b1 << 8; + parameter BLOCK_9 = 12'b1 << 9; + parameter GET_M = 12'b1 << 10; + parameter STREAM = 12'b1 << 11; + parameter REKEY = 12'b1 << 12; + parameter nSTATES = 13; + + reg [(nSTATES-1):0] cstate = {{(nSTATES-1){1'b0}},1'b1}; + reg [(nSTATES-1):0] nstate; + +// `define SIMULATION 1 +`ifdef SIMULATION + // synthesis translate_off + reg [8*20:1] state_ascii = "INIT "; + always @(cstate) begin + if (cstate == INIT ) state_ascii <= "INIT "; + else if (cstate == BLOCK_1 ) state_ascii <= "BLOCK_1 "; + else if (cstate == BLOCK_2 ) state_ascii <= "BLOCK_2 "; + else if (cstate == BLOCK_3 ) state_ascii <= "BLOCK_3 "; + else if (cstate == BLOCK_4 ) state_ascii <= "BLOCK_4 "; + else if (cstate == BLOCK_5 ) state_ascii <= "BLOCK_5 "; + else if (cstate == BLOCK_6 ) state_ascii <= "BLOCK_6 "; + else if (cstate == BLOCK_7 ) state_ascii <= "BLOCK_7 "; + else if (cstate == BLOCK_8 ) state_ascii <= "BLOCK_8 "; + else if (cstate == BLOCK_9 ) state_ascii <= "BLOCK_9 "; + else if (cstate == GET_M ) state_ascii <= "GET_M "; + else if (cstate == STREAM ) state_ascii <= "STREAM "; + else if (cstate == REKEY ) state_ascii <= "REKEY "; + else state_ascii <= "WTF "; + end + // synthesis translate_on +`endif // `ifdef SIMULATION + + reg [5:0] statecnt; + reg rekey; + reg load_block; + reg load_56; // load 56 or 80 bits... + reg load_lfsr; + reg advance_lfsr; + reg advance_block; + reg [83:0] Ks; + reg [83:0] Ki; + reg [63:0] Mi; + reg load_ks; + reg auth_mode; + reg [83:0] Kmod; + + always @ (posedge clk or posedge reset) begin + if (reset) + cstate <= INIT; + else + cstate <=#1 nstate; + end + + hdcp_lfsr lfsr( .clk(clk), .reset(reset), + .iv(auth_mode ? Ks[55:0] : Ki[55:0]), + .init_iv(load_lfsr), + .advance(advance_lfsr), + .onebit(lfsr_out)); + + hdcp_block block( .clk(clk), .reset(reset), + + .load(load_block), + .B(auth_mode ? {20'b0,An} : {20'b0,Mi}), + .K(Kmod), + .Bo(Bo_wire), + .rekey(rekey), + .lfsr_in(lfsr_out), + .ostream(ostream), + .advance(advance_block)); + assign pr_data = ostream; + + always @ (*) begin + case ({auth_mode,load_56}) //synthesis parallel_case full_case + 2'b00: begin // not auth mode, load 84 bits + Kmod = Ki; + end + 2'b01: begin // not auth mode, but load 56 bits only + Kmod = {28'b0,Ks[55:0]}; + end + 2'b10: begin // auth mode, load 84 bits + Kmod = Ks; + end + 2'b11: begin // auth mode, load only 56 bits + Kmod = {28'b0,Km[55:0]}; + end + endcase // case ({auth_mode,load_56}) + end // always @ (*) + + + always @ (*) begin + case (cstate) //synthesis parallel_case full_case + INIT: begin + nstate = hdcpBlockCipher_init ? BLOCK_1 : INIT; + end + BLOCK_1: begin + nstate = BLOCK_2; + end + BLOCK_2: begin + nstate = (statecnt >= 6'd47) ? BLOCK_3: BLOCK_2; + end + BLOCK_3: begin + nstate = BLOCK_4; + end + BLOCK_4: begin + nstate = BLOCK_5; + end + BLOCK_5: begin + nstate = BLOCK_6; + end + BLOCK_6: begin + nstate = BLOCK_7; + end + BLOCK_7: begin + nstate = BLOCK_8; + end + BLOCK_8: begin + nstate = (statecnt >= 6'd55) ? BLOCK_9: BLOCK_8; + end + BLOCK_9: begin + nstate = GET_M; + end + GET_M: begin + nstate = STREAM; + end + STREAM: begin + if( hdcpBlockCipher_init ) begin + nstate = BLOCK_1; + end else if( hdcpRekeyCipher ) begin + nstate = REKEY; + end else begin + nstate = STREAM; + end + end + REKEY: begin + if( hdcpBlockCipher_init ) begin + nstate = BLOCK_1; + end else begin + nstate = (statecnt >= 6'd55) ? STREAM : REKEY; + end + end + endcase // case (cstate) + end + + always @ (posedge clk or posedge reset) begin + if( reset ) begin + statecnt <=#1 6'b0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end else begin + case (cstate) // synthesis parallel_case full_case + INIT: begin + statecnt <=#1 6'b0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 authentication; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_1: begin + statecnt <=#1 6'b0; + rekey <=#1 1'b0; + load_block <=#1 1'b1; // load B & K regs of block module + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b1; + end + BLOCK_2: begin + statecnt <=#1 statecnt + 1; // 48 clocks + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b1; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_3: begin + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b1; // save Ks, Ki, and B=>K + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_4: begin + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b1; // dup of above + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_5: begin + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b1; // reload block cipher + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_6: begin + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b1; // init lfsr + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_7: begin + statecnt <=#1 0; + rekey <=#1 1'b1; // assert rekey + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_8: begin + statecnt <=#1 statecnt + 1; // 56 clocks + rekey <=#1 1'b1; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b1; + advance_block <=#1 1'b1; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + BLOCK_9: begin + statecnt <=#1 0; + rekey <=#1 1'b0; // de-assert rekey + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end // case: BLOCK_9 + GET_M: begin // one cycle wait to get M register loaded properly + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b0; + advance_block <=#1 1'b0; + load_ks <=#1 1'b0; + auth_mode <=#1 1'b0; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + STREAM: begin + statecnt <=#1 0; + rekey <=#1 1'b0; + load_block <=#1 1'b0; + advance_lfsr <=#1 hdcpStreamCipher; + advance_block <=#1 hdcpStreamCipher; + load_ks <=#1 1'b0; + auth_mode <=#1 authentication; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b1; + load_56 <=#1 1'b0; + end + REKEY: begin + statecnt <=#1 statecnt + 1; + rekey <=#1 1'b1; + load_block <=#1 1'b0; + advance_lfsr <=#1 1'b1; + advance_block <=#1 1'b1; + load_ks <=#1 1'b0; + auth_mode <=#1 auth_mode; + load_lfsr <=#1 1'b0; + stream_ready <=#1 1'b0; + load_56 <=#1 1'b0; + end + endcase // case (cstate) + end + end // always @ (posedge clk or posedge reset) + + always @(posedge clk or posedge reset) begin + if( reset ) begin + Ks <= 80'b0; + Ki <= 80'b0; + end else begin +// if( hdcpBlockCipher_init ) begin +// Ks <= (authentication | auth_mode) ? {28'b0,Km} : Ks; +// Ki <= 80'b0; +// end else if( load_ks && auth_mode ) begin + if( load_ks && auth_mode ) begin + Ks <= Bo_wire; + Ki <= 80'b0; + end else if( load_ks && !auth_mode ) begin + Ks <= Ks; + Ki <= Bo_wire; + end else begin + Ks <= Ks; + Ki <= Ki; + end + end + end // always @ (posedge clk or posedge reset) + + always @(posedge clk or posedge reset) begin + if( reset ) begin + Mi <= 80'b0; + end else begin + if( (cstate == BLOCK_8) || (cstate == BLOCK_9) || (cstate == GET_M) ) begin + Mi[15:0] <= ostream[15:0]; + Mi[31:16] <= Mi[15:0]; + Mi[47:32] <= Mi[31:16]; + Mi[63:48] <= Mi[47:32]; + end else begin + Mi <= Mi; + end + end // else: !if( reset ) + end // always @ (posedge clk or posedge reset) + +endmodule // hdcp_cipher diff --git a/hdcp/hdcp_lfsr.v b/hdcp/hdcp_lfsr.v new file mode 100755 index 0000000..a85d753 --- /dev/null +++ b/hdcp/hdcp_lfsr.v @@ -0,0 +1,196 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011, Andrew "bunnie" Huang +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +// lfsr module for hdcp cipher +module hdcp_lfsr( + input wire clk, + input wire reset, // this is just a low-level reset + + input wire [55:0] iv, // initial values + + input wire init_iv, // load initial values + input wire advance, // advance state one cycle + output wire onebit // my one-bit output + ); + + reg [12:0] lfsr0; + reg [13:0] lfsr1; + reg [15:0] lfsr2; + reg [16:0] lfsr3; + + wire [3:0] comb_tap0; + wire [3:0] comb_tap1; + wire [3:0] comb_tap2; + + always @(posedge clk or posedge reset) begin + if( reset == 1 ) begin + lfsr0 <= 13'b0; + lfsr1 <= 14'b0; + lfsr2 <= 16'b0; + lfsr3 <= 17'b0; + end else begin + if( init_iv ) begin + // assume bit-offsets start from 0 + lfsr0[12:0] <= {~iv[6],iv[11:0]}; + lfsr1[13:0] <= {~iv[18],iv[24:12]}; + lfsr2[15:0] <= {~iv[32],iv[39:25]}; + lfsr3[16:0] <= {~iv[47],iv[55:40]}; + end else if( advance ) begin + // 13 11 9 5 + // 12 10 8 4 + lfsr0[0 ] <= lfsr0[4] ^ lfsr0[8] ^ lfsr0[10] ^ lfsr0[12]; + lfsr0[1 ] <= lfsr0[0 ]; + lfsr0[2 ] <= lfsr0[1 ]; + lfsr0[3 ] <= lfsr0[2 ]; + lfsr0[4 ] <= lfsr0[3 ]; + lfsr0[5 ] <= lfsr0[4 ]; + lfsr0[6 ] <= lfsr0[5 ]; + lfsr0[7 ] <= lfsr0[6 ]; + lfsr0[8 ] <= lfsr0[7 ]; + lfsr0[9 ] <= lfsr0[8 ]; + lfsr0[10] <= lfsr0[9 ]; + lfsr0[11] <= lfsr0[10]; + lfsr0[12] <= lfsr0[11]; + + //4 6 7 10 11 14 + //3 5 6 9 10 13 + lfsr1[0 ] <= lfsr1[3] ^ lfsr1[5] ^ lfsr1[6] ^ lfsr1[9] ^ lfsr1[10] ^ lfsr1[13]; + lfsr1[1 ] <= lfsr1[0 ]; + lfsr1[2 ] <= lfsr1[1 ]; + lfsr1[3 ] <= lfsr1[2 ]; + lfsr1[4 ] <= lfsr1[3 ]; + lfsr1[5 ] <= lfsr1[4 ]; + lfsr1[6 ] <= lfsr1[5 ]; + lfsr1[7 ] <= lfsr1[6 ]; + lfsr1[8 ] <= lfsr1[7 ]; + lfsr1[9 ] <= lfsr1[8 ]; + lfsr1[10] <= lfsr1[9 ]; + lfsr1[11] <= lfsr1[10]; + lfsr1[12] <= lfsr1[11]; + lfsr1[13] <= lfsr1[12]; + + //5 7 8 12 15 16 + //4 6 7 11 14 15 + lfsr2[0 ] <= lfsr2[4] ^ lfsr2[6] ^ lfsr2[7] ^ lfsr2[11] ^ lfsr2[14] ^ lfsr2[15]; + lfsr2[1 ] <= lfsr2[0 ]; + lfsr2[2 ] <= lfsr2[1 ]; + lfsr2[3 ] <= lfsr2[2 ]; + lfsr2[4 ] <= lfsr2[3 ]; + lfsr2[5 ] <= lfsr2[4 ]; + lfsr2[6 ] <= lfsr2[5 ]; + lfsr2[7 ] <= lfsr2[6 ]; + lfsr2[8 ] <= lfsr2[7 ]; + lfsr2[9 ] <= lfsr2[8 ]; + lfsr2[10] <= lfsr2[9 ]; + lfsr2[11] <= lfsr2[10]; + lfsr2[12] <= lfsr2[11]; + lfsr2[13] <= lfsr2[12]; + lfsr2[14] <= lfsr2[13]; + lfsr2[15] <= lfsr2[14]; + + //5 11 15 17 + //4 10 14 16 + lfsr3[0 ] <= lfsr3[4] ^ lfsr3[10] ^ lfsr3[14] ^ lfsr3[16]; + lfsr3[1 ] <= lfsr3[0 ]; + lfsr3[2 ] <= lfsr3[1 ]; + lfsr3[3 ] <= lfsr3[2 ]; + lfsr3[4 ] <= lfsr3[3 ]; + lfsr3[5 ] <= lfsr3[4 ]; + lfsr3[6 ] <= lfsr3[5 ]; + lfsr3[7 ] <= lfsr3[6 ]; + lfsr3[8 ] <= lfsr3[7 ]; + lfsr3[9 ] <= lfsr3[8 ]; + lfsr3[10] <= lfsr3[9 ]; + lfsr3[11] <= lfsr3[10]; + lfsr3[12] <= lfsr3[11]; + lfsr3[13] <= lfsr3[12]; + lfsr3[14] <= lfsr3[13]; + lfsr3[15] <= lfsr3[14]; + lfsr3[16] <= lfsr3[15]; + end else begin + // hold state + lfsr0 <= lfsr0; + lfsr1 <= lfsr1; + lfsr2 <= lfsr2; + lfsr3 <= lfsr3; + end + end // else: !if( reset == 1 ) + end // always @ (posedge clk or posedge reset) + + assign comb_tap0[0] = lfsr0[3]; + assign comb_tap0[1] = lfsr1[4]; + assign comb_tap0[2] = lfsr2[5]; + assign comb_tap0[3] = lfsr3[5]; + + assign comb_tap1[0] = lfsr0[7]; + assign comb_tap1[1] = lfsr1[8]; + assign comb_tap1[2] = lfsr2[9]; + assign comb_tap1[3] = lfsr3[11]; + + assign comb_tap2[0] = lfsr0[12]; + assign comb_tap2[1] = lfsr1[13]; + assign comb_tap2[2] = lfsr2[15]; + assign comb_tap2[3] = lfsr3[16]; + + wire [3:0] sh_dout; + shuffle_network sh0 ( .clk(clk), .reset(reset), + .din(comb_tap0[0] ^ comb_tap0[1] ^ comb_tap0[2] ^ comb_tap0[3]), + .sel(comb_tap1[0]), + .advance(advance), + .init_iv(init_iv), + .dout(sh_dout[0]) + ); + + shuffle_network sh1 ( .clk(clk), .reset(reset), + .din(sh_dout[0]), + .sel(comb_tap1[1]), + .advance(advance), + .init_iv(init_iv), + .dout(sh_dout[1]) + ); + + shuffle_network sh2 ( .clk(clk), .reset(reset), + .din(sh_dout[1]), + .sel(comb_tap1[2]), + .advance(advance), + .init_iv(init_iv), + .dout(sh_dout[2]) + ); + + shuffle_network sh3 ( .clk(clk), .reset(reset), + .din(sh_dout[2]), + .sel(comb_tap1[3]), + .advance(advance), + .init_iv(init_iv), + .dout(sh_dout[3]) + ); + + assign onebit = sh_dout[3] ^ comb_tap2[0] ^ comb_tap2[1] ^ comb_tap2[2] ^ comb_tap2[3]; + +endmodule // hdcp_lfsr + diff --git a/hdcp/shuffle_network.v b/hdcp/shuffle_network.v new file mode 100755 index 0000000..f0c5315 --- /dev/null +++ b/hdcp/shuffle_network.v @@ -0,0 +1,59 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011, Andrew "bunnie" Huang +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +module shuffle_network ( + input wire clk, + input wire reset, + input wire din, + input wire sel, + input wire advance, + input wire init_iv, + output wire dout + ); + + reg a, b; + + always @(posedge clk or posedge reset) begin + if( reset == 1 ) begin + a <= 1'b0; + b <= 1'b1; + end else begin + if( init_iv ) begin + a <= 1'b0; + b <= 1'b1; + end else if( advance ) begin + a <= sel ? din : b; + b <= sel ? a : din; + end else begin + a <= a; + b <= b; + end + end // else: !if( reset == 1 ) + end // always @ (posedge clk or posedge reset) + + assign dout = sel ? b : a; + +endmodule // shuffle_network -- cgit v1.2.3