32 8 bit RSA encryption

32 : 8 bit RSA encryption

Design render
  • Author: Caio Alonso da Costa
  • Description: 8 bit RSA encryption coprocessor with SPI interface
  • GitHub repository
  • Clock: 50000000 Hz

How it works

This project consists of an 8-bit RSA verilog design that implements the RSA (https://en.wikipedia.org/wiki/RSA_(cryptosystem)) encryption/decryption scheme with an 8-bit private/public key size.

The design implements modular exponentiation (https://en.wikipedia.org/wiki/Modular_exponentiation) through a series of Montgomery modular multiplication (https://en.wikipedia.org/wiki/Montgomery_modular_multiplication) to encrypt/decrypt a message using an 8-bit key.

Due to I/O constraints, a SPI slave peripheral has been created to load/read data into/from the design.

The SPI Slave peripheral implementation supports all 4 SPI mode of operations (CPOL is configurable through ui[2] and CPHA is configurable through ui[3]), 8 Configurable (Read/Write) 8-bit registers and 8 Status (Read only) 8-bit registers.

The RP2040 SPI1 peripheral shall be used to communicate with the RSA core. Configure RP2040 SPI1 peripheral to GPIOs 24 to 27.

SPI Limitations:

  • Single register access per SPI transaction.
  • SPI transaction is limited to 16 bits transfer at a time (Addr + Data). Please refer to Protocol for timing diagrams.
  • Design tested for 8 configuration registers + 8 status registers.
  • Even though the number of configuration registers and status registers is configurable, design only supports equal number of configuration and status registers for now.
  • Writes targeting Read Only address are dropped, i.e., no configuration registers gets updated.

Address Space:

Address Type of register
0 Configurable Read/Write register [0]
1 Configurable Read/Write register [1] - bit[1] Stop, bit[0] Start - Rising edge detector to trigger encryption/decryption
2 Configurable Read/Write register [2] - Plain text [7:0]
3 Configurable Read/Write register [3] - E [7:0]
4 Configurable Read/Write register [4] - M [7:0]
5 Configurable Read/Write register [5] - Montgomery Constant [7:0]
6 Configurable Read/Write register [6]
7 Configurable Read/Write register [7] - Spare [7:0] - Connected to 7-segment Display
8 Status Read Only register [0] - bit[0] IRQ - Encryption/decryption completed
9 Status Read Only register [1] - Fixed data 8'hC4
10 Status Read Only register [2] - Fixed data 8'h10
11 Status Read Only register [3] - Fixed data 8'hDE
12 Status Read Only register [4] - Fixed data 8'hAD
13 Status Read Only register [5] - Fixed data 8'h00
14 Status Read Only register [6] - Encrypted/Decrypted data [7:0]
15 Status Read Only register [7] - Fixed data 8'hFF

Connection

RP2040 SPI Master <--SPI--> SPI_WRAPPER <--regaccess--> User logic (RSA)

  • SPI: MOSI MISO SCLK CS
  • regaccess: config_regs (used to drive/control user logic), status_regs (used to read/monitor user logic)

Protocol

SPI settings

  • Address Bits = 4 and Databits = 8, MSB First
  • Tested SPI frequency: spi_clk <= clk / 20

SPI commands

  • Write data cmd = 0x80+addr, addr = 0 ~ 7
    Bit:       | <15>      <14>         <13>         <12>        <11>     <10>       <9>       <8>       <7>       <6>       <5>       <4>       <3>       <2>       <1>       <0>   |
    MOSI:      |   1  | Don't Care | Don't Care | Don't Care | addr[3] | addr[2] | addr[1] | addr[0] | data[7] | data[6] | data[5] | data[4] | data[3] | data[2] | data[1] | data[0] |
    MISO:      |   0  |      0     |      0     |      0     |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |
    CS:     1  |   0  |      0     |      0     |      0     |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |    0    |  1
  • Read data cmd = 0x00+addr, addr = 0 ~ 15
    Bit:     | <15>      <14>         <13>         <12>       <11>       <10>      <9>       <8>           <7>             <6>             <5>             <4>             <3>             <2>             <1>             <0>     |
    MOSI:    |   0  | Don't Care | Don't Care | Don't Care | addr[3] | addr[2] | addr[1] | addr[0] |   Don't Care  |   Don't Care  |   Don't Care  |   Don't Care  |   Don't Care  |   Don't Care  |   Don't Care  |   Don't Care  |
    MISO:    |   0  |      0     |      0     |      0     |    0    |    0    |    0    |    0    | data[addr][7] | data[addr][6] | data[addr][5] | data[addr][4] | data[addr][3] | data[addr][2] | data[addr][1] | data[addr][0] |
    CS:   1  |   0  |      0     |      0     |      0     |    0    |    0    |    0    |    0    |       0       |       0       |       0       |       0       |       0       |       0       |       0       |       0       |  1

How to test

Key generation example:

  1. Choose two large prime numbers p and q : p = 7, q = 13
  2. Compute n = p * q : n = 91
  3. Compute Euller totient function φ(n) = (p - 1) * (q - 1) : φ(n) = 72
  4. Choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1: e = 11
  5. Determine d as d ≡ e^(−1) (mod φ(n)); that is, d is the modular multiplicative inverse of e modulo φ(n) : d = 59

Private key {e, n} = {11, 91}

Public key {d, n} = {59, 91}

The plain text is limited to a number in the interval [0:91[, as per this example. Since the design uses the Montgomery mutiplication, a Montgomery Constant shall be used to map the plain text into the Montgomery integer domain.

  1. Compute Montgomery constant (fixed value that depends only on the value of p and q and the max-key lenght of the RSA core implementation).

Const = (2 ** (2 * hwbits)) mod n, where hwbits = (8 (RSA max key-lenght core support) + 2).

Const = (2 ** (2 * (8+2))) mod 91 = 74

Now, use SPI Master peripheral in RP2040 to start communication on SPI interface towards this design. Remember to configure the SPI mode in the RP2040 accordingly.

Steps for start an/a encryption/decryption process:

  1. Write any value between 0 and n-1 to the configurable Read/Write register [2] - Plain text [7:0]: Value suggestes: 12
  2. Write to configurable Read/Write register [3] the value of e: 11
  3. Write to configurable Read/Write register [4] the value of n: 91
  4. Write to configurable Read/Write register [5] the value of const: 74
  5. Write to configurable Read/Write register [1] the value 1 - (Trigger the start encryption command).
  6. Wait for rising edge of the IRQ output.
  7. Read the Status Read Only register [6] - Encrypted data. Valeu expected: 38.

12 ^ 11 mod 91 = 743008370688 mod 91 = 38

https://github.com/calonso88/tt09_rsa/blob/main/test/test.py implements a self-checking test that verify the encrypted data produced by the RSA core against the predicted values produced locally on the test. The test randomize the elements for key generation and the plain text. All derived values needed for the encryption/decryption are calculated locally in the test through helper functions.

External hardware

Not required.

IO

#InputOutputBidirectional
0gpio_startspare[0]irq
1gpio_stopspare[1]ui[4]
2cpolspare[2]ui[5]
3cphaspare[3]spi_miso
4spare[4]spi_cs_n
5spare[5]spi_clk
6spare[6]spi_mosi
7spare[7]ui[7]

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (TinyTapeout Factory Test) tt_um_MichaelBell_tinyQV (TinyQV Risc-V SoC) tt_um_urish_silife_max (Game of Life 8x32 (siLife)) tt_um_vc32_cpu (VC 16-bit CPU) tt_um_tinytapeout_logo_screensaver (VGA Screensaver with Tiny Tapeout Logo) tt_um_htfab_rotfpga2 (ROTFPGA v2a) tt_um_htfab_latch_test (Latch test) tt_um_no_time_for_squares_tommythorn (No Time For Squares, IHP edition) tt_um_tommythorn_maxbw (Asynchronous Multiplier) tt_um_urish_simon (Simon Says memory game) tt_um_htfab_rotfpga2_ff (ROTFPGA v2b) tt_um_meiniKi_ttihp_fazyrv_exotiny (FazyRV-ExoTiny) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_algofoogle_raybox_zero (raybox-zero TTIHP0p2 edition) tt_um_z2a_rgb_mixer (RGB Mixer demo) tt_um_vga_clock (VGA clock) tt_um_frequency_counter (Frequency counter) tt_um_brandonramos_VGA_Pong_with_NES_Controllers (VGA Pong with NES Controllers) tt_um_demosiine_sda (DemoSiine) tt_um_toivoh_demo_deluxe (Sequential Shadows Deluxe [TT08 demo competition]) tt_um_edwintorok (Rounding error) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_hpretl_spi (SPI Test) tt_um_top_mole99 (One Sprite Pony) tt_um_urish_spell (SPELL) tt_um_rebeccargb_vga_pride (VGA Pride) tt_um_autosel (I2C EEPROM Project Selection) tt_um_a1k0n_nyancat (VGA Nyan Cat) tt_um_a1k0n_vgadonut (VGA donut) tt_um_rebeccargb_colorbars (Color Bars) tt_um_crispy_vga (Crispy VGA) tt_um_kbeckmann_flame (Flame demo) tt_um_jamesrosssharp_1bitam (1bit_am_sdr) tt_um_simon_cipher (simon_cipher) tt_um_htfab_bouncy_capsule (Bouncy Capsule) tt_um_phansel_laplace_lut (Experiment Number Six: Laplace LUT) tt_um_kianv_bare_metal (KianV RISC-V RV32E Baremetal SoC) tt_um_calonso88_rsa (8 bit RSA encryption) tt_um_silice (Warp) tt_um_rejunity_vga_test01 (VGA Drop (audio/visual demo)) tt_um_a1k0n_demo (Demo by a1k0n) tt_um_MichaelBell_canon (TT08 Pachelbel's Canon demo) tt_um_htfab_caterpillar (Simon's Caterpillar) tt_um_ravenslofty_chess (Chess) tt_um_fountaincoder_top_V2 (maddihp) tt_um_tomkeddie_a (VGA Experiments in Tennis) tt_um_MichaelBell_mandelbrot (VGA Mandelbrot) tt_um_MichaelBell_rle_vga (RLE Video Player) tt_um_jayjaywong12 (mulmul) tt_um_wokwi_392873974467527681 (PILIPINASLASALLE) tt_um_froith_goldcrest (Goldcrest RISC-V) tt_um_dvxf_dj8v (DJ8 8-bit CPU) tt_um_hpretl_minilogix (Minilogix) tt_um_tomkeddie_b (Transmit UART) tt_um_joerdsonsilva_modem (Multimode Modem) tt_um_oled_frequency_counter (Frequency Counter SSD1306 OLED) tt_um_stochastic_addmultiply_CL123abc (Stochastic Multiplier, Adder and Self-Multiplier) tt_um_QIF_8bit (8 Bit Digital QIF) tt_um_toivoh_retro_console (Retro Console) tt_um_cejmu (CEJMU Beers and Adders) tt_um_rejunity_sn76489 (Classic 8-bit era Programmable Sound Generator SN76489) tt_um_dlmiles_tt05_i2c_bert (I2C BERT) tt_um_dlmiles_muldiv8 (MULDIV unit (8-bit signed/unsigned)) tt_um_dlmiles_loopback (IHP loopback tile with input skew measurement) tt_um_dlmiles_bad_synchronizer (Example of Bad Synchronizer) tt_um_wokwi_407306064811090945 (DDR throughput and flop aperature test) tt_um_urish_giant_ringosc (Giant Ring Oscillator (3853 inverters)) tt_um_digital_clock_example (Digital Desk Clock v2.0) tt_um_rejunity_z80 (Zilog Z80) tt_um_rejunity_ay8913 (Classic 8-bit era Programmable Sound Generator AY-3-8913) tt_um_rtfb_collatz (Collatz conjecture brute-forcer) tt_um_ccattuto_conway (Conway's Game of Life on UART and VGA) tt_um_snow (Snow) tt_um_calonso88_74181 (8-bit ALU based on 2x 74181) tt_um_rejunity_vga_logo (VGA Tiny Logo (1 tile)) tt_um_NicklausThompson_SkyKing (SkyKing Demo) tt_um_htfab_cells (Cell mux) tt_um_htfab_pg_1x1 (Power gating test (1x1)) tt_um_htfab_pg_1x2 (Power gating test (1x2)) tt_um_dlmiles_ringosc_5inv (Ring Oscillator (5 inverter)) tt_um_devinatkin_pulse_width_counter (Pulse Width Counter) tt_um_algofoogle_vga_fun_wrapper (TTIHP VGA FUN!) tt_um_cfib_demo (cfib Demoscene Entry) tt_um_vga_glyph_mode (Glyph Mode) tt_um_favoritohjs_scroller (VGA Scroller) tt_um_pulse_generator (TTL Pulse Generator) tt_um_rajum_iterativeMAC (Iterative MAC) tt_um_algofoogle_tinyvga_fun_wrapper (TTIHP TinyVGA FUN!) tt_um_urish_sram_test (SRAM (1024x8) test) tt_um_one_bit_puf_wrapper (One Bit PUF) tt_um_multi_bit_puf_wrapper (One Bit PUF) tt_um_gray_sobel (Gray scale and Sobel filter) tt_um_rebeccargb_intercal_alu (INTERCAL ALU)