IEEE 1735 IP Protection

Simulate encrypted SystemVerilog IP with broker-based key management.

Overview

IEEE 1735 is the industry standard for distributing encrypted HDL intellectual property. It allows IP vendors to ship encrypted SystemVerilog source files that only authorized EDA tools can decrypt and simulate.

RyuSim supports IEEE 1735 with a security-first architecture: the RSA private key never exists on the user's machine. Instead, session key unwrapping is performed by a Seiraiyu-hosted remote broker over HTTPS, AES decryption happens in memory, generated C++ is written to a memory-backed file descriptor (memfd/tmpfs), and decrypted source is scrubbed from memory immediately after compilation.

This design directly addresses the vulnerabilities documented by Speith et al. (IEEE S&P 2022), where every major EDA vendor's local key storage was broken within hours to weeks.

Quick Start

Simulating encrypted IP requires nothing beyond the .svp file itself. RyuSim handles decryption transparently — no API keys, no extra flags.

With cocotb

Create a Makefile alongside your testbench, just like any other cocotb test:

SIM ?= ryusim TOPLEVEL_LANG := verilog VERILOG_SOURCES = $(PWD)/design_protected.svp TOPLEVEL = module_name COCOTB_TEST_MODULES = test_module include $(shell cocotb-config --makefiles)/Makefile.sim

Then run:

make

Manual compilation

# Compile — RyuSim detects pragma protect and decrypts transparently ryusim compile design_protected.svp --top module_name

RyuSim detects pragma protect regions in .svp files, contacts the broker to unwrap the session key, decrypts the source in memory, and proceeds with normal compilation. No additional flags or configuration are needed.

Try it: encrypted pipelined adder

Copy this encrypted design into pipelined_adder.svp to test the full flow.

module pipelined_adder #( parameter WIDTH = 8 ) ( input logic clk, input logic rst, input logic [WIDTH-1:0] a, input logic [WIDTH-1:0] b, output logic [WIDTH:0] sum, output logic valid ); `pragma protect version = 2 `pragma protect encrypt_agent = "ryusim-protect" `pragma protect key_keyowner = "Seiraiyu" `pragma protect key_keyname = "RyuSim-RSA-2026-01" `pragma protect key_method = rsa `pragma protect key_block KUNB27Vcm4Xhq16d59nvsQGT9HzJjaRgve+imwNX9AlD2TVngWh3FIVi3XyIjf5DV7OU1vgT09gcxODE7Kf4fBH02x8TULG7rSJGpW9tjmx+6SPceQVVaa4hT7w9bwN2v5BGHPgeTerZuVs6H4g/I/kl6CHkQAJgEIFU51N6ucMqiYbcPhyc15VybXq1iBNI6QKFNw+QtA4EOQMfnww33g8qBO826U3sq1FYQ7vNCsUHgncMyZERKkqYuYUplwYfq50DlzTNnltbhZSM9du2xNOlicmDcKgMvjeyVPbrUrRQ8k5Gl0+9j6cj8MOtL6wMtBTVX0nTt7wb61eTuB2YVFKfODpQXRyu2ZPuNP8lrAPfyzE33ElLsxq6sZh2psweTmhbXMKrkYD3quuaImbR2L3GbWiH/4Mo/t0VLC3kb/zh+gB/K42jJRfA5ljqK9XqI9fyOWIYyBk0iU4UftiObE27sWbWy17Xm8BtqQXqpEdOrhbkZYJS1+dVgi3XHgmlRY18+nykBZWAlfzif85AQnNcRzzDvf3y5bItxUx9EF3iXGsQ1qrAEUN+iRY0dWC7+Hf8gY/qqTSjtzbyDlpS8CweitBSG3Q4IqBrIqyHjmNHRo4p7ehb8WG9pYkEP9zyQCf9/GLXZrZ4BRJ+8iKP9bc74H0C5utAZbg3caNUjnA= `pragma protect data_method = "aes-256-gcm" `pragma protect iv = "6cdf01d6adb98217219aa68f" `pragma protect begin_protected `pragma protect data_block iFJYVYfclfGcGOgXdun96UA+IerbCZf0YgSyfGCvPie6shRDy/TtJ7ggMgB60XIiD9Tr0XUMip+D4pVtbhGkq34u3PjKaXX4IuJ7wiyyN8zrBiDLQd65pqYTeiw3ySFRXpjlPIEcY1szNCdwqyKOSGxFwG9KPwFKD8P6wjlK0cQwlYpcE1I/eNarUUd4AO0CoucZsyQLdK6RO6xaRZGNSiCXIdtTniato5B7KHV59RXAW7Rr0EyJLMxIKnd98GpiAXya8HXsREhSQKuX2YlLPb2Pxha+JvWEVZWvOT6kQJJkYA6rbApkNxJOP8QYHSVv+388SKc6lZLsoYbTJtDDndw1OA5cF4wZZzSIS4E4JF4OxKscVsvQKjkS5MIqPBSe0abTLKX8nVTNRmD/DGbt3h4ox/dGYlJ6Ye7SqSxXqq8AE6IU8Df8rBhqPA06mDMA3ErSh7n/75nspnP9pKm/RzyAS0r/aoNM57sgxYFvVgUsTKWfVjZc2iiPyI5sKkICyyazdaKN+9B99SPnh03GhN2Bs9y1hQXBKU8MIcHKd5JRTfOMSC4YTPpg37rhg3/4YDCWvwb7ohRmulTWROB/hHA691thNoQHtqgNlQaPc9qaUAlqZl803OPRCsGD2pZ2KgFEX7ScYDqd3qXGheRROyDfVmaROpea5kjJunGqLKNhmDpsh0nrHOvZD0tnjQt6ozct1B3zrioqR3AkrkPKtp53sGIpBZVEOR0/H8nWfo9jT2WTH2RXCXrpFQ2dmv4RdcI7AgxbrJMTT775g2UqP+18WUMNPtmTI36yXBJ5IWwCh0RlXo7c8zIFlI3xyiNVaKnAXjnY5FkQv03XbtYStn/JRej3W20xBSh5pZhNOzD5Q+YI0Qmia6lsqUavriu+FR+jogCc/9KutYDJloMGF1/H1K/SKg8S `pragma protect auth_tag = "bf5f6dc6a5edcd53cd5273d581df6ebc" `pragma protect end_protected endmodule

Create test_pipelined_adder.py:

import cocotb from cocotb.triggers import RisingEdge, Timer from cocotb.clock import Clock @cocotb.test() async def test_pipelined_add(dut): """Verify the encrypted pipelined adder compiles and simulates.""" cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start()) # Reset dut.rst.value = 1 dut.a.value = 0 dut.b.value = 0 for _ in range(3): await RisingEdge(dut.clk) dut.rst.value = 0 # Apply inputs and wait for pipeline to produce results dut.a.value = 10 dut.b.value = 20 for _ in range(5): await RisingEdge(dut.clk) await Timer(1, unit="ns") assert dut.valid.value == 1, "valid should be asserted after pipeline fill" result = int(dut.sum.value) assert result == 30, f"Expected 10+20=30, got {result}" dut._log.info(f"Encrypted IP works! sum={result}")

Create a Makefile:

SIM ?= ryusim TOPLEVEL_LANG := verilog VERILOG_SOURCES = $(PWD)/pipelined_adder.svp TOPLEVEL = pipelined_adder COCOTB_TEST_MODULES = test_pipelined_adder include $(shell cocotb-config --makefiles)/Makefile.sim

Run make and the encrypted design compiles and simulates just like plaintext.

How It Works

RyuSim's IEEE 1735 pipeline operates in six stages:

  1. Pragma protect parsing — Before Slang sees the source, a pre-processor scans for pragma protect begin_protected / end_protected regions. It extracts the RSA-wrapped session key (key_block), the AES-encrypted payload (data_block), and metadata such as key_keyowner, key_keyname, and data_method.
  2. Remote key unwrapping — The encrypted session key is sent to the Seiraiyu broker (POST https://broker.seiraiyu.com/api/v1/unwrap) over HTTPS with TLS certificate verification. The broker performs RSA private-key decryption server-side and returns the AES session key. The RSA private key never leaves the broker.
  3. Local AES decryption — Using the returned session key, RyuSim decrypts the data_block locally. For AES-256-GCM (the recommended method), the GCM authentication tag is verified to detect any tampering.
  4. Source reassembly — The decrypted SystemVerilog source replaces the pragma protect region in the file buffer. The reassembled source is fed to Slang for parsing.
  5. Memory scrub — After Slang has parsed the source into its AST, the decrypted buffer is explicitly zeroed using explicit_bzero. The plaintext SystemVerilog no longer exists in process memory.
  6. Protected code generation — Modules originating from encrypted source are marked is_protected in the IR. Their generated C++ is written to a memory-backed file descriptor (memfd_create on Linux, or /dev/shm/ as fallback), compiled to an object file, and the C++ source is deleted immediately. Only the compiled .o is retained for linking.

Encrypting Your IP

The ryusim-protect command-line tool encrypts SystemVerilog files for distribution using the IEEE 1735 standard.

Mark what to encrypt

Use the standard `pragma protect begin / `pragma protect end directives (IEEE 1800-2023 §34.5) to define exactly what gets encrypted. Everything outside these markers stays plaintext — including the module declaration, ports, parameters, typedefs, and defines — so consumers can see the interface and override parameters without access to the source.

module my_ip #( parameter int WIDTH = 8 ) ( input logic clk, input logic [WIDTH-1:0] data_in, output logic [WIDTH-1:0] data_out ); // Typedefs and constants visible to consumers typedef enum logic [1:0] { IDLE, RUN, DONE } state_t; `pragma protect begin // Implementation — encrypted in the .svp output state_t state; always_ff @(posedge clk) begin // ... end `pragma protect end endmodule

Encrypt a SystemVerilog file

ryusim-protect encrypt \ --input my_ip.sv \ --output my_ip.svp \ --recipient ryusim \ --data-method aes-256-gcm

The --recipient flag specifies which tools can decrypt the file. Use ryusim for RyuSim. You can specify multiple recipients to create a single .svp file that works with multiple tools:

ryusim-protect encrypt \ --input my_ip.sv \ --output my_ip.svp \ --recipient ryusim \ --recipient vivado \ --recipient questa \ --data-method aes-256-gcm

Each recipient gets its own key_block in the pragma protect envelope, containing the AES session key wrapped with that tool's RSA public key. The data_block (AES-encrypted source) is shared across all recipients.

Validate an encrypted file

ryusim-protect validate my_ip.svp

Checks the structural integrity of the pragma protect envelope without decrypting. Reports whether the file has valid syntax, lists the key blocks present, and verifies base64 encoding.

View file metadata

ryusim-protect info my_ip.svp

Displays the envelope version, data method, number of key blocks, and the key_keyowner/key_keyname for each block.

List known vendor keys

ryusim-protect list-recipients

Shows the built-in recipient registry with known identifiers for major EDA tools:

Recipient ID key_keyowner key_keyname
ryusim Seiraiyu RyuSim-RSA-2026-01
vivado Xilinx xilinxt_2019_11
questa Mentor Graphics Corporation MGC-VERIF-SIM-RSA-2
quartus Altera Corporation Altera-Quartus-RSA-1
vcs Synopsys SNPS-VCS-RSA-2
xcelium Cadence Design Systems. CDS-RSA-KEY-VER-1

The tool ships with RyuSim's public key built in. Other vendor public keys must be provided by the user (typically obtained from the vendor's tool installation directory). The registry provides only the correct identifier strings.

Multi-recipient encryption

When encrypting for multiple recipients, each gets an independent RSA-wrapped copy of the same AES session key. The encrypted payload is identical for all recipients. This means:

Supported Encryption Methods

AES-256-GCM (recommended)

Security Model

Design principles

No local private key. The RSA private key used to unwrap session keys exists only on the Seiraiyu broker server. It is never downloaded, embedded in binaries, or cached on the user's machine. This directly addresses the root cause identified by Speith et al. (IEEE S&P 2022): every vendor that stored keys locally had them extracted.

Broker-based RSA unwrap. Session key unwrapping is a server-side operation. The client sends the RSA-encrypted session key to the broker; the broker performs the RSA decryption and returns the AES session key over TLS. No user-facing credentials are required — the broker validates requests and applies rate limiting to prevent abuse.

GCM integrity verification. AES-256-GCM provides authenticated encryption. If any byte of the encrypted payload or authentication tag is modified, decryption fails with an integrity error. This prevents the padding-oracle attacks that were demonstrated against CBC-based IEEE 1735 implementations.

Memory-backed code generation. Generated C++ for protected modules is written to memfd_create file descriptors (or /dev/shm/ as fallback) rather than the normal obj_dir/ on disk. The C++ source is deleted immediately after compilation to .o. Only the compiled object file is retained.

Explicit memory scrub. After Slang parses the decrypted source into its AST, the decrypted buffer is zeroed using explicit_bzero (which the compiler cannot optimize away). This minimizes the window during which plaintext source exists in process memory.

Threat model

Threat Protection
Casual viewing (opening .svp in an editor) AES encryption renders content unreadable
Private key extraction from simulator binary Key never exists on user's machine
Padding-oracle / data modification attacks AES-256-GCM authenticated encryption rejects tampered data
Generated C++ source readable on disk memfd/tmpfs output with immediate deletion
Decrypted source lingering in memory explicit_bzero after Slang parse
Unauthorized use of broker Rate limiting and request validation
Key compromise blast radius Per-version keys with rotation support

Known limitations

Troubleshooting

"broker rejected request (HTTP 403)"

Cause: The broker refused the unwrap request. This is uncommon and typically indicates a server-side issue.

Fix:

"cannot connect to broker.seiraiyu.com — network required for encrypted IP"

Cause: The broker is unreachable. This can be a network outage, DNS failure, firewall blocking HTTPS (port 443), or a proxy configuration issue.

Fix:

"no IEEE 1735 key block for key_owner="Seiraiyu" in <file>"

Cause: The encrypted file does not contain a key block for RyuSim. It was encrypted for other tools but not for RyuSim.

Fix:

ryusim-protect encrypt --input source.sv --output source.svp --recipient ryusim

"integrity check failed for encrypted IP in <file> — file may be tampered"

Cause: The AES-256-GCM authentication tag does not match. The encrypted file has been modified since encryption — either corrupted during transfer or intentionally tampered with.

Fix:

"unsupported data_method "<method>" in <file>"

Cause: The encrypted file uses an encryption algorithm that RyuSim does not support.

Fix:

"TLS verification failed for broker.seiraiyu.com"

Cause: The TLS certificate presented by the broker could not be verified. This may indicate a man-in-the-middle attack, an expired certificate, or a missing CA bundle.

Fix:

"malformed IEEE 1735 envelope in <file>:<line>"

Cause: The pragma protect structure in the file has syntax errors.

Fix:

Vendor Integration

IP vendors who want their encrypted SystemVerilog to work with RyuSim need to include a key block for key_keyowner="Seiraiyu", key_keyname="RyuSim-RSA-2026-01" in their pragma protect envelope.

Getting your public key registered

To have your tool's public key included in the ryusim-protect built-in recipient registry:

  1. Contact Seiraiyu at ip-protection@seiraiyu.com with your tool name and vendor name, the key_keyowner and key_keyname strings your tool expects, and your RSA public key in PEM format.
  2. Verification — Seiraiyu will verify the key by encrypting a test file and confirming your tool can decrypt it.
  3. Registry inclusion — Once verified, your tool will be added to the ryusim-protect list-recipients registry in the next release.

Using RyuSim's public key

RyuSim's public key and metadata are distributed in the ieee1735/ directory of the RyuSim installation:

{ "tool": "RyuSim", "vendor": "Seiraiyu", "key_owner": "Seiraiyu", "key_name": "RyuSim-RSA-2026-01", "key_method": "rsa", "key_size": 2048, "supported_data_methods": ["aes-256-gcm"], "supported_languages": ["verilog", "systemverilog"], "public_key_file": "Seiraiyu_RyuSim-RSA-2026-01_public.pem", "broker_url": "https://broker.seiraiyu.com/api/v1/unwrap" }

Use aes-256-gcm as the data_method when encrypting for RyuSim.