256位NIST素域椭圆曲线运算优化细节之一(单个素数p的加减法)
2015-10-10 00:00
721 查看
摘要: 在素域椭圆曲线运算过程中,256位加法和减法运算结果常常位于区间[0,p)之外的情形,需要做+p或是-p的运算,本文以x64汇编编程的视角探讨此运算的优化过程
在素域椭圆曲线运算过程中,256位加法和减法运算结果常常位于区间[0,p)之外的情形,需要做+p或是-p的运算
256位NIST素域椭圆曲线参数p的生成公式为:
按照符号将此式分解得:
转化为16进制并按64位分节,变成下面的形式:
仔细观察可以发现,所涉及64位加法和减法中,只出现一个64位立即数:
假设某次256位减法最终发生借位,其低256位数值保存于寄存器r8:r11中,现在需要+p运算以修正之,若是用构成p的4个立即数直接运算的话,其代码如下:
由x64指令特性可知,这么书写是不允许的,大于32位的立即数会使编译通不过,通过前面的分析可知,可以将4个加法转化为3个加法和4个减法来实现,其代码如下:
有没有其它方法呢?当然有,比如可以预先将素数p的4个64位数值保存于寄存器r12:r15中,其代码如下:
为了一个256位常数牺牲4个通用寄存器是万不得已的选择,除非此运算占据整体运算的大部分,才值得这么做,比如对素数p求乘法逆时,超过80%的运算都是+/-p,此时有必要将素数p直接保存在通用寄存器中以便随时使用。
利用x64立即数书写规则,使用两个寄存器RAX:RDX生成素数p的内容,其代码如下:
这里特别要注意立即数-1的实际数值,在x86汇编里相当于0xffffffff,即32个连续的二进制1,在x64汇编则是64个连续的二进制1,相当于0xffffffffffffffff,其它立即数的书写规则和x86一致,都是32位有符号立即数,只有movq指令对rax操作时,才支持64位立即数,千万要小心。
在编写256位NIST素域椭圆曲线倍点函数时,最终采用的方案是使用两个通用寄存器分别保存素数p的最高64位和最低64位,同时利用x64汇编的立即数书写规则,其数值的生成代码如下:
倍点函数内计算+p的代码如下:
倍点函数内计算-p的代码如下:
国密素域椭圆曲线SM2从公式上来讲和NIST素域椭圆曲线有相似之处,同样可以优化+/-素数p的汇编代码,首先我们回顾一下国密SM2的素数p取值:
现仍旧使用2个通用寄存器缓存素数p的部分数值,其数值生成代码如下:
SM2倍点函数内计算+p的代码如下:
SM2倍点函数内计算-p的代码如下:
在素域椭圆曲线运算过程中,256位加法和减法运算结果常常位于区间[0,p)之外的情形,需要做+p或是-p的运算
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位立即数:
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个减法来实现,其代码如下:
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的内容,其代码如下:
# ------------------------ # 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
相关文章推荐
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区