256位NIST素域橢圓曲線運算優化細節之一(單個素數p的加減法)

在素域橢圓曲線運算過程當中,256位加法和減法運算結果經常位於區間[0,p)以外的情形,須要作+p或是-p的運算shell

256位NIST素域橢圓曲線參數p的生成公式爲:緩存

p = 2^256 − 2^224 + 2^192 + 2^96 − 1

按照符號將此式分解得:
函數

p = (2^256 + 2^192 + 2^96) - (2^224 + 1)

轉化爲16進制並按64位分節,變成下面的形式:優化

+: 0000000000000001 0000000000000000 0000000100000000 0000000000000000
-: 0000000100000000 0000000000000000 0000000000000000 0000000000000001
=: ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff

仔細觀察能夠發現,所涉及64位加法和減法中,只出現一個64位當即數:code

0000000100000000

假設某次256位減法最終發生借位,其低256位數值保存於寄存器r8:r11中,如今須要+p運算以修正之,如果用構成p的4個當即數直接運算的話,其代碼以下:編譯

#   --------------
#   r8:r11 += p256
#   --------------
    addq    $0xffffffffffffffff, %r8
    adcq    $0xffffffff, %r9
    adcq    $0, %r10
    adcq    $0xffffffff00000001, %r11

由x64指令特性可知,這麼書寫是不容許的,大於32位的當即數會使編譯通不過,經過前面的分析可知,能夠將4個加法轉化爲3個加法和4個減法來實現,其代碼以下:class

    movq    $0x100000000, %rax
    addq    %rax, %r9
    adcq    $0x0, %r10
    adcq    $0x1, %r11
#   ----
    subq    $0x1, %r8
    sbbq    $0, %r9
    sbbq    $0, %r10
    sbbq    %rax, %r11

有沒有其它方法呢?固然有,好比能夠預先將素數p的4個64位數值保存於寄存器r12:r15中,其代碼以下:二進制

#   --------------
#   r12:r15 = p256
#   r8:r11 += p256
#   --------------
    addq    %r12, %r8
    adcq    %r13, %r9
    adcq    %r14, %r10
    adcq    %r15, %r11

爲了一個256位常數犧牲4個通用寄存器是萬不得已的選擇,除非此運算佔據總體運算的大部分,才值得這麼作,好比對素數p求乘法逆時,超過80%的運算都是+/-p,此時有必要將素數p直接保存在通用寄存器中以便隨時使用。
方法

利用x64當即數書寫規則,使用兩個寄存器RAX:RDX生成素數p的內容,其代碼以下:co

#   ------------------------
#   rax = 0x00000000ffffffff
#   rdx = 0xffffffff00000001
#   ------------------------
    movq    $0xffffffff, %rax
    movq    %rax, %rdx
    negq    %rdx
#   --------------
#   r8:r11 += p256
#   --------------
    addq    $-1, %r8
    adcq    %rax, %r9
    adcq    $0, %r10
    adcq    %rdx, %r11

這裏特別要注意當即數-1的實際數值,在x86彙編裏至關於0xffffffff,即32個連續的二進制1,在x64彙編則是64個連續的二進制1,至關於0xffffffffffffffff,其它當即數的書寫規則和x86一致,都是32位有符號當即數,只有movq指令對rax操做時,才支持64位當即數,千萬要當心。

在編寫256位NIST素域橢圓曲線倍點函數時,最終採用的方案是使用兩個通用寄存器分別保存素數p的最高64位和最低64位,同時利用x64彙編的當即數書寫規則,其數值的生成代碼以下:

#   ------------------------
#   rbx = 0x00000000ffffffff
#   rbp = 0xffffffff00000001
#   ------------------------
    xorq    %rbp, %rbp
    movq    $0xffffffff, %rax
    movq    %rax, %rbx
    subq    %rax, %rbp

倍點函數內計算+p的代碼以下:

#   ---------------
#   r12:r15 += p256
#   ---------------
    addq    $-1, %r12
    adcq    %rbx, %r13
    adcq    $0, %r14
    adcq    %rbp, %r15

倍點函數內計算-p的代碼以下:

#   ---------------
#   r12:r15 -= p256
#   ---------------
    subq    $-1, %r12
    sbbq    %rbx, %r13
    sbbq    $0, %r14
    sbbq    %rbp, %r15

國密素域橢圓曲線SM2從公式上來說和NIST素域橢圓曲線有類似之處,一樣能夠優化+/-素數p的彙編代碼,首先咱們回顧一下國密SM2的素數p取值:

p256 = FFFFFFFEFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF00000000 FFFFFFFFFFFFFFFF

現仍舊使用2個通用寄存器緩存素數p的部分數值,其數值生成代碼以下:

#   ------------------------
#   rbx = 0xFFFFFFFF00000000
#   rbp = 0xFFFFFFFEFFFFFFFF
#   ------------------------
    movq    $-0x100000000, %rbx
    movq    $-0x100000001, %rbp

SM2倍點函數內計算+p的代碼以下:

#   --------------
#   r8:r11 += p256
#   --------------
    addq    $-1, %r8
    adcq    %rbx, %r9
    adcq    $-1, %r10
    adcq    %rbp, %r11

SM2倍點函數內計算-p的代碼以下:

#   --------------
#   r8:r11 -= p256
#   --------------
    subq    $-1, %r8
    sbbq    %rbx, %r9
    sbbq    $-1, %r10
    sbbq    %rbp, %r11
相關文章
相關標籤/搜索