Exemple #1
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;
}
Exemple #2
0
cdk_error_t _cdk_pubkey_compare(cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
{
	int na, nb, i;

	if (a->timestamp != b->timestamp
	    || a->pubkey_algo != b->pubkey_algo)
		return -1;
	if (a->version < 4 && a->expiredate != b->expiredate)
		return -1;
	na = cdk_pk_get_npkey(a->pubkey_algo);
	nb = cdk_pk_get_npkey(b->pubkey_algo);
	if (na != nb)
		return -1;

	for (i = 0; i < na; i++) {
		if (_gnutls_mpi_cmp(a->mpi[i], b->mpi[i]))
			return -1;
	}

	return 0;
}
Exemple #3
0
/* Check if N is a prime and G a generator of the
 * group. This is check only done if N is big enough.
 * Otherwise only the included parameters must be used.
 */
static int
group_check_g_n (mpi_t g, mpi_t n)
{
  mpi_t q = NULL, two = NULL, w = NULL;
  int ret;

  if (_gnutls_mpi_get_nbits (n) < 2048)
    {
      gnutls_assert ();
      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

  /* N must be of the form N=2q+1
   * where q is also a prime.
   */
  if (_gnutls_prime_check (n, 0) != 0)
    {
      _gnutls_dump_mpi ("no prime N: ", n);
      gnutls_assert ();
      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

  two = _gnutls_mpi_new (4);
  if (two == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  q = _gnutls_mpi_alloc_like (n);
  if (q == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  /* q = n-1 
   */
  _gnutls_mpi_sub_ui (q, n, 1);

  /* q = q/2, remember that q is divisible by 2 (prime - 1)
   */
  _gnutls_mpi_set_ui (two, 2);
  _gnutls_mpi_div (q, NULL, q, two, 0);

  if (_gnutls_prime_check (q, 0) != 0)
    {
      /* N was not on the form N=2q+1, where q = prime
       */
      _gnutls_dump_mpi ("no prime Q: ", q);
      gnutls_assert ();
      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

  /* We also check whether g is a generator,
   */

  /* check if g < q < N
   */
  if (_gnutls_mpi_cmp (g, q) >= 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
      goto error;
    }

  w = _gnutls_mpi_alloc_like (q);
  if (w == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  /* check if g^q mod N == N-1
   * w = g^q mod N
   */
  _gnutls_mpi_powm (w, g, q, n);

  /* w++
   */
  _gnutls_mpi_add_ui (w, w, 1);

  if (_gnutls_mpi_cmp (w, n) != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
      goto error;
    }

  ret = 0;

error:
  _gnutls_mpi_release (&q);
  _gnutls_mpi_release (&two);
  _gnutls_mpi_release (&w);

  return ret;

}
Exemple #4
0
/* Check if N is a prime and G a generator of the
 * group. This check is only done if N is big enough.
 * Otherwise only the included parameters must be used.
 */
static int
group_check_g_n(gnutls_session_t session, bigint_t g, bigint_t n)
{
	bigint_t q = NULL, two = NULL, w = NULL;
	int ret;

	if (_gnutls_mpi_get_nbits(n) < (session->internals.srp_prime_bits
					? session->internals.srp_prime_bits
					: 2048)) {
		gnutls_assert();
		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
	}

	/* N must be of the form N=2q+1
	 * where q is also a prime.
	 */
	if (_gnutls_prime_check(n) != 0) {
		_gnutls_mpi_log("no prime N: ", n);
		gnutls_assert();
		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
	}

	ret = _gnutls_mpi_init_multi(&two, &q, &w, NULL);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* q = n-1 
	 */
	ret = _gnutls_mpi_sub_ui(q, n, 1);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	/* q = q/2, remember that q is divisible by 2 (prime - 1)
	 */
	ret = _gnutls_mpi_set_ui(two, 2);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls_mpi_div(q, q, two);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_prime_check(q) != 0) {
		/* N was not on the form N=2q+1, where q = prime
		 */
		_gnutls_mpi_log("no prime Q: ", q);
		gnutls_assert();
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
		goto error;
	}

	/* We also check whether g is a generator,
	 */

	/* check if g < q < N
	 */
	if (_gnutls_mpi_cmp(g, q) >= 0) {
		gnutls_assert();
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
		goto error;
	}

	/* check if g^q mod N == N-1
	 * w = g^q mod N
	 */
	ret = _gnutls_mpi_powm(w, g, q, n);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	/* w++
	 */
	ret = _gnutls_mpi_add_ui(w, w, 1);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_mpi_cmp(w, n) != 0) {
		gnutls_assert();
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
		goto error;
	}

	ret = 0;

      error:
	_gnutls_mpi_release(&q);
	_gnutls_mpi_release(&two);
	_gnutls_mpi_release(&w);

	return ret;

}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
/* 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;
}