예제 #1
0
/* Checks if b%n==0 which is a fatal srp error.
 * Returns a proper error code in that case, and 0 when
 * all are ok.
 */
inline static int
check_b_mod_n (bigint_t b, bigint_t n)
{
  int ret;
  bigint_t r;

  r = _gnutls_mpi_mod (b, n);

  if (r == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  ret = _gnutls_mpi_cmp_ui (r, 0);

  _gnutls_mpi_release (&r);

  if (ret == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

  return 0;
}
예제 #2
0
/* Checks if a%n==0,+1,-1%n which is a fatal srp error.
 * Returns a proper error code in that case, and 0 when
 * all are ok.
 */
inline static int
check_a_mod_n (mpi_t a, mpi_t n)
{
  int ret;
  mpi_t r = _gnutls_mpi_alloc_like (a);

  if (r == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_mpi_mod (r, a, n);
  ret = _gnutls_mpi_cmp_ui (r, 0);

  _gnutls_mpi_release (&r);

  if (ret == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

  return 0;
}
예제 #3
0
파일: mpi.c 프로젝트: Chronic-Dev/gnutls
/*
 * Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
 *
 * Author: Simon Josefsson
 *
 * This file is part of GnuTLS.
 *
 * GnuTLS 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 3 of the License, or
 * (at your option) any later version.
 *
 * GnuTLS 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 GnuTLS; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>

#include "utils.h"
#include "../lib/gnutls_int.h"
#include "../lib/gnutls_mpi.h"
#include "../lib/gnutls_errors.h"
#include "../lib/debug.h"

static void
tls_log_func (int level, const char *str)
{
  fprintf (stderr, "|<%d>| %s", level, str);
}

#define RND_BITS 510		/* not multiple of 8 */
void
doit (void)
{
  int rc;
  bigint_t n1, n2, n3, n4;

  gnutls_global_init ();

  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (99);

  n1 = _gnutls_mpi_new (1000);
  if (n1 == NULL)
    fail ("mpi_new failed\n");

  n2 = _gnutls_mpi_set_ui (NULL, 2);
  if (n2 == NULL)
    fail ("mpi_set_ui failed\n");

  n3 = _gnutls_mpi_set_ui (NULL, 5);
  if (n3 == NULL)
    fail ("mpi_set_ui failed\n");

  _gnutls_mpi_randomize (n1, RND_BITS, GNUTLS_RND_NONCE);

  _gnutls_mpi_log ("rand:", n1);

  rc = _gnutls_mpi_get_nbits (n1);
  if (rc > RND_BITS)
    fail ("mpi_get_nbits failed... returned %d\n", rc);

  n4 = _gnutls_mpi_addm (NULL, n1, n3, n2);
  if (n4 == NULL)
    fail ("mpi_set_ui failed\n");

  if (_gnutls_mpi_cmp_ui (n4, 0) != 0 && _gnutls_mpi_cmp_ui (n4, 1) != 0)
    fail ("mpi_cmp_ui failed\n");

  _gnutls_mpi_release (&n1);
  _gnutls_mpi_release (&n2);
  _gnutls_mpi_release (&n3);
  _gnutls_mpi_release (&n4);

  success ("mpi ops ok\n");
}
예제 #4
0
/* Checks if a%n==0,+1,-1%n which is a fatal srp error.
 * Returns a proper error code in that case, and 0 when
 * all are ok.
 */
inline static int check_param_mod_n(bigint_t a, bigint_t n, int is_a)
{
	int ret, err = 0;
	bigint_t r;

	ret = _gnutls_mpi_init(&r);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = _gnutls_mpi_modm(r, a, n);
	if (ret < 0) {
		_gnutls_mpi_release(&r);
		return gnutls_assert_val(ret);
	}

	ret = _gnutls_mpi_cmp_ui(r, 0);
	if (ret == 0)
		err = 1;

	if (is_a != 0) {
		ret = _gnutls_mpi_cmp_ui(r, 1);
		if (ret == 0)
			err = 1;

		ret = _gnutls_mpi_add_ui(r, r, 1);
		if (ret < 0) {
			_gnutls_mpi_release(&r);
			return gnutls_assert_val(ret);
		}
		
		ret = _gnutls_mpi_cmp(r, n);
		if (ret == 0)
			err = 1;
	}

	_gnutls_mpi_release(&r);

	if (err != 0) {
		gnutls_assert();
		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
	}

	return 0;
}
예제 #5
0
/* returns the public value (X), and the secret (ret_x).
 */
mpi_t
gnutls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime)
{
  mpi_t e, x;
  int x_size = _gnutls_mpi_get_nbits (prime) - 1;
  /* The size of the secret key is less than
   * prime/2
   */

  if (x_size > MAX_BITS || x_size <= 0)
    {
      gnutls_assert ();
      return NULL;
    }

  x = _gnutls_mpi_new (x_size);
  if (x == NULL)
    {
      gnutls_assert ();
      if (ret_x)
	*ret_x = NULL;

      return NULL;
    }

  /* FIXME: (x_size/8)*8 is there to overcome a bug in libgcrypt
   * which does not really check the bits given but the bytes.
   */
  do
    {
      _gnutls_mpi_randomize (x, (x_size / 8) * 8, GCRY_STRONG_RANDOM);
      /* Check whether x is zero. 
       */
    }
  while (_gnutls_mpi_cmp_ui (x, 0) == 0);

  e = _gnutls_mpi_alloc_like (prime);
  if (e == NULL)
    {
      gnutls_assert ();
      if (ret_x)
	*ret_x = NULL;

      _gnutls_mpi_release (&x);
      return NULL;
    }

  _gnutls_mpi_powm (e, g, x, prime);

  if (ret_x)
    *ret_x = x;
  else
    _gnutls_mpi_release (&x);
  return e;
}
예제 #6
0
파일: gnutls_mpi.c 프로젝트: ares89/vlc
/* returns zero on success. Fails if the number is zero.
 */
int
_gnutls_mpi_scan_nz (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
{
  int ret;

  ret = _gnutls_mpi_scan (ret_mpi, buffer, nbytes);
  if (ret < 0)
    return ret;

  /* MPIs with 0 bits are illegal
   */
  if (_gnutls_mpi_cmp_ui (*ret_mpi, 0) == 0)
    {
      _gnutls_mpi_release (ret_mpi);
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  return 0;
}
예제 #7
0
파일: dh.c 프로젝트: gnutls/gnutls
/**
 * gnutls_dh_params_import_pkcs3:
 * @params: The parameters
 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
 * @format: the format of params. PEM or DER.
 *
 * This function will extract the DHParams found in a PKCS3 formatted
 * structure. This is the format generated by "openssl dhparam" tool.
 *
 * If the structure is PEM encoded, it should have a header
 * of "BEGIN DH PARAMETERS".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_dh_params_import_pkcs3(gnutls_dh_params_t params,
			      const gnutls_datum_t * pkcs3_params,
			      gnutls_x509_crt_fmt_t format)
{
	ASN1_TYPE c2;
	int result, need_free = 0;
	unsigned int q_bits;
	gnutls_datum_t _params;

	if (format == GNUTLS_X509_FMT_PEM) {

		result = _gnutls_fbase64_decode("DH PARAMETERS",
						pkcs3_params->data,
						pkcs3_params->size,
						&_params);

		if (result < 0) {
			gnutls_assert();
			return result;
		}

		need_free = 1;
	} else {
		_params.data = pkcs3_params->data;
		_params.size = pkcs3_params->size;
	}

	if ((result = asn1_create_element
	     (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
	    != ASN1_SUCCESS) {
		gnutls_assert();
		if (need_free != 0) {
			gnutls_free(_params.data);
			_params.data = NULL;
		}
		return _gnutls_asn2err(result);
	}

	/* PKCS#3 doesn't specify whether DHParameter is encoded as
	 * BER or DER, thus we don't restrict libtasn1 to DER subset */
	result = asn1_der_decoding(&c2, _params.data, _params.size, NULL);

	if (need_free != 0) {
		gnutls_free(_params.data);
		_params.data = NULL;
	}

	if (result != ASN1_SUCCESS) {
		/* couldn't decode DER */

		_gnutls_debug_log("DHParams: Decoding error %d\n", result);
		gnutls_assert();
		asn1_delete_structure(&c2);
		return _gnutls_asn2err(result);
	}

	/* Read q length */
	result = _gnutls_x509_read_uint(c2, "privateValueLength", &q_bits);
	if (result < 0) {
		gnutls_assert();
		params->q_bits = 0;
	} else
		params->q_bits = q_bits;

	/* Read PRIME 
	 */
	result = _gnutls_x509_read_int(c2, "prime", &params->params[0]);
	if (result < 0) {
		asn1_delete_structure(&c2);
		gnutls_assert();
		return result;
	}

	if (_gnutls_mpi_cmp_ui(params->params[0], 0) == 0) {
		asn1_delete_structure(&c2);
		return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
	}

	/* read the generator
	 */
	result = _gnutls_x509_read_int(c2, "base", &params->params[1]);
	if (result < 0) {
		asn1_delete_structure(&c2);
		_gnutls_mpi_release(&params->params[0]);
		gnutls_assert();
		return result;
	}

	if (_gnutls_mpi_cmp_ui(params->params[1], 0) == 0) {
		asn1_delete_structure(&c2);
		_gnutls_mpi_release(&params->params[0]);
		return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
	}

	asn1_delete_structure(&c2);

	return 0;
}
예제 #8
0
/* Decodes an DSA privateKey and params from a PKCS8 structure.
 */
static int
_decode_pkcs8_dsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};

	gnutls_pk_params_init(&pkey->params);

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_der_int(tmp.data, tmp.size,
				      &pkey->params.params[4]);
	_gnutls_free_key_datum(&tmp);

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_value(pkcs8_asn,
				    "privateKeyAlgorithm.parameters",
				    &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_pubkey_params(GNUTLS_PK_DSA, tmp.data,
					    tmp.size, &pkey->params);
	_gnutls_free_datum(&tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_mpi_cmp_ui(pkey->params.params[0], 0) == 0) {
		gnutls_assert();
		ret = GNUTLS_E_ILLEGAL_PARAMETER;
		goto error;
	}

	/* the public key can be generated as g^x mod p */
	ret = _gnutls_mpi_init(&pkey->params.params[3]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls_mpi_powm(pkey->params.params[3], pkey->params.params[2],
			 pkey->params.params[4], pkey->params.params[0]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	pkey->params.algo = GNUTLS_PK_DSA;
	pkey->params.params_nr = DSA_PRIVATE_PARAMS;

	ret =
	    _gnutls_asn1_encode_privkey(&pkey->key,
					&pkey->params);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	return 0;

 error:
	if (pkey->params.params_nr != DSA_PRIVATE_PARAMS)
		_gnutls_mpi_release(&pkey->params.params[4]);
	return ret;
}
예제 #9
0
파일: pk.c 프로젝트: intgr/gnutls
static int
wrap_nettle_pk_verify_params (gnutls_pk_algorithm_t algo,
                              const gnutls_pk_params_st * params)
{
  int ret;

  switch (algo)
    {
    case GNUTLS_PK_RSA:
      {
        bigint_t t1 = NULL, t2 = NULL;

        if (params->params_nr != RSA_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        
        t1 = _gnutls_mpi_new (256);
        if (t1 == NULL)
          return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

        _gnutls_mpi_mulm (t1, params->params[RSA_PRIME1], params->params[RSA_PRIME2], params->params[RSA_MODULUS]);
        if (_gnutls_mpi_cmp_ui(t1, 0) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }

        mpz_invert (TOMPZ(t1), TOMPZ (params->params[RSA_PRIME2]), TOMPZ (params->params[RSA_PRIME1]));
        if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF]) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }

        /* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */
        _gnutls_mpi_sub_ui (t1, params->params[RSA_PRIME1], 1);
        t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1);
        if (t2 == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto rsa_cleanup;
          }
  
        if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }
        
        _gnutls_mpi_sub_ui (t1, params->params[RSA_PRIME2], 1);
        _gnutls_mpi_release(&t2);

        t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1);
        if (t2 == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto rsa_cleanup;
          }
  
        if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }
        
        ret = 0;

rsa_cleanup:
        _gnutls_mpi_release(&t1);
        _gnutls_mpi_release(&t2);
      }

      break;
    case GNUTLS_PK_DSA:
      {
        bigint_t t1 = NULL;

        if (params->params_nr != DSA_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        
        t1 = _gnutls_mpi_new (256);
        if (t1 == NULL)
          return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

        _gnutls_mpi_powm (t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]);

        if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto dsa_cleanup;
          }

        ret = 0;

dsa_cleanup:
        _gnutls_mpi_release(&t1);
      }

      break;
    case GNUTLS_PK_EC:
      {
        int curve = params->flags;
        ecc_key ecc_priv;
        ecc_point *R;
        ecc_point zero;

        if (params->params_nr != ECC_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

        if (is_supported_curve(curve) == 0)
          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);

        _ecc_params_to_privkey(params, &ecc_priv);
        R = ecc_new_point();

        /* verify that x,y lie on the curve */
        ret = ecc_projective_check_point(&ecc_priv.pubkey, TOMPZ(params->params[ECC_B]), params->params[ECC_PRIME]);
        if (ret != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }

        memcpy(&zero.x, ecc_priv.Gx, sizeof(mpz_t));
        memcpy(&zero.y, ecc_priv.Gy, sizeof(mpz_t));
        memcpy(&zero.z, ecc_priv.pubkey.z, sizeof(mpz_t)); /* z = 1 */

        /* verify that k*(Gx,Gy)=(x,y) */
        ret = ecc_mulmod_cached(ecc_priv.k, curve, R, TOMPZ(params->params[ECC_A]), TOMPZ(params->params[ECC_PRIME]), 1);
        if (ret != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }

        if (mpz_cmp(ecc_priv.pubkey.x, R->x) != 0 || mpz_cmp(ecc_priv.pubkey.y, R->y) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }
        
        ret = 0;

ecc_cleanup:
        _ecc_params_clear(&ecc_priv);
        ecc_del_point(R);
      }  
      break;
    default:
      ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    }

  return ret;
}
예제 #10
0
파일: pk.c 프로젝트: randombit/hacrypto
static int
wrap_nettle_pk_verify_params(gnutls_pk_algorithm_t algo,
			     const gnutls_pk_params_st * params)
{
	int ret;

	switch (algo) {
	case GNUTLS_PK_RSA:
		{
			bigint_t t1 = NULL, t2 = NULL;

			if (params->params_nr != RSA_PRIVATE_PARAMS)
				return
				    gnutls_assert_val
				    (GNUTLS_E_INVALID_REQUEST);

			t1 = _gnutls_mpi_new(256);
			if (t1 == NULL)
				return
				    gnutls_assert_val
				    (GNUTLS_E_MEMORY_ERROR);

			_gnutls_mpi_mulm(t1, params->params[RSA_PRIME1],
					 params->params[RSA_PRIME2],
					 params->params[RSA_MODULUS]);
			if (_gnutls_mpi_cmp_ui(t1, 0) != 0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto rsa_cleanup;
			}

			mpz_invert(TOMPZ(t1),
				   TOMPZ(params->params[RSA_PRIME2]),
				   TOMPZ(params->params[RSA_PRIME1]));
			if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF])
			    != 0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto rsa_cleanup;
			}

			/* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */
			_gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME1],
					   1);
			t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1);
			if (t2 == NULL) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_MEMORY_ERROR);
				goto rsa_cleanup;
			}

			if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) !=
			    0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto rsa_cleanup;
			}

			_gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME2],
					   1);
			_gnutls_mpi_release(&t2);

			t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1);
			if (t2 == NULL) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_MEMORY_ERROR);
				goto rsa_cleanup;
			}

			if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) !=
			    0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto rsa_cleanup;
			}

			ret = 0;

		      rsa_cleanup:
			_gnutls_mpi_release(&t1);
			_gnutls_mpi_release(&t2);
		}

		break;
	case GNUTLS_PK_DSA:
		{
			bigint_t t1 = NULL;

			if (params->params_nr != DSA_PRIVATE_PARAMS)
				return
				    gnutls_assert_val
				    (GNUTLS_E_INVALID_REQUEST);

			t1 = _gnutls_mpi_new(256);
			if (t1 == NULL)
				return
				    gnutls_assert_val
				    (GNUTLS_E_MEMORY_ERROR);

			_gnutls_mpi_powm(t1, params->params[DSA_G],
					 params->params[DSA_X],
					 params->params[DSA_P]);

			if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) !=
			    0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto dsa_cleanup;
			}

			ret = 0;

		      dsa_cleanup:
			_gnutls_mpi_release(&t1);
		}

		break;
	case GNUTLS_PK_EC:
		{
			struct ecc_point r, pub;
			struct ecc_scalar priv;
			mpz_t x1, y1, x2, y2;
			const struct ecc_curve *curve;

			if (params->params_nr != ECC_PRIVATE_PARAMS)
				return
				    gnutls_assert_val
				    (GNUTLS_E_INVALID_REQUEST);

			curve = get_supported_curve(params->flags);
			if (curve == NULL)
				return
				    gnutls_assert_val
				    (GNUTLS_E_ECC_UNSUPPORTED_CURVE);

			ret = _ecc_params_to_pubkey(params, &pub, curve);
			if (ret < 0)
				return gnutls_assert_val(ret);

			ret = _ecc_params_to_privkey(params, &priv, curve);
			if (ret < 0) {
				ecc_point_clear(&pub);
				return gnutls_assert_val(ret);
			}

			ecc_point_init(&r, curve);
			/* verify that x,y lie on the curve */
			ret =
			    ecc_point_set(&r, TOMPZ(params->params[ECC_X]),
					  TOMPZ(params->params[ECC_Y]));
			if (ret == 0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto ecc_cleanup;
			}
			ecc_point_clear(&r);

			ecc_point_init(&r, curve);
			ecc_point_mul_g(&r, &priv);

			mpz_init(x1);
			mpz_init(y1);
			ecc_point_get(&r, x1, y1);
			ecc_point_clear(&r);

			mpz_init(x2);
			mpz_init(y2);
			ecc_point_get(&pub, x2, y2);

			/* verify that k*(Gx,Gy)=(x,y) */
			if (mpz_cmp(x1, x2) != 0 || mpz_cmp(y1, y2) != 0) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_ILLEGAL_PARAMETER);
				goto ecc_cleanup;
			}

			ret = 0;

		      ecc_cleanup:
			ecc_scalar_clear(&priv);
			ecc_point_clear(&pub);
		}
		break;
	default:
		ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
	}

	return ret;
}
예제 #11
0
파일: pk.c 프로젝트: Drakey83/steamlink-sdk
/* This is used for DH or ECDH key derivation. In DH for example
 * it is given the peers Y and our x, and calculates Y^x 
 */
static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
				  gnutls_datum_t * out,
				  const gnutls_pk_params_st * priv,
				  const gnutls_pk_params_st * pub)
{
	int ret;

	switch (algo) {
	case GNUTLS_PK_DH: {
		bigint_t f, x, prime;
		bigint_t k = NULL, ff = NULL;
		unsigned int bits;

		f = pub->params[DH_Y];
		x = priv->params[DH_X];
		prime = priv->params[DH_P];

		ret = _gnutls_mpi_init_multi(&k, &ff, NULL);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret = _gnutls_mpi_modm(ff, f, prime);
		if (ret < 0) {
			gnutls_assert();
			goto dh_cleanup;
		}

		ret = _gnutls_mpi_add_ui(ff, ff, 1);
		if (ret < 0) {
			gnutls_assert();
			goto dh_cleanup;
		}

		/* check if f==0,1,p-1. 
		 * or (ff=f+1) equivalently ff==1,2,p */
		if ((_gnutls_mpi_cmp_ui(ff, 2) == 0)
		    || (_gnutls_mpi_cmp_ui(ff, 1) == 0)
		    || (_gnutls_mpi_cmp(ff, prime) == 0)) {
			gnutls_assert();
			ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			goto dh_cleanup;
		}

		/* prevent denial of service */
		bits = _gnutls_mpi_get_nbits(prime);
		if (bits == 0 || bits > MAX_DH_BITS) {
			gnutls_assert();
			ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			goto dh_cleanup;
		}


		ret = _gnutls_mpi_powm(k, f, x, prime);
		if (ret < 0) {
			gnutls_assert();
			goto dh_cleanup;
		}

		ret = _gnutls_mpi_dprint(k, out);
		if (ret < 0) {
			gnutls_assert();
			goto dh_cleanup;
		}

		ret = 0;
dh_cleanup:
		_gnutls_mpi_release(&ff);
		zrelease_temp_mpi_key(&k);
		if (ret < 0)
			goto cleanup;

		break;
	}
	case GNUTLS_PK_EC:
		{
			struct ecc_scalar ecc_priv;
			struct ecc_point ecc_pub;
			const struct ecc_curve *curve;

			out->data = NULL;

			curve = get_supported_curve(priv->flags);
			if (curve == NULL)
				return
				    gnutls_assert_val
				    (GNUTLS_E_ECC_UNSUPPORTED_CURVE);

			ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve);
			if (ret < 0)
				return gnutls_assert_val(ret);

			ret =
			    _ecc_params_to_privkey(priv, &ecc_priv, curve);
			if (ret < 0) {
				ecc_point_clear(&ecc_pub);
				return gnutls_assert_val(ret);
			}

			out->size = gnutls_ecc_curve_get_size(priv->flags);
			/*ecc_size(curve)*sizeof(mp_limb_t); */
			out->data = gnutls_malloc(out->size);
			if (out->data == NULL) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_MEMORY_ERROR);
				goto ecc_cleanup;
			}

			ecc_shared_secret(&ecc_priv, &ecc_pub, out->data,
					  out->size);

		      ecc_cleanup:
			ecc_point_clear(&ecc_pub);
			ecc_scalar_zclear(&ecc_priv);
			if (ret < 0)
				goto cleanup;
			break;
		}
	default:
		gnutls_assert();
		ret = GNUTLS_E_INTERNAL_ERROR;
		goto cleanup;
	}

	ret = 0;

      cleanup:

	return ret;
}