Suggest that local support staff are useful.
[u/mdw/putty] / sshdh.c
CommitLineData
e5574168 1#include "ssh.h"
2
65a22376 3const struct ssh_kex ssh_diffiehellman = {
e5574168 4 "diffie-hellman-group1-sha1"
5};
6
65a22376 7const struct ssh_kex ssh_diffiehellman_gex = {
a92dd380 8 "diffie-hellman-group-exchange-sha1"
9};
10
e5574168 11/*
12 * The prime p used in the key exchange.
13 */
27cd7fc2 14static const unsigned char P[] = {
3709bfe9 15 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
16 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
17 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
18 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
19 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
20 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
21 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
22 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
23 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
24 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
25 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
e5574168 26};
27
28/*
3709bfe9 29 * The generator g = 2.
e5574168 30 */
27cd7fc2 31static const unsigned char G[] = { 2 };
e5574168 32
33/*
3709bfe9 34 * Variables.
e5574168 35 */
27cd7fc2 36struct dh_ctx {
37 Bignum x, e, p, q, qmask, g;
38};
e5574168 39
40/*
3709bfe9 41 * Common DH initialisation.
e5574168 42 */
27cd7fc2 43static void dh_init(struct dh_ctx *ctx)
32874aea 44{
27cd7fc2 45 ctx->q = bignum_rshift(ctx->p, 1);
46 ctx->qmask = bignum_bitmask(ctx->q);
47 ctx->x = ctx->e = NULL;
3709bfe9 48}
e5574168 49
50/*
3709bfe9 51 * Initialise DH for the standard group1.
e5574168 52 */
27cd7fc2 53void *dh_setup_group1(void)
32874aea 54{
3d88e64d 55 struct dh_ctx *ctx = snew(struct dh_ctx);
27cd7fc2 56 ctx->p = bignum_from_bytes(P, sizeof(P));
57 ctx->g = bignum_from_bytes(G, sizeof(G));
58 dh_init(ctx);
59 return ctx;
3709bfe9 60}
61
62/*
a92dd380 63 * Initialise DH for an alternative group.
64 */
27cd7fc2 65void *dh_setup_group(Bignum pval, Bignum gval)
32874aea 66{
3d88e64d 67 struct dh_ctx *ctx = snew(struct dh_ctx);
27cd7fc2 68 ctx->p = copybn(pval);
69 ctx->g = copybn(gval);
70 dh_init(ctx);
71 return ctx;
a92dd380 72}
73
74/*
27cd7fc2 75 * Clean up and free a context.
3709bfe9 76 */
27cd7fc2 77void dh_cleanup(void *handle)
32874aea 78{
27cd7fc2 79 struct dh_ctx *ctx = (struct dh_ctx *)handle;
80 freebn(ctx->x);
81 freebn(ctx->e);
82 freebn(ctx->p);
83 freebn(ctx->g);
84 freebn(ctx->q);
85 freebn(ctx->qmask);
86 sfree(ctx);
3709bfe9 87}
e5574168 88
89/*
90 * DH stage 1: invent a number x between 1 and q, and compute e =
91 * g^x mod p. Return e.
7bd5a860 92 *
93 * If `nbits' is greater than zero, it is used as an upper limit
94 * for the number of bits in x. This is safe provided that (a) you
95 * use twice as many bits in x as the number of bits you expect to
96 * use in your session key, and (b) the DH group is a safe prime
97 * (which SSH demands that it must be).
98 *
99 * P. C. van Oorschot, M. J. Wiener
100 * "On Diffie-Hellman Key Agreement with Short Exponents".
101 * Advances in Cryptology: Proceedings of Eurocrypt '96
102 * Springer-Verlag, May 1996.
e5574168 103 */
27cd7fc2 104Bignum dh_create_e(void *handle, int nbits)
32874aea 105{
27cd7fc2 106 struct dh_ctx *ctx = (struct dh_ctx *)handle;
e5574168 107 int i;
108
3709bfe9 109 int nbytes;
110 unsigned char *buf;
111
27cd7fc2 112 nbytes = ssh1_bignum_length(ctx->qmask);
3d88e64d 113 buf = snewn(nbytes, unsigned char);
e5574168 114
a71540b9 115 do {
116 /*
117 * Create a potential x, by ANDing a string of random bytes
3709bfe9 118 * with qmask.
a71540b9 119 */
27cd7fc2 120 if (ctx->x)
121 freebn(ctx->x);
122 if (nbits == 0 || nbits > bignum_bitcount(ctx->qmask)) {
123 ssh1_write_bignum(buf, ctx->qmask);
7bd5a860 124 for (i = 2; i < nbytes; i++)
125 buf[i] &= random_byte();
27cd7fc2 126 ssh1_read_bignum(buf, &ctx->x);
7bd5a860 127 } else {
128 int b, nb;
27cd7fc2 129 ctx->x = bn_power_2(nbits);
2d466ffd 130 b = nb = 0;
7bd5a860 131 for (i = 0; i < nbits; i++) {
132 if (nb == 0) {
133 nb = 8;
134 b = random_byte();
135 }
27cd7fc2 136 bignum_set_bit(ctx->x, i, b & 1);
7bd5a860 137 b >>= 1;
138 nb--;
139 }
140 }
27cd7fc2 141 } while (bignum_cmp(ctx->x, One) <= 0 || bignum_cmp(ctx->x, ctx->q) >= 0);
e5574168 142
143 /*
144 * Done. Now compute e = g^x mod p.
145 */
27cd7fc2 146 ctx->e = modpow(ctx->g, ctx->x, ctx->p);
e5574168 147
27cd7fc2 148 return ctx->e;
e5574168 149}
150
151/*
152 * DH stage 2: given a number f, compute K = f^x mod p.
153 */
27cd7fc2 154Bignum dh_find_K(void *handle, Bignum f)
32874aea 155{
27cd7fc2 156 struct dh_ctx *ctx = (struct dh_ctx *)handle;
7bd5a860 157 Bignum ret;
27cd7fc2 158 ret = modpow(f, ctx->x, ctx->p);
7bd5a860 159 return ret;
e5574168 160}