Beispiel #1
0
/**
 * gnutls_dh_params_import_raw - import DH parameters
 * @dh_params: Is a structure that will hold the prime numbers
 * @prime: holds the new prime
 * @generator: holds the new generator
 *
 * This function will replace the pair of prime and generator for use
 * in the Diffie-Hellman key exchange.  The new parameters should be
 * stored in the appropriate gnutls_datum.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
 *   otherwise an error code is returned.
 **/
int
gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params,
                             const gnutls_datum_t * prime,
                             const gnutls_datum_t * generator)
{
    bigint_t tmp_prime, tmp_g;
    size_t siz;

    siz = prime->size;
    if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz))
    {
        gnutls_assert ();
        return GNUTLS_E_MPI_SCAN_FAILED;
    }

    siz = generator->size;
    if (_gnutls_mpi_scan_nz (&tmp_g, generator->data, siz))
    {
        _gnutls_mpi_release (&tmp_prime);
        gnutls_assert ();
        return GNUTLS_E_MPI_SCAN_FAILED;
    }

    /* store the generated values
     */
    dh_params->params[0] = tmp_prime;
    dh_params->params[1] = tmp_g;

    return 0;

}
/**
 * gnutls_x509_privkey_import_ecc_raw:
 * @key: The structure to store the parsed key
 * @curve: holds the curve
 * @x: holds the x
 * @y: holds the y
 * @k: holds the k
 *
 * This function will convert the given elliptic curve parameters to the
 * native #gnutls_x509_privkey_t format.  The output will be stored
 * in @key.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_x509_privkey_import_ecc_raw (gnutls_x509_privkey_t key,
                                    gnutls_ecc_curve_t curve,
                                    const gnutls_datum_t * x,
                                    const gnutls_datum_t * y,
                                    const gnutls_datum_t * k)
{
  int ret;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  key->params.flags = curve;

  ret = _gnutls_ecc_curve_fill_params(curve, &key->params);
  if (ret < 0)
    return gnutls_assert_val(ret);

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_X], x->data, x->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_Y], y->data, y->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_K], k->data, k->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  key->pk_algorithm = GNUTLS_PK_EC;

  return 0;

cleanup:
  gnutls_pk_params_release(&key->params);
  return ret;

}
static int read_rs(bigint_t *r, bigint_t *s, uint8_t *data, size_t data_size)
{
unsigned int dhalf = data_size/2;

  if (_gnutls_mpi_scan_nz (r, data, dhalf) != 0)
    return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);

  if (_gnutls_mpi_scan_nz (s, &data[dhalf], dhalf) != 0)
    {
      _gnutls_mpi_release(r);
      return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
    }

  return 0;
}
Beispiel #4
0
/**
  * gnutls_srp_verifier - Used to calculate an SRP verifier
  * @username: is the user's name
  * @password: is the user's password
  * @salt: should be some randomly generated bytes
  * @generator: is the generator of the group
  * @prime: is the group's prime
  * @res: where the verifier will be stored.
  *
  * This function will create an SRP verifier, as specified in RFC2945.
  * The @prime and @generator should be one of the static parameters defined
  * in gnutls/extra.h or may be generated using the GCRYPT functions
  * gcry_prime_generate() and gcry_prime_group_generator().
  * The verifier will be allocated with @malloc and will be stored in @res using 
  * binary format.
  *
  **/
int
gnutls_srp_verifier (const char *username, const char *password,
		     const gnutls_datum_t * salt,
		     const gnutls_datum_t * generator,
		     const gnutls_datum_t * prime, gnutls_datum_t * res)
{
  mpi_t _n, _g;
  int ret;
  size_t digest_size = 20, size;
  opaque digest[20];

  ret = _gnutls_calc_srp_sha (username, password, salt->data,
			      salt->size, &digest_size, digest);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  size = prime->size;
  if (_gnutls_mpi_scan_nz (&_n, prime->data, &size))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  size = generator->size;
  if (_gnutls_mpi_scan_nz (&_g, generator->data, &size))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n, malloc);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  res->size = ret;

  return 0;
}
Beispiel #5
0
/* This calculates the SHA1(A | B)
 * A and B will be left-padded with zeros to fill n_size.
 */
mpi_t
_gnutls_calc_srp_u (mpi_t A, mpi_t B, mpi_t n)
{
  size_t b_size, a_size;
  opaque *holder, hd[MAX_HASH_SIZE];
  size_t holder_size, hash_size, n_size;
  GNUTLS_HASH_HANDLE td;
  int ret;
  mpi_t res;

  /* get the size of n in bytes */
  _gnutls_mpi_print (NULL, &n_size, n);

  _gnutls_mpi_print (NULL, &a_size, A);
  _gnutls_mpi_print (NULL, &b_size, B);

  if (a_size > n_size || b_size > n_size)
    {
      gnutls_assert ();
      return NULL;		/* internal error */
    }

  holder_size = n_size + n_size;

  holder = gnutls_calloc (1, holder_size);
  if (holder == NULL)
    return NULL;

  _gnutls_mpi_print (&holder[n_size - a_size], &a_size, A);
  _gnutls_mpi_print (&holder[n_size + n_size - b_size], &b_size, B);

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      gnutls_free (holder);
      gnutls_assert ();
      return NULL;
    }
  _gnutls_hash (td, holder, holder_size);
  _gnutls_hash_deinit (td, hd);

  /* convert the bytes of hd to integer
   */
  hash_size = 20;		/* SHA */
  ret = _gnutls_mpi_scan_nz (&res, hd, &hash_size);
  gnutls_free (holder);

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

  return res;
}
Beispiel #6
0
int
_gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result,
                bigint_t g, bigint_t prime, gnutls_alloc_function galloc_func)
{
  bigint_t x, e;
  size_t result_size;
  int ret;

  if (_gnutls_mpi_scan_nz (&x, text, textsize))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  e = _gnutls_mpi_alloc_like (prime);
  if (e == NULL)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&x);
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* e = g^x mod prime (n) */
  _gnutls_mpi_powm (e, g, x, prime);
  _gnutls_mpi_release (&x);

  ret = _gnutls_mpi_print (e, NULL, &result_size);
  if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
    {
      *result = galloc_func (result_size);
      if ((*result) == NULL)
        return GNUTLS_E_MEMORY_ERROR;

      _gnutls_mpi_print (e, *result, &result_size);
      ret = result_size;
    }
  else
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_mpi_release (&e);

  return ret;

}
Beispiel #7
0
static int
_wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
                         gnutls_datum_t * ciphertext,
                         const gnutls_datum_t * plaintext,
                         const gnutls_pk_params_st * pk_params)
{
  int ret;

  switch (algo)
    {
    case GNUTLS_PK_RSA:
      {
        bigint_t p;

        if (_gnutls_mpi_scan_nz (&p, plaintext->data, plaintext->size) != 0)
          {
            gnutls_assert ();
            return GNUTLS_E_MPI_SCAN_FAILED;
          }

        mpz_powm (p, p, TOMPZ (pk_params->params[1]) /*e */ ,
                  TOMPZ (pk_params->params[0] /*m */ ));

        ret = _gnutls_mpi_dprint_size (p, ciphertext, plaintext->size);
        _gnutls_mpi_release (&p);

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

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
Beispiel #8
0
/* params is p, q, g, y in that order
 */
int
_gnutls_dsa_verify (const gnutls_datum_t * vdata,
		    const gnutls_datum_t * sig_value, mpi_t * params,
		    int params_len)
{

  mpi_t mdata;
  int ret;
  size_t k;
  mpi_t rs[2];

  if (vdata->size != 20)
    {				/* sha-1 only */
      gnutls_assert ();
      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
    }

  if (decode_ber_rs (sig_value, &rs[0], &rs[1]) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  k = vdata->size;
  if (_gnutls_mpi_scan_nz (&mdata, vdata->data, &k) != 0)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&rs[0]);
      _gnutls_mpi_release (&rs[1]);
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* decrypt signature */
  ret = _gnutls_pk_verify (GCRY_PK_DSA, mdata, rs, params, params_len);
  _gnutls_mpi_release (&mdata);
  _gnutls_mpi_release (&rs[0]);
  _gnutls_mpi_release (&rs[1]);

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

  return 0;			/* ok */
}
Beispiel #9
0
/* Do DSA signature calculation. params is p, q, g, y, x in that order.
 */
int
_gnutls_dsa_sign (gnutls_datum_t * signature,
		  const gnutls_datum_t * hash, mpi_t * params,
		  unsigned params_len)
{
  mpi_t rs[2], mdata;
  int ret;
  size_t k;

  k = hash->size;
  if (k != 20)
    {				/* SHA only */
      gnutls_assert ();
      return GNUTLS_E_PK_SIGN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&mdata, hash->data, &k) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  ret = _gnutls_pk_sign (GCRY_PK_DSA, rs, mdata, params, params_len);
  /* rs[0], rs[1] now hold r,s */
  _gnutls_mpi_release (&mdata);

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

  ret = encode_ber_rs (signature, rs[0], rs[1]);

  /* free r,s */
  _gnutls_mpi_release (&rs[0]);
  _gnutls_mpi_release (&rs[1]);

  if (ret != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  return 0;
}
Beispiel #10
0
int
_gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result,
		mpi_t g, mpi_t prime, gnutls_alloc_function galloc_func)
{
  mpi_t x, e;
  size_t result_size;

  if (_gnutls_mpi_scan_nz (&x, text, &textsize))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  e = _gnutls_mpi_alloc_like (prime);
  if (e == NULL)
    {
      gnutls_assert ();
      _gnutls_mpi_release (&x);
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* e = g^x mod prime (n) */
  _gnutls_mpi_powm (e, g, x, prime);
  _gnutls_mpi_release (&x);

  _gnutls_mpi_print (NULL, &result_size, e);
  if (result != NULL)
    {
      *result = galloc_func (result_size);
      if ((*result) == NULL)
	return GNUTLS_E_MEMORY_ERROR;

      _gnutls_mpi_print (*result, &result_size, e);
    }

  _gnutls_mpi_release (&e);

  return result_size;

}
Beispiel #11
0
/* receive the key exchange message ( n, g, s, B) 
 */
int
_gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  uint8_t n_s;
  uint16_t n_g, n_n, n_b;
  size_t _n_s, _n_g, _n_n, _n_b;
  const uint8_t *data_n;
  const uint8_t *data_g;
  const uint8_t *data_s;
  const uint8_t *data_b;
  int i, ret;
  opaque hd[SRP_MAX_HASH_SIZE];
  char *username, *password;
  ssize_t data_size = _data_size;
  gnutls_srp_client_credentials_t cred;

  cred = (gnutls_srp_client_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);

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

  if (session->internals.srp_username == NULL)
    {
      username = cred->username;
      password = cred->password;
    }
  else
    {
      username = session->internals.srp_username;
      password = session->internals.srp_password;
    }

  if (username == NULL || password == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  i = 0;

  /* Read N 
   */
  DECR_LEN (data_size, 2);
  n_n = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_n);
  data_n = &data[i];
  i += n_n;

  /* Read G 
   */
  DECR_LEN (data_size, 2);
  n_g = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_g);
  data_g = &data[i];
  i += n_g;

  /* Read salt 
   */
  DECR_LEN (data_size, 1);
  n_s = data[i];
  i += 1;

  DECR_LEN (data_size, n_s);
  data_s = &data[i];
  i += n_s;

  /* Read B 
   */
  DECR_LEN (data_size, 2);
  n_b = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_b);
  data_b = &data[i];
  i += n_b;

  _n_s = n_s;
  _n_g = n_g;
  _n_n = n_n;
  _n_b = n_b;

  if (_gnutls_mpi_scan_nz (&N, data_n, &_n_n) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }


  /* Check if the g and n are from the SRP
   * draft. Otherwise check if N is a prime and G
   * a generator.
   */
  if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
    {
      _gnutls_x509_log ("Checking the SRP group parameters.\n");
      if ((ret = group_check_g_n (G, N)) < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
    }

  /* Checks if b % n == 0
   */
  if ((ret = check_b_mod_n (B, N)) < 0)
    {
      gnutls_assert ();
      return ret;
    }


  /* generate x = SHA(s | SHA(U | ":" | p))
   * (or the equivalent using bcrypt)
   */
  if ((ret =
       _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s,
			   &_n_g, hd)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }


  return i;			/* return the processed data
				 * needed in auth_srp_rsa.
				 */
}
Beispiel #12
0
/**
  * gnutls_x509_privkey_import_dsa_raw - This function will import a raw DSA key
  * @key: The structure to store the parsed key
  * @p: holds the p
  * @q: holds the q
  * @g: holds the g
  * @y: holds the y
  * @x: holds the x
  *
  * This function will convert the given DSA raw parameters
  * to the native gnutls_x509_privkey_t format. The output will be stored in @key.
  * 
  **/
int
gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t key,
				    const gnutls_datum_t * p,
				    const gnutls_datum_t * q,
				    const gnutls_datum_t * g,
				    const gnutls_datum_t * y,
				    const gnutls_datum_t * x)
{
  int i = 0, ret;
  size_t siz = 0;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  siz = p->size;
  if (_gnutls_mpi_scan_nz (&key->params[0], p->data, &siz))
    {
      gnutls_assert ();
      FREE_DSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = q->size;
  if (_gnutls_mpi_scan_nz (&key->params[1], q->data, &siz))
    {
      gnutls_assert ();
      FREE_DSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = g->size;
  if (_gnutls_mpi_scan_nz (&key->params[2], g->data, &siz))
    {
      gnutls_assert ();
      FREE_DSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = y->size;
  if (_gnutls_mpi_scan_nz (&key->params[3], y->data, &siz))
    {
      gnutls_assert ();
      FREE_DSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = x->size;
  if (_gnutls_mpi_scan_nz (&key->params[4], x->data, &siz))
    {
      gnutls_assert ();
      FREE_DSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (!key->crippled)
    {
      ret = _encode_dsa (&key->key, key->params);
      if (ret < 0)
	{
	  gnutls_assert ();
	  FREE_DSA_PRIVATE_PARAMS;
	  return ret;
	}
    }

  key->params_size = DSA_PRIVATE_PARAMS;
  key->pk_algorithm = GNUTLS_PK_DSA;

  return 0;

}
Beispiel #13
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;
}
Beispiel #14
0
/**
 * gnutls_x509_privkey_import_rsa_raw2:
 * @key: The structure to store the parsed key
 * @m: holds the modulus
 * @e: holds the public exponent
 * @d: holds the private exponent
 * @p: holds the first prime (p)
 * @q: holds the second prime (q)
 * @u: holds the coefficient
 *
 * This function will convert the given RSA raw parameters to the
 * native #gnutls_x509_privkey_t format.  The output will be stored in
 * @key.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_rsa_raw2 (gnutls_x509_privkey_t key,
                                     const gnutls_datum_t * m,
                                     const gnutls_datum_t * e,
                                     const gnutls_datum_t * d,
                                     const gnutls_datum_t * p,
                                     const gnutls_datum_t * q,
                                     const gnutls_datum_t * u,
                                     const gnutls_datum_t * e1,
                                     const gnutls_datum_t * e2)
{
  int i = 0, ret;
  size_t siz = 0;
  gnutls_pk_params_st pk_params;

  memset (&pk_params, 0, sizeof (pk_params));

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  key->params_size = 0;

  siz = m->size;
  if (_gnutls_mpi_scan_nz (&key->params[0], m->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  siz = e->size;
  if (_gnutls_mpi_scan_nz (&key->params[1], e->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  siz = d->size;
  if (_gnutls_mpi_scan_nz (&key->params[2], d->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  siz = p->size;
  if (_gnutls_mpi_scan_nz (&key->params[3], p->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  siz = q->size;
  if (_gnutls_mpi_scan_nz (&key->params[4], q->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  siz = u->size;
  if (_gnutls_mpi_scan_nz (&key->params[5], u->data, siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  key->params_size++;

  if (e1 && e2)
    {
      siz = e1->size;
      if (_gnutls_mpi_scan_nz (&key->params[6], e1->data, siz))
        {
          gnutls_assert ();
          FREE_RSA_PRIVATE_PARAMS;
          return GNUTLS_E_MPI_SCAN_FAILED;
        }
      key->params_size++;

      siz = e2->size;
      if (_gnutls_mpi_scan_nz (&key->params[7], e2->data, siz))
        {
          gnutls_assert ();
          FREE_RSA_PRIVATE_PARAMS;
          return GNUTLS_E_MPI_SCAN_FAILED;
        }
      key->params_size++;
    }

  for (i = 0; i < key->params_size; i++)
    {
      pk_params.params[i] = key->params[i];
    }

  pk_params.params_nr = key->params_size;

  ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pk_params);
  if (ret < 0)
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return ret;
    }

  for (i = 0; i < pk_params.params_nr; i++)
    {
      key->params[i] = pk_params.params[i];
    }
  key->params_size = pk_params.params_nr;

  if (!key->crippled)
    {
      ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
      if (ret < 0)
        {
          gnutls_assert ();
          FREE_RSA_PRIVATE_PARAMS;
          return ret;
        }
    }

  key->params_size = RSA_PRIVATE_PARAMS;
  key->pk_algorithm = GNUTLS_PK_RSA;

  return 0;

}
Beispiel #15
0
/**
  * gnutls_x509_privkey_import_rsa_raw - This function will import a raw RSA key
  * @key: The structure to store the parsed key
  * @m: holds the modulus
  * @e: holds the public exponent
  * @d: holds the private exponent
  * @p: holds the first prime (p)
  * @q: holds the second prime (q)
  * @u: holds the coefficient
  *
  * This function will convert the given RSA raw parameters
  * to the native gnutls_x509_privkey_t format. The output will be stored in @key.
  * 
  **/
int
gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key,
				    const gnutls_datum_t * m,
				    const gnutls_datum_t * e,
				    const gnutls_datum_t * d,
				    const gnutls_datum_t * p,
				    const gnutls_datum_t * q,
				    const gnutls_datum_t * u)
{
  int i = 0, ret;
  size_t siz = 0;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  siz = m->size;
  if (_gnutls_mpi_scan_nz (&key->params[0], m->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = e->size;
  if (_gnutls_mpi_scan_nz (&key->params[1], e->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = d->size;
  if (_gnutls_mpi_scan_nz (&key->params[2], d->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = p->size;
  if (_gnutls_mpi_scan_nz (&key->params[3], p->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  siz = q->size;
  if (_gnutls_mpi_scan_nz (&key->params[4], q->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

#ifdef CALC_COEFF
  key->params[5] = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (key->params[0]));

  if (key->params[5] == NULL)
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_mpi_invm (key->params[5], key->params[3], key->params[4]);
#else
  siz = u->size;
  if (_gnutls_mpi_scan_nz (&key->params[5], u->data, &siz))
    {
      gnutls_assert ();
      FREE_RSA_PRIVATE_PARAMS;
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
#endif

  if (!key->crippled)
    {
      ret = _encode_rsa (&key->key, key->params);
      if (ret < 0)
	{
	  gnutls_assert ();
	  FREE_RSA_PRIVATE_PARAMS;
	  return ret;
	}
    }

  key->params_size = RSA_PRIVATE_PARAMS;
  key->pk_algorithm = GNUTLS_PK_RSA;

  return 0;

}
Beispiel #16
0
static int
_wrap_gcry_pk_verify (gnutls_pk_algorithm_t algo,
                      const gnutls_datum_t * vdata,
                      const gnutls_datum_t * signature,
                      const gnutls_pk_params_st * pk_params)
{
  gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
  int rc = -1, ret;
  bigint_t hash;
  bigint_t tmp[2] = { NULL, NULL };

  if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_DSA:
      if (pk_params->params_nr >= 4)
        rc = gcry_sexp_build (&s_pkey, NULL,
                              "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3]);
      break;
    case GNUTLS_PK_RSA:
      if (pk_params->params_nr >= 2)
        rc = gcry_sexp_build (&s_pkey, NULL,
                              "(public-key(rsa(n%m)(e%m)))",
                              pk_params->params[0], pk_params->params[1]);
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* put the data into a simple list */
  if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  switch (algo)
    {
    case GNUTLS_PK_DSA:
      ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
      if (ret < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
      rc = gcry_sexp_build (&s_sig, NULL,
                            "(sig-val(dsa(r%m)(s%m)))", tmp[0], tmp[1]);
      _gnutls_mpi_release (&tmp[0]);
      _gnutls_mpi_release (&tmp[1]);
      break;

    case GNUTLS_PK_RSA:
      ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
      if (ret < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
      rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", tmp[0]);
      _gnutls_mpi_release (&tmp[0]);
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  rc = gcry_pk_verify (s_sig, s_hash, s_pkey);

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
      goto cleanup;
    }

  ret = 0;

cleanup:
  _gnutls_mpi_release (&hash);
  if (s_sig)
    gcry_sexp_release (s_sig);
  if (s_hash)
    gcry_sexp_release (s_hash);
  if (s_pkey)
    gcry_sexp_release (s_pkey);

  return ret;
}
Beispiel #17
0
static int
_wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
                        const gnutls_datum_t * vdata,
                        const gnutls_datum_t * signature,
                        const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash_len;
  bigint_t tmp[2] = { NULL, NULL };

  switch (algo)
    {
    case GNUTLS_PK_EC: /* ECDSA */
      {
        ecc_key pub;
        struct dsa_signature sig;
        int stat;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        _ecc_params_to_pubkey(pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub);
        if (ret != 0 || stat != 1)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        _ecc_params_clear( &pub);
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_signature sig;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        break;
      }
    case GNUTLS_PK_RSA:
      {
        bigint_t hash;

        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
          {
            gnutls_assert ();
            return GNUTLS_E_MPI_SCAN_FAILED;
          }

        ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        ret = _int_rsa_verify (pk_params, hash, tmp[0]);
        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&hash);
        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

cleanup:

  return ret;
}
Beispiel #18
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;
}
/**
 * gnutls_x509_privkey_import_dsa_raw:
 * @key: The structure to store the parsed key
 * @p: holds the p
 * @q: holds the q
 * @g: holds the g
 * @y: holds the y
 * @x: holds the x
 *
 * This function will convert the given DSA raw parameters to the
 * native #gnutls_x509_privkey_t format.  The output will be stored
 * in @key.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t key,
                                    const gnutls_datum_t * p,
                                    const gnutls_datum_t * q,
                                    const gnutls_datum_t * g,
                                    const gnutls_datum_t * y,
                                    const gnutls_datum_t * x)
{
  int ret;
  size_t siz = 0;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  siz = p->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }

  siz = q->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }

  siz = g->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }

  siz = y->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }

  siz = x->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[4], x->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }

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

  key->params.params_nr = DSA_PRIVATE_PARAMS;
  key->pk_algorithm = GNUTLS_PK_DSA;

  return 0;

cleanup:
  gnutls_pk_params_release(&key->params);
  return ret;

}
Beispiel #20
0
Datei: pk.c Projekt: intgr/gnutls
static int
_wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
                        const gnutls_datum_t * vdata,
                        const gnutls_datum_t * signature,
                        const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash_len;
  bigint_t tmp[2] = { NULL, NULL };

  switch (algo)
    {
    case GNUTLS_PK_EC: /* ECDSA */
      {
        ecc_key pub;
        struct dsa_signature sig;
        int stat;
        int curve_id = pk_params->flags;

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

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        _ecc_params_to_pubkey(pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, curve_id);
        if (ret != 0 || stat != 1)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        _ecc_params_clear( &pub);
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_signature sig;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_public_key pub;
        
        _rsa_params_to_pubkey (pk_params, &pub);

        ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0]));
        if (ret == 0) 
          ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
        else ret = 0;
        
        _gnutls_mpi_release (&tmp[0]);
        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

cleanup:

  return ret;
}
Beispiel #21
0
/* just read A and put it to session */
int
_gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  size_t _n_A;
  ssize_t data_size = _data_size;
  int ret;

  DECR_LEN (data_size, 2);
  _n_A = _gnutls_read_uint16 (&data[0]);

  DECR_LEN (data_size, _n_A);
  if (_gnutls_mpi_scan_nz (&A, &data[2], &_n_A) || A == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  _gnutls_dump_mpi ("SRP A: ", A);
  _gnutls_dump_mpi ("SRP B: ", B);

  /* Checks if A % n == 0.
   */
  if ((ret = check_a_mod_n (A, N)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* Start the SRP calculations.
   * - Calculate u 
   */
  session->key->u = _gnutls_calc_srp_u (A, B, N);
  if (session->key->u == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_dump_mpi ("SRP U: ", session->key->u);

  /* S = (A * v^u) ^ b % N 
   */
  S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N);
  if (S == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_dump_mpi ("SRP S: ", S);

  _gnutls_mpi_release (&A);
  _gnutls_mpi_release (&_b);
  _gnutls_mpi_release (&V);
  _gnutls_mpi_release (&session->key->u);
  _gnutls_mpi_release (&B);

  ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
  _gnutls_mpi_release (&S);

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

  return 0;
}
Beispiel #22
0
static int
_wrap_gcry_pk_decrypt (gnutls_pk_algorithm_t algo,
                       gnutls_datum_t * plaintext,
                       const gnutls_datum_t * ciphertext,
                       const gnutls_pk_params_st * pk_params)
{
  gcry_sexp_t s_plain = NULL, s_data = NULL, s_pkey = NULL;
  int rc = -1;
  int ret;
  bigint_t data, res;

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

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_RSA:
      if (pk_params->params_nr >= 6)
        rc = gcry_sexp_build (&s_pkey, NULL,
                              "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3],
                              pk_params->params[4], pk_params->params[5]);
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* put the data into a simple list */
  if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data))
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* pass it to libgcrypt */
  rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey);
  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_PK_DECRYPTION_FAILED;
      goto cleanup;
    }

  res = gcry_sexp_nth_mpi (s_plain, 0, GCRYMPI_FMT_USG);
  if (res == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = _gnutls_mpi_dprint_size (res, plaintext, ciphertext->size);
  _gnutls_mpi_release (&res);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = 0;

cleanup:
  _gnutls_mpi_release (&data);
  if (s_plain)
    gcry_sexp_release (s_plain);
  if (s_data)
    gcry_sexp_release (s_data);
  if (s_pkey)
    gcry_sexp_release (s_pkey);

  return ret;

}
Beispiel #23
0
int
_gnutls_proc_dh_common_client_kx (gnutls_session_t session,
                                  uint8_t * data, size_t _data_size,
                                  bigint_t g, bigint_t p,
                                  gnutls_datum_t* psk_key)
{
  uint16_t n_Y;
  size_t _n_Y;
  int ret;
  ssize_t data_size = _data_size;


  DECR_LEN (data_size, 2);
  n_Y = _gnutls_read_uint16 (&data[0]);
  _n_Y = n_Y;

  DECR_LEN (data_size, n_Y);
  if (_gnutls_mpi_scan_nz (&session->key.client_Y, &data[2], _n_Y))
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  _gnutls_dh_set_peer_public (session, session->key.client_Y);

  ret =
    gnutls_calc_dh_key (&session->key.KEY, session->key.client_Y, session->key.dh_secret, p);
  if (ret < 0)
    return gnutls_assert_val(ret);

  _gnutls_mpi_release (&session->key.client_Y);
  _gnutls_mpi_release (&session->key.dh_secret);


  if (psk_key == NULL)
    {
      ret = _gnutls_mpi_dprint (session->key.KEY, &session->key.key);
    }
  else                          /* In DHE_PSK the key is set differently */
    {
      gnutls_datum_t tmp_dh_key;
      ret = _gnutls_mpi_dprint (session->key.KEY, &tmp_dh_key);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
      _gnutls_free_datum (&tmp_dh_key);

    }

  _gnutls_mpi_release (&session->key.KEY);

  if (ret < 0)
    {
      return ret;
    }

  return 0;
}
Beispiel #24
0
/* Returns the bytes parsed */
int
_gnutls_proc_dh_common_server_kx (gnutls_session_t session,
                                  uint8_t * data, size_t _data_size)
{
  uint16_t n_Y, n_g, n_p;
  size_t _n_Y, _n_g, _n_p;
  uint8_t *data_p;
  uint8_t *data_g;
  uint8_t *data_Y;
  int i, bits, ret;
  ssize_t data_size = _data_size;

  i = 0;

  DECR_LEN (data_size, 2);
  n_p = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_p);
  data_p = &data[i];
  i += n_p;

  DECR_LEN (data_size, 2);
  n_g = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_g);
  data_g = &data[i];
  i += n_g;

  DECR_LEN (data_size, 2);
  n_Y = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_Y);
  data_Y = &data[i];

  _n_Y = n_Y;
  _n_g = n_g;
  _n_p = n_p;

  if (_gnutls_mpi_scan_nz (&session->key.client_Y, data_Y, _n_Y) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&session->key.client_g, data_g, _n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }
  if (_gnutls_mpi_scan_nz (&session->key.client_p, data_p, _n_p) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  bits = _gnutls_dh_get_allowed_prime_bits (session);
  if (bits < 0)
    {
      gnutls_assert ();
      return bits;
    }

  if (_gnutls_mpi_get_nbits (session->key.client_p) < (size_t) bits)
    {
      /* the prime used by the peer is not acceptable
       */
      gnutls_assert ();
      return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
    }

  _gnutls_dh_set_group (session, session->key.client_g,
                        session->key.client_p);
  _gnutls_dh_set_peer_public (session, session->key.client_Y);

  ret = n_Y + n_p + n_g + 6;

  return ret;
}
Beispiel #25
0
static int
proc_rsa_export_server_kx (gnutls_session_t session,
                           opaque * data, size_t _data_size)
{
  uint16_t n_m, n_e;
  size_t _n_m, _n_e;
  uint8_t *data_m;
  uint8_t *data_e;
  int i, sigsize;
  gnutls_datum_t vparams, signature;
  int ret;
  ssize_t data_size = _data_size;
  cert_auth_info_t info;
  gnutls_pcert_st peer_cert;

  info = _gnutls_get_auth_info (session);
  if (info == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      /* we need this in order to get peer's certificate */
      return GNUTLS_E_INTERNAL_ERROR;
    }


  i = 0;

  DECR_LEN (data_size, 2);
  n_m = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_m);
  data_m = &data[i];
  i += n_m;

  DECR_LEN (data_size, 2);
  n_e = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_e);
  data_e = &data[i];
  i += n_e;

  _n_e = n_e;
  _n_m = n_m;

  if (_gnutls_mpi_scan_nz (&session->key->rsa[0], data_m, _n_m) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&session->key->rsa[1], data_e, _n_e) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  _gnutls_rsa_export_set_pubkey (session, session->key->rsa[1],
                                 session->key->rsa[0]);

  /* VERIFY SIGNATURE */

  vparams.size = n_m + n_e + 4;
  vparams.data = data;

  DECR_LEN (data_size, 2);
  sigsize = _gnutls_read_uint16 (&data[vparams.size]);

  DECR_LEN (data_size, sigsize);
  signature.data = &data[vparams.size + 2];
  signature.size = sigsize;

  if ((ret =
       _gnutls_get_auth_info_pcert (&peer_cert,
                                    session->security_parameters.cert_type,
                                    info)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature,
                                   GNUTLS_SIGN_UNKNOWN);

  gnutls_pcert_deinit (&peer_cert);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;
}
Beispiel #26
0
static int
_wrap_gcry_pk_encrypt (gnutls_pk_algorithm_t algo,
                       gnutls_datum_t * ciphertext,
                       const gnutls_datum_t * plaintext,
                       const gnutls_pk_params_st * pk_params)
{
  gcry_sexp_t s_ciph = NULL, s_data = NULL, s_pkey = NULL;
  int rc = -1;
  int ret;
  bigint_t data, res;
  gcry_sexp_t list;

  if (_gnutls_mpi_scan_nz (&data, plaintext->data, plaintext->size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_RSA:
      if (pk_params->params_nr >= 2)
        rc = gcry_sexp_build (&s_pkey, NULL,
                              "(public-key(rsa(n%m)(e%m)))",
                              pk_params->params[0], pk_params->params[1]);
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* put the data into a simple list */
  if (gcry_sexp_build (&s_data, NULL, "%m", data))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  /* pass it to libgcrypt */
  rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_PK_ENCRYPTION_FAILED;
      goto cleanup;
    }

  list = gcry_sexp_find_token (s_ciph, "a", 0);
  if (list == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  res = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
  gcry_sexp_release (list);
  if (res == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = _gnutls_mpi_dprint_size (res, ciphertext, plaintext->size);
  _gnutls_mpi_release (&res);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = 0;

cleanup:
  _gnutls_mpi_release (&data);
  if (s_ciph)
    gcry_sexp_release (s_ciph);
  if (s_data)
    gcry_sexp_release (s_data);
  if (s_pkey)
    gcry_sexp_release (s_pkey);

  return ret;
}
/**
 * gnutls_x509_privkey_import_rsa_raw2:
 * @key: The structure to store the parsed key
 * @m: holds the modulus
 * @e: holds the public exponent
 * @d: holds the private exponent
 * @p: holds the first prime (p)
 * @q: holds the second prime (q)
 * @u: holds the coefficient
 * @e1: holds e1 = d mod (p-1)
 * @e2: holds e2 = d mod (q-1)
 *
 * This function will convert the given RSA raw parameters to the
 * native #gnutls_x509_privkey_t format.  The output will be stored in
 * @key.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_rsa_raw2 (gnutls_x509_privkey_t key,
                                     const gnutls_datum_t * m,
                                     const gnutls_datum_t * e,
                                     const gnutls_datum_t * d,
                                     const gnutls_datum_t * p,
                                     const gnutls_datum_t * q,
                                     const gnutls_datum_t * u,
                                     const gnutls_datum_t * e1,
                                     const gnutls_datum_t * e2)
{
  int ret;
  size_t siz = 0;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  gnutls_pk_params_init(&key->params);

  siz = m->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  siz = e->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  siz = d->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[2], d->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  siz = p->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[3], p->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  siz = q->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[4], q->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  siz = u->size;
  if (_gnutls_mpi_scan_nz (&key->params.params[5], u->data, siz))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  if (e1 && e2)
    {
      siz = e1->size;
      if (_gnutls_mpi_scan_nz (&key->params.params[6], e1->data, siz))
        {
          gnutls_assert ();
          ret = GNUTLS_E_MPI_SCAN_FAILED;
          goto cleanup;
        }
      key->params.params_nr++;

      siz = e2->size;
      if (_gnutls_mpi_scan_nz (&key->params.params[7], e2->data, siz))
        {
          gnutls_assert ();
          ret = GNUTLS_E_MPI_SCAN_FAILED;
          goto cleanup;
        }
      key->params.params_nr++;
    }

  ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &key->params);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

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

  key->params.params_nr = RSA_PRIVATE_PARAMS;
  key->pk_algorithm = GNUTLS_PK_RSA;

  return 0;

cleanup:
  gnutls_pk_params_release(&key->params);
  return ret;

}
Beispiel #28
0
Datei: pk.c Projekt: intgr/gnutls
static int
_wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo,
                         gnutls_datum_t * plaintext,
                         const gnutls_datum_t * ciphertext,
                         const gnutls_pk_params_st * pk_params)
{
  int ret;

  plaintext->data = NULL;

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        struct rsa_public_key pub;
        unsigned length;
        bigint_t c;

        _rsa_params_to_privkey (pk_params, &priv);
        _rsa_params_to_pubkey (pk_params, &pub);

        if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
            goto cleanup;
          }

        length = pub.size;
        plaintext->data = gnutls_malloc(length);
        if (plaintext->data == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto cleanup;
          }
        
        ret = rsa_decrypt_tr(&pub, &priv, NULL, rnd_func, &length, plaintext->data,
                             TOMPZ(c));
        _gnutls_mpi_release (&c);
        plaintext->size = length;

        if (ret == 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
            goto cleanup;
          }

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:
  if (ret < 0)
    gnutls_free(plaintext->data);

  return ret;
}
Beispiel #29
0
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number 
 * Data is allocated by the caller, and should have data_size size.
 */
int
_gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
{
  int ret;
  uint8_t *data_n, *data_s;
  uint8_t *data_g;
  char *username;
  SRP_PWD_ENTRY *pwd_entry;
  srp_server_auth_info_t info;
  ssize_t data_size;
  size_t n_b, tmp_size;
  char buf[64];
  uint8_t *data_b;

  if ((ret =
       _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
			      sizeof (srp_server_auth_info_st), 1)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  username = info->username;

  _gnutls_str_cpy (username, MAX_SRP_USERNAME,
		   session->security_parameters.extensions.srp_username);

  ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);

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

  /* copy from pwd_entry to local variables (actually in session) */
  tmp_size = pwd_entry->g.size;
  if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->n.size;
  if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->v.size;
  if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* Calculate:  B = (k*v + g^b) % N 
   */
  B = _gnutls_calc_srp_B (&_b, G, N, V);
  if (B == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  if (_gnutls_mpi_print (NULL, &n_b, B) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }


  /* Allocate size to hold the N, g, s, B 
   */

  data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
	       pwd_entry->salt.size + 1) + (n_b + 2);

  (*data) = gnutls_malloc (data_size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* copy N (mod n) 
   */
  data_n = *data;
  _gnutls_write_datum16 (data_n, pwd_entry->n);


  /* copy G (generator) to data 
   */
  data_g = &data_n[2 + pwd_entry->n.size];
  _gnutls_write_datum16 (data_g, pwd_entry->g);


  /* copy the salt 
   */
  data_s = &data_g[2 + pwd_entry->g.size];
  _gnutls_write_datum8 (data_s, pwd_entry->salt);


  /* Copy the B value
   */

  data_b = &data_s[1 + pwd_entry->salt.size];
  if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) 
    {
      gnutls_assert();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_write_uint16 (n_b, data_b);

  _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b,
		    _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf)));

  _gnutls_srp_entry_free (pwd_entry);

  return data_size;
}
Beispiel #30
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_gcry_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature,
                    const gnutls_datum_t * vdata,
                    const gnutls_pk_params_st * pk_params)
{
  gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL;
  gcry_sexp_t list = NULL;
  int rc = -1, ret;
  bigint_t hash;
  bigint_t res[2] = { NULL, NULL };

  if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_DSA:
      if (pk_params->params_nr >= 5)
        rc = gcry_sexp_build (&s_key, NULL,
                              "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3],
                              pk_params->params[4]);
      else
        {
          gnutls_assert ();
        }

      break;
    case GNUTLS_PK_RSA:
      if (pk_params->params_nr >= 6)
        rc = gcry_sexp_build (&s_key, NULL,
                              "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3],
                              pk_params->params[4], pk_params->params[5]);
      else
        {
          gnutls_assert ();
        }
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* put the data into a simple list */
  if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }


  /* pass it to libgcrypt */
  rc = gcry_pk_sign (&s_sig, s_hash, s_key);
  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_PK_SIGN_FAILED;
      goto cleanup;
    }

  ret = GNUTLS_E_INTERNAL_ERROR;

  switch (algo)
    {
    case GNUTLS_PK_DSA:
      {
        list = gcry_sexp_find_token (s_sig, "r", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        list = gcry_sexp_find_token (s_sig, "s", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        ret = _gnutls_encode_ber_rs (signature, res[0], res[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
      }
      break;

    case GNUTLS_PK_RSA:
      {
        list = gcry_sexp_find_token (s_sig, "s", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        ret = _gnutls_mpi_dprint (res[0], signature);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
      }
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:
  _gnutls_mpi_release (&hash);
  if (res[0])
    _gnutls_mpi_release (&res[0]);
  if (res[1])
    _gnutls_mpi_release (&res[1]);
  if (s_sig)
    gcry_sexp_release (s_sig);
  if (s_hash)
    gcry_sexp_release (s_hash);
  if (s_key)
    gcry_sexp_release (s_key);

  return ret;
}