mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-08 08:58:00 +00:00
dec79cf152
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.
58 lines
1.4 KiB
C
58 lines
1.4 KiB
C
#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;
|
|
}
|