Example #1
0
/**
 * gnutls_ext_register - Register a handler for a TLS extension
 * @type: the 16-bit integer referring to the extension type
 * @name: human printable name of the extension used for debugging
 * @parse_type: either #GNUTLS_EXT_TLS or %GNUTLS_EXT_APPLICATION.
 * @recv_func: a function to receive extension data
 * @send_func: a function to send extension data
 *
 * This function is used to register a new TLS extension handler.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 *
 * Since: 2.6.0
 **/
int
gnutls_ext_register (int type,
		     const char *name,
		     gnutls_ext_parse_type_t parse_type,
		     gnutls_ext_recv_func recv_func,
		     gnutls_ext_send_func send_func)
{
  gnutls_extension_entry *p;

  p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
  if (!p)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }
  extfunc = p;

  extfunc[extfunc_size].type = type;
  extfunc[extfunc_size].name = name;
  extfunc[extfunc_size].parse_type = parse_type;
  extfunc[extfunc_size].recv_func = recv_func;
  extfunc[extfunc_size].send_func = send_func;

  extfunc_size++;

  return GNUTLS_E_SUCCESS;
}
Example #2
0
/* This function will return the internal (per session) temporary
 * recv buffer. If the buffer was not initialized before it will
 * also initialize it.
 */
inline static int
get_temp_recv_buffer (gnutls_session_t session, gnutls_datum_t * tmp)
{

  /* We allocate MAX_RECORD_RECV_SIZE length
   * because we cannot predict the output data by the record
   * packet length (due to compression).
   */

  if (MAX_RECORD_RECV_SIZE > session->internals.recv_buffer.size ||
      session->internals.recv_buffer.data == NULL)
    {

      /* Initialize the internal buffer.
       */
      session->internals.recv_buffer.data =
	gnutls_realloc (session->internals.recv_buffer.data,
			MAX_RECORD_RECV_SIZE);

      if (session->internals.recv_buffer.data == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      session->internals.recv_buffer.size = MAX_RECORD_RECV_SIZE;
    }

  tmp->data = session->internals.recv_buffer.data;
  tmp->size = session->internals.recv_buffer.size;

  return 0;
}
Example #3
0
int
_gnutls_datum_append (gnutls_datum_t * dst, const void *data,
                        size_t data_size)
{

  dst->data = gnutls_realloc (dst->data, data_size + dst->size);
  if (dst->data == NULL)
    return GNUTLS_E_MEMORY_ERROR;

  memcpy (&dst->data[dst->size], data, data_size);
  dst->size += data_size;

  return 0;
}
Example #4
0
int
_gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
                            size_t data_size)
{
  size_t tot_len = data_size + dest->length;

  if (data_size == 0) return 0;

  if (dest->max_length >= tot_len)
    {
      size_t unused = MEMSUB (dest->data, dest->allocd);

      if (dest->max_length - unused <= tot_len)
        {
          if (dest->length && dest->data)
            memmove (dest->allocd, dest->data, dest->length);

          dest->data = dest->allocd;
        }
      memmove (&dest->data[dest->length], data, data_size);
      dest->length = tot_len;

      return tot_len;
    }
  else
    {
      size_t unused = MEMSUB (dest->data, dest->allocd);
      size_t new_len =
        MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);

      dest->allocd = gnutls_realloc (dest->allocd, new_len);
      if (dest->allocd == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      dest->max_length = new_len;
      dest->data = dest->allocd + unused;

      if (dest->length && dest->data)
        memmove (dest->allocd, dest->data, dest->length);
      dest->data = dest->allocd;

      memcpy (&dest->data[dest->length], data, data_size);
      dest->length = tot_len;

      return tot_len;
    }
}
Example #5
0
/* Checks if the extra_certs contain certificates that may form a chain
 * with the first certificate in chain (it is expected that chain_len==1)
 * and appends those in the chain.
 */
static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
                      gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len,
                      unsigned int flags)
{
unsigned int i;

  if (*chain_len != 1)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
  
  i = 0;
  while(i<*extra_certs_len)
    {
      /* if it is an issuer but not a self-signed one */
      if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0)
        {
          if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) && 
              gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) != 0)
            goto skip;

          *chain = gnutls_realloc (*chain, sizeof((*chain)[0]) *
                                                     ++(*chain_len));
          if (*chain == NULL)
            {
              gnutls_assert();
              return GNUTLS_E_MEMORY_ERROR;
            }
          (*chain)[*chain_len - 1] = (*extra_certs)[i];
          
          (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1];
          (*extra_certs_len)--;

          i=0;
          continue;
        }

skip:
      i++;
    }
  return 0;
}
Example #6
0
/* This function will return the internal (per session) temporary
 * recv buffer. If the buffer was not initialized before it will
 * also initialize it.
 */
inline static int
get_temp_recv_buffer (gnutls_session_t session, gnutls_datum_t * tmp)
{
  size_t max_record_size;

  if (gnutls_compression_get (session) != GNUTLS_COMP_NULL ||
      session->internals.priorities.allow_large_records != 0)
    max_record_size = MAX_RECORD_RECV_SIZE + EXTRA_COMP_SIZE;
  else
    max_record_size = MAX_RECORD_RECV_SIZE;

  /* We allocate MAX_RECORD_RECV_SIZE length
   * because we cannot predict the output data by the record
   * packet length (due to compression).
   */

  if (max_record_size > session->internals.recv_buffer.size ||
      session->internals.recv_buffer.data == NULL)
    {

      /* Initialize the internal buffer.
       */
      session->internals.recv_buffer.data =
        gnutls_realloc (session->internals.recv_buffer.data, max_record_size);

      if (session->internals.recv_buffer.data == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }

      session->internals.recv_buffer.size = max_record_size;
    }

  tmp->data = session->internals.recv_buffer.data;
  tmp->size = session->internals.recv_buffer.size;

  return 0;
}
Example #7
0
int
_gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size)
{
  if (dest->max_length >= new_size)
    {
      size_t unused = MEMSUB (dest->data, dest->allocd);
      if (dest->max_length - unused <= new_size)
        {
          if (dest->length && dest->data)
            memmove (dest->allocd, dest->data, dest->length);
          dest->data = dest->allocd;
        }

      return 0;
    }
  else
    {
      size_t unused = MEMSUB (dest->data, dest->allocd);
      size_t alloc_len =
        MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);

      dest->allocd = gnutls_realloc (dest->allocd, alloc_len);
      if (dest->allocd == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      dest->max_length = alloc_len;
      dest->data = dest->allocd + unused;

      if (dest->length && dest->data)
        memmove (dest->allocd, dest->data, dest->length);
      dest->data = dest->allocd;

      return 0;
    }
}
Example #8
0
/* Checks if the extra_certs contain certificates that may form a chain
 * with the first certificate in chain (it is expected that chain_len==1)
 * and appends those in the chain.
 */
static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
                      gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len)
{
unsigned int i;

  if (*chain_len != 1)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
  
  i = 0;
  while(i<*extra_certs_len)
    {
      /* if it is an issuer but not a self-signed one */
      if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0 &&
          gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) == 0)
        {
           void *tmp = *chain;
           *chain = gnutls_realloc (*chain, sizeof((*chain)[0]) *
                                                     ++(*chain_len));
           if (*chain == NULL)
             {
               gnutls_assert();
               gnutls_free(tmp);
               return GNUTLS_E_MEMORY_ERROR;
             }
           (*chain)[*chain_len - 1] = (*extra_certs)[i];
           
           (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1];
           (*extra_certs_len)--;

           i=0;
           continue;
        }
      i++;
    }
  return 0;
}
Example #9
0
/* Like above but it accepts a parsed certificate instead.
 */
int
_gnutls_x509_crt_to_gcert (gnutls_cert * gcert,
			   gnutls_x509_crt_t cert, unsigned int flags)
{
  int ret = 0;

  memset (gcert, 0, sizeof (gnutls_cert));
  gcert->cert_type = GNUTLS_CRT_X509;

  if (!(flags & CERT_NO_COPY))
    {
#define SMALL_DER 512
      opaque *der;
      size_t der_size = SMALL_DER;

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

      ret =
	gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der, &der_size);
      if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
	{
	  gnutls_assert ();
	  gnutls_free (der);
	  return ret;
	}

      if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
	{
	  der = gnutls_realloc (der, der_size);
	  if (der == NULL)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	  ret =
	    gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
				    &der_size);
	  if (ret < 0)
	    {
	      gnutls_assert ();
	      gnutls_free (der);
	      return ret;
	    }
	}

      gcert->raw.data = der;
      gcert->raw.size = der_size;
    }
  else
    /* now we have 0 or a bitwise or of things to decode */
    flags ^= CERT_NO_COPY;


  if (flags & CERT_ONLY_EXTENSIONS || flags == 0)
    {
      gnutls_x509_crt_get_key_usage (cert, &gcert->key_usage, NULL);
      gcert->version = gnutls_x509_crt_get_version (cert);
    }
  gcert->subject_pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL);

  if (flags & CERT_ONLY_PUBKEY || flags == 0)
    {
      gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
      ret =
	_gnutls_x509_crt_get_mpis (cert, gcert->params, &gcert->params_size);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
    }

  return 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      idx++;
      gnutls_pkcs12_bag_deinit (bag);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      idx++;
      gnutls_pkcs12_bag_deinit (bag);
    }

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

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

  ret = 0;

done:
  if (bag)
    gnutls_pkcs12_bag_deinit (bag);

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

  return ret;
}
Example #11
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;
}
Example #12
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;

}