國密SM2素域橢圓曲線快速約減算法x64編程研究(上)

這是NIST公開資料公佈的256位素域橢圓曲線快速約減算法描述:
git

p256 = (2 ^ 256) − (2 ^ 224) + (2 ^ 192) + (2 ^ 96) − 1
p256 = ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff

Routine 3.2.9 mp_mod_256 (r, a): Set r = a (mod p256 )
1: {Note: the ai are 32–bit quantities.}
2: t  = ( a7 |a6 |a5 |a4 |a3 |a2 |a1 |a0  )
3: s1 = ( a15|a14|a13|a12|a11| 0 | 0 | 0  )
4: s2 = (  0 |a15|a14|a13|a12| 0 | 0 | 0  )
5: s3 = ( a15|a14| 0 | 0 | 0 |a10|a9 |a8  )
6: s4 = ( a8 |a13|a15|a14|a13|a11|a10|a9  )
7: d1 = ( a10|a8 | 0 | 0 | 0 |a13|a12|a11 )
8: d2 = ( a11|a9 | 0 | 0 |a15|a14|a13|a12 )
9: d3 = ( a12| 0 |a10|a9 |a8 |a15|a14|a13 )
10:d4 = ( a13| 0 |a11|a10|a9 | 0 |15 |a14 )
11:d1 = 2p256 − d1
12:d2 = 2p256 − d2
13:d3 = p256 − d3
14:d4 = p256 − d4
15:r  = t + 2s1 + 2s2 + s3 + s4 + d1 + d2 + d3 + d4
16:Reduce r mod p256 by subtraction of up to ten multiples of p256 .

國密算法代號SM2能夠認爲是NIST素域256位橢圓曲線的變種,最主要區別在於p256和b的取值。國密SM2的公開資料給出的參數爲:github

(y ^ 2) = (X ^ 3) + (a * x) + b mod p
p  = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a  = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC

其中a = p - 3,這代表國密SM2和NIST的256v1使用了一樣特性的素域橢圓曲線公式:算法

(y ^2) = (X ^ 3)  - (3 * x) + b mod p256
shell

通過簡單推導,獲得國密SM2的p256生成公式:編程

p256 = (2 ^ 256) - (2 ^ 224) - (2 ^ 96) + (2 ^ 64) - 1緩存

公開資料並無國密SM2的快速約減算法詳細描述,但只要有素數p的生成公式,很容易自行推導出來,具體推導方法詳見橢圓曲線密碼學的基本數學知識,下面是仿NIST風格的算法描述文本:函數

算法:已知正整數a,數值不大於p256的平方,求模r = a (mod p256)
1 : 注:單元長度位均爲32位
2 : t   = ( a7 |a6 |a5 |a4 |a3 |a2 |a1 |a0  )
3 : s1  = ( a8 |a11|a10|a9 |a8 | 0 |a9 |a8  )
4 : s2  = ( a9 |a14|a13|a12|a11| 0 |a10|a9  )
5 : s3  = ( a10|a15|a14|a13|a12| 0 |a11|a10 )
6 : s4  = ( a11| 0 |a15|a14|a13| 0 |a12|a11 )
7 : s5  = ( a12| 0 |a15|a14|a13| 0 |a13|a12 )
8 : s6  = ( a12| 0 | 0 |a15|a14| 0 |a14|a13 )
9 : s7  = ( a13| 0 | 0 | 0 |a15| 0 |a14|a13 )
10: s8  = ( a13| 0 | 0 | 0 | 0 | 0 |a15|a14 )
11: s9  = ( a14| 0 | 0 | 0 | 0 | 0 |a15|a14 )
12: s10 = ( a14| 0 | 0 | 0 | 0 | 0 | 0 |a15 )
13: s11 = ( a15| 0 | 0 | 0 | 0 | 0 | 0 |a15 )
14: s12 = ( a15| 0 | 0 | 0 | 0 | 0 | 0 | 0  )
15: d1  = (  0 | 0 | 0 | 0 | 0 |a8 | 0 | 0  )
16: d2  = (  0 | 0 | 0 | 0 | 0 |a9 | 0 | 0  )
17: d3  = (  0 | 0 | 0 | 0 | 0 |a13| 0 | 0  )
18: d4  = (  0 | 0 | 0 | 0 | 0 |a14| 0 | 0  )
19: r   = t + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8
          + s9 + s10 + s11 + 2s12 - d1 -d2 -d3 - d4
20: 約減r直到r小於p256,最多減去(12 * p256)

爲了方便進行x64編程,將算法描述改成從低到高書寫,去除左側的臨時變量名稱,並在右側加上運算符號:優化

|a00|a01|a02|a03|a04|a05|a06|a07|(=)
|a08|a09| 0 |a08|a09|a10|a11|a08|(+)
|a09|a10| 0 |a11|a12|a13|a14|a09|(+)
|a10|a11| 0 |a12|a13|a14|a15|a10|(+)
|a11|a12| 0 |a13|a14|a15| 0 |a11|(+)
|a12|a13| 0 |a13|a14|a15| 0 |a12|(+)
|a13|a14| 0 |a14|a15| 0 | 0 |a12|(+)
|a13|a14| 0 |a15| 0 | 0 | 0 |a13|(+)
|a14|a15| 0 | 0 | 0 | 0 | 0 |a13|(+)
|a14|a15| 0 | 0 | 0 | 0 | 0 |a14|(+)
|a15| 0 | 0 | 0 | 0 | 0 | 0 |a14|(+)
|a15| 0 | 0 | 0 | 0 | 0 | 0 |a15|(+)
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |a15|(+)
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |a15|(+)
---------------------------------
| 0 | 0 |a08| 0 | 0 | 0 | 0 | 0 |(-)
| 0 | 0 |a09| 0 | 0 | 0 | 0 | 0 |(-)
| 0 | 0 |a13| 0 | 0 | 0 | 0 | 0 |(-)
| 0 | 0 |a14| 0 | 0 | 0 | 0 | 0 |(-)

直覺告訴我,若是就這麼直接按行進行加法運算,運算效率不會過高,爲此整理以下:指針

|===|===|===|===|===|===|===|===|
|a08|a08|   |   |   |   |   |a08|
|a09|a09|   |   |   |   |   |a09|
|a10|a10|   |   |   |   |   |a10|
|a11|a11|   |   |   |   |   |a11|
|---|---|---|---|---|---|---|---|
|a12|a12|   |a12|a12|   |   |a12|
|a13|a13|   |a13|a13|   |   |a13|
|a14|a14|   |a14|a14|   |   |a14|
|a15|a15|   |a15|a15|   |   |a15|
|---|---|---|---|---|---|---|---|
|   |   |   |   |   |   |   |a12|
|a13|   |   |   |   |a13|   |a13|
|a14|a14|   |   |   |a14|a14|a14|
|a15|a15|   |   |   |a15|a15|a15|
|---|---|---|---|---|---|---|---|
|   |   |   |a08|a09|a10|   |   |
|---|---|---|---|---|---|---|---|
|   |   |   |a11|   |   |a11|   |
|---|---|---|---|---|---|---|---|
|   |   |   |a13|a14|a15|   |a15|
|===|===|===|===|===|===|===|===|
|   |a08|a08|   |   |   |   |   |
|---|---|---|---|---|---|---|---|
|   |   |a09|   |   |   |   |   |
|---|---|---|---|---|---|---|---|
|   |   |a13|   |   |   |   |   |
|---|---|---|---|---|---|---|---|
|   |   |a14|   |   |   |   |   |
|===|===|===|===|===|===|===|===|

從表中能夠看出:code

組合數值使用頻次:
a08 + a09 + a10 + a11   3次
a12 + a13 + a14 + a15   6次
a13 + a14 + a15         2次
a14 + a15               2次

單獨數值使用頻次:
a08                     3次
a09                     2次
a10                     1次
a11                     2次
a13                     1次
a14                     1次
a15                     2次

據此制定相應的寄存器規劃:

數據輸入指針:通用寄存器rsi
 
數據輸出指針:通用寄存器rdi
 
通用寄存器備份與恢復:
|---------------|---------------|
|     xmm14     |     xmm15     |
|-------|-------|-------|-------|
|  r12  |  r13  |  r14  |  r15  |
|-------|-------|-------|-------|

原始數據加載:
|---------------|---------------|---------------|---------------|
|     xmm10     |     xmm11     |     xmm12     |     xmm13     |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|a00|a01|a02|a03|a04|a05|a06|a07|a08|a09|a10|a11|a12|a13|a14|a15|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|

運算結果緩存:
|---------------|---------------|
|     xmm0      |     xmm1      |
|---|---|---|---|---|---|---|---|
|r00|r01|r02|r03|r04|r05|r06|r07|
|---|---|---|---|---|---|---|---|

下述寄存器用於存放高頻數值:
r15 = a15
r14 = a14 + a15
r13 = a13 + a14 + a15
r12 = a12 + a13 + a14 + a15
r11 = a11
r9  = a09
r8  = a08
rsi = a08 + a09 + a10 + a11


按照上述思路實現的完整彙編程序代碼見本文的下篇

2015-10-17

最近在作SM2倍點運算函數中發現,前述的思路還能夠繼續優化,個別寄存器的使用也須要調整,快速約減運算表改進以下:

|===|===|===|===|===|===|===|===|
|a08|a08|   |   |   |   |   |a08|
|a09|a09|   |   |   |   |   |a09|
|a10|a10|   |   |   |   |   |a10|
|a11|a11|   |   |   |   |   |a11|
|a12|a12|   |a12|a12|   |   |a12|
|a13|a13|   |a13|a13|   |   |a13|
|a14|a14|   |a14|a14|   |   |a14|
|a15|a15|   |a15|a15|   |   |a15|
|---|---|---|---|---|---|---|---|
|   |   |   |   |   |   |   |a12|
|a13|a13|   |   |   |a13|   |a13|
|a14|a14|   |   |   |a14|   |a14|
|a15|a15|   |   |   |a15|   |a15|
|---|---|---|---|---|---|---|---|
|   |   |   |a08|a09|a10|a14|   |
|   |   |   |a13|a14|   |a15|   |
|---|---|---|---|---|---|---|---|
|   |   |   |a11|   |   |a11|   |
|---|---|---|---|---|---|---|---|
|   |   |   |   |   |a15|   |a15|
|===|===|===|===|===|===|===|===|
|   |a08|a08|   |   |   |   |   |
|   |a13|a13|   |   |   |   |   |
|---|---|---|---|---|---|---|---|
|   |   |a09|   |   |   |   |   |
|   |   |a14|   |   |   |   |   |
|===|===|===|===|===|===|===|===|

寄存器規劃中,用於保存中間數值的寄存器及其數值作了部分調整後以下所示:

r8  = a08 + a13
r9  = a09 + a14
r10 = a10
r11 = a11

rcx = a08 + a09 + a10 + a11 + a12 + a13 + a14 + a15

r12 = a12 + a13 + a14 + a15
r13 = a13 + a14 + a15
r14 = a14 + a15
r15 = a15

並在最終處理上保證了數學正確性,最新完整代碼見本人的git項目站點https://github.com/safedead/ecc-x64

相關文章
相關標籤/搜索