Example #1
0
int
shishi_apreq_decrypt (Shishi * handle,
		      Shishi_asn1 apreq,
		      Shishi_key * key,
		      int keyusage, Shishi_asn1 * authenticator)
{
  int res;
  int i;
  char *buf;
  size_t buflen;
  char *cipher;
  size_t cipherlen;
  int etype;

  res = shishi_apreq_get_authenticator_etype (handle, apreq, &etype);
  if (res != SHISHI_OK)
    return res;

  if (etype != shishi_key_type (key))
    return SHISHI_APREQ_BAD_KEYTYPE;

  res = shishi_asn1_read (handle, apreq, "authenticator.cipher",
			  &cipher, &cipherlen);
  if (res != SHISHI_OK)
    return res;

  res = shishi_decrypt (handle, key, keyusage,
			cipher, cipherlen, &buf, &buflen);
  free (cipher);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (handle,
			   "decrypt fail, most likely wrong password\n");
      return SHISHI_APREQ_DECRYPT_FAILED;
    }

  /* The crypto is so 1980; no length indicator. Trim off pad bytes
     until we can parse it. */
  for (i = 0; i < 8; i++)
    {
      if (VERBOSEASN1 (handle))
	printf ("Trying with %d pad in enckdcrep...\n", i);

      *authenticator = shishi_der2asn1_authenticator (handle, &buf[0],
						      buflen - i);
      if (*authenticator != NULL)
	break;
    }

  if (*authenticator == NULL)
    {
      shishi_error_printf (handle, "Could not DER decode Authenticator. "
			   "Password probably correct (decrypt ok) though\n");
      return SHISHI_ASN1_ERROR;
    }

  return SHISHI_OK;
}
Example #2
0
/**
 * shishi_authenticator_add_cksum:
 * @handle: shishi handle as allocated by shishi_init().
 * @authenticator: authenticator as allocated by shishi_authenticator().
 * @key: key to to use for encryption.
 * @keyusage: cryptographic key usage value to use in encryption.
 * @data: input array with data to calculate checksum on.
 * @datalen: size of input array with data to calculate checksum on.
 *
 * Calculate checksum for data and store it in the authenticator.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_authenticator_add_cksum (Shishi * handle,
                                Shishi_asn1 authenticator,
                                Shishi_key * key,
                                int keyusage, char *data, size_t datalen)
{
    return shishi_authenticator_add_cksum_type (handle, authenticator, key,
            keyusage,
            shishi_cipher_defaultcksumtype
            (shishi_key_type (key)),
            data, datalen);
}
Example #3
0
/**
 * shishi_authenticator_add_subkey:
 * @handle: shishi handle as allocated by shishi_init().
 * @authenticator: authenticator as allocated by shishi_authenticator().
 * @subkey: subkey to add to authenticator.
 *
 * Store subkey in the authenticator.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_authenticator_add_subkey (Shishi * handle,
                                 Shishi_asn1 authenticator,
                                 Shishi_key * subkey)
{
    int res;

    res = shishi_authenticator_set_subkey (handle, authenticator,
                                           shishi_key_type (subkey),
                                           shishi_key_value (subkey),
                                           shishi_key_length (subkey));
    if (res != SHISHI_OK)
        return res;

    return SHISHI_OK;
}
Example #4
0
/**
 * shishi_encticketpart_key_set:
 * @handle: shishi handle as allocated by shishi_init().
 * @encticketpart: input EncTicketPart variable.
 * @key: key handle with information to store in encticketpart.
 *
 * Set the EncTicketPart.key field to key type and value of supplied
 * key.
 *
 * Return value: Returns %SHISHI_OK iff successful.
 **/
int
shishi_encticketpart_key_set (Shishi * handle,
			      Shishi_asn1 encticketpart, Shishi_key * key)
{
  int res;
  int keytype;

  keytype = shishi_key_type (key);
  res = shishi_asn1_write_uint32 (handle, encticketpart,
				  "key.keytype", keytype);
  if (res != SHISHI_OK)
    return res;

  res = shishi_asn1_write (handle, encticketpart, "key.keyvalue",
			   shishi_key_value (key), shishi_key_length (key));
  if (res != SHISHI_OK)
    return res;

  return SHISHI_OK;
}
Example #5
0
/**
 * shishi_apreq_add_authenticator:
 * @handle: shishi handle as allocated by shishi_init().
 * @apreq: AP-REQ to add authenticator field to.
 * @key: key to to use for encryption.
 * @keyusage: cryptographic key usage value to use in encryption.
 * @authenticator: authenticator as allocated by shishi_authenticator().
 *
 * Encrypts DER encoded authenticator using key and store it in the
 * AP-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_apreq_add_authenticator (Shishi * handle,
				Shishi_asn1 apreq,
				Shishi_key * key,
				int keyusage, Shishi_asn1 authenticator)
{
  int res;
  char *buf;
  size_t buflen;
  char *der;
  size_t derlen;

  res = shishi_asn1_to_der (handle, authenticator, &der, &derlen);
  if (res != SHISHI_OK)
    {
      shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
			   shishi_strerror (res));
      return res;
    }

  res = shishi_encrypt (handle, key, keyusage, der, derlen, &buf, &buflen);

  free (der);

  if (res != SHISHI_OK)
    {
      shishi_error_printf (handle, "Cannot encrypt authenticator.\n");
      return res;
    }

  res = shishi_apreq_set_authenticator (handle, apreq, shishi_key_type (key),
					shishi_key_version (key),
					buf, buflen);

  return res;
}
Example #6
0
int
do_shishi_login (int infd, struct auth_data *ad, const char **err_msg)
{
  int rc;
  int error = 0;
  int keylen, keytype;
  struct passwd *pwd = NULL;
  int cksumtype, cksumlen = 30;
  char *cksum;
  char *compcksum;
  size_t compcksumlen;
  char cksumdata[100];
  struct sockaddr_in sock;
  size_t socklen = sizeof (struct sockaddr_in);

#  ifdef ENCRYPTION
  rc = get_auth (infd, &ad->h, &ad->ap, &ad->enckey, err_msg, &ad->protocol,
		 &cksumtype, &cksum, &cksumlen);
#  else
  rc = get_auth (infd, &ad->h, &ad->ap, NULL, err_msg, &ad->protocol,
		 &cksumtype, &cksum, &cksumlen);
#  endif
  if (rc != SHISHI_OK)
    return rc;

#  ifdef ENCRYPTION
  /* init IV */
  if (encrypt_io)
    {
      int i;
      char *iv;

      ad->ivtab[0] = &ad->iv1;
      ad->ivtab[1] = &ad->iv2;

      keytype = shishi_key_type (ad->enckey);
      keylen = shishi_cipher_blocksize (keytype);

      for (i = 0; i < 2; i++)
	{
	  ad->ivtab[i]->ivlen = keylen;

	  switch (keytype)
	    {
	    case SHISHI_DES_CBC_CRC:
	    case SHISHI_DES_CBC_MD4:
	    case SHISHI_DES_CBC_MD5:
	    case SHISHI_DES_CBC_NONE:
	    case SHISHI_DES3_CBC_HMAC_SHA1_KD:
	      ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES;
	      ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen);
	      memset (ad->ivtab[i]->iv, i, ad->ivtab[i]->ivlen);
	      ad->ivtab[i]->ctx =
		shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage,
			       shishi_key_type (ad->enckey), ad->ivtab[i]->iv,
			       ad->ivtab[i]->ivlen);
	      break;
	    case SHISHI_ARCFOUR_HMAC:
	    case SHISHI_ARCFOUR_HMAC_EXP:
	      ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4 * i;
	      ad->ivtab[i]->ctx =
		shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage,
			       shishi_key_type (ad->enckey), NULL, 0);
	      break;
	    default:
	      ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4 * i;
	      ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen);
	      memset (ad->ivtab[i]->iv, 0, ad->ivtab[i]->ivlen);
	      if (ad->protocol == 2)
		ad->ivtab[i]->ctx =
		  shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage,
				 shishi_key_type (ad->enckey),
				 ad->ivtab[i]->iv, ad->ivtab[i]->ivlen);
	    }
	}
    }
#  endif

  getstr (infd, &ad->lusername, NULL);
  getstr (infd, &ad->term, "TERM=");
  getstr (infd, &ad->rusername, NULL);

  rc = read (infd, &error, sizeof (int));
  if ((rc != sizeof (int)) && rc)
    {
      free (pwd);
      free (cksum);
      return 1;
    }

  /*
     getpwnam crash !!!!

     pwd = getpwnam (ad->lusername);
     if (pwd == NULL)
     {
     *err_msg = "getpwnam failed";
     syslog (LOG_ERR, "getpwnam failed: %m");
     return 1;
     }

     syslog (LOG_INFO | LOG_AUTH,
     "%sKerberos V login from %s on %s\n",
     (pwd->pw_uid == 0) ? "ROOT " : "",
     ad->lusername, ad->hostname);

   */

  free (pwd);

  syslog (LOG_INFO | LOG_AUTH,
	  "Kerberos V login from %s on %s\n", ad->lusername, ad->hostname);

  /* verify checksum */

  if (getsockname (infd, (struct sockaddr *) &sock, &socklen) < 0)
    {
      syslog (LOG_ERR, "Can't get sock name");
      fatal (infd, "Can't get sockname", 1);
    }

  snprintf (cksumdata, 100, "%u:%s%s", ntohs (sock.sin_port), ad->term + 5,
	    ad->lusername);
  rc = shishi_checksum (ad->h, ad->enckey, 0, cksumtype, cksumdata,
			strlen (cksumdata), &compcksum, &compcksumlen);
  free (cksum);
  if (rc != SHISHI_OK
      || compcksumlen != cksumlen || memcmp (compcksum, cksum, cksumlen) != 0)
    {
      /* err_msg crash ? */
      /* *err_msg = "checksum verify failed"; */
      syslog (LOG_ERR, "checksum verify failed: %s", shishi_error (ad->h));
      free (compcksum);
      return 1;
    }

  free (compcksum);

  rc = shishi_authorized_p (ad->h, shishi_ap_tkt (ad->ap), ad->lusername);
  if (!rc)
    {
      syslog (LOG_ERR, "User is not authorized to log in as: %s",
	      ad->lusername);
      shishi_ap_done (ad->ap);
      return 1;
    }

  shishi_ap_done (ad->ap);

  return SHISHI_OK;
}
Example #7
0
int
main (int argc, char **argv)
{
  int index;
  struct passwd *pw;
  struct servent *sp;
  sigset_t sigs, osigs;
  int asrsh, rem;
  pid_t pid = 0;
  uid_t uid;
  char *args, *host;

  set_program_name (argv[0]);

  asrsh = 0;
  host = user = NULL;

  /* If called as something other than "rsh", use it as the host name */
  {
    char *p = strrchr (argv[0], '/');
    if (p)
      ++p;
    else
      p = argv[0];
    if (strcmp (p, "rsh"))
      host = p;
    else
      asrsh = 1;
  }

  /* Parse command line */
  iu_argp_init ("rsh", default_program_authors);
  argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &index, NULL);

  if (index < argc)
    host = argv[index++];

  /* To few args.  */
  if (!host)
    error (EXIT_FAILURE, 0, "host not specified");

  /* If no further arguments, must have been called as rlogin. */
  if (!argv[index])
    {
      if (asrsh)
	*argv = (char *) "rlogin";
      seteuid (getuid ());
      setuid (getuid ());
      execv (PATH_RLOGIN, argv);
      error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN);
    }

  argc -= index;
  argv += index;

  /* We must be setuid root.  */
  if (geteuid ())
    error (EXIT_FAILURE, 0, "must be setuid root.\n");

  if (!(pw = getpwuid (uid = getuid ())))
    error (EXIT_FAILURE, 0, "unknown user id");

  /* Accept user1@host format, though "-l user2" overrides user1 */
  {
    char *p = strchr (host, '@');
    if (p)
      {
	*p = '\0';
	if (!user && p > host)
	  user = host;
	host = p + 1;
	if (*host == '\0')
	  error (EXIT_FAILURE, 0, "empty host name");
      }
  }

#if defined KERBEROS || defined SHISHI
# ifdef ENCRYPTION
  /* -x turns off -n */
  if (doencrypt)
    null_input_option = 0;
# endif
#endif

  args = copyargs (argv);

  sp = NULL;
#ifdef KERBEROS
  if (use_kerberos)
    {
      sp = getservbyname ((doencrypt ? "ekshell" : "kshell"), "tcp");
      if (sp == NULL)
	{
	  use_kerberos = 0;
	  warning ("can't get entry for %s/tcp service",
		   doencrypt ? "ekshell" : "kshell");
	}
    }
#elif defined(SHISHI)
  if (use_kerberos)
    {
      sp = getservbyname ("kshell", "tcp");
      if (sp == NULL)
	{
	  use_kerberos = 0;
	  warning ("can't get entry for %s/tcp service", "kshell");
	}
    }
#endif
  if (sp == NULL)
    sp = getservbyname ("shell", "tcp");
  if (sp == NULL)
    error (EXIT_FAILURE, 0, "shell/tcp: unknown service");


#if defined KERBEROS || defined SHISHI
try_connect:
  if (use_kerberos)
    {
      struct hostent *hp;

      /* fully qualify hostname (needed for krb_realmofhost) */
      hp = gethostbyname (host);
      if (hp != NULL && !(host = strdup (hp->h_name)))
	error (EXIT_FAILURE, errno, "strdup");

# if defined KERBEROS
      rem = KSUCCESS;
      errno = 0;
      if (dest_realm == NULL)
	dest_realm = krb_realmofhost (host);
# elif defined (SHISHI)
      rem = SHISHI_OK;
      errno = 0;
# endif

# ifdef ENCRYPTION
      if (doencrypt)
#  if defined SHISHI
	{
	  int i;
	  char *term;

	  term = xmalloc (strlen (args) + 4);
	  strcpy (term, "-x ");
	  strcat (term, args);

	  rem = krcmd_mutual (&h, &host, sp->s_port, &user, term, &rfd2,
			      dest_realm, &enckey);
	  if (rem > 0)
	    {
	      keytype = shishi_key_type (enckey);
	      keylen = shishi_cipher_blocksize (keytype);

	      ivtab[0] = &iv1;
	      ivtab[1] = &iv2;
	      ivtab[2] = &iv3;
	      ivtab[3] = &iv4;

	      for (i = 0; i < 4; i++)
		{
		  ivtab[i]->ivlen = keylen;

		  switch (keytype)
		    {
		    case SHISHI_DES_CBC_CRC:
		    case SHISHI_DES_CBC_MD4:
		    case SHISHI_DES_CBC_MD5:
		    case SHISHI_DES_CBC_NONE:
		    case SHISHI_DES3_CBC_HMAC_SHA1_KD:
		      ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES;
		      ivtab[i]->iv = malloc (ivtab[i]->ivlen);
		      memset (ivtab[i]->iv,
			      2 * i + 1 * (i < 2) - 4 * (i >= 2),
			      ivtab[i]->ivlen);
		      ivtab[i]->ctx =
			shishi_crypto (h, enckey, ivtab[i]->keyusage,
				       shishi_key_type (enckey), ivtab[i]->iv,
				       ivtab[i]->ivlen);
		      break;
		    case SHISHI_ARCFOUR_HMAC:
		    case SHISHI_ARCFOUR_HMAC_EXP:
		      ivtab[i]->keyusage =
			SHISHI_KEYUSAGE_KCMD_DES + 2 + 4 * i;
		      ivtab[i]->ctx =
			shishi_crypto (h, enckey, ivtab[i]->keyusage,
				       shishi_key_type (enckey), NULL, 0);
		      break;
		    default:
		      ivtab[i]->keyusage =
			SHISHI_KEYUSAGE_KCMD_DES + 2 + 4 * i;
		      ivtab[i]->iv = malloc (ivtab[i]->ivlen);
		      memset (ivtab[i]->iv, 0, ivtab[i]->ivlen);
		      ivtab[i]->ctx =
			shishi_crypto (h, enckey, ivtab[i]->keyusage,
				       shishi_key_type (enckey), ivtab[i]->iv,
				       ivtab[i]->ivlen);
		    }
		}
	    }
	  free (term);
	}
      else
#  else
	rem = krcmd_mutual (&host, sp->s_port, user, args, &rfd2,
			    dest_realm, &cred, schedule);
      else
#  endif
# endif
	rem = krcmd (
# if defined SHISHI
		      &h, &host, sp->s_port, &user, args, &rfd2, dest_realm);
# else
		      &host, sp->s_port, user, args, &rfd2, dest_realm);
# endif
      if (rem < 0)
	{
	  use_kerberos = 0;
	  sp = getservbyname ("shell", "tcp");
	  if (sp == NULL)
	    error (EXIT_FAILURE, 0, "shell/tcp: unknown service");
	  if (errno == ECONNREFUSED)
	    warning ("remote host doesn't support Kerberos");
	  if (errno == ENOENT)
	    warning ("can't provide Kerberos auth data");
	  goto try_connect;
	}
    }
Example #8
0
/* read encrypted data on socket */
int
readenc (Shishi * h, int sock, char *buf, int *len, char *iv, int *ivlen,
	 Shishi_key * enckey)
{
  char *out;
  char *outbis;
  char *iv2;

  int rc;
  int val;
  int outlen;
  int dlen = 0, blocksize, enctype, hashsize;

  /* read size of message */
  read (sock, &dlen, sizeof (int));

  dlen = ntohl (dlen);
  /* if 0 put read size to 0 */
  if (!dlen)
    {
      *len = dlen;
      return SHISHI_OK;
    }

  /* convert size to encryption size */
  enctype = shishi_key_type (enckey);

  blocksize = shishi_cipher_blocksize (enctype);
  hashsize =
    shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype));

  dlen += blocksize - 1 + 4;
  if (shishi_key_type (enckey) != SHISHI_DES3_CBC_HMAC_SHA1_KD)
    dlen += hashsize;
  else
    dlen += blocksize;

  dlen /= blocksize;
  dlen *= blocksize;

  if (shishi_key_type (enckey) == SHISHI_DES3_CBC_HMAC_SHA1_KD)
    dlen += hashsize;

  /* read encrypted data */
  outbis = malloc (dlen);
  if (outbis == NULL)
    {
      printf ("Malloc error!\n");
      return 1;
    }

  rc = read (sock, outbis, dlen);
  if (rc != dlen)
    {
      printf ("Error during read socket\n");
      return 1;
    }

  /* decrypt it */
  rc =
    shishi_decrypt_ivupdate (h, enckey, 1026, iv, *ivlen, &iv2, ivlen, outbis,
			     dlen, &out, &outlen);
  if (rc != SHISHI_OK)
    {
      printf ("decryption error\n");
      return 1;
    }

  /* len = first 4 bytes of decrypted data */
  *len = ntohl (*((int *) out));

  /* update iv */
  memcpy (iv, iv2, *ivlen);

  /* Temp patch to remove 5 unidentified bytes data from server */
  memset (buf, 0, BUFLEN);
  if ((unsigned char) out[4] == 255)
    val = 5 + sizeof (int);
  else
    val = sizeof (int);

  /* copy decrypted data to output */
  memcpy (buf, out + val, strlen (out + val));


  free (out);
  free (outbis);

  return SHISHI_OK;
}
Example #9
0
/**
 * shishi_kdcreq_add_padata_preauth:
 * @handle: shishi handle as allocated by shishi_init().
 * @kdcreq: KDC-REQ to add pre-authentication data to.
 * @key: Key used to encrypt pre-auth data.
 *
 * Add pre-authentication data to KDC-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_kdcreq_add_padata_preauth (Shishi * handle,
                                  Shishi_asn1 kdcreq, Shishi_key * key)
{
    char *der, *data;
    size_t derlen, datalen;
    Shishi_asn1 pa;
    struct timeval tv;
    int rc;
    Shishi_asn1 ed;

    pa = shishi_asn1_pa_enc_ts_enc (handle);
    if (!pa)
        return SHISHI_ASN1_ERROR;

    rc = gettimeofday (&tv, NULL);
    if (rc != 0)
        return SHISHI_GETTIMEOFDAY_ERROR;

    rc = shishi_asn1_write (handle, pa, "patimestamp",
                            shishi_generalize_time (handle, tv.tv_sec),
                            SHISHI_GENERALIZEDTIME_LENGTH);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_asn1_write_integer (handle, pa, "pausec", tv.tv_usec);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_asn1_to_der (handle, pa, &der, &derlen);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ASREQ_PA_ENC_TIMESTAMP,
                         der, derlen, &data, &datalen);
    free (der);
    if (rc != SHISHI_OK)
        return rc;

    ed = shishi_asn1_encrypteddata (handle);
    if (!ed)
        return SHISHI_ASN1_ERROR;

    rc = shishi_asn1_write_integer (handle, ed, "etype", shishi_key_type (key));
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_asn1_write (handle, ed, "cipher", data, datalen);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_asn1_write (handle, ed, "kvno", NULL, 0);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_asn1_to_der (handle, ed, &der, &derlen);
    free (data);
    if (rc != SHISHI_OK)
        return rc;

    rc = shishi_kdcreq_add_padata (handle, kdcreq, SHISHI_PA_ENC_TIMESTAMP,
                                   der, derlen);
    free (der);
    if (rc != SHISHI_OK)
        return rc;

    return rc;
}
Example #10
0
/* read encrypted data on socket */
int
readenc (Shishi * h, int sock, char *buf, int *len, shishi_ivector * iv,
	 Shishi_key * enckey, int proto)
{
  char *out;
  char *outbis;

  int rc;
  int val;
  int outlen;
  int dlen = 0, blocksize, enctype, hashsize;

  /* read size of message */
  read (sock, &dlen, sizeof (int));

  dlen = ntohl (dlen);
  /* if 0 put read size to 0 */
  if (!dlen)
    {
      *len = dlen;
      return SHISHI_OK;
    }

  if (proto == 1)
    *len = dlen;

  /* convert size to encryption size */
  enctype = shishi_key_type (enckey);

  blocksize = shishi_cipher_blocksize (enctype);
  hashsize =
    shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype));

  switch (enctype)
    {
    case SHISHI_AES128_CTS_HMAC_SHA1_96:
    case SHISHI_AES256_CTS_HMAC_SHA1_96:
      dlen += 4 + hashsize + blocksize;
      break;
    case SHISHI_ARCFOUR_HMAC:
    case SHISHI_ARCFOUR_HMAC_EXP:
      dlen += 4 + 8 + blocksize - 1;
      dlen /= blocksize;
      dlen *= blocksize;
      dlen += hashsize;
      break;
    case SHISHI_DES3_CBC_HMAC_SHA1_KD:
      dlen += 4 + 2 * blocksize - 1;
      dlen /= blocksize;
      dlen *= blocksize;
      dlen += hashsize;
      break;
    case SHISHI_DES_CBC_CRC:
      dlen += 2 * blocksize - 1;
      if (proto == 2)
	dlen += 4;
      dlen += hashsize;
      dlen /= blocksize;
      dlen *= blocksize;
      break;
    default:
      dlen += blocksize - 1;
      if (proto == 2)
	dlen += 4;
      dlen += hashsize;
      dlen /= blocksize;
      dlen *= blocksize;
      break;
    }

  /* read encrypted data */
  outbis = malloc (dlen);
  if (outbis == NULL)
    {
      perror ("readenc()");
      return 1;
    }

  rc = read (sock, outbis, dlen);
  if (rc != dlen)
    {
      fprintf (stderr, "Error during read socket\n");
      free (outbis);
      return 1;
    }

  if (proto == 1)
    {
      rc =
	shishi_decrypt (h, enckey, iv->keyusage, outbis, dlen, &out, &outlen);
      if (rc != SHISHI_OK)
	{
	  fprintf (stderr, "decryption error\n");
	  free (outbis);
	  return 1;
	}

      val = 0;
    }
  else
    {
      rc = shishi_crypto_decrypt (iv->ctx, outbis, dlen, &out, &outlen);
      if (rc != SHISHI_OK)
	{
	  fprintf (stderr, "decryption error\n");
	  free (outbis);
	  return 1;
	}

      /* in KCMDV0.2 first 4 bytes of decrypted data = len of data */
      *len = ntohl (*((int *) out));
      val = sizeof (int);
    }

  memset (buf, 0, BUFLEN);

  /* copy decrypted data to output */
  memcpy (buf, out + val, outlen - val);

  free (out);
  free (outbis);

  return SHISHI_OK;
}