Example #1
0
File: gc.c Project: bf4/pidgin-mac
void
doit (void)
{
  char digest[20];
  int err;

  /* XXX: We need this to fix secure memory. */
  gnutls_global_init ();

  err =
    _gnutls_hmac_fast (GNUTLS_MAC_MD5, "keykeykey", 9, "abcdefgh", 8, digest);
  if (err < 0)
    fail ("_gnutls_hmac_fast(MD5) failed: %d\n", err);
  else
    {
      if (memcmp (digest, "\x3c\xb0\x9d\x83\x28\x01\xef\xc0"
		  "\x7b\xb3\xaf\x42\x69\xe5\x93\x9a", 16) == 0)
	success ("_gnutls_hmac_fast(MD5) OK\n");
      else
	{
	  hexprint (digest, 16);
	  fail ("_gnutls_hmac_fast(MD5) failure\n");
	}
    }

  err =
    _gnutls_hmac_fast (GNUTLS_MAC_SHA1, "keykeykey", 9, "abcdefgh", 8,
		       digest);
  if (err < 0)
    fail ("_gnutls_hmac_fast(SHA1) failed: %d\n", err);
  else
    {
      if (memcmp (digest, "\x58\x93\x7a\x58\xfe\xea\x82\xf8"
		  "\x0e\x64\x62\x01\x40\x2b\x2c\xed\x5d\x54\xc1\xfa",
		  20) == 0)
	success ("_gnutls_hmac_fast(SHA1) OK\n");
      else
	{
	  hexprint (digest, 20);
	  fail ("_gnutls_hmac_fast(SHA1) failure\n");
	}
    }

  err = _gnutls_pbkdf2_sha1 ("password", 8, "salt", 4, 4711, digest, 16);
  if (err < 0)
    fail ("_gnutls_pkcs5_pbkdf2_sha1() failed: %d\n", err);
  else
    {
      if (memcmp (digest, "\x09\xb7\x85\x57\xdd\xf6\x07\x15"
		  "\x1c\x52\x34\xde\xba\x5c\xdc\x59", 16) == 0)
	success ("_gnutls_pkcs5_pbkdf2_sha1() OK\n");
      else
	{
	  hexprint (digest, 16);
	  fail ("_gnutls_pkcs5_pbkdf2_sha1() failure\n");
	}
    }

  gnutls_global_deinit ();
}
Example #2
0
/**
 * gnutls_dtls_cookie_verify:
 * @key: is a random key to be used at cookie generation
 * @client_data: contains data identifying the client (i.e. address)
 * @client_data_size: The size of client's data
 * @_msg: An incoming message that initiates a connection.
 * @msg_size: The size of the message.
 * @prestate: The cookie of this client.
 *
 * This function will verify an incoming message for
 * a valid cookie. If a valid cookie is returned then
 * it should be associated with the session using
 * gnutls_dtls_prestate_set();
 *
 * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.  
 *
 * Since: 3.0
 **/
int gnutls_dtls_cookie_verify(gnutls_datum_t* key, 
  void* client_data, size_t client_data_size, 
  void* _msg, size_t msg_size, gnutls_dtls_prestate_st* prestate)
{
gnutls_datum_t cookie;
int ret;
unsigned int pos, sid_size;
uint8_t * msg = _msg;
uint8_t digest[C_HASH_SIZE];

  if (key == NULL || key->data == NULL || key->size == 0)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  /* format:
   * version - 2 bytes
   * random - 32 bytes
   * session_id - 1 byte length + content
   * cookie - 1 byte length + content
   */

  pos = 34+DTLS_RECORD_HEADER_SIZE+DTLS_HANDSHAKE_HEADER_SIZE;

  if (msg_size < pos+1)
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

  sid_size = msg[pos++];

  if (sid_size > 32 || msg_size < pos+sid_size+1)
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

  pos += sid_size;
  cookie.size = msg[pos++];

  if (msg_size < pos+cookie.size+1)
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
  
  cookie.data = &msg[pos];
  if (cookie.size != COOKIE_SIZE)
    {
      if (cookie.size > 0) _gnutls_audit_log(NULL, "Received cookie with illegal size %d. Expected %d\n", (int)cookie.size, COOKIE_SIZE);
      return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
    }

  ret = _gnutls_hmac_fast(C_HASH, key->data, key->size, client_data, client_data_size, digest);
  if (ret < 0)
    return gnutls_assert_val(ret);

  if (memcmp(digest, cookie.data, COOKIE_MAC_SIZE) != 0)
    return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
  
  prestate->record_seq = msg[10]; /* client's record seq */
  prestate->hsk_read_seq =  msg[DTLS_RECORD_HEADER_SIZE+5]; /* client's hsk seq */
  prestate->hsk_write_seq = 0;/* we always send zero for this msg */
  
  return 0;
}
int
_gnutls_pbkdf2_sha1 (const char *P, size_t Plen,
                     const unsigned char *S, size_t Slen,
                     unsigned int c, unsigned char *DK, size_t dkLen)
{
  unsigned int hLen = 20;
  char U[20];
  char T[20];
  unsigned int u;
  unsigned int l;
  unsigned int r;
  unsigned int i;
  unsigned int k;
  int rc;
  char *tmp;
  size_t tmplen = Slen + 4;

  if (c == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (dkLen == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }
  /*
   *
   *  Steps:
   *
   *     1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
   *        stop.
   */

  if (dkLen > 4294967295U)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /*
   *     2. Let l be the number of hLen-octet blocks in the derived key,
   *        rounding up, and let r be the number of octets in the last
   *        block:
   *
   *                  l = CEIL (dkLen / hLen) ,
   *                  r = dkLen - (l - 1) * hLen .
   *
   *        Here, CEIL (x) is the "ceiling" function, i.e. the smallest
   *        integer greater than, or equal to, x.
   */

  l = ((dkLen - 1) / hLen) + 1;
  r = dkLen - (l - 1) * hLen;

  /*
   *     3. For each block of the derived key apply the function F defined
   *        below to the password P, the salt S, the iteration count c, and
   *        the block index to compute the block:
   *
   *                  T_1 = F (P, S, c, 1) ,
   *                  T_2 = F (P, S, c, 2) ,
   *                  ...
   *                  T_l = F (P, S, c, l) ,
   *
   *        where the function F is defined as the exclusive-or sum of the
   *        first c iterates of the underlying pseudorandom function PRF
   *        applied to the password P and the concatenation of the salt S
   *        and the block index i:
   *
   *                  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
   *
   *        where
   *
   *                  U_1 = PRF (P, S || INT (i)) ,
   *                  U_2 = PRF (P, U_1) ,
   *                  ...
   *                  U_c = PRF (P, U_{c-1}) .
   *
   *        Here, INT (i) is a four-octet encoding of the integer i, most
   *        significant octet first.
   *
   *     4. Concatenate the blocks and extract the first dkLen octets to
   *        produce a derived key DK:
   *
   *                  DK = T_1 || T_2 ||  ...  || T_l<0..r-1>
   *
   *     5. Output the derived key DK.
   *
   *  Note. The construction of the function F follows a "belt-and-
   *  suspenders" approach. The iterates U_i are computed recursively to
   *  remove a degree of parallelism from an opponent; they are exclusive-
   *  ored together to reduce concerns about the recursion degenerating
   *  into a small set of values.
   *
   */

  tmp = gnutls_malloc (tmplen);
  if (tmp == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  memcpy (tmp, S, Slen);

  for (i = 1; i <= l; i++)
    {
      memset (T, 0, hLen);

      for (u = 1; u <= c; u++)
        {
          if (u == 1)
            {
              tmp[Slen + 0] = (i & 0xff000000) >> 24;
              tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
              tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
              tmp[Slen + 3] = (i & 0x000000ff) >> 0;

              rc =
                _gnutls_hmac_fast (GNUTLS_MAC_SHA1, P, Plen, tmp, tmplen, U);
            }
          else
            rc = _gnutls_hmac_fast (GNUTLS_MAC_SHA1, P, Plen, U, hLen, U);

          if (rc < 0)
            {
              gnutls_free (tmp);
              return rc;
            }

          for (k = 0; k < hLen; k++)
            T[k] ^= U[k];
        }
Example #4
0
/**
 * gnutls_dtls_cookie_send:
 * @key: is a random key to be used at cookie generation
 * @client_data: contains data identifying the client (i.e. address)
 * @client_data_size: The size of client's data
 * @prestate: The previous cookie returned by gnutls_dtls_cookie_verify()
 * @ptr: A transport pointer to be used by @push_func
 * @push_func: A function that will be used to reply
 *
 * This function can be used to prevent denial of service
 * attacks to a DTLS server by requiring the client to
 * reply using a cookie sent by this function. That way
 * it can be ensured that a client we allocated resources
 * for (i.e. #gnutls_session_t) is the one that the 
 * original incoming packet was originated from.
 *
 * Returns: the number of bytes sent, or a negative error code.  
 *
 * Since: 3.0
 **/
int gnutls_dtls_cookie_send(gnutls_datum_t* key, void* client_data, size_t client_data_size, 
  gnutls_dtls_prestate_st* prestate,
  gnutls_transport_ptr_t ptr, gnutls_push_func push_func)
{
uint8_t hvr[20+DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE];
int hvr_size = 0, ret;
uint8_t digest[C_HASH_SIZE];

  if (key == NULL || key->data == NULL || key->size == 0)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

/* send
 *  struct {
 *    ContentType type - 1 byte GNUTLS_HANDSHAKE;
 *    ProtocolVersion version; - 2 bytes (254,255)
 *    uint16 epoch; - 2 bytes (0, 0)
 *    uint48 sequence_number; - 4 bytes (0,0,0,0)
 *    uint16 length; - 2 bytes (COOKIE_SIZE+1+2)+DTLS_HANDSHAKE_HEADER_SIZE
 *    uint8_t fragment[DTLSPlaintext.length];
 *  } DTLSPlaintext;
 *
 *
 * struct {
 *    HandshakeType msg_type; 1 byte - GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST
 *    uint24 length; - COOKIE_SIZE+3
 *    uint16 message_seq; - 2 bytes (0,0)
 *    uint24 fragment_offset; - 3 bytes (0,0,0)
 *    uint24 fragment_length; - same as length
 * }
 *
 * struct {
 *   ProtocolVersion server_version;
 *   uint8_t cookie<0..32>;
 * } HelloVerifyRequest;
 */ 

  hvr[hvr_size++] = GNUTLS_HANDSHAKE;
  /* version */
  hvr[hvr_size++] = 254;
  hvr[hvr_size++] = 255;
  
  /* epoch + seq */
  memset(&hvr[hvr_size], 0, 8);
  hvr_size += 7;
  hvr[hvr_size++] = prestate->record_seq;

  /* length */
  _gnutls_write_uint16(DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 2;

  /* now handshake headers */
  hvr[hvr_size++] = GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST;
  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 3;
  
  /* handshake seq */
  hvr[hvr_size++] = 0;
  hvr[hvr_size++] = prestate->hsk_write_seq;

  _gnutls_write_uint24(0, &hvr[hvr_size]);
  hvr_size += 3;

  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 3;

  /* version */
  hvr[hvr_size++] = 254;
  hvr[hvr_size++] = 255;
  hvr[hvr_size++] = COOKIE_SIZE;

  ret = _gnutls_hmac_fast(C_HASH, key->data, key->size, client_data, client_data_size, digest);
  if (ret < 0)
    return gnutls_assert_val(ret);

  memcpy(&hvr[hvr_size], digest, COOKIE_MAC_SIZE);
  hvr_size+= COOKIE_MAC_SIZE;

  ret = push_func(ptr, hvr, hvr_size);
  if (ret < 0)
    ret = GNUTLS_E_PUSH_ERROR;

  return ret;
}