Exemple #1
0
/* returns zero on success. Fails if the number is zero.
 */
int
_gnutls_mpi_scan_nz (bigint_t * ret_mpi, const void *buffer, size_t nbytes)
{
  int ret;

  ret = _gnutls_mpi_scan (ret_mpi, buffer, nbytes);
  if (ret < 0)
    return ret;

  /* MPIs with 0 bits are illegal
   */
  if (_gnutls_mpi_cmp_ui (*ret_mpi, 0) == 0)
    {
      _gnutls_mpi_release (ret_mpi);
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  return 0;
}
Exemple #2
0
/* this function reads an integer
 * from asn1 structs. Combines the read and mpi_scan
 * steps.
 */
int
_gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi)
{
  int result;
  opaque *tmpstr = NULL;
  int tmpstr_size;

  tmpstr_size = 0;
  result = asn1_read_value (node, value, NULL, &tmpstr_size);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  tmpstr = gnutls_malloc (tmpstr_size);
  if (tmpstr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  result = asn1_read_value (node, value, tmpstr, &tmpstr_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      gnutls_free (tmpstr);
      return _gnutls_asn2err (result);
    }

  result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size);
  gnutls_free (tmpstr);

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

  return 0;
}
Exemple #3
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 */
int
_gnutls_pkcs12_string_to_key (unsigned int id, const opaque * salt,
			      unsigned int salt_size, unsigned int iter,
			      const char *pw, unsigned int req_keylen,
			      opaque * keybuf)
{
  int rc;
  unsigned int i, j;
  digest_hd_st md;
  bigint_t num_b1 = NULL, num_ij = NULL;
  bigint_t mpi512 = NULL;
  unsigned int pwlen;
  opaque hash[20], buf_b[64], buf_i[128], *p;
  size_t cur_keylen;
  size_t n;
  const opaque buf_512[] =	/* 2^64 */
  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };

  cur_keylen = 0;

  if (pw == NULL)
    pwlen = 0;
  else
    pwlen = strlen (pw);

  if (pwlen > 63 / 2)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0)
    {
      gnutls_assert ();
      return rc;
    }

  rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512));
  if (rc < 0)
    {
      gnutls_assert ();
      return rc;
    }

  /* Store salt and password in BUF_I */
  p = buf_i;
  for (i = 0; i < 64; i++)
    *p++ = salt[i % salt_size];
  if (pw)
    {
      for (i = j = 0; i < 64; i += 2)
	{
	  *p++ = 0;
	  *p++ = pw[j];
	  if (++j > pwlen)	/* Note, that we include the trailing zero */
	    j = 0;
	}
    }
  else
    memset (p, 0, 64);

  for (;;)
    {
      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      for (i = 0; i < 64; i++)
	{
	  unsigned char lid = id & 0xFF;
	  _gnutls_hash (&md, &lid, 1);
	}
      _gnutls_hash (&md, buf_i, pw ? 128 : 64);
      _gnutls_hash_deinit (&md, hash);
      for (i = 1; i < iter; i++)
	{
	  rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_hash (&md, hash, 20);
	  _gnutls_hash_deinit (&md, hash);
	}
      for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
	keybuf[cur_keylen++] = hash[i];
      if (cur_keylen == req_keylen)
	{
	  rc = 0;		/* ready */
	  goto cleanup;
	}

      /* need more bytes. */
      for (i = 0; i < 64; i++)
	buf_b[i] = hash[i % 20];
      n = 64;
      rc = _gnutls_mpi_scan (&num_b1, buf_b, n);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      _gnutls_mpi_add_ui (num_b1, num_b1, 1);
      for (i = 0; i < 128; i += 64)
	{
	  n = 64;
	  rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512);
	  n = 64;
	  rc = _gnutls_mpi_print (num_ij, buf_i + i, &n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_release (&num_ij);
	}
    }
cleanup:
  _gnutls_mpi_release (&num_ij);
  _gnutls_mpi_release (&num_b1);
  _gnutls_mpi_release (&mpi512);

  return rc;
}
Exemple #4
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 *
 * Note that this function produces different key for the
 * NULL password, and for the password with zero length.
 */
int
_gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt,
                              unsigned int salt_size, unsigned int iter,
                              const char *pw, unsigned int req_keylen,
                              uint8_t * keybuf)
{
  int rc;
  unsigned int i, j;
  digest_hd_st md;
  bigint_t num_b1 = NULL, num_ij = NULL;
  bigint_t mpi512 = NULL;
  unsigned int pwlen;
  uint8_t hash[20], buf_b[64], buf_i[MAX_PASS_LEN*2+64], *p;
  uint8_t d[64];
  size_t cur_keylen;
  size_t n, m, p_size, i_size;
  const uint8_t buf_512[] =      /* 2^64 */
  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00
  };

  cur_keylen = 0;

  if (pw == NULL)
    pwlen = 0;
  else
    pwlen = strlen (pw);

  if (pwlen > MAX_PASS_LEN)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0)
    {
      gnutls_assert ();
      return rc;
    }

  rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512));
  if (rc < 0)
    {
      gnutls_assert ();
      return rc;
    }

  /* Store salt and password in BUF_I */
  p_size = ((pwlen/64)*64) + 64;
  
  if (p_size > sizeof(buf_i)-64)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
  
  p = buf_i;
  for (i = 0; i < 64; i++)
    *p++ = salt[i % salt_size];
  if (pw)
    {
      for (i = j = 0; i < p_size; i += 2)
        {
          *p++ = 0;
          *p++ = pw[j];
          if (++j > pwlen)      /* Note, that we include the trailing (0) */
            j = 0;
        }
    }
  else
    memset (p, 0, p_size);

  i_size = 64+p_size;

  for (;;)
    {
      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
      if (rc < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
      memset(d, id & 0xff, 64);
      _gnutls_hash (&md, d, 64);
      _gnutls_hash (&md, buf_i, pw ? i_size : 64);
      _gnutls_hash_deinit (&md, hash);
      for (i = 1; i < iter; i++)
        {
          rc = _gnutls_hash_fast (GNUTLS_MAC_SHA1, hash, 20, hash);
          if (rc < 0)
            {
              gnutls_assert ();
              goto cleanup;
            }
        }
      for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
        keybuf[cur_keylen++] = hash[i];
      if (cur_keylen == req_keylen)
        {
          rc = 0;               /* ready */
          goto cleanup;
        }

      /* need more bytes. */
      for (i = 0; i < 64; i++)
        buf_b[i] = hash[i % 20];
      n = 64;
      rc = _gnutls_mpi_scan (&num_b1, buf_b, n);
      if (rc < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
      _gnutls_mpi_add_ui (num_b1, num_b1, 1);
      for (i = 0; i < 128; i += 64)
        {
          n = 64;
          rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n);
          if (rc < 0)
            {
              gnutls_assert ();
              goto cleanup;
            }
          _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512);
          n = 64;
#ifndef PKCS12_BROKEN_KEYGEN
          m = (_gnutls_mpi_get_nbits (num_ij) + 7) / 8;
#else
          m = n;
#endif
          memset (buf_i + i, 0, n - m);
          rc = _gnutls_mpi_print (num_ij, buf_i + i + n - m, &n);
          if (rc < 0)
            {
              gnutls_assert ();
              goto cleanup;
            }
          _gnutls_mpi_release (&num_ij);
        }
    }
cleanup:
  _gnutls_mpi_release (&num_ij);
  _gnutls_mpi_release (&num_b1);
  _gnutls_mpi_release (&mpi512);

  return rc;
}
Exemple #5
0
bigint_t
_gnutls_mpi_randomize (bigint_t r, unsigned int bits,
                       gnutls_rnd_level_t level)
{
  size_t size = 1 + (bits / 8);
  int ret;
  int rem, i;
  bigint_t tmp;
  char tmpbuf[512];
  opaque *buf;
  int buf_release = 0;

  if (size < sizeof (tmpbuf))
    {
      buf = tmpbuf;
    }
  else
    {
      buf = gnutls_malloc (size);
      if (buf == NULL)
        {
          gnutls_assert ();
          goto cleanup;
        }
      buf_release = 1;
    }


  ret = _gnutls_rnd (level, buf, size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  /* mask the bits that weren't requested */
  rem = bits % 8;

  if (rem == 0)
    {
      buf[0] = 0;
    }
  else
    {
      for (i = 8; i >= rem; i--)
        buf[0] = clearbit (buf[0], i);
    }

  ret = _gnutls_mpi_scan (&tmp, buf, size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  if (buf_release != 0)
    {
      gnutls_free (buf);
      buf = NULL;
    }

  if (r != NULL)
    {
      _gnutls_mpi_set (r, tmp);
      _gnutls_mpi_release (&tmp);
      return r;
    }

  return tmp;

cleanup:
  if (buf_release != 0)
    gnutls_free (buf);
  return NULL;
}