void
ssh_eap_protocol_send_request_random_delay(SshEapProtocol protocol,
                                           SshEap eap,
                                           SshBuffer buf,
                                           unsigned long max_delay)
{
  SshUInt8 rnd_byte[4];
  unsigned long val;
  unsigned long sec, usec;

  eap->id = ssh_eap_packet_get_identifier(buf);
  eap->id_isinit = 1;
  eap->num_retransmit = -1;

  rnd_byte[0] = (SshUInt8)ssh_random_get_byte();
  rnd_byte[1] = (SshUInt8)ssh_random_get_byte();
  rnd_byte[2] = (SshUInt8)ssh_random_get_byte();
  rnd_byte[3] = (SshUInt8)ssh_random_get_byte();

  val = rnd_byte[0] | (rnd_byte[1] << 8)
    | (rnd_byte[2] << 8) | (rnd_byte[3] << 8);

  /* The Ssh API allows a granularity of 1 microsecond for timeouts, but
     it is not realistic to assume that the timeout mechanism will always
     work at that granularity.

     If we assume that the timeout mechanism works at a granularity
     of approximately one millisecond, then the amount of entropy
     that can be added to leaked timing information is approximately
     10 bits per second.

     Additionally any leaked timing information may be padded
     by the amount (time_when_set_timeout % granularity). */

  val = val & 0xfffff;

  sec = (max_delay * val) >> 20;
  usec = (max_delay * val) & 0xFFFFF;

  SSH_DEBUG(SSH_D_MY,("delay send by %lu sec %lu usec",
		      (unsigned long) sec, (unsigned long) usec));

  ssh_eap_set_send_timeout(eap, sec, usec);
  ssh_eap_remember_packet(eap, buf);
}
/*                                                              shade{0.9}
 * Create isakmp cookie. Generate completely random
 * cookie, as checking the cookie from the hash table is
 * about as fast or faster than hashing stuff together.
 * This also makes cookies movable against multiple machines
 * (high availability or checkpointing systems).
 * The return_buffer must be SSH_IKE_COOKIE_LENGTH
 * bytes long.                                                  shade{1.0}
 */
void ike_cookie_create(SshIkeContext isakmp_context,
                       unsigned char *cookie)
{
  int i;

  for (i = 0; i < SSH_IKE_COOKIE_LENGTH; i++)
    cookie[i] = ssh_random_get_byte();

  SSH_DEBUG_HEXDUMP(SSH_D_LOWOK, ("Cookie create"), cookie, 8);
}
Beispiel #3
0
SshCryptoStatus
ssh_rsa_oaep_encode_with_mgf1(const char *hash_name,
			      const unsigned char *msg,
			      size_t msg_len,
			      const unsigned char *param,
			      size_t param_len,
			      unsigned char *emsg, size_t emsg_len)
{
  unsigned char *db;
  unsigned char seed[SSH_MAX_HASH_DIGEST_LENGTH];
  size_t db_len, i, digest_len;
  SshHash hash;
  SshCryptoStatus status;

  if ((status = ssh_hash_allocate(hash_name, &hash)) != SSH_CRYPTO_OK)
    return status;

  digest_len = ssh_hash_digest_length(hash_name);

  /* Check that the size constraints are satisfied. */
  if (msg_len > emsg_len - 2 * digest_len - 1)
    {
      ssh_hash_free(hash);
      return SSH_CRYPTO_OPERATION_FAILED;
    }

  /* This is: emLen - ||M|| - 2hLen - 1  + hLen + 1 + ||M|| =
     emLen - hLen. */
  db_len = emsg_len - digest_len;
  if ((db = ssh_calloc(1, db_len)) == NULL)
    {
      ssh_hash_free(hash);
      return SSH_CRYPTO_NO_MEMORY;
    }

  ssh_hash_update(hash, param, param_len);
  if ((status = ssh_hash_final(hash, db)) != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      return status;
    }

  /* Add the "01" before the last msg_len bytes. */
  db[db_len - msg_len - 1] = 0x1;

  /* Now throw in the msg. */
  memcpy(db + db_len - msg_len, msg, msg_len);

  /* Generate a random octet string. */
  for (i = 0; i < digest_len; i++)
    seed[i] = ssh_random_get_byte();

  /* Now use the MGF1. */
  if ((status = ssh_rsa_mgf1(hash_name,
			     seed, digest_len,
			     emsg + digest_len, db_len))
      != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      ssh_free(db);
      return status;
    }

  /* Xor. */
  for (i = 0; i < db_len; i++)
    emsg[digest_len + i] ^= db[i];
  memset(db, 0, db_len);

  /* Use MGF1 again. */
  if ((status = ssh_rsa_mgf1(hash_name,
			     emsg + digest_len, db_len,
			     emsg, digest_len))
      != SSH_CRYPTO_OK)
    {
      ssh_hash_free(hash);
      ssh_free(db);
      return status;
    }

  /* Xor the seed. */
  for (i = 0; i < digest_len; i++)
    emsg[i] ^= seed[i];
  memset(seed, 0, digest_len);

  /* Now free the allocated information. */
  ssh_hash_free(hash);
  ssh_free(db);

  return SSH_CRYPTO_OK;
}
SshTlsTransStatus ssh_tls_trans_write_client_hello(SshTlsProtocolState s)
{
  SshTlsCipherSuite tab[SSH_TLS_NUM_CIPHERSUITES];
  SshTlsCipherSuite *suites_to_send;
  SshTlsCipherSuiteDetailsStruct details;
  int number_suites;
  int contents_len;
  unsigned char tempbuf[2];
  int i;

  s->kex.flags |= SSH_TLS_KEX_NEW_SESSION; /* Initially. */

  if (s->conf.preferred_suites != NULL)
    {

      /* If a preference list has been given, check that the
         preferences are sound w.r.t. the protocol flags given in the
         configuration. */

      SshTlsCipherSuite *tmp;

      SSH_DEBUG(6, ("Got a preference list."));

      number_suites = 0;
      tmp = s->conf.preferred_suites;
      while (*tmp != SSH_TLS_NO_CIPHERSUITE)
        {
          ssh_tls_get_ciphersuite_details(*tmp, &details);
          if (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS)))
            {
	      return SSH_TLS_TRANS_FAILED;
            }
          if (details.cipher == SSH_TLS_CIPH_NULL &&
              (!(s->conf.flags & SSH_TLS_NULLCIPHER)))
            {
	      return SSH_TLS_TRANS_FAILED;
            }
          tmp++; number_suites++;
        }
      suites_to_send = s->conf.preferred_suites;
    }
  else
    {
      /* Otherwise construct a list containing all those ciphersuites
         that are supported by our implementation and that can be used
         according to the protocol configuration flags. */

      number_suites = 0;

      for (i = SSH_TLS_RSA_WITH_NULL_MD5; i < SSH_TLS_MAX_CIPHERSUITE; i++)
        {
          ssh_tls_get_ciphersuite_details(i, &details);

          SSH_DEBUG(7, ("Check if suite %d can be supported.", i));

	  if ((details.kex_method == SSH_TLS_UNKNOWN_SUITE)
	       || !(ssh_tls_supported_suite(s->conf.flags, 
					    (SshTlsCipherSuite) i)))
	     continue;

          SSH_DEBUG(7, ("Null? %d  Crippled? %d  RC2? %d  RSA? %d  "
                        "Nosign? %d",
                        (details.cipher == SSH_TLS_CIPH_NULL),
                        (details.crippled),
                        (details.cipher == SSH_TLS_CIPH_RC2),
                        (details.kex_method == SSH_TLS_KEX_RSA),
                        (details.signature_method == SSH_TLS_SIGN_NONE)));

          if ((details.cipher == SSH_TLS_CIPH_NULL &&
               (!(s->conf.flags & SSH_TLS_NULLCIPHER)))
              || (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS)))
              || (details.cipher == SSH_TLS_CIPH_RC2)
              || (details.kex_method != SSH_TLS_KEX_RSA)
              || (details.signature_method != SSH_TLS_SIGN_NONE))
            continue;

          SSH_DEBUG(7, ("Adding the cipher suite %d.", i));

          tab[number_suites++] = i;
        }
      suites_to_send = tab;
    }

  /* Now we can calculate the length of the packet. */

  /* Protocol version 2 bytes, random value 32 bytes,
     session ID 1 + N bytes, ciphersuites list 2 bytes (length)
     plus number_suites * 2 bytes, and 2 bytes for the single
     compression method (no compression) we support. */

  contents_len = 2 + 32 + 1 + s->kex.id_len + 2 + number_suites * 2 + 2;

  /* Initialize the handshake history buffer now. */
  SSH_ASSERT(s->kex.handshake_history == NULL);
  s->kex.handshake_history = ssh_buffer_allocate();

  if (s->kex.handshake_history == NULL)
    return SSH_TLS_TRANS_FAILED;

  ssh_tls_make_hs_header(s, SSH_TLS_HS_CLIENT_HELLO, contents_len);

  /* Write the highest protocol version or that of a hopefully-resumed
     session. */

  tempbuf[0] = s->kex.client_version.major;
  tempbuf[1] = s->kex.client_version.minor;

  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  /* Write unix time. */
  SSH_PUT_32BIT(s->kex.client_random, (SshUInt32)ssh_time());

  /* Write 28 random bytes. */
  for (i = 4; i < 32; i++)
    {
      s->kex.client_random[i]
        = ssh_random_get_byte();
    }
  ssh_tls_add_to_kex_packet(s, s->kex.client_random, 32);

  /* Write the requested session identifier. */
  tempbuf[0] = s->kex.id_len;
  ssh_tls_add_to_kex_packet(s, &tempbuf[0], 1);
  if (s->kex.id_len > 0)
    {
      ssh_tls_add_to_kex_packet(s, s->kex.session_id, s->kex.id_len);
    }

  /* Write the cipher suites. */
  SSH_PUT_16BIT(tempbuf, number_suites * 2);
  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  for (i = 0; i < number_suites; i++)
    {
      SSH_PUT_16BIT(tempbuf, suites_to_send[i]);
      ssh_tls_add_to_kex_packet(s, tempbuf, 2);
    }

  /* And the compression method. */
  tempbuf[0] = 1;
  tempbuf[1] = 0; /* the null compression */
  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  s->kex.state = SSH_TLS_KEX_WAIT_S_HELLO;

  return SSH_TLS_TRANS_OK;
}
Beispiel #5
0
static void
ssh_eap_md5_server_begin(SshEapProtocol protocol, SshEap eap)
{
  unsigned long name_len;
  SshEapMd5State state;
  SshEapMd5Params params;
  SshUInt8 rndbyte;
  SshBuffer pkt;
  int i;

  state = ssh_eap_protocol_get_state(protocol);
  params = ssh_eap_protocol_get_params(protocol);

  if (state == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR,
                ("eap md5 state not initialized. "
                 "can not begin authentication"));
      return;
    }

  /* Parse parameters for defaults and free any "old" state */

  if (params == NULL)
    {
      /* Do not leak too much information regarding the state of the PRNG,
         but make a sufficiently difficult (256 bits) challenge. */
      state->challenge_length = 32;
      name_len = 0;
    }
  else
    {
      state->challenge_length = params->challenge_length;
      name_len = params->name_length;
    }

  if (state->challenge_length > 255)
    state->challenge_length = 255;

  SSH_ASSERT(state->challenge_length > 0);

  if (state->challenge_buffer != NULL)
    {
      ssh_free(state->challenge_buffer);
      state->challenge_buffer = NULL;
    }

  /* Build packet */

  pkt = ssh_eap_create_request(eap,
                               (SshUInt16)(1 + state->challenge_length
                                           + name_len),
                               protocol->impl->id);

  if (pkt == NULL)
    {
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not create request");
      return;
    }

  SSH_ASSERT(state->challenge_length < 256);

  rndbyte = (SshUInt8)state->challenge_length;

  if (ssh_buffer_append(pkt, &rndbyte, 1) != SSH_BUFFER_OK)
    {
      ssh_buffer_free(pkt);
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not create request");
      return;
    }

  state->challenge_buffer = ssh_malloc(state->challenge_length);

  if (state->challenge_buffer == NULL)
    {
      ssh_buffer_free(pkt);
      ssh_eap_fatal(eap, protocol,
                    "Out of memory. Could not create challenge");
      return;
    }


  for (i = 0; i < state->challenge_length; i++)
    {
      rndbyte = (SshUInt8)ssh_random_get_byte();
      state->challenge_buffer[i] = rndbyte;
      if (ssh_buffer_append(pkt, &rndbyte, 1) != SSH_BUFFER_OK)
        {
          ssh_buffer_free(pkt);
          ssh_free(state->challenge_buffer);
          state->challenge_buffer = NULL;
          ssh_eap_fatal(eap, protocol,
                        "Out of memory. Could not create request");
          return;
        }
    }

  if (name_len > 0)
    {
      SSH_ASSERT(params != NULL && params->name_buffer != NULL);

      if (ssh_buffer_append(pkt, params->name_buffer, name_len))
        {
          ssh_buffer_free(pkt);
          ssh_free(state->challenge_buffer);
          state->challenge_buffer = NULL;
          ssh_eap_fatal(eap, protocol,
                        "Out of memory. Could not create request");
          return;
        }
    }

  state->response_id = ssh_eap_packet_get_identifier(pkt);

  SSH_DEBUG(SSH_D_MIDOK,("sending eap md5 authentication request"));
  ssh_eap_protocol_send_request(protocol, eap, pkt);
}
Beispiel #6
0
int main(int ac, char **av)
{
  char port[100];
  int i;
  TestCase *testcase;
  int pass;
  SshTime time_now;

  time_now = ssh_time();
  srandom(time_now);

  for (pass = 0; pass < PASSES; pass++)
    {
#ifdef DEBUG
      ssh_debug("pass %d", pass);
#endif
      random_state = ssh_random_allocate();

      /* randomize it a bit */
      ssh_random_add_noise(random_state, &time_now, sizeof(time_now));

      ssh_buffer_init(&testdata);
      for (i = 0; i < 100000; i++)
        buffer_put_char(&testdata, ssh_random_get_byte(random_state));

      ssh_event_loop_initialize();

      for (i = 0; tests[i].name; i++)
        {
          testcase = &tests[i];
          end_of_script_count = 0;

#ifdef DEBUG      
          ssh_debug("Running test %s", testcase->name);
#endif
          
          snprintf(port, sizeof(port), "%d", (int)(35000 + random() % 1000));
#ifdef DEBUG
          ssh_debug("Making listener, port %s...", port);
#endif
          listener = ssh_tcp_make_listener("127.0.0.1", port,
                                              listener_callback,
                                              (void *)testcase);
          if (!listener)
            ssh_fatal("making listener failed");
#ifdef DEBUG      
          ssh_debug("Making connect...");
#endif
          ssh_tcp_connect_with_socks("127.0.0.1", port, NULL, 2,
                             connect_callback, (void *)testcase);

#ifdef DEBUG      
          ssh_debug("Event loop running...");
#endif 
          ssh_event_loop_run();
#ifdef DEBUG
          ssh_debug("Event loop exited...");
#endif
          if (end_of_script_count != 2)
            ssh_fatal("end_of_script_count %d, script end not reached.",
                  end_of_script_count);
          /* Listener was destroyed in callback. */
        }
  
      ssh_event_loop_uninitialize();
      ssh_buffer_uninit(&testdata);
      ssh_random_free(random_state);
    }
#ifdef DEBUG
  ssh_debug("Exiting...");
#endif
  return 0;
}
Beispiel #7
0
int
main(int argc, char *argv[])
{
  unsigned char *buf = ssh_xmalloc(BUFSIZE);
  unsigned char *buf2 = ssh_xmalloc(BUFSIZE);
  unsigned char *buf3 = ssh_xmalloc(BUFSIZE);
  int buf2len;
  int i;
  int status;
  z_stream s_deflate;
  z_stream s_inflate;

  for (i = 0; i < BUFSIZE; i++)
#if 0
    buf[i] = (unsigned char) ssh_random_get_byte();
#else
    buf[i] = (unsigned char) i;
#endif

  memset(&s_deflate, 0, sizeof(s_deflate));
  status = deflateInit2_(&s_deflate, Z_DEFAULT_COMPRESSION,
                         Z_DEFLATED, -11, DEF_MEM_LEVEL,
                         Z_DEFAULT_STRATEGY, ZLIB_VERSION,
                         sizeof(z_stream));
  SSH_ASSERT(status == Z_OK);

  memset(&s_inflate, 0, sizeof(s_inflate));
  status = inflateInit2_(&s_inflate,  -15, ZLIB_VERSION,
                         sizeof(z_stream));
  SSH_ASSERT(status == Z_OK);

  for (i = 0; i < BUFSIZE; i++)
    {
      s_deflate.next_in = buf;
      s_deflate.avail_in = i;
      s_deflate.next_out = buf2;
      s_deflate.avail_out = BUFSIZE;

      status = deflate(&s_deflate, Z_FINISH);
      if (status != Z_STREAM_END)
        ssh_fatal("status=%d", status);

      buf2len = s_deflate.total_out;
      status = deflateReset(&s_deflate);
      SSH_ASSERT(status == Z_OK);

      s_inflate.next_in = buf2;
      s_inflate.avail_in = buf2len;
      s_inflate.next_out = buf3;
      s_inflate.avail_out = BUFSIZE;

      status = inflate(&s_inflate, Z_FINISH);
      if (status != Z_STREAM_END)
        ssh_warning("status=%d", status);

      if (buf2len < i || 1)
        printf("inlen=%d, outlen=%d, inlen=%lu, %.2f\n", i, buf2len,
               (unsigned long) s_inflate.total_out,
               (double) buf2len / i);
#if 0
      SSH_ASSERT(i == s_inflate.total_out);
#endif
      if (memcmp(buf, buf3, i) != 0)
        ssh_warning("output differs");

      status = inflateReset(&s_inflate);
      SSH_ASSERT(status == Z_OK);
    }

  return 0;
}
Beispiel #8
0
SshX509Status
ssh_pkcs8_encrypt_private_key(const unsigned char *ciphername,
                              const char *hashname,
                              const unsigned char *password,
                              size_t password_len,
                              const SshPrivateKey key,
                              unsigned char **buf, size_t *len)
{
  unsigned char salt[8], *src, *dst;
  size_t i, src_len, dst_len, iters = 1024;
  SshAsn1Context context;
  SshAsn1Node pbeparam, node;
  unsigned char probe[64];
  const SshOidStruct *oid;
  SshX509Status rv;

  /* Encode keymaterial. */
  if ((rv = ssh_pkcs8_encode_private_key(key, &src, &src_len))
      != SSH_X509_OK)
    return rv;

  /* Create salt. */
  for (i = 0; i < sizeof(salt); i++) salt[i] = ssh_random_get_byte();

  /* Probe for this oid being supported at pkcs5 or pkcs12. */
  ssh_snprintf(probe, sizeof(probe), "pbewith%sand%s", hashname, ciphername);
  if ((oid = ssh_oid_find_by_std_name(ssh_sstr(probe))) != NULL)
    {
      dst = ssh_pkcs5_pbes1_encrypt(ciphername, hashname,
                                    password, password_len, salt, iters,
                                    src, src_len,
                                    &dst_len);
    }
  else if ((oid = ssh_oid_find_by_oid_of_type(ciphername, SSH_OID_PKCS12))
           != NULL)
    {
      const SshOidPkcs5Struct *extra = oid->extra;

      if (hashname && strcmp(hashname, extra->hash))
        return SSH_X509_FAILED_UNKNOWN_VALUE;

      dst = ssh_pkcs12_pbe_encrypt(extra->cipher,
                                   extra->keylen, extra->hash, iters,
                                   password, password_len,
                                   salt, sizeof(salt), src, src_len,
                                   &dst_len);
    }
  else
    {
      ssh_free(src);
      return SSH_X509_FAILED_UNKNOWN_VALUE;
    }

  ssh_free(src);

  /* If OK, then encode the PKCS8 encrypted private key payload. */
  if (dst)
    {
      if ((context = ssh_asn1_init()) == NULL)
        {
          ssh_free(dst);
          return SSH_X509_FAILURE;
        }
      /* PKCS#5 PBEParameter */
      if (ssh_asn1_create_node(context, &pbeparam,
                               "(sequence ()"
                               "  (octet-string ())"
                               "  (integer-short ()))",
                               salt, sizeof(salt),
                               iters)
          == SSH_ASN1_STATUS_OK)
        {
          if (ssh_asn1_create_node(context, &node,
                                   "(sequence ()"
                                   "  (sequence ()"
                                   "    (object-identifier ())"
                                   "    (any ()))"
                                   "  (octet-string ()))",
                                   oid->oid, pbeparam, dst, dst_len)
              == SSH_ASN1_STATUS_OK)
            {
              ssh_asn1_encode_node(context, node);
              ssh_asn1_node_get_data(node, buf, len);
              ssh_asn1_free(context);
              ssh_free(dst);
              return SSH_X509_OK;
            }
        }
      ssh_asn1_free(context);
      ssh_free(dst);
      return SSH_X509_FAILED_ASN1_ENCODE;
    }
  return SSH_X509_FAILED_UNKNOWN_VALUE;
}