зеркало из https://github.com/github/putty.git
Start a file of 'unsafe' mp_int functions.
Unlike the ones in mpint.c proper, these are not intended to respect the constant-time guarantees. They're going to be the kind of thing you use in key generation, which is too random to be constant-time in any case. I've arranged several precautions to try to make sure these functions don't accidentally get linked into the main SSH application, only into key generators: - declare them in a separate header with "unsafe" in the name - put "unsafe" in the name of every actual function - don't even link the mpunsafe.c translation unit into PuTTY proper - in fact, define global symbols of the same name in that file and the SSH client code, so that there will be a link failure if we ever try to do it by accident The initial contents of the new source file consist of the subroutine mp_mod_short() that previously lived in sshprime.c (and was not in mpint.c proper precisely because it was unsafe). While I'm here, I've turned it into mp_unsafe_mod_integer() and let it take a modulus of up to 32 bits instead of 16. Also added some obviously useful functions to shrink an mpint to the smallest physical size that can hold the contained number (rather like bn_restore_invariant in the old Bignum system), which I expect to be using shortly.
This commit is contained in:
Родитель
9af72ca1e8
Коммит
dec79cf152
2
Recipe
2
Recipe
|
@ -282,7 +282,7 @@ UXSSH = SSH uxnoise uxagentc uxgss uxshare
|
|||
SFTP = psftpcommon sftp sftpcommon logging cmdline
|
||||
|
||||
# Components of the prime-generation system.
|
||||
SSHPRIME = sshprime smallprimes
|
||||
SSHPRIME = sshprime smallprimes mpunsafe
|
||||
|
||||
# Miscellaneous objects appearing in all the utilities, or all the
|
||||
# network ones, or the Unix or Windows subsets of those in turn.
|
||||
|
|
2
mpint.c
2
mpint.c
|
@ -33,7 +33,7 @@ static inline BignumInt mp_word(mp_int *x, size_t i)
|
|||
return i < x->nw ? x->w[i] : 0;
|
||||
}
|
||||
|
||||
static mp_int *mp_make_sized(size_t nw)
|
||||
mp_int *mp_make_sized(size_t nw)
|
||||
{
|
||||
mp_int *x = snew_plus(mp_int, nw * sizeof(BignumInt));
|
||||
assert(nw); /* we outlaw the zero-word mp_int */
|
||||
|
|
|
@ -319,3 +319,6 @@ struct MontyContext {
|
|||
*/
|
||||
mp_int *scratch;
|
||||
};
|
||||
|
||||
/* Functions shared between mpint.c and mpunsafe.c */
|
||||
mp_int *mp_make_sized(size_t nw);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "misc.h"
|
||||
#include "puttymem.h"
|
||||
|
||||
#include "mpint.h"
|
||||
#include "mpint_i.h"
|
||||
|
||||
/*
|
||||
* This global symbol is also defined in ssh2kex-client.c, to ensure
|
||||
* that these unsafe non-constant-time mp_int functions can't end up
|
||||
* accidentally linked in to any PuTTY tool that actually makes an SSH
|
||||
* client connection.
|
||||
*
|
||||
* (Only _client_ connections, however. Uppity, being a test server
|
||||
* only, is exempt.)
|
||||
*/
|
||||
const int deliberate_symbol_clash = 12345;
|
||||
|
||||
static size_t mp_unsafe_words_needed(mp_int *x)
|
||||
{
|
||||
size_t words = x->nw;
|
||||
while (words > 1 && !x->w[words-1])
|
||||
words--;
|
||||
return words;
|
||||
}
|
||||
|
||||
mp_int *mp_unsafe_shrink(mp_int *x)
|
||||
{
|
||||
x->nw = mp_unsafe_words_needed(x);
|
||||
/* This potentially leaves some allocated words between the new
|
||||
* and old values of x->nw, which won't be wiped by mp_free now
|
||||
* that x->nw doesn't mention that they exist. But we've just
|
||||
* checked they're all zero, so we don't need to wipe them now
|
||||
* either. */
|
||||
return x;
|
||||
}
|
||||
|
||||
mp_int *mp_unsafe_copy(mp_int *x)
|
||||
{
|
||||
mp_int *copy = mp_make_sized(mp_unsafe_words_needed(x));
|
||||
mp_copy_into(copy, x);
|
||||
return copy;
|
||||
}
|
||||
|
||||
uint32_t mp_unsafe_mod_integer(mp_int *x, uint32_t modulus)
|
||||
{
|
||||
uint64_t accumulator = 0;
|
||||
for (size_t i = mp_max_bytes(x); i-- > 0 ;) {
|
||||
accumulator = 0x100 * accumulator + mp_get_byte(x, i);
|
||||
accumulator %= modulus;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* mpunsafe.h: functions that deal with mp_ints in ways that are *not*
|
||||
* expected to be constant-time. Used during key generation, in which
|
||||
* constant run time is a lost cause anyway.
|
||||
*
|
||||
* These functions are in a separate header, so that you can easily
|
||||
* check that you're not calling them in the wrong context. They're
|
||||
* also defined in a separate source file, which is only linked in to
|
||||
* the key generation tools. Furthermore, that source file also
|
||||
* defines a global symbol that intentionally conflicts with one
|
||||
* defined in the SSH client code, so that any attempt to put these
|
||||
* functions into the same binary as the live SSH client
|
||||
* implementation will cause a link-time failure. They should only be
|
||||
* linked into PuTTYgen and auxiliary test programs.
|
||||
*
|
||||
* Also, just in case those precautions aren't enough, all the unsafe
|
||||
* functions have 'unsafe' in the name.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_MPINT_UNSAFE_H
|
||||
#define PUTTY_MPINT_UNSAFE_H
|
||||
|
||||
/*
|
||||
* The most obvious unsafe thing you want to do with an mp_int is to
|
||||
* get rid of leading zero words in its representation, so that its
|
||||
* nominal size is as close as possible to its true size, and you
|
||||
* don't waste any time processing it.
|
||||
*
|
||||
* mp_unsafe_shrink performs this operation in place, mutating the
|
||||
* size field of the mp_int it's given. It returns the same pointer it
|
||||
* was given.
|
||||
*
|
||||
* mp_unsafe_copy leaves the original mp_int alone and makes a new one
|
||||
* with the minimal size.
|
||||
*/
|
||||
mp_int *mp_unsafe_shrink(mp_int *m);
|
||||
mp_int *mp_unsafe_copy(mp_int *m);
|
||||
|
||||
/*
|
||||
* Compute the residue of x mod m. This is implemented in the most
|
||||
* obvious way using the C % operator, which won't be constant-time on
|
||||
* many C implementations.
|
||||
*/
|
||||
uint32_t mp_unsafe_mod_integer(mp_int *x, uint32_t m);
|
||||
|
||||
#endif /* PUTTY_MPINT_UNSAFE_H */
|
|
@ -13,6 +13,12 @@
|
|||
#include "ssh2transport.h"
|
||||
#include "mpint.h"
|
||||
|
||||
/*
|
||||
* Another copy of the symbol defined in mpunsafe.c. See the comment
|
||||
* there.
|
||||
*/
|
||||
const int deliberate_symbol_clash = 12345;
|
||||
|
||||
void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
|
||||
{
|
||||
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
|
||||
|
|
22
sshprime.c
22
sshprime.c
|
@ -5,6 +5,7 @@
|
|||
#include <assert.h>
|
||||
#include "ssh.h"
|
||||
#include "mpint.h"
|
||||
#include "mpunsafe.h"
|
||||
#include "sshkeygen.h"
|
||||
|
||||
/*
|
||||
|
@ -108,23 +109,6 @@
|
|||
* but 1s.)
|
||||
*/
|
||||
|
||||
static unsigned short mp_mod_short(mp_int *x, unsigned short modulus)
|
||||
{
|
||||
/*
|
||||
* This function lives here rather than in mpint.c partly because
|
||||
* this is the only place it's needed, but mostly because it
|
||||
* doesn't pay careful attention to constant running time, since
|
||||
* as far as I can tell that's a lost cause for key generation
|
||||
* anyway.
|
||||
*/
|
||||
unsigned accumulator = 0;
|
||||
for (size_t i = mp_max_bytes(x); i-- > 0 ;) {
|
||||
accumulator = 0x100 * accumulator + mp_get_byte(x, i);
|
||||
accumulator %= modulus;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a prime. We can deal with various extra properties of
|
||||
* the prime:
|
||||
|
@ -204,9 +188,9 @@ mp_int *primegen(
|
|||
* we're incrementing by multiples of factor). */
|
||||
unsigned long residues[NSMALLPRIMES + 1], multipliers[NSMALLPRIMES + 1];
|
||||
for (size_t i = 0; i < lenof(moduli); i++) {
|
||||
residues[i] = mp_mod_short(p, moduli[i]);
|
||||
residues[i] = mp_unsafe_mod_integer(p, moduli[i]);
|
||||
if (factor)
|
||||
multipliers[i] = mp_mod_short(factor, moduli[i]);
|
||||
multipliers[i] = mp_unsafe_mod_integer(factor, moduli[i]);
|
||||
else
|
||||
multipliers[i] = 1;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче