Пример #1
0
/* Do PKCS-1 RSA decryption. 
 * params is modulus, public exp., private key
 * Can decrypt block type 1 and type 2 packets.
 */
int
_gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
			   const gnutls_datum_t * ciphertext,
			   mpi_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned k, i;
  int ret;
  mpi_t c, res;
  opaque *edata;
  size_t esize, mod_bits;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  esize = ciphertext->size;

  if (esize != k)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_DECRYPTION_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&c, ciphertext->data, &esize) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* we can use btype to see if the private key is
   * available.
   */
  if (btype == 2)
    ret = _gnutls_pk_decrypt (GCRY_PK_RSA, &res, c, params, params_len);
  else
    {
      ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, c, params, params_len);
    }
  _gnutls_mpi_release (&c);

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

  _gnutls_mpi_print (NULL, &esize, res);
  edata = gnutls_alloca (esize + 1);
  if (edata == NULL)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&res);
      return GNUTLS_E_MEMORY_ERROR;
    }
  _gnutls_mpi_print (&edata[1], &esize, res);

  _gnutls_mpi_release (&res);

  /* EB = 00||BT||PS||00||D
   * (use block type 'btype')
   *
   * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
   * avoid attacks similar to the one described by Bleichenbacher in:
   * "Chosen Ciphertext Attacks against Protocols Based on RSA
   * Encryption Standard PKCS #1".
   */


  edata[0] = 0;
  esize++;

  if (edata[0] != 0 || edata[1] != btype)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  ret = GNUTLS_E_DECRYPTION_FAILED;
  switch (btype)
    {
    case 2:
      for (i = 2; i < esize; i++)
	{
	  if (edata[i] == 0)
	    {
	      ret = 0;
	      break;
	    }
	}
      break;
    case 1:
      for (i = 2; i < esize; i++)
	{
	  if (edata[i] == 0 && i > 2)
	    {
	      ret = 0;
	      break;
	    }
	  if (edata[i] != 0xff)
	    {
	      _gnutls_handshake_log ("PKCS #1 padding error");
	      /* PKCS #1 padding error.  Don't use
		 GNUTLS_E_PKCS1_WRONG_PAD here.  */
	      break;
	    }
	}
      break;
    default:
      gnutls_assert ();
      gnutls_afree (edata);
      break;
    }
  i++;

  if (ret < 0)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  if (_gnutls_sset_datum (plaintext, &edata[i], esize - i) < 0)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_MEMORY_ERROR;
    }

  gnutls_afree (edata);

  return 0;
}
Пример #2
0
/* Do PKCS-1 RSA encryption. 
 * params is modulus, public exp.
 */
int
_gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
			   const gnutls_datum_t * plaintext,
			   mpi_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned int i, pad;
  int ret;
  mpi_t m, res;
  opaque *edata, *ps;
  size_t k, psize;
  size_t mod_bits;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  if (plaintext->size > k - 11)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_ENCRYPTION_FAILED;
    }

  edata = gnutls_alloca (k);
  if (edata == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* EB = 00||BT||PS||00||D 
   * (use block type 'btype')
   */

  edata[0] = 0;
  edata[1] = btype;
  psize = k - 3 - plaintext->size;

  ps = &edata[2];
  switch (btype)
    {
    case 2:
      /* using public key */
      if (params_len < RSA_PUBLIC_PARAMS)
	{
	  gnutls_assert ();
	  gnutls_afree (edata);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      if (gc_pseudo_random (ps, psize) != GC_OK)
	{
	  gnutls_assert ();
	  gnutls_afree (edata);
	  return GNUTLS_E_RANDOM_FAILED;
	}
      for (i = 0; i < psize; i++)
	while (ps[i] == 0)
	  {
	    if (gc_pseudo_random (&ps[i], 1) != GC_OK)
	      {
		gnutls_assert ();
		gnutls_afree (edata);
		return GNUTLS_E_RANDOM_FAILED;
	      }
	  }
      break;
    case 1:
      /* using private key */

      if (params_len < RSA_PRIVATE_PARAMS)
	{
	  gnutls_assert ();
	  gnutls_afree (edata);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      for (i = 0; i < psize; i++)
	ps[i] = 0xff;
      break;
    default:
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ps[psize] = 0;
  memcpy (&ps[psize + 1], plaintext->data, plaintext->size);

  if (_gnutls_mpi_scan_nz (&m, edata, &k) != 0)
    {
      gnutls_assert ();
      gnutls_afree (edata);
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  gnutls_afree (edata);

  if (btype == 2)		/* encrypt */
    ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, m, params, params_len);
  else				/* sign */
    ret = _gnutls_pk_sign (GCRY_PK_RSA, &res, m, params, params_len);

  _gnutls_mpi_release (&m);

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

  _gnutls_mpi_print (NULL, &psize, res);

  if (psize < k)
    {
      /* padding psize */
      pad = k - psize;
      psize = k;
    }
  else if (psize == k)
    {
      pad = 0;
    }
  else
    {				/* psize > k !!! */
      /* This is an impossible situation */
      gnutls_assert ();
      _gnutls_mpi_release (&res);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ciphertext->data = gnutls_malloc (psize);
  if (ciphertext->data == NULL)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&res);
      return GNUTLS_E_MEMORY_ERROR;
    }
  _gnutls_mpi_print (&ciphertext->data[pad], &psize, res);
  for (i = 0; i < pad; i++)
    ciphertext->data[i] = 0;

  ciphertext->size = k;

  _gnutls_mpi_release (&res);

  return 0;
}
Пример #3
0
/* Do PKCS-1 RSA encryption. 
 * params is modulus, public exp.
 */
int
_gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
			   const gnutls_datum_t * plaintext,
			   bigint_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned int i, pad;
  int ret;
  opaque *edata, *ps;
  size_t k, psize;
  size_t mod_bits;
  gnutls_pk_params_st pk_params;
  gnutls_datum to_encrypt, encrypted;

  for (i = 0; i < params_len; i++)
    pk_params.params[i] = params[i];
  pk_params.params_nr = params_len;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  if (plaintext->size > k - 11)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_ENCRYPTION_FAILED;
    }

  edata = gnutls_malloc (k);
  if (edata == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* EB = 00||BT||PS||00||D 
   * (use block type 'btype')
   */

  edata[0] = 0;
  edata[1] = btype;
  psize = k - 3 - plaintext->size;

  ps = &edata[2];
  switch (btype)
    {
    case 2:
      /* using public key */
      if (params_len < RSA_PUBLIC_PARAMS)
	{
	  gnutls_assert ();
	  gnutls_free (edata);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      ret = _gnutls_rnd (GNUTLS_RND_RANDOM, ps, psize);
      if (ret < 0)
	{
	  gnutls_assert ();
	  gnutls_free (edata);
	  return ret;
	}
      for (i = 0; i < psize; i++)
	while (ps[i] == 0)
	  {
	    ret = _gnutls_rnd (GNUTLS_RND_RANDOM, &ps[i], 1);
	    if (ret < 0)
	      {
		gnutls_assert ();
		gnutls_free (edata);
		return ret;
	      }
	  }
      break;
    case 1:
      /* using private key */

      if (params_len < RSA_PRIVATE_PARAMS)
	{
	  gnutls_assert ();
	  gnutls_free (edata);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      for (i = 0; i < psize; i++)
	ps[i] = 0xff;
      break;
    default:
      gnutls_assert ();
      gnutls_free (edata);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ps[psize] = 0;
  memcpy (&ps[psize + 1], plaintext->data, plaintext->size);

  to_encrypt.data = edata;
  to_encrypt.size = k;

  if (btype == 2)		/* encrypt */
    ret =
      _gnutls_pk_encrypt (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params);
  else				/* sign */
    ret =
      _gnutls_pk_sign (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params);

  gnutls_free (edata);

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

  psize = encrypted.size;
  if (psize < k)
    {
      /* padding psize */
      pad = k - psize;
      psize = k;
    }
  else if (psize == k)
    {
      /* pad = 0; 
       * no need to do anything else
       */
      ciphertext->data = encrypted.data;
      ciphertext->size = encrypted.size;
      return 0;
    }
  else
    {				/* psize > k !!! */
      /* This is an impossible situation */
      gnutls_assert ();
      _gnutls_free_datum (&encrypted);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ciphertext->data = gnutls_malloc (psize);
  if (ciphertext->data == NULL)
    {
      gnutls_assert ();
      _gnutls_free_datum (&encrypted);
      return GNUTLS_E_MEMORY_ERROR;
    }

  memcpy (&ciphertext->data[pad], encrypted.data, encrypted.size);
  for (i = 0; i < pad; i++)
    ciphertext->data[i] = 0;

  ciphertext->size = k;

  _gnutls_free_datum (&encrypted);

  return 0;
}
Пример #4
0
/* Do PKCS-1 RSA decryption. 
 * params is modulus, public exp., private key
 * Can decrypt block type 1 and type 2 packets.
 */
int
_gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
			   const gnutls_datum_t * ciphertext,
			   bigint_t * params, unsigned params_len,
			   unsigned btype)
{
  unsigned int k, i;
  int ret;
  size_t esize, mod_bits;
  gnutls_pk_params_st pk_params;

  for (i = 0; i < params_len; i++)
    pk_params.params[i] = params[i];
  pk_params.params_nr = params_len;

  mod_bits = _gnutls_mpi_get_nbits (params[0]);
  k = mod_bits / 8;
  if (mod_bits % 8 != 0)
    k++;

  esize = ciphertext->size;

  if (esize != k)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_DECRYPTION_FAILED;
    }

  /* we can use btype to see if the private key is
   * available.
   */
  if (btype == 2)
    {
      ret =
	_gnutls_pk_decrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
    }
  else
    {
      ret =
	_gnutls_pk_encrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
    }

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

  /* EB = 00||BT||PS||00||D
   * (use block type 'btype')
   *
   * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
   * avoid attacks similar to the one described by Bleichenbacher in:
   * "Chosen Ciphertext Attacks against Protocols Based on RSA
   * Encryption Standard PKCS #1".
   */
  if (plaintext->data[0] != 0 || plaintext->data[1] != btype)
    {
      gnutls_assert ();
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  ret = GNUTLS_E_DECRYPTION_FAILED;
  switch (btype)
    {
    case 2:
      for (i = 2; i < plaintext->size; i++)
	{
	  if (plaintext->data[i] == 0)
	    {
	      ret = 0;
	      break;
	    }
	}
      break;
    case 1:
      for (i = 2; i < plaintext->size; i++)
	{
	  if (plaintext->data[i] == 0 && i > 2)
	    {
	      ret = 0;
	      break;
	    }
	  if (plaintext->data[i] != 0xff)
	    {
	      _gnutls_handshake_log ("PKCS #1 padding error");
	      _gnutls_free_datum (plaintext);
	      /* PKCS #1 padding error.  Don't use
	         GNUTLS_E_PKCS1_WRONG_PAD here.  */
	      break;
	    }
	}
      break;
    default:
      gnutls_assert ();
      _gnutls_free_datum (plaintext);
      break;
    }
  i++;

  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (plaintext);
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  memmove (plaintext->data, &plaintext->data[i], esize - i);
  plaintext->size = esize - i;

  return 0;
}
Пример #5
0
/* return RSA(random) using the peers public key 
 */
int
_gnutls_gen_rsa_client_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	cert_auth_info_t auth = session->key.auth_info;
	gnutls_datum_t sdata;	/* data to send */
	gnutls_pk_params_st params;
	int ret;

	if (auth == NULL) {
		/* this shouldn't have happened. The proc_certificate
		 * function should have detected that.
		 */
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	session->key.key.size = GNUTLS_MASTER_SIZE;
	session->key.key.data = gnutls_malloc(session->key.key.size);

	if (session->key.key.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data,
			  session->key.key.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (session->internals.rsa_pms_version[0] == 0) {
		session->key.key.data[0] =
		    _gnutls_get_adv_version_major(session);
		session->key.key.data[1] =
		    _gnutls_get_adv_version_minor(session);
	} else {		/* use the version provided */
		session->key.key.data[0] =
		    session->internals.rsa_pms_version[0];
		session->key.key.data[1] =
		    session->internals.rsa_pms_version[1];
	}

	/* move RSA parameters to key (session).
	 */
	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
			       &params);

	gnutls_pk_params_release(&params);

	if (ret < 0)
		return gnutls_assert_val(ret);


	if (get_num_version(session) == GNUTLS_SSL3) {
		/* SSL 3.0 */
		_gnutls_buffer_replace_data(data, &sdata);

		return data->length;
	} else {		/* TLS 1 */
		ret =
		    _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
						      sdata.size);

		_gnutls_free_datum(&sdata);
		return ret;
	}

}
Пример #6
0
/* Generate client key exchange message
 *
 *
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *       EncryptedPreMasterSecret;
 *    } exchange_keys;
 * } ClientKeyExchange;
 */
static int
_gnutls_gen_rsa_psk_client_kx(gnutls_session_t session,
			      gnutls_buffer_st * data)
{
	cert_auth_info_t auth = session->key.auth_info;
	gnutls_datum_t sdata;	/* data to send */
	gnutls_pk_params_st params;
	gnutls_psk_client_credentials_t cred;
	gnutls_datum_t username, key;
	int ret, free;
	unsigned init_pos;

	if (auth == NULL) {
		/* this shouldn't have happened. The proc_certificate
		 * function should have detected that.
		 */
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	gnutls_datum_t premaster_secret;
	premaster_secret.size = GNUTLS_MASTER_SIZE;
	premaster_secret.data =
	    gnutls_malloc(premaster_secret.size);

	if (premaster_secret.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	/* Generate random */
	ret = gnutls_rnd(GNUTLS_RND_RANDOM, premaster_secret.data,
			  premaster_secret.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Set version */
	if (session->internals.rsa_pms_version[0] == 0) {
		premaster_secret.data[0] =
		    _gnutls_get_adv_version_major(session);
		premaster_secret.data[1] =
		    _gnutls_get_adv_version_minor(session);
	} else {		/* use the version provided */
		premaster_secret.data[0] =
		    session->internals.rsa_pms_version[0];
		premaster_secret.data[1] =
		    session->internals.rsa_pms_version[1];
	}

	/* move RSA parameters to key (session).
	 */
	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
		gnutls_assert();
		return ret;
	}

	/* Encrypt premaster secret */
	if ((ret =
	     _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &premaster_secret,
				&params)) < 0) {
		gnutls_assert();
		return ret;
	}

	gnutls_pk_params_release(&params);

	cred = (gnutls_psk_client_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);

	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Here we set the PSK key */
	ret = set_rsa_psk_session_key(session, &key, &premaster_secret);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Create message for client key exchange
	 *
	 * struct {
	 *   uint8_t psk_identity<0..2^16-1>;
	 *   EncryptedPreMasterSecret;
	 * }
	 */

	init_pos = data->length;

	/* Write psk_identity and EncryptedPreMasterSecret into data stream
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16,
					      username.data,
					      username.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
					      sdata.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length - init_pos;

      cleanup:
	_gnutls_free_datum(&sdata);
	_gnutls_free_temp_key_datum(&premaster_secret);
	if (free) {
		_gnutls_free_temp_key_datum(&key);
		gnutls_free(username.data);
	}

	return ret;
}
Пример #7
0
static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params)
{
int ret;
gnutls_datum_t sig = {NULL, 0};
const char const_data[20] = "onetwothreefourfive";
gnutls_datum_t ddata, tmp = {NULL,0};
char* gen_data = NULL;

	if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) {
		unsigned hash_len;

		_gnutls_dsa_q_to_hash(algo, params, &hash_len);
		gen_data = gnutls_malloc(hash_len);
		gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len);

		ddata.data = (void*)gen_data;
		ddata.size = hash_len;
	} else {
		ddata.data = (void*)const_data;
		ddata.size = sizeof(const_data);
	}

	switch (algo) {
	case GNUTLS_PK_RSA:
		ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		if (ddata.size == sig.size && memcmp(ddata.data, sig.data, sig.size) == 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		ret = _gnutls_pk_decrypt(algo, &tmp, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		if (tmp.size != ddata.size || memcmp(tmp.data, ddata.data, tmp.size) != 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		free(sig.data);
		sig.data = NULL;

		/* Here we don't know the purpose of the key. Check both
		 * signing and encryption.
		 */
	case GNUTLS_PK_EC: /* we only do keys for ECDSA */
	case GNUTLS_PK_DSA:
		ret = _gnutls_pk_sign(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		ret = _gnutls_pk_verify(algo, &ddata, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}
		break;

	default:
		ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
		goto cleanup;
	}

	ret = 0;
cleanup:
	if (ret == GNUTLS_E_PK_GENERATION_ERROR) {
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
	}
	gnutls_free(gen_data);
	gnutls_free(sig.data);
	gnutls_free(tmp.data);
	return ret;
}