Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
N
nettle
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dmitry Baryshkov
nettle
Commits
4c5a4472
Commit
4c5a4472
authored
6 years ago
by
Simo Sorce
Committed by
Niels Möller
6 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Use side-channel silent root for rsa signatures
Signed-off-by:
Simo Sorce
<
simo@redhat.com
>
parent
f7350548
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
rsa-sign-tr.c
+252
-0
252 additions, 0 deletions
rsa-sign-tr.c
rsa.h
+9
-0
9 additions, 0 deletions
rsa.h
with
261 additions
and
0 deletions
rsa-sign-tr.c
+
252
−
0
View file @
4c5a4472
...
@@ -36,8 +36,15 @@
...
@@ -36,8 +36,15 @@
# include "config.h"
# include "config.h"
#endif
#endif
#include
<assert.h>
#include
"gmp-glue.h"
#include
"rsa.h"
#include
"rsa.h"
#include
"rsa-internal.h"
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#if NETTLE_USE_MINI_GMP
/* Blinds m, by computing c = m r^e (mod n), for a random r. Also
/* Blinds m, by computing c = m r^e (mod n), for a random r. Also
returns the inverse (ri), for use by rsa_unblind. */
returns the inverse (ri), for use by rsa_unblind. */
static
void
static
void
...
@@ -118,3 +125,248 @@ rsa_compute_root_tr(const struct rsa_public_key *pub,
...
@@ -118,3 +125,248 @@ rsa_compute_root_tr(const struct rsa_public_key *pub,
return
res
;
return
res
;
}
}
int
rsa_sec_compute_root_tr
(
const
struct
rsa_public_key
*
pub
,
const
struct
rsa_private_key
*
key
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mp_limb_t
*
x
,
const
mp_limb_t
*
m
,
size_t
mn
)
{
mpz_t
mz
;
mpz_t
xz
;
int
res
;
mpz_init
(
mz
);
mpz_init
(
xz
);
mpn_copyi
(
mpz_limbs_write
(
mz
,
mn
),
m
,
mn
);
mpz_limbs_finish
(
mz
,
mn
);
res
=
rsa_compute_root_tr
(
pub
,
key
,
random_ctx
,
random
,
xz
,
mz
);
if
(
res
)
mpz_limbs_copy
(
x
,
xz
,
mpz_size
(
pub
->
n
));
mpz_clear
(
mz
);
mpz_clear
(
xz
);
return
res
;
}
#else
/* Blinds m, by computing c = m r^e (mod n), for a random r. Also
returns the inverse (ri), for use by rsa_unblind. */
static
void
rsa_sec_blind
(
const
struct
rsa_public_key
*
pub
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mp_limb_t
*
c
,
mp_limb_t
*
ri
,
const
mp_limb_t
*
m
,
mp_size_t
mn
)
{
const
mp_limb_t
*
ep
=
mpz_limbs_read
(
pub
->
e
);
const
mp_limb_t
*
np
=
mpz_limbs_read
(
pub
->
n
);
mp_bitcnt_t
ebn
=
mpz_sizeinbase
(
pub
->
e
,
2
);
mp_size_t
nn
=
mpz_size
(
pub
->
n
);
size_t
itch
;
size_t
i2
;
mp_limb_t
*
scratch
;
TMP_GMP_DECL
(
tp
,
mp_limb_t
);
TMP_GMP_DECL
(
rp
,
mp_limb_t
);
TMP_GMP_DECL
(
r
,
uint8_t
);
TMP_GMP_ALLOC
(
rp
,
nn
);
TMP_GMP_ALLOC
(
r
,
nn
*
sizeof
(
mp_limb_t
));
/* c = m*(r^e) mod n */
itch
=
mpn_sec_powm_itch
(
nn
,
ebn
,
nn
);
i2
=
mpn_sec_mul_itch
(
nn
,
mn
);
itch
=
MAX
(
itch
,
i2
);
i2
=
mpn_sec_div_r_itch
(
nn
+
mn
,
nn
);
itch
=
MAX
(
itch
,
i2
);
i2
=
mpn_sec_invert_itch
(
nn
);
itch
=
MAX
(
itch
,
i2
);
TMP_GMP_ALLOC
(
tp
,
nn
+
mn
+
itch
);
scratch
=
tp
+
nn
+
mn
;
/* ri = r^(-1) */
do
{
random
(
random_ctx
,
nn
*
sizeof
(
mp_limb_t
),
(
uint8_t
*
)
r
);
mpn_set_base256
(
rp
,
nn
,
r
,
nn
*
sizeof
(
mp_limb_t
));
mpn_copyi
(
tp
,
rp
,
nn
);
/* invert r */
}
while
(
!
mpn_sec_invert
(
ri
,
tp
,
np
,
nn
,
2
*
nn
*
GMP_NUMB_BITS
,
scratch
));
mpn_sec_powm
(
c
,
rp
,
nn
,
ep
,
ebn
,
np
,
nn
,
scratch
);
/* normally mn == nn, but m can be smaller in some cases */
mpn_sec_mul
(
tp
,
c
,
nn
,
m
,
mn
,
scratch
);
mpn_sec_div_r
(
tp
,
nn
+
mn
,
np
,
nn
,
scratch
);
mpn_copyi
(
c
,
tp
,
nn
);
TMP_GMP_FREE
(
r
);
TMP_GMP_FREE
(
rp
);
TMP_GMP_FREE
(
tp
);
}
/* m = c ri mod n */
static
void
rsa_sec_unblind
(
const
struct
rsa_public_key
*
pub
,
mp_limb_t
*
x
,
mp_limb_t
*
ri
,
const
mp_limb_t
*
c
)
{
const
mp_limb_t
*
np
=
mpz_limbs_read
(
pub
->
n
);
mp_size_t
nn
=
mpz_size
(
pub
->
n
);
size_t
itch
;
size_t
i2
;
mp_limb_t
*
scratch
;
TMP_GMP_DECL
(
tp
,
mp_limb_t
);
itch
=
mpn_sec_mul_itch
(
nn
,
nn
);
i2
=
mpn_sec_div_r_itch
(
nn
+
nn
,
nn
);
itch
=
MAX
(
itch
,
i2
);
TMP_GMP_ALLOC
(
tp
,
nn
+
nn
+
itch
);
scratch
=
tp
+
nn
+
nn
;
mpn_sec_mul
(
tp
,
c
,
nn
,
ri
,
nn
,
scratch
);
mpn_sec_div_r
(
tp
,
nn
+
nn
,
np
,
nn
,
scratch
);
mpn_copyi
(
x
,
tp
,
nn
);
TMP_GMP_FREE
(
tp
);
}
static
int
sec_equal
(
const
mp_limb_t
*
a
,
const
mp_limb_t
*
b
,
size_t
limbs
)
{
volatile
mp_limb_t
z
=
0
;
for
(
size_t
i
=
0
;
i
<
limbs
;
i
++
)
{
z
|=
(
a
[
i
]
^
b
[
i
]);
}
return
z
==
0
;
}
static
int
rsa_sec_check_root
(
const
struct
rsa_public_key
*
pub
,
const
mp_limb_t
*
x
,
const
mp_limb_t
*
m
)
{
mp_size_t
nn
=
mpz_size
(
pub
->
n
);
mp_size_t
ebn
=
mpz_sizeinbase
(
pub
->
e
,
2
);
const
mp_limb_t
*
np
=
mpz_limbs_read
(
pub
->
n
);
const
mp_limb_t
*
ep
=
mpz_limbs_read
(
pub
->
e
);
int
ret
;
mp_size_t
itch
;
mp_limb_t
*
scratch
;
TMP_GMP_DECL
(
tp
,
mp_limb_t
);
itch
=
mpn_sec_powm_itch
(
nn
,
ebn
,
nn
);
TMP_GMP_ALLOC
(
tp
,
nn
+
itch
);
scratch
=
tp
+
nn
;
mpn_sec_powm
(
tp
,
x
,
nn
,
ep
,
ebn
,
np
,
nn
,
scratch
);
ret
=
sec_equal
(
tp
,
m
,
nn
);
TMP_GMP_FREE
(
tp
);
return
ret
;
}
static
void
cnd_mpn_zero
(
int
cnd
,
volatile
mp_ptr
rp
,
mp_size_t
n
)
{
volatile
mp_limb_t
c
;
while
(
--
n
>=
0
)
{
c
=
rp
[
n
];
c
&=
((
mp_limb_t
)
cnd
-
1
);
rp
[
n
]
=
c
;
}
}
/* Checks for any errors done in the RSA computation. That avoids
* attacks which rely on faults on hardware, or even software MPI
* implementation.
* This version is side-channel silent even in case of error,
* the destination buffer is always overwritten */
int
rsa_sec_compute_root_tr
(
const
struct
rsa_public_key
*
pub
,
const
struct
rsa_private_key
*
key
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mp_limb_t
*
x
,
const
mp_limb_t
*
m
,
size_t
mn
)
{
TMP_GMP_DECL
(
c
,
mp_limb_t
);
TMP_GMP_DECL
(
ri
,
mp_limb_t
);
TMP_GMP_DECL
(
scratch
,
mp_limb_t
);
size_t
key_limb_size
;
int
ret
;
key_limb_size
=
NETTLE_OCTET_SIZE_TO_LIMB_SIZE
(
key
->
size
);
/* mpz_powm_sec handles only odd moduli. If p, q or n is even, the
key is invalid and rejected by rsa_private_key_prepare. However,
some applications, notably gnutls, don't use this function, and
we don't want an invalid key to lead to a crash down inside
mpz_powm_sec. So do an additional check here. */
if
(
mpz_even_p
(
pub
->
n
)
||
mpz_even_p
(
key
->
p
)
||
mpz_even_p
(
key
->
q
))
{
mpn_zero
(
x
,
key_limb_size
);
return
0
;
}
assert
(
mpz_size
(
pub
->
n
)
==
key_limb_size
);
assert
(
mn
<=
key_limb_size
);
TMP_GMP_ALLOC
(
c
,
key_limb_size
);
TMP_GMP_ALLOC
(
ri
,
key_limb_size
);
TMP_GMP_ALLOC
(
scratch
,
_rsa_sec_compute_root_itch
(
key
));
rsa_sec_blind
(
pub
,
random_ctx
,
random
,
x
,
ri
,
m
,
mn
);
_rsa_sec_compute_root
(
key
,
c
,
x
,
scratch
);
ret
=
rsa_sec_check_root
(
pub
,
c
,
x
);
rsa_sec_unblind
(
pub
,
x
,
ri
,
c
);
cnd_mpn_zero
(
1
-
ret
,
x
,
key_limb_size
);
TMP_GMP_FREE
(
scratch
);
TMP_GMP_FREE
(
ri
);
TMP_GMP_FREE
(
c
);
return
ret
;
}
/* Checks for any errors done in the RSA computation. That avoids
* attacks which rely on faults on hardware, or even software MPI
* implementation.
* This version is maintained for API compatibility reasons. It
* is not completely side-channel silent. There are conditionals
* in buffer copying both in case of success or error.
*/
int
rsa_compute_root_tr
(
const
struct
rsa_public_key
*
pub
,
const
struct
rsa_private_key
*
key
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mpz_t
x
,
const
mpz_t
m
)
{
TMP_GMP_DECL
(
l
,
mp_limb_t
);
int
res
;
mp_size_t
l_size
=
NETTLE_OCTET_SIZE_TO_LIMB_SIZE
(
key
->
size
);
TMP_GMP_ALLOC
(
l
,
l_size
);
res
=
rsa_sec_compute_root_tr
(
pub
,
key
,
random_ctx
,
random
,
l
,
mpz_limbs_read
(
m
),
mpz_size
(
m
));
if
(
res
)
{
mp_limb_t
*
xp
=
mpz_limbs_write
(
x
,
l_size
);
mpn_copyi
(
xp
,
l
,
l_size
);
mpz_limbs_finish
(
x
,
l_size
);
}
TMP_GMP_FREE
(
l
);
return
res
;
}
#endif
This diff is collapsed.
Click to expand it.
rsa.h
+
9
−
0
View file @
4c5a4472
...
@@ -90,6 +90,7 @@ extern "C" {
...
@@ -90,6 +90,7 @@ extern "C" {
#define rsa_decrypt_tr nettle_rsa_decrypt_tr
#define rsa_decrypt_tr nettle_rsa_decrypt_tr
#define rsa_compute_root nettle_rsa_compute_root
#define rsa_compute_root nettle_rsa_compute_root
#define rsa_compute_root_tr nettle_rsa_compute_root_tr
#define rsa_compute_root_tr nettle_rsa_compute_root_tr
#define rsa_sec_compute_root_tr _nettle_rsa_sec_compute_root_tr
#define rsa_generate_keypair nettle_rsa_generate_keypair
#define rsa_generate_keypair nettle_rsa_generate_keypair
#define rsa_keypair_to_sexp nettle_rsa_keypair_to_sexp
#define rsa_keypair_to_sexp nettle_rsa_keypair_to_sexp
#define rsa_keypair_from_sexp_alist nettle_rsa_keypair_from_sexp_alist
#define rsa_keypair_from_sexp_alist nettle_rsa_keypair_from_sexp_alist
...
@@ -436,6 +437,14 @@ rsa_compute_root_tr(const struct rsa_public_key *pub,
...
@@ -436,6 +437,14 @@ rsa_compute_root_tr(const struct rsa_public_key *pub,
void
*
random_ctx
,
nettle_random_func
*
random
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mpz_t
x
,
const
mpz_t
m
);
mpz_t
x
,
const
mpz_t
m
);
/* Safe side-channel silent variant, using RSA blinding, and checking the
* result after CRT. */
int
rsa_sec_compute_root_tr
(
const
struct
rsa_public_key
*
pub
,
const
struct
rsa_private_key
*
key
,
void
*
random_ctx
,
nettle_random_func
*
random
,
mp_limb_t
*
x
,
const
mp_limb_t
*
m
,
size_t
mn
);
/* Key generation */
/* Key generation */
/* Note that the key structs must be initialized first. */
/* Note that the key structs must be initialized first. */
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment