Driving Intermediate Cryptographic State/Results to Hardware Module Outputs

The product uses a hardware module implementing a cryptographic algorithm that writes sensitive information about the intermediate state or results of its cryptographic operations via one of its output wires (typically the output port containing the final result).


Demonstrations

The following examples help to illustrate the nature of this weakness and describe methods or techniques which can be used to mitigate the risk.

Note that the examples here are by no means exhaustive and any given weakness may have many subtle varieties, each of which may require different detection methods or runtime controls.

Example One

The following SystemVerilog code is a crypto module that takes input data and encrypts it by processing the data through multiple encryption rounds. Note: this example is derived from [REF-1469].

01 | module crypto_core_with_leakage
02 | (

  03 |     input  clk,
  04 |     input  rst,
  05 |     input  [127:0] data_i,
  06 |     output [127:0] data_o,
  07 |     output valid

08 | );
09 |
10 | localparam int total_rounds = 10;
11 | logic [3:0]   round_id_q;
12 | logic [127:0] data_state_q, data_state_d;
13 | logic [127:0] key_state_q, key_state_d;
14 |
15 | crypto_algo_round u_algo_round (

  16 |     .clk     (clk),
  17 |     .rst     (rst),
  18 |     .round_i (round_id_q  ),
  19 |     .key_i   (key_state_q ),
  20 |     .data_i  (data_state_q),
  21 |     .key_o   (key_state_d ),
  22 |     .data_o  (data_state_d)

23 | );
24 |
25 | always @(posedge clk) begin

  26 |     if (rst) begin

    27 |         data_state_q <= 0;
    28 |         key_state_q  <= 0;
    29 |         round_id_q   <= 0;

  30 |     end
  31 |     else begin

    32 |         case (round_id_q)

      33 |             total_rounds: begin

        34 |                 data_state_q <= 0;
        35 |                 key_state_q  <= 0;
        36 |                 round_id_q   <= 0;

      37 |             end
      38 |
      39 |             default: begin

        40 |                 data_state_q <= data_state_d;
        41 |                 key_state_q  <= key_state_d;
        42 |                 round_id_q   <= round_id_q + 1;

      43 |             end

    44 |         endcase

  45 |     end

46 | end
47 |
48 | assign valid  = (round_id_q == total_rounds) ? 1'b1 : 1'b0;
49 |
50 | assign data_o = data_state_q;
51 |
52 | endmodule

In line 50 above, data_state_q is assigned to data_o. Since data_state_q contains intermediate state/results, this allows an attacker to obtain these results through data_o.

In line 50 of the fixed logic below, while "data_state_q" does not contain the final result, a "sanitizing" mechanism drives a safe default value (i.e., 0) to "data_o" instead of the value of "data_state_q". In doing so, the mechanism prevents the exposure of intermediate state/results which could be used to break soundness of the cryptographic operation being performed. A real-world example of this weakness and mitigation can be seen in a pull request that was submitted to the OpenTitan Github repository [REF-1469].

01 | module crypto_core_without_leakage
02 | (

  03 |     input  clk,
  04 |     input  rst,
  05 |     input  [127:0] data_i,
  06 |     output [127:0] data_o,
  07 |     output valid
  08 | );

09 |
10 | localparam int total_rounds = 10;
11 | logic [3:0]   round_id_q;
12 | logic [127:0] data_state_q, data_state_d;
13 | logic [127:0] key_state_q, key_state_d;
14 |
15 | crypto_algo_round u_algo_round (

  16 |     .clk     (clk),
  17 |     .rst     (rst),
  18 |     .round_i (round_id_q  ),
  19 |     .key_i   (key_state_q ),
  20 |     .data_i  (data_state_q),
  21 |     .key_o   (key_state_d ),
  22 |     .data_o  (data_state_d)

23 | );
24 |
25 | always @(posedge clk) begin

  26 |     if (rst) begin

    27 |         data_state_q <= 0;
    28 |         key_state_q  <= 0;
    29 |         round_id_q   <= 0;

  30 |     end
  31 |     else begin

    32 |         case (round_id_q)

      33 |             total_rounds: begin

        34 |                 data_state_q <= 0;
        35 |                 key_state_q  <= 0;
        36 |                 round_id_q   <= 0;

      37 |             end
      38 |
      39 |             default: begin

        40 |                 data_state_q <= data_state_d;
        41 |                 key_state_q  <= key_state_d;
        42 |                 round_id_q   <= round_id_q + 1;

      43 |             end

    44 |         endcase

  45 |     end

46 | end
47 |
48 | assign valid  = (round_id_q == total_rounds) ? 1'b1 : 1'b0;
49 |
50 | assign data_o = (valid) ? data_state_q : 0;
51 |
52 | endmodule

See Also

Comprehensive Categorization: Sensitive Information Exposure

Weaknesses in this category are related to sensitive information exposure.

Security Primitives and Cryptography Issues

Weaknesses in this category are related to hardware implementations of cryptographic protocols and other hardware-security primitives such as physical unclonable funct...

Comprehensive CWE Dictionary

This view (slice) covers all the elements in CWE.

Weaknesses Introduced During Implementation

This view (slice) lists weaknesses that can be introduced during implementation.

Weakness Base Elements

This view (slice) displays only weakness base elements.


Common Weakness Enumeration content on this website is copyright of The MITRE Corporation unless otherwise specified. Use of the Common Weakness Enumeration and the associated references on this website are subject to the Terms of Use as specified by The MITRE Corporation.