Exemple #1
0
static void
print_oneline(gnutls_buffer_st * str, gnutls_openpgp_crt_t cert)
{
	int err, i;

	i = 0;
	do {
		char *dn;
		size_t dn_size = 0;

		err = gnutls_openpgp_crt_get_name(cert, i, NULL, &dn_size);
		if (err != GNUTLS_E_SHORT_MEMORY_BUFFER
		    && err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
		    && err != GNUTLS_E_OPENPGP_UID_REVOKED)
			addf(str, "unknown name (%s), ",
			     gnutls_strerror(err));
		else {
			dn = gnutls_malloc(dn_size);
			if (!dn)
				addf(str, "unknown name (%s), ",
				     gnutls_strerror
				     (GNUTLS_E_MEMORY_ERROR));
			else {
				err =
				    gnutls_openpgp_crt_get_name(cert, i,
								dn,
								&dn_size);
				if (err < 0
				    && err !=
				    GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
				    && err != GNUTLS_E_OPENPGP_UID_REVOKED)
					addf(str, "unknown name (%s), ",
					     gnutls_strerror(err));
				else if (err >= 0)
					addf(str, _("name[%d]: %s, "), i,
					     dn);
				else if (err ==
					 GNUTLS_E_OPENPGP_UID_REVOKED)
					addf(str,
					     _("revoked name[%d]: %s, "),
					     i, dn);

				gnutls_free(dn);
			}
		}

		i++;
	}
	while (err >= 0);

	{
		char fpr[128];
		size_t fpr_size = sizeof(fpr);
		int err;

		err =
		    gnutls_openpgp_crt_get_fingerprint(cert, fpr,
						       &fpr_size);
		if (err < 0)
			addf(str, "error: get_fingerprint: %s\n",
			     gnutls_strerror(err));
		else {
			adds(str, _("fingerprint: "));
			_gnutls_buffer_hexprint(str, fpr, fpr_size);
			addf(str, ", ");
		}
	}

	{
		time_t tim;

		tim = gnutls_openpgp_crt_get_creation_time(cert);
		{
			char s[42];
			size_t max = sizeof(s);
			struct tm t;

			if (gmtime_r(&tim, &t) == NULL)
				addf(str, "error: gmtime_r (%ld), ",
				     (unsigned long) tim);
			else if (strftime
				 (s, max, "%Y-%m-%d %H:%M:%S UTC",
				  &t) == 0)
				addf(str, "error: strftime (%ld), ",
				     (unsigned long) tim);
			else
				addf(str, _("created: %s, "), s);
		}

		tim = gnutls_openpgp_crt_get_expiration_time(cert);
		{
			char s[42];
			size_t max = sizeof(s);
			struct tm t;

			if (tim == 0)
				adds(str, _("never expires, "));
			else {
				if (gmtime_r(&tim, &t) == NULL)
					addf(str,
					     "error: gmtime_r (%ld), ",
					     (unsigned long) tim);
				else if (strftime
					 (s, max, "%Y-%m-%d %H:%M:%S UTC",
					  &t) == 0)
					addf(str,
					     "error: strftime (%ld), ",
					     (unsigned long) tim);
				else
					addf(str, _("expires: %s, "), s);
			}
		}
	}

	{
		unsigned int bits = 0;
		gnutls_pk_algorithm_t algo =
		    gnutls_openpgp_crt_get_pk_algorithm(cert, &bits);
		const char *algostr = gnutls_pk_algorithm_get_name(algo);

		if (algostr)
			addf(str, _("key algorithm %s (%d bits)"), algostr,
			     bits);
		else
			addf(str, _("unknown key algorithm (%d)"), algo);
	}
}
/* Do PKCS-1 RSA encryption. 
 * params is modulus, public exp.
 */
int
_gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
                           const gnutls_datum_t * plaintext,
                           gnutls_pk_params_st * params, 
                           unsigned btype)
{
  unsigned int i, pad;
  int ret;
  opaque *edata, *ps;
  size_t k, psize;
  size_t mod_bits;
  gnutls_datum_t to_encrypt, encrypted;

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

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

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

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

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

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

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

      if (params->params_nr < RSA_PRIVATE_PARAMS)
        {
          gnutls_assert ();
          gnutls_free (edata);
          return GNUTLS_E_INTERNAL_ERROR;
        }

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

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

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

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

  gnutls_free (edata);

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

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

  ciphertext->data = gnutls_malloc (psize);
  if (ciphertext->data == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

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

  ciphertext->size = k;

  ret = 0;

cleanup:
  _gnutls_free_datum (&encrypted);

  return ret;
}
/**
 * gnutls_pkcs12_simple_parse:
 * @p12: the PKCS#12 blob.
 * @password: optional password used to decrypt PKCS#12 blob, bags and keys.
 * @key: a structure to store the parsed private key.
 * @chain: the corresponding to key certificate chain
 * @chain_len: will be updated with the number of additional
 * @extra_certs: optional pointer to receive an array of additional
 *                   certificates found in the PKCS#12 blob.
 * @extra_certs_len: will be updated with the number of additional
 *                       certs.
 * @crl: an optional structure to store the parsed CRL.
 * @flags: should be zero
 *
 * This function parses a PKCS#12 blob in @p12blob and extracts the
 * private key, the corresponding certificate chain, and any additional
 * certificates and a CRL.
 *
 * The @extra_certs_ret and @extra_certs_ret_len parameters are optional
 * and both may be set to %NULL. If either is non-%NULL, then both must
 * be.
 * 
 * MAC:ed PKCS#12 files are supported.  Encrypted PKCS#12 bags are
 * supported.  Encrypted PKCS#8 private keys are supported.  However,
 * only password based security, and the same password for all
 * operations, are supported.
 *
 * The private keys may be RSA PKCS#1 or DSA private keys encoded in
 * the OpenSSL way.
 *
 * PKCS#12 file may contain many keys and/or certificates, and there
 * is no way to identify which key/certificate pair you want.  You
 * should make sure the PKCS#12 file only contain one key/certificate
 * pair and/or one CRL.
 *
 * It is believed that the limitations of this function is acceptable
 * for most usage, and that any more flexibility would introduce
 * complexity that would make it harder to use this functionality at
 * all.
 *
 * If the provided structure has encrypted fields but no password
 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1
 **/
int
gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12,
                     const char *password,
                     gnutls_x509_privkey_t * key,
                     gnutls_x509_crt_t ** chain,
                     unsigned int * chain_len,
                     gnutls_x509_crt_t ** extra_certs,
                     unsigned int * extra_certs_len,
                     gnutls_x509_crl_t * crl,
                     unsigned int flags)
{
  gnutls_pkcs12_bag_t bag = NULL;
  gnutls_x509_crt_t *_extra_certs = NULL;
  unsigned int _extra_certs_len = 0;
  gnutls_x509_crt_t *_chain = NULL;
  unsigned int _chain_len = 0;
  int idx = 0;
  int ret;
  size_t cert_id_size = 0;
  size_t key_id_size = 0;
  opaque cert_id[20];
  opaque key_id[20];
  int privkey_ok = 0;

  *key = NULL;
  
  if (crl)
    *crl = NULL;

  /* find the first private key */
  for (;;)
    {
      int elements_in_bag;
      int i;

      ret = gnutls_pkcs12_bag_init (&bag);
      if (ret < 0)
        {
          bag = NULL;
          gnutls_assert ();
          goto done;
        }

      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
        break;
      if (ret < 0)
        {
          gnutls_assert ();
          goto done;
        }

      ret = gnutls_pkcs12_bag_get_type (bag, 0);
      if (ret < 0)
        {
          gnutls_assert ();
          goto done;
        }

      if (ret == GNUTLS_BAG_ENCRYPTED)
        {
          if (password == NULL)
            {
              ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
              goto done;
            }

          ret = gnutls_pkcs12_bag_decrypt (bag, password);
          if (ret < 0)
            {
              gnutls_assert ();
              goto done;
            }
        }

      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
      if (elements_in_bag < 0)
        {
          gnutls_assert ();
          goto done;
        }

      for (i = 0; i < elements_in_bag; i++)
        {
          int type;
          gnutls_datum_t data;

          type = gnutls_pkcs12_bag_get_type (bag, i);
          if (type < 0)
            {
              gnutls_assert ();
              goto done;
            }

          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
          if (ret < 0)
            {
              gnutls_assert ();
              goto done;
            }

          switch (type)
            {
            case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
              if (password == NULL)
                {
                  ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
                  goto done;
                }

            case GNUTLS_BAG_PKCS8_KEY:
              if (*key != NULL) /* too simple to continue */
                {
                  gnutls_assert ();
                  break;
                }

              ret = gnutls_x509_privkey_init (key);
              if (ret < 0)
                {
                  gnutls_assert ();
                  goto done;
                }

              ret = gnutls_x509_privkey_import_pkcs8
                (*key, &data, GNUTLS_X509_FMT_DER, password,
                 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
              if (ret < 0)
                {
                  gnutls_assert ();
                  gnutls_x509_privkey_deinit (*key);
                  goto done;
                }

              key_id_size = sizeof (key_id);
              ret =
                gnutls_x509_privkey_get_key_id (*key, 0, key_id,
                                                &key_id_size);
              if (ret < 0)
                {
                  gnutls_assert ();
                  gnutls_x509_privkey_deinit (*key);
                  goto done;
                }

              privkey_ok = 1;   /* break */
              break;
            default:
              break;
            }
        }

      idx++;
      gnutls_pkcs12_bag_deinit (bag);

      if (privkey_ok != 0)      /* private key was found */
        break;
    }

  if (privkey_ok == 0)          /* no private key */
    {
      gnutls_assert ();
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  /* now find the corresponding certificate 
   */
  idx = 0;
  bag = NULL;
  for (;;)
    {
      int elements_in_bag;
      int i;

      ret = gnutls_pkcs12_bag_init (&bag);
      if (ret < 0)
        {
          bag = NULL;
          gnutls_assert ();
          goto done;
        }

      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
        break;
      if (ret < 0)
        {
          gnutls_assert ();
          goto done;
        }

      ret = gnutls_pkcs12_bag_get_type (bag, 0);
      if (ret < 0)
        {
          gnutls_assert ();
          goto done;
        }

      if (ret == GNUTLS_BAG_ENCRYPTED)
        {
          ret = gnutls_pkcs12_bag_decrypt (bag, password);
          if (ret < 0)
            {
              gnutls_assert ();
              goto done;
            }
        }

      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
      if (elements_in_bag < 0)
        {
          gnutls_assert ();
          goto done;
        }

      for (i = 0; i < elements_in_bag; i++)
        {
          int type;
          gnutls_datum_t data;
          gnutls_x509_crt_t this_cert;

          type = gnutls_pkcs12_bag_get_type (bag, i);
          if (type < 0)
            {
              gnutls_assert ();
              goto done;
            }

          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
          if (ret < 0)
            {
              gnutls_assert ();
              goto done;
            }

          switch (type)
            {
            case GNUTLS_BAG_CERTIFICATE:
              ret = gnutls_x509_crt_init (&this_cert);
              if (ret < 0)
                {
                  gnutls_assert ();
                  goto done;
                }

              ret =
                gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
              if (ret < 0)
                {
                  gnutls_assert ();
                  gnutls_x509_crt_deinit (this_cert);
                  goto done;
                }

              /* check if the key id match */
              cert_id_size = sizeof (cert_id);
              ret =
                gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size);
              if (ret < 0)
                {
                  gnutls_assert ();
                  gnutls_x509_crt_deinit (this_cert);
                  goto done;
                }

              if (memcmp (cert_id, key_id, cert_id_size) != 0)
                { /* they don't match - skip the certificate */
                  if (extra_certs)
                    {
                      void *tmp = _extra_certs;
                      _extra_certs = gnutls_realloc (_extra_certs,
                                                     sizeof(_extra_certs[0]) *
                                                     ++_extra_certs_len);
                      if (!_extra_certs)
                        {
                          gnutls_assert ();
                          gnutls_free(tmp);
                          ret = GNUTLS_E_MEMORY_ERROR;
                          goto done;
                        }
                      _extra_certs[_extra_certs_len - 1] = this_cert;
                      this_cert = NULL;
                    }
                  else
                    {
                       gnutls_x509_crt_deinit (this_cert);
                    }
                }
              else
                {
                  if (_chain_len == 0)
                    {
                      _chain = gnutls_malloc (sizeof(_chain[0]) * (++_chain_len));
                      if (!_chain)
                        {
                          gnutls_assert ();
                          ret = GNUTLS_E_MEMORY_ERROR;
                          goto done;
                        }
                      _chain[_chain_len - 1] = this_cert;
                      this_cert = NULL;
                    }
                  else
                    {
                       gnutls_x509_crt_deinit (this_cert);
                    }
                }
              break;

            case GNUTLS_BAG_CRL:
              if (crl == NULL || *crl != NULL)
                {
                  gnutls_assert ();
                  break;
                }

              ret = gnutls_x509_crl_init (crl);
              if (ret < 0)
                {
                  gnutls_assert ();
                  goto done;
                }

              ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
              if (ret < 0)
                {
                  gnutls_assert ();
                  gnutls_x509_crl_deinit (*crl);
                  goto done;
                }
              break;

            case GNUTLS_BAG_ENCRYPTED:
              /* XXX Bother to recurse one level down?  Unlikely to
                 use the same password anyway. */
            case GNUTLS_BAG_EMPTY:
            default:
              break;
            }
        }

      idx++;
      gnutls_pkcs12_bag_deinit (bag);
    }

  if (_chain_len != 1)
    {
      ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
      goto done;
    }

  ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len);
  if (ret < 0)
    {
      gnutls_assert();
      goto done;
    }

  ret = 0;

done:
  if (bag)
    gnutls_pkcs12_bag_deinit (bag);

  if (ret < 0)
    {
      if (*key)
        gnutls_x509_privkey_deinit(*key);
      if (_extra_certs_len && _extra_certs != NULL)
        {
          unsigned int i;
          for (i = 0; i < _extra_certs_len; i++)
            gnutls_x509_crt_deinit(_extra_certs[i]);
          gnutls_free(_extra_certs);
        }
      if (_chain_len && _chain != NULL)
        {
          unsigned int i;
          for (i = 0; i < _chain_len; i++)
            gnutls_x509_crt_deinit(_chain[i]);
          gnutls_free(_chain);
        }
    }
  else 
    {
      if (extra_certs) 
        {
          *extra_certs = _extra_certs;
          *extra_certs_len = _extra_certs_len;
        }
      
      *chain = _chain;
      *chain_len = _chain_len;
    }

  return ret;
}
Exemple #4
0
/* Writes the value of the datum in the given ASN1_TYPE. If str is non
 * zero it encodes it as OCTET STRING.
 */
int
_gnutls_x509_write_value (ASN1_TYPE c, const char *root,
			  const gnutls_datum_t * data, int str)
{
  int result;
  int asize;
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  gnutls_datum_t val;

  asize = data->size + 16;

  val.data = gnutls_malloc (asize);
  if (val.data == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  if (str)
    {
      /* Convert it to OCTET STRING
       */
      if ((result = asn1_create_element
	   (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      result = asn1_write_value (c2, "", data->data, data->size);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      result = _gnutls_x509_der_encode (c2, "", &val, 0);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

    }
  else
    {
      val.data = data->data;
      val.size = data->size;
    }

  /* Write the data.
   */
  result = asn1_write_value (c, root, val.data, val.size);

  if (val.data != data->data)
    _gnutls_free_datum (&val);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  return 0;

cleanup:
  if (val.data != data->data)
    _gnutls_free_datum (&val);
  return result;
}
Exemple #5
0
/* DER Encodes the src ASN1_TYPE and stores it to
 * the given datum. If str is non null then the data are encoded as
 * an OCTET STRING.
 */
int
_gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name,
			 gnutls_datum_t * res, int str)
{
  int size, result;
  int asize;
  opaque *data = NULL;
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;

  size = 0;
  result = asn1_der_coding (src, src_name, NULL, &size, NULL);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* allocate data for the der
   */

  if (str)
    size += 16;			/* for later to include the octet tags */
  asize = size;

  data = gnutls_malloc (size);
  if (data == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  result = asn1_der_coding (src, src_name, data, &size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (str)
    {
      if ((result = asn1_create_element
	   (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      result = asn1_write_value (c2, "", data, size);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      result = asn1_der_coding (c2, "", data, &asize, NULL);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      size = asize;

      asn1_delete_structure (&c2);
    }

  res->data = data;
  res->size = size;
  return 0;

cleanup:
  gnutls_free (data);
  asn1_delete_structure (&c2);
  return result;

}
Exemple #6
0
/* Copy datum 'src' to 'dest'. */
static void copy_datum(gnutls_datum *dest, gnutls_datum *src)
{
    dest->size = src->size;
    dest->data = memcpy(gnutls_malloc(src->size), src->data, src->size);
}
/**
 * gnutls_x509_privkey_import_openssl:
 * @key: The structure to store the parsed key
 * @data: The DER or PEM encoded key.
 * @password: the password to decrypt the key (if it is encrypted).
 *
 * This function will convert the given PEM encrypted to 
 * the native gnutls_x509_privkey_t format. The
 * output will be stored in @key.  
 *
 * The @password should be in ASCII. If the password is not provided
 * or wrong then %GNUTLS_E_DECRYPTION_FAILED will be returned.
 *
 * If the Certificate is PEM encoded it should have a header of
 * "PRIVATE KEY" and the "DEK-Info" header. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_openssl(gnutls_x509_privkey_t key,
				   const gnutls_datum_t * data,
				   const char *password)
{
	gnutls_cipher_hd_t handle;
	gnutls_cipher_algorithm_t cipher = GNUTLS_CIPHER_UNKNOWN;
	gnutls_datum_t b64_data;
	gnutls_datum_t salt, enc_key;
	unsigned char *key_data;
	size_t key_data_size;
	const char *pem_header = (void *) data->data;
	const char *pem_header_start = (void *) data->data;
	ssize_t pem_header_size;
	int ret;
	unsigned int i, iv_size, l;

	pem_header_size = data->size;

	pem_header =
	    memmem(pem_header, pem_header_size, "PRIVATE KEY---", 14);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size -= (ptrdiff_t) (pem_header - pem_header_start);

	pem_header = memmem(pem_header, pem_header_size, "DEK-Info: ", 10);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size =
	    data->size - (ptrdiff_t) (pem_header - pem_header_start) - 10;
	pem_header += 10;

	for (i = 0; i < sizeof(pem_ciphers) / sizeof(pem_ciphers[0]); i++) {
		l = strlen(pem_ciphers[i].name);
		if (!strncmp(pem_header, pem_ciphers[i].name, l) &&
		    pem_header[l] == ',') {
			pem_header += l + 1;
			cipher = pem_ciphers[i].cipher;
			break;
		}
	}

	if (cipher == GNUTLS_CIPHER_UNKNOWN) {
		_gnutls_debug_log
		    ("Unsupported PEM encryption type: %.10s\n",
		     pem_header);
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	iv_size = gnutls_cipher_get_iv_size(cipher);
	salt.size = iv_size;
	salt.data = gnutls_malloc(salt.size);
	if (!salt.data)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	for (i = 0; i < salt.size * 2; i++) {
		unsigned char x;
		const char *c = &pem_header[i];

		if (*c >= '0' && *c <= '9')
			x = (*c) - '0';
		else if (*c >= 'A' && *c <= 'F')
			x = (*c) - 'A' + 10;
		else {
			gnutls_assert();
			/* Invalid salt in encrypted PEM file */
			ret = GNUTLS_E_INVALID_REQUEST;
			goto out_salt;
		}
		if (i & 1)
			salt.data[i / 2] |= x;
		else
			salt.data[i / 2] = x << 4;
	}

	pem_header += salt.size * 2;
	if (*pem_header != '\r' && *pem_header != '\n') {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_salt;
	}
	while (*pem_header == '\n' || *pem_header == '\r')
		pem_header++;

	ret =
	    _gnutls_base64_decode((const void *) pem_header,
				  pem_header_size, &b64_data);
	if (ret < 0) {
		gnutls_assert();
		goto out_salt;
	}

	if (b64_data.size < 16) {
		/* Just to be sure our parsing is OK */
		gnutls_assert();
		ret = GNUTLS_E_PARSING_ERROR;
		goto out_b64;
	}

	ret = GNUTLS_E_MEMORY_ERROR;
	enc_key.size = gnutls_cipher_get_key_size(cipher);
	enc_key.data = gnutls_malloc(enc_key.size);
	if (!enc_key.data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_b64;
	}

	key_data_size = b64_data.size;
	key_data = gnutls_malloc(key_data_size);
	if (!key_data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_enc_key;
	}

	while (1) {
		memcpy(key_data, b64_data.data, key_data_size);

		ret = openssl_hash_password(password, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			goto out;
		}

		ret = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			gnutls_cipher_deinit(handle);
			goto out;
		}

		ret =
		    gnutls_cipher_decrypt(handle, key_data, key_data_size);
		gnutls_cipher_deinit(handle);

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

		/* We have to strip any padding to accept it.
		   So a bit more ASN.1 parsing for us. */
		if (key_data[0] == 0x30) {
			gnutls_datum_t key_datum;
			unsigned int blocksize =
			    gnutls_cipher_get_block_size(cipher);
			unsigned int keylen = key_data[1];
			unsigned int ofs = 2;

			if (keylen & 0x80) {
				int lenlen = keylen & 0x7f;
				keylen = 0;

				if (lenlen > 3) {
					gnutls_assert();
					goto fail;
				}

				while (lenlen) {
					keylen <<= 8;
					keylen |= key_data[ofs++];
					lenlen--;
				}
			}
			keylen += ofs;

			/* If there appears to be more padding than required, fail */
			if (key_data_size - keylen > blocksize) {
				gnutls_assert();
				goto fail;
			}

			/* If the padding bytes aren't all equal to the amount of padding, fail */
			ofs = keylen;
			while (ofs < key_data_size) {
				if (key_data[ofs] !=
				    key_data_size - keylen) {
					gnutls_assert();
					goto fail;
				}
				ofs++;
			}

			key_datum.data = key_data;
			key_datum.size = keylen;
			ret =
			    gnutls_x509_privkey_import(key, &key_datum,
						       GNUTLS_X509_FMT_DER);
			if (ret == 0)
				goto out;
		}
	      fail:
		ret = GNUTLS_E_DECRYPTION_FAILED;
		goto out;
	}
      out:
	zeroize_key(key_data, key_data_size);
	gnutls_free(key_data);
      out_enc_key:
	_gnutls_free_key_datum(&enc_key);
      out_b64:
	gnutls_free(b64_data.data);
      out_salt:
	gnutls_free(salt.data);
	return ret;
}
Exemple #8
0
static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * out,
                                  const gnutls_pk_params_st * priv,
                                  const gnutls_pk_params_st * pub)
{
  int ret;

  switch (algo)
    {
    case GNUTLS_PK_EC:
      {
        ecc_key ecc_pub, ecc_priv;
        int curve = priv->flags;
        unsigned long sz;

        out->data = NULL;

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

        _ecc_params_to_pubkey(pub, &ecc_pub);
        _ecc_params_to_privkey(priv, &ecc_priv);
        
        if (ecc_projective_check_point(&ecc_pub.pubkey, pub->params[ECC_B], pub->params[ECC_PRIME]) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }

        sz = ECC_BUF_SIZE;
        out->data = gnutls_malloc(sz);
        if (out->data == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto ecc_cleanup;
          }

        ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, &sz);
        if (ret != 0)
          ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

ecc_cleanup:
        _ecc_params_clear(&ecc_pub);
        _ecc_params_clear(&ecc_priv);

        if (ret < 0)
          {
            gnutls_free(out->data);
            return ret;
          }

        out->size = sz;
        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
Exemple #9
0
/* Format: 
 *      1 byte the credentials type
 *      4 bytes the size of the whole structure
 *        DH stuff
 *      2 bytes the size of secret key in bits
 *      4 bytes the size of the prime
 *      x bytes the prime
 *      4 bytes the size of the generator
 *      x bytes the generator
 *      4 bytes the size of the public key
 *      x bytes the public key
 *        RSA stuff
 *      4 bytes the size of the modulus
 *      x bytes the modulus
 *      4 bytes the size of the exponent
 *      x bytes the exponent
 *        CERTIFICATES
 *      4 bytes the length of the certificate list
 *      4 bytes the size of first certificate
 *      x bytes the certificate
 *       and so on...
 */
static int
pack_certificate_auth_info (gnutls_session_t session,
			    gnutls_datum_t * packed_session)
{
  unsigned int pos = 0, i;
  int cert_size, pack_size;
  cert_auth_info_t info = _gnutls_get_auth_info (session);


  if (info == NULL && session->key->auth_info_size != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (info)
    {
      cert_size = 4;

      for (i = 0; i < info->ncerts; i++)
	cert_size += 4 + info->raw_certificate_list[i].size;

      pack_size = 2 + 4 + info->dh.prime.size +
	4 + info->dh.generator.size + 4 + info->dh.public_key.size +
	4 + info->rsa_export.modulus.size +
	4 + info->rsa_export.exponent.size + cert_size;
    }
  else
    pack_size = 0;

  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);

  /* calculate the size and allocate the data.
   */
  packed_session->data =
    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);

  if (packed_session->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
  pos += 4 + PACK_HEADER_SIZE;


  if (pack_size > 0)
    {

      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
      pos += 2;

      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
      pos += 4 + info->dh.prime.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
      pos += 4 + info->dh.generator.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
      pos += 4 + info->dh.public_key.size;

      _gnutls_write_datum32 (&packed_session->data[pos],
			     info->rsa_export.modulus);
      pos += 4 + info->rsa_export.modulus.size;
      _gnutls_write_datum32 (&packed_session->data[pos],
			     info->rsa_export.exponent);
      pos += 4 + info->rsa_export.exponent.size;

      _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]);
      pos += 4;

      for (i = 0; i < info->ncerts; i++)
	{
	  _gnutls_write_datum32 (&packed_session->data[pos],
				 info->raw_certificate_list[i]);
	  pos += sizeof (uint32_t) + info->raw_certificate_list[i].size;
	}
    }

  return 0;
}
Exemple #10
0
static gnutls_datum_t
wrap_db_fetch (void *dbf, gnutls_datum_t key)
{
  gnutls_datum_t res = { NULL, 0 };
  int i;

  if (debug)
    success ("resume db fetch... (%d)\n", key.size);
  if (debug)
    {
      unsigned int i;
      printf ("key:\n");
      for (i = 0; i < key.size; i++)
        {
          printf ("%02x ", key.data[i] & 0xFF);
          if ((i + 1) % 16 == 0)
            printf ("\n");
        }
      printf ("\n");
    }

  if (cache_db == NULL)
    return res;

  for (i = 0; i < TLS_SESSION_CACHE; i++)
    {
      if (key.size == cache_db[i].session_id_size &&
          memcmp (key.data, cache_db[i].session_id, key.size) == 0)
        {
          if (debug)
            success ("resume db fetch... return info\n");

          res.size = cache_db[i].session_data_size;

          res.data = gnutls_malloc (res.size);
          if (res.data == NULL)
            return res;

          memcpy (res.data, cache_db[i].session_data, res.size);

          if (debug)
            {
              unsigned int i;
              printf ("data:\n");
              for (i = 0; i < res.size; i++)
                {
                  printf ("%02x ", res.data[i] & 0xFF);
                  if ((i + 1) % 16 == 0)
                    printf ("\n");
                }
              printf ("\n");
            }

          return res;
        }
    }

  if (debug)
    success ("resume db fetch... NOT FOUND\n");
  return res;
}
Exemple #11
0
static int
server_recv(gnutls_session_t session,
	    status_request_ext_st * priv,
	    const uint8_t * data, size_t size)
{
	size_t i;
	ssize_t data_size = size;

	/* minimum message is type (1) + responder_id_list (2) +
	   request_extension (2) = 5 */
	if (data_size < 5)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	/* We ignore non-ocsp CertificateStatusType.  The spec is unclear
	   what should be done. */
	if (data[0] != 0x01) {
		gnutls_assert();
		_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
				      session, data[0]);
		return 0;
	}
	DECR_LEN(data_size, 1);
	data++;

	priv->responder_id_size = _gnutls_read_uint16(data);

	DECR_LEN(data_size, 2);
	data += 2;

	if (data_size <= (ssize_t) (priv->responder_id_size * 2))
		return
		    gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);

	priv->responder_id = gnutls_malloc(priv->responder_id_size
					   * sizeof(*priv->responder_id));
	if (priv->responder_id == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	for (i = 0; i < priv->responder_id_size; i++) {
		size_t l;

		DECR_LEN(data_size, 2);

		l = _gnutls_read_uint16(data);
		data += 2;

		DECR_LEN(data_size, l);

		priv->responder_id[i].data = gnutls_malloc(l);
		if (priv->responder_id[i].data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memcpy(priv->responder_id[i].data, data, l);
		priv->responder_id[i].size = l;

		data += l;
	}

	return 0;
}
Exemple #12
0
/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, 
 * which holds them. If raw is non null then the raw decoded
 * data are copied (they are locally allocated) there.
 */
static int
_decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
                           gnutls_datum_t * raw)
{
  char oid[MAX_OID_SIZE];
  ASN1_TYPE c2;
  opaque *tmp = NULL;
  int tmp_size, len, result;

  len = sizeof (oid) - 1;
  result = asn1_read_value (pkcs7, "contentType", oid, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (strcmp (oid, SIGNED_DATA_OID) != 0)
    {
      gnutls_assert ();
      _gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid);
      return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
    }

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  /* the Signed-data has been created, so
   * decode them.
   */
  tmp_size = 0;
  result = asn1_read_value (pkcs7, "content", NULL, &tmp_size);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  tmp = gnutls_malloc (tmp_size);
  if (tmp == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  result = asn1_read_value (pkcs7, "content", tmp, &tmp_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* tmp, tmp_size hold the data and the size of the CertificateSet structure
   * actually the ANY stuff.
   */

  /* Step 1. In case of a signed structure extract certificate set.
   */

  result = asn1_der_decoding (&c2, tmp, tmp_size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (raw == NULL)
    {
      gnutls_free (tmp);
    }
  else
    {
      raw->data = tmp;
      raw->size = tmp_size;
    }

  *sdata = c2;

  return 0;

cleanup:
  if (c2)
    asn1_delete_structure (&c2);
  gnutls_free (tmp);
  return result;
}
Exemple #13
0
/* If the psk flag is set, then an empty psk_identity_hint will
 * be inserted */
int
_gnutls_dh_common_print_server_kx (gnutls_session_t session,
				   mpi_t g, mpi_t p, opaque ** data, int psk)
{
  mpi_t x, X;
  size_t n_X, n_g, n_p;
  int ret, data_size, pos;
  uint8_t *pdata;

  X = gnutls_calc_dh_secret (&x, g, p);
  if (X == NULL || x == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  session->key->dh_secret = x;
  _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));

  _gnutls_mpi_print (NULL, &n_g, g);
  _gnutls_mpi_print (NULL, &n_p, p);
  _gnutls_mpi_print (NULL, &n_X, X);

  data_size = n_g + n_p + n_X + 6;
  if (psk != 0)
    data_size += 2;

  (*data) = gnutls_malloc (data_size);
  if (*data == NULL)
    {
      _gnutls_mpi_release (&X);
      return GNUTLS_E_MEMORY_ERROR;
    }

  pos = 0;
  pdata = *data;

  if (psk != 0)
    {
      _gnutls_write_uint16 (0, &pdata[pos]);
      pos += 2;
    }

  _gnutls_mpi_print (&pdata[pos + 2], &n_p, p);
  _gnutls_write_uint16 (n_p, &pdata[pos]);

  pos += n_p + 2;

  _gnutls_mpi_print (&pdata[pos + 2], &n_g, g);
  _gnutls_write_uint16 (n_g, &pdata[pos]);

  pos += n_g + 2;

  _gnutls_mpi_print (&pdata[pos + 2], &n_X, X);
  _gnutls_mpi_release (&X);

  _gnutls_write_uint16 (n_X, &pdata[pos]);

  ret = data_size;

  return ret;
}
Exemple #14
0
int
_gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque ** data)
{
  mpi_t x = NULL, X = NULL;
  size_t n_X;
  int ret;

  *data = NULL;

  X = gnutls_calc_dh_secret (&x, session->key->client_g,
			     session->key->client_p);
  if (X == NULL || x == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));

  _gnutls_mpi_print (NULL, &n_X, X);
  (*data) = gnutls_malloc (n_X + 2);
  if (*data == NULL)
    {
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  _gnutls_mpi_print (&(*data)[2], &n_X, X);
  _gnutls_mpi_release (&X);

  _gnutls_write_uint16 (n_X, &(*data)[0]);

  /* calculate the key after calculating the message */
  session->key->KEY =
    gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p);

  _gnutls_mpi_release (&x);
  if (session->key->KEY == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

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

  /* THESE SHOULD BE DISCARDED */
  _gnutls_mpi_release (&session->key->client_Y);
  _gnutls_mpi_release (&session->key->client_p);
  _gnutls_mpi_release (&session->key->client_g);

  if (_gnutls_cipher_suite_get_kx_algo
      (&session->security_parameters.current_cipher_suite)
      != GNUTLS_KX_DHE_PSK)
    {
      ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
    }
  else				/* In DHE_PSK the key is set differently */
    {
      gnutls_datum tmp_dh_key;
      ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto error;
	}

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

    }

  _gnutls_mpi_release (&session->key->KEY);

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

  return n_X + 2;

error:
  _gnutls_mpi_release (&x);
  _gnutls_mpi_release (&X);
  gnutls_free (*data);
  *data = NULL;
  return ret;
}
Exemple #15
0
/* Reads a certificate key from a token.
 */
static int
read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *url)
{
	int ret;
	gnutls_x509_crt_t crt = NULL;
	gnutls_pcert_st *ccert = NULL;
	gnutls_str_array_t names;
	gnutls_datum_t t = {NULL, 0};
	unsigned i, count = 0;

	_gnutls_str_array_init(&names);

	ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN);
	if (ccert == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret = gnutls_x509_crt_init(&crt);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (res->pin.cb)
		gnutls_x509_crt_set_pin_function(crt, res->pin.cb,
						 res->pin.data);

	ret = gnutls_x509_crt_import_url(crt, url, 0);
	if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
		ret =
		    gnutls_x509_crt_import_url(crt, url,
					       GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_get_x509_name(crt, &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Try to load the whole certificate chain from the PKCS #11 token */
	for (i=0;i<MAX_PKCS11_CERT_CHAIN;i++) {
		ret = gnutls_x509_crt_check_issuer(crt, crt);
		if (i > 0 && ret != 0) {
			/* self signed */
			break;
		}

		ret = gnutls_pcert_import_x509(&ccert[i], crt, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		count++;

		ret = _gnutls_get_raw_issuer(url, crt, &t, 0);
		if (ret < 0)
			break;

		gnutls_x509_crt_deinit(crt);
		crt = NULL;
		ret = gnutls_x509_crt_init(&crt);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_x509_crt_import(crt, &t, GNUTLS_X509_FMT_DER);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		gnutls_free(t.data);
	}

	ret = _gnutls_certificate_credential_append_keypair(res, key, names, ccert, count);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (crt != NULL)
		gnutls_x509_crt_deinit(crt);

	return 0;
cleanup:
	if (crt != NULL)
		gnutls_x509_crt_deinit(crt);
	gnutls_free(t.data);
	_gnutls_str_array_clear(&names);
	gnutls_free(ccert);
	return ret;
}
Exemple #16
0
/* Format: 
 *      1 byte the credentials type
 *      4 bytes the size of the whole structure
 *      4 bytes the size of the PSK username (x)
 *      x bytes the PSK username
 *      2 bytes the size of secret key in bits
 *      4 bytes the size of the prime
 *      x bytes the prime
 *      4 bytes the size of the generator
 *      x bytes the generator
 *      4 bytes the size of the public key
 *      x bytes the public key
 */
static int
pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
{
  psk_auth_info_t info;
  int pack_size, username_size = 0, pos;

  info = _gnutls_get_auth_info (session);

  if (info == NULL && session->key->auth_info_size != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (info)
    {
      username_size = strlen (info->username) + 1;	/* include the terminating null */
      pack_size = username_size +
	2 + 4 * 3 + info->dh.prime.size + info->dh.generator.size +
	info->dh.public_key.size;
    }
  else
    pack_size = 0;

  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);

  /* calculate the size and allocate the data.
   */
  packed_session->data =
    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);

  if (packed_session->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  pos = 0;

  packed_session->data[pos] = GNUTLS_CRD_PSK;
  pos++;

  _gnutls_write_uint32 (pack_size, &packed_session->data[pos]);
  pos += 4;


  if (pack_size > 0)
    {
      _gnutls_write_uint32 (username_size, &packed_session->data[pos]);
      pos += 4;

      memcpy (&packed_session->data[pos], info->username, username_size);
      pos += username_size;

      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
      pos += 2;

      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
      pos += 4 + info->dh.prime.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
      pos += 4 + info->dh.generator.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
      pos += 4 + info->dh.public_key.size;

    }


  return 0;
}
Exemple #17
0
/**
 * gnutls_certificate_set_x509_key:
 * @res: is a #gnutls_certificate_credentials_t type.
 * @cert_list: contains a certificate list (path) for the specified private key
 * @cert_list_size: holds the size of the certificate list
 * @key: is a #gnutls_x509_privkey_t key
 *
 * This function sets a certificate/private key pair in the
 * gnutls_certificate_credentials_t type.  This function may be
 * called more than once, in case multiple keys/certificates exist for
 * the server.  For clients that wants to send more than their own end
 * entity certificate (e.g., also an intermediate CA cert) then put
 * the certificate chain in @cert_list.
 *
 * Note that the certificates and keys provided, can be safely deinitialized
 * after this function is called.
 *
 * If that function fails to load the @res type is at an undefined state, it must
 * not be reused to load other keys or certificates.
 *
 * Note that, this function by default returns zero on success and a negative value on error.
 * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
 * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
 *
 * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
 *
 * Since: 2.4.0
 **/
int
gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res,
				gnutls_x509_crt_t * cert_list,
				int cert_list_size,
				gnutls_x509_privkey_t key)
{
	int ret;
	gnutls_privkey_t pkey;
	gnutls_pcert_st *pcerts = NULL;
	gnutls_str_array_t names;

	_gnutls_str_array_init(&names);

	/* this should be first
	 */
	ret = gnutls_privkey_init(&pkey);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (res->pin.cb)
		gnutls_privkey_set_pin_function(pkey, res->pin.cb,
						res->pin.data);

	ret =
	    gnutls_privkey_import_x509(pkey, key,
				       GNUTLS_PRIVKEY_IMPORT_COPY);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* load certificates */
	pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size);
	if (pcerts == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_get_x509_name(cert_list[0], &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
		gnutls_pcert_import_x509_list(pcerts, cert_list, (unsigned int*)&cert_list_size,
					      GNUTLS_X509_CRT_LIST_SORT);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_certificate_credential_append_keypair(res, pkey, names, pcerts,
						   cert_list_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	res->ncerts++;

	/* after this point we do not deinitialize anything on failure to avoid
	 * double freeing. We intentionally keep everything as the credentials state
	 * is documented to be on undefined state. */
	if ((ret = _gnutls_check_key_cert_match(res)) < 0) {
		gnutls_assert();
		return ret;
	}

	CRED_RET_SUCCESS(res);

      cleanup:
	gnutls_free(pcerts);
	_gnutls_str_array_clear(&names);
	return ret;
}
Exemple #18
0
static int
gen_rsa_export_server_kx (gnutls_session_t session, opaque ** data)
{
  gnutls_rsa_params_t rsa_params;
  const bigint_t *rsa_mpis;
  size_t n_e, n_m;
  uint8_t *data_e, *data_m;
  int ret = 0, data_size;
  gnutls_cert *apr_cert_list;
  gnutls_privkey *apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature, ddata;
  cert_auth_info_t info;
  gnutls_certificate_credentials_t cred;

  cred = (gnutls_certificate_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* find the appropriate certificate */
  if ((ret =
       _gnutls_get_selected_cert (session, &apr_cert_list,
				  &apr_cert_list_length, &apr_pkey)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* abort sending this message if we have a certificate
   * of 512 bits or less.
   */
  if (apr_pkey && _gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  rsa_params =
    _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
					session);
  rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params);
  if (rsa_mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
    }

  if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
				    sizeof (cert_auth_info_st), 0)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);

  _gnutls_mpi_print (rsa_mpis[0], NULL, &n_m);
  _gnutls_mpi_print (rsa_mpis[1], NULL, &n_e);

  (*data) = gnutls_malloc (n_e + n_m + 4);
  if (*data == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }

  data_m = &(*data)[0];
  _gnutls_mpi_print (rsa_mpis[0], &data_m[2], &n_m);

  _gnutls_write_uint16 (n_m, data_m);

  data_e = &data_m[2 + n_m];
  _gnutls_mpi_print (rsa_mpis[1], &data_e[2], &n_e);

  _gnutls_write_uint16 (n_e, data_e);

  data_size = n_m + n_e + 4;


  /* Generate the signature. */

  ddata.data = *data;
  ddata.size = data_size;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
	   _gnutls_tls_sign_params (session, &apr_cert_list[0],
				    apr_pkey, &ddata, &signature)) < 0)
	{
	  gnutls_assert ();
	  gnutls_free (*data);
	  *data = NULL;
	  return ret;
	}
    }
  else
    {
      gnutls_assert ();
      return data_size;		/* do not put a signature - ILLEGAL! */
    }

  *data = gnutls_realloc_fast (*data, data_size + signature.size + 2);
  if (*data == NULL)
    {
      _gnutls_free_datum (&signature);
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_write_datum16 (&((*data)[data_size]), signature);
  data_size += signature.size + 2;

  _gnutls_free_datum (&signature);

  return data_size;
}
Exemple #19
0
/**
 * gnutls_x509_trust_list_iter_get_ca:
 * @list: The structure of the list
 * @iter: A pointer to an iterator (initially the iterator should be %NULL)
 * @crt: where the certificate will be copied
 *
 * This function obtains a certificate in the trust list and advances the
 * iterator to the next certificate. The certificate returned in @crt must be
 * deallocated with gnutls_x509_crt_deinit().
 *
 * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
 * is returned and the iterator is reset.
 *
 * After use, the iterator must be deinitialized usin
 *  gnutls_x509_trust_list_iter_deinit().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int
gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list,
                                   gnutls_x509_trust_list_iter_t *iter,
                                   gnutls_x509_crt_t *crt)
{
	int ret;

	/* initialize iterator */
	if (*iter == NULL) {
		*iter = gnutls_malloc(sizeof (struct gnutls_x509_trust_list_iter));
		if (*iter == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		(*iter)->node_index = 0;
		(*iter)->ca_index = 0;

#ifdef ENABLE_PKCS11
		(*iter)->pkcs11_list = NULL;
		(*iter)->pkcs11_size = 0;
		(*iter)->pkcs11_index = 0;
#endif

		/* Advance iterator to the first valid entry */
		if (list->node[0].trusted_ca_size == 0) {
			ret = advance_iter(list, *iter);
			if (ret != 0) {
				gnutls_x509_trust_list_iter_deinit(*iter);
				*iter = NULL;

				*crt = NULL;
				return gnutls_assert_val(ret);
			}
		}
	}

	/* obtain the certificate at the current iterator position */
	if ((*iter)->node_index < list->size) {
		ret = gnutls_x509_crt_init(crt);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]);
		if (ret < 0) {
			gnutls_x509_crt_deinit(*crt);
			return gnutls_assert_val(ret);
		}
	}
#ifdef ENABLE_PKCS11
	else if ( (*iter)->pkcs11_index < (*iter)->pkcs11_size) {
		ret = gnutls_x509_crt_init(crt);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret = gnutls_x509_crt_import_pkcs11(*crt, (*iter)->pkcs11_list[(*iter)->pkcs11_index]);
		if (ret < 0) {
			gnutls_x509_crt_deinit(*crt);
			return gnutls_assert_val(ret);
		}
	}
#endif

	else {
		/* iterator is at end */
		gnutls_x509_trust_list_iter_deinit(*iter);
		*iter = NULL;

		*crt = NULL;
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
	}

	/* Move iterator to the next position.
	 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned if the iterator
	 * has been moved to the end position. That is okay, we return the
	 * certificate that we read and when this function is called again we
	 * report GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE to our caller. */
	ret = advance_iter(list, *iter);
	if (ret	< 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
		gnutls_x509_crt_deinit(*crt);
		*crt = NULL;

		return gnutls_assert_val(ret);
	}

	return 0;
}
Exemple #20
0
/** Private function which generate private keys and certificates.
 *
 * @return 1 if keys were successfully generated, 0 otherwise
 */
static userpref_error_t userpref_gen_keys_and_cert(void)
{
	userpref_error_t ret = USERPREF_E_SSL_ERROR;

	gnutls_x509_privkey_t root_privkey;
	gnutls_x509_crt_t root_cert;
	gnutls_x509_privkey_t host_privkey;
	gnutls_x509_crt_t host_cert;

	gnutls_global_deinit();
	gnutls_global_init();

	//use less secure random to speed up key generation
	gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM);

	gnutls_x509_privkey_init(&root_privkey);
	gnutls_x509_privkey_init(&host_privkey);

	gnutls_x509_crt_init(&root_cert);
	gnutls_x509_crt_init(&host_cert);

	/* generate root key */
	gnutls_x509_privkey_generate(root_privkey, GNUTLS_PK_RSA, 2048, 0);
	gnutls_x509_privkey_generate(host_privkey, GNUTLS_PK_RSA, 2048, 0);

	/* generate certificates */
	gnutls_x509_crt_set_key(root_cert, root_privkey);
	gnutls_x509_crt_set_serial(root_cert, "\x00", 1);
	gnutls_x509_crt_set_version(root_cert, 3);
	gnutls_x509_crt_set_ca_status(root_cert, 1);
	gnutls_x509_crt_set_activation_time(root_cert, time(NULL));
	gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
	gnutls_x509_crt_sign(root_cert, root_cert, root_privkey);

	gnutls_x509_crt_set_key(host_cert, host_privkey);
	gnutls_x509_crt_set_serial(host_cert, "\x00", 1);
	gnutls_x509_crt_set_version(host_cert, 3);
	gnutls_x509_crt_set_ca_status(host_cert, 0);
	gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE);
	gnutls_x509_crt_set_activation_time(host_cert, time(NULL));
	gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
	gnutls_x509_crt_sign(host_cert, root_cert, root_privkey);

	/* export to PEM format */
	size_t root_key_export_size = 0;
	size_t host_key_export_size = 0;
	gnutls_datum_t root_key_pem = { NULL, 0 };
	gnutls_datum_t host_key_pem = { NULL, 0 };

	gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);
	gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size);

	root_key_pem.data = gnutls_malloc(root_key_export_size);
	host_key_pem.data = gnutls_malloc(host_key_export_size);

	gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, root_key_pem.data, &root_key_export_size);
	root_key_pem.size = root_key_export_size;
	gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, host_key_pem.data, &host_key_export_size);
	host_key_pem.size = host_key_export_size;

	size_t root_cert_export_size = 0;
	size_t host_cert_export_size = 0;
	gnutls_datum_t root_cert_pem = { NULL, 0 };
	gnutls_datum_t host_cert_pem = { NULL, 0 };

	gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);
	gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size);

	root_cert_pem.data = gnutls_malloc(root_cert_export_size);
	host_cert_pem.data = gnutls_malloc(host_cert_export_size);

	gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_export_size);
	root_cert_pem.size = root_cert_export_size;
	gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
	host_cert_pem.size = host_cert_export_size;

	if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
		NULL != host_cert_pem.data && 0 != host_cert_pem.size)
		ret = USERPREF_E_SUCCESS;

	/* store values in config file */
	userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem);

	gnutls_free(root_key_pem.data);
	gnutls_free(root_cert_pem.data);
	gnutls_free(host_key_pem.data);
	gnutls_free(host_cert_pem.data);

	//restore gnutls env
	gnutls_global_deinit();
	gnutls_global_init();

	return ret;
}
Exemple #21
0
int
_gnutls_x509_crq_set_extension(gnutls_x509_crq_t crq,
                               const char *ext_id,
                               const gnutls_datum_t * ext_data,
                               unsigned int critical)
{
    unsigned char *extensions = NULL;
    size_t extensions_size = 0;
    gnutls_datum_t der;
    ASN1_TYPE c2;
    int result;

    result =
        gnutls_x509_crq_get_attribute_by_oid(crq,
                "1.2.840.113549.1.9.14",
                0, NULL,
                &extensions_size);
    if (result == GNUTLS_E_SHORT_MEMORY_BUFFER) {
        extensions = gnutls_malloc(extensions_size);
        if (extensions == NULL) {
            gnutls_assert();
            return GNUTLS_E_MEMORY_ERROR;
        }

        result = gnutls_x509_crq_get_attribute_by_oid(crq,
                 "1.2.840.113549.1.9.14",
                 0,
                 extensions,
                 &extensions_size);
    }
    if (result < 0) {
        if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
            extensions_size = 0;
        } else {
            gnutls_assert();
            gnutls_free(extensions);
            return result;
        }
    }

    result =
        asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extensions",
                            &c2);
    if (result != ASN1_SUCCESS) {
        gnutls_assert();
        gnutls_free(extensions);
        return _gnutls_asn2err(result);
    }

    if (extensions_size > 0) {
        result =
            asn1_der_decoding(&c2, extensions, extensions_size,
                              NULL);
        gnutls_free(extensions);
        if (result != ASN1_SUCCESS) {
            gnutls_assert();
            asn1_delete_structure(&c2);
            return _gnutls_asn2err(result);
        }
    }

    result = set_extension(c2, "", ext_id, ext_data, critical);
    if (result < 0) {
        gnutls_assert();
        asn1_delete_structure(&c2);
        return result;
    }

    result = _gnutls_x509_der_encode(c2, "", &der, 0);

    asn1_delete_structure(&c2);

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

    result =
        gnutls_x509_crq_set_attribute_by_oid(crq,
                "1.2.840.113549.1.9.14",
                der.data, der.size);
    gnutls_free(der.data);
    if (result < 0) {
        gnutls_assert();
        return result;
    }


    return 0;
}
Exemple #22
0
static gnutls_pubkey_t
create_rsa_from_modulus(unsigned char *modulus, unsigned int modulus_len,
                        uint32_t exponent)
{
    unsigned char exp_array[4];
    uint32_t exponent_no = htonl(exponent);
    gnutls_pubkey_t rsa = NULL;
    gnutls_datum_t mod;
    gnutls_datum_t exp = {
        .data = exp_array,
        .size = sizeof(exp_array),
    };
    int err;

    memcpy(exp_array, &exponent_no, sizeof(exp_array));

    err = gnutls_pubkey_init(&rsa);
    if (err < 0) {
        fprintf(stderr, "Could not initialized public key structure : %s\n",
                gnutls_strerror(err));
        return NULL;
    }

    mod.data = modulus;
    mod.size = modulus_len;

    err = gnutls_pubkey_import_rsa_raw(rsa, &mod, &exp);
    if (err < 0) {
        fprintf(stderr, "Could not set modulus and exponent on RSA key : %s\n",
                gnutls_strerror(err));
        gnutls_pubkey_deinit(rsa);
        rsa = NULL;
    }

    return rsa;
}

static int
asn_init()
{
    static bool inited;
    int err;

    if (inited)
        return ASN1_SUCCESS;

    err = asn1_array2tree(tpm_asn1_tab, &_tpm_asn, NULL);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "array2tree error: %d", err);
        goto cleanup;
    }

    inited = true;

cleanup:

    return err;
}

static int
create_tpm_manufacturer_info(const char *manufacturer,
                             const char *tpm_model,
                             const char *tpm_version,
                             gnutls_datum_t *asn1)
{
    ASN1_TYPE at = ASN1_TYPE_EMPTY;
    int err;

    err = asn_init();
    if (err != ASN1_SUCCESS) {
        goto cleanup;
    }

    err = asn1_create_element(_tpm_asn, "TPM.TPMManufacturerInfo", &at);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "asn1_create_element error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "tpmManufacturer.id", "2.23.133.2.1", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "1. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "tpmManufacturer.manufacturer",
                           manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "2. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    err = asn1_write_value(at, "tpmModel.id", "2.23.133.2.2", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "3. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "tpmModel.model", manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "4. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    err = asn1_write_value(at, "tpmVersion.id", "2.23.133.2.3", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "5. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "tpmVersion.version", manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "6. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    /* determine needed size of byte array */
    asn1->size = 0;
    err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL);
    if (err != ASN1_MEM_ERROR) {
        fprintf(stderr, "1. asn1_der_coding error: %d\n", err);
        goto cleanup;
    }
    //fprintf(stderr, "size=%d\n", asn1->size);
    asn1->data = gnutls_malloc(asn1->size + 16);
    err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL);

    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "2. asn1_der_coding error: %d\n", err);
        gnutls_free(asn1->data);
        asn1->data = NULL;
        goto cleanup;
    }

#if 0
    fprintf(stderr, "size=%d\n", asn1->size);
    unsigned int i = 0;
    for (i = 0; i < asn1->size; i++) {
        fprintf(stderr, "%02x ", asn1->data[i]);
    }
    fprintf(stderr, "\n");
#endif

 cleanup:    
    asn1_delete_structure(&at);
    
    return err;
}
Exemple #23
0
/* Reads and returns the PK algorithm of the given certificate-like
 * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo".
 */
int
_gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name,
			       unsigned int *bits)
{
  int result;
  opaque *str = NULL;
  int algo;
  char oid[64];
  int len;
  mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
  char name[128];

  _gnutls_str_cpy (name, sizeof (name), src_name);
  _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm");

  len = sizeof (oid);
  result = asn1_read_value (src, name, oid, &len);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  algo = _gnutls_x509_oid2pk_algorithm (oid);

  if (bits == NULL)
    {
      gnutls_free (str);
      return algo;
    }

  /* Now read the parameters' bits 
   */
  _gnutls_str_cpy (name, sizeof (name), src_name);
  _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");

  len = 0;
  result = asn1_read_value (src, name, NULL, &len);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (len % 8 != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_CERTIFICATE_ERROR;
    }

  len /= 8;

  str = gnutls_malloc (len);
  if (str == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_str_cpy (name, sizeof (name), src_name);
  _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");

  result = asn1_read_value (src, name, str, &len);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      gnutls_free (str);
      return _gnutls_asn2err (result);
    }

  len /= 8;

  if (algo == GNUTLS_PK_RSA)
    {
      if ((result = _gnutls_x509_read_rsa_params (str, len, params)) < 0)
	{
	  gnutls_assert ();
	  return result;
	}

      bits[0] = _gnutls_mpi_get_nbits (params[0]);

      _gnutls_mpi_release (&params[0]);
      _gnutls_mpi_release (&params[1]);
    }

  if (algo == GNUTLS_PK_DSA)
    {

      if ((result = _gnutls_x509_read_dsa_pubkey (str, len, params)) < 0)
	{
	  gnutls_assert ();
	  return result;
	}

      bits[0] = _gnutls_mpi_get_nbits (params[3]);

      _gnutls_mpi_release (&params[3]);
    }

  gnutls_free (str);
  return algo;
}
Exemple #24
0
static int
create_platf_manufacturer_info(const char *manufacturer,
                               const char *platf_model,
                               const char *platf_version,
                               gnutls_datum_t *asn1)
{
    ASN1_TYPE at = ASN1_TYPE_EMPTY;
    int err;

    err = asn_init();
    if (err != ASN1_SUCCESS) {
        goto cleanup;
    }

    err = asn1_create_element(_tpm_asn, "TPM.PlatformManufacturerInfo", &at);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "asn1_create_element error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "platformManufacturer.id", "2.23.133.2.4", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b1. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "platformManufacturer.manufacturer",
                           manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b2. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    err = asn1_write_value(at, "platformModel.id", "2.23.133.2.5", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b3. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "platformModel.model", manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b4. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    err = asn1_write_value(at, "platformVersion.id", "2.23.133.2.6", 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b5. asn1_write_value error: %d\n", err);
        goto cleanup;
    }

    err = asn1_write_value(at, "platformVersion.version", manufacturer, 0);
    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b6. asn1_write_value error: %d\n", err);
        goto cleanup;
    }
    
    /* determine needed size of byte array */
    asn1->size = 0;
    err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL);
    if (err != ASN1_MEM_ERROR) {
        fprintf(stderr, "b1. asn1_der_coding error: %d\n", err);
        goto cleanup;
    }
    //fprintf(stderr, "size=%d\n", asn1->size);
    asn1->data = gnutls_malloc(asn1->size + 16);
    err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL);

    if (err != ASN1_SUCCESS) {
        fprintf(stderr, "b2. asn1_der_coding error: %d\n", err);
        gnutls_free(asn1->data);
        asn1->data = NULL;
        goto cleanup;
    }

#if 0
    fprintf(stderr, "size=%d\n", asn1->size);
    unsigned int i = 0;
    for (i = 0; i < asn1->size; i++) {
        fprintf(stderr, "%02x ", asn1->data[i]);
    }
    fprintf(stderr, "\n");
#endif

 cleanup:    
    asn1_delete_structure(&at);
    
    return err;
}
int
proc_rsa_export_client_kx (gnutls_session_t session, uint8_t * data,
                           size_t _data_size)
{
  gnutls_datum_t plaintext;
  gnutls_datum_t ciphertext;
  int ret, dsize;
  gnutls_pk_params_st *params;
  int randomize_key = 0;
  ssize_t data_size = _data_size;

  if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
    {
      /* SSL 3.0 
       */
      ciphertext.data = data;
      ciphertext.size = data_size;
    }
  else
    {
      /* TLS 1.0
       */
      DECR_LEN (data_size, 2);
      ciphertext.data = &data[2];
      dsize = _gnutls_read_uint16 (data);

      if (dsize != data_size)
        {
          gnutls_assert ();
          return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
        }
      ciphertext.size = dsize;
    }

  ret = _gnutls_get_private_rsa_params (session, &params);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, 2);     /* btype==2 */

  if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
    {
      /* In case decryption fails then don't inform
       * the peer. Just use a random key. (in order to avoid
       * attack against pkcs-1 formating).
       */
      gnutls_assert ();
      _gnutls_audit_log (session, "auth_rsa: Possible PKCS #1 format attack\n");
      randomize_key = 1;
    }
  else
    {
      /* If the secret was properly formatted, then
       * check the version number.
       */
      if (_gnutls_get_adv_version_major (session) != plaintext.data[0]
          || _gnutls_get_adv_version_minor (session) != plaintext.data[1])
        {
          /* No error is returned here, if the version number check
           * fails. We proceed normally.
           * That is to defend against the attack described in the paper
           * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
           * Ondej Pokorny and Tomas Rosa.
           */
          gnutls_assert ();
          _gnutls_audit_log
            (session, "auth_rsa: Possible PKCS #1 version check format attack\n");
        }
    }

  if (randomize_key != 0)
    {
      session->key->key.size = GNUTLS_MASTER_SIZE;
      session->key->key.data = gnutls_malloc (session->key->key.size);
      if (session->key->key.data == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }

      /* we do not need strong random numbers here.
       */
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data,
                         session->key->key.size);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

    }
  else
    {
      session->key->key.data = plaintext.data;
      session->key->key.size = plaintext.size;
    }

  /* This is here to avoid the version check attack
   * discussed above.
   */
  session->key->key.data[0] = _gnutls_get_adv_version_major (session);
  session->key->key.data[1] = _gnutls_get_adv_version_minor (session);

  return 0;
}
Exemple #26
0
/* Reads a DER encoded certificate list from memory and stores it to a
 * gnutls_cert structure. Returns the number of certificates parsed.
 */
static int
parse_der_cert_mem(gnutls_certificate_credentials_t res,
		   gnutls_privkey_t key,
		   const void *input_cert, int input_cert_size)
{
	gnutls_datum_t tmp;
	gnutls_x509_crt_t crt;
	gnutls_pcert_st *ccert;
	int ret;
	gnutls_str_array_t names;

	_gnutls_str_array_init(&names);

	ccert = gnutls_malloc(sizeof(*ccert));
	if (ccert == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = gnutls_x509_crt_init(&crt);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	tmp.data = (uint8_t *) input_cert;
	tmp.size = input_cert_size;

	ret = gnutls_x509_crt_import(crt, &tmp, GNUTLS_X509_FMT_DER);
	if (ret < 0) {
		gnutls_assert();
		gnutls_x509_crt_deinit(crt);
		goto cleanup;
	}

	ret = _gnutls_get_x509_name(crt, &names);
	if (ret < 0) {
		gnutls_assert();
		gnutls_x509_crt_deinit(crt);
		goto cleanup;
	}

	ret = gnutls_pcert_import_x509(ccert, crt, 0);
	gnutls_x509_crt_deinit(crt);

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

	ret = _gnutls_certificate_credential_append_keypair(res, key, names, ccert, 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return ret;

      cleanup:
	_gnutls_str_array_clear(&names);
	gnutls_free(ccert);
	return ret;
}
Exemple #27
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 #28
0
/* Reads a base64 encoded certificate list from memory and stores it to
 * a gnutls_cert structure. Returns the number of certificate parsed.
 */
static int
parse_pem_cert_mem(gnutls_certificate_credentials_t res,
		   gnutls_privkey_t key,
		   const char *input_cert, int input_cert_size)
{
	int size;
	const char *ptr;
	gnutls_datum_t tmp;
	int ret, count, i;
	unsigned ncerts = 0;
	gnutls_pcert_st *pcerts = NULL;
	gnutls_str_array_t names;
	gnutls_x509_crt_t unsorted[DEFAULT_MAX_VERIFY_DEPTH];

	_gnutls_str_array_init(&names);

	/* move to the certificate
	 */
	ptr = memmem(input_cert, input_cert_size,
		     PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1);
	if (ptr == NULL)
		ptr = memmem(input_cert, input_cert_size,
			     PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1);

	if (ptr == NULL) {
		gnutls_assert();
		return GNUTLS_E_BASE64_DECODING_ERROR;
	}
	size = input_cert_size - (ptr - input_cert);

	count = 0;

	do {
		tmp.data = (void *) ptr;
		tmp.size = size;

		ret = gnutls_x509_crt_init(&unsorted[count]);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_x509_crt_import(unsorted[count], &tmp, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		count++;

		/* now we move ptr after the pem header
		 */
		ptr++;
		size--;

		/* find the next certificate (if any)
		 */

		if (size > 0) {
			char *ptr3;

			ptr3 =
			    memmem(ptr, size, PEM_CERT_SEP,
				   sizeof(PEM_CERT_SEP) - 1);
			if (ptr3 == NULL)
				ptr3 = memmem(ptr, size, PEM_CERT_SEP2,
					      sizeof(PEM_CERT_SEP2) - 1);

			ptr = ptr3;
			size = input_cert_size - (ptr - input_cert);
		} else
			ptr = NULL;

	}
	while (ptr != NULL && count < DEFAULT_MAX_VERIFY_DEPTH);

	ret =
	    _gnutls_get_x509_name(unsorted[0], &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count);
	if (pcerts == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ncerts = count;
	ret =
	    gnutls_pcert_import_x509_list(pcerts, unsorted, &ncerts, GNUTLS_X509_CRT_LIST_SORT);
	if (ret < 0) {
		gnutls_free(pcerts);
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_certificate_credential_append_keypair(res, key, names, pcerts, ncerts);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	for (i = 0; i < count; i++)
		gnutls_x509_crt_deinit(unsorted[i]);

	return ncerts;

      cleanup:
	_gnutls_str_array_clear(&names);
	for (i = 0; i < count; i++)
		gnutls_x509_crt_deinit(unsorted[i]);
	if (pcerts) {
		for (i = 0; i < count; i++)
			gnutls_pcert_deinit(&pcerts[i]);
		gnutls_free(pcerts);
	}
	return ret;
}
Exemple #29
0
/**
 * gnutls_pkcs11_copy_x509_crt:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: A certificate
 * @label: A name to be used for the stored data
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a certificate into a PKCS #11 token specified by
 * a URL. The certificate can be marked as trusted or not.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pkcs11_copy_x509_crt(const char *token_url,
			    gnutls_x509_crt_t crt, const char *label,
			    unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t der_size, id_size;
	uint8_t *der = NULL;
	uint8_t id[20];
	struct ck_attribute a[16];
	ck_object_class_t class = CKO_CERTIFICATE;
	ck_certificate_type_t type = CKC_X_509;
	ck_object_handle_t obj;
	int a_val;
	unsigned long category;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

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

	ret = pkcs11_url_to_info(token_url, &info);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	der_size = 0;
	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
				   &der_size);
	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		goto cleanup;
	}

	der = gnutls_malloc(der_size);
	if (der == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
				   &der_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	id_size = sizeof(id);
	ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
	if (ret < 0) {
	        id_size = sizeof(id);
		ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
		if (ret < 0) {
		  gnutls_assert();
		  goto cleanup;
                }
	}

	/* FIXME: copy key usage flags */

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);
	a[1].type = CKA_ID;
	a[1].value = id;
	a[1].value_len = id_size;
	a[2].type = CKA_VALUE;
	a[2].value = der;
	a[2].value_len = der_size;
	a[3].type = CKA_TOKEN;
	a[3].value = (void *) &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_CERTIFICATE_TYPE;
	a[4].value = &type;
	a[4].value_len = sizeof(type);

	a_val = 5;

	a[a_val].type = CKA_SUBJECT;
	a[a_val].value = crt->raw_dn.data;
	a[a_val].value_len = crt->raw_dn.size;
	a_val++;

	if (label) {
		a[a_val].type = CKA_LABEL;
		a[a_val].value = (void *) label;
		a[a_val].value_len = strlen(label);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
		category = 2;
		a[a_val].type = CKA_CERTIFICATE_CATEGORY;
		a[a_val].value = (void *) &category;
		a[a_val].value_len = sizeof(category);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
		a[a_val].type = CKA_TRUSTED;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		a_val++;

		a[a_val].type = CKA_PRIVATE;
		a[a_val].value = (void *) &fval;
		a[a_val].value_len = sizeof(fval);
		a_val++;
	} else {
		if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &tval;
			a[a_val].value_len = sizeof(tval);
			a_val++;
		} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &fval;
			a[a_val].value_len = sizeof(fval);
			a_val++;
		}
	}

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	gnutls_free(der);
	pkcs11_close_session(&sinfo);
	return ret;

}
Exemple #30
0
static void print_cert(gnutls_buffer_st * str, gnutls_openpgp_crt_t cert)
{
	int i, subkeys;
	int err;

	print_key_revoked(str, cert, -1);

	/* Version. */
	{
		int version = gnutls_openpgp_crt_get_version(cert);
		if (version < 0)
			addf(str, "error: get_version: %s\n",
			     gnutls_strerror(version));
		else
			addf(str, _("\tVersion: %d\n"), version);
	}

	/* ID. */
	print_key_id(str, cert, -1);

	print_key_fingerprint(str, cert);

	/* Names. */
	i = 0;
	do {
		char *dn;
		size_t dn_size = 0;

		err = gnutls_openpgp_crt_get_name(cert, i, NULL, &dn_size);
		if (err != GNUTLS_E_SHORT_MEMORY_BUFFER
		    && err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
		    && err != GNUTLS_E_OPENPGP_UID_REVOKED)
			addf(str, "error: get_name: %s\n",
			     gnutls_strerror(err));
		else {
			dn = gnutls_malloc(dn_size);
			if (!dn)
				addf(str, "error: malloc (%d): %s\n",
				     (int) dn_size,
				     gnutls_strerror
				     (GNUTLS_E_MEMORY_ERROR));
			else {
				err =
				    gnutls_openpgp_crt_get_name(cert, i,
								dn,
								&dn_size);
				if (err < 0
				    && err !=
				    GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
				    && err != GNUTLS_E_OPENPGP_UID_REVOKED)
					addf(str, "error: get_name: %s\n",
					     gnutls_strerror(err));
				else if (err >= 0)
					addf(str, _("\tName[%d]: %s\n"), i,
					     dn);
				else if (err ==
					 GNUTLS_E_OPENPGP_UID_REVOKED)
					addf(str,
					     _("\tRevoked Name[%d]: %s\n"),
					     i, dn);

				gnutls_free(dn);
			}
		}

		i++;
	}
	while (err >= 0);

	print_key_times(str, cert, -1);

	print_key_info(str, cert, -1);
	print_key_usage(str, cert, -1);

	subkeys = gnutls_openpgp_crt_get_subkey_count(cert);
	if (subkeys < 0)
		return;

	for (i = 0; i < subkeys; i++) {
		addf(str, _("\n\tSubkey[%d]:\n"), i);

		print_key_revoked(str, cert, i);
		print_key_id(str, cert, i);
		print_key_times(str, cert, i);
		print_key_info(str, cert, i);
		print_key_usage(str, cert, i);
	}

}