diff options
Diffstat (limited to 'source4/heimdal/lib/hcrypto/dh.c')
-rw-r--r-- | source4/heimdal/lib/hcrypto/dh.c | 215 |
1 files changed, 206 insertions, 9 deletions
diff --git a/source4/heimdal/lib/hcrypto/dh.c b/source4/heimdal/lib/hcrypto/dh.c index b558eb901c..9f1af0b3b1 100644 --- a/source4/heimdal/lib/hcrypto/dh.c +++ b/source4/heimdal/lib/hcrypto/dh.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,7 +35,7 @@ #include <config.h> #endif -RCSID("$Id: dh.c 18618 2006-10-19 17:31:51Z lha $"); +RCSID("$Id: dh.c 22397 2008-01-01 20:20:31Z lha $"); #include <stdio.h> #include <stdlib.h> @@ -43,8 +43,23 @@ RCSID("$Id: dh.c 18618 2006-10-19 17:31:51Z lha $"); #include <roken.h> -/* +/** + * @page page_dh DH - Diffie-Hellman key exchange + * + * Diffie-Hellman key exchange is a protocol that allows two parties + * to establish a shared secret key. + * + * Include and example how to use DH_new() and friends here. * + * See the library functions here: @ref hcrypto_dh + */ + +/** + * Create a new DH object using DH_new_method(NULL), see DH_new_method(). + * + * @return a newly allocated DH object. + * + * @ingroup hcrypto_dh */ DH * @@ -53,6 +68,17 @@ DH_new(void) return DH_new_method(NULL); } +/** + * Create a new DH object from the given engine, if the NULL is used, + * the default engine is used. Free the DH object with DH_free(). + * + * @param engine The engine to use to allocate the DH object. + * + * @return a newly allocated DH object. + * + * @ingroup hcrypto_dh + */ + DH * DH_new_method(ENGINE *engine) { @@ -88,6 +114,15 @@ DH_new_method(ENGINE *engine) return dh; } +/** + * Free a DH object and release related resources, like ENGINE, that + * the object was using. + * + * @param dh object to be freed. + * + * @ingroup hcrypto_dh + */ + void DH_free(DH *dh) { @@ -116,18 +151,52 @@ DH_free(DH *dh) free(dh); } +/** + * Add a reference to the DH object. The object should be free with + * DH_free() to drop the reference. + * + * @param dh the object to increase the reference count too. + * + * @return the updated reference count, can't safely be used except + * for debug printing. + * + * @ingroup hcrypto_dh + */ + int DH_up_ref(DH *dh) { return ++dh->references; } +/** + * The maximum output size of the DH_compute_key() function. + * + * @param dh The DH object to get the size from. + * + * @return the maximum size in bytes of the out data. + * + * @ingroup hcrypto_dh + */ + int DH_size(const DH *dh) { return BN_num_bytes(dh->p); } +/** + * Set the data index idx in the DH object to data. + * + * @param dh DH object. + * @param idx index to set the data for. + * @param data data to store for the index idx. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_set_ex_data(DH *dh, int idx, void *data) { @@ -135,12 +204,36 @@ DH_set_ex_data(DH *dh, int idx, void *data) return 1; } +/** + * Get the data for index idx in the DH object. + * + * @param dh DH object. + * @param idx index to get the data for. + * + * @return the object store in index idx + * + * @ingroup hcrypto_dh + */ + void * DH_get_ex_data(DH *dh, int idx) { return dh->ex_data.sk; } +/** + * Generate DH parameters for the DH object give parameters. + * + * @param dh The DH object to generate parameters for. + * @param prime_len length of the prime + * @param generator generator, g + * @param cb Callback parameters to show progress, can be NULL. + * + * @return the maximum size in bytes of the out data. + * + * @ingroup hcrypto_dh + */ + int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb) { @@ -149,12 +242,17 @@ DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb) return 0; } -/* - * Check that +/** + * Check that the public key is sane. * - * pub_key > 1 and pub_key < p - 1 + * @param dh the local peer DH parameters. + * @param pub_key the remote peer public key parameters. + * @param codes return that the failures of the pub_key are. * - * to avoid small subgroups attack. + * @return 1 on success, 0 on failure and *codes is set the the + * combined fail check for the public key + * + * @ingroup hcrypto_dh */ int @@ -165,6 +263,19 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) *codes = 0; + /** + * Checks that the function performs are: + * - pub_key is not negative + */ + + if (BN_is_negative(pub_key)) + goto out; + + /** + * - pub_key > 1 and pub_key < p - 1, + * to avoid small subgroups attack. + */ + bn = BN_new(); if (bn == NULL) goto out; @@ -184,6 +295,28 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) if (BN_cmp(sum, dh->p) >= 0) *codes |= DH_CHECK_PUBKEY_TOO_LARGE; + /** + * - if g == 2, pub_key have more then one bit set, + * if bits set is 1, log_2(pub_key) is trival + */ + + if (!BN_set_word(bn, 2)) + goto out; + + if (BN_cmp(bn, pub_key) == 0) { + unsigned i, n = BN_num_bits(pub_key); + unsigned bits = 0; + + for (i = 0; i <= n; i++) + if (BN_is_bit_set(pub_key, i)) + bits++; + + if (bits > 1) { + *codes |= DH_CHECK_PUBKEY_TOO_SMALL; + goto out; + } + } + ret = 1; out: if (bn) @@ -194,24 +327,64 @@ out: return ret; } +/** + * Generate a new DH private-public key pair. The dh parameter must be + * allocted first with DH_new(). dh->p and dp->g must be set. + * + * @param dh dh parameter. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_generate_key(DH *dh) { return dh->meth->generate_key(dh); } +/** + * Complute the shared secret key. + * + * @param shared_key the resulting shared key, need to be at least + * DH_size() large. + * @param peer_pub_key the peer's public key. + * @param dh the dh key pair. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_compute_key(unsigned char *shared_key, const BIGNUM *peer_pub_key, DH *dh) { int codes; + /** + * Checks that the pubkey passed in is valid using + * DH_check_pubkey(). + */ + if (!DH_check_pubkey(dh, peer_pub_key, &codes) || codes != 0) return -1; return dh->meth->compute_key(shared_key, peer_pub_key, dh); } +/** + * Set a new method for the DH keypair. + * + * @param dh dh parameter. + * @param method the new method for the DH parameter. + * + * @return 1 on success. + * + * @ingroup hcrypto_dh + */ + int DH_set_method(DH *dh, const DH_METHOD *method) { @@ -271,8 +444,16 @@ static const DH_METHOD dh_null_method = { dh_null_generate_params }; -extern const DH_METHOD hc_dh_imath_method; -static const DH_METHOD *dh_default_method = &hc_dh_imath_method; +extern const DH_METHOD _hc_dh_imath_method; +static const DH_METHOD *dh_default_method = &_hc_dh_imath_method; + +/** + * Return the dummy DH implementation. + * + * @return pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ const DH_METHOD * DH_null_method(void) @@ -280,12 +461,28 @@ DH_null_method(void) return &dh_null_method; } +/** + * Set the default DH implementation. + * + * @param meth pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ + void DH_set_default_method(const DH_METHOD *meth) { dh_default_method = meth; } +/** + * Return the default DH implementation. + * + * @return pointer to a DH_METHOD. + * + * @ingroup hcrypto_dh + */ + const DH_METHOD * DH_get_default_method(void) { |