Beispiel #1
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;

}
/* 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;
  uint8_t *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_debug_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;
}
Beispiel #3
0
/**
 * gnutls_x509_trust_list_verify_crt2:
 * @list: The list
 * @cert_list: is the certificate list to be verified
 * @cert_list_size: is the certificate list size
 * @data: an array of typed data
 * @elements: the number of data elements
 * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
 * @voutput: will hold the certificate verification output.
 * @func: If non-null will be called on each chain element verification with the output.
 *
 * This function will attempt to verify the given certificate chain and return
 * its status. The @voutput parameter will hold an OR'ed sequence of
 * %gnutls_certificate_status_t flags.
 *
 * When a certificate chain of @cert_list_size with more than one certificates is
 * provided, the verification status will apply to the first certificate in the chain
 * that failed verification. The verification process starts from the end of the chain
 * (from CA to end certificate). The first certificate in the chain must be the end-certificate
 * while the rest of the members may be sorted or not.
 *
 * Additionally a certificate verification profile can be specified
 * from the ones in %gnutls_certificate_verification_profiles_t by
 * ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
 * flags.
 *
 * Additional verification parameters are possible via the @data types; the
 * acceptable types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_IP_ADDRESS and %GNUTLS_DT_KEY_PURPOSE_OID.
 * The former accepts as data a null-terminated hostname, and the latter a null-terminated
 * object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
 * If a DNS hostname is provided then this function will compare
 * the hostname in the end certificate against the given. If names do not match the
 * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set. In addition it
 * will consider certificates provided with gnutls_x509_trust_list_add_named_crt().
 *
 * If a key purpose OID is provided and the end-certificate contains the extended key
 * usage PKIX extension, it will be required to match the provided OID
 * or be marked for any purpose, otherwise verification will fail with 
 * %GNUTLS_CERT_PURPOSE_MISMATCH status.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value. Note that verification failure will not result to an
 *   error code, only @voutput will be updated.
 *
 * Since: 3.3.8
 **/
int
gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
				  gnutls_x509_crt_t * cert_list,
				  unsigned int cert_list_size,
				  gnutls_typed_vdata_st *data,
				  unsigned int elements,
				  unsigned int flags,
				  unsigned int *voutput,
				  gnutls_verify_output_function func)
{
	int ret;
	unsigned int i;
	uint32_t hash;
	gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
	const char *hostname = NULL, *purpose = NULL, *email = NULL;
	unsigned hostname_size = 0;
	unsigned have_set_name = 0;
	unsigned saved_output;
	gnutls_datum_t ip = {NULL, 0};

	if (cert_list == NULL || cert_list_size < 1)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	for (i=0;i<elements;i++) {
		if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) {
			hostname = (void*)data[i].data;
			if (data[i].size > 0) {
				hostname_size = data[i].size;
			}

			if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
			have_set_name = 1;
		} else if (data[i].type == GNUTLS_DT_IP_ADDRESS) {
			if (data[i].size > 0) {
				ip.data = data[i].data;
				ip.size = data[i].size;
			}

			if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
			have_set_name = 1;
		} else if (data[i].type == GNUTLS_DT_RFC822NAME) {
			email = (void*)data[i].data;

			if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
			have_set_name = 1;
		} else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
			purpose = (void*)data[i].data;
		}
	}

	if (hostname) { /* shortcut using the named certs - if any */
		unsigned vtmp = 0;
		if (hostname_size == 0)
			hostname_size = strlen(hostname);

		ret = gnutls_x509_trust_list_verify_named_crt(list,
					cert_list[0], hostname, hostname_size,
					flags, &vtmp, func);
		if (ret == 0 && vtmp == 0) {
			*voutput = vtmp;
			return 0;
		}
	}

	if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN))
		cert_list = _gnutls_sort_clist(sorted, cert_list, &cert_list_size, NULL);

	cert_list_size = shorten_clist(list, cert_list, cert_list_size);
	if (cert_list_size <= 0)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	hash =
	    hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
			  data,
			  cert_list[cert_list_size -
				    1]->raw_issuer_dn.size);
	hash %= list->size;

	ret = check_if_in_blacklist(cert_list, cert_list_size,
		list->blacklisted, list->blacklisted_size);
	if (ret != 0) {
		*voutput = 0;
		*voutput |= GNUTLS_CERT_REVOKED;
		*voutput |= GNUTLS_CERT_INVALID;
		return 0;
	}

	*voutput =
	    _gnutls_verify_crt_status(cert_list, cert_list_size,
					    list->node[hash].trusted_cas,
					    list->
					    node[hash].trusted_ca_size,
					    flags, purpose, func);
	saved_output = *voutput;

	if (SIGNER_OLD_OR_UNKNOWN(*voutput) &&
		(LAST_DN.size != LAST_IDN.size ||
		 memcmp(LAST_DN.data, LAST_IDN.data, LAST_IDN.size) != 0)) {

		/* if we couldn't find the issuer, try to see if the last
		 * certificate is in the trusted list and try to verify against
		 * (if it is not self signed) */
		hash =
		    hash_pjw_bare(cert_list[cert_list_size - 1]->raw_dn.
			  data, cert_list[cert_list_size - 1]->raw_dn.size);
		hash %= list->size;

		 _gnutls_debug_log("issuer in verification was not found or insecure; trying against trust list\n");

		*voutput =
		    _gnutls_verify_crt_status(cert_list, cert_list_size,
					    list->node[hash].trusted_cas,
					    list->
					    node[hash].trusted_ca_size,
					    flags, purpose, func);
		if (*voutput != 0) {
			if (SIGNER_WAS_KNOWN(saved_output))
				*voutput = saved_output;
			gnutls_assert();
		}
	}

	saved_output = *voutput;

#ifdef ENABLE_PKCS11
	if (SIGNER_OLD_OR_UNKNOWN(*voutput) && list->pkcs11_token) {
		/* use the token for verification */

		*voutput = _gnutls_pkcs11_verify_crt_status(list->pkcs11_token,
								cert_list, cert_list_size,
								purpose,
								flags, func);
		if (*voutput != 0) {
			if (SIGNER_WAS_KNOWN(saved_output))
				*voutput = saved_output;
			gnutls_assert();
		}
	}
#endif

	/* End-certificate, key purpose and hostname checks. */
	if (purpose) {
		ret = _gnutls_check_key_purpose(cert_list[0], purpose, 0);
		if (ret != 1) {
			gnutls_assert();
			*voutput |= GNUTLS_CERT_PURPOSE_MISMATCH|GNUTLS_CERT_INVALID;
		}
	}

	if (hostname) {
		ret =
		    gnutls_x509_crt_check_hostname2(cert_list[0], hostname, flags);
		if (ret == 0) {
			gnutls_assert();
			*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
		}
	}

	if (ip.data) {
		ret =
		    gnutls_x509_crt_check_ip(cert_list[0], ip.data, ip.size, flags);
		if (ret == 0) {
			gnutls_assert();
			*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
		}
	}

	if (email) {
		ret =
		    gnutls_x509_crt_check_email(cert_list[0], email, 0);
		if (ret == 0) {
			gnutls_assert();
			*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
		}
	}

	/* CRL checks follow */

	if (*voutput != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
		return 0;

	/* Check revocation of individual certificates.
	 * start with the last one that we already have its hash
	 */
	ret =
	    _gnutls_x509_crt_check_revocation(cert_list
					      [cert_list_size - 1],
					      list->node[hash].crls,
					      list->node[hash].crl_size,
					      func);
	if (ret == 1) {		/* revoked */
		*voutput |= GNUTLS_CERT_REVOKED;
		*voutput |= GNUTLS_CERT_INVALID;
		return 0;
	}

	for (i = 0; i < cert_list_size - 1; i++) {
		hash =
		    hash_pjw_bare(cert_list[i]->raw_issuer_dn.data,
				  cert_list[i]->raw_issuer_dn.size);
		hash %= list->size;

		ret = _gnutls_x509_crt_check_revocation(cert_list[i],
							list->node[hash].
							crls,
							list->node[hash].
							crl_size, func);
		if (ret < 0) {
			gnutls_assert();
		} else if (ret == 1) {	/* revoked */
			*voutput |= GNUTLS_CERT_REVOKED;
			*voutput |= GNUTLS_CERT_INVALID;
			return 0;
		}
	}

	return 0;
}
/**
 * gnutls_pkcs11_privkey_generate:
 * @url: a token URL
 * @pk: the public key algorithm
 * @bits: the security bits
 * @label: a label
 * @flags: should be zero
 *
 * This function will generate a private key in the specified
 * by the @url token. The pivate key will be generate within
 * the token and will not be exportable.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_pkcs11_privkey_generate (const char* url, 
  gnutls_pk_algorithm_t pk, unsigned int bits, 
  const char* label, unsigned int flags)
{
  int ret;
  const ck_bool_t tval = 1;
  const ck_bool_t fval = 0;
  struct ck_function_list *module;
  ck_session_handle_t pks = 0;
  struct p11_kit_uri *info = NULL;
  ck_rv_t rv;
  struct ck_attribute a[10], p[10];
  ck_object_handle_t pub, priv;
  unsigned long _bits = bits;
  int a_val, p_val;
  struct ck_mechanism mech;

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

  ret =
    pkcs11_open_session (&module, &pks, info,
                         SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
  p11_kit_uri_free (info);

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

  /* a holds the public key template
   * and p the private key */
  a_val = p_val = 0;
  mech.parameter = NULL;
  mech.parameter_len = 0;
  mech.mechanism = pk_to_genmech(pk);

  switch(pk)
    {
      case GNUTLS_PK_RSA:
        p[p_val].type = CKA_DECRYPT;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_ENCRYPT;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      case GNUTLS_PK_DSA:
        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      case GNUTLS_PK_EC:
        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      default:
        ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        goto cleanup;
    }

  /* a private key is set always as private unless
   * requested otherwise
   */
  if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
    {
      p[p_val].type = CKA_PRIVATE;
      p[p_val].value = (void*)&fval;
      p[p_val].value_len = sizeof(fval);
      p_val++;
    }
  else
    {
      p[p_val].type = CKA_PRIVATE;
      p[p_val].value = (void*)&tval;
      p[p_val].value_len = sizeof (tval);
      p_val++;
    }

  p[p_val].type = CKA_TOKEN;
  p[p_val].value = (void *)&tval;
  p[p_val].value_len = sizeof (tval);
  p_val++;

  if (label)
    {
      p[p_val].type = CKA_LABEL;
      p[p_val].value = (void*)label;
      p[p_val].value_len = strlen (label);
      p_val++;

      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_SENSITIVE)
    {
      p[p_val].type = CKA_SENSITIVE;
      p[p_val].value = (void*)&tval;
      p[p_val].value_len = sizeof (tval);
      p_val++;
    }
  else
    {
      p[p_val].type = CKA_SENSITIVE;
      p[p_val].value = (void*)&fval;
      p[p_val].value_len = sizeof (fval);
      p_val++;
    }

  rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }
    

cleanup:
  if (pks != 0)
    pkcs11_close_session (module, pks);

  return ret;
}
Beispiel #5
0
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
 * which holds them. Returns an ASN1_TYPE of authenticatedSafe.
 */
static int
_decode_pkcs12_auth_safe(ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
			 gnutls_datum_t * raw)
{
	char oid[MAX_OID_SIZE];
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	gnutls_datum_t auth_safe = { NULL, 0 };
	int len, result;
	char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

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

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

	/* Step 1. Read the content data
	 */

	result =
	    _gnutls_x509_read_string(pkcs12, "authSafe.content",
				     &auth_safe, ASN1_ETYPE_OCTET_STRING);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Step 2. Extract the authenticatedSafe.
	 */

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

	result =
	    asn1_der_decoding(&c2, auth_safe.data, auth_safe.size,
			      error_str);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		_gnutls_debug_log("DER error: %s\n", error_str);
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (raw == NULL) {
		_gnutls_free_datum(&auth_safe);
	} else {
		raw->data = auth_safe.data;
		raw->size = auth_safe.size;
	}

	if (authen_safe)
		*authen_safe = c2;
	else
		asn1_delete_structure(&c2);

	return 0;

      cleanup:
	if (c2)
		asn1_delete_structure(&c2);
	_gnutls_free_datum(&auth_safe);
	return result;
}
Beispiel #6
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
		     gnutls_datum_t * signature,
		     const gnutls_datum_t * vdata,
		     const gnutls_pk_params_st * pk_params)
{
	int ret;
	unsigned int hash_len;
	const mac_entry_st *me;

	switch (algo) {
	case GNUTLS_PK_EC:	/* we do ECDSA */
		{
			struct ecc_scalar priv;
			struct dsa_signature sig;
			int curve_id = pk_params->flags;
			const struct ecc_curve *curve;

			curve = get_supported_curve(curve_id);
			if (curve == NULL)
				return
				    gnutls_assert_val
				    (GNUTLS_E_ECC_UNSUPPORTED_CURVE);

			ret =
			    _ecc_params_to_privkey(pk_params, &priv,
						   curve);
			if (ret < 0)
				return gnutls_assert_val(ret);

			dsa_signature_init(&sig);

			me = _gnutls_dsa_q_to_hash(algo, pk_params,
						   &hash_len);

			if (hash_len > vdata->size) {
				gnutls_assert();
				_gnutls_debug_log
				    ("Security level of algorithm requires hash %s(%d) or better\n",
				     _gnutls_mac_get_name(me), hash_len);
				hash_len = vdata->size;
			}

			ecdsa_sign(&priv, NULL, rnd_func, hash_len,
				   vdata->data, &sig);

			ret =
			    _gnutls_encode_ber_rs(signature, &sig.r,
						  &sig.s);

			dsa_signature_clear(&sig);
			ecc_scalar_clear(&priv);

			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
			break;
		}
	case GNUTLS_PK_DSA:
		{
			struct dsa_public_key pub;
			struct dsa_private_key priv;
			struct dsa_signature sig;

			memset(&priv, 0, sizeof(priv));
			memset(&pub, 0, sizeof(pub));
			_dsa_params_to_pubkey(pk_params, &pub);
			_dsa_params_to_privkey(pk_params, &priv);

			dsa_signature_init(&sig);

			me = _gnutls_dsa_q_to_hash(algo, pk_params,
						   &hash_len);

			if (hash_len > vdata->size) {
				gnutls_assert();
				_gnutls_debug_log
				    ("Security level of algorithm requires hash %s(%d) or better\n",
				     _gnutls_mac_get_name(me), hash_len);
				hash_len = vdata->size;
			}

			ret =
			    _dsa_sign(&pub, &priv, NULL, rnd_func,
				      hash_len, vdata->data, &sig);
			if (ret == 0) {
				gnutls_assert();
				ret = GNUTLS_E_PK_SIGN_FAILED;
				goto dsa_fail;
			}

			ret =
			    _gnutls_encode_ber_rs(signature, &sig.r,
						  &sig.s);

		      dsa_fail:
			dsa_signature_clear(&sig);

			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
			break;
		}
	case GNUTLS_PK_RSA:
		{
			struct rsa_private_key priv;
			struct rsa_public_key pub;
			mpz_t s;

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

			mpz_init(s);

			ret =
			    rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func,
					      vdata->size, vdata->data, s);
			if (ret == 0) {
				gnutls_assert();
				ret = GNUTLS_E_PK_SIGN_FAILED;
				goto rsa_fail;
			}

			ret =
			    _gnutls_mpi_dprint_size(s, signature,
						    pub.size);

		      rsa_fail:
			mpz_clear(s);

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

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

	ret = 0;

      cleanup:

	return ret;
}
Beispiel #7
0
/**
 * gnutls_dh_params_import_pkcs3:
 * @params: A structure where the parameters will be copied to
 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
 * @format: the format of params. PEM or DER.
 *
 * This function will extract the DHParams found in a PKCS3 formatted
 * structure. This is the format generated by "openssl dhparam" tool.
 *
 * If the structure is PEM encoded, it should have a header
 * of "BEGIN DH PARAMETERS".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
 *   otherwise an error code is returned.
 **/
int
gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
                               const gnutls_datum_t * pkcs3_params,
                               gnutls_x509_crt_fmt_t format)
{
  ASN1_TYPE c2;
  int result, need_free = 0;
  gnutls_datum_t _params;

  if (format == GNUTLS_X509_FMT_PEM)
    {
      opaque *out;

      result = _gnutls_fbase64_decode ("DH PARAMETERS",
                                       pkcs3_params->data,
                                       pkcs3_params->size, &out);

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

      _params.data = out;
      _params.size = result;

      need_free = 1;

    }
  else
    {
      _params.data = pkcs3_params->data;
      _params.size = pkcs3_params->size;
    }

  if ((result = asn1_create_element
       (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
      != ASN1_SUCCESS)
    {
      gnutls_assert ();
      if (need_free != 0)
        {
          gnutls_free (_params.data);
          _params.data = NULL;
        }
      return _gnutls_asn2err (result);
    }

  result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);

  if (need_free != 0)
    {
      gnutls_free (_params.data);
      _params.data = NULL;
    }

  if (result != ASN1_SUCCESS)
    {
      /* couldn't decode DER */

      _gnutls_debug_log ("DHParams: Decoding error %d\n", result);
      gnutls_assert ();
      asn1_delete_structure (&c2);
      return _gnutls_asn2err (result);
    }

  /* Read PRIME 
   */
  result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
  if (result < 0)
    {
      asn1_delete_structure (&c2);
      gnutls_assert ();
      return result;
    }

  /* read the generator
   */
  result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
  if (result < 0)
    {
      asn1_delete_structure (&c2);
      _gnutls_mpi_release (&params->params[0]);
      gnutls_assert ();
      return result;
    }

  asn1_delete_structure (&c2);

  return 0;
}
Beispiel #8
0
static
int capi_sign(gnutls_privkey_t key, void *userdata,
	      const gnutls_datum_t * raw_data, gnutls_datum_t * signature)
{
	priv_st *priv = (priv_st *) userdata;
	ALG_ID Algid;
	HCRYPTHASH hHash = NULL;
	uint8_t digest[MAX_HASH_SIZE];
	unsigned int digest_size;
	gnutls_digest_algorithm_t algo;
	DWORD size1 = 0, sizesize = sizeof(DWORD);
	DWORD ret_sig = 0;
	int ret;

	signature->data = NULL;
	signature->size = 0;

	digest_size = raw_data->size;

	switch (digest_size) {
	case 16:
		Algid = CALG_MD5;
		break;
		//case 35:  size=20;                                    // DigestInfo SHA1
	case 20:
		Algid = CALG_SHA1;
		break;
		//case 51:  size=32;                                    // DigestInto SHA-256
	case 32:
		Algid = CALG_SHA_256;
		break;
	case 36:
		Algid = CALG_SSL3_SHAMD5;
		break;
	case 48:
		Algid = CALG_SHA_384;
		break;
	case 64:
		Algid = CALG_SHA_512;
		break;
	default:
		digest_size = sizeof(digest);
		ret =
		    decode_ber_digest_info(raw_data, &algo, digest,
					   &digest_size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		switch (algo) {
		case GNUTLS_DIG_SHA1:
			Algid = CALG_SHA1;
			break;
#ifdef NCRYPT_SHA224_ALGORITHM
		case GNUTLS_DIG_SHA224:
			Algid = CALG_SHA_224;
			break;
#endif
		case GNUTLS_DIG_SHA256:
			Algid = CALG_SHA_256;
			break;
		case GNUTLS_DIG_SHA384:
			Algid = CALG_SHA_384;
			break;
		case GNUTLS_DIG_SHA512:
			Algid = CALG_SHA_512;
			break;
		default:
			return
			    gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
		}
	}

	if (!CryptCreateHash(priv->hCryptProv, Algid, 0, 0, &hHash)) {
		gnutls_assert();
		_gnutls_debug_log("error in create hash: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	if (!CryptSetHashParam(hHash, HP_HASHVAL, digest, 0)) {
		gnutls_assert();
		_gnutls_debug_log("error in set hash val: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	if (!CryptGetHashParam
	    (hHash, HP_HASHSIZE, (BYTE *) & size1, &sizesize, 0)
	    || digest_size != size1) {
		gnutls_assert();
		_gnutls_debug_log("error in hash size: %d\n", (int)size1);
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	if (!CryptSignHash(hHash, priv->dwKeySpec, NULL, 0, NULL, &ret_sig)) {
		gnutls_assert();
		_gnutls_debug_log("error in pre-signing: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	signature->size = ret_sig;
	signature->data = (unsigned char *)gnutls_malloc(signature->size);

	if (signature->data == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	if (!CryptSignHash
	    (hHash, priv->dwKeySpec, NULL, 0, signature->data, &ret_sig)) {
		gnutls_assert();
		_gnutls_debug_log("error in signing: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	memrev(signature->data, signature->size);

	CryptDestroyHash(hHash);
	signature->size = ret_sig;

	return 0;
 fail:
	if (hHash != 0)
		CryptDestroyHash(hHash);
	gnutls_free(signature->data);
	return ret;
}
Beispiel #9
0
static
int cng_sign(gnutls_privkey_t key, void *userdata,
	     const gnutls_datum_t * raw_data, gnutls_datum_t * signature)
{
	priv_st *priv = userdata;
	BCRYPT_PKCS1_PADDING_INFO _info;
	void *info = NULL;
	DWORD ret_sig = 0;
	int ret;
	DWORD flags = 0;
	gnutls_datum_t data = { raw_data->data, raw_data->size };
	uint8_t digest[MAX_HASH_SIZE];
	unsigned int digest_size;
	gnutls_digest_algorithm_t algo;
	SECURITY_STATUS r;

	signature->data = NULL;
	signature->size = 0;

	if (priv->pk == GNUTLS_PK_RSA) {

		flags = BCRYPT_PAD_PKCS1;
		info = &_info;

		if (raw_data->size == 36) {	/* TLS 1.0 MD5+SHA1 */
			_info.pszAlgId = NULL;
		} else {
			digest_size = sizeof(digest);
			ret =
			    decode_ber_digest_info(raw_data, &algo, digest,
						   &digest_size);
			if (ret < 0)
				return gnutls_assert_val(ret);

			switch (algo) {
			case GNUTLS_DIG_SHA1:
				_info.pszAlgId = NCRYPT_SHA1_ALGORITHM;
				break;
#ifdef NCRYPT_SHA224_ALGORITHM
			case GNUTLS_DIG_SHA224:
				_info.pszAlgId = NCRYPT_SHA224_ALGORITHM;
				break;
#endif
			case GNUTLS_DIG_SHA256:
				_info.pszAlgId = NCRYPT_SHA256_ALGORITHM;
				break;
			case GNUTLS_DIG_SHA384:
				_info.pszAlgId = NCRYPT_SHA384_ALGORITHM;
				break;
			case GNUTLS_DIG_SHA512:
				_info.pszAlgId = NCRYPT_SHA512_ALGORITHM;
				break;
			default:
				return
				    gnutls_assert_val
				    (GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
			}
			data.data = digest;
			data.size = digest_size;
		}
	}

	r = pNCryptSignHash(priv->nc, info, data.data, data.size,
			    NULL, 0, &ret_sig, flags);
	if (FAILED(r)) {
		gnutls_assert();
		_gnutls_debug_log("error in pre-signing: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	signature->size = ret_sig;
	signature->data = gnutls_malloc(signature->size);
	if (signature->data == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	r = pNCryptSignHash(priv->nc, info, data.data, data.size,
			    signature->data, signature->size, &ret_sig, flags);
	if (FAILED(r)) {
		gnutls_assert();
		_gnutls_debug_log("error in signing: %d\n",
				  (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	signature->size = ret_sig;

	return 0;
 fail:
	gnutls_free(signature->data);
	return ret;
}
Beispiel #10
0
/* Run an HMAC using the key above on the library binary data. 
 * Returns true on success and false on error.
 */
static unsigned check_binary_integrity(const char* libname, const char* symbol)
{
	int ret;
	unsigned prev;
	char mac_file[GNUTLS_PATH_MAX];
	char file[GNUTLS_PATH_MAX];
	uint8_t hmac[HMAC_SIZE];
	uint8_t new_hmac[HMAC_SIZE];
	size_t hmac_size;
	gnutls_datum_t data;

	ret = get_library_path(libname, symbol, file, sizeof(file));
	if (ret < 0) {
		_gnutls_debug_log("Could not get path for library %s\n", libname);
		return 0;
	}

	_gnutls_debug_log("Loading: %s\n", file);
	ret = gnutls_load_file(file, &data);
	if (ret < 0) {
		_gnutls_debug_log("Could not load: %s\n", file);
		return gnutls_assert_val(0);
	}

	prev = _gnutls_get_lib_state();
	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
	ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1,
		data.data, data.size, new_hmac);
	_gnutls_switch_lib_state(prev);
	
	gnutls_free(data.data);

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

	/* now open the .hmac file and compare */
	get_hmac_file(mac_file, sizeof(mac_file), file);

	ret = gnutls_load_file(mac_file, &data);
	if (ret < 0) {
		get_hmac_file2(mac_file, sizeof(mac_file), file);
		ret = gnutls_load_file(mac_file, &data);
		if (ret < 0) {
			_gnutls_debug_log("Could not open %s for MAC testing: %s\n", mac_file, gnutls_strerror(ret));
			return gnutls_assert_val(0);
		}
	}

	hmac_size = hex_data_size(data.size);
	ret = gnutls_hex_decode(&data, hmac, &hmac_size);
	gnutls_free(data.data);

	if (ret < 0) {
		_gnutls_debug_log("Could not convert hex data to binary for MAC testing for %s.\n", libname);
		return gnutls_assert_val(0);
	}

	if (hmac_size != sizeof(hmac) ||
			memcmp(hmac, new_hmac, sizeof(hmac)) != 0) {
		_gnutls_debug_log("Calculated MAC for %s does not match\n", libname);
		return gnutls_assert_val(0);
	}
	_gnutls_debug_log("Successfully verified MAC for %s (%s)\n", mac_file, libname);
	
	return 1;
}
/*-
 * _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;
}
void
register_padlock_crypto (void)
{
  int ret, phe;

  if (check_via () == 0)
    return;
  if (check_padlock ())
    {
      _gnutls_debug_log ("Padlock AES accelerator was detected\n");
      ret =
        gnutls_crypto_single_cipher_register
        (GNUTLS_CIPHER_AES_128_CBC, 80, &aes_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      /* register GCM ciphers */
      ret =
        gnutls_crypto_single_cipher_register
        (GNUTLS_CIPHER_AES_128_GCM, 80, &aes_gcm_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }
#ifdef HAVE_LIBNETTLE
      ret =
        gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_192_CBC,
                                              80, &aes_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_256_CBC,
                                              80, &aes_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_256_GCM,
                                              80, &aes_gcm_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

#endif
    }

#ifdef HAVE_LIBNETTLE
  phe = check_phe ();

  if (phe && check_phe_partial ())
    {
      _gnutls_debug_log ("Padlock SHA1 and SHA256 (partial) accelerator was detected\n");
      if (check_phe_sha512 ())
        {
          _gnutls_debug_log ("Padlock SHA512 (partial) accelerator was detected\n");
          ret =
            gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA384,
                                                  80,
                                                  &sha_padlock_nano_struct);
          if (ret < 0)
            {
              gnutls_assert ();
            }

          ret =
            gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA512,
                                                  80,
                                                  &sha_padlock_nano_struct);
          if (ret < 0)
            {
              gnutls_assert ();
            }

          ret =
            gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA384,
                                               80,
                                               &hmac_sha_padlock_nano_struct);
          if (ret < 0)
            {
              gnutls_assert ();
            }

          ret =
            gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA512,
                                               80,
                                               &hmac_sha_padlock_nano_struct);
          if (ret < 0)
            {
              gnutls_assert ();
            }
        }

      ret =
        gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA1,
                                              80, &sha_padlock_nano_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA224,
                                              80, &sha_padlock_nano_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA256,
                                              80, &sha_padlock_nano_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA1,
                                           80, &hmac_sha_padlock_nano_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      /* we don't register MAC_SHA224 because it is not used by TLS */

      ret =
        gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA256,
                                           80, &hmac_sha_padlock_nano_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }
    }
  else if (phe)
    {
      /* Original padlock PHE. Does not support incremental operations.
       */
      _gnutls_debug_log ("Padlock SHA1 and SHA256 accelerator was detected\n");
      ret =
        gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA1,
                                              80, &sha_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_digest_register (GNUTLS_DIG_SHA256,
                                              80, &sha_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA1,
                                           80, &hmac_sha_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }

      ret =
        gnutls_crypto_single_mac_register (GNUTLS_MAC_SHA256,
                                           80, &hmac_sha_padlock_struct);
      if (ret < 0)
        {
          gnutls_assert ();
        }
    }
#endif

  return;
}
Beispiel #13
0
int _gnutls_ucs2_to_utf8(const void *data, size_t size,
			 gnutls_datum_t * output, unsigned be)
{
	int ret;
	unsigned i;
	int len = 0, src_len;
	char *dst = NULL;
	char *src = NULL;
	static unsigned flags = 0;
	static int checked = 0;

	if (checked == 0) {
		/* Not all windows versions support MB_ERR_INVALID_CHARS */
		ret =
		    WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS,
				L"hello", -1, NULL, 0, NULL, NULL);
		if (ret > 0)
			flags = MB_ERR_INVALID_CHARS;
		checked = 1;
	}

	if (((uint8_t *) data)[size] == 0 && ((uint8_t *) data)[size+1] == 0) {
		size -= 2;
	}

	src = gnutls_malloc(size+2);
	if (src == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	/* convert to LE */
	if (be) {
		for (i = 0; i < size; i += 2) {
			src[i] = ((uint8_t *) data)[1 + i];
			src[1 + i] = ((uint8_t *) data)[i];
		}
	} else {
		memcpy(src, data, size);
	}
	src[size] = 0;
	src[size+1] = 0;

	src_len = wcslen(src);

	ret =
	    WideCharToMultiByte(CP_UTF8, flags,
				(void *) src, src_len, NULL, 0,
				NULL, NULL);
	if (ret == 0) {
		_gnutls_debug_log("WideCharToMultiByte: %d\n", (int)GetLastError());
		ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		goto fail;
	}

	len = ret + 1;
	dst = gnutls_malloc(len);
	if (dst == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto fail;
	}
	dst[0] = 0;

	ret =
	    WideCharToMultiByte(CP_UTF8, flags,
				(void *) src, src_len, dst, len-1, NULL,
				NULL);
	if (ret == 0) {
		ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		goto fail;
	}
	dst[len - 1] = 0;

	output->data = dst;
	output->size = ret;

	ret = 0;
	goto cleanup;

      fail:
	gnutls_free(dst);

      cleanup:
	gnutls_free(src);
	return ret;
}
Beispiel #14
0
static
int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
		     unsigned int tl_vflags)
{
	char path[GNUTLS_PATH_MAX];
	unsigned int i;
	int r = 0;

	for (i = 0; i < 2; i++) {
		HCERTSTORE store;
		const CERT_CONTEXT *cert;
		const CRL_CONTEXT *crl;
		gnutls_datum_t data;

		if (i == 0)
			store = CertOpenSystemStore(0, "ROOT");
		else
			store = CertOpenSystemStore(0, "CA");

		if (store == NULL)
			return GNUTLS_E_FILE_ERROR;

		cert = CertEnumCertificatesInStore(store, NULL);
		crl = pCertEnumCRLsInStore(store, NULL);

		while (cert != NULL) {
			if (cert->dwCertEncodingType == X509_ASN_ENCODING) {
				data.data = cert->pbCertEncoded;
				data.size = cert->cbCertEncoded;
				if (gnutls_x509_trust_list_add_trust_mem
				    (list, &data, NULL,
				     GNUTLS_X509_FMT_DER, tl_flags,
				     tl_vflags) > 0)
					r++;
			}
			cert = CertEnumCertificatesInStore(store, cert);
		}

		while (crl != NULL) {
			if (crl->dwCertEncodingType == X509_ASN_ENCODING) {
				data.data = crl->pbCrlEncoded;
				data.size = crl->cbCrlEncoded;
				gnutls_x509_trust_list_add_trust_mem(list,
								     NULL,
								     &data,
								     GNUTLS_X509_FMT_DER,
								     tl_flags,
								     tl_vflags);
			}
			crl = pCertEnumCRLsInStore(store, crl);
		}
		CertCloseStore(store, 0);
	}

#ifdef DEFAULT_BLACKLIST_FILE
	ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		_gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE);
	}
#endif

	return r;
}
Beispiel #15
0
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
 * 
 * The hash function used is SHA384.
 * The exponent e used is the value in pub->e.
 */
int
_rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
				struct rsa_private_key *key,
				unsigned seed_length, uint8_t * seed,
				void *progress_ctx,
				nettle_progress_func * progress,
				/* Desired size of modulo, in bits */
				unsigned n_size)
{
	mpz_t t, r, p1, q1, lcm;
	int ret;
	struct dss_params_validation_seeds cert;
	unsigned l = n_size / 2;

	FIPS_RULE(n_size == 2048 && seed_length != 14 * 2, 0, "seed length other than 28 bytes\n");
	FIPS_RULE(n_size == 3072 && seed_length != 16 * 2, 0, "seed length other than 32 bytes\n");
	FIPS_RULE(n_size != 2048 && n_size != 3072, 0, "unsupported size for modulus\n");

	if (!mpz_tstbit(pub->e, 0)) {
		_gnutls_debug_log("Unacceptable e (it is even)\n");
		return 0;
	}

	if (mpz_cmp_ui(pub->e, 65536) <= 0) {
		_gnutls_debug_log("Unacceptable e\n");
		return 0;
	}

	mpz_init(p1);
	mpz_init(q1);
	mpz_init(lcm);
	mpz_init(t);
	mpz_init(r);

	mpz_set_ui(t, 1);
	mpz_mul_2exp(t, t, 256);

	if (mpz_cmp(pub->e, t) >= 0) {
		ret = 0;
		goto cleanup;
	}

	cert.pseed_length = sizeof(cert.pseed);
	ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed,
				l, seed_length,
				seed, pub->e, progress_ctx, progress);
	if (ret == 0) {
		goto cleanup;
	}

	mpz_set_ui(r, 1);
	mpz_mul_2exp(r, r, (l) - 100);

	do {
		cert.qseed_length = sizeof(cert.qseed);
		ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed,
					l, cert.pseed_length, cert.pseed,
					pub->e,
					progress_ctx, progress);
		if (ret == 0) {
			goto cleanup;
		}


		cert.pseed_length = cert.qseed_length;
		memcpy(cert.pseed, cert.qseed, cert.qseed_length);


		if (mpz_cmp(key->p, key->q) > 0)
			mpz_sub(t, key->p, key->q);
		else
			mpz_sub(t, key->q, key->p);
	} while (mpz_cmp(t, r) <= 0);

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

	mpz_mul(pub->n, key->p, key->q);

	if (mpz_sizeinbase(pub->n, 2) != n_size) {
		ret = 0;
		goto cleanup;
	}

	/* c = q^{-1} (mod p) */
	if (mpz_invert(key->c, key->q, key->p) == 0) {
		ret = 0;
		goto cleanup;
	}

	mpz_sub_ui(p1, key->p, 1);
	mpz_sub_ui(q1, key->q, 1);

	mpz_lcm(lcm, p1, q1);

	if (mpz_invert(key->d, pub->e, lcm) == 0) {
		ret = 0;
		goto cleanup;
	}

	/* check whether d > 2^(nlen/2) -- FIPS186-4 5.3.1 */
	if (mpz_sizeinbase(key->d, 2) < n_size/2) {
		ret = 0;
		goto cleanup;
	}

	/* Done! Almost, we must compute the auxiliary private values. */
	/* a = d % (p-1) */
	mpz_fdiv_r(key->a, key->d, p1);

	/* b = d % (q-1) */
	mpz_fdiv_r(key->b, key->d, q1);

	/* c was computed earlier */

	pub->size = key->size = (n_size + 7) / 8;
	if (pub->size < RSA_MINIMUM_N_OCTETS) {
		ret = 0;
		goto cleanup;
	}

	ret = 1;
 cleanup:
	mpz_clear(p1);
	mpz_clear(q1);
	mpz_clear(lcm);
	mpz_clear(t);
	mpz_clear(r);
	return ret;
}
Beispiel #16
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
}
Beispiel #17
0
static
int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t * name,
		    const gnutls_datum_t * val, unsigned is_raw)
{
	char _oid[MAX_OID_SIZE];
	gnutls_datum_t tmp;
	const char *oid;
	int ret;
	unsigned i,j;

	if (name->size == 0 || val->size == 0)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	if (c_isdigit(name->data[0]) != 0) {
		if (name->size >= sizeof(_oid))
			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

		memcpy(_oid, name->data, name->size);
		_oid[name->size] = 0;

		oid = _oid;

		if (gnutls_x509_dn_oid_known(oid) == 0 && !is_raw) {
			_gnutls_debug_log("Unknown OID: '%s'\n", oid);
			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		}
	} else {
		oid =
		    _gnutls_ldap_string_to_oid((char *) name->data,
					       name->size);
	}

	if (oid == NULL) {
		_gnutls_debug_log("Unknown DN attribute: '%.*s'\n",
				  (int) name->size, name->data);
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
	}

	if (is_raw) {
		gnutls_datum_t hex = {val->data+1, val->size-1};

		ret = gnutls_hex_decode2(&hex, &tmp);
		if (ret < 0)
			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
	} else {
		tmp.size = val->size;
		tmp.data = gnutls_malloc(tmp.size+1);
		if (tmp.data == NULL) {
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		}

		/* unescape */
		for (j=i=0;i<tmp.size;i++) {
			if (1+j!=val->size && val->data[j] == '\\') {
				if (val->data[j+1] == ',' || val->data[j+1] == '#' ||
				    val->data[j+1] == ' ' || val->data[j+1] == '+' ||
				    val->data[j+1] == '"' || val->data[j+1] == '<' ||
				    val->data[j+1] == '>' || val->data[j+1] == ';' ||
				    val->data[j+1] == '\\' || val->data[j+1] == '=') {
					tmp.data[i] = val->data[j+1];
					j+=2;
					tmp.size--;
				} else {
					ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
					goto fail;
				}
			} else {
				tmp.data[i] = val->data[j++];
			}
		}
		tmp.data[tmp.size] = 0;
	}

	ret = f(crt, oid, is_raw, tmp.data, tmp.size);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	ret = 0;
 fail:
	gnutls_free(tmp.data);
	return ret;
}
Beispiel #18
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
                      gnutls_datum_t * signature,
                      const gnutls_datum_t * vdata,
                      const gnutls_pk_params_st * pk_params)
{
  int ret, hash;

  switch (algo)
    {
    case GNUTLS_PK_ECC: /* we do ECDSA */
      {
        ecc_key priv;
        struct dsa_signature sig;
        int hash_len;

        _ecc_params_to_privkey(pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret = ecc_sign_hash(vdata->data, hash_len, 
                            &sig, NULL, rnd_func, &priv);
        if (ret != 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto ecdsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      ecdsa_fail:
        dsa_signature_clear (&sig);
        _ecc_params_clear( &priv);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_private_key priv;
        struct dsa_signature sig;
        int hash_len;

        memset(&priv, 0, sizeof(priv));
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        _dsa_params_to_privkey (pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret =
          _dsa_sign (&pub, &priv, NULL, rnd_func,
                     hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto dsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      dsa_fail:
        dsa_signature_clear (&sig);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        bigint_t hash, nc, ri;

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

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

        nc = rsa_blind (hash, pk_params->params[1] /*e */ ,
                        pk_params->params[0] /*m */ , &ri);

        _gnutls_mpi_release (&hash);

        if (nc == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_MEMORY_ERROR;
            goto rsa_fail;
          }

        rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc));

        rsa_unblind (nc, ri, pk_params->params[0] /*m */ );

        ret = _gnutls_mpi_dprint (nc, signature);

rsa_fail:
        _gnutls_mpi_release (&nc);
        _gnutls_mpi_release (&ri);

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

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

  ret = 0;

cleanup:

  return ret;
}
Beispiel #19
0
/* Reads the digest information.
 * we use DER here, although we should use BER. It works fine
 * anyway.
 */
static int
decode_ber_digest_info (const gnutls_datum_t * info,
                        gnutls_mac_algorithm_t * hash,
                        opaque * digest, int *digest_size)
{
    ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
    int result;
    char str[1024];
    int len;

    if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
                                       "GNUTLS.DigestInfo",
                                       &dinfo)) != ASN1_SUCCESS)
    {
        gnutls_assert ();
        return _gnutls_asn2err (result);
    }

    result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
    if (result != ASN1_SUCCESS)
    {
        gnutls_assert ();
        asn1_delete_structure (&dinfo);
        return _gnutls_asn2err (result);
    }

    len = sizeof (str) - 1;
    result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
    if (result != ASN1_SUCCESS)
    {
        gnutls_assert ();
        asn1_delete_structure (&dinfo);
        return _gnutls_asn2err (result);
    }

    *hash = _gnutls_x509_oid2mac_algorithm (str);

    if (*hash == GNUTLS_MAC_UNKNOWN)
    {

        _gnutls_debug_log ("verify.c: HASH OID: %s\n", str);

        gnutls_assert ();
        asn1_delete_structure (&dinfo);
        return GNUTLS_E_UNKNOWN_ALGORITHM;
    }

    len = sizeof (str) - 1;
    result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
    /* To avoid permitting garbage in the parameters field, either the
       parameters field is not present, or it contains 0x05 0x00. */
    if (!(result == ASN1_ELEMENT_NOT_FOUND ||
            (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
             memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
    {
        gnutls_assert ();
        asn1_delete_structure (&dinfo);
        return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

    result = asn1_read_value (dinfo, "digest", digest, digest_size);
    if (result != ASN1_SUCCESS)
    {
        gnutls_assert ();
        asn1_delete_structure (&dinfo);
        return _gnutls_asn2err (result);
    }

    asn1_delete_structure (&dinfo);

    return 0;
}
Beispiel #20
0
/**
 * gnutls_store_pubkey:
 * @db_name: A file specifying the stored keys (use NULL for the default)
 * @tdb: A storage structure or NULL to use the default
 * @host: The peer's name
 * @service: non-NULL if this key is specific to a service (e.g. http)
 * @cert_type: The type of the certificate
 * @cert: The data of the certificate
 * @expiration: The expiration time (use 0 to disable expiration)
 * @flags: should be 0.
 *
 * This function will store a raw public-key or a public-key provided via
 * a raw (DER-encoded) certificate to the list of stored public keys. The key
 * will be considered valid until the provided expiration time.
 *
 * The @tdb variable if non-null specifies a custom backend for
 * the storage of entries. If it is NULL then the
 * default file backend will be used.
 *
 * Unless an alternative @tdb is provided, the storage format is a textual format
 * consisting of a line for each host with fields separated by '|'. The contents of
 * the fields are a format-identifier which is set to 'g0', the hostname that the
 * rest of the data applies to, the numeric port or host name, the expiration
 * time in seconds since the epoch (0 for no expiration), and a base64
 * encoding of the raw (DER) public key information (SPKI) of the peer.
 *
 * As of GnuTLS 3.6.6 this function also accepts raw public keys.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0.13
 **/
int
gnutls_store_pubkey(const char *db_name,
		    gnutls_tdb_t tdb,
		    const char *host,
		    const char *service,
		    gnutls_certificate_type_t cert_type,
		    const gnutls_datum_t * cert,
		    time_t expiration, unsigned int flags)
{
	gnutls_datum_t pubkey = { NULL, 0 }; // Holds the pubkey in subjectPublicKeyInfo format (DER encoded)
	int ret;
	char local_file[MAX_FILENAME];
	bool need_free;


	if (db_name == NULL && tdb == NULL) {
		ret =
		    _gnutls_find_config_path(local_file,
					     sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_debug_log("Configuration path: %s\n", local_file);
		mkdir(local_file, 0700);

		ret = find_config_file(local_file, sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);
		db_name = local_file;
	}

	if (tdb == NULL)
		tdb = &default_tdb;

	/* Import the public key depending on the provided certificate type */
	switch (cert_type) {
		case GNUTLS_CRT_X509:
			/* Extract the pubkey from the cert. This function does a malloc
			 * deep down the call chain. We are responsible for freeing. */
			ret = _gnutls_x509_raw_crt_to_raw_pubkey(cert, &pubkey);

			if (ret < 0) {
				_gnutls_free_datum(&pubkey);
				return gnutls_assert_val(ret);
			}

			need_free = true;
			break;
		case GNUTLS_CRT_RAWPK:
			pubkey.data = cert->data;
			pubkey.size = cert->size;
			need_free = false;
			break;
		default:
			return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
	}

	_gnutls_debug_log("Configuration file: %s\n", db_name);

	tdb->store(db_name, host, service, expiration, &pubkey);

	if (need_free) {
		_gnutls_free_datum(&pubkey);
	}

	return GNUTLS_E_SUCCESS;
}
/**
 * gnutls_pkcs11_privkey_import_url:
 * @pkey: The structure to store the parsed key
 * @url: a PKCS 11 url identifying the key
 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
 *
 * This function will "import" a PKCS 11 URL identifying a private
 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
 * in most cases keys cannot be exported, the private key structure
 * is being associated with the available operations on the token.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
                                  const char *url, unsigned int flags)
{
  int ret;
  struct ck_function_list *module;
  struct ck_attribute *attr;
  ck_session_handle_t pks;
  ck_object_handle_t obj;
  struct ck_attribute a[4];
  ck_key_type_t key_type;

  ret = pkcs11_url_to_info (url, &pkey->info);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  pkey->flags = flags;

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
  if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
      *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
  if (!attr || !attr->value_len)
    {
      attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
      if (!attr || !attr->value_len)
        {
          gnutls_assert ();
          return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
        }
    }

  FIND_OBJECT (module, pks, obj, pkey);
  a[0].type = CKA_KEY_TYPE;
  a[0].value = &key_type;
  a[0].value_len = sizeof (key_type);

  if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
    {
      pkey->pk_algorithm = mech_to_pk(key_type);
      if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
        {
          _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
    }

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}
Beispiel #22
0
static int
do_device_source_urandom (int init)
{
  time_t now = gnutls_time (NULL);
  int read_size = DEVICE_READ_SIZE;

  if (init)
    {
      int old;

      device_fd = open ("/dev/urandom", O_RDONLY);
      if (device_fd < 0)
        {
          _gnutls_debug_log ("Cannot open urandom!\n");
          return GNUTLS_E_FILE_ERROR;
        }

      old = fcntl (device_fd, F_GETFD);
      fcntl (device_fd, F_SETFD, old | 1);
      device_last_read = now;

      read_size = DEVICE_READ_SIZE_MAX; /* initially read more data */
    }

  if ((device_fd > 0)
      && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL)))
    {
      /* More than a minute since we last read the device */
      uint8_t buf[DEVICE_READ_SIZE_MAX];
      uint32_t done;

      for (done = 0; done < read_size;)
        {
          int res;
          do
            res = read (device_fd, buf + done, sizeof (buf) - done);
          while (res < 0 && errno == EINTR);

          if (res <= 0)
            {
              if (res < 0)
                {
                  _gnutls_debug_log ("Failed to read /dev/urandom: %s\n",
                                     strerror (errno));
                }
              else
                {
                  _gnutls_debug_log
                    ("Failed to read /dev/urandom: end of file\n");
                }

              return GNUTLS_E_INTERNAL_ERROR;
            }

          done += res;
        }

      device_last_read = now;
      return yarrow256_update (&yctx, RANDOM_SOURCE_DEVICE,
                               read_size * 8 / 2 /* we trust the RNG */ ,
                               read_size, buf);
    }
  return 0;
}
Beispiel #23
0
/* Decodes the SafeContents, and puts the output in
 * the given bag. 
 */
int
_pkcs12_decode_safe_contents(const gnutls_datum_t * content,
			     gnutls_pkcs12_bag_t bag)
{
	char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	int len, result;
	int bag_type;
	gnutls_datum_t attr_val;
	gnutls_datum_t t;
	int count = 0, i, attributes, j;

	/* Step 1. Extract the SEQUENCE.
	 */

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

	result =
	    asn1_der_decoding(&c2, content->data, content->size, NULL);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* Count the number of bags
	 */
	result = asn1_number_of_elements(c2, "", &count);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	bag->bag_elements = MIN(MAX_BAG_ELEMENTS, count);

	for (i = 0; i < bag->bag_elements; i++) {

		snprintf(root, sizeof(root), "?%u.bagId", i + 1);

		len = sizeof(oid);
		result = asn1_read_value(c2, root, oid, &len);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		/* Read the Bag type
		 */
		bag_type = oid2bag(oid);

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

		/* Read the Bag Value
		 */

		snprintf(root, sizeof(root), "?%u.bagValue", i + 1);

		result =
		    _gnutls_x509_read_value(c2, root,
					    &bag->element[i].data);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (bag_type == GNUTLS_BAG_CERTIFICATE
		    || bag_type == GNUTLS_BAG_CRL
		    || bag_type == GNUTLS_BAG_SECRET) {
			gnutls_datum_t tmp = bag->element[i].data;

			result =
			    _pkcs12_decode_crt_bag(bag_type, &tmp,
						   &bag->element[i].data);
			if (result < 0) {
				gnutls_assert();
				goto cleanup;
			}

			_gnutls_free_datum(&tmp);
		}

		/* read the bag attributes
		 */
		snprintf(root, sizeof(root), "?%u.bagAttributes", i + 1);

		result = asn1_number_of_elements(c2, root, &attributes);
		if (result != ASN1_SUCCESS
		    && result != ASN1_ELEMENT_NOT_FOUND) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		if (attributes < 0)
			attributes = 1;

		if (result != ASN1_ELEMENT_NOT_FOUND)
			for (j = 0; j < attributes; j++) {

				snprintf(root, sizeof(root),
					 "?%u.bagAttributes.?%u", i + 1,
					 j + 1);

				result =
				    _gnutls_x509_decode_and_read_attribute
				    (c2, root, oid, sizeof(oid), &attr_val,
				     1, 0);

				if (result < 0) {
					gnutls_assert();
					continue;	/* continue in case we find some known attributes */
				}

				if (strcmp(oid, KEY_ID_OID) == 0) {
					result =
					    _gnutls_x509_decode_string
					    (ASN1_ETYPE_OCTET_STRING,
					     attr_val.data, attr_val.size,
					     &t);
					_gnutls_free_datum(&attr_val);
					if (result < 0) {
						gnutls_assert();
						_gnutls_debug_log
						    ("Error decoding PKCS12 Bag Attribute OID '%s'\n",
						     oid);
						continue;
					}

					attr_val.data = t.data;
					attr_val.size = t.size;

					bag->element[i].local_key_id =
					    attr_val;
				} else if (strcmp(oid, FRIENDLY_NAME_OID)
					   == 0) {
					result =
					    _gnutls_x509_decode_string
					    (ASN1_ETYPE_BMP_STRING,
					     attr_val.data, attr_val.size,
					     &t);
					_gnutls_free_datum(&attr_val);
					if (result < 0) {
						gnutls_assert();
						_gnutls_debug_log
						    ("Error decoding PKCS12 Bag Attribute OID '%s'\n",
						     oid);
						continue;
					}

					attr_val.data = t.data;
					attr_val.size = t.size;

					bag->element[i].friendly_name =
					    (char *) t.data;
				} else {
					_gnutls_free_datum(&attr_val);
					_gnutls_debug_log
					    ("Unknown PKCS12 Bag Attribute OID '%s'\n",
					     oid);
				}
			}


		bag->element[i].type = bag_type;

	}

	asn1_delete_structure(&c2);


	return 0;

      cleanup:
	if (c2)
		asn1_delete_structure(&c2);
	return result;

}
Beispiel #24
0
int
_gnutls_compress (comp_hd_t handle, const opaque * plain,
		  size_t plain_size, opaque ** compressed,
		  size_t max_comp_size)
{
  int compressed_size = GNUTLS_E_COMPRESSION_FAILED;
  int err;

  /* NULL compression is not handled here
   */
  if (handle == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  switch (handle->algo)
    {
#ifdef USE_LZO
    case GNUTLS_COMP_LZO:
      {
	lzo_uint out_len;
	size_t size;

	if (_gnutls_lzo1x_1_compress == NULL)
	  return GNUTLS_E_COMPRESSION_FAILED;

	size = plain_size + plain_size / 64 + 16 + 3;
	*compressed = gnutls_malloc (size);
	if (*compressed == NULL)
	  {
	    gnutls_assert ();
	    return GNUTLS_E_MEMORY_ERROR;
	  }

	err = _gnutls_lzo1x_1_compress (plain, plain_size, *compressed,
					&out_len, handle->handle);

	if (err != LZO_E_OK)
	  {
	    gnutls_assert ();
	    gnutls_free (*compressed);
	    *compressed = NULL;
	    return GNUTLS_E_COMPRESSION_FAILED;
	  }

	compressed_size = out_len;
	break;
      }
#endif
#ifdef HAVE_LIBZ
    case GNUTLS_COMP_DEFLATE:
      {
	uLongf size;
	z_stream *zhandle;

	size = (plain_size + plain_size) + 10;
	*compressed = gnutls_malloc (size);
	if (*compressed == NULL)
	  {
	    gnutls_assert ();
	    return GNUTLS_E_MEMORY_ERROR;
	  }

	zhandle = handle->handle;

	zhandle->next_in = (Bytef *) plain;
	zhandle->avail_in = plain_size;
	zhandle->next_out = (Bytef *) * compressed;
	zhandle->avail_out = size;

	err = deflate (zhandle, Z_SYNC_FLUSH);

	if (err != Z_OK || zhandle->avail_in != 0)
	  {
	    gnutls_assert ();
	    gnutls_free (*compressed);
	    *compressed = NULL;
	    return GNUTLS_E_COMPRESSION_FAILED;
	  }

	compressed_size = size - zhandle->avail_out;
	break;
      }
#endif
    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }				/* switch */

#ifdef COMPRESSION_DEBUG
  _gnutls_debug_log ("Compression ratio: %f\n",
		     (float) ((float) compressed_size / (float) plain_size));
#endif

  if ((size_t) compressed_size > max_comp_size)
    {
      gnutls_free (*compressed);
      *compressed = NULL;
      return GNUTLS_E_COMPRESSION_FAILED;
    }

  return compressed_size;
}
Beispiel #25
0
/**
 * gnutls_global_init:
 *
 * This function performs any required precalculations, detects
 * the supported CPU capabilities and initializes the underlying
 * cryptographic backend. In order to free any resources 
 * taken by this call you should gnutls_global_deinit() 
 * when gnutls usage is no longer needed.
 *
 * This function increments a global counter, so that
 * gnutls_global_deinit() only releases resources when it has been
 * called as many times as gnutls_global_init().  This is useful when
 * GnuTLS is used by more than one library in an application.  This
 * function can be called many times, but will only do something the
 * first time.
 *
 * Note!  This function is not thread safe.  If two threads call this
 * function simultaneously, they can cause a race between checking
 * the global counter and incrementing it, causing both threads to
 * execute the library initialization code.  That would lead to a
 * memory leak.  To handle this, your application could invoke this
 * function after aquiring a thread mutex.  To ignore the potential
 * memory leak is also an option.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_global_init (void)
{
  int result = 0;
  int res;

  if (_gnutls_init++)
    goto out;

  if (gl_sockets_startup (SOCKETS_1_1))
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);

  bindtextdomain (PACKAGE, LOCALEDIR);

  res = gnutls_crypto_init ();
  if (res != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_CRYPTO_INIT_FAILED;
    }

  _gnutls_register_accel_crypto();

  /* initialize ASN.1 parser
   * This should not deal with files in the final
   * version.
   */
  if (asn1_check_version (GNUTLS_MIN_LIBTASN1_VERSION) == NULL)
    {
      gnutls_assert ();
      _gnutls_debug_log ("Checking for libtasn1 failed: %s < %s\n",
                         asn1_check_version (NULL),
                         GNUTLS_MIN_LIBTASN1_VERSION);
      return GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY;
    }

  res = asn1_array2tree (pkix_asn1_tab, &_gnutls_pkix1_asn, NULL);
  if (res != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (res);
      goto out;
    }

  res = asn1_array2tree (gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
  if (res != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (res);
      goto out;
    }

  /* Initialize the random generator */
  result = _gnutls_rnd_init ();
  if (result < 0)
    {
      gnutls_assert ();
      goto out;
    }

  /* Initialize the default TLS extensions */
  result = _gnutls_ext_init ();
  if (result < 0)
    {
      gnutls_assert ();
      goto out;
    }

  result = gnutls_mutex_init(&_gnutls_file_mutex);
  if (result < 0)
    {
      gnutls_assert();
      goto out;
    }

  result = gnutls_system_global_init ();
  if (result < 0)
    {
      gnutls_assert ();
      goto out;
    }

#ifdef ENABLE_PKCS11
  gnutls_pkcs11_init (GNUTLS_PKCS11_FLAG_AUTO, NULL);
#endif

  _gnutls_cryptodev_init ();

out:
  return result;
}
Beispiel #26
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_server_name_send_params(gnutls_session_t session,
				gnutls_buffer_st * extdata)
{
	uint16_t len;
	unsigned i;
	int total_size = 0, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0)
		return 0;

	/* this function sends the client extension data (dnsname)
	 */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		priv = epriv;

		if (priv->server_names_size == 0)
			return 0;

		/* uint16_t
		 */
		total_size = 2;
		for (i = 0; i < priv->server_names_size; i++) {
			/* count the total size
			 */
			len = priv->server_names[i].name_length;

			/* uint8_t + uint16_t + size
			 */
			total_size += 1 + 2 + len;
		}

		/* UINT16: write total size of all names
		 */
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 total_size - 2);
		if (ret < 0)
			return gnutls_assert_val(ret);

		for (i = 0; i < priv->server_names_size; i++) {

			switch (priv->server_names[i].type) {
			case GNUTLS_NAME_DNS:
				len = priv->server_names[i].name_length;
				if (len == 0)
					break;

				/* UINT8: type of this extension
				 * UINT16: size of the first name
				 * LEN: the actual server name.
				 */
				ret =
				    _gnutls_buffer_append_prefix(extdata,
								 8, 0);
				if (ret < 0)
					return gnutls_assert_val(ret);

				_gnutls_debug_log("HSK[%p]: sent server name: '%s'\n", session, priv->server_names[i].name);

				ret =
				    _gnutls_buffer_append_data_prefix
				    (extdata, 16,
				     priv->server_names[i].name, len);
				if (ret < 0)
					return gnutls_assert_val(ret);

				break;
			default:
				gnutls_assert();
				return GNUTLS_E_INTERNAL_ERROR;
			}
		}
	}

	return total_size;
}
Beispiel #27
0
/**
 * gnutls_openpgp_keyring_import:
 * @keyring: The structure to store the parsed key.
 * @data: The RAW or BASE64 encoded keyring.
 * @format: One of #gnutls_openpgp_keyring_fmt elements.
 *
 * This function will convert the given RAW or Base64 encoded keyring
 * to the native #gnutls_openpgp_keyring_t format.  The output will be
 * stored in 'keyring'.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring,
                               const gnutls_datum_t * data,
                               gnutls_openpgp_crt_fmt_t format)
{
    cdk_error_t err;
    cdk_stream_t input = NULL;
    size_t raw_len = 0;
    uint8_t *raw_data = NULL;

    if (data->data == NULL || data->size == 0)
    {
        gnutls_assert ();
        return GNUTLS_E_OPENPGP_GETKEY_FAILED;
    }

    _gnutls_debug_log ("PGP: keyring import format '%s'\n",
                       format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");

    /* Create a new stream from the given data, decode it, and import
     * the raw database. This to avoid using opencdk streams which are
     * not thread safe.
     */
    if (format == GNUTLS_OPENPGP_FMT_BASE64)
    {
        size_t written = 0;

        err = cdk_stream_tmp_from_mem (data->data, data->size, &input);
        if (err == 0)
            err = cdk_stream_set_armor_flag (input, 0);
        if (err)
        {
            gnutls_assert ();
            err = _gnutls_map_cdk_rc (err);
            goto error;
        }

        raw_len = cdk_stream_get_length (input);
        if (raw_len == 0)
        {
            gnutls_assert ();
            err = GNUTLS_E_BASE64_DECODING_ERROR;
            goto error;
        }

        raw_data = gnutls_malloc (raw_len);
        if (raw_data == NULL)
        {
            gnutls_assert ();
            err = GNUTLS_E_MEMORY_ERROR;
            goto error;
        }

        do
        {
            err =
                cdk_stream_read (input, raw_data + written, raw_len - written);

            if (err > 0)
                written += err;
        }
        while (written < raw_len && err != EOF && err > 0);

        raw_len = written;
    }
    else
    {   /* RAW */
        raw_len = data->size;
        raw_data = data->data;
    }

    err = cdk_keydb_new_from_mem (&keyring->db, 0, 0, raw_data, raw_len);
    if (err)
        gnutls_assert ();

    return _gnutls_map_cdk_rc (err);

error:
    gnutls_free (raw_data);
    cdk_stream_close (input);

    return err;
}
Beispiel #28
0
/* Writes the digest information and the digest in a DER encoded
 * structure. The digest info is allocated and stored into the info structure.
 */
int
encode_ber_digest_info(const mac_entry_st * e,
		       const gnutls_datum_t * digest,
		       gnutls_datum_t * output)
{
	ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
	int result;
	const char *algo;
	uint8_t *tmp_output;
	int tmp_output_size;

	algo = _gnutls_x509_mac_to_oid(e);
	if (algo == NULL) {
		gnutls_assert();
		_gnutls_debug_log("Hash algorithm: %d has no OID\n",
				  e->id);
		return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
					  "GNUTLS.DigestInfo",
					  &dinfo)) != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	result =
	    asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return _gnutls_asn2err(result);
	}

	/* Write an ASN.1 NULL in the parameters field.  This matches RFC
	   3279 and RFC 4055, although is arguable incorrect from a historic
	   perspective (see those documents for more information).
	   Regardless of what is correct, this appears to be what most
	   implementations do.  */
	result = asn1_write_value(dinfo, "digestAlgorithm.parameters",
				  ASN1_NULL, ASN1_NULL_SIZE);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return _gnutls_asn2err(result);
	}

	result =
	    asn1_write_value(dinfo, "digest", digest->data, digest->size);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return _gnutls_asn2err(result);
	}

	tmp_output_size = 0;
	result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL);
	if (result != ASN1_MEM_ERROR) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return _gnutls_asn2err(result);
	}

	tmp_output = gnutls_malloc(tmp_output_size);
	if (tmp_output == NULL) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return GNUTLS_E_MEMORY_ERROR;
	}

	result =
	    asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		asn1_delete_structure(&dinfo);
		return _gnutls_asn2err(result);
	}

	asn1_delete_structure(&dinfo);

	output->size = tmp_output_size;
	output->data = tmp_output;

	return 0;
}
Beispiel #29
0
/**
 * gnutls_x509_trust_list_add_crls:
 * @list: The list
 * @crl_list: A list of CRLs
 * @crl_size: The length of the CRL list
 * @flags: flags from %gnutls_trust_list_flags_t
 * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
 *
 * This function will add the given certificate revocation lists
 * to the trusted list. The CRLs in @crl_list must not be deinitialized
 * during the lifetime of @list.
 *
 * This function must be called after gnutls_x509_trust_list_add_cas()
 * to allow verifying the CRLs for validity. If the flag %GNUTLS_TL_NO_DUPLICATES
 * is given, then the final CRL list will not contain duplicate entries.
 *
 * If the flag %GNUTLS_TL_NO_DUPLICATES is given, gnutls_x509_trust_list_deinit() must be
 * called with parameter @all being 1.
 *
 * If flag %GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added,
 * and if verification fails, they will be skipped.
 *
 * Returns: The number of added elements is returned; that includes
 *          duplicate entries.
 *
 * Since: 3.0
 **/
int
gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
				const gnutls_x509_crl_t * crl_list,
				unsigned crl_size, unsigned int flags,
				unsigned int verification_flags)
{
	int ret;
	unsigned x, i, j = 0;
	unsigned int vret = 0;
	uint32_t hash;
	gnutls_x509_crl_t *tmp;

	/* Probably we can optimize things such as removing duplicates
	 * etc.
	 */
	if (crl_size == 0 || crl_list == NULL)
		return 0;

	for (i = 0; i < crl_size; i++) {
		hash =
		    hash_pjw_bare(crl_list[i]->raw_issuer_dn.data,
				  crl_list[i]->raw_issuer_dn.size);
		hash %= list->size;

		if (flags & GNUTLS_TL_VERIFY_CRL) {

			ret =
			    gnutls_x509_crl_verify(crl_list[i],
						   list->node[hash].
						   trusted_cas,
						   list->node[hash].
						   trusted_ca_size,
						   verification_flags,
						   &vret);
			if (ret < 0 || vret != 0) {
				_gnutls_debug_log("CRL verification failed, not adding it\n");
				if (flags & GNUTLS_TL_NO_DUPLICATES)
					gnutls_x509_crl_deinit(crl_list[i]);
				if (flags & GNUTLS_TL_FAIL_ON_INVALID_CRL)
					return gnutls_assert_val(GNUTLS_E_CRL_VERIFICATION_ERROR);
				continue;
			}
		}

		/* If the CRL added overrides a previous one, then overwrite
		 * the old one */
		if (flags & GNUTLS_TL_NO_DUPLICATES) {
			for (x=0;x<list->node[hash].crl_size;x++) {
				if (crl_list[i]->raw_issuer_dn.size == list->node[hash].crls[x]->raw_issuer_dn.size &&
				    memcmp(crl_list[i]->raw_issuer_dn.data, list->node[hash].crls[x]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size) == 0) {
					if (gnutls_x509_crl_get_this_update(crl_list[i]) >=
					    gnutls_x509_crl_get_this_update(list->node[hash].crls[x])) {

						gnutls_x509_crl_deinit(list->node[hash].crls[x]);
						list->node[hash].crls[x] = crl_list[i];
						goto next;
					} else {
						/* The new is older, discard it */
						gnutls_x509_crl_deinit(crl_list[i]);
						goto next;
					}
				}
			}
		}

		tmp =
		    gnutls_realloc(list->node[hash].crls,
					(list->node[hash].crl_size +
					 1) *
					sizeof(list->node[hash].
					       crls[0]));
		if (tmp == NULL) {
			ret = i;
			gnutls_assert();
			if (flags & GNUTLS_TL_NO_DUPLICATES)
				while (i < crl_size)
					gnutls_x509_crl_deinit(crl_list[i++]);
			return ret;
		}
		list->node[hash].crls = tmp;


		list->node[hash].crls[list->node[hash].crl_size] =
		    crl_list[i];
		list->node[hash].crl_size++;

 next:
		j++;
	}

	return j;
}
Beispiel #30
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;

}