Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
David Goulet
Tor
Commits
17ea931a
Commit
17ea931a
authored
Jul 17, 2018
by
Nick Mathewson
⛰
Browse files
Implement DH in NSS.
parent
32bbc8f6
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/lib/crypt_ops/crypto_dh.c
View file @
17ea931a
...
...
@@ -43,6 +43,28 @@ const char OAKLEY_PRIME_2[] =
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF"
;
void
crypto_dh_init
(
void
)
{
#ifdef ENABLE_OPENSSL
crypto_dh_init_openssl
();
#endif
#ifdef ENABLE_NSS
crypto_dh_init_nss
();
#endif
}
void
crypto_dh_free_all
(
void
)
{
#ifdef ENABLE_OPENSSL
crypto_dh_free_all_openssl
();
#endif
#ifdef ENABLE_NSS
crypto_dh_free_all_nss
();
#endif
}
/** Given a DH key exchange object, and our peer's value of g^y (as a
* <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
* <b>secret_bytes_out</b> bytes of shared key material and write them
...
...
src/lib/crypt_ops/crypto_dh.h
View file @
17ea931a
...
...
@@ -27,7 +27,7 @@ extern const char OAKLEY_PRIME_2[];
#define DH_TYPE_CIRCUIT 1
#define DH_TYPE_REND 2
#define DH_TYPE_TLS 3
void
crypto_
set_tls_dh_prime
(
void
);
void
crypto_
dh_init
(
void
);
crypto_dh_t
*
crypto_dh_new
(
int
dh_type
);
crypto_dh_t
*
crypto_dh_dup
(
const
crypto_dh_t
*
dh
);
int
crypto_dh_get_bytes
(
crypto_dh_t
*
dh
);
...
...
@@ -52,4 +52,13 @@ void crypto_dh_free_all(void);
struct
dh_st
;
struct
dh_st
*
crypto_dh_new_openssl_tls
(
void
);
#ifdef ENABLE_OPENSSL
void
crypto_dh_init_openssl
(
void
);
void
crypto_dh_free_all_openssl
(
void
);
#endif
#ifdef ENABLE_OPENSSL
void
crypto_dh_init_nss
(
void
);
void
crypto_dh_free_all_nss
(
void
);
#endif
#endif
/* !defined(TOR_CRYPTO_DH_H) */
src/lib/crypt_ops/crypto_dh_nss.c
0 → 100644
View file @
17ea931a
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_dh_nss.h
*
* \brief NSS implementation of Diffie-Hellman over Z_p.
**/
#include
"lib/crypt_ops/crypto_dh.h"
#include
"lib/crypt_ops/crypto_nss_mgt.h"
#include
"lib/encoding/binascii.h"
#include
"lib/log/util_bug.h"
#include
"lib/malloc/malloc.h"
#include
<cryptohi.h>
#include
<keyhi.h>
#include
<pk11pub.h>
static
int
dh_initialized
=
0
;
static
SECKEYDHParams
tls_dh_param
,
circuit_dh_param
;
static
unsigned
char
tls_dh_prime_data
[
DH1024_KEY_LEN
];
static
unsigned
char
circuit_dh_prime_data
[
DH1024_KEY_LEN
];
static
unsigned
char
dh_generator_data
[
1
];
void
crypto_dh_init_nss
(
void
)
{
if
(
dh_initialized
)
return
;
int
r
;
r
=
base16_decode
((
char
*
)
tls_dh_prime_data
,
sizeof
(
tls_dh_prime_data
),
TLS_DH_PRIME
,
strlen
(
TLS_DH_PRIME
));
tor_assert
(
r
==
DH1024_KEY_LEN
);
r
=
base16_decode
((
char
*
)
circuit_dh_prime_data
,
sizeof
(
circuit_dh_prime_data
),
OAKLEY_PRIME_2
,
strlen
(
OAKLEY_PRIME_2
));
tor_assert
(
r
==
DH1024_KEY_LEN
);
dh_generator_data
[
0
]
=
DH_GENERATOR
;
tls_dh_param
.
prime
.
data
=
tls_dh_prime_data
;
tls_dh_param
.
prime
.
len
=
DH1024_KEY_LEN
;
tls_dh_param
.
base
.
data
=
dh_generator_data
;
tls_dh_param
.
base
.
len
=
1
;
circuit_dh_param
.
prime
.
data
=
circuit_dh_prime_data
;
circuit_dh_param
.
prime
.
len
=
DH1024_KEY_LEN
;
circuit_dh_param
.
base
.
data
=
dh_generator_data
;
circuit_dh_param
.
base
.
len
=
1
;
}
void
crypto_dh_free_all_nss
(
void
)
{
dh_initialized
=
0
;
}
struct
crypto_dh_t
{
int
dh_type
;
// XXXX let's remove this later on.
SECKEYPrivateKey
*
seckey
;
SECKEYPublicKey
*
pubkey
;
};
crypto_dh_t
*
crypto_dh_new
(
int
dh_type
)
{
crypto_dh_t
*
r
=
tor_malloc_zero
(
sizeof
(
crypto_dh_t
));
r
->
dh_type
=
dh_type
;
return
r
;
}
crypto_dh_t
*
crypto_dh_dup
(
const
crypto_dh_t
*
dh
)
{
tor_assert
(
dh
);
crypto_dh_t
*
r
=
crypto_dh_new
(
dh
->
dh_type
);
if
(
dh
->
seckey
)
r
->
seckey
=
SECKEY_CopyPrivateKey
(
dh
->
seckey
);
if
(
dh
->
pubkey
)
r
->
pubkey
=
SECKEY_CopyPublicKey
(
dh
->
pubkey
);
return
r
;
}
int
crypto_dh_get_bytes
(
crypto_dh_t
*
dh
)
{
(
void
)
dh
;
return
DH1024_KEY_LEN
;
}
int
crypto_dh_generate_public
(
crypto_dh_t
*
dh
)
{
tor_assert
(
dh
);
SECKEYDHParams
*
p
;
if
(
dh
->
dh_type
==
DH_TYPE_TLS
)
p
=
&
tls_dh_param
;
else
p
=
&
circuit_dh_param
;
dh
->
seckey
=
SECKEY_CreateDHPrivateKey
(
p
,
&
dh
->
pubkey
,
NULL
);
if
(
!
dh
->
seckey
||
!
dh
->
pubkey
)
return
-
1
;
else
return
0
;
}
int
crypto_dh_get_public
(
crypto_dh_t
*
dh
,
char
*
pubkey_out
,
size_t
pubkey_out_len
)
{
tor_assert
(
dh
);
tor_assert
(
pubkey_out
);
if
(
!
dh
->
pubkey
)
{
if
(
crypto_dh_generate_public
(
dh
)
<
0
)
return
-
1
;
}
const
SECItem
*
item
=
&
dh
->
pubkey
->
u
.
dh
.
publicValue
;
if
(
item
->
len
>
pubkey_out_len
)
return
-
1
;
/* Left-pad the result with 0s. */
memset
(
pubkey_out
,
0
,
pubkey_out_len
);
memcpy
(
pubkey_out
+
pubkey_out_len
-
item
->
len
,
item
->
data
,
item
->
len
);
return
0
;
}
void
crypto_dh_free_
(
crypto_dh_t
*
dh
)
{
if
(
!
dh
)
return
;
if
(
dh
->
seckey
)
SECKEY_DestroyPrivateKey
(
dh
->
seckey
);
if
(
dh
->
pubkey
)
SECKEY_DestroyPublicKey
(
dh
->
pubkey
);
tor_free
(
dh
);
}
ssize_t
crypto_dh_handshake
(
int
severity
,
crypto_dh_t
*
dh
,
const
char
*
pubkey
,
size_t
pubkey_len
,
unsigned
char
*
secret_out
,
size_t
secret_bytes_out
)
{
tor_assert
(
dh
);
if
(
pubkey_len
>
DH1024_KEY_LEN
)
return
-
1
;
if
(
!
dh
->
pubkey
||
!
dh
->
seckey
)
return
-
1
;
if
(
secret_bytes_out
<
DH1024_KEY_LEN
)
return
-
1
;
SECKEYPublicKey
peer_key
;
memset
(
&
peer_key
,
0
,
sizeof
(
peer_key
));
peer_key
.
keyType
=
dhKey
;
peer_key
.
pkcs11ID
=
CK_INVALID_HANDLE
;
if
(
dh
->
dh_type
==
DH_TYPE_TLS
)
peer_key
.
u
.
dh
.
prime
.
data
=
tls_dh_prime_data
;
// should never use this code
else
peer_key
.
u
.
dh
.
prime
.
data
=
circuit_dh_prime_data
;
peer_key
.
u
.
dh
.
prime
.
len
=
DH1024_KEY_LEN
;
peer_key
.
u
.
dh
.
base
.
data
=
dh_generator_data
;
peer_key
.
u
.
dh
.
base
.
len
=
1
;
peer_key
.
u
.
dh
.
publicValue
.
data
=
(
unsigned
char
*
)
pubkey
;
peer_key
.
u
.
dh
.
publicValue
.
len
=
pubkey_len
;
PK11SymKey
*
sym
=
PK11_PubDerive
(
dh
->
seckey
,
&
peer_key
,
PR_FALSE
,
NULL
,
NULL
,
CKM_DH_PKCS_DERIVE
,
CKM_GENERIC_SECRET_KEY_GEN
/* ??? */
,
CKA_DERIVE
,
0
,
NULL
);
if
(
!
sym
)
{
crypto_nss_log_errors
(
severity
,
"deriving a DH shared secret"
);
return
-
1
;
}
SECStatus
s
=
PK11_ExtractKeyValue
(
sym
);
if
(
s
!=
SECSuccess
)
{
crypto_nss_log_errors
(
severity
,
"extracting a DH shared secret"
);
PK11_FreeSymKey
(
sym
);
return
-
1
;
}
SECItem
*
result
=
PK11_GetKeyData
(
sym
);
tor_assert
(
result
);
// This cannot fail.
if
(
BUG
(
result
->
len
>
secret_bytes_out
))
{
PK11_FreeSymKey
(
sym
);
return
-
1
;
}
ssize_t
len
=
result
->
len
;
memcpy
(
secret_out
,
result
->
data
,
len
);
PK11_FreeSymKey
(
sym
);
return
len
;
}
src/lib/crypt_ops/crypto_dh_openssl.c
View file @
17ea931a
...
...
@@ -26,14 +26,17 @@ ENABLE_GCC_WARNING(redundant-decls)
#include
<openssl/bn.h>
#include
<string.h>
#ifndef ENABLE_NSS
static
int
tor_check_dh_key
(
int
severity
,
const
BIGNUM
*
bn
);
static
DH
*
new_openssl_dh_from_params
(
BIGNUM
*
p
,
BIGNUM
*
g
);
/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
* while we're waiting for the second.*/
struct
crypto_dh_t
{
DH
*
dh
;
/**< The openssl DH object */
};
#endif
static
DH
*
new_openssl_dh_from_params
(
BIGNUM
*
p
,
BIGNUM
*
g
);
/** Shared P parameter for our circuit-crypto DH key exchanges. */
static
BIGNUM
*
dh_param_p
=
NULL
;
...
...
@@ -96,6 +99,22 @@ crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
return
ret
;
}
/**
* Helper: convert <b>hex<b> to a bignum, and return it. Assert that the
* operation was successful.
*/
static
BIGNUM
*
bignum_from_hex
(
const
char
*
hex
)
{
BIGNUM
*
result
=
BN_new
();
tor_assert
(
result
);
int
r
=
BN_hex2bn
(
&
result
,
hex
);
tor_assert
(
r
);
tor_assert
(
result
);
return
result
;
}
/** Set the global Diffie-Hellman generator, used for both TLS and internal
* DH stuff.
*/
...
...
@@ -117,62 +136,23 @@ crypto_set_dh_generator(void)
dh_param_g
=
generator
;
}
/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
* modulus. */
/** Initialize our DH parameters. Idempotent. */
void
crypto_
set_tls_dh_prime
(
void
)
crypto_
dh_init_openssl
(
void
)
{
BIGNUM
*
tls_prime
=
NULL
;
int
r
;
/* If the space is occupied, free the previous TLS DH prime */
if
(
BUG
(
dh_param_p_tls
))
{
/* LCOV_EXCL_START
*
* We shouldn't be calling this twice.
*/
BN_clear_free
(
dh_param_p_tls
);
dh_param_p_tls
=
NULL
;
/* LCOV_EXCL_STOP */
}
tls_prime
=
BN_new
();
tor_assert
(
tls_prime
);
r
=
BN_hex2bn
(
&
tls_prime
,
TLS_DH_PRIME
);
tor_assert
(
r
);
if
(
dh_param_p
&&
dh_param_g
&&
dh_param_p_tls
)
return
;
tor_assert
(
tls_prime
);
tor_assert
(
dh_param_g
==
NULL
);
tor_assert
(
dh_param_p
==
NULL
);
tor_assert
(
dh_param_p_tls
==
NULL
);
dh_param_p_tls
=
tls_prime
;
crypto_set_dh_generator
();
tor_assert
(
0
==
crypto_validate_dh_params
(
dh_param_p_tls
,
dh_param_g
));
}
/** Initialize dh_param_p and dh_param_g if they are not already
* set. */
static
void
init_dh_param
(
void
)
{
BIGNUM
*
circuit_dh_prime
;
int
r
;
if
(
BUG
(
dh_param_p
&&
dh_param_g
))
return
;
// LCOV_EXCL_LINE This function isn't supposed to be called twice.
dh_param_p
=
bignum_from_hex
(
OAKLEY_PRIME_2
);
dh_param_p_tls
=
bignum_from_hex
(
TLS_DH_PRIME
);
circuit_dh_prime
=
BN_new
();
tor_assert
(
circuit_dh_prime
);
r
=
BN_hex2bn
(
&
circuit_dh_prime
,
OAKLEY_PRIME_2
);
tor_assert
(
r
);
/* Set the new values as the global DH parameters. */
dh_param_p
=
circuit_dh_prime
;
crypto_set_dh_generator
();
tor_assert
(
0
==
crypto_validate_dh_params
(
dh_param_p
,
dh_param_g
));
if
(
!
dh_param_p_tls
)
{
crypto_set_tls_dh_prime
();
}
tor_assert
(
0
==
crypto_validate_dh_params
(
dh_param_p_tls
,
dh_param_g
));
}
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
...
...
@@ -189,6 +169,7 @@ crypto_dh_new_openssl_tls(void)
return
new_openssl_dh_from_params
(
dh_param_p_tls
,
dh_param_g
);
}
#ifndef ENABLE_NSS
/** Allocate and return a new DH object for a key exchange. Returns NULL on
* failure.
*/
...
...
@@ -201,7 +182,7 @@ crypto_dh_new(int dh_type)
dh_type
==
DH_TYPE_REND
);
if
(
!
dh_param_p
)
init_dh_param
();
crypto_dh_init
();
BIGNUM
*
dh_p
=
NULL
;
if
(
dh_type
==
DH_TYPE_TLS
)
{
...
...
@@ -215,6 +196,7 @@ crypto_dh_new(int dh_type)
tor_free
(
res
);
// sets res to NULL.
return
res
;
}
#endif
/** Create and return a new openssl DH from a given prime and generator. */
static
DH
*
...
...
@@ -260,6 +242,7 @@ new_openssl_dh_from_params(BIGNUM *p, BIGNUM *g)
/* LCOV_EXCL_STOP */
}
#ifndef ENABLE_NSS
/** Return a copy of <b>dh</b>, sharing its internal state. */
crypto_dh_t
*
crypto_dh_dup
(
const
crypto_dh_t
*
dh
)
...
...
@@ -386,7 +369,7 @@ tor_check_dh_key(int severity, const BIGNUM *bn)
x
=
BN_new
();
tor_assert
(
x
);
if
(
BUG
(
!
dh_param_p
))
init_dh_param
();
//LCOV_EXCL_LINE we already checked whether we did this.
crypto_dh_init
();
//LCOV_EXCL_LINE we already checked whether we did this.
BN_set_word
(
x
,
1
);
if
(
BN_cmp
(
bn
,
x
)
<=
0
)
{
log_fn
(
severity
,
LD_CRYPTO
,
"DH key must be at least 2."
);
...
...
@@ -472,9 +455,10 @@ crypto_dh_free_(crypto_dh_t *dh)
DH_free
(
dh
->
dh
);
tor_free
(
dh
);
}
#endif
void
crypto_dh_free_all
(
void
)
crypto_dh_free_all
_openssl
(
void
)
{
if
(
dh_param_p
)
BN_clear_free
(
dh_param_p
);
...
...
src/lib/crypt_ops/crypto_init.c
View file @
17ea931a
...
...
@@ -83,6 +83,8 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
crypto_global_initialized_
=
1
;
crypto_dh_init
();
#ifdef ENABLE_OPENSSL
if
(
crypto_openssl_late_init
(
useAccel
,
accelName
,
accelDir
)
<
0
)
return
-
1
;
...
...
src/lib/crypt_ops/include.am
View file @
17ea931a
...
...
@@ -25,10 +25,12 @@ src_lib_libtor_crypt_ops_a_SOURCES = \
if USE_NSS
src_lib_libtor_crypt_ops_a_SOURCES += \
src/lib/crypt_ops/aes_nss.c \
src/lib/crypt_ops/crypto_dh_nss.c \
src/lib/crypt_ops/crypto_nss_mgt.c
else
src_lib_libtor_crypt_ops_a_SOURCES += \
src/lib/crypt_ops/aes_openssl.c
src/lib/crypt_ops/aes_openssl.c \
src/lib/crypt_ops/crypto_dh_openssl.c
endif
if USE_OPENSSL
...
...
src/test/testing_common.c
View file @
17ea931a
...
...
@@ -292,7 +292,6 @@ main(int c, const char **v)
printf
(
"Can't initialize crypto subsystem; exiting.
\n
"
);
return
1
;
}
crypto_set_tls_dh_prime
();
if
(
crypto_seed_rng
()
<
0
)
{
printf
(
"Couldn't seed RNG; exiting.
\n
"
);
return
1
;
...
...
Write
Preview
Supports
Markdown
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