LCOV - code coverage report
Current view: top level - source4/heimdal/lib/hcrypto - dh.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 64 147 43.5 %
Date: 2021-09-23 10:06:22 Functions: 8 22 36.4 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #ifdef HAVE_CONFIG_H
      35             : #include <config.h>
      36             : #endif
      37             : 
      38             : #include <stdio.h>
      39             : #include <stdlib.h>
      40             : #include <krb5-types.h>
      41             : #include <rfc2459_asn1.h>
      42             : 
      43             : #include <dh.h>
      44             : 
      45             : #include <roken.h>
      46             : 
      47             : /**
      48             :  * @page page_dh DH - Diffie-Hellman key exchange
      49             :  *
      50             :  * Diffie-Hellman key exchange is a protocol that allows two parties
      51             :  * to establish a shared secret key.
      52             :  *
      53             :  * Include and example how to use DH_new() and friends here.
      54             :  *
      55             :  * See the library functions here: @ref hcrypto_dh
      56             :  */
      57             : 
      58             : /**
      59             :  * Create a new DH object using DH_new_method(NULL), see DH_new_method().
      60             :  *
      61             :  * @return a newly allocated DH object.
      62             :  *
      63             :  * @ingroup hcrypto_dh
      64             :  */
      65             : 
      66             : DH *
      67          74 : DH_new(void)
      68             : {
      69          74 :     return DH_new_method(NULL);
      70             : }
      71             : 
      72             : /**
      73             :  * Create a new DH object from the given engine, if the NULL is used,
      74             :  * the default engine is used. Free the DH object with DH_free().
      75             :  *
      76             :  * @param engine The engine to use to allocate the DH object.
      77             :  *
      78             :  * @return a newly allocated DH object.
      79             :  *
      80             :  * @ingroup hcrypto_dh
      81             :  */
      82             : 
      83             : DH *
      84          74 : DH_new_method(ENGINE *engine)
      85             : {
      86             :     DH *dh;
      87             : 
      88          74 :     dh = calloc(1, sizeof(*dh));
      89          74 :     if (dh == NULL)
      90           0 :         return NULL;
      91             : 
      92          74 :     dh->references = 1;
      93             : 
      94          74 :     if (engine) {
      95           0 :         ENGINE_up_ref(engine);
      96           0 :         dh->engine = engine;
      97             :     } else {
      98          74 :         dh->engine = ENGINE_get_default_DH();
      99             :     }
     100             : 
     101          74 :     if (dh->engine) {
     102           0 :         dh->meth = ENGINE_get_DH(dh->engine);
     103           0 :         if (dh->meth == NULL) {
     104           0 :             ENGINE_finish(engine);
     105           0 :             free(dh);
     106           0 :             return 0;
     107             :         }
     108             :     }
     109             : 
     110          74 :     if (dh->meth == NULL)
     111          74 :         dh->meth = DH_get_default_method();
     112             : 
     113          74 :     (*dh->meth->init)(dh);
     114             : 
     115          74 :     return dh;
     116             : }
     117             : 
     118             : /**
     119             :  * Free a DH object and release related resources, like ENGINE, that
     120             :  * the object was using.
     121             :  *
     122             :  * @param dh object to be freed.
     123             :  *
     124             :  * @ingroup hcrypto_dh
     125             :  */
     126             : 
     127             : void
     128          74 : DH_free(DH *dh)
     129             : {
     130          74 :     if (dh->references <= 0)
     131           0 :         abort();
     132             : 
     133          74 :     if (--dh->references > 0)
     134           0 :         return;
     135             : 
     136          74 :     (*dh->meth->finish)(dh);
     137             : 
     138          74 :     if (dh->engine)
     139           0 :         ENGINE_finish(dh->engine);
     140             : 
     141             : #define free_if(f) if (f) { BN_free(f); }
     142          74 :     free_if(dh->p);
     143          74 :     free_if(dh->g);
     144          74 :     free_if(dh->pub_key);
     145          74 :     free_if(dh->priv_key);
     146          74 :     free_if(dh->q);
     147          74 :     free_if(dh->j);
     148          74 :     free_if(dh->counter);
     149             : #undef free_if
     150             : 
     151          74 :     memset(dh, 0, sizeof(*dh));
     152          74 :     free(dh);
     153             : }
     154             : 
     155             : /**
     156             :  * Add a reference to the DH object. The object should be free with
     157             :  * DH_free() to drop the reference.
     158             :  *
     159             :  * @param dh the object to increase the reference count too.
     160             :  *
     161             :  * @return the updated reference count, can't safely be used except
     162             :  * for debug printing.
     163             :  *
     164             :  * @ingroup hcrypto_dh
     165             :  */
     166             : 
     167             : int
     168           0 : DH_up_ref(DH *dh)
     169             : {
     170           0 :     return ++dh->references;
     171             : }
     172             : 
     173             : /**
     174             :  * The maximum output size of the DH_compute_key() function.
     175             :  *
     176             :  * @param dh The DH object to get the size from.
     177             :  *
     178             :  * @return the maximum size in bytes of the out data.
     179             :  *
     180             :  * @ingroup hcrypto_dh
     181             :  */
     182             : 
     183             : int
     184          52 : DH_size(const DH *dh)
     185             : {
     186          52 :     return BN_num_bytes(dh->p);
     187             : }
     188             : 
     189             : /**
     190             :  * Set the data index idx in the DH object to data.
     191             :  *
     192             :  * @param dh DH object.
     193             :  * @param idx index to set the data for.
     194             :  * @param data data to store for the index idx.
     195             :  *
     196             :  * @return 1 on success.
     197             :  *
     198             :  * @ingroup hcrypto_dh
     199             :  */
     200             : 
     201             : int
     202           0 : DH_set_ex_data(DH *dh, int idx, void *data)
     203             : {
     204           0 :     dh->ex_data.sk = data;
     205           0 :     return 1;
     206             : }
     207             : 
     208             : /**
     209             :  * Get the data for index idx in the DH object.
     210             :  *
     211             :  * @param dh DH object.
     212             :  * @param idx index to get the data for.
     213             :  *
     214             :  * @return the object store in index idx
     215             :  *
     216             :  * @ingroup hcrypto_dh
     217             :  */
     218             : 
     219             : void *
     220           0 : DH_get_ex_data(DH *dh, int idx)
     221             : {
     222           0 :     return dh->ex_data.sk;
     223             : }
     224             : 
     225             : /**
     226             :  * Generate DH parameters for the DH object give parameters.
     227             :  *
     228             :  * @param dh The DH object to generate parameters for.
     229             :  * @param prime_len length of the prime
     230             :  * @param generator generator, g
     231             :  * @param cb Callback parameters to show progress, can be NULL.
     232             :  *
     233             :  * @return the maximum size in bytes of the out data.
     234             :  *
     235             :  * @ingroup hcrypto_dh
     236             :  */
     237             : 
     238             : int
     239           0 : DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb)
     240             : {
     241           0 :     if (dh->meth->generate_params)
     242           0 :         return dh->meth->generate_params(dh, prime_len, generator, cb);
     243           0 :     return 0;
     244             : }
     245             : 
     246             : /**
     247             :  * Check that the public key is sane.
     248             :  *
     249             :  * @param dh the local peer DH parameters.
     250             :  * @param pub_key the remote peer public key parameters.
     251             :  * @param codes return that the failures of the pub_key are.
     252             :  *
     253             :  * @return 1 on success, 0 on failure and *codes is set the the
     254             :  * combined fail check for the public key
     255             :  *
     256             :  * @ingroup hcrypto_dh
     257             :  */
     258             : 
     259             : int
     260         118 : DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes)
     261             : {
     262         118 :     BIGNUM *bn = NULL, *sum = NULL;
     263         118 :     int ret = 0;
     264             : 
     265         118 :     *codes = 0;
     266             : 
     267             :     /**
     268             :      * Checks that the function performs are:
     269             :      * - pub_key is not negative
     270             :      */
     271             : 
     272         118 :     if (BN_is_negative(pub_key))
     273           0 :         goto out;
     274             : 
     275             :     /**
     276             :      * - pub_key > 1    and    pub_key < p - 1,
     277             :      *    to avoid small subgroups attack.
     278             :      */
     279             : 
     280         118 :     bn = BN_new();
     281         118 :     if (bn == NULL)
     282           0 :         goto out;
     283             : 
     284         118 :     if (!BN_set_word(bn, 1))
     285           0 :         goto out;
     286             : 
     287         118 :     if (BN_cmp(bn, pub_key) >= 0)
     288           0 :         *codes |= DH_CHECK_PUBKEY_TOO_SMALL;
     289             : 
     290         118 :     sum = BN_new();
     291         118 :     if (sum == NULL)
     292           0 :         goto out;
     293             : 
     294         118 :     BN_uadd(sum, pub_key, bn);
     295             : 
     296         118 :     if (BN_cmp(sum, dh->p) >= 0)
     297           0 :         *codes |= DH_CHECK_PUBKEY_TOO_LARGE;
     298             : 
     299             :     /**
     300             :      * - if g == 2, pub_key have more then one bit set,
     301             :      *   if bits set is 1, log_2(pub_key) is trival
     302             :      */
     303             : 
     304         118 :     if (!BN_set_word(bn, 2))
     305           0 :         goto out;
     306             : 
     307         118 :     if (BN_cmp(bn, dh->g) == 0) {
     308         118 :         unsigned i, n = BN_num_bits(pub_key);
     309         118 :         unsigned bits = 0;
     310             : 
     311      120982 :         for (i = 0; i <= n; i++)
     312      120864 :             if (BN_is_bit_set(pub_key, i))
     313       59898 :                 bits++;
     314             : 
     315         118 :         if (bits < 2) {
     316           0 :             *codes |= DH_CHECK_PUBKEY_TOO_SMALL;
     317           0 :             goto out;
     318             :         }
     319             :     }
     320             : 
     321         118 :     ret = 1;
     322         118 : out:
     323         118 :     if (bn)
     324         118 :         BN_free(bn);
     325         118 :     if (sum)
     326         118 :         BN_free(sum);
     327             : 
     328         118 :     return ret;
     329             : }
     330             : 
     331             : /**
     332             :  * Generate a new DH private-public key pair. The dh parameter must be
     333             :  * allocted first with DH_new(). dh->p and dp->g must be set.
     334             :  *
     335             :  * @param dh dh parameter.
     336             :  *
     337             :  * @return 1 on success.
     338             :  *
     339             :  * @ingroup hcrypto_dh
     340             :  */
     341             : 
     342             : int
     343          66 : DH_generate_key(DH *dh)
     344             : {
     345          66 :     return dh->meth->generate_key(dh);
     346             : }
     347             : 
     348             : /**
     349             :  * Complute the shared secret key.
     350             :  *
     351             :  * @param shared_key the resulting shared key, need to be at least
     352             :  * DH_size() large.
     353             :  * @param peer_pub_key the peer's public key.
     354             :  * @param dh the dh key pair.
     355             :  *
     356             :  * @return 1 on success.
     357             :  *
     358             :  * @ingroup hcrypto_dh
     359             :  */
     360             : 
     361             : int
     362          52 : DH_compute_key(unsigned char *shared_key,
     363             :                const BIGNUM *peer_pub_key, DH *dh)
     364             : {
     365             :     int codes;
     366             : 
     367             :     /**
     368             :      * Checks that the pubkey passed in is valid using
     369             :      * DH_check_pubkey().
     370             :      */
     371             : 
     372          52 :     if (!DH_check_pubkey(dh, peer_pub_key, &codes) || codes != 0)
     373           0 :         return -1;
     374             : 
     375          52 :     return dh->meth->compute_key(shared_key, peer_pub_key, dh);
     376             : }
     377             : 
     378             : /**
     379             :  * Set a new method for the DH keypair.
     380             :  *
     381             :  * @param dh dh parameter.
     382             :  * @param method the new method for the DH parameter.
     383             :  *
     384             :  * @return 1 on success.
     385             :  *
     386             :  * @ingroup hcrypto_dh
     387             :  */
     388             : 
     389             : int
     390           0 : DH_set_method(DH *dh, const DH_METHOD *method)
     391             : {
     392           0 :     (*dh->meth->finish)(dh);
     393           0 :     if (dh->engine) {
     394           0 :         ENGINE_finish(dh->engine);
     395           0 :         dh->engine = NULL;
     396             :     }
     397           0 :     dh->meth = method;
     398           0 :     (*dh->meth->init)(dh);
     399           0 :     return 1;
     400             : }
     401             : 
     402             : /*
     403             :  *
     404             :  */
     405             : 
     406             : static int
     407           0 : dh_null_generate_key(DH *dh)
     408             : {
     409           0 :     return 0;
     410             : }
     411             : 
     412             : static int
     413           0 : dh_null_compute_key(unsigned char *shared,const BIGNUM *pub, DH *dh)
     414             : {
     415           0 :     return 0;
     416             : }
     417             : 
     418             : static int
     419           0 : dh_null_init(DH *dh)
     420             : {
     421           0 :     return 1;
     422             : }
     423             : 
     424             : static int
     425           0 : dh_null_finish(DH *dh)
     426             : {
     427           0 :     return 1;
     428             : }
     429             : 
     430             : static int
     431           0 : dh_null_generate_params(DH *dh, int prime_num, int len, BN_GENCB *cb)
     432             : {
     433           0 :     return 0;
     434             : }
     435             : 
     436             : static const DH_METHOD dh_null_method = {
     437             :     "hcrypto null DH",
     438             :     dh_null_generate_key,
     439             :     dh_null_compute_key,
     440             :     NULL,
     441             :     dh_null_init,
     442             :     dh_null_finish,
     443             :     0,
     444             :     NULL,
     445             :     dh_null_generate_params
     446             : };
     447             : 
     448             : extern const DH_METHOD _hc_dh_ltm_method;
     449             : static const DH_METHOD *dh_default_method = &_hc_dh_ltm_method;
     450             : 
     451             : /**
     452             :  * Return the dummy DH implementation.
     453             :  *
     454             :  * @return pointer to a DH_METHOD.
     455             :  *
     456             :  * @ingroup hcrypto_dh
     457             :  */
     458             : 
     459             : const DH_METHOD *
     460           0 : DH_null_method(void)
     461             : {
     462           0 :     return &dh_null_method;
     463             : }
     464             : 
     465             : /**
     466             :  * Set the default DH implementation.
     467             :  *
     468             :  * @param meth pointer to a DH_METHOD.
     469             :  *
     470             :  * @ingroup hcrypto_dh
     471             :  */
     472             : 
     473             : void
     474           0 : DH_set_default_method(const DH_METHOD *meth)
     475             : {
     476           0 :     dh_default_method = meth;
     477           0 : }
     478             : 
     479             : /**
     480             :  * Return the default DH implementation.
     481             :  *
     482             :  * @return pointer to a DH_METHOD.
     483             :  *
     484             :  * @ingroup hcrypto_dh
     485             :  */
     486             : 
     487             : const DH_METHOD *
     488          74 : DH_get_default_method(void)
     489             : {
     490          74 :     return dh_default_method;
     491             : }
     492             : 
     493             : /*
     494             :  *
     495             :  */
     496             : 
     497             : static int
     498           0 : bn2heim_int(BIGNUM *bn, heim_integer *integer)
     499             : {
     500           0 :     integer->length = BN_num_bytes(bn);
     501           0 :     integer->data = malloc(integer->length);
     502           0 :     if (integer->data == NULL) {
     503           0 :         integer->length = 0;
     504           0 :         return ENOMEM;
     505             :     }
     506           0 :     BN_bn2bin(bn, integer->data);
     507           0 :     integer->negative = BN_is_negative(bn);
     508           0 :     return 0;
     509             : }
     510             : 
     511             : /**
     512             :  *
     513             :  */
     514             : 
     515             : int
     516           0 : i2d_DHparams(DH *dh, unsigned char **pp)
     517             : {
     518             :     DHParameter data;
     519             :     size_t size;
     520             :     int ret;
     521             : 
     522           0 :     memset(&data, 0, sizeof(data));
     523             : 
     524           0 :     if (bn2heim_int(dh->p, &data.prime) ||
     525           0 :         bn2heim_int(dh->g, &data.base))
     526             :     {
     527           0 :         free_DHParameter(&data);
     528           0 :         return -1;
     529             :     }
     530             : 
     531           0 :     if (pp == NULL) {
     532           0 :         size = length_DHParameter(&data);
     533           0 :         free_DHParameter(&data);
     534             :     } else {
     535             :         void *p;
     536             :         size_t len;
     537             : 
     538           0 :         ASN1_MALLOC_ENCODE(DHParameter, p, len, &data, &size, ret);
     539           0 :         free_DHParameter(&data);
     540           0 :         if (ret)
     541           0 :             return -1;
     542           0 :         if (len != size) {
     543           0 :             abort();
     544             :             return -1;
     545             :         }
     546             : 
     547           0 :         memcpy(*pp, p, size);
     548           0 :         free(p);
     549             : 
     550           0 :         *pp += size;
     551             :     }
     552             : 
     553           0 :     return size;
     554             : }

Generated by: LCOV version 1.13