当前位置:   article > 正文

SM3杂凑算法的verilog实现(附免费可用代码)_sm3 verilog实现

sm3 verilog实现

        SM3算法作为我国自主要发设计的密码杂凑算法,输出消息摘要值长度为 256bit,消息分组长度512bit,迭代压缩次数64次。在算法的硬件实现中,信息需要经过消息填充、扩展生成消息字和轮函数迭代压缩。因此硬件结构模块划分为:消息填充模块、消息扩展模块和迭代压缩模块。

       消息填充模块将输入的明文数据按照规则填充,并分成512bit一组的模块,是 SM3 杂凑算法的基础组成部分。消息填充模块每次输入32 bit,当输入不是最后一个字时,将输入字直接输出,否则判断输入字节寄存器中值,并进行相应的填充。

        消息扩展模块用来产生消息字 Wj和 Wj’,并将轮函数需要的消息字送入到指定位置,该部分是SM3算法硬件结构中的重要模块。由于在后续迭代计算中需要使用消息字参与计算,为降低迭代压缩的操作时间,需要提前生成消息字,在设定节拍送入迭代压缩模块。为减少寄存器的使用数目,本设计采取复用的方式减少寄存器的使用数量。在该设计中,每次生成两个新的消息字保证下一个周期消息字的产生。

        迭代函数作为杂凑算法的核心处理部分在硬件设计中非常重要。SM3算法的迭代函数共有64轮,根据对算法的分析可以看出,对每一个消息分组的运算而言,将迭代展开直接计算无疑是最节省时间的。因为运算路径中没有其它多余元件(例如寄存器)的插入,所以路径是最短的。但是这种将循环迭代展开的方式对大大减少了硬件资源的使用,占用面积很大。E203 RISC-V处理器主要用于低功耗、低面积的嵌入式应用,所以本设计采用了循环结构的设计方式,这种方式的占用面积小,但需要64个时钟周期才能完成一个消息分组的迭代。

        由于最后一个字节的消息经过消息填充模块后可能扩展出两个消息分组,而迭代压缩模块只能处理一个消息分组,所以需要增加一个fifo对最后一个消息分组进行存储。

下面是各模块的verilog代码。

消息填充模块:

  1. module msg_padding (
  2. input clk,rst_n,
  3. input msg_padding_en,
  4. input [31:0] msg_in,
  5. input msg_in_vld,
  6. input msg_is_last_word,
  7. input [1:0] msg_bytes_num, //00:x000 01:xx00 10:xxx0 11:xxxx
  8. output reg [31:0] pad_result,
  9. output reg res_vld,
  10. output reg pad_done
  11. );
  12. localparam DIRECT = 3'd0;
  13. localparam CASE_80 = 3'd1;
  14. localparam CASE_00 = 3'd2;
  15. localparam CASE_LH = 3'd3;
  16. localparam CASE_LL = 3'd4;
  17. reg [2:0] state_r;
  18. reg [3:0] gene_counter;
  19. reg [63:0] bit_counter;
  20. wire [3:0] gcnt_add1 = gene_counter+1'b1;
  21. wire [2:0] bcnt_add_num = {~msg_is_last_word|(msg_bytes_num==2'b11),
  22. msg_is_last_word&((msg_bytes_num==2'b01)|(msg_bytes_num==2'b10)),
  23. msg_is_last_word&~msg_bytes_num[0]};
  24. wire [63:0] bcnt_adder = bit_counter+{bcnt_add_num,3'd0};
  25. wire msg_bn_00 = (msg_bytes_num==2'b00);
  26. wire msg_bn_01 = (msg_bytes_num==2'b01);
  27. wire msg_bn_10 = (msg_bytes_num==2'b10);
  28. wire msg_bn_11 = (msg_bytes_num==2'b11);
  29. always @(posedge clk,negedge rst_n) begin
  30. if(~rst_n)begin
  31. state_r<=DIRECT;
  32. res_vld<=1'b0;
  33. gene_counter<=4'd0;
  34. bit_counter<=64'd0;
  35. pad_result<=32'd0;
  36. pad_done<=1'b0;
  37. end
  38. else if(msg_padding_en)begin
  39. case (state_r)
  40. DIRECT:begin
  41. if(msg_in_vld)begin
  42. res_vld<=1'b1;
  43. bit_counter<=bcnt_adder;
  44. gene_counter<=gcnt_add1;
  45. if(msg_is_last_word)begin
  46. if(msg_bn_00)begin
  47. pad_result<={msg_in[31:24],24'h800000};
  48. state_r<=CASE_00;
  49. end
  50. if(msg_bn_01)begin
  51. pad_result<={msg_in[31:16],16'h8000};
  52. state_r<=CASE_00;
  53. end
  54. if(msg_bn_10)begin
  55. pad_result<={msg_in[31:8],8'h80};
  56. state_r<=CASE_00;
  57. end
  58. if(msg_bn_11)begin
  59. pad_result<=msg_in;
  60. state_r <= CASE_80;
  61. end
  62. end
  63. else pad_result<=msg_in;
  64. if(gene_counter==4'd15)
  65. pad_done<=1'b1;
  66. else pad_done<=1'b0;
  67. end
  68. else begin
  69. res_vld<=1'b0;
  70. pad_done<=1'b0;
  71. end
  72. end
  73. CASE_80:begin
  74. pad_result<=32'h8000_0000;
  75. gene_counter<=gcnt_add1;
  76. if(gene_counter==4'd13)
  77. state_r<=CASE_LH;
  78. else state_r<=CASE_00;
  79. end
  80. CASE_00:begin
  81. gene_counter<=gcnt_add1;
  82. pad_result<=32'd0;
  83. if(gene_counter==4'd13)
  84. state_r<=CASE_LH;
  85. end
  86. CASE_LH:begin
  87. pad_result<=bit_counter[63:32];
  88. state_r<=CASE_LL;
  89. end
  90. CASE_LL:begin
  91. pad_result<=bit_counter[31:0];
  92. gene_counter<=4'd0;
  93. bit_counter<=64'd0;
  94. pad_done<=1'b1;
  95. state_r<=DIRECT;
  96. end
  97. default:state_r<=DIRECT;
  98. endcase
  99. end
  100. end
  101. endmodule

消息扩展模块:

  1. module msg_expansion (
  2. input clk,rst_n,
  3. input msg_expansion_en,
  4. input [31:0] msg_expansion_in,
  5. input msg_in_vld,
  6. output msg_in_ready,
  7. output [31:0] wj0,wj1,
  8. output res_vld
  9. );
  10. wire state_is_padreg;
  11. wire state_is_genw16;
  12. reg [6:0] counter;
  13. reg [31:0] w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15;
  14. wire [31:0] tmp0 = w0^w7^{w13[16:0],w13[31:17]};
  15. wire [31:0] tmp1 = tmp0^{tmp0[16:0],tmp0[31:17]}^{tmp0[8:0],tmp0[31:9]};
  16. wire [31:0] w16 = tmp1^{w3[24:0],w3[31:25]}^w10;
  17. assign state_is_padreg = counter<=7'd15;
  18. assign state_is_genw16 = ~state_is_padreg;
  19. assign wj0 = w11;
  20. assign wj1 = wj0^w15;
  21. assign res_vld = (counter>=7'd5);
  22. assign msg_in_ready=state_is_padreg;
  23. always @(posedge clk,negedge rst_n)begin
  24. if(~rst_n){w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15}<=512'd0;
  25. else if(msg_expansion_en)begin
  26. if(state_is_padreg&msg_in_vld)
  27. {w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15}<={w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,msg_expansion_in};
  28. else if(state_is_genw16)
  29. {w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15}<={w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16};
  30. else {w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15}<={w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15};
  31. end
  32. end
  33. always @(posedge clk,negedge rst_n)begin
  34. if(~rst_n)counter<=7'd0;
  35. else if(msg_expansion_en)begin
  36. if((state_is_padreg&msg_in_vld)|state_is_genw16)
  37. counter <= (counter==7'd68)?7'd0:(counter+1'b1);
  38. else counter<=counter;
  39. end
  40. end
  41. endmodule

迭代压缩模块:

  1. module msg_compression (
  2. input clk,rst_n,
  3. input msg_compression_en,
  4. input [31:0] wj0,wj1,
  5. input msg_in_vld,
  6. input last_block,
  7. output [31:0] hash,
  8. output reg res_vld,
  9. output reg one_block_done
  10. );
  11. localparam A0=32'h7380166f;
  12. localparam B0=32'h4914b2b9;
  13. localparam C0=32'h172442d7;
  14. localparam D0=32'hda8a0600;
  15. localparam E0=32'ha96f30bc;
  16. localparam F0=32'h163138aa;
  17. localparam G0=32'he38dee4d;
  18. localparam H0=32'hb0fb0e4e;
  19. localparam TJ0=32'h79cc4519;
  20. localparam TJ1=32'h7a879d8a;
  21. reg [31:0] IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7;
  22. reg [31:0] A,B,C,D,E,F,G,H;
  23. reg [5:0] index_j;
  24. wire [255:0] IV_AH;
  25. reg [31:0] Tj0,Tj1;
  26. wire j_less16 = (index_j<=6'd15);
  27. wire j_equal7 = (index_j==6'd7);
  28. wire j_equal63= (index_j==6'd63);
  29. wire [31:0] Tj_shift=j_less16?Tj0:Tj1;
  30. wire [31:0] ss0,cc0;
  31. wire [31:0] tmp_for_ss1=ss0+cc0;
  32. wire [31:0] SS1={tmp_for_ss1[24:0],tmp_for_ss1[31:25]};
  33. wire [31:0] SS2=SS1^{A[19:0],A[31:20]};
  34. wire [31:0] FFj=j_less16?(A^B^C):((A&B)|(A&C)|(B&C));
  35. wire [31:0] GGj=j_less16?(E^F^G):((E&F)|(~E&G));
  36. wire [31:0] s0,c0,s1,c1,s2,c2,s3,c3;
  37. wire [31:0] TT1=s1+c1;
  38. wire [31:0] TT2=s3+c3;
  39. assign s0=FFj^D^SS2;
  40. assign c0=((FFj&D)|(FFj&SS2)|(D&SS2))<<1;
  41. assign s1=s0^c0^wj1;
  42. assign c1=((s0&c0)|(s0&wj1)|(c0&wj1))<<1;
  43. assign s2=GGj^H^SS1;
  44. assign c2=((GGj&H)|(GGj&SS1)|(H&SS1))<<1;
  45. assign s3=s2^c2^wj0;
  46. assign c3=((s2&c2)|(s2&wj0)|(c2&wj0))<<1;
  47. assign ss0={A[19:0],A[31:20]}^E^Tj_shift;
  48. assign cc0=(({A[19:0],A[31:20]}&E)|({A[19:0],A[31:20]}&Tj_shift)|(E&Tj_shift))<<1;
  49. assign IV_AH={IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7}^{A,B,C,D,E,F,G,H};
  50. assign hash=IV0;
  51. always @(posedge clk,negedge rst_n) begin
  52. if(~rst_n){A,B,C,D,E,F,G,H}<={A0,B0,C0,D0,E0,F0,G0,H0};
  53. else begin
  54. if(msg_compression_en&msg_in_vld)
  55. {A,B,C,D,E,F,G,H}<={
  56. TT1,A,{B[22:0],B[31:23]},C,
  57. TT2^{TT2[22:0],TT2[31:23]}^{TT2[14:0],TT2[31:15]},
  58. E,{F[12:0],F[31:13]},G
  59. };
  60. if(one_block_done) {A,B,C,D,E,F,G,H}<=IV_AH;
  61. if(res_vld&j_equal7)
  62. {A,B,C,D,E,F,G,H}<={A0,B0,C0,D0,E0,F0,G0,H0};
  63. end
  64. end
  65. always @(posedge clk,negedge rst_n) begin
  66. if(~rst_n){IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7}<={A0,B0,C0,D0,E0,F0,G0,H0};
  67. else begin
  68. if(one_block_done)
  69. {IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7}<=IV_AH;
  70. if(res_vld&~j_equal7)
  71. {IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7}<={IV1,IV2,IV3,IV4,IV5,IV6,IV7,32'd0};
  72. if(res_vld&j_equal7)
  73. {IV0,IV1,IV2,IV3,IV4,IV5,IV6,IV7}<={A0,B0,C0,D0,E0,F0,G0,H0};
  74. end
  75. end
  76. always @(posedge clk,negedge rst_n) begin
  77. if(~rst_n)index_j<=6'd0;
  78. else begin
  79. if((msg_compression_en&msg_in_vld)|(res_vld&~j_equal7))
  80. index_j<=index_j+1'b1;
  81. if(res_vld&j_equal7)
  82. index_j<=6'd0;
  83. end
  84. end
  85. always @(posedge clk,negedge rst_n) begin
  86. if(~rst_n)Tj0<=TJ0;
  87. else if(msg_compression_en&msg_in_vld)
  88. Tj0<={Tj0[30:0],Tj0[31]};
  89. end
  90. always @(posedge clk,negedge rst_n) begin
  91. if(~rst_n)Tj1<=TJ1;
  92. else if(msg_compression_en&msg_in_vld)
  93. Tj1<={Tj1[30:0],Tj1[31]};
  94. end
  95. always @(posedge clk,negedge rst_n) begin
  96. if(~rst_n)res_vld<=1'b0;
  97. else if(msg_compression_en)begin
  98. if(res_vld)res_vld<=~j_equal7;
  99. else res_vld<=last_block&one_block_done;
  100. end
  101. end
  102. always @(posedge clk,negedge rst_n) begin
  103. if(~rst_n)one_block_done<=1'b0;
  104. else one_block_done<=msg_compression_en&msg_in_vld&j_equal63;
  105. end
  106. endmodule

FIFO模块:

  1. module sm3_fifo # (
  2. parameter DP = 8,
  3. parameter DW = 32
  4. ) (
  5. input i_vld,
  6. output i_rdy,
  7. input [DW-1:0] i_dat,
  8. output o_vld,
  9. input o_rdy,
  10. output [DW-1:0] o_dat,
  11. input clk,
  12. input rst_n
  13. );
  14. genvar i;
  15. generate
  16. reg [DW-1:0] fifo_rf_r [DP-1:0];
  17. wire [DP-1:0] fifo_rf_en;
  18. wire wen = i_vld & i_rdy;
  19. wire ren = o_vld & o_rdy;
  20. wire [DP-1:0] rptr_vec_nxt;
  21. reg [DP-1:0] rptr_vec_r;
  22. wire [DP-1:0] wptr_vec_nxt;
  23. reg [DP-1:0] wptr_vec_r;
  24. assign rptr_vec_nxt = rptr_vec_r[DP-1]?{{DP-1{1'b0}},1'b1}:(rptr_vec_r<<1);
  25. assign wptr_vec_nxt = wptr_vec_r[DP-1]?{{DP-1{1'b0}},1'b1}:(wptr_vec_r<< 1);
  26. always @(posedge clk,negedge rst_n) begin
  27. if(~rst_n)rptr_vec_r<=1'b1;
  28. else if(ren)
  29. rptr_vec_r<=rptr_vec_nxt;
  30. end
  31. always @(posedge clk,negedge rst_n) begin
  32. if(~rst_n)wptr_vec_r<=1'b1;
  33. else if(wen)
  34. wptr_vec_r<=wptr_vec_nxt;
  35. end
  36. wire [DP:0] i_vec;
  37. wire [DP:0] o_vec;
  38. wire [DP:0] vec_nxt;
  39. reg [DP:0] vec_r;
  40. wire vec_en = (ren ^ wen );
  41. assign vec_nxt = wen ? {vec_r[DP-1:0], 1'b1} : (vec_r >> 1);
  42. always @(posedge clk,negedge rst_n) begin
  43. if(~rst_n)vec_r<=1'b1;
  44. else if(vec_en)
  45. vec_r<=vec_nxt;
  46. end
  47. assign i_vec = {1'b0,vec_r[DP:1]};
  48. assign o_vec = {1'b0,vec_r[DP:1]};
  49. assign i_rdy = (~i_vec[DP-1]);
  50. for (i=0; i<DP; i=i+1) begin:fifo_rf
  51. assign fifo_rf_en[i] = wen & wptr_vec_r[i];
  52. always @(posedge clk) begin
  53. if(fifo_rf_en[i])fifo_rf_r[i]<=i_dat;
  54. end
  55. end
  56. integer j;
  57. reg [DW-1:0] mux_rdat;
  58. always @*
  59. begin : rd_port_PROC
  60. mux_rdat = {DW{1'b0}};
  61. for(j=0; j<DP; j=j+1) begin
  62. mux_rdat = mux_rdat | ({DW{rptr_vec_r[j]}} & fifo_rf_r[j]);
  63. end
  64. end
  65. assign o_dat = mux_rdat;
  66. assign o_vld = (o_vec[0]);
  67. endgenerate
  68. endmodule

顶层模块:

  1. module sm3_top (
  2. input clk,rst_n,
  3. input sm3_en,
  4. input [31:0] msg_in,
  5. input msg_in_vld,
  6. input msg_is_last_word,
  7. input [1:0] msg_bytes_num,
  8. output one_block_done,
  9. output [31:0] msg_hash,
  10. output msg_hash_vld
  11. );
  12. wire [31:0] pad_result;
  13. wire [31:0] msg_expansion_in;
  14. wire pad_res_vld,pad_done;
  15. wire expansion_in_vld;
  16. wire expansion_in_rdy;
  17. wire exp_res_vld;
  18. wire [31:0] wj0,wj1;
  19. reg last_word_in,last_block;
  20. always @(posedge clk,negedge rst_n) begin
  21. if(~rst_n)last_word_in<=1'b0;
  22. else if(sm3_en)
  23. last_word_in<=last_word_in?~msg_hash_vld:msg_is_last_word;
  24. end
  25. always @(posedge clk,negedge rst_n) begin
  26. if(~rst_n)last_block<=1'b0;
  27. else if(sm3_en)
  28. last_block<=last_block?~msg_hash_vld:(last_word_in&~expansion_in_rdy&~expansion_in_vld);
  29. end
  30. msg_padding u_msg_padding(
  31. .clk(clk),
  32. .rst_n(rst_n),
  33. .msg_padding_en(sm3_en),
  34. .msg_in(msg_in),
  35. .msg_in_vld(msg_in_vld),
  36. .msg_is_last_word(msg_is_last_word),
  37. .msg_bytes_num(msg_bytes_num),
  38. .pad_result(pad_result),
  39. .res_vld(pad_res_vld),
  40. .pad_done(pad_done)
  41. );
  42. msg_expansion u_msg_expansion(
  43. .clk(clk),
  44. .rst_n(rst_n),
  45. .msg_expansion_en(sm3_en),
  46. .msg_expansion_in(msg_expansion_in),
  47. .msg_in_vld(expansion_in_vld),
  48. .msg_in_ready(expansion_in_rdy),
  49. .wj0(wj0),
  50. .wj1(wj1),
  51. .res_vld(exp_res_vld)
  52. );
  53. msg_compression u_msg_compression(
  54. .clk(clk),
  55. .rst_n(rst_n),
  56. .msg_compression_en(sm3_en),
  57. .wj0(wj0),
  58. .wj1(wj1),
  59. .msg_in_vld(exp_res_vld),
  60. .last_block(last_block),
  61. .hash(msg_hash),
  62. .res_vld(msg_hash_vld),
  63. .one_block_done(one_block_done)
  64. );
  65. sm3_fifo #(.DP(32)) fifo_paddout(
  66. .i_vld(pad_res_vld),
  67. .i_rdy(),
  68. .i_dat(pad_result),
  69. .o_vld(expansion_in_vld),
  70. .o_rdy(expansion_in_rdy),
  71. .o_dat(msg_expansion_in),
  72. .clk(clk),
  73. .rst_n(rst_n)
  74. );
  75. endmodule

使用两个标准测试向量进行仿真,其结果如下:

 

 在Cyclone III ,型号为EP3C16F484I7的资源占用及最高频率如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/139570
推荐阅读
相关标签
  

闽ICP备14008679号