Exemple #1
0
/**
  * gnutls_hex_encode - convert raw data to hex encoded
  * @data: contain the raw data
  * @result: the place where hex data will be copied
  * @result_size: holds the size of the result
  *
  * This function will convert the given data to printable data, using
  * the hex encoding, as used in the PSK password files.
  *
  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
  * long enough, or 0 on success.
  **/
int
gnutls_hex_encode (const gnutls_datum_t * data, char *result,
		   size_t * result_size)
{
size_t res = data->size + data->size + 1;

  if (*result_size < res)
    {
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  _gnutls_bin2hex (data->data, data->size, result, *result_size);
  *result_size = res;
  
  return 0;
}
Exemple #2
0
/* Converts a data string to an LDAP rfc2253 hex string
 * something like '#01020304'
 */
int
_gnutls_x509_data2hex (const opaque * data, size_t data_size,
		       opaque * out, size_t * sizeof_out)
{
  char *res;
  char escaped[MAX_STRING_LEN];

  if (2 * data_size + 1 > MAX_STRING_LEN)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  res = _gnutls_bin2hex (data, data_size, escaped, sizeof (escaped));

  if (res)
    {
      unsigned int size = strlen (res) + 1;
      if (size + 1 > *sizeof_out)
	{
	  *sizeof_out = size;
	  return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}
      *sizeof_out = size;	/* -1 for the null +1 for the '#' */

      if (out)
	{
	  strcpy (out, "#");
	  strcat (out, res);
	}

      return 0;
    }
  else
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  return 0;
}
Exemple #3
0
/* Converts a data string to an LDAP rfc2253 hex string
 * something like '#01020304'
 */
static int
data2hex(const void *data, size_t data_size,
	 void *_out, size_t * sizeof_out)
{
	char *res;
	char escaped[MAX_STRING_LEN];
	unsigned int size, res_size;
	char *out = _out;

	if (2 * data_size + 1 > MAX_STRING_LEN) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	res =
	    _gnutls_bin2hex(data, data_size, escaped, sizeof(escaped),
			    NULL);
	if (!res) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	res_size = strlen(res);
	size = res_size + 1;	/* +1 for the '#' */
	if (size + 1 > *sizeof_out) {
		*sizeof_out = size + 1;
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}
	*sizeof_out = size;	/* -1 for the null +1 for the '#' */

	if (out) {
		out[0] = '#';
		memcpy(&out[1], res, res_size);
		out[size] = 0;
	}

	return 0;
}
static 
int store_commitment(const char* db_name, const char* host,
                 const char* service, time_t expiration, 
                 gnutls_digest_algorithm_t hash_algo,
                 const gnutls_datum_t* hash)
{
FILE* fd;
char buffer[MAX_HASH_SIZE*2+1];

  fd = fopen(db_name, "ab+");
  if (fd == NULL)
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);

  if (service == NULL) service = "*";
  if (host == NULL) host = "*";

  fprintf(fd, "|c0|%s|%s|%lu|%u|%s\n", host, service, (unsigned long)expiration, 
          (unsigned)hash_algo, _gnutls_bin2hex(hash->data, hash->size, buffer, sizeof(buffer), NULL));
  
  fclose(fd);
  
  return 0;
}
static int
generate_normal_master (gnutls_session_t session, int keep_premaster)
{
  int ret = 0;
  char buf[512];

  _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
                    _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
                                     sizeof (buf), NULL));
  _gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32,
                    _gnutls_bin2hex (session->
                                     security_parameters.client_random, 32,
                                     buf, sizeof (buf), NULL));
  _gnutls_hard_log ("INT: SERVER RANDOM[%d]: %s\n", 32,
                    _gnutls_bin2hex (session->
                                     security_parameters.server_random, 32,
                                     buf, sizeof (buf), NULL));

  if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
    {
      opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];

      memcpy (rnd, session->security_parameters.client_random,
              GNUTLS_RANDOM_SIZE);
      memcpy (&rnd[GNUTLS_RANDOM_SIZE],
              session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

      ret =
        _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
                                      rnd, 2 * GNUTLS_RANDOM_SIZE,
                                      GNUTLS_MASTER_SIZE,
                                      session->
                                      security_parameters.master_secret);

    }
  else
    {
      opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];

      memcpy (rnd, session->security_parameters.client_random,
              GNUTLS_RANDOM_SIZE);
      memcpy (&rnd[GNUTLS_RANDOM_SIZE],
              session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

      ret =
        _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
                     MASTER_SECRET, MASTER_SECRET_SIZE,
                     rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
                     session->security_parameters.master_secret);
    }

  if (!keep_premaster)
    _gnutls_free_datum (&PREMASTER);

  if (ret < 0)
    return ret;

  _gnutls_hard_log ("INT: MASTER SECRET: %s\n",
                    _gnutls_bin2hex (session->
                                     security_parameters.master_secret,
                                     GNUTLS_MASTER_SIZE, buf, sizeof (buf),
                                     NULL));

  return ret;
}
static int parse_commitment_line(char* line, 
                      const char* host, size_t host_len,
                      const char* service, size_t service_len,
                      time_t now,
                      const gnutls_datum_t *skey)
{
char* p, *kp;
char* savep = NULL;
size_t kp_len, phash_size;
time_t expiration;
int ret;
gnutls_digest_algorithm_t hash_algo;
uint8_t phash[MAX_HASH_SIZE];
uint8_t hphash[MAX_HASH_SIZE*2+1];

  /* read host */
  p = strtok_r(line, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  if (p[0] != '*' && strcmp(p, host) != 0)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read service */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  if (p[0] != '*' && strcmp(p, service) != 0)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read expiration */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  expiration = (time_t)atol(p);
  if (expiration > 0 && now > expiration)
    return gnutls_assert_val(GNUTLS_E_EXPIRED);

  /* read hash algorithm */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  hash_algo = (time_t)atol(p);
  if (_gnutls_digest_get_name(hash_algo) == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read hash */
  kp = strtok_r(NULL, "|", &savep);
  if (kp == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
  
  p = strpbrk(kp, "\n \r\t|");
  if (p != NULL) *p = 0;

  /* hash and hex encode */
  ret = _gnutls_hash_fast (hash_algo, skey->data, skey->size, phash);
  if (ret < 0)
    return gnutls_assert_val(ret);
    
  phash_size = _gnutls_hash_get_algo_len(hash_algo);

  p = _gnutls_bin2hex (phash, phash_size,(void*) hphash,
                         sizeof(hphash), NULL);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

  kp_len = strlen(kp);
  if (kp_len != phash_size*2)
    return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

  if (memcmp(kp, hphash, kp_len) != 0)
    return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

  /* key found and matches */
  return 0;
}
Exemple #7
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
static int
_gnutls_set_keys (gnutls_session_t session, record_parameters_st * params,
                  int hash_size, int IV_size, int key_size, int export_flag)
{
  /* FIXME: This function is too long
   */
  opaque rnd[2 * GNUTLS_RANDOM_SIZE];
  opaque rrnd[2 * GNUTLS_RANDOM_SIZE];
  int pos, ret;
  int block_size;
  char buf[65];
  /* avoid using malloc */
  opaque key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
                   2 * MAX_CIPHER_BLOCK_SIZE];
  record_state_st *client_write, *server_write;

  client_write =
    session->security_parameters.entity ==
    GNUTLS_CLIENT ? &params->write : &params->read;
  server_write =
    session->security_parameters.entity ==
    GNUTLS_SERVER ? &params->write : &params->read;

  block_size = 2 * hash_size + 2 * key_size;
  if (export_flag == 0)
    block_size += 2 * IV_size;

  memcpy (rnd, session->security_parameters.server_random,
          GNUTLS_RANDOM_SIZE);
  memcpy (&rnd[GNUTLS_RANDOM_SIZE],
          session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);

  memcpy (rrnd, session->security_parameters.client_random,
          GNUTLS_RANDOM_SIZE);
  memcpy (&rrnd[GNUTLS_RANDOM_SIZE],
          session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

  if (session->security_parameters.version == GNUTLS_SSL3)
    {                           /* SSL 3 */
      ret =
        _gnutls_ssl3_generate_random
        (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd,
         2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
    }
  else
    {                           /* TLS 1.0 */
      ret =
        _gnutls_PRF (session, session->security_parameters.master_secret,
                     GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
                     rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
    }

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

  _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
                    _gnutls_bin2hex (key_block, block_size, buf,
                                     sizeof (buf), NULL));

  pos = 0;
  if (hash_size > 0)
    {

      if (_gnutls_sset_datum
          (&client_write->mac_secret, &key_block[pos], hash_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += hash_size;

      if (_gnutls_sset_datum
          (&server_write->mac_secret, &key_block[pos], hash_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += hash_size;
    }

  if (key_size > 0)
    {
      opaque key1[EXPORT_FINAL_KEY_SIZE];
      opaque key2[EXPORT_FINAL_KEY_SIZE];
      opaque *client_write_key, *server_write_key;
      int client_write_key_size, server_write_key_size;

      if (export_flag == 0)
        {
          client_write_key = &key_block[pos];
          client_write_key_size = key_size;

          pos += key_size;

          server_write_key = &key_block[pos];
          server_write_key_size = key_size;

          pos += key_size;

        }
      else
        {                       /* export */
          client_write_key = key1;
          server_write_key = key2;

          /* generate the final keys */

          if (session->security_parameters.version == GNUTLS_SSL3)
            {                   /* SSL 3 */
              ret =
                _gnutls_ssl3_hash_md5 (&key_block[pos],
                                       key_size, rrnd,
                                       2 * GNUTLS_RANDOM_SIZE,
                                       EXPORT_FINAL_KEY_SIZE,
                                       client_write_key);

            }
          else
            {                   /* TLS 1.0 */
              ret =
                _gnutls_PRF (session, &key_block[pos], key_size,
                             cliwrite, cliwrite_length,
                             rrnd,
                             2 * GNUTLS_RANDOM_SIZE,
                             EXPORT_FINAL_KEY_SIZE, client_write_key);
            }

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

          client_write_key_size = EXPORT_FINAL_KEY_SIZE;
          pos += key_size;

          if (session->security_parameters.version == GNUTLS_SSL3)
            {                   /* SSL 3 */
              ret =
                _gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
                                       rnd, 2 * GNUTLS_RANDOM_SIZE,
                                       EXPORT_FINAL_KEY_SIZE,
                                       server_write_key);
            }
          else
            {                   /* TLS 1.0 */
              ret =
                _gnutls_PRF (session, &key_block[pos], key_size,
                             servwrite, servwrite_length,
                             rrnd, 2 * GNUTLS_RANDOM_SIZE,
                             EXPORT_FINAL_KEY_SIZE, server_write_key);
            }

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

          server_write_key_size = EXPORT_FINAL_KEY_SIZE;
          pos += key_size;
        }

      if (_gnutls_sset_datum
          (&client_write->key, client_write_key, client_write_key_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
                        client_write_key_size,
                        _gnutls_bin2hex (client_write_key,
                                         client_write_key_size, buf,
                                         sizeof (buf), NULL));

      if (_gnutls_sset_datum
          (&server_write->key, server_write_key, server_write_key_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
                        server_write_key_size,
                        _gnutls_bin2hex (server_write_key,
                                         server_write_key_size, buf,
                                         sizeof (buf), NULL));

    }


  /* IV generation in export and non export ciphers.
   */
  if (IV_size > 0 && export_flag == 0)
    {
      if (_gnutls_sset_datum
          (&client_write->IV, &key_block[pos], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += IV_size;

      if (_gnutls_sset_datum
          (&server_write->IV, &key_block[pos], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += IV_size;

    }
  else if (IV_size > 0 && export_flag != 0)
    {
      opaque iv_block[MAX_CIPHER_BLOCK_SIZE * 2];

      if (session->security_parameters.version == GNUTLS_SSL3)
        {                       /* SSL 3 */
          ret = _gnutls_ssl3_hash_md5 ("", 0,
                                       rrnd, GNUTLS_RANDOM_SIZE * 2,
                                       IV_size, iv_block);

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


          ret = _gnutls_ssl3_hash_md5 ("", 0, rnd,
                                       GNUTLS_RANDOM_SIZE * 2,
                                       IV_size, &iv_block[IV_size]);

        }
      else
        {                       /* TLS 1.0 */
          ret = _gnutls_PRF (session, "", 0,
                             ivblock, ivblock_length, rrnd,
                             2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block);
        }

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

      if (_gnutls_sset_datum (&client_write->IV, iv_block, IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      if (_gnutls_sset_datum
          (&server_write->IV, &iv_block[IV_size], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
    }

  return 0;
}
/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure.
 */
int
_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
{
  int ret;
  gnutls_openpgp_keyid_t keyid;
  char err_buf[33];

  memset (gcert, 0, sizeof (gnutls_cert));
  gcert->cert_type = GNUTLS_CRT_OPENPGP;
  gcert->version = gnutls_openpgp_crt_get_version (cert);
  gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;

  ret = gnutls_openpgp_crt_get_preferred_key_id (cert, keyid);

  if (ret == 0)
    {
      int idx;
      uint32_t kid32[2];

      _gnutls_debug_log
	("Importing Openpgp cert and using openpgp sub key: %s\n",
	 _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf)));

      KEYID_IMPORT (kid32, keyid);

      idx = gnutls_openpgp_crt_get_subkey_idx (cert, keyid);
      if (idx < 0)
	{
	  gnutls_assert ();
	  return idx;
	}

      gcert->subject_pk_algorithm =
	gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, NULL);

      gnutls_openpgp_crt_get_subkey_usage (cert, idx, &gcert->key_usage);
      gcert->use_subkey = 1;

      memcpy (gcert->subkey_id, keyid, sizeof (keyid));

      ret =
	_gnutls_openpgp_crt_get_mpis (cert, kid32, gcert->params,
				      &gcert->params_size);
    }
  else
    {
      _gnutls_debug_log
	("Importing Openpgp cert and using main openpgp key\n");
      gcert->subject_pk_algorithm =
	gnutls_openpgp_crt_get_pk_algorithm (cert, NULL);

      gnutls_openpgp_crt_get_key_usage (cert, &gcert->key_usage);
      ret =
	_gnutls_openpgp_crt_get_mpis (cert, NULL, gcert->params,
				      &gcert->params_size);
      gcert->use_subkey = 0;
    }

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

  {				/* copy the raw certificate */
#define SMALL_RAW 512
    opaque *raw;
    size_t raw_size = SMALL_RAW;

    /* initially allocate a bogus size, just in case the certificate
     * fits in it. That way we minimize the DER encodings performed.
     */
    raw = gnutls_malloc (raw_size);
    if (raw == NULL)
      {
	gnutls_assert ();
	return GNUTLS_E_MEMORY_ERROR;
      }

    ret =
      gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
				 &raw_size);
    if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
      {
	gnutls_assert ();
	gnutls_free (raw);
	return ret;
      }

    if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
      {
	raw = gnutls_realloc (raw, raw_size);
	if (raw == NULL)
	  {
	    gnutls_assert ();
	    return GNUTLS_E_MEMORY_ERROR;
	  }

	ret =
	  gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
				     &raw_size);
	if (ret < 0)
	  {
	    gnutls_assert ();
	    gnutls_free (raw);
	    return ret;
	  }
      }

    gcert->raw.data = raw;
    gcert->raw.size = raw_size;
  }

  return 0;

}
Exemple #9
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;
}
void
doit (void)
{
  int rc, i, j, x;
  char key[32];
  char tmp[1024];

  gnutls_global_init ();

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

  x = 0;
  for (i = 1; i < 4; i++)
    {
      for (j = 0; j < 3; j++)
        {
          rc =
            _gnutls_pkcs12_string_to_key (i, salt[j], strlen (salt[j]),
                                          j + i + 15, pw[j], sizeof (key),
                                          key);
          if (rc < 0)
            fail ("_gnutls_pkcs12_string_to_key failed[0]: %d\n", rc);

          if (strcmp (_gnutls_bin2hex (key, sizeof (key),
                                       tmp, sizeof (tmp), NULL),
                      values[x]) != 0)
            fail ("_gnutls_pkcs12_string_to_key failed[1]\n");

          if (debug)
            printf ("ij: %d.%d: %s\n", i, j,
                    _gnutls_bin2hex (key, sizeof (key), tmp, sizeof (tmp),
                                     NULL));
          x++;
        }
    }
  if (debug)
    printf ("\n");

  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
    {
      rc = _gnutls_pkcs12_string_to_key (tv[i].id, tv[i].salt, 8,
                                         tv[i].iter, tv[i].password,
                                         tv[i].keylen, key);
      if (rc < 0)
        fail ("_gnutls_pkcs12_string_to_key failed[2]: %d\n", rc);

      if (memcmp (_gnutls_bin2hex (key, tv[i].keylen,
                                   tmp, sizeof (tmp), NULL),
                  tv[i].key, tv[i].keylen) != 0)
        fail ("_gnutls_pkcs12_string_to_key failed[3]\n");

      if (debug)
        printf ("tv[%d]: %s\n", i,
                _gnutls_bin2hex (key, tv[i].keylen, tmp, sizeof (tmp), NULL));
    }
  if (debug)
    printf ("\n");

  gnutls_global_deinit ();

  if (debug)
    success ("_gnutls_pkcs12_string_to_key ok\n");
}
Exemple #11
0
static int append_elements(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_buffer_st *str, int k1, unsigned last)
{
	int k2, result, max_k2;
	int len;
	uint8_t value[MAX_STRING_LEN];
	char tmpbuffer1[ASN1_MAX_NAME_SIZE];
	char tmpbuffer2[ASN1_MAX_NAME_SIZE];
	char tmpbuffer3[ASN1_MAX_NAME_SIZE];
	const char *ldap_desc;
	char oid[MAX_OID_SIZE];
	gnutls_datum_t td = { NULL, 0 };
	gnutls_datum_t tvd = { NULL, 0 };

	/* create a string like "tbsCertList.issuer.rdnSequence.?1"
	 */
	if (asn1_rdn_name[0] != 0)
		snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
			 asn1_rdn_name, k1);
	else
		snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
			 k1);

	len = sizeof(value) - 1;
	result =
	    asn1_read_value(asn1_struct, tmpbuffer1, value, &len);

	if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	k2 = 0;

	result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	do {		/* Move to the attibute type and values
				 */
		k2++;

		if (tmpbuffer1[0] != 0)
			snprintf(tmpbuffer2, sizeof(tmpbuffer2),
				 "%s.?%u", tmpbuffer1, k2);
		else
			snprintf(tmpbuffer2, sizeof(tmpbuffer2),
				 "?%u", k2);

		/* Try to read the RelativeDistinguishedName attributes.
		 */

		len = sizeof(value) - 1;
		result =
		    asn1_read_value(asn1_struct, tmpbuffer2, value,
				    &len);

		if (result == ASN1_ELEMENT_NOT_FOUND)
			break;
		if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		/* Read the OID 
		 */
		_gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
				tmpbuffer2);
		_gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
				".type");

		len = sizeof(oid) - 1;
		result =
		    asn1_read_value(asn1_struct, tmpbuffer3, oid,
				    &len);

		if (result == ASN1_ELEMENT_NOT_FOUND)
			break;
		else if (result != ASN1_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		/* Read the Value 
		 */
		_gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
				tmpbuffer2);
		_gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
				".value");

		len = 0;

		result =
		    _gnutls_x509_read_value(asn1_struct,
					    tmpbuffer3, &tvd);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
#define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
		/*   The encodings of adjoining RelativeDistinguishedNames are separated
		 *   by a comma character (',' ASCII 44).
		 */

		ldap_desc =
		    gnutls_x509_dn_oid_name(oid,
					    GNUTLS_X509_DN_OID_RETURN_OID);

		STR_APPEND(ldap_desc);
		STR_APPEND("=");

		result =
		    _gnutls_x509_dn_to_string(oid, tvd.data,
					      tvd.size, &td);
		if (result < 0) {
			gnutls_assert();
			_gnutls_debug_log
			    ("Cannot parse OID: '%s' with value '%s'\n",
			     oid, _gnutls_bin2hex(tvd.data,
						  tvd.size,
						  tmpbuffer3,
						  sizeof
						  (tmpbuffer3),
						  NULL));
			goto cleanup;
		}

		DATA_APPEND(td.data, td.size);
		_gnutls_free_datum(&td);
		_gnutls_free_datum(&tvd);

		/*   Where there is a multi-valued RDN, the outputs from adjoining
		 *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
		 *   character.
		 */
		if (k2 < max_k2) {
			STR_APPEND("+");
		} else if (!last) {
			STR_APPEND(",");
		}
	}
	while (1);

	result = 0;

 cleanup:
	_gnutls_free_datum(&td);
	_gnutls_free_datum(&tvd);
	return result;
}
Exemple #12
0
/**
 * gnutls_openpgp_privkey_sign_hash:
 * @key: Holds the key
 * @hash: holds the data to be signed
 * @signature: will contain newly allocated signature
 *
 * This function will sign the given hash using the private key.  You
 * should use gnutls_openpgp_privkey_set_preferred_key_id() before
 * calling this function to set the subkey to use.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Deprecated: Use gnutls_privkey_sign_hash() instead.
 */
int
gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key,
				 const gnutls_datum_t * hash,
				 gnutls_datum_t * signature)
{
	int result;
	gnutls_pk_params_st params;
	int pk_algorithm;
	uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
	char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1];

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

	result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid);
	if (result == 0) {
		uint32_t kid[2];
		int idx;

		KEYID_IMPORT(kid, keyid);

		_gnutls_hard_log("Signing using PGP key ID %s\n",
				 _gnutls_bin2hex(keyid,
						 GNUTLS_OPENPGP_KEYID_SIZE,
						 buf, sizeof(buf), NULL));

		idx = gnutls_openpgp_privkey_get_subkey_idx(key, keyid);
		pk_algorithm =
		    gnutls_openpgp_privkey_get_subkey_pk_algorithm(key,
								   idx,
								   NULL);
		result =
		    _gnutls_openpgp_privkey_get_mpis(key, kid, &params);
	} else {
		_gnutls_hard_log("Signing using master PGP key\n");

		pk_algorithm =
		    gnutls_openpgp_privkey_get_pk_algorithm(key, NULL);
		result =
		    _gnutls_openpgp_privkey_get_mpis(key, NULL, &params);
	}

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


	result = _gnutls_pk_sign(pk_algorithm, signature, hash, &params);

	gnutls_pk_params_clear(&params);
	gnutls_pk_params_release(&params);

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

	return 0;
}
Exemple #13
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
int
_gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size,
		  int key_size, int export_flag)
{

/* FIXME: This function is too long
 */
  opaque *key_block;
  opaque rnd[2 * TLS_RANDOM_SIZE];
  opaque rrnd[2 * TLS_RANDOM_SIZE];
  int pos, ret;
  int block_size;
  char buf[65];

  if (session->cipher_specs.generated_keys != 0)
    {
      /* keys have already been generated.
       * reset generated_keys and exit normally.
       */
      session->cipher_specs.generated_keys = 0;
      return 0;
    }

  block_size = 2 * hash_size + 2 * key_size;
  if (export_flag == 0)
    block_size += 2 * IV_size;

  key_block = gnutls_secure_malloc (block_size);
  if (key_block == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  memcpy (rnd, session->security_parameters.server_random, TLS_RANDOM_SIZE);
  memcpy (&rnd[TLS_RANDOM_SIZE],
	  session->security_parameters.client_random, TLS_RANDOM_SIZE);

  memcpy (rrnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
  memcpy (&rrnd[TLS_RANDOM_SIZE],
	  session->security_parameters.server_random, TLS_RANDOM_SIZE);

  if (session->security_parameters.version == GNUTLS_SSL3)
    {				/* SSL 3 */
      ret =
	_gnutls_ssl3_generate_random (session->
				      security_parameters.
				      master_secret,
				      TLS_MASTER_SIZE, rnd,
				      2 * TLS_RANDOM_SIZE,
				      block_size, key_block);
    }
  else
    {				/* TLS 1.0 */
      ret =
	_gnutls_PRF (session, session->security_parameters.master_secret,
		     TLS_MASTER_SIZE, keyexp, keyexp_length,
		     rnd, 2 * TLS_RANDOM_SIZE, block_size, key_block);
    }

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

  _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
		    _gnutls_bin2hex (key_block, block_size, buf,
				     sizeof (buf)));

  pos = 0;
  if (hash_size > 0)
    {
      if (_gnutls_sset_datum
	  (&session->cipher_specs.client_write_mac_secret,
	   &key_block[pos], hash_size) < 0)
	{
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}
      pos += hash_size;

      if (_gnutls_sset_datum
	  (&session->cipher_specs.server_write_mac_secret,
	   &key_block[pos], hash_size) < 0)
	{
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}
      pos += hash_size;
    }

  if (key_size > 0)
    {
      opaque *client_write_key, *server_write_key;
      int client_write_key_size, server_write_key_size;
      int free_keys = 0;

      if (export_flag == 0)
	{
	  client_write_key = &key_block[pos];
	  client_write_key_size = key_size;

	  pos += key_size;

	  server_write_key = &key_block[pos];
	  server_write_key_size = key_size;

	  pos += key_size;

	}
      else
	{			/* export */
	  free_keys = 1;

	  client_write_key = gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
	  if (client_write_key == NULL)
	    {
	      gnutls_assert ();
	      gnutls_free (key_block);
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	  server_write_key = gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
	  if (server_write_key == NULL)
	    {
	      gnutls_assert ();
	      gnutls_free (key_block);
	      gnutls_free (client_write_key);
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	  /* generate the final keys */

	  if (session->security_parameters.version == GNUTLS_SSL3)
	    {			/* SSL 3 */
	      ret =
		_gnutls_ssl3_hash_md5 (&key_block[pos],
				       key_size, rrnd,
				       2 * TLS_RANDOM_SIZE,
				       EXPORT_FINAL_KEY_SIZE,
				       client_write_key);

	    }
	  else
	    {			/* TLS 1.0 */
	      ret =
		_gnutls_PRF (session, &key_block[pos], key_size,
			     cliwrite, cliwrite_length,
			     rrnd,
			     2 * TLS_RANDOM_SIZE,
			     EXPORT_FINAL_KEY_SIZE, client_write_key);
	    }

	  if (ret < 0)
	    {
	      gnutls_assert ();
	      gnutls_free (key_block);
	      gnutls_free (server_write_key);
	      gnutls_free (client_write_key);
	      return ret;
	    }

	  client_write_key_size = EXPORT_FINAL_KEY_SIZE;
	  pos += key_size;

	  if (session->security_parameters.version == GNUTLS_SSL3)
	    {			/* SSL 3 */
	      ret =
		_gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
				       rnd, 2 * TLS_RANDOM_SIZE,
				       EXPORT_FINAL_KEY_SIZE,
				       server_write_key);
	    }
	  else
	    {			/* TLS 1.0 */
	      ret =
		_gnutls_PRF (session, &key_block[pos], key_size,
			     servwrite, servwrite_length,
			     rrnd, 2 * TLS_RANDOM_SIZE,
			     EXPORT_FINAL_KEY_SIZE, server_write_key);
	    }

	  if (ret < 0)
	    {
	      gnutls_assert ();
	      gnutls_free (key_block);
	      gnutls_free (server_write_key);
	      gnutls_free (client_write_key);
	      return ret;
	    }

	  server_write_key_size = EXPORT_FINAL_KEY_SIZE;
	  pos += key_size;
	}

      if (_gnutls_sset_datum
	  (&session->cipher_specs.client_write_key,
	   client_write_key, client_write_key_size) < 0)
	{
	  gnutls_free (key_block);
	  gnutls_free (server_write_key);
	  gnutls_free (client_write_key);
	  return GNUTLS_E_MEMORY_ERROR;
	}
      _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
			client_write_key_size,
			_gnutls_bin2hex (client_write_key,
					 client_write_key_size, buf,
					 sizeof (buf)));

      if (_gnutls_sset_datum
	  (&session->cipher_specs.server_write_key,
	   server_write_key, server_write_key_size) < 0)
	{
	  gnutls_free (key_block);
	  gnutls_free (server_write_key);
	  gnutls_free (client_write_key);
	  return GNUTLS_E_MEMORY_ERROR;
	}

      _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
			server_write_key_size,
			_gnutls_bin2hex (server_write_key,
					 server_write_key_size, buf,
					 sizeof (buf)));

      if (free_keys != 0)
	{
	  gnutls_free (server_write_key);
	  gnutls_free (client_write_key);
	}
    }


  /* IV generation in export and non export ciphers.
   */
  if (IV_size > 0 && export_flag == 0)
    {
      if (_gnutls_sset_datum
	  (&session->cipher_specs.client_write_IV, &key_block[pos],
	   IV_size) < 0)
	{
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}
      pos += IV_size;

      if (_gnutls_sset_datum
	  (&session->cipher_specs.server_write_IV, &key_block[pos],
	   IV_size) < 0)
	{
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}
      pos += IV_size;

    }
  else if (IV_size > 0 && export_flag != 0)
    {
      opaque *iv_block = gnutls_alloca (IV_size * 2);
      if (iv_block == NULL)
	{
	  gnutls_assert ();
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}

      if (session->security_parameters.version == GNUTLS_SSL3)
	{			/* SSL 3 */
	  ret = _gnutls_ssl3_hash_md5 ("", 0,
				       rrnd, TLS_RANDOM_SIZE * 2,
				       IV_size, iv_block);

	  if (ret < 0)
	    {
	      gnutls_assert ();
	      gnutls_free (key_block);
	      gnutls_afree (iv_block);
	      return ret;
	    }

	  ret = _gnutls_ssl3_hash_md5 ("", 0, rnd,
				       TLS_RANDOM_SIZE * 2,
				       IV_size, &iv_block[IV_size]);

	}
      else
	{			/* TLS 1.0 */
	  ret = _gnutls_PRF (session, "", 0,
			     ivblock, ivblock_length, rrnd,
			     2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block);
	}

      if (ret < 0)
	{
	  gnutls_assert ();
	  gnutls_afree (iv_block);
	  gnutls_free (key_block);
	  return ret;
	}

      if (_gnutls_sset_datum
	  (&session->cipher_specs.client_write_IV, iv_block, IV_size) < 0)
	{
	  gnutls_afree (iv_block);
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}

      if (_gnutls_sset_datum
	  (&session->cipher_specs.server_write_IV,
	   &iv_block[IV_size], IV_size) < 0)
	{
	  gnutls_afree (iv_block);
	  gnutls_free (key_block);
	  return GNUTLS_E_MEMORY_ERROR;
	}

      gnutls_afree (iv_block);
    }

  gnutls_free (key_block);

  session->cipher_specs.generated_keys = 1;

  return 0;
}
Exemple #14
0
static
int get_win_urls(const CERT_CONTEXT * cert, char **cert_url, char **key_url,
		 char **label, gnutls_datum_t * der)
{
	BOOL r;
	int ret;
	DWORD tl_size;
	gnutls_datum_t tmp_label = { NULL, 0 };
	char name[MAX_CN * 2];
	char hex[MAX_WID_SIZE * 2 + 1];
	gnutls_buffer_st str;
#ifdef WORDS_BIGENDIAN
	const unsigned bigendian = 1;
#else
	const unsigned bigendian = 0;
#endif

	if (cert == NULL)
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	if (der) {
		der->data = gnutls_malloc(cert->cbCertEncoded);
		if (der->data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memcpy(der->data, cert->pbCertEncoded, cert->cbCertEncoded);
		der->size = cert->cbCertEncoded;
	}

	_gnutls_buffer_init(&str);
	if (label)
		*label = NULL;
	if (key_url)
		*key_url = NULL;
	if (cert_url)
		*cert_url = NULL;

	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
					      name, &tl_size);
	if (r != 0) {		/* optional */
		ret =
		    _gnutls_ucs2_to_utf8(name, tl_size, &tmp_label, bigendian);
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
		if (label)
			*label = (char *)tmp_label.data;
	}

	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
					      name, &tl_size);
	if (r == 0) {
		gnutls_assert();
		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		goto fail;
	}

	if (_gnutls_bin2hex(name, tl_size, hex, sizeof(hex), 0) == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		goto fail;
	}

	ret =
	    _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=cert", hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret =
		    _gnutls_buffer_append_escape(&str, tmp_label.data,
						 tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (cert_url)
		*cert_url = (char *)str.data;
	_gnutls_buffer_init(&str);

	ret =
	    _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=privkey",
					 hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret =
		    _gnutls_buffer_append_escape(&str, tmp_label.data,
						 tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (key_url)
		*key_url = (char *)str.data;
	_gnutls_buffer_init(&str);

	ret = 0;
	goto cleanup;

 fail:
	if (der)
		gnutls_free(der->data);
	if (cert_url)
		gnutls_free(*cert_url);
	if (key_url)
		gnutls_free(*key_url);
	if (label)
		gnutls_free(*label);
 cleanup:
	_gnutls_buffer_clear(&str);
	return ret;
}
Exemple #15
0
/*-
 * _gnutls_privkey_import_system:
 * @pkey: The private key
 * @url: The URL of the key
 *
 * This function will import the given private key to the abstract
 * #gnutls_privkey_t type. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 *
 -*/
int _gnutls_privkey_import_system_url(gnutls_privkey_t pkey, const char *url)
{
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
    return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
#else
	uint8_t id[MAX_WID_SIZE];
	HCERTSTORE store = NULL;
	size_t id_size;
	const CERT_CONTEXT *cert = NULL;
	CRYPT_HASH_BLOB blob;
	CRYPT_KEY_PROV_INFO *kpi = NULL;
	NCRYPT_KEY_HANDLE nc = NULL;
	HCRYPTPROV hCryptProv = NULL;
	NCRYPT_PROV_HANDLE sctx = NULL;
	DWORD kpi_size;
	SECURITY_STATUS r;
	int ret, enc_too = 0;
	WCHAR algo_str[64];
	DWORD algo_str_size = 0;
	priv_st *priv;
	DWORD i, dwErrCode = 0;

	if (ncrypt_init == 0)
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);

	if (url == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	priv = gnutls_calloc(1, sizeof(*priv));
	if (priv == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	id_size = sizeof(id);
	ret = get_id(url, id, &id_size, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	blob.cbData = id_size;
	blob.pbData = id;

	store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
	if (store == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_FILE_ERROR;
		goto cleanup;
	}

	cert = CertFindCertificateInStore(store,
					  X509_ASN_ENCODING,
					  0,
					  CERT_FIND_KEY_IDENTIFIER,
					  &blob, NULL);

	if (cert == NULL) {
		char buf[64];
		_gnutls_debug_log("cannot find ID: %s from %s\n",
				  _gnutls_bin2hex(id, id_size,
						  buf, sizeof(buf), NULL), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi_size = 0;
	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      NULL, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
				  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi = gnutls_malloc(kpi_size);
	if (kpi == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      kpi, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
				  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenStorageProvider(&sctx, kpi->pwszProvName, 0);
	if (!FAILED(r)) {	/* if this works carry on with CNG */

		r = pNCryptOpenKey(sctx, &nc, kpi->pwszContainerName, 0, 0);
		if (FAILED(r)) {
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		r = pNCryptGetProperty(nc, NCRYPT_ALGORITHM_PROPERTY,
				       (BYTE *) algo_str, sizeof(algo_str),
				       &algo_str_size, 0);
		if (FAILED(r)) {
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		if (StrCmpW(algo_str, BCRYPT_RSA_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_RSA;
			priv->sign_algo = GNUTLS_SIGN_RSA_SHA256;
			enc_too = 1;
		} else if (StrCmpW(algo_str, BCRYPT_DSA_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_DSA;
			priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P256_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA256;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P384_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA384;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P521_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA512;
		} else {
			_gnutls_debug_log("unknown key algorithm: %ls\n",
					  algo_str);
			ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
			goto cleanup;
		}
		priv->nc = nc;

		ret = gnutls_privkey_import_ext3(pkey, priv, cng_sign,
						 (enc_too !=
						  0) ? cng_decrypt : NULL,
						 cng_deinit, cng_info, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		/* this should be CAPI */
		_gnutls_debug_log
		    ("error in opening CNG keystore: %x from %ls\n", (int)r,
		     kpi->pwszProvName);

		if (CryptAcquireContextW(&hCryptProv,
					 kpi->pwszContainerName,
					 kpi->pwszProvName,
					 kpi->dwProvType, kpi->dwFlags)) {
			for (i = 0; i < kpi->cProvParam; i++)
				if (!CryptSetProvParam(hCryptProv,
						       kpi->rgProvParam[i].
						       dwParam,
						       kpi->rgProvParam[i].
						       pbData,
						       kpi->rgProvParam[i].
						       dwFlags)) {
					dwErrCode = GetLastError();
					break;
				};
		} else {
			dwErrCode = GetLastError();
		}

		if (ERROR_SUCCESS != dwErrCode) {
			_gnutls_debug_log
			    ("error in getting cryptprov: %d from %s\n",
			     (int)GetLastError(), url);
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		{
			BYTE buf[100 + sizeof(PROV_ENUMALGS_EX) * 2];
			PROV_ENUMALGS_EX *pAlgo = (PROV_ENUMALGS_EX *) buf;
			DWORD len = sizeof(buf);

			if (CryptGetProvParam
			    (hCryptProv, PP_ENUMALGS_EX, buf, &len,
			     CRYPT_FIRST)) {
				DWORD hash = 0;
				do {
					switch (pAlgo->aiAlgid) {
					case CALG_RSA_SIGN:
						priv->pk = GNUTLS_PK_RSA;
						enc_too = 1;
						break;
					case CALG_DSS_SIGN:
						priv->pk =
						    priv->pk ==
						    GNUTLS_PK_RSA ?
						    GNUTLS_PK_RSA :
						    GNUTLS_PK_DSA;
						break;
					case CALG_SHA1:
						hash = 1;
						break;
					case CALG_SHA_256:
						hash = 256;
						break;
					default:
						break;
					}

					len = sizeof(buf);	// reset the buffer size
				} while (CryptGetProvParam
					 (hCryptProv, PP_ENUMALGS_EX, buf, &len,
					  CRYPT_NEXT));

				if (priv->pk == GNUTLS_PK_DSA)
					priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
				else
					priv->sign_algo =
					    (hash >
					     1) ? GNUTLS_SIGN_RSA_SHA256 :
					    GNUTLS_SIGN_RSA_SHA1;
			}
		}

		priv->hCryptProv = hCryptProv;
		priv->dwKeySpec = kpi->dwKeySpec;

		ret = gnutls_privkey_import_ext3(pkey, priv, capi_sign,
						 (enc_too !=
						  0) ? capi_decrypt : NULL,
						 capi_deinit, capi_info, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}
	ret = 0;
 cleanup:
	if (ret < 0) {
		if (nc != 0)
			pNCryptFreeObject(nc);
		if (hCryptProv != 0)
			CryptReleaseContext(hCryptProv, 0);
		gnutls_free(priv);
	}
	if (sctx != 0)
		pNCryptFreeObject(sctx);

	gnutls_free(kpi);

	if (cert != 0)
		CertFreeCertificateContext(cert);

	CertCloseStore(store, 0);
	return ret;
#endif
}
/*-
 * _gnutls_privkey_import_system:
 * @pkey: The private key
 * @url: The URL of the key
 *
 * This function will import the given private key to the abstract
 * #gnutls_privkey_t type. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 *
 -*/
int
_gnutls_privkey_import_system_url(gnutls_privkey_t pkey,
			          const char *url)
{
	uint8_t id[MAX_WID_SIZE];
	HCERTSTORE store = NULL;
	size_t id_size;
	const CERT_CONTEXT *cert = NULL;
	CRYPT_HASH_BLOB blob;
	CRYPT_KEY_PROV_INFO *kpi = NULL;
	NCRYPT_KEY_HANDLE nc = NULL;
	NCRYPT_PROV_HANDLE sctx = NULL;
	DWORD kpi_size;
	SECURITY_STATUS r;
	int ret, enc_too = 0;
	WCHAR algo_str[64];
	DWORD algo_str_size = 0;
	priv_st *priv;

	if (ncrypt_init == 0)
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);

	if (url == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	priv = gnutls_calloc(1, sizeof(*priv));
	if (priv == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	id_size = sizeof(id);
	ret = get_id(url, id, &id_size, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	blob.cbData = id_size;
	blob.pbData = id;

	store = CertOpenSystemStore(0, "MY");
	if (store == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_FILE_ERROR;
		goto cleanup;
	}

	cert = CertFindCertificateInStore(store,
				X509_ASN_ENCODING,
				0,
				CERT_FIND_KEY_IDENTIFIER,
				&blob,
				NULL);

	if (cert == NULL) {
		char buf[64];
		_gnutls_debug_log("cannot find ID: %s from %s\n",
			      _gnutls_bin2hex(id, id_size,
					      buf, sizeof(buf), NULL),
				url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi_size = 0;
	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      NULL, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
			      	  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi = gnutls_malloc(kpi_size);
	if (kpi == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      kpi, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
			      	  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenStorageProvider(&sctx, kpi->pwszProvName, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenKey(sctx, &nc, kpi->pwszContainerName, 0, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptGetProperty(nc, NCRYPT_ALGORITHM_PROPERTY,
				(BYTE*)algo_str, sizeof(algo_str),
				&algo_str_size, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	if (StrCmpW(algo_str, BCRYPT_RSA_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_RSA;
		priv->sign_algo = GNUTLS_SIGN_RSA_SHA256;
		enc_too = 1;
	} else if (StrCmpW(algo_str, BCRYPT_DSA_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_DSA;
		priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P256_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA256;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P384_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA384;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P521_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA512;
	} else {
		_gnutls_debug_log("unknown key algorithm: %ls\n", algo_str);
		ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
		goto cleanup;
	}
	priv->nc = nc;

	ret = gnutls_privkey_import_ext3(pkey, priv, cng_sign,
					 (enc_too!=0)?cng_decrypt:NULL,
					 cng_deinit,
					 cng_info, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
 cleanup:
	if (ret < 0) {
		if (nc != 0)
			pNCryptFreeObject(nc);
		gnutls_free(priv);
	}
	if (sctx != 0)
		pNCryptFreeObject(sctx);

	gnutls_free(kpi);
	CertCloseStore(store, 0);
	return ret;
}
Exemple #17
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
static int
_gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
		 int hash_size, int IV_size, int key_size)
{
	/* FIXME: This function is too long
	 */
	uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
	uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
	int pos, ret;
	int block_size;
	char buf[65];
	/* avoid using malloc */
	uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
			  2 * MAX_CIPHER_BLOCK_SIZE];
	record_state_st *client_write, *server_write;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		client_write = &params->write;
		server_write = &params->read;
	} else {
		client_write = &params->read;
		server_write = &params->write;
	}

	block_size = 2 * hash_size + 2 * key_size;
	block_size += 2 * IV_size;

	memcpy(rnd, session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);

	memcpy(rrnd, session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rrnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);

	if (get_num_version(session) == GNUTLS_SSL3) {	/* SSL 3 */
		ret =
		    _gnutls_ssl3_generate_random
		    (session->security_parameters.master_secret,
		     GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE,
		     block_size, key_block);
	} else {		/* TLS 1.0 */
		ret =
		    _gnutls_PRF(session,
				session->security_parameters.master_secret,
				GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
				rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
				key_block);
	}

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

	_gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
			 _gnutls_bin2hex(key_block, block_size, buf,
					 sizeof(buf), NULL));

	pos = 0;
	if (hash_size > 0) {

		if (_gnutls_set_datum
		    (&client_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;

		if (_gnutls_set_datum
		    (&server_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;
	}

	if (key_size > 0) {
		uint8_t *client_write_key, *server_write_key;
		int client_write_key_size, server_write_key_size;

		client_write_key = &key_block[pos];
		client_write_key_size = key_size;

		pos += key_size;

		server_write_key = &key_block[pos];
		server_write_key_size = key_size;

		pos += key_size;

		if (_gnutls_set_datum
		    (&client_write->key, client_write_key,
		     client_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
				 client_write_key_size,
				 _gnutls_bin2hex(client_write_key,
						 client_write_key_size,
						 buf, sizeof(buf), NULL));

		if (_gnutls_set_datum
		    (&server_write->key, server_write_key,
		     server_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
				 server_write_key_size,
				 _gnutls_bin2hex(server_write_key,
						 server_write_key_size,
						 buf, sizeof(buf), NULL));

	}

	/* IV generation in export and non export ciphers.
	 */
	if (IV_size > 0) {
		if (_gnutls_set_datum
		    (&client_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += IV_size;

		if (_gnutls_set_datum
		    (&server_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);


		_gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n",
				 client_write->IV.size,
				 _gnutls_bin2hex(client_write->IV.data,
						 client_write->IV.size,
						 buf, sizeof(buf), NULL));

		_gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n",
				 server_write->IV.size,
				 _gnutls_bin2hex(server_write->IV.data,
						 server_write->IV.size,
						 buf, sizeof(buf), NULL));
	}

	return 0;
}
Exemple #18
0
/*-
 * _gnutls_openpgp_privkey_decrypt_data:
 * @key: Holds the key
 * @flags: (0) for now
 * @ciphertext: holds the data to be decrypted
 * @plaintext: will contain newly allocated plaintext
 *
 * This function will sign the given hash using the private key.  You
 * should use gnutls_openpgp_privkey_set_preferred_key_id() before
 * calling this function to set the subkey to use.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_openpgp_privkey_decrypt_data(gnutls_openpgp_privkey_t key,
				     unsigned int flags,
				     const gnutls_datum_t * ciphertext,
				     gnutls_datum_t * plaintext)
{
	int result, i;
	gnutls_pk_params_st params;
	int pk_algorithm;
	uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
	char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1];

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

	result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid);
	if (result == 0) {
		uint32_t kid[2];

		KEYID_IMPORT(kid, keyid);

		_gnutls_hard_log("Decrypting using PGP key ID %s\n",
				 _gnutls_bin2hex(keyid,
						 GNUTLS_OPENPGP_KEYID_SIZE,
						 buf, sizeof(buf), NULL));

		result =
		    _gnutls_openpgp_privkey_get_mpis(key, kid, &params);

		i = gnutls_openpgp_privkey_get_subkey_idx(key, keyid);

		pk_algorithm =
		    gnutls_openpgp_privkey_get_subkey_pk_algorithm(key, i,
								   NULL);
	} else {
		_gnutls_hard_log("Decrypting using master PGP key\n");

		pk_algorithm =
		    gnutls_openpgp_privkey_get_pk_algorithm(key, NULL);

		result =
		    _gnutls_openpgp_privkey_get_mpis(key, NULL, &params);

	}

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

	result =
	    _gnutls_pk_decrypt(pk_algorithm, plaintext, ciphertext,
			       &params);

	gnutls_pk_params_clear(&params);
	gnutls_pk_params_release(&params);

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

	return 0;
}
Exemple #19
0
/* here we generate the TLS Master secret.
 */
static int
generate_normal_master(gnutls_session_t session,
		       gnutls_datum_t * premaster, int keep_premaster)
{
	int ret = 0;
	char buf[512];

	_gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n",
			 premaster->size, _gnutls_bin2hex(premaster->data,
							  premaster->size,
							  buf, sizeof(buf),
							  NULL));
	_gnutls_hard_log("INT: CLIENT RANDOM[%d]: %s\n", 32,
			 _gnutls_bin2hex(session->security_parameters.
					 client_random, 32, buf,
					 sizeof(buf), NULL));
	_gnutls_hard_log("INT: SERVER RANDOM[%d]: %s\n", 32,
			 _gnutls_bin2hex(session->security_parameters.
					 server_random, 32, buf,
					 sizeof(buf), NULL));

	if (session->security_parameters.ext_master_secret == 0) {
		uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
		memcpy(rnd, session->security_parameters.client_random,
		       GNUTLS_RANDOM_SIZE);
		memcpy(&rnd[GNUTLS_RANDOM_SIZE],
		       session->security_parameters.server_random,
		       GNUTLS_RANDOM_SIZE);

#ifdef ENABLE_SSL3
		if (get_num_version(session) == GNUTLS_SSL3) {
			ret =
			    _gnutls_ssl3_generate_random(premaster->data,
							 premaster->size, rnd,
							 2 * GNUTLS_RANDOM_SIZE,
							 GNUTLS_MASTER_SIZE,
							 session->security_parameters.
							 master_secret);
		} else
#endif
			ret =
			    _gnutls_PRF(session, premaster->data, premaster->size,
					MASTER_SECRET, MASTER_SECRET_SIZE,
					rnd, 2 * GNUTLS_RANDOM_SIZE,
					GNUTLS_MASTER_SIZE,
					session->security_parameters.
					master_secret);
	} else {
		gnutls_datum_t shash = {NULL, 0};

		/* draft-ietf-tls-session-hash-02 */
		ret = _gnutls_handshake_get_session_hash(session, &shash);
		if (ret < 0)
			return gnutls_assert_val(ret);
#ifdef ENABLE_SSL3
		if (get_num_version(session) == GNUTLS_SSL3)
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
#endif

		ret =
		    _gnutls_PRF(session, premaster->data, premaster->size,
				EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
				shash.data, shash.size,
				GNUTLS_MASTER_SIZE,
				session->security_parameters.
				master_secret);

		gnutls_free(shash.data);
	}

	write_nss_key_log(session, premaster);

	if (!keep_premaster)
		_gnutls_free_temp_key_datum(premaster);

	if (ret < 0)
		return ret;

	_gnutls_hard_log("INT: MASTER SECRET: %s\n",
			 _gnutls_bin2hex(session->security_parameters.
					 master_secret, GNUTLS_MASTER_SIZE,
					 buf, sizeof(buf), NULL));

	return ret;
}
Exemple #20
0
/* return A = g^a % N */
int
_gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
{
  size_t n_a;
  int ret;
  uint8_t *data_a;
  char *username, *password;
  char buf[64];
  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;
    }

  /* calc A = g^a % N 
   */
  if (G == NULL || N == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  A = _gnutls_calc_srp_A (&_a, G, N);
  if (A == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* Rest of 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 = (B - g^x) ^ (a + u * x) % N */
  S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
  if (S == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_dump_mpi ("SRP B: ", B);

  _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;
    }

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

  (*data) = gnutls_malloc (n_a + 2);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* copy A */
  data_a = (*data);
  if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0)
    {
      gnutls_free (*data);
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a,
		    _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf)));

  _gnutls_mpi_release (&A);

  _gnutls_write_uint16 (n_a, data_a);

  return n_a + 2;
}
Exemple #21
0
/* Parses an X509 DN in the asn1_struct, and puts the output into
 * the string buf. The output is an LDAP encoded DN.
 *
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
 * That is to point in the rndSequence.
 */
int
_gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
		       const char *asn1_rdn_name, char *buf,
		       size_t * sizeof_buf)
{
  gnutls_string out_str;
  int k2, k1, result;
  char tmpbuffer1[MAX_NAME_SIZE];
  char tmpbuffer2[MAX_NAME_SIZE];
  char tmpbuffer3[MAX_NAME_SIZE];
  opaque value[MAX_STRING_LEN], *value2 = NULL;
  char *escaped = NULL;
  const char *ldap_desc;
  char oid[128];
  int len, printable;
  char *string = NULL;
  size_t sizeof_string, sizeof_escaped;

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

  if (buf)
    buf[0] = 0;
  else
    *sizeof_buf = 0;

  _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free);

  k1 = 0;
  do
    {

      k1++;
      /* create a string like "tbsCertList.issuer.rdnSequence.?1"
       */
      if (asn1_rdn_name[0]!=0)
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, k1);
      else
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
      
      len = sizeof (value) - 1;
      result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      if (result != ASN1_VALUE_NOT_FOUND)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      k2 = 0;

      do
	{			/* Move to the attibute type and values
				 */
	  k2++;

          if (tmpbuffer1[0] != 0)
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, k2);
          else
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);

	  /* Try to read the RelativeDistinguishedName attributes.
	   */

	  len = sizeof (value) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  if (result != ASN1_VALUE_NOT_FOUND)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the OID 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");

	  len = sizeof (oid) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  else if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the Value 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");

	  len = 0;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len);

	  value2 = gnutls_malloc (len);
	  if (value2 == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len);

	  if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }
#define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
	  /*   The encodings of adjoining RelativeDistinguishedNames are separated
	   *   by a comma character (',' ASCII 44).
	   */

	  /*   Where there is a multi-valued RDN, the outputs from adjoining
	   *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
	   *   character.
	   */
	  if (k1 != 1)
	    {			/* the first time do not append a comma */
	      if (k2 != 1)
		{		/* adjoining multi-value RDN */
		  STR_APPEND ("+");
		}
	      else
		{
		  STR_APPEND (",");
		}
	    }

	  ldap_desc = oid2ldap_string (oid);
	  printable = _gnutls_x509_oid_data_printable (oid);

	  sizeof_escaped = 2 * len + 1;

	  escaped = gnutls_malloc (sizeof_escaped);
	  if (escaped == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  sizeof_string = 2 * len + 2;	/* in case it is not printable */

	  string = gnutls_malloc (sizeof_string);
	  if (string == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  STR_APPEND (ldap_desc);
	  STR_APPEND ("=");
	  if (printable)
	    result =
	      _gnutls_x509_oid_data2string (oid,
					    value2, len,
					    string, &sizeof_string);
	  else
	    result =
	      _gnutls_x509_data2hex (value2, len, string, &sizeof_string);

	  if (result < 0)
	    {
	      gnutls_assert ();
	      _gnutls_x509_log
		("Found OID: '%s' with value '%s'\n",
		 oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped));
	      goto cleanup;
	    }
	  STR_APPEND (str_escape (string, escaped, sizeof_escaped));
	  gnutls_free (string);
	  string = NULL;

	  gnutls_free (escaped);
	  escaped = NULL;
	  gnutls_free (value2);
	  value2 = NULL;

	}
      while (1);

    }
  while (1);

  if (out_str.length >= (unsigned int) *sizeof_buf)
    {
      gnutls_assert ();
      *sizeof_buf = out_str.length + 1;
      result = GNUTLS_E_SHORT_MEMORY_BUFFER;
      goto cleanup;
    }

  if (buf)
    {
      memcpy (buf, out_str.data, out_str.length);
      buf[out_str.length] = 0;
    }
  *sizeof_buf = out_str.length;

  result = 0;

cleanup:
  gnutls_free (value2);
  gnutls_free (string);
  gnutls_free (escaped);
  _gnutls_string_clear (&out_str);
  return result;
}
Exemple #22
0
static int
generate_normal_master (gnutls_session_t session, int keep_premaster)
{
    int ret = 0;
    char buf[512];

    _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
                      _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
                                       sizeof (buf)));
    _gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32,
                      _gnutls_bin2hex (session->
                                       security_parameters.client_random, 32,
                                       buf, sizeof (buf)));
    _gnutls_hard_log ("INT: SERVER RANDOM[%d]: %s\n", 32,
                      _gnutls_bin2hex (session->
                                       security_parameters.server_random, 32,
                                       buf, sizeof (buf)));

    if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
    {
        opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];

        memcpy (rnd, session->security_parameters.client_random,
                GNUTLS_RANDOM_SIZE);
        memcpy (&rnd[GNUTLS_RANDOM_SIZE],
                session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

        ret =
            _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
                                          rnd, 2 * GNUTLS_RANDOM_SIZE,
                                          GNUTLS_MASTER_SIZE,
                                          session->
                                          security_parameters.master_secret);

    }
    else if (session->security_parameters.extensions.oprfi_client_len > 0 &&
             session->security_parameters.extensions.oprfi_server_len > 0)
    {
        opaque *rnd;
        size_t rndlen = 2 * GNUTLS_RANDOM_SIZE;

        rndlen += session->security_parameters.extensions.oprfi_client_len;
        rndlen += session->security_parameters.extensions.oprfi_server_len;

        rnd = gnutls_malloc (rndlen + 1);
        if (!rnd)
        {
            gnutls_assert ();
            return GNUTLS_E_MEMORY_ERROR;
        }

        _gnutls_hard_log ("INT: CLIENT OPRFI[%d]: %s\n",
                          session->security_parameters.extensions.
                          oprfi_server_len,
                          _gnutls_bin2hex (session->
                                           security_parameters.extensions.
                                           oprfi_client,
                                           session->
                                           security_parameters.extensions.
                                           oprfi_client_len, buf,
                                           sizeof (buf)));
        _gnutls_hard_log ("INT: SERVER OPRFI[%d]: %s\n",
                          session->security_parameters.extensions.
                          oprfi_server_len,
                          _gnutls_bin2hex (session->
                                           security_parameters.extensions.
                                           oprfi_server,
                                           session->
                                           security_parameters.extensions.
                                           oprfi_server_len, buf,
                                           sizeof (buf)));

        memcpy (rnd, session->security_parameters.client_random,
                GNUTLS_RANDOM_SIZE);
        memcpy (rnd + GNUTLS_RANDOM_SIZE,
                session->security_parameters.extensions.oprfi_client,
                session->security_parameters.extensions.oprfi_client_len);
        memcpy (rnd + GNUTLS_RANDOM_SIZE +
                session->security_parameters.extensions.oprfi_client_len,
                session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
        memcpy (rnd + GNUTLS_RANDOM_SIZE +
                session->security_parameters.extensions.oprfi_client_len +
                GNUTLS_RANDOM_SIZE,
                session->security_parameters.extensions.oprfi_server,
                session->security_parameters.extensions.oprfi_server_len);

        ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
                           MASTER_SECRET, strlen (MASTER_SECRET),
                           rnd, rndlen, GNUTLS_MASTER_SIZE,
                           session->security_parameters.master_secret);

        gnutls_free (rnd);
    }
    else
    {
        opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];

        memcpy (rnd, session->security_parameters.client_random,
                GNUTLS_RANDOM_SIZE);
        memcpy (&rnd[GNUTLS_RANDOM_SIZE],
                session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

        ret =
            _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
                         MASTER_SECRET, strlen (MASTER_SECRET),
                         rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
                         session->security_parameters.master_secret);
    }

    /* TLS/IA inner secret is derived from the master secret. */
    memcpy (session->security_parameters.inner_secret,
            session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);

    if (!keep_premaster)
        _gnutls_free_datum (&PREMASTER);

    if (ret < 0)
        return ret;

    _gnutls_hard_log ("INT: MASTER SECRET: %s\n",
                      _gnutls_bin2hex (session->
                                       security_parameters.master_secret,
                                       GNUTLS_MASTER_SIZE, buf, sizeof (buf)));

    return ret;
}
Exemple #23
0
int
_gnutls_x509_get_dn(ASN1_TYPE asn1_struct,
		    const char *asn1_rdn_name, gnutls_datum_t * dn)
{
	gnutls_buffer_st out_str;
	int k2, k1, result;
	char tmpbuffer1[ASN1_MAX_NAME_SIZE];
	char tmpbuffer2[ASN1_MAX_NAME_SIZE];
	char tmpbuffer3[ASN1_MAX_NAME_SIZE];
	uint8_t value[MAX_STRING_LEN];
	gnutls_datum_t td = { NULL, 0 }, tvd = {
	NULL, 0};
	const char *ldap_desc;
	char oid[MAX_OID_SIZE];
	int len;

	_gnutls_buffer_init(&out_str);

	k1 = 0;
	do {
		k1++;
		/* create a string like "tbsCertList.issuer.rdnSequence.?1"
		 */
		if (asn1_rdn_name[0] != 0)
			snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
				 asn1_rdn_name, k1);
		else
			snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
				 k1);

		len = sizeof(value) - 1;
		result =
		    asn1_read_value(asn1_struct, tmpbuffer1, value, &len);

		if (result == ASN1_ELEMENT_NOT_FOUND) {
			if (k1 == 1) {
				gnutls_assert();
				result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
				goto cleanup;
			}
			break;
		}

		if (result != ASN1_VALUE_NOT_FOUND) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		k2 = 0;

		do {		/* Move to the attibute type and values
				 */
			k2++;

			if (tmpbuffer1[0] != 0)
				snprintf(tmpbuffer2, sizeof(tmpbuffer2),
					 "%s.?%u", tmpbuffer1, k2);
			else
				snprintf(tmpbuffer2, sizeof(tmpbuffer2),
					 "?%u", k2);

			/* Try to read the RelativeDistinguishedName attributes.
			 */

			len = sizeof(value) - 1;
			result =
			    asn1_read_value(asn1_struct, tmpbuffer2, value,
					    &len);

			if (result == ASN1_ELEMENT_NOT_FOUND)
				break;
			if (result != ASN1_VALUE_NOT_FOUND) {
				gnutls_assert();
				result = _gnutls_asn2err(result);
				goto cleanup;
			}

			/* Read the OID 
			 */
			_gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
					tmpbuffer2);
			_gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
					".type");

			len = sizeof(oid) - 1;
			result =
			    asn1_read_value(asn1_struct, tmpbuffer3, oid,
					    &len);

			if (result == ASN1_ELEMENT_NOT_FOUND)
				break;
			else if (result != ASN1_SUCCESS) {
				gnutls_assert();
				result = _gnutls_asn2err(result);
				goto cleanup;
			}

			/* Read the Value 
			 */
			_gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
					tmpbuffer2);
			_gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
					".value");

			len = 0;

			result =
			    _gnutls_x509_read_value(asn1_struct,
						    tmpbuffer3, &tvd);
			if (result < 0) {
				gnutls_assert();
				goto cleanup;
			}
#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
#define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
			/*   The encodings of adjoining RelativeDistinguishedNames are separated
			 *   by a comma character (',' ASCII 44).
			 */

			/*   Where there is a multi-valued RDN, the outputs from adjoining
			 *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
			 *   character.
			 */
			if (k1 != 1) {	/* the first time do not append a comma */
				if (k2 != 1) {	/* adjoining multi-value RDN */
					STR_APPEND("+");
				} else {
					STR_APPEND(",");
				}
			}

			ldap_desc =
			    gnutls_x509_dn_oid_name(oid,
						    GNUTLS_X509_DN_OID_RETURN_OID);

			STR_APPEND(ldap_desc);
			STR_APPEND("=");

			result =
			    _gnutls_x509_dn_to_string(oid, tvd.data,
						      tvd.size, &td);
			if (result < 0) {
				gnutls_assert();
				_gnutls_debug_log
				    ("Cannot parse OID: '%s' with value '%s'\n",
				     oid, _gnutls_bin2hex(tvd.data,
							  tvd.size,
							  tmpbuffer3,
							  sizeof
							  (tmpbuffer3),
							  NULL));
				goto cleanup;
			}

			DATA_APPEND(td.data, td.size);
			_gnutls_free_datum(&td);
			_gnutls_free_datum(&tvd);
		}
		while (1);
	}
	while (1);

	result = _gnutls_buffer_to_datum(&out_str, dn, 1);
	if (result < 0)
		gnutls_assert();

	goto cleanup1;

      cleanup:
	_gnutls_buffer_clear(&out_str);
      cleanup1:
	_gnutls_free_datum(&td);
	_gnutls_free_datum(&tvd);
	return result;

}
Exemple #24
0
void _gnutls_mpi_log(const char *prefix, bigint_t a)
{
	size_t binlen = 0;
	void *binbuf;
	size_t hexlen;
	char *hexbuf;
	int res;

	if (_gnutls_log_level < 2)
		return;

	res = _gnutls_mpi_print(a, NULL, &binlen);
	if (res < 0 && res != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s can't print value (%d/%d)\n",
				 prefix, res, (int) binlen);
		return;
	}

	if (binlen > 1024 * 1024) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s too large mpi (%d)\n", prefix,
				 (int) binlen);
		return;
	}

	binbuf = gnutls_malloc(binlen);
	if (!binbuf) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s out of memory (%d)\n", prefix,
				 (int) binlen);
		return;
	}

	res = _gnutls_mpi_print(a, binbuf, &binlen);
	if (res != 0) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s can't print value (%d/%d)\n",
				 prefix, res, (int) binlen);
		gnutls_free(binbuf);
		return;
	}

	hexlen = 2 * binlen + 1;
	hexbuf = gnutls_malloc(hexlen);

	if (!hexbuf) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s out of memory (hex %d)\n",
				 prefix, (int) hexlen);
		gnutls_free(binbuf);
		return;
	}

	_gnutls_bin2hex(binbuf, binlen, hexbuf, hexlen, NULL);

	_gnutls_hard_log("MPI: length: %d\n\t%s%s\n", (int) binlen, prefix,
			 hexbuf);

	gnutls_free(hexbuf);
	gnutls_free(binbuf);
}
Exemple #25
0
/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */
int
_gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
				 gnutls_openpgp_privkey_t src)
{
  int ret = 0;
  gnutls_openpgp_keyid_t keyid;
  char err_buf[33];

  if (dest == NULL || src == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_CERTIFICATE_ERROR;
    }

  dest->params_size = MAX_PRIV_PARAMS_SIZE;

  ret = gnutls_openpgp_privkey_get_preferred_key_id (src, keyid);

  if (ret == 0)
    {
      int idx;
      uint32_t kid32[2];

      _gnutls_debug_log
	("Importing Openpgp key and using openpgp sub key: %s\n",
	 _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf)));

      KEYID_IMPORT (kid32, keyid);

      idx = gnutls_openpgp_privkey_get_subkey_idx (src, keyid);
      if (idx < 0)
	{
	  gnutls_assert ();
	  return idx;
	}

      dest->pk_algorithm =
	gnutls_openpgp_privkey_get_subkey_pk_algorithm (src, idx, NULL);

      ret =
	_gnutls_openpgp_privkey_get_mpis (src, kid32, dest->params,
					  &dest->params_size);
    }
  else
    {
      _gnutls_debug_log
	("Importing Openpgp key and using main openpgp key.\n");

      dest->pk_algorithm =
	gnutls_openpgp_privkey_get_pk_algorithm (src, NULL);
      ret =
	_gnutls_openpgp_privkey_get_mpis (src, NULL, dest->params,
					  &dest->params_size);
    }


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

  return 0;

}