Exemplo n.º 1
0
/**
 * gnutls_x509_privkey_export_ecc_raw:
 * @key: a structure that holds the rsa parameters
 * @curve: will hold the curve
 * @x: will hold the x coordinate
 * @y: will hold the y coordinate
 * @k: will hold the private key
 *
 * This function will export the ECC private key's parameters found
 * in the given structure. The new parameters will be allocated using
 * gnutls_malloc() and will be stored in the appropriate datum.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int gnutls_x509_privkey_export_ecc_raw (gnutls_x509_privkey_t key, 
                                        gnutls_ecc_curve_t *curve,  
                                        gnutls_datum_t * x, gnutls_datum_t * y,
                                        gnutls_datum_t* k)
{
  int ret;

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

  *curve = key->params.flags;

  /* X */
  ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_X], x);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* Y */
  ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_Y], y);
  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (x);
      return ret;
    }


  /* K */
  ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_K], k);
  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (x);
      _gnutls_free_datum (y);
      return ret;
    }

  return 0;

}
Exemplo n.º 2
0
/**
 * gnutls_x509_trust_list_add_crls:
 * @list: The structure of the list
 * @crl_list: A list of CRLs
 * @crl_size: The length of the CRL list
 * @flags: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added.
 * @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 list of CRLs must not be deinitialized
 * during this structure's lifetime.
 *
 * This function must be called after gnutls_x509_trust_list_add_cas()
 * to allow verifying the CRLs for validity.
 *
 * Returns: The number of added elements is returned.
 *
 * Since: 3.0.0
 **/
int
gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
                                const gnutls_x509_crl_t * crl_list,
                                int crl_size, unsigned int flags,
                                unsigned int verification_flags)
{
    int ret, i, j = 0;
    gnutls_datum_t dn;
    unsigned int vret = 0;
    uint32_t hash;

    /* 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++) {
        ret = gnutls_x509_crl_get_raw_issuer_dn(crl_list[i], &dn);
        if (ret < 0) {
            gnutls_assert();
            return i;
        }

        hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
        hash %= list->size;

        _gnutls_free_datum(&dn);

        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)
                continue;
        }

        list->node[hash].crls =
            gnutls_realloc_fast(list->node[hash].crls,
                                (list->node[hash].crl_size +
                                 1) *
                                sizeof(list->node[hash].trusted_cas[0]));
        if (list->node[hash].crls == NULL) {
            gnutls_assert();
            return i;
        }

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

    return j;
}
Exemplo n.º 3
0
/**
 * gnutls_pkcs7_get_crl_raw:
 * @pkcs7: should contain a #gnutls_pkcs7_t structure
 * @indx: contains the index of the crl to extract
 * @crl: the contents of the crl will be copied there (may be null)
 * @crl_size: should hold the size of the crl
 *
 * This function will return a crl of the PKCS7 or RFC2630 crl set.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.  If the provided buffer is not long enough,
 *   then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
 *   returned.  After the last crl has been read
 *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
 **/
int
gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7,
			 int indx, void *crl, size_t * crl_size)
{
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	int result;
	char root2[ASN1_MAX_NAME_SIZE];
	gnutls_datum_t tmp = { NULL, 0 };
	int start, end;

	if (pkcs7 == NULL || crl_size == NULL)
		return GNUTLS_E_INVALID_REQUEST;

	/* Step 1. decode the signed data.
	 */
	result = _decode_pkcs7_signed_data(pkcs7->pkcs7, &c2, &tmp);
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	/* Step 2. Parse the CertificateSet 
	 */

	snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);

	/* Get the raw CRL 
	 */
	result = asn1_der_decoding_startEnd(c2, tmp.data, tmp.size,
					    root2, &start, &end);

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

	end = end - start + 1;

	if ((unsigned) end > *crl_size) {
		*crl_size = end;
		result = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	if (crl)
		memcpy(crl, &tmp.data[start], end);

	*crl_size = end;

	result = 0;

      cleanup:
	_gnutls_free_datum(&tmp);
	if (c2)
		asn1_delete_structure(&c2);
	return result;
}
Exemplo n.º 4
0
/* This function will convert an attribute value, specified by the OID,
 * to a string. The result will be a null terminated string.
 *
 * res may be null. This will just return the res_size, needed to
 * hold the string.
 */
int
_gnutls_x509_dn_to_string(const char *oid, void *value,
			  int value_size, gnutls_datum_t * str)
{
	const struct oid_to_string *oentry;
	int ret;
	gnutls_datum_t tmp;
	size_t size;

	if (value == NULL || value_size <= 0) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	oentry = get_oid_entry(oid);
	if (oentry == NULL) {	/* unknown OID -> hex */
 unknown_oid:
		str->size = value_size * 2 + 2;
		str->data = gnutls_malloc(str->size);
		if (str->data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		size = str->size;
		ret = data2hex(value, value_size, str->data, &size);
		if (ret < 0) {
			gnutls_assert();
			gnutls_free(str->data);
			return ret;
		}
		str->size = size;
		return 0;
	}

	if (oentry->asn_desc != NULL) {	/* complex */
		ret =
		    decode_complex_string(oentry, value, value_size, &tmp);
		if (ret < 0) {
			/* we failed decoding -> handle it as unknown OID */
			goto unknown_oid;
		}
	} else {
		ret =
		    _gnutls_x509_decode_string(oentry->etype, value,
					       value_size, &tmp);
		if (ret < 0) {
			/* we failed decoding -> handle it as unknown OID */
			goto unknown_oid;
		}
	}

	ret = str_escape(&tmp, str);
	_gnutls_free_datum(&tmp);

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

	return 0;
}
Exemplo n.º 5
0
int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf)
{
	int ret;
	uint8_t value;
	tls13_ticket_st *ticket = &session->internals.tls13_ticket;
	gnutls_datum_t t;
	size_t val;

	if (unlikely(buf == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	_gnutls_free_datum(&ticket->ticket);
	memset(ticket, 0, sizeof(tls13_ticket_st));

	_gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session);

	/* ticket_lifetime */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->lifetime = val;

	/* ticket_age_add */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->age_add = val;

	/* ticket_nonce */
	ret = _gnutls_buffer_pop_prefix8(buf, &value, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ticket->nonce_size = value;
	ret = _gnutls_buffer_pop_data(buf, ticket->nonce, ticket->nonce_size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* ticket */
	ret = _gnutls_buffer_pop_datum_prefix16(buf, &t);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_free(ticket->ticket.data);
	ret = _gnutls_set_datum(&ticket->ticket, t.data, t.size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Extensions */
	ret = _gnutls_extv_parse(session, parse_nst_extension, buf->data, buf->length);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Record the ticket arrival time */
	gnutls_gettime(&ticket->arrival_time);

	return 0;
}
Exemplo n.º 6
0
/* Takes a certificate list and shortens it if there are
 * intermedia certificates already trusted by us.
 *
 * FIXME: This is very similar to _gnutls_x509_verify_certificate().
 *
 * Returns the new size of the list or a negative number on error.
 */
static int shorten_clist(gnutls_x509_trust_list_t list,
                         gnutls_x509_crt_t * certificate_list,
                         int clist_size)
{
    int i, ret;
    uint32_t hash;
    gnutls_datum_t dn;

    if (clist_size > 1) {
        /* Check if the last certificate in the path is self signed.
         * In that case ignore it (a certificate is trusted only if it
         * leads to a trusted party by us, not the server's).
         *
         * This prevents from verifying self signed certificates against
         * themselves. This (although not bad) caused verification
         * failures on some root self signed certificates that use the
         * MD2 algorithm.
         */
        if (gnutls_x509_crt_check_issuer(certificate_list[clist_size - 1],
                                         certificate_list[clist_size -
                                                          1]) > 0) {
            clist_size--;
        }
    }

    /* We want to shorten the chain by removing the cert that matches
     * one of the certs we trust and all the certs after that i.e. if
     * cert chain is A signed-by B signed-by C signed-by D (signed-by
     * self-signed E but already removed above), and we trust B, remove
     * B, C and D. */
    for (i = 1; i < clist_size; i++) {
        int j;

        ret = gnutls_x509_crt_get_raw_issuer_dn(certificate_list[i], &dn);
        if (ret < 0) {
            gnutls_assert();
            return ret;
        }

        hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
        hash %= list->size;

        _gnutls_free_datum(&dn);

        for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
            if (check_if_same_cert
                (certificate_list[i],
                 list->node[hash].trusted_cas[j]) == 0) {
                /* cut the list at the point of first the trusted certificate */
                clist_size = i + 1;
                break;
            }
        }
        /* clist_size may have been changed which gets out of loop */
    }

    return clist_size;
}
Exemplo n.º 7
0
/**
  * gnutls_pkcs12_bag_decrypt - This function will decrypt an encrypted bag
  * @bag: The bag
  * @pass: The password used for encryption. This can only be ASCII.
  *
  * This function will decrypt the given encrypted bag and return 0 on success.
  *
  **/
int
gnutls_pkcs12_bag_decrypt (gnutls_pkcs12_bag_t bag, const char *pass)
{
  int ret;
  gnutls_datum_t dec;

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

  if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  ret = _gnutls_pkcs7_decrypt_data (&bag->element[0].data, pass, &dec);

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

  /* decryption succeeded. Now decode the SafeContents
   * stuff, and parse it.
   */

  _gnutls_free_datum (&bag->element[0].data);

  ret = _pkcs12_decode_safe_contents (&dec, bag);

  _gnutls_free_datum (&dec);

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

  return 0;
}
Exemplo n.º 8
0
static int
_get_authority_key_id(gnutls_x509_crl_t cert, ASN1_TYPE * c2,
		      unsigned int *critical)
{
	int ret;
	gnutls_datum_t id;

	*c2 = ASN1_TYPE_EMPTY;

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

	if ((ret =
	     _gnutls_x509_crl_get_extension(cert, "2.5.29.35", 0, &id,
					    critical)) < 0) {
		return gnutls_assert_val(ret);
	}

	if (id.size == 0 || id.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	ret = asn1_create_element
	    (_gnutls_get_pkix(), "PKIX1.AuthorityKeyIdentifier", c2);
	if (ret != ASN1_SUCCESS) {
		gnutls_assert();
		_gnutls_free_datum(&id);
		return _gnutls_asn2err(ret);
	}

	ret = asn1_der_decoding(c2, id.data, id.size, NULL);
	_gnutls_free_datum(&id);

	if (ret != ASN1_SUCCESS) {
		gnutls_assert();
		asn1_delete_structure(c2);
		return _gnutls_asn2err(ret);
	}

	return 0;
}
Exemplo n.º 9
0
/**
  * gnutls_psk_set_client_credentials - Used to set the username/password, in a gnutls_psk_client_credentials_t structure
  * @res: is a #gnutls_psk_client_credentials_t structure.
  * @username: is the user's zero-terminated userid
  * @key: is the user's key
  * @format: indicate the format of the key, either
  * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX.
  *
  * This function sets the username and password, in a
  * gnutls_psk_client_credentials_t structure.  Those will be used in
  * PSK authentication. @username should be an ASCII string or UTF-8
  * strings prepared using the "SASLprep" profile of "stringprep".
  * The key can be either in raw byte format or in Hex (not with the
  * '0x' prefix).
  *
  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
  **/
int
gnutls_psk_set_client_credentials (gnutls_psk_client_credentials_t res,
				   const char *username,
				   const gnutls_datum_t * key,
				   gnutls_psk_key_flags flags)
{
  int ret;

  if (username == NULL || key == NULL || key->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  ret = _gnutls_set_datum (&res->username, username, strlen (username));
  if (ret < 0)
    return ret;

  if (flags == GNUTLS_PSK_KEY_RAW)
    {
      if (_gnutls_set_datum (&res->key, key->data, key->size) < 0)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_MEMORY_ERROR;
	  goto error;
	}
    }
  else
    {				/* HEX key */
      size_t size;
      size = res->key.size = key->size / 2;
      res->key.data = gnutls_malloc (size);
      if (res->key.data == NULL)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_MEMORY_ERROR;
	  goto error;
	}

      ret = gnutls_hex_decode (key, (char *) res->key.data, &size);
      res->key.size = (unsigned int) size;
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto error;
	}

    }

  return 0;

error:
  _gnutls_free_datum (&res->username);

  return ret;
}
Exemplo n.º 10
0
/**
 * gnutls_x509_trust_list_verify_named_crt:
 * @list: The structure of the list
 * @cert: is the certificate to be verified
 * @name: is the certificate's name
 * @name_size: is the certificate's name size
 * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
 * @verify: will hold the certificate verification output.
 * @func: If non-null will be called on each chain element verification with the output.
 *
 * This function will try to find a matching named certificate. If a
 * match is found the certificate is considered valid. In addition to that
 * this function will also check CRLs.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
                                        gnutls_x509_crt_t cert,
                                        const void *name,
                                        size_t name_size,
                                        unsigned int flags,
                                        unsigned int *verify,
                                        gnutls_verify_output_function func)
{
    gnutls_datum_t dn;
    int ret;
    unsigned int i;
    uint32_t hash;

    ret = gnutls_x509_crt_get_raw_issuer_dn(cert, &dn);
    if (ret < 0) {
        gnutls_assert();
        return ret;
    }

    hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
    hash %= list->size;

    _gnutls_free_datum(&dn);

    *verify = GNUTLS_CERT_INVALID;

    for (i = 0; i < list->node[hash].named_cert_size; i++) {
        if (check_if_same_cert(cert, list->node[hash].named_certs[i].cert) == 0) {      /* check if name matches */
            if (list->node[hash].named_certs[i].name_size == name_size &&
                memcmp(list->node[hash].named_certs[i].name, name,
                       name_size) == 0) {
                *verify = 0;
                break;
            }
        }
    }

    if (*verify != 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->node[hash].crls,
                                            list->node[hash].crl_size,
                                            func);
    if (ret == 1) {             /* revoked */
        *verify |= GNUTLS_CERT_REVOKED;
        *verify |= GNUTLS_CERT_INVALID;
        return 0;
    }

    return 0;
}
Exemplo n.º 11
0
/* If the psk flag is set, then an empty psk_identity_hint will
 * be inserted */
int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
					gnutls_buffer_st * data,
					gnutls_ecc_curve_t curve)
{
	uint8_t p;
	int ret;
	gnutls_datum_t out;

	if (curve == GNUTLS_ECC_CURVE_INVALID)
		return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);

	/* just in case we are resuming a session */
	gnutls_pk_params_release(&session->key.ecdh_params);

	gnutls_pk_params_init(&session->key.ecdh_params);

	/* curve type */
	p = 3;

	ret = _gnutls_buffer_append_data(data, &p, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_prefix(data, 16,
					 _gnutls_ecc_curve_get_tls_id
					 (curve));
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* generate temporal key */
	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
				     &session->key.ecdh_params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_ecc_ansi_x963_export(curve,
					 session->key.ecdh_params.
					 params[ECC_X] /* x */ ,
					 session->key.ecdh_params.
					 params[ECC_Y] /* y */ , &out);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);

	_gnutls_free_datum(&out);

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

	return data->length;
}
Exemplo n.º 12
0
static int
gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret, free;
	gnutls_psk_client_credentials_t cred;
	gnutls_datum_t username, key;

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

	if (cred == NULL)
		return
		    gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);

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

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

	/* The PSK key is set in there */
	ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length;

      cleanup:
	if (free) {
		_gnutls_free_datum(&username);
		_gnutls_free_datum(&key);
	}

	return ret;
}
Exemplo n.º 13
0
/* if hash==MD5 then we do RSA-MD5
 * if hash==SHA then we do RSA-SHA
 * params[0] is modulus
 * params[1] is public key
 */
static int
pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text,
		bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest, info;

  ret = _gnutls_hash_init (&hd, HASH2MAC (hash));
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash));

  /* Encode the digest as a DigestInfo
   */
  if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0)
    {
      gnutls_assert ();
      return ret;
    }

  if ((ret =
       _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info,
		     signature)) < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&info);
      return ret;
    }

  _gnutls_free_datum (&info);

  return 0;
}
Exemplo n.º 14
0
/* Free all the entry parameters, except if g and n are
 * the static ones defined in gnutls.h
 */
void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry)
{
	_gnutls_free_key_datum(&entry->v);
	_gnutls_free_datum(&entry->salt);

	if ((entry->g.data != gnutls_srp_1024_group_generator.data)
	    && (entry->g.data != gnutls_srp_3072_group_generator.data))
		_gnutls_free_datum(&entry->g);

	if (entry->n.data != gnutls_srp_1024_group_prime.data &&
	    entry->n.data != gnutls_srp_1536_group_prime.data &&
	    entry->n.data != gnutls_srp_2048_group_prime.data &&
	    entry->n.data != gnutls_srp_3072_group_prime.data &&
	    entry->n.data != gnutls_srp_4096_group_prime.data)
		_gnutls_free_datum(&entry->n);

	gnutls_free(entry->username);
	gnutls_free(entry);
}
Exemplo n.º 15
0
/**
 * gnutls_privkey_sign_data:
 * @signer: Holds the key
 * @hash: should be a digest algorithm
 * @flags: Zero or one of %gnutls_privkey_flags_t
 * @data: holds the data to be signed
 * @signature: will contain the signature allocate with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only the SHA family for the DSA keys.
 *
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 * negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_privkey_sign_data(gnutls_privkey_t signer,
			 gnutls_digest_algorithm_t hash,
			 unsigned int flags,
			 const gnutls_datum_t * data,
			 gnutls_datum_t * signature)
{
	int ret;
	gnutls_datum_t digest;
	const mac_entry_st *me = mac_to_entry(hash);

	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = pk_prepare_hash(signer->pk_algorithm, me, &digest);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    gnutls_privkey_sign_raw_data(signer, flags, &digest,
					 signature);
	_gnutls_free_datum(&digest);

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

	return 0;

      cleanup:
	_gnutls_free_datum(&digest);
	return ret;
}
Exemplo n.º 16
0
/* returns ciphertext which contains the headers too. This also
 * calculates the size in the header field.
 * 
 * If random pad != 0 then the random pad data will be appended.
 */
int
_gnutls_encrypt (gnutls_session_t session, const opaque * headers,
                 size_t headers_size, const opaque * data,
                 size_t data_size, opaque * ciphertext,
                 size_t ciphertext_size, content_type_t type, int random_pad,
                 record_parameters_st * params)
{
  gnutls_datum_t plain;
  gnutls_datum_t comp;
  int ret;
  int free_comp = 1;

  plain.data = (opaque *) data;
  plain.size = data_size;

  if (plain.size == 0 || is_write_comp_null (session) == 0)
    {
      comp = plain;
      free_comp = 0;
    }
  else
    {
      /* Here comp is allocated and must be 
       * freed.
       */
      ret = _gnutls_m_plaintext2compressed (session, &comp, &plain, params);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }
    }

  ret = _gnutls_compressed2ciphertext (session, &ciphertext[headers_size],
                                       ciphertext_size - headers_size,
                                       comp, type, random_pad, params);

  if (free_comp)
    _gnutls_free_datum (&comp);

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


  /* copy the headers */
  memcpy (ciphertext, headers, headers_size);
  _gnutls_write_uint16 (ret, &ciphertext[3]);

  return ret + headers_size;
}
Exemplo n.º 17
0
/**
  * gnutls_x509_crq_sign2 - This function will sign a Certificate request with a key
  * @crq: should contain a gnutls_x509_crq_t structure
  * @key: holds a private key
  * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing.
  * @flags: must be 0
  *
  * This function will sign the certificate request with a private key.
  * This must be the same key as the one used in gnutls_x509_crt_set_key() since a
  * certificate request is self signed.
  *
  * This must be the last step in a certificate request generation since all
  * the previously set parameters are now signed.
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key,
                       gnutls_digest_algorithm_t dig, unsigned int flags)
{
    int result;
    gnutls_datum_t signature;

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

    /* Step 1. Self sign the request.
     */
    result =
        _gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo",
                               dig, key, &signature);

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

    /* Step 2. write the signature (bits)
     */
    result =
        asn1_write_value (crq->crq, "signature", signature.data,
                          signature.size * 8);

    _gnutls_free_datum (&signature);

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

    /* Step 3. Write the signatureAlgorithm field.
     */
    result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm",
                                            key->pk_algorithm, dig, key->params,
                                            key->params_size);
    if (result < 0)
    {
        gnutls_assert ();
        return result;
    }

    return 0;
}
Exemplo n.º 18
0
/**
 * gnutls_x509_crt_set_private_key_usage_period:
 * @crt: a certificate of type #gnutls_x509_crt_t
 * @activation: The activation time
 * @expiration: The expiration time
 *
 * This function will set the private key usage period extension (2.5.29.16).
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crt_set_private_key_usage_period(gnutls_x509_crt_t crt,
					     time_t activation,
					     time_t expiration)
{
	int result;
	gnutls_datum_t der_data;
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;

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

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

	result = _gnutls_x509_set_time(c2, "notBefore", activation, 1);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	result = _gnutls_x509_set_time(c2, "notAfter", expiration, 1);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

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

	result = _gnutls_x509_crt_set_extension(crt, "2.5.29.16",
						&der_data, 0);

	_gnutls_free_datum(&der_data);

	crt->use_extensions = 1;

      cleanup:
	asn1_delete_structure(&c2);

	return result;
}
Exemplo n.º 19
0
/**
 * gnutls_privkey_sign_data:
 * @signer: Holds the key
 * @digest: should be a digest algorithm
 * @flags: should be 0 for now
 * @data: holds the data to be signed
 * @signature: will contain the signature allocate with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 * negative error value.
 **/
int
gnutls_privkey_sign_data2 (gnutls_privkey_t signer,
                          gnutls_digest_algorithm_t hash,
                          unsigned int flags,
                          const gnutls_datum_t * data,
                          gnutls_datum_t * signature)
{
  int ret;
  gnutls_datum_t digest;

  ret = pk_hash_data (signer->pk_algorithm, hash, NULL, data, &digest);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret = pk_prepare_hash (signer->pk_algorithm, hash, &digest);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = _gnutls_privkey_sign_hash (signer, &digest, signature);
  _gnutls_free_datum (&digest);

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

  return 0;

cleanup:
  _gnutls_free_datum (&digest);
  return ret;
}
Exemplo n.º 20
0
Arquivo: psk.c Projeto: nobled/gnutls
/* Set the PSK premaster secret.
 */
int
_gnutls_set_psk_session_key (gnutls_session_t session,
    gnutls_datum_t * ppsk /* key */,
    gnutls_datum_t * dh_secret)
{
  gnutls_datum_t pwd_psk = { NULL, 0 };
  size_t dh_secret_size;
  uint8_t * p;
  int ret;

  if (dh_secret == NULL)
    dh_secret_size = ppsk->size;
  else
    dh_secret_size = dh_secret->size;

  /* set the session key
   */
  session->key.key.size = 4 + dh_secret_size + ppsk->size;
  session->key.key.data = gnutls_malloc (session->key.key.size);
  if (session->key.key.data == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  /* format of the premaster secret:
   * (uint16_t) psk_size
   * psk_size bytes of (0)s
   * (uint16_t) psk_size
   * the psk
   */
  p = session->key.key.data;
  _gnutls_write_uint16 (dh_secret_size, p);
  p+=2;
  if (dh_secret == NULL)
    memset (p, 0, dh_secret_size);
  else
    memcpy (p, dh_secret->data, dh_secret->size);

  p += dh_secret_size;
  _gnutls_write_uint16 (ppsk->size, p);
  if (ppsk->data != NULL)
    memcpy (p+2, ppsk->data, ppsk->size);

  ret = 0;

error:
  _gnutls_free_datum (&pwd_psk);
  return ret;
}
Exemplo n.º 21
0
/**
 * gnutls_dh_get_group:
 * @session: is a gnutls session
 * @raw_gen: will hold the generator.
 * @raw_prime: will hold the prime.
 *
 * This function will return the group parameters used in the last
 * Diffie-Hellman key exchange with the peer.  These are the prime and
 * the generator used.  This function should be used for both
 * anonymous and ephemeral Diffie-Hellman.  The output parameters must
 * be freed with gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_dh_get_group(gnutls_session_t session,
		    gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
{
	dh_info_st *dh;
	int ret;
	anon_auth_info_t anon_info;
	cert_auth_info_t cert_info;
	psk_auth_info_t psk_info;

	switch (gnutls_auth_get_type(session)) {
	case GNUTLS_CRD_ANON:
		anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
		if (anon_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &anon_info->dh;
		break;
	case GNUTLS_CRD_PSK:
		psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		if (psk_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &psk_info->dh;
		break;
	case GNUTLS_CRD_CERTIFICATE:
		cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
		if (cert_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &cert_info->dh;
		break;
	default:
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    _gnutls_set_datum(raw_gen, dh->generator.data,
			      dh->generator.size);
	if (ret < 0) {
		gnutls_assert();
		_gnutls_free_datum(raw_prime);
		return ret;
	}

	return 0;
}
Exemplo n.º 22
0
/* returns error if the certificate has different algorithm than
 * the given key parameters.
 */
static int
_gnutls_check_key_cert_match (gnutls_certificate_credentials_t res)
{
  gnutls_datum_t cid;
  gnutls_datum_t kid;
  unsigned pk = res->cert_list[res->ncerts - 1][0].subject_pk_algorithm;

  if (res->pkey[res->ncerts - 1].pk_algorithm != pk)
    {
      gnutls_assert ();
      return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
    }

  if (pk == GNUTLS_PK_RSA)
    {
      _gnutls_x509_write_rsa_params (res->pkey[res->ncerts - 1].params,
				     res->pkey[res->ncerts -
					       1].params_size, &kid);


      _gnutls_x509_write_rsa_params (res->
				     cert_list[res->ncerts - 1][0].params,
				     res->cert_list[res->ncerts -
						    1][0].params_size, &cid);
    }
  else if (pk == GNUTLS_PK_DSA)
    {

      _gnutls_x509_write_dsa_params (res->pkey[res->ncerts - 1].params,
				     res->pkey[res->ncerts -
					       1].params_size, &kid);

      _gnutls_x509_write_dsa_params (res->
				     cert_list[res->ncerts - 1][0].params,
				     res->cert_list[res->ncerts -
						    1][0].params_size, &cid);
    }

  if (cid.size != kid.size)
    {
      gnutls_assert ();
      _gnutls_free_datum (&kid);
      _gnutls_free_datum (&cid);
      return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
    }

  if (memcmp (kid.data, cid.data, kid.size) != 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&kid);
      _gnutls_free_datum (&cid);
      return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
    }

  _gnutls_free_datum (&kid);
  _gnutls_free_datum (&cid);
  return 0;
}
Exemplo n.º 23
0
int
_gnutls_rsa_verify (const gnutls_datum_t * vdata,
                    const gnutls_datum_t * ciphertext, 
                    gnutls_pk_params_st * params,
                    int btype)
{

  gnutls_datum_t plain;
  int ret;

  /* decrypt signature */
  if ((ret =
       _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params,
                                  btype)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (plain.size != vdata->size)
    {
      gnutls_assert ();
      _gnutls_free_datum (&plain);
      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
    }

  if (memcmp (plain.data, vdata->data, plain.size) != 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&plain);
      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
    }

  _gnutls_free_datum (&plain);

  return 0;                     /* ok */
}
Exemplo n.º 24
0
/**
  * gnutls_x509_privkey_sign_data - This function will sign the given data using the private key params
  * @key: Holds the key
  * @digest: should be MD5 or SHA1
  * @flags: should be 0 for now
  * @data: holds the data to be signed
  * @signature: will contain the signature
  * @signature_size: holds the size of signature (and will be replaced
  *   by the new size)
  *
  * This function will sign the given data using a signature algorithm
  * supported by the private key. Signature algorithms are always used
  * together with a hash functions.  Different hash functions may be
  * used for the RSA algorithm, but only SHA-1 for the DSA keys.
  *
  * If the buffer provided is not long enough to hold the output, then
  * *signature_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
  * be returned.
  *
  * In case of failure a negative value will be returned, and
  * 0 on success.
  *
  **/
int
gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key,
			       gnutls_digest_algorithm_t digest,
			       unsigned int flags,
			       const gnutls_datum_t * data,
			       void *signature, size_t * signature_size)
{
  int result;
  gnutls_datum_t sig = { NULL, 0 };

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

  result = _gnutls_x509_sign (data, digest, key, &sig);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  if (*signature_size < sig.size)
    {
      *signature_size = sig.size;
      _gnutls_free_datum (&sig);
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  *signature_size = sig.size;
  memcpy (signature, sig.data, sig.size);

  _gnutls_free_datum (&sig);

  return 0;
}
Exemplo n.º 25
0
int
_gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session,
				      gnutls_buffer_st * data,
				      gnutls_datum_t * psk_key)
{
	int ret;
	gnutls_datum_t out;
	int curve = _gnutls_session_ecc_curve_get(session);

	/* generate temporal key */
	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
				     &session->key.ecdh_params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_ecc_ansi_x963_export(curve,
					 session->key.ecdh_params.
					 params[ECC_X] /* x */ ,
					 session->key.ecdh_params.
					 params[ECC_Y] /* y */ , &out);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);

	_gnutls_free_datum(&out);

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

	/* generate pre-shared key */
	ret = calc_ecdh_key(session, psk_key, curve);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length;
cleanup:
      	gnutls_pk_params_clear(&session->key.ecdh_params);
	return ret;
}
Exemplo n.º 26
0
static int calc_ecdh_key( gnutls_session_t session, gnutls_datum_t * psk_key)
{
gnutls_pk_params_st pub;
int ret;

  memset(&pub,0,sizeof(pub));
  pub.params[ECC_PRIME] = session->key.ecdh_params.params[ECC_PRIME];
  pub.params[ECC_ORDER] = session->key.ecdh_params.params[ECC_ORDER];
  pub.params[ECC_A] = session->key.ecdh_params.params[ECC_A];
  pub.params[ECC_B] = session->key.ecdh_params.params[ECC_B];
  pub.params[ECC_GX] = session->key.ecdh_params.params[ECC_GX];
  pub.params[ECC_GY] = session->key.ecdh_params.params[ECC_GY];
  pub.params[ECC_X] = session->key.ecdh_x;
  pub.params[ECC_Y] = session->key.ecdh_y;

  if (psk_key == NULL)
    ret = _gnutls_pk_derive(GNUTLS_PK_EC, &session->key.key, &session->key.ecdh_params, &pub);
  else
    {
      gnutls_datum_t tmp_dh_key;

      ret = _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key, &session->key.ecdh_params, &pub);
      if (ret < 0)
        {
          ret = gnutls_assert_val(ret);
          goto cleanup;
        }

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

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

cleanup:
  /* no longer needed */
  _gnutls_mpi_release (&session->key.ecdh_x);
  _gnutls_mpi_release (&session->key.ecdh_y);
  gnutls_pk_params_release( &session->key.ecdh_params);
  return ret;

}
Exemplo n.º 27
0
void
_gnutls_gcert_deinit (gnutls_cert * cert)
{
  int i;

  if (cert == NULL)
    return;

  for (i = 0; i < cert->params_size; i++)
    {
      _gnutls_mpi_release (&cert->params[i]);
    }

  _gnutls_free_datum (&cert->raw);
}
Exemplo n.º 28
0
/* Reads the DER signed data from the certificate and allocates space and
 * returns them into signed_data.
 */
int
_gnutls_x509_get_signed_data(ASN1_TYPE src,  const gnutls_datum *_der,
			     const char *src_name,
			     gnutls_datum_t * signed_data)
{
	int start, end, result;
	gnutls_datum_t der;
	unsigned need_free = 0;

	if (_der == NULL || _der->size == 0) {
		result = _gnutls_x509_der_encode(src, "", &der, 0);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
		need_free = 1;
	} else {
		der.data = _der->data;
		der.size = _der->size;
	}

	/* Get the signed data
	 */
	result = asn1_der_decoding_startEnd(src, der.data, der.size,
					    src_name, &start, &end);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result =
	    _gnutls_set_datum(signed_data, &der.data[start],
			      end - start + 1);

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

	result = 0;

      cleanup:
	if (need_free != 0)
		_gnutls_free_datum(&der);

	return result;
}
Exemplo n.º 29
0
/**
 * gnutls_srp_set_server_fake_salt_seed:
 * @cred: is a #gnutls_srp_server_credentials_t type
 * @seed: is the seed data, only needs to be valid until the function
 * returns; size of the seed must be greater than zero
 * @salt_length: is the length of the generated fake salts
 *
 * This function sets the seed that is used to generate salts for
 * invalid (non-existent) usernames.
 *
 * In order to prevent attackers from guessing valid usernames,
 * when a user does not exist gnutls generates a salt and a verifier
 * and proceeds with the protocol as usual.
 * The authentication will ultimately fail, but the client cannot tell
 * whether the username is valid (exists) or invalid.
 *
 * If an attacker learns the seed, given a salt (which is part of the
 * handshake) which was generated when the seed was in use, it can tell
 * whether or not the authentication failed because of an unknown username.
 * This seed cannot be used to reveal application data or passwords.
 *
 * @salt_length should represent the salt length your application uses.
 * Generating fake salts longer than 20 bytes is not supported.
 *
 * By default the seed is a random value, different each time a
 * #gnutls_srp_server_credentials_t is allocated and fake salts are
 * 16 bytes long.
 *
 * Since: 3.3.0
 **/
void
gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
				     const gnutls_datum_t * seed,
				     unsigned int salt_length)
{
	_gnutls_free_datum(&cred->fake_salt_seed);
	_gnutls_set_datum(&cred->fake_salt_seed, seed->data, seed->size);

	/* Cap the salt length at the output size of the MAC algorithm
	 * we are using to generate the fake salts.
	 */
	const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC);
	const size_t mac_len = me->output_size;

	cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len);
}
Exemplo n.º 30
0
/**
 * gnutls_x509_crl_get_number - get the CRL number (extension)
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @ret: The place where the number will be copied
 * @ret_size: Holds the size of the result field.
 * @critical: will be non zero if the extension is marked as critical
 *   (may be null)
 *
 * This function will return the CRL number extension.  This is
 * obtained by the CRL Number extension field (2.5.29.20).
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative value in case of an error.
 *
 * Since: 2.8.0
 **/
int
gnutls_x509_crl_get_number (gnutls_x509_crl_t crl, void *ret,
			    size_t * ret_size, unsigned int *critical)
{
  int result;
  gnutls_datum_t id;

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


  if (ret)
    memset (ret, 0, *ret_size);
  else
    *ret_size = 0;

  if ((result =
       _gnutls_x509_crl_get_extension (crl, "2.5.29.20", 0, &id,
				       critical)) < 0)
    {
      return result;
    }

  if (id.size == 0 || id.data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  result = _gnutls_x509_ext_extract_number (ret, ret_size, id.data, id.size);

  _gnutls_free_datum (&id);

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

  return 0;
}