Device Family: Intel® Stratix® 10

Intel Software: Quartus Prime Pro

Type: Answers, How-To

Area: Component


Last Modified: January 06, 2020
Version Found: v19.3
Bug ID: 14010336497

How can I write or erase the Intel® Stratix 10 AES BBRAM encryption key using the Mailbox Client Intel® FPGA IP interface and System Console?

Description

You can program the Intel® Stratix® 10 AES encryption key into battery backup RAM (BBRAM) using either the Intel Quartus® Prime Pro Programmer via JTAG or through the Mailbox Client Intel FPGA IP Interface.

When you program the key using Intel Quartus Prime Pro Programmer, the Programmer sends the Quartus encryption key (.qek) file using JTAG and programs the BBRAM.

When using the Mailbox Client Intel FPGA IP interface, you write the 8 individual 32-bit words that comprise the AES encryption key to the Mailbox Client IP.

Workaround/Fix

Using the quartus_encrypt command with the –operation=aes_key option, generate the .qek file:

quartus_encrypt –family=stratix10 --operation=make_aes_key -–aes_key=mykey.txt ik_count=4 max_key_use=32 keyfile.qek

The mykey.txt file contains the 8 key values you choose for your AES key (for example):

0xD6971FC7 0x28932CB0 0x5097E5A7 0x16968C52 0x7BB0AE8E 0x5C2F59E6 0x35B69453 0xC8E357BA

The key words you choose program the AES encryption key using the Mailbox Client IP interface.

The .qek file encrypts the bitstream file using the quartus_pfg command.

You can load the following .tcl script into System Console. This script contains functions that program or erase the AES key:

package require Tcl 8.5

# functions defined in this script:

#      volatile_aes_write

#      volatile_aes_erase

#

#      example use:

#

#      start_service_master

#      volatile_aes_write {0xD6971FC7 0x28932CB0 0x5097E5A7 0x16968C52 0x7BB0AE8E

#                          0x5C2F59E6 #0x35B69453 0xC8E357BA}

#      stop_service_master

#

#

#      start_service_master

#      volatile_aes_erase

#      stop_service_master

#

# #####################################################

# global variables definition

# #####################################################

#Mailbox AVMM Memory Map

#Base + 0    W      Command

#Base + 1    W      Command last word (eop)

#Base + 2    R      Command FIFO empty space

#Base + 3    W      Urgent command

#Base + 4    R      Urgent FIFO empty space

#Base + 5    R      Response data

#Base + 6    R      Response FIFO fill level   EOP    SOP

#Base + 7    R/W    IER

#Base + 8    R      ISR

#set base address according to Qsys system

set base 0x00000000

#set the variables to their respective offset

set b0 [expr {$base + 0x0}]

set b1 [expr {$base + 0x4}]

set b2 [expr {$base + 0x8}]

set b3 [expr {$base + 0xc}]

set b4 [expr {$base + 0x10}]

set b5 [expr {$base + 0x14}]

set b6 [expr {$base + 0x18}]

set b7 [expr {$base + 0x1c}]

set b8 [expr {$base + 0x20}]

#assign variable mp to the string that is the 0th element in the list returned by get_service_paths master

set mp [lindex [get_service_paths master] 0]

proc start_service_master {} {

       global mp omp

       set omp [claim_service master $mp top]

       }

proc stop_service_master {} {

       global mp omp

       close_service master $omp

       set omp {}

       }

proc volatile_aes_erase { } {

global omp b0 b1 b2 b3 b4 b5 b6 b7 b8        

       set status [master_read_32 $omp $b5 1]

       #puts $status

       if {$status!=0x0000000} {

             puts "volatile_aes_write error!!!"

       }

       #volatile_aes_erase

       master_write_32 $omp $b1 0x00000029

       after 1

       #read offset 8 (Interrupt service register) to determine if there is data in the FIFO

       set ISR [master_read_32 $omp $b8 1]

       #puts "ISR, $ISR"

       set mask_ISR 0x00000003

       while {($ISR & $mask_ISR)!=0x00000003} {

             set ISR [master_read_32 $omp $b8 1]

             puts "ISR is empty"

       }

       #puts "data exist in FIFO"

       #read offset 5 for the first packet of data (this will be the response header), the length field will notify user how many packets of argument that is to follow

       set status [master_read_32 $omp $b5 1]

#puts $status

    if {$status!=0x0000000} {

        puts "volatile aes erase error!!!" }

#read offset 5 again to retrieve the response argument (in this case, this command only has one response argument, which is the IDCODE) master_read_32 $omp $b5 1

}

 

proc volatile_aes_write { key_list } {
    global omp b0 b1 b2 b3 b4 b5 b6 b7 b8
    #volatile aes write
    master_write_32 $omp $b0 0x00008028


    for {set j 0} {$j < [llength $key_list] } {incr j 1} {    
       if {$j == [expr {[llength $key_list] -1}]} {
            set a [lindex $key_list $j]
            puts "write to b1 $a"
            master_write_32 $omp $b1 [lindex $key_list $j]
        } else {
            master_write_32 $omp $b0 [lindex $key_list $j]
            set a [lindex $key_list $j]
            puts "write to b0 $a"
        }
    }

    set key_len [expr [llength $key_list] + 2]

    set ISR [master_read_32 $omp $b8 1]
    set mask_ISR 0x00000003
    while {($ISR & $mask_ISR)!=0x00000003} {
        set ISR [master_read_32 $omp $b8 1]
        puts "ISR is empty"
    }

    set status [master_read_32 $omp $b5 1]
    puts $status
    if {$status!=0x0000000} {
        error "volatile key write error!!!"
    }

    #puts "data exist in FIFO"

}