Boolean
ssh_virtual_adapter_param_decode(SshVirtualAdapterParams params,
				 const unsigned char *data, size_t len)
{
  unsigned char *dns;
  size_t dns_len;
  unsigned char *wins;
  size_t wins_len;
  unsigned char *win_domain;
  size_t win_domain_len;
  SshUInt32 netbios_node_type;
  SshUInt32 i;
  size_t decode_len;

  SSH_ASSERT(params != NULL);
  SSH_ASSERT(data != NULL);
  SSH_ASSERT(len > 0);

  memset(params, 0, sizeof(*params));
  
  if (ssh_decode_array(data, len,
		       SSH_DECODE_UINT32(&params->mtu),
		       SSH_DECODE_UINT32(&params->dns_ip_count),
		       SSH_DECODE_UINT32_STR_NOCOPY(&dns, &dns_len),
		       SSH_DECODE_UINT32(&params->wins_ip_count),
		       SSH_DECODE_UINT32_STR_NOCOPY(&wins, &wins_len),
		       SSH_DECODE_UINT32_STR_NOCOPY(
		       &win_domain, &win_domain_len),
		       SSH_DECODE_UINT32(&netbios_node_type),
		       SSH_FORMAT_END) != len)
    return FALSE;

  /* DNS. */
  if (params->dns_ip_count)
    {
      params->dns_ip = ssh_calloc(params->dns_ip_count, 
				  sizeof(*params->dns_ip));
      if (params->dns_ip == NULL)
	goto error;
      
      for (i = 0; i < params->dns_ip_count; i++)
	{
	  decode_len = ssh_decode_ipaddr_array(dns, dns_len, 
					       &params->dns_ip[i]);
	  if (decode_len == 0)
	    goto error;	  
	  dns += decode_len;
	  dns_len -= decode_len;
	}
    }
  
      /* WINS. */
  if (params->wins_ip_count)
    {
      params->wins_ip = ssh_calloc(params->wins_ip_count, 
				   sizeof(*params->wins_ip));
      if (params->wins_ip == NULL)
	goto error;
      
      for (i = 0; i < params->wins_ip_count; i++)
	{
	  decode_len = ssh_decode_ipaddr_array(wins, wins_len, 
					       &params->wins_ip[i]);
	  if (decode_len == 0)
	    goto error;	  
	  wins += decode_len;
	  wins_len -= decode_len;
	}
    }
  
  if (win_domain_len)
    {
      params->win_domain = ssh_memdup(win_domain, win_domain_len);
      if (params->win_domain == NULL)
	goto error;
    }
  
  params->netbios_node_type = (SshUInt8) netbios_node_type;

  return TRUE;

 error:
  ssh_free(params->dns_ip);
  ssh_free(params->wins_ip);
  ssh_free(params->win_domain);
  memset(params, 0, sizeof(*params));
  return FALSE;
}
void ssh_acc_device_modexp_op_done(SshCryptoStatus status,
                                   const unsigned char *data,
                                   size_t data_len,
                                   void *context)
{

  SshAccDeviceModExpContext ctx = context;
  
  ctx->sub_op = NULL;
  
  if (status == SSH_CRYPTO_OK)
    {
      /* No array decoding is needed. */
      (*ctx->callback)(SSH_CRYPTO_OK, data, data_len, ctx->context);
      ssh_acc_device_modexp_op_free(ctx);
      return;
    }
  else 
    {
      unsigned char *b, *e, *m, *ret;
      size_t b_len, e_len, mod_len, ret_len;

      /* The accelerated operation has failed, instead perform the operation 
	 in software. */
      SSH_DEBUG(SSH_D_FAIL, ("Accelerated modexp operation has failed, "
			     "now performing the operation in software"));
      
      /* Decode the data buffer to extract the original parameters */
      if (ssh_decode_array(ctx->data, ctx->data_len,
			   SSH_DECODE_UINT32_STR_NOCOPY(&b, &b_len),
			   SSH_DECODE_UINT32_STR_NOCOPY(&e, &e_len),
			   SSH_DECODE_UINT32_STR_NOCOPY(&m, &mod_len),
			   SSH_FORMAT_END) != ctx->data_len)
        {
          (*ctx->callback)(SSH_CRYPTO_NO_MEMORY, NULL, 0, ctx->context);
	  ssh_acc_device_modexp_op_free(ctx);
          return;
        }
      
      ret_len = mod_len;
      if ((ret = ssh_calloc(1, ret_len)) == NULL)
        {
          (*ctx->callback)(SSH_CRYPTO_NO_MEMORY, NULL, 0, ctx->context);
	  ssh_acc_device_modexp_op_free(ctx);
          return;
        }
      
      if (modexp_op_buf(ret, ret_len, b, b_len, 
                        e, e_len, m, mod_len))
        {
          (*ctx->callback)(SSH_CRYPTO_OK, ret, ret_len, ctx->context);
        }
      else
        {
          (*ctx->callback)(SSH_CRYPTO_OPERATION_FAILED, NULL, 0, ctx->context);
        }

      ssh_acc_device_modexp_op_free(ctx);
      ssh_free(ret);
      return;
    } 

}