1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-08 08:58:00 +00:00
putty-source/mpunsafe.c
Simon Tatham dec79cf152 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.
2020-02-23 14:49:54 +00:00

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;
}