This content is translated with AI. Please refer to the original Traditional Chinese version (zh-TW) for accuracy.

In the previous discussion on Silicon IP , we briefly mentioned IEEE1735. However, I found that the principles of IEEE1735 could be explained more thoroughly, mainly by elucidating the effects IEEE1735 has on HDL files.

The reason for writing this article is that recently, while using Cadence's Xcelium , I discovered it offers more features than Synopsys VCS. Its documentation is also on another level, as VCS hardly provides anything, thereby enhancing our understanding of IEEE1735's implementation. Additionally, the most detailed online article about IEEE1735 Using IEEE (1735) Verilog Standard Mechanisms for IP Protection has been locked for paid viewing, resulting in a scarcity of articles on this topic online. Therefore, I decided to write an article to introduce it.

Technical Background

To understand IEEE1735, we first need to understand several technical terms. Of course, we don't need to comprehend the underlying principles; understanding the concept is sufficient. If there's a conceptual issue you don't understand, just ask AI.

1. Symmetric Encryption Algorithm

The same key is used for both encryption and decryption, which can transform plain text into a mess that no one can understand, and then decrypt it back into its original form using the same key. In IEEE1735, the AES128-CBC mode is typically used, and the following can also be chosen:

  • AES128-CBC
  • AES192-CBC
  • AES256-CBC

The following are additionally supported by Xcelium:

  • DES-CBC
  • AES128-CTR
  • AES192-CTR
  • AES256-CTR

However, DES is no longer a secure standard, and CTR is not a recommended mode by IEEE1735.

2. Asymmetric Encryption Algorithm

The encryption and decryption keys are divided into public and private keys. Encrypting with a public key means only the private key can decrypt it. IEEE 1735 uses RSA and there is no information available on supporting ECC. Additionally, Xcelium also supports RC2, RC4, RC5, but I'm not sure why these three are present, theoretically, this is symmetric encryption; why do they appear in the asymmetric section?

3. Encoding

Remember, encoding is not encryption. Anyone who knows the encoding rules can restore the encoded content. Encoding is used in IEEE1735 because many of the encrypted contents fall among non-displayable content, which in the file will be encoded into a displayable area. IEEE1735 uses base64.

4. Hashing

An algorithm to verify if a file has been modified; it can condense a file into a short string of numbers, and any slight modification of the contents will produce a completely different result. IEEE1735 generally uses SHA256, and can specify SHA512.

How IEEE1735 Works

The purpose of IEEE1735 is to allow silicon IP designers to hand their designs to IP users without the users knowing the details of the design; but the users still need to be able to input the IP into EDA software for processing to transform the silicon IP design into an actual circuit.

The operation of IEEE1735 is as follows:

  1. Every EDA company will have a private key, hardcoded somewhere in their software, while the public key is publicly released.
  2. The designer generates an AES key and encrypts the design file.
  3. After encryption, the public key of the EDA tool is used to encrypt the symmetric algorithm key, and the result is written into the file.

After obtaining the IP, users input the encrypted file into the EDA software, since the private key is hardcoded in the software, it can:

  1. Use the private key to decrypt the AES key
  2. Use the AES key to decrypt and extract the original source code from the encrypted data block

The file encrypted by IEEE1735 contains the following blocks:

Category Example Field Description
Header Area (Metadata) begin_protected, version, encrypt_agent Declares that the file is protected by IEEE 1735, along with encryption source, version, and encryptor information
Authorization and Access Control Area commonblock data_usage, rights_digest_method, license_expiration, begin_license Controls executable actions (simulation, synthesis, etc.), authorization period, integrity check methods, etc.
Key Area toolblock key_keyowner, key_method, key_block Specifies the public key of which EDA company, the key algorithm, and the encrypted symmetric key content
Data Area datablock data_block HDL content encrypted with AES
Version and Security Information version, rights_digest_method Specifies the IEEE 1735 version and hash algorithm (e.g., SHA-256) used to verify if protected content has been tampered
End Declaration end_protected Declares the end of the protected area

Using IEEE1735 Automatic Encryption with Xcelium

Below is the file I tested for encryption:

`pragma protect begin
module counter (
    input logic clk,
    input logic rst_n,
    output logic [1:0] count
);
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            count <= 2'b00;
        else
            count <= count + 1;
    end
endmodule
`pragma protect end

Using the Xcelium command

xmprotect -autoprotect -v2_ip1735 dut.sv`

The output encrypted content, xcelium automatically selects Cadence's key pair CDS_RSA_KEY_VER_2, and the encrypted AES key is the key_block specified content which can be extracted to the hex content with base64 -d | hexdump -C.

Interestingly, IEEE1735 has not updated any modern cryptographic concepts on the RSA part, and rsa encryption uses purely no_padding mode, not even the known vulnerable PKCS#1 v1.5 padding is used, let alone the newer and more secure OAEP padding .

`pragma protect begin_protected
`pragma protect version=2
`pragma protect encrypt_agent="NCPROTECT"
`pragma protect encrypt_agent_info="Encrypted using API"
`pragma protect data_method="AES128-CBC"

`pragma protect begin_commonblock
`pragma protect end_commonblock

`pragma protect begin_toolblock
`pragma protect key_keyowner="Cadence Design Systems."
`pragma protect key_keyname="CDS_RSA_KEY_VER_2"
`pragma protect key_method="RSA"
`pragma protect rights_digest_method="sha256"
`pragma protect encoding = (enctype = "BASE64", line_length = 48, bytes = 256)
`pragma protect key_block
AcGtKbMIbm5GriSB9Okgd1fdO+th/gdd7DysikiKL4biU8xh
5WDtXr/Kx4w0X5ohS8u8My1EoCgU80ToR7uj7aX7DO1O57/0
YjJIM36gRB8WWn3Ux/+q8i2TbzrXCReTK/GknF9yVEiDioRJ
p4dc8dgG07CLKOdFtwVeehAak1vSsnX49p3wkadQpaiEursG
RthxxTBRuY34rh2ZRo4z3A/yN4RUR1PGm7/NhGW3kCAH6DSO
rDy5dFGvVRczVZkSImSL1W6eZKKbiw3dcwACo6uk0eYLZKVo
/RmdxcnzVKlVrc7S+YthEElTzH6J0EsGdwLkH1LGlStDsXS3
FChz9Q==

`pragma protect end_toolblock="Tldb4a+fP8nJrj7zI0Wp/4/W9pfiUVYG7Un8J1njQCY="
`pragma protect encoding = (enctype = "BASE64", line_length = 48, bytes = 320)
`pragma protect data_block
lujf2DVPsigDbuCJ6Lzygr8b1okGVlo4oYhVZmKiu39t4R5f
sm0GOf/1lVk0dnXlNJkWwCgd3ycNZEg+W9rr8jyU7DEsxvQw
749dup7fESX+S+Nzt2sq7tUdhKRSZ2RzYZkc8QNx3Mm7XrxG
wJfiLIDkfxv2N/lQJhydcpl0m1VT11pAqNZpiB1SnmD1y4xQ
33cvZL9/04EaURgxSswvvmxldVkWKce7DXpVqfA+36eFLeE0
mVv53dpXl1CqeZ//AETdk/k2KBIU6GySMVCXZ7kycIHNO3om
1NjwwoXRhKIJxL5q49oGuej9rlqPuE057Wo8+ApVWO4STOfJ
4FTydEGSdkKpv8w4zuehdgd461/T8ck3Dr6WtM9brWZhkZoh
HHLtzW2/59KJAyd0P6UDwr6U+rmhU6OrhueTibEscWA=

`pragma protect end_protected

Note that the key area begin_toolblock above is not limited to one company; the same AES key can be encrypted with public keys for all the software you can think of. Taking this public file as an example, if keys from various companies were used for encryption, it would look like this. Each company leaves a key block, and the EDA software will search for its own company's part to decrypt with the private key. For example, if you run VCS on a file encrypted by Xcelium, you will encounter the following error message:

Error-[DECSPE] Decryption failed
encrypted/dut.svp, 29
  Error while decrypting source file
  Failed to load key needed to decrypt data_block. No key_block found for VCS.
  Please use vcs RSA public key and pragma expressions to identify the 
  keyblock mentioned in vcs documentation while encrypting to be able to 
  decrypt with vcs.

Besides CDS_RSA_KEY_VER_2, Xcelium can also encrypt using the following two keys specified with -use_key "key_name"

  • CDS_XM: Common for Cadence tools; post-encryption in Xcelium can be used by Jasper or Palladium.
  • CDS_XM_PUBKEY: Unique to Xcelium, other Cadence tools cannot use the encrypted file.

The keys mentioned above are Cadence's unpublished key pairs, and their private keys should have not been cracked... shouldn't have been. Even if I knew the cracked result, I wouldn't dare to shout it out loudI won't tell you Wei Lei. Another key CDS_RSA_KEY_VER_1 should have already been cracked, specifying it in xmprotect will prompt a non-secure warning.

Part of the Rights Hash

The encrypted file will have the following end_toolblock.

end_toolblock="Tldb4a+fP8nJrj7zI0Wp/4/W9pfiUVYG7Un8J1njQCY="

This is the hash calculated using SHA256 on the contents of the commonblock and toolblock. Some EDA tools may add access rights, etc., here, to prevent users from tampering with the file to gain higher privileges. If you modify this hash, the following error will occur during simulation in xcelium:

xmvlog: *F,DECERR (encrypted/dut.svp,28|26): Error while decrypting : AEAD signature in end_protected/end_toolblock pragma doesn't match.
xrun: *E,VLGERR: An error occurred during parsing. Review the log file for errors with the code *E and fix those identified problems to proceed. Exiting with code (status 2).

Theoretically, its input is the text within commonblock and toolblock, processed as follows:

  1. Remove the beginning `pragma protect
  2. Remove leading and trailing whitespace
  3. Replace newline characters with Line Feed \n However, theory aside, after I directly input the text into SHA256 and base64 encode it, I still can't reproduce the same result. Below is the python script used for processing.
    If anyone knows how to calculate this end_toolblock hash, or if you bump into the same hash value, please instruct me (if it's the latter case, might as well consider buying a lottery ticket).
import hashlib
import base64

content = """
`pragma protect key_keyowner="Cadence Design Systems."
`pragma protect key_keyname="CDS_RSA_KEY_VER_2"
`pragma protect key_method="RSA"
`pragma protect rights_digest_method="sha256"
`pragma protect encoding = (enctype = "BASE64", line_length = 48, bytes = 256)
`pragma protect key_block
AcGtKbMIbm5GriSB9Okgd1fdO+th/gdd7DysikiKL4biU8xh
5WDtXr/Kx4w0X5ohS8u8My1EoCgU80ToR7uj7aX7DO1O57/0
YjJIM36gRB8WWn3Ux/+q8i2TbzrXCReTK/GknF9yVEiDioRJ
p4dc8dgG07CLKOdFtwVeehAak1vSsnX49p3wkadQpaiEursG
RthxxTBRuY34rh2ZRo4z3A/yN4RUR1PGm7/NhGW3kCAH6DSO
rDy5dFGvVRczVZkSImSL1W6eZKKbiw3dcwACo6uk0eYLZKVo
/RmdxcnzVKlVrc7S+YthEElTzH6J0EsGdwLkH1LGlStDsXS3
FChz9Q==
""".strip()

cleaned_content = ""
for line in content.splitlines():
    line = line.replace("`pragma protect", "").strip()
    cleaned_content += line + '\n'

# Compute SHA256 hash
sha256_hash = hashlib.sha256(cleaned_content).digest()
sha256_hash_base64 = base64.b64encode(sha256_hash).decode('utf-8')
print(f"Hash (Base64): {sha256_hash_base64}")

Conclusion

IEEE1735 is somewhat of a fragmented standard. Excluding the need to hardcode the RSA private key for offline decryption support in EDA software, some parts of the specification haven't kept up with the latest cryptographic standards. Of course, the reduction in security level is far from equivalent to actual data being cracked, and cryptographers are often said to be overly anxious for this reason.
But seriously, the most common problem usually lies in the implementation of cryptography, regardless of how well the theory is written if the implementation is disorderly, the most secure theory becomes empty talk immediately; IEEE1735 itself has had several vulnerabilities discovered.

As stated in the use of IP chapter, the reason the IP ecosystem is thriving instead of collapsing is relying on industry norms rather than encryption, figuring it out still doesn't allow you to proclaim it nor actually taking it offline, causing any disturbance offends the entire semiconductor industry and leads to being blacklisted.