Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
LSH
lsh
Commits
a1b409cd
Commit
a1b409cd
authored
Sep 06, 1998
by
Niels Möller
Browse files
Implemented DH key exchange.
Rev: src/publickey_crypto.c:1.3 Rev: src/publickey_crypto.h:1.2
parent
876c2b47
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/publickey_crypto.c
View file @
a1b409cd
...
...
@@ -5,13 +5,16 @@
#include "bignum.h"
#include "sha.h"
#include "atoms.h"
#include "publickey_crypto.h"
/* DSS signatures */
struct
dss_public
{
bignum
p
;
bignum
q
;
bignum
g
;
bignum
y
;
mpz_t
p
;
mpz_t
q
;
mpz_t
g
;
mpz_t
y
;
};
struct
dss_signer
...
...
@@ -19,7 +22,7 @@ struct dss_signer
struct
signer
super
;
struct
randomness
*
random
;
struct
dss_public
public
;
bignum
a
;
mpz_t
a
;
};
struct
dss_verifier
...
...
@@ -34,7 +37,7 @@ struct dss_algorithm
struct
randomness
*
random
;
};
static
void
dss_hash
(
bignum
h
,
UINT32
length
,
UINT8
*
msg
)
static
void
dss_hash
(
mpz_t
h
,
UINT32
length
,
UINT8
*
msg
)
{
/* Compute hash */
hash
=
MAKE_HASH
(
&
sha_algorithm
);
...
...
@@ -52,7 +55,7 @@ static struct lsh_string *do_dss_sign(struct signer *s,
UINT8
*
msg
)
{
struct
dss_signer
*
closure
=
(
struct
dss_signer
*
)
s
;
bignum
k
,
r
,
s
,
tmp
;
mpz_t
k
,
r
,
s
,
tmp
;
struct
hash_instance
*
hash
;
UINT8
*
digest
;
struct
lsh_string
*
signature
;
...
...
@@ -114,9 +117,9 @@ ind do_dss_verify(struct verifier *closure,
int
res
;
int
atom
;
bignum
r
,
s
;
mpz_t
r
,
s
;
bignum
w
,
tmp
,
u
,
v
;
mpz_t
w
,
tmp
,
u
,
v
;
simple_buffer_init
(
&
buffer
,
signature_length
,
signature_data
);
if
(
!
parse_atom
(
&
buffer
,
&
atom
)
...
...
@@ -301,3 +304,207 @@ struct make_dss_algorithm(struct randomness *random)
return
&
dss
->
super
;
}
/* Groups */
struct
group_zn
/* Z_n^* */
{
struct
group
super
;
mpz_t
modulo
;
};
static
int
zn_member
(
struct
group
*
c
,
mpz_t
x
)
{
struct
group_zn
*
closure
=
(
struct
group_zn
*
)
c
;
return
(
(
mpz_sgn
(
x
)
==
1
)
&&
(
mpz_cmp
(
x
,
closure
->
modulo
)
<
0
)
);
}
static
void
zn_invert
(
struct
group
*
c
,
mpz_t
res
,
mpz_t
x
)
{
struct
group_zn
*
closure
=
(
struct
group_zn
*
)
c
;
if
(
!
mpz_invert
(
res
,
x
,
closure
->
modulo
))
fatal
(
"zn_invert: element is non-invertible
\n
"
);
}
static
void
zn_combine
(
struct
group
*
c
,
mpz_t
res
,
mpz_t
a
,
mpz_t
b
)
{
struct
group_zn
*
closure
=
(
struct
group_zn
*
)
c
;
mpz_mul
(
res
,
a
,
b
);
mpz_tdiv_r
(
res
,
res
,
closure
->
modulo
);
}
static
void
zn_power
(
struct
group
*
c
,
mpz_t
res
,
mpz_t
g
,
mpz_t
e
)
{
struct
group_zn
*
closure
=
(
struct
group_zn
*
)
c
;
mpz_powm
(
res
,
g
,
e
,
closure
->
modulo
);
}
/* Assumes p is a prime number */
struct
group
*
make_zn
(
mpz_t
p
)
{
struct
group_zn
*
res
=
xalloc
(
sizeof
(
struct
group_zn
));
res
->
super
.
member
=
zn_member
;
res
->
super
.
invert
=
zn_invert
;
res
->
super
.
combine
=
zn_combine
;
res
->
super
.
power
=
zn_power
;
/* Pretty Mutation! Magical Recall! */
mpz_init_set
(
res
->
modulo
,
n
);
mpz_init_set
(
res
->
super
.
order
,
n
);
return
&
res
->
super
;
}
/* diffie-hellman */
struct
diffie_hellman_instance
*
make_diffie_hellman_instance
(
struct
diffie_hellman_method
*
m
,
struct
connection
*
c
)
{
struct
diffie_hellman_instance
*
res
=
xalloc
(
sizeof
(
struct
diffie_hellman_instance
));
mpz_init
(
res
->
e
);
mpz_init
(
res
->
f
);
mpz_init
(
res
->
secret
);
res
->
method
=
m
;
res
->
hash
=
make_hash
(
m
->
H
);
HASH_UPDATE
(
res
->
hash
,
c
->
client_version
->
length
,
c
->
client_version
->
data
);
HASH_UPDATE
(
res
->
hash
,
c
->
server_version
->
length
,
c
->
server_version
->
data
);
return
res
;
}
struct
group
*
make_dh1
(
struct
randomness
*
r
)
{
struct
diffie_hellman_method
*
res
=
xalloc
(
sizeof
(
struct
diffie_hellman_method
));
mpz_t
p
;
mpz_init_set_str
(
p
,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
"FFFFFFFFFFFFFFFF"
,
16
);
res
->
G
=
make_zn
(
p
);
mpz_clear
(
p
);
mpz_init_set_ui
(
res
->
generator
,
2
);
res
->
hash_algorithm
=
&
sha_algorithm
;
res
->
random
=
r
;
return
res
;
}
void
dh_generate_secret
(
struct
diffie_hellman_instance
*
self
,
mpz_t
r
)
{
mpz_t
tmp
;
/* Generate a random number, 1 < x < O(G) */
mpz_init_set
(
tmp
,
self
->
method
->
G
->
order
);
mpz_sub_ui
(
tmp
,
tmp
,
2
);
bignum_random
(
self
->
secret
,
tmp
);
mpz_add_ui
(
self
->
secret
,
self
->
secret
,
2
);
mpz_clear
(
tmp
);
GROUP_POWER
(
self
->
methog
->
G
,
r
,
self
->
method
->
generator
,
self
->
secret
);
}
struct
lsh_string
*
dh_make_client_msg
(
struct
diffie_hellman_instance
*
self
)
{
dh_generate_secret
(
self
,
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
;
UINT8
msg_number
;
simple_buffer_init
(
&
buffer
,
packet
->
length
,
packet
->
data
);
return
(
parse_uint8
(
&
buffer
,
&
msg_number
)
&&
(
msg_number
==
SSH_MSG_KEXDH_INIT
)
&&
parse_bignum
(
&
buffer
,
self
->
e
)
&&
(
mpz_cmp_ui
(
self
->
e
,
1
)
>
0
)
&&
(
mpz_cmp
(
self
->
e
,
self
->
method
->
G
->
order
)
<
0
)
&&
parse_eod
(
&
buffer
)
);
}
void
dh_hash_update
(
struct
diffie_hellman_instance
*
self
,
struct
lsh_string
*
packet
)
{
HASH_UPDATE
(
self
->
hash
,
packet
->
length
,
packet
->
data
);
}
/* 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"
,
self
->
server_key
,
self
->
e
,
self
->
f
);
HASH_UPDATE
(
self
->
hash
,
s
->
length
,
s
->
data
);
lsh_string_free
(
s
);
HASH_DIGEST
(
hash
,
digest
);
}
struct
lsh_string
*
dh_make_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
signer
*
s
)
{
UINT8
*
digest
;
dh_generate_secret
(
self
,
self
->
f
);
digest
=
alloca
(
self
->
hash
->
hash_size
);
dh_digest
(
self
,
digest
);
return
ssh_format
(
"%c%S%n%fS"
,
SSH_MSG_KEXDH_REPLY
,
self
->
server_key
,
self
->
f
,
SIGN
(
s
,
self
->
hash
->
hash_size
,
digest
));
}
int
dh_process_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
lsh_string
*
packet
)
{
struct
simple_buffer
buffer
;
UINT8
msg_number
;
simple_buffer_init
(
&
buffer
,
packet
->
length
,
packet
->
data
);
return
(
parse_uint8
(
&
buffer
,
&
msg_number
)
&&
(
msg_number
==
SSH_MSG_KEXDH_REPLY
)
&&
(
res
->
server_key
=
parse_string_copy
(
&
buffer
))
&&
(
parse_bignum
(
&
buffer
,
res
->
f
))
&&
(
mpz_cmp_ui
(
self
->
f
,
1
)
>
0
)
&&
(
mpz_cmp
(
self
->
f
,
self
->
method
->
G
->
order
)
<
0
)
&&
(
res
->
signature
=
parse_string_copy
(
&
buffer
))
&&
parse_eod
(
&
buffer
));
}
int
dh_verify_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
verifier
*
v
)
{
UINT8
*
digest
;
digest
=
alloca
(
self
->
hash
->
hash_size
);
dh_digest
(
self
,
digest
);
return
VERIFY
(
v
,
self
->
hash
->
hash_size
,
digest
,
self
->
signature
->
length
,
self
->
signature
->
data
);
}
src/publickey_crypto.h
View file @
a1b409cd
...
...
@@ -9,5 +9,80 @@
struct
make_dss_algorithm
(
struct
randomness
*
random
);
/* Groups. For now, assume that all group elements are represented by
* bignums. */
struct
group
{
/* Returns 1 if x is an element of the group, and is in the
* canonical representation */
int
(
*
member
)(
struct
group
*
closure
,
mpz_t
x
);
void
(
*
invert
)(
struct
group
*
closure
,
mpz_t
res
,
mpz_t
x
);
void
(
*
combine
)(
struct
group
*
closure
,
mpz_t
res
,
mpz_t
a
,
mpz_t
b
);
/* FIXME: Doesn't handle negative exponents */
void
(
*
power
)(
struct
group
*
closure
,
mpz_t
res
,
mpz_t
g
,
mpz_t
e
);
mpz_t
order
;
};
#define GROUP_MEMBER(group, x) ((group)->member((group), (x)))
#define GROUP_INVERT(group, res, x) ((group)->invert((group), (res), (x)))
#define GROUP_COMBINE(group, res, a, b) \
((group)->combine((group), (res), (a), (b)))
#define GROUP_POWER(group, res, g, e) \
((group)->POWER((group), (res), (g), (e)))
/* DH key exchange, with authentication */
struct
diffie_hellman_method
{
struct
group
*
G
;
mpz_t
generator
;
struct
hash_algorithm
*
H
;
struct
randomness
*
random
;
};
struct
diffie_hellman_instance
{
struct
diffie_hellman_method
*
method
;
mpz_t
e
;
/* client value */
mpz_t
f
;
/* server value */
struct
lsh_string
*
server_key
;
struct
lsh_string
*
signature
;
mpz_t
secret
;
/* This side's secret exponent */
struct
lsh_string
*
K
;
struct
hash_instance
*
hash
;
};
/* Creates client message */
struct
lsh_string
*
dh_make_client_msg
(
struct
diffie_hellman_instance
*
self
);
/* Recieves client message */
int
dh_process_client_msg
(
struct
diffie_hellman_instance
*
self
,
struct
lsh_string
*
packet
);
/* Should be called with the kex_init messages, client's first */
void
dh_hash_update
(
struct
diffie_hellman_instance
*
self
,
struct
lsh_string
*
packet
);
/* Creates server message */
struct
lsh_string
*
dh_make_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
signer
s
);
/* Decodes server message, but does not verify its signature */
int
dh_process_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
lsh_string
*
packet
);
/* Verifies server's signature */
int
dh_verify_server_msg
(
struct
diffie_hellman_instance
*
self
,
struct
verifier
*
v
);
#if 0
struct diffie_hellman_method *
make_diffie_hellman_method(struct group *group,
struct hash_algorithm *h,
struct randomness *r);
#endif
struct
diffie_hellman_instance
*
make_diffie_hellman_instance
(
struct
diffie_hellman_method
*
m
,
struct
connection
*
c
);
#endif
/* LSH_PUBLICKEY_CRYPTO_H_INCLUDED */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment