Thứ Năm, 3 tháng 10, 2019

[AES] Bài 3 - Thiết kế bộ mã hóa AES-128

Bài viết này trình bày chi tiết về cách thiết kế bộ mã hóa AES-128. Trước khi đọc bài này, các bạn cần xem lại các bài trước trình bày về lý thuyết mã hóagiải mã AES-128.

1) Mô tả tổng quan thiết kế
Bộ mã hóa AES-128, aes128_cipher_top, được thiết kế gồm 2 khối:
  • Khối mã hóa dữ liệu aes128_cipher_core
  • Khối tính toán tạo khóa vòng aes128_key_expansion
Bộ mã hóa gồm các tín hiệu giao tiếp sau:
  • clk_sys: clock đồng bộ
  • rst_n: reset tích cực mức thấp
  • cipher_key[127:0]: khóa mã
  • plain_text[127:0]: dữ liệu cần mã hóa, bản rõ
  • cipher_en: tín hiệu cho phép bộ mã hóa hoạt động, tích cực 1 chu kỳ xung clock clk_sys để yêu cầu bộ mã hóa hoạt động
  • cipher_ready: báo trạng thái bộ mã hóa sẵn sàng hoạt động. Tín hiệu này chỉ bằng 0 khi bộ mã hóa đang trong quá trình mã hóa dữ liệu.
  • cipher_text[127:0]: dữ liệu sau khi được mã hóa, bản mã.
Các tín hiệu giao tiếp giữa khối aes128_cipher_core aes128_key_expansion:
  • rkey_en: tín hiệu cho phép khối aes128_key_expansion hoạt động
  • round_num[3:0]: tín hiệu báo vòng lặp mã hóa hiện tại, round_num[3:0]=0 là bước khởi tạo đầu tiên.
  • round_key_out[127:0] là giá trị khóa vòng từ khối aes128_key_expansion gửi cho khối aes128_cipher_core.
Bên cạnh đó, thiết kế sử dụng một số function được đặt trong các file sau:
  • aes128_mul.sv: file chưa các function nhân
  • aes128_sbox.sv: file chứa function tra bảng S-BOX
  • aes128_rcon.sv: file chứa function chọn giá trị Rcon

Hình 1: Sơ đồ khối bộ mã hóa AES-128
2) Mạch logic khối aes128_key_expansion

Khối này thực hiện chức năng KeyExpansion đã trình bày ở bài 1.
Khối này sử dụng một thanh ghi round_key_reg[127:0] để lưu lại giá trị khóa vòng sau mỗi lần tính toán.
Các bạn hãy xem từ MUX, dưới cùng của hình, lên sẽ hình dung được hoạt động của mỗi lần lặp tính khóa vòng (round key).
round_num[3:0] sẽ cho biết khóa vòng thứ mấy đang được tính, nếu nó bằng 0 thì khóa mã gốc cipher_key[127:0] sẽ nối đến key_in[127:0] và đưa vào mạch logic để tính khóa vòng đầu tiên.
Từ lần tính tiếp theo trở đi, round_num[3:0] bằng 1 đến 10, giá trị được dùng để tính toán sẽ lấy từ thanh ghi round_key_reg[127:0].
Ở đây 32 bit cuối, ứng với w[3] (w[0] là 32 bit đầu [127:96]), sẽ được biến đổi qua các bước:
  • RotWord: đảo byte MSB xuống LSB
  • SubWord: ứng với function aes128_sbox()
  • AddRcon: lấy ngõ ra SubWord XOR với giá trị Rcon chọn từ function aes128_rcon(). Function này chọn Rcon theo giá trị của round_num[3:0]
Kết quả sau khi AddRcon sẽ được dùng để tạo ra các word của round_key[127:0] và lưu vào thanh ghi round_key_reg[127:0].

Hình 2: Mạch logic khối aes128_key_expansion
3) Mạch logic khối mã hóa aes128_cipher_core

Khối này sử dụng một bộ đếm để điều khiển quá trình mã hóa. Bộ đếm sẽ bắt đầu hoạt động khi cipher_en=1. Sau đó, nó sẽ đếm lên trong suốt quá trình mã hóa, ứng với rkey_en=1, khi đó cipher_ready=0. Bộ đếm bị xóa tại vòng lặp mã hóa thứ 10, bước tính cuối cùng của mã hóa AES-128.
Bên cạnh đó, bit cipher_ready, tín hiệu báo trạng thái mã hóa sẽ bằng 0 trong suốt quá trình mã hóa và tích cực 1 khi quá trình mã hóa kết thúc.

Hình 3: Bộ đếm giám sát quá trình mã hóa cipher_counter[3:0] và bit báo trạng thái sẵn sàng của bộ mã hóa
Bộ đếm cipher_counter[3:0] và bit trạng thái cipher_ready sẽ tạo ra các tín hiệu điều khiển quá trình mã hóa.
Mạch logic bộ mã hóa AES-128 gồm 1 thanh ghi cipherText_reg[127:0] lưu lại giá trị sau mỗi vòng lặp mã hóa, thanh ghi này đặt sau chức năng AddRoundKey.
Chúng ta bắt đầu từ tín hiệu after_addRoundkey[127:0], tín hiệu này được tạo ra từ 1 cổng XOR, đây là chức năng addRoundKey, với các ngõ vào được lấy từ:
  • Khóa mã, cipher_key[127:0], và bản rõ, plain_text[127:0] cho lần tính đầu tiên khi cipher_en=1.
  • Khóa vòng, round_key[127:0], và bản mã trung gian cho các lần tính tiếp theo, sau lần đầu tiên. Trong đó, bản mã trung gian lấy từ:
    • Ngõ ra chức năng MixColumns nếu đây là lần lặp cuối cùng, lần thứ 10.
    • Ngõ vào chức năng MixColumns, ứng với ngõ ra chức năng ShiftRows, nếu đây là lần lặp từ 1 đến 9.
after_addRoundkey[127:0] sẽ được lưu vào thanh ghi cipherText_reg[127:0] sau mỗi lần tính toán. Giá trị thanh ghi này sẽ lần lượt đi qua các chức năng:
  • SubBytes: tính bằng function aes128_sbox()
  • ShiftRows: chuyển đổi vị trí các byte trong 1 hàng
  • MixColumns: tính bằng function mixcol()
Chi tiết về các function, các bạn có thể tìm thấy trong RTL code.


Hình 4: Mạch nguyên lý bộ mã hóa AES-128
4) Kết quả tổng hợp trên FPGA

RTL code đã được tổng hợp trên Quartus II (Altera-Intel).
Hình 5: Thông tin tổng hợp trên Quartus II
5) Mô phỏng và kiểm chứng kết quả

Tác giả chưa xây dựng một môi trường mô phỏng với đầy đủ các trường hợp. Các bạn có thể dùng testbench đơn giản sau đây để kiểm chứng các trường hợp mong muốn.
module tb_cipher_top;
  //input
  reg clk_sys;
  reg rst_n;
  reg [127:0] cipher_key;
  reg [127:0] plain_text;
  reg cipher_en;
  //output
  wire [127:0] cipher_text;
  wire         cipher_ready;
  //
  aes128_cipher_top aes128_cipher_top(
  //input
  clk_sys,
  rst_n,
  cipher_key,
  plain_text,
  cipher_en,
  //output
  cipher_text,
  cipher_ready
  );

  initial begin    clk_sys = 0;
    rst_n = 0;
    cipher_key = 0;
    plain_text = 0;
    cipher_en = 0;
  end  initial begin    forever #5 clk_sys = ~clk_sys;
  end  initial begin    #16
    rst_n = 1;
    #10
    cipher_en = 1;
    plain_text = 128'h00112233445566778899aabbccddeeff;    cipher_key = 128'h000102030405060708090a0b0c0d0e0f; 
    #10
    cipher_en = 0;
    #120
    $display ("---- cipher_text: %32h - READY: %1b\n", cipher_text[127:0], cipher_ready);
    #10
    cipher_en = 1;
    plain_text = 128'h00112233445566778899aabbccddeeff;    cipher_key = 128'ha5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5; 
    #10
    cipher_en = 0;
    #120
    $display ("---- cipher_text: %32h - READY: %1b\n", cipher_text[127:0], cipher_ready);
    $stop;
  end
endmodule
Trong test này, tác giả chỉ để 2 trường hợp giúp bạn nào quan tâm có thể thử nhanh. Kết quả chạy mô phỏng như sau:
# ---- cipher_text: 69c4e0d86a7b0430d8cdb78070b4c55a - READY: 1 
# ---- cipher_text: daba0685a6b6ef1d096f7980accf3ac5 - READY: 1
Các bạn dùng trang web sau đây để kiểm chứng kết quả.
http://testprotect.com/appendix/AEScalc

Dữ liệu có thể tải:
Source code trên GitHub

Lịch sử cập nhật:
1) 2019.10.03 - Tạo lần đầu

1 bình luận: