Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
btwise
openssl
提交
bf3dfe7f
O
openssl
项目概览
btwise
/
openssl
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
openssl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bf3dfe7f
编写于
8月 14, 2011
作者:
A
Andy Polyakov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
bn_div.c: remove duplicate code by merging BN_div and BN_div_no_branch.
上级
e7d1363d
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
34 addition
and
238 deletion
+34
-238
crypto/bn/bn_div.c
crypto/bn/bn_div.c
+34
-238
未找到文件。
crypto/bn/bn_div.c
浏览文件 @
bf3dfe7f
...
...
@@ -173,15 +173,13 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
#endif
/* OPENSSL_NO_ASM */
/* BN_div
[_no_branch]
computes dv := num / divisor, rounding towards
/* BN_div computes dv := num / divisor, rounding towards
* zero, and sets up rm such that dv*divisor + rm = num holds.
* Thus:
* dv->neg == num->neg ^ divisor->neg (unless the result is zero)
* rm->neg == num->neg (unless the remainder is zero)
* If 'dv' or 'rm' is NULL, the respective value is not returned.
*/
static
int
BN_div_no_branch
(
BIGNUM
*
dv
,
BIGNUM
*
rm
,
const
BIGNUM
*
num
,
const
BIGNUM
*
divisor
,
BN_CTX
*
ctx
);
int
BN_div
(
BIGNUM
*
dv
,
BIGNUM
*
rm
,
const
BIGNUM
*
num
,
const
BIGNUM
*
divisor
,
BN_CTX
*
ctx
)
{
...
...
@@ -190,6 +188,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
BN_ULONG
*
resp
,
*
wnump
;
BN_ULONG
d0
,
d1
;
int
num_n
,
div_n
;
int
no_branch
=
0
;
/* Invalid zero-padding would have particularly bad consequences
* in the case of 'num', so don't just rely on bn_check_top() for this one
...
...
@@ -204,7 +203,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
if
((
BN_get_flags
(
num
,
BN_FLG_CONSTTIME
)
!=
0
)
||
(
BN_get_flags
(
divisor
,
BN_FLG_CONSTTIME
)
!=
0
))
{
return
BN_div_no_branch
(
dv
,
rm
,
num
,
divisor
,
ctx
)
;
no_branch
=
1
;
}
bn_check_top
(
dv
);
...
...
@@ -218,7 +217,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
return
(
0
);
}
if
(
BN_ucmp
(
num
,
divisor
)
<
0
)
if
(
!
no_branch
&&
BN_ucmp
(
num
,
divisor
)
<
0
)
{
if
(
rm
!=
NULL
)
{
if
(
BN_copy
(
rm
,
num
)
==
NULL
)
return
(
0
);
}
...
...
@@ -243,227 +242,9 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
norm_shift
+=
BN_BITS2
;
if
(
!
(
BN_lshift
(
snum
,
num
,
norm_shift
)))
goto
err
;
snum
->
neg
=
0
;
div_n
=
sdiv
->
top
;
num_n
=
snum
->
top
;
loop
=
num_n
-
div_n
;
/* Lets setup a 'window' into snum
* This is the part that corresponds to the current
* 'area' being divided */
wnum
.
neg
=
0
;
wnum
.
d
=
&
(
snum
->
d
[
loop
]);
wnum
.
top
=
div_n
;
/* only needed when BN_ucmp messes up the values between top and max */
wnum
.
dmax
=
snum
->
dmax
-
loop
;
/* so we don't step out of bounds */
/* Get the top 2 words of sdiv */
/* div_n=sdiv->top; */
d0
=
sdiv
->
d
[
div_n
-
1
];
d1
=
(
div_n
==
1
)
?
0
:
sdiv
->
d
[
div_n
-
2
];
/* pointer to the 'top' of snum */
wnump
=
&
(
snum
->
d
[
num_n
-
1
]);
/* Setup to 'res' */
res
->
neg
=
(
num
->
neg
^
divisor
->
neg
);
if
(
!
bn_wexpand
(
res
,(
loop
+
1
)))
goto
err
;
res
->
top
=
loop
;
resp
=
&
(
res
->
d
[
loop
-
1
]);
/* space for temp */
if
(
!
bn_wexpand
(
tmp
,(
div_n
+
1
)))
goto
err
;
if
(
BN_ucmp
(
&
wnum
,
sdiv
)
>=
0
)
{
/* If BN_DEBUG_RAND is defined BN_ucmp changes (via
* bn_pollute) the const bignum arguments =>
* clean the values between top and max again */
bn_clear_top2max
(
&
wnum
);
bn_sub_words
(
wnum
.
d
,
wnum
.
d
,
sdiv
->
d
,
div_n
);
*
resp
=
1
;
}
else
res
->
top
--
;
/* if res->top == 0 then clear the neg value otherwise decrease
* the resp pointer */
if
(
res
->
top
==
0
)
res
->
neg
=
0
;
else
resp
--
;
for
(
i
=
0
;
i
<
loop
-
1
;
i
++
,
wnump
--
,
resp
--
)
{
BN_ULONG
q
,
l0
;
/* the first part of the loop uses the top two words of
* snum and sdiv to calculate a BN_ULONG q such that
* | wnum - sdiv * q | < sdiv */
#if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
BN_ULONG
bn_div_3_words
(
BN_ULONG
*
,
BN_ULONG
,
BN_ULONG
);
q
=
bn_div_3_words
(
wnump
,
d1
,
d0
);
#else
BN_ULONG
n0
,
n1
,
rem
=
0
;
n0
=
wnump
[
0
];
n1
=
wnump
[
-
1
];
if
(
n0
==
d0
)
q
=
BN_MASK2
;
else
/* n0 < d0 */
{
#ifdef BN_LLONG
BN_ULLONG
t2
;
#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
q
=
(
BN_ULONG
)(((((
BN_ULLONG
)
n0
)
<<
BN_BITS2
)
|
n1
)
/
d0
);
#else
q
=
bn_div_words
(
n0
,
n1
,
d0
);
#ifdef BN_DEBUG_LEVITTE
fprintf
(
stderr
,
"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
X) -> 0x%08X
\n
"
,
n0
,
n1
,
d0
,
q
);
#endif
#endif
#ifndef REMAINDER_IS_ALREADY_CALCULATED
/*
* rem doesn't have to be BN_ULLONG. The least we
* know it's less that d0, isn't it?
*/
rem
=
(
n1
-
q
*
d0
)
&
BN_MASK2
;
#endif
t2
=
(
BN_ULLONG
)
d1
*
q
;
for
(;;)
{
if
(
t2
<=
((((
BN_ULLONG
)
rem
)
<<
BN_BITS2
)
|
wnump
[
-
2
]))
break
;
q
--
;
rem
+=
d0
;
if
(
rem
<
d0
)
break
;
/* don't let rem overflow */
t2
-=
d1
;
}
#else
/* !BN_LLONG */
BN_ULONG
t2l
,
t2h
;
q
=
bn_div_words
(
n0
,
n1
,
d0
);
#ifdef BN_DEBUG_LEVITTE
fprintf
(
stderr
,
"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
X) -> 0x%08X
\n
"
,
n0
,
n1
,
d0
,
q
);
#endif
#ifndef REMAINDER_IS_ALREADY_CALCULATED
rem
=
(
n1
-
q
*
d0
)
&
BN_MASK2
;
#endif
#if defined(BN_UMULT_LOHI)
BN_UMULT_LOHI
(
t2l
,
t2h
,
d1
,
q
);
#elif defined(BN_UMULT_HIGH)
t2l
=
d1
*
q
;
t2h
=
BN_UMULT_HIGH
(
d1
,
q
);
#else
if
(
no_branch
)
{
BN_ULONG
ql
,
qh
;
t2l
=
LBITS
(
d1
);
t2h
=
HBITS
(
d1
);
ql
=
LBITS
(
q
);
qh
=
HBITS
(
q
);
mul64
(
t2l
,
t2h
,
ql
,
qh
);
/* t2=(BN_ULLONG)d1*q; */
}
#endif
for
(;;)
{
if
((
t2h
<
rem
)
||
((
t2h
==
rem
)
&&
(
t2l
<=
wnump
[
-
2
])))
break
;
q
--
;
rem
+=
d0
;
if
(
rem
<
d0
)
break
;
/* don't let rem overflow */
if
(
t2l
<
d1
)
t2h
--
;
t2l
-=
d1
;
}
#endif
/* !BN_LLONG */
}
#endif
/* !BN_DIV3W */
l0
=
bn_mul_words
(
tmp
->
d
,
sdiv
->
d
,
div_n
,
q
);
tmp
->
d
[
div_n
]
=
l0
;
wnum
.
d
--
;
/* ingore top values of the bignums just sub the two
* BN_ULONG arrays with bn_sub_words */
if
(
bn_sub_words
(
wnum
.
d
,
wnum
.
d
,
tmp
->
d
,
div_n
+
1
))
{
/* Note: As we have considered only the leading
* two BN_ULONGs in the calculation of q, sdiv * q
* might be greater than wnum (but then (q-1) * sdiv
* is less or equal than wnum)
*/
q
--
;
if
(
bn_add_words
(
wnum
.
d
,
wnum
.
d
,
sdiv
->
d
,
div_n
))
/* we can't have an overflow here (assuming
* that q != 0, but if q == 0 then tmp is
* zero anyway) */
(
*
wnump
)
++
;
}
/* store part of the result */
*
resp
=
q
;
}
bn_correct_top
(
snum
);
if
(
rm
!=
NULL
)
{
/* Keep a copy of the neg flag in num because if rm==num
* BN_rshift() will overwrite it.
*/
int
neg
=
num
->
neg
;
BN_rshift
(
rm
,
snum
,
norm_shift
);
if
(
!
BN_is_zero
(
rm
))
rm
->
neg
=
neg
;
bn_check_top
(
rm
);
}
BN_CTX_end
(
ctx
);
return
(
1
);
err:
bn_check_top
(
rm
);
BN_CTX_end
(
ctx
);
return
(
0
);
}
/* BN_div_no_branch is a special version of BN_div. It does not contain
* branches that may leak sensitive information.
*/
static
int
BN_div_no_branch
(
BIGNUM
*
dv
,
BIGNUM
*
rm
,
const
BIGNUM
*
num
,
const
BIGNUM
*
divisor
,
BN_CTX
*
ctx
)
{
int
norm_shift
,
i
,
loop
;
BIGNUM
*
tmp
,
wnum
,
*
snum
,
*
sdiv
,
*
res
;
BN_ULONG
*
resp
,
*
wnump
;
BN_ULONG
d0
,
d1
;
int
num_n
,
div_n
;
bn_check_top
(
dv
);
bn_check_top
(
rm
);
/* bn_check_top(num); */
/* 'num' has been checked in BN_div() */
bn_check_top
(
divisor
);
if
(
BN_is_zero
(
divisor
))
{
BNerr
(
BN_F_BN_DIV_NO_BRANCH
,
BN_R_DIV_BY_ZERO
);
return
(
0
);
}
BN_CTX_start
(
ctx
);
tmp
=
BN_CTX_get
(
ctx
);
snum
=
BN_CTX_get
(
ctx
);
sdiv
=
BN_CTX_get
(
ctx
);
if
(
dv
==
NULL
)
res
=
BN_CTX_get
(
ctx
);
else
res
=
dv
;
if
(
sdiv
==
NULL
||
res
==
NULL
)
goto
err
;
/* First we normalise the numbers */
norm_shift
=
BN_BITS2
-
((
BN_num_bits
(
divisor
))
%
BN_BITS2
);
if
(
!
(
BN_lshift
(
sdiv
,
divisor
,
norm_shift
)))
goto
err
;
sdiv
->
neg
=
0
;
norm_shift
+=
BN_BITS2
;
if
(
!
(
BN_lshift
(
snum
,
num
,
norm_shift
)))
goto
err
;
snum
->
neg
=
0
;
/* Since we don't know whether snum is larger than sdiv,
* we pad snum with enough zeroes without changing its
* value.
...
...
@@ -480,6 +261,7 @@ static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
snum
->
d
[
snum
->
top
]
=
0
;
snum
->
top
++
;
}
}
div_n
=
sdiv
->
top
;
num_n
=
snum
->
top
;
...
...
@@ -504,12 +286,27 @@ static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
/* Setup to 'res' */
res
->
neg
=
(
num
->
neg
^
divisor
->
neg
);
if
(
!
bn_wexpand
(
res
,(
loop
+
1
)))
goto
err
;
res
->
top
=
loop
-
1
;
res
->
top
=
loop
-
no_branch
;
resp
=
&
(
res
->
d
[
loop
-
1
]);
/* space for temp */
if
(
!
bn_wexpand
(
tmp
,(
div_n
+
1
)))
goto
err
;
if
(
!
no_branch
)
{
if
(
BN_ucmp
(
&
wnum
,
sdiv
)
>=
0
)
{
/* If BN_DEBUG_RAND is defined BN_ucmp changes (via
* bn_pollute) the const bignum arguments =>
* clean the values between top and max again */
bn_clear_top2max
(
&
wnum
);
bn_sub_words
(
wnum
.
d
,
wnum
.
d
,
sdiv
->
d
,
div_n
);
*
resp
=
1
;
}
else
res
->
top
--
;
}
/* if res->top == 0 then clear the neg value otherwise decrease
* the resp pointer */
if
(
res
->
top
==
0
)
...
...
@@ -642,7 +439,7 @@ X) -> 0x%08X\n",
rm
->
neg
=
neg
;
bn_check_top
(
rm
);
}
bn_correct_top
(
res
);
if
(
no_branch
)
bn_correct_top
(
res
);
BN_CTX_end
(
ctx
);
return
(
1
);
err:
...
...
@@ -650,5 +447,4 @@ err:
BN_CTX_end
(
ctx
);
return
(
0
);
}
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录