Commit b5f05ef8 authored by Niels Möller's avatar Niels Möller
Browse files

*** empty log message ***

Rev: ChangeLog:1.198
Rev: src/dh_exchange.c:1.1
Rev: src/srp_exchange.c:1.1
parent 099df978
2000-05-27 Niels Mller <nisse@cuckoo.localdomain>
* src/publickey_crypto.h: Renamed the class group to abstract_group.
(GROUP_RANGE): Renamed from GROUP_MEMBER, as it actually doesn't
check membership.
(GROUP_SMALL_POWER): New method, for raising a group element to a
power that fits in an UINT32.
(abstract_group): Added generator attribute.
* src/publickey_crypto.c: Moved most dh-related code to
dh_exchange.c. Moved the definition of the group_zn class to
publickey_crypto.h.
* src/Makefile.am.in (liblsh_a_SOURCES): Added dh_Exchange.c and
srp_exchange.c.
* src/userauth.h (lsh_user): Added read_file method.
* src/unix_user.c (do_read_file): New function.
(make_unix_user_db): Added backend argument.
* src/io.c (check_user_permissions): New function.
(io_read_user_file): New function.
* src/io.h (io_read_user_file): Added prototype.
2000-05-24 Niels Mller <nisse@cuckoo.localdomain>
* contrib/lsh.spec.in: Use -o flag for lsh_writekey (Thayne).
......
/* dh_exchange.c
*
*
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "publickey_crypto.h"
#include "connection.h"
#include "crypto.h"
#include "format.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"
void
init_diffie_hellman_instance(struct diffie_hellman_method *m,
struct diffie_hellman_instance *self,
struct ssh_connection *c)
{
struct lsh_string *s;
/* FIXME: The allocator could do this kind of initialization
* automatically. */
mpz_init(self->e);
mpz_init(self->f);
mpz_init(self->secret);
mpz_init(self->K);
self->method = m;
self->hash = MAKE_HASH(m->H);
self->exchange_hash = NULL;
debug("init_diffie_hellman_instance()\n"
" V_C: %pS\n", c->versions[CONNECTION_CLIENT]);
debug(" V_S: %pS\n", c->versions[CONNECTION_SERVER]);
debug(" I_C: %pS\n", c->literal_kexinits[CONNECTION_CLIENT]);
debug(" I_C: %pS\n", c->literal_kexinits[CONNECTION_SERVER]);
s = ssh_format("%S%S%S%S",
c->versions[CONNECTION_CLIENT],
c->versions[CONNECTION_SERVER],
c->literal_kexinits[CONNECTION_CLIENT],
c->literal_kexinits[CONNECTION_SERVER]);
HASH_UPDATE(self->hash, s->length, s->data);
lsh_string_free(s);
/* We don't need the kexinit strings anymore. */
lsh_string_free(c->literal_kexinits[CONNECTION_CLIENT]);
lsh_string_free(c->literal_kexinits[CONNECTION_SERVER]);
c->literal_kexinits[CONNECTION_CLIENT] = NULL;
c->literal_kexinits[CONNECTION_SERVER] = NULL;
}
struct diffie_hellman_method *
make_dh1(struct randomness *r)
{
NEW(diffie_hellman_method, res);
mpz_t p;
mpz_t g;
mpz_t order;
mpz_init_set_str(p,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
"FFFFFFFFFFFFFFFF", 16);
mpz_init_set(order, p);
mpz_sub_ui(order, order, 1);
mpz_fdiv_q_2exp(order, order, 1);
mpz_init_set_ui(g, 2);
res->G = &make_zn(p, g, order)->super;
mpz_clear(p);
mpz_clear(g);
mpz_clear(order);
res->H = &sha1_algorithm;
res->random = r;
return res;
}
/* R is set to a random, secret, exponent, and V set to is g^r */
void
dh_generate_secret(struct diffie_hellman_method *self,
mpz_t r, mpz_t v)
{
mpz_t tmp;
/* Generate a random number, 1 < x <= p-1 = O(G) */
mpz_init_set(tmp, self->G->order);
mpz_sub_ui(tmp, tmp, 1);
bignum_random(r, self->random, tmp);
mpz_add_ui(r, r, 1);
mpz_clear(tmp);
GROUP_POWER(self->G, v, self->G->generator, r);
}
struct lsh_string *
dh_make_client_msg(struct diffie_hellman_instance *self)
{
dh_generate_secret(self->method, self->secret, self->e);
return ssh_format("%c%n", SSH_MSG_KEXDH_INIT, self->e);
}
int
dh_process_client_msg(struct diffie_hellman_instance *self,
struct lsh_string *packet)
{
struct simple_buffer buffer;
unsigned msg_number;
simple_buffer_init(&buffer, packet->length, packet->data);
if (! (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_KEXDH_INIT)
&& parse_bignum(&buffer, self->e)
&& (mpz_cmp_ui(self->e, 1) > 0)
&& GROUP_RANGE(self->method->G, self->e)
&& parse_eod(&buffer) ))
return 0;
GROUP_POWER(self->method->G, self->K, self->e, self->secret);
return 1;
}
#if 0
void dh_hash_update(struct diffie_hellman_instance *self,
struct lsh_string *packet)
{
debug("dh_hash_update, length = %i, data:\n", packet->length);
debug_safe(packet->length, packet->data);
debug("\n");
HASH_UPDATE(self->hash, packet->length, packet->data);
}
#endif
/* Hashes server key, e and f */
void
dh_hash_digest(struct diffie_hellman_instance *self, UINT8 *digest)
{
struct lsh_string *s = ssh_format("%S%n%n%n",
self->server_key,
self->e, self->f,
self->K);
debug("dh_hash_digest()\n '%pS'\n", s);
HASH_UPDATE(self->hash, s->length, s->data);
lsh_string_free(s);
HASH_DIGEST(self->hash, digest);
}
void
dh_make_server_secret(struct diffie_hellman_instance *self)
{
dh_generate_secret(self->method, self->secret, self->f);
}
struct lsh_string *
dh_make_server_msg(struct diffie_hellman_instance *self,
struct signer *s)
{
self->exchange_hash = lsh_string_alloc(self->hash->hash_size);
dh_hash_digest(self, self->exchange_hash->data);
return ssh_format("%c%S%n%fS",
SSH_MSG_KEXDH_REPLY,
self->server_key,
self->f, SIGN(s,
self->exchange_hash->length,
self->exchange_hash->data));
}
int
dh_process_server_msg(struct diffie_hellman_instance *self,
struct lsh_string *packet)
{
struct simple_buffer buffer;
unsigned msg_number;
simple_buffer_init(&buffer, packet->length, packet->data);
if (!(parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_KEXDH_REPLY)
&& (self->server_key = parse_string_copy(&buffer))
&& (parse_bignum(&buffer, self->f))
&& (mpz_cmp_ui(self->f, 1) > 0)
&& GROUP_RANGE(self->method->G, self->f)
&& (self->signature = parse_string_copy(&buffer))
&& parse_eod(&buffer)))
return 0;
GROUP_POWER(self->method->G, self->K, self->f, self->secret);
return 1;
}
int
dh_verify_server_msg(struct diffie_hellman_instance *self,
struct verifier *v)
{
self->exchange_hash = lsh_string_alloc(self->hash->hash_size);
dh_hash_digest(self, self->exchange_hash->data);
return VERIFY(v,
self->hash->hash_size, self->exchange_hash->data,
self->signature->length, self->signature->data);
}
/* srp_exchange.h
*
* Thomas Wu's Secure Remote Password Protocol
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 2000 Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if 0
/* GABA:
(class
(name srp_entry)
(vars
(name string)
(salt string)
(verifier bignum)))
*/
/* GABA:
(class
(name srp_server_exchange)
(super keyexchange_algorithm)
(vars
(dh object diffie_hellman_method)
(db object user_db)
;; Remove this?
;; (keys object alist)))
*/
/* Thomas Wu's Secure Remote Password Protocol, with a fixed group. */
/* GABA:
(struct
(name srp_instance)
(vars
;; FIXME: Use super for the dh_instance
(dh struct dh_instance)
(user string) ; User name
(salt string)
(u . UINT32)
(v bignum)))
*/
void
srp_hash_password(mpz_t x,
struct hash_algorithm *H,
struct lsh_string *salt,
struct lsh_string *name,
struct lsh_string *passwd)
{
struct lsh_string *h
= hash_string(H, ssh_format("%s%s", salt,
hash_string(H, ssh_format("%s%s", name, passwd), 1),
1));
bignum_parse_u(r, h->length, h->data);
lsh_string_free(h);
}
/* dh_instance, name */
struct lsh_string *
srp_make_init_msg(struct srp_instance *self)
{
dh_generate_secret(&self->dh, self->dh.e);
return ssh_format("%c%s%n", SSH_MSG_KEXSRP_INIT, self->name, self->dh.e);
}
/* dh_instance, packet -> name */
struct lsh_string *
srp_process_init_msg(struct srp_instance *self, struct lsh_string *packet)
{
struct simple_buffer buffer;
unsigned msg_number;
simple_buffer_init(&buffer, packet->length, packet->data);
return (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_KEXSRP_INIT)
&& ( (self->name = parse_string_copy(&buffer) ))
&& parse_bignum(&buffer, self->e)
&& (mpz_cmp_ui(self->e, 1) > 0)
&& GROUP_RANGE(self->method->G, self->e)
&& parse_eod(&buffer) );
}
/* dh_instance */
static UINT32
srp_select_u(struct srp_instance *self)
{
struct lsh_string *h;
h = hash_string(self->dh.method->H, ssh_format("%ln", self->dh.f), 1);
self->u = READ_UINT32(h->data);
lsh_string_free(h);
return self->u;
}
/* dh_instance, v */
struct lsh_string *
srp_make_reply_msg(struct srp_instance *self)
{
for (;;)
{
/* Loop, in case f or u turns out to be zero */
dh_generate_secret(&self->dh, &self->dh.f);
/* FIXME: We use XOR rather than addition modulo p */
mpz_xor(&self->dh.f, &self.dh.f, self->v);
if (!mpz_sgn(&self->df.h))
{
werror("srp_exchange.c: Found cleartext password by mistake!\n");
continue;
}
if (srp_select_u(self))
break;
}
/* Compute (e v^u) ^ b */
GROUP_SMALL_POWER(self->dh.G, self->dh.K, self->v, self->u);
GROUP_COMBINE(self->dh.G, self->dh.K, self->dh.e, self->dh.K);
GROUP_POWER(self->dh.G, self->dh.K, self->dh.K, self->dh.secret);
return ssh_format("%c%s%n", SSH_MSG_KEXSRP_REPLY, self->salt, self->dh.f);
}
/* dh_instance, packet -> salt */
int
srp_process_reply_msg(struct srp_instance *self, struct lsh_string *packet)
{
struct simple_buffer buffer;
unsigned msg_number;
UINT32 u;
mpz_t t;
simple_buffer_init(&buffer, packet->length, packet->data);
if (! (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_KEXSRP_REPLY)
&& ( (self->salt = parse_string_copy(&buffer) ))
&& parse_bignum(&buffer, self->f)
&& (mpz_cmp_ui(self->f, 1) > 0)
&& GROUP_RANGE(self->method->G, self->f)
&& parse_eod(&buffer)))
return 0;
u = srp_select_u(...);
if (!u)
return 0;
return 1;
}
struct lsh_string *make_
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment