コード例 #1
0
ファイル: cipher-nettle.c プロジェクト: 32bitmicro/riscv-qemu
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
                                  QCryptoCipherMode mode,
                                  const uint8_t *key, size_t nkey,
                                  Error **errp)
{
    QCryptoCipher *cipher;
    QCryptoCipherNettle *ctx;
    uint8_t *rfbkey;

    switch (mode) {
    case QCRYPTO_CIPHER_MODE_ECB:
    case QCRYPTO_CIPHER_MODE_CBC:
        break;
    default:
        error_setg(errp, "Unsupported cipher mode %d", mode);
        return NULL;
    }

    if (!qcrypto_cipher_validate_key_length(alg, nkey, errp)) {
        return NULL;
    }

    cipher = g_new0(QCryptoCipher, 1);
    cipher->alg = alg;
    cipher->mode = mode;

    ctx = g_new0(QCryptoCipherNettle, 1);

    switch (alg) {
    case QCRYPTO_CIPHER_ALG_DES_RFB:
        ctx->ctx_encrypt = g_new0(struct des_ctx, 1);
        ctx->ctx_decrypt = NULL; /* 1 ctx can do both */
        rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
        des_set_key(ctx->ctx_encrypt, rfbkey);
        g_free(rfbkey);

        ctx->alg_encrypt = des_encrypt_wrapper;
        ctx->alg_decrypt = des_decrypt_wrapper;

        ctx->blocksize = DES_BLOCK_SIZE;
        break;

    case QCRYPTO_CIPHER_ALG_AES_128:
    case QCRYPTO_CIPHER_ALG_AES_192:
    case QCRYPTO_CIPHER_ALG_AES_256:
        ctx->ctx_encrypt = g_new0(struct aes_ctx, 1);
        ctx->ctx_decrypt = g_new0(struct aes_ctx, 1);

        aes_set_encrypt_key(ctx->ctx_encrypt, nkey, key);
        aes_set_decrypt_key(ctx->ctx_decrypt, nkey, key);

        ctx->alg_encrypt = aes_encrypt_wrapper;
        ctx->alg_decrypt = aes_decrypt_wrapper;

        ctx->blocksize = AES_BLOCK_SIZE;
        break;
    default:
        error_setg(errp, "Unsupported cipher algorithm %d", alg);
        goto error;
    }

    ctx->iv = g_new0(uint8_t, ctx->blocksize);
    cipher->opaque = ctx;

    return cipher;

 error:
    g_free(cipher);
    g_free(ctx);
    return NULL;
}
コード例 #2
0
ファイル: tunet.c プロジェクト: alick/mytunet
int tunet_keepalive()
{
	BYTE tmpbuf[1024];
	BYTE repbuf[9];
	CHAR tmp[1024];
	BYTE *p;
	BYTE btag;
	BYTE data[16];

	CHAR smoney[255];

	des_context ctx;
	int len;
	UINT32 uint_used_money, uint_money;
	STRING *str = NULL;
	
//	BOOL sr, sw, se;
	
	if(!keepalive_socket) return OK;
	
//	os_socket_tcp_status(keepalive_socket, &sr, &sw, &se);

	if(tunet_state != TUNET_STATE_KEEPALIVE){
//		printf("state error\n");
		return OK;
		}

/*	if(se)
	{
		logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0);
		return ERR;
	}

	if(!sr) return OK;

*/
//	printf("start recv.\n");
	len = os_socket_tcp_recv(keepalive_socket, tmpbuf, sizeof(tmpbuf));
//	printf("finished recv.\n");
	if(len == -1)
	{
		logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0);
		return ERR;
	}

	if(len > 0)
	{
		keepalive_socket_buffer = buffer_append(keepalive_socket_buffer, tmpbuf, len);
		buf2output(tmpbuf, len, tmp, 16);
		//dprintf("data received(keepalive):\n%s\n", tmp);


		logs_append(g_logs, "TUNET_KEEPALIVE_RECV", NULL, tmpbuf, len);

		p = keepalive_socket_buffer->data;
		while(buffer_fetch_BYTE(keepalive_socket_buffer, &p, &btag))
		{
			switch(btag)
			{
				case 0x03:

					if(!buffer_fetch_bytes(keepalive_socket_buffer, &p, data, 16))
						return OK;

					logs_append(g_logs, "TUNET_KEEPALIVE_CONFIRM", NULL, NULL, 0);

					uint_used_money = htonl(BUFDWORD( (data + 8) ));
					

					uint_money = htonl(BUFDWORD( (data + 12) ));
					

					des_set_key(&ctx, (uint8 *)keepalive_key);
					des_encrypt(&ctx, (uint8 *)data, (uint8 *)(repbuf + 1));
					repbuf[0] = 0x02;
					os_socket_tcp_send(keepalive_socket, repbuf, sizeof(repbuf));



					keepalive_socket_buffer = buffer_rollto(keepalive_socket_buffer, p);
					p = keepalive_socket_buffer->data;

					os_tick_clear(keepalive_timeout);

					snprintf(smoney, sizeof(smoney), "%0.2f", tunet_imoney_to_fmoney(uint_money));					
					logs_append(g_logs, "TUNET_KEEPALIVE_MONEY", smoney, NULL, 0);

					snprintf(smoney, sizeof(smoney), "%0.2f", tunet_imoney_to_fmoney(uint_used_money));					
					logs_append(g_logs, "TUNET_KEEPALIVE_USED_MONEY", smoney, NULL, 0);

					break; 


				case 0xff://ff 53 65 72 76 69 63 65 20 54 65 72 6d 69 6e 61 74 65 64 21 0d 0a
					tunet_state = TUNET_STATE_ERROR;

					str = string_nappend(str, (CHAR *)(keepalive_socket_buffer->data + 1), keepalive_socket_buffer->len - 1);
					logs_append(g_logs, "TUNET_KEEPALIVE_ERROR", str->str, NULL, 0);
					str = string_free(str);
			
					

					keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer);

					break;
				default:
					tunet_state = TUNET_STATE_ERROR;

					logs_append(g_logs, "TUNET_KEEPALIVE_RECV_UNKNOWN", NULL, NULL, 0);

					//dprintf("%s\n", "意外的标记");

					
					break;
			}
		}
	}
	return OK;
}		
コード例 #3
0
ファイル: kerberos.c プロジェクト: aunali1/exopc
void
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
{
    struct sockaddr_in addr;
    char realm[REALM_SZ];
    char instance[INST_SZ];
    int r;
    int addr_len;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	if (krb_get_lrealm(realm, 1) != KSUCCESS) {
	    Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("No local realm\r\n");
	    return;
	}
	memmove(auth.dat, data, auth.length = cnt);
	if (auth_debug_mode) {
	    printf("Got %d bytes of authentication data\r\n", cnt);
	    printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	    printd(auth.dat, auth.length);
	    printf("\r\n");
	}
	k_getsockinst(0, instance, sizeof(instance));
	addr_len = sizeof(addr);
	if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
	    if(auth_debug_mode)
		printf("getpeername failed\r\n");
	    Data(ap, KRB_REJECT, "getpeername failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	r = krb_rd_req(&auth, KRB_SERVICE_NAME,
		       instance, addr.sin_addr.s_addr, &adat, "");
	if (r) {
	    if (auth_debug_mode)
		printf("Kerberos failed him as %s\r\n", name);
	    Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	/* save the session key */
	memmove(session_key, adat.session, sizeof(adat.session));
	krb_kntoln(&adat, name);

	if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
	    char ts[MAXPATHLEN];
	    struct passwd *pw = getpwnam(UserNameRequested);

	    if(pw){
		snprintf(ts, sizeof(ts),
			 "%s%u",
			 TKT_ROOT,
			 (unsigned)pw->pw_uid);
		setenv("KRBTKFILE", ts, 1);
	    }
	    Data(ap, KRB_ACCEPT, NULL, 0);
	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      krb_unparse_name_long(adat.pname, 
					    adat.pinst, 
					    adat.prealm), 
		      UserNameRequested ? UserNameRequested : "<nobody>");
	    if (msg == NULL)
		Data(ap, KRB_REJECT, NULL, 0);
	    else {
		Data(ap, KRB_REJECT, (void *)msg, -1);
		free(msg);
	    }
	}
	auth_finished(ap, AUTH_USER);
	break;
	
    case KRB_CHALLENGE:
#ifndef ENCRYPTION
	Data(ap, KRB_RESPONSE, NULL, 0);
#else
	if(!VALIDKEY(session_key)){
	    Data(ap, KRB_RESPONSE, NULL, 0);
	    break;
	}
	des_key_sched(&session_key, sched);
	{
	    des_cblock d_block;
	    int i;
	    Session_Key skey;

	    memmove(d_block, data, sizeof(d_block));

	    /* make a session key for encryption */
	    des_ecb_encrypt(&d_block, &session_key, sched, 1);
	    skey.type=SK_DES;
	    skey.length=8;
	    skey.data=session_key;
	    encrypt_session_key(&skey, 1);

	    /* decrypt challenge, add one and encrypt it */
	    des_ecb_encrypt(&d_block, &challenge, sched, 0);
	    for (i = 7; i >= 0; i--)
		if(++challenge[i] != 0)
		    break;
	    des_ecb_encrypt(&challenge, &challenge, sched, 1);
	    Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
	}
#endif
	break;

    case KRB_FORWARD:
	{
	    des_key_schedule ks;
	    unsigned char netcred[sizeof(CREDENTIALS)];
	    CREDENTIALS cred;
	    int ret;
	    if(cnt > sizeof(cred))
		abort();

	    des_set_key(&session_key, ks);
	    des_pcbc_encrypt((void*)data, (void*)netcred, cnt, 
			     ks, &session_key, DES_DECRYPT);
	    unpack_cred(netcred, cnt, &cred);
	    {
		if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||
		   strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||
		   cred.lifetime < 0 || cred.lifetime > 255 ||
		   cred.kvno < 0 || cred.kvno > 255 ||
		   cred.issue_date < 0 || 
		   cred.issue_date > time(0) + CLOCK_SKEW ||
		   strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||
		   strncmp(cred.pinst, adat.pinst, sizeof(cred.pname))){
		    Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);
		}else{
		    if((ret = tf_setup(&cred,
				       cred.pname,
				       cred.pinst)) == KSUCCESS){
		        struct passwd *pw = getpwnam(UserNameRequested);

			if (pw)
			  chown(tkt_string(), pw->pw_uid, pw->pw_gid);
			Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
		    } else{
			Data(ap, KRB_FORWARD_REJECT, 
			     krb_get_err_text(ret), -1);
		    }
		}
	    }
	    memset(data, 0, cnt);
	    memset(ks, 0, sizeof(ks));
	    memset(&cred, 0, sizeof(cred));
	}
	
	break;

    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
コード例 #4
0
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	struct servent *sp;
	struct sgttyb ttyb;
	long omask;
	int argoff, ch, dflag, Dflag, one, uid;
	char *host, *localname, *p, *user, term[1024];
#ifdef KERBEROS
	char *k;
#endif
	struct sockaddr_storage ss;
	int sslen;

	argoff = dflag = Dflag = 0;
	one = 1;
	host = localname = user = NULL;

	if ((p = strrchr(argv[0], '/')))
		++p;
	else
		p = argv[0];

	if (strcmp(p, "rlogin"))
		host = p;

	/* handle "rlogin host flags" */
	if (!host && argc > 2 && argv[1][0] != '-') {
		host = argv[1];
		argoff = 1;
	}

#ifdef KERBEROS
#define	OPTIONS	"468DEKLde:i:k:l:x"
#else
#define	OPTIONS	"468DEKLde:i:l:"
#endif
	while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
		switch(ch) {
		case '4':
			family = PF_INET;
			break;

		case '6':
			family = PF_INET6;
			break;

		case '8':
			eight = 1;
			break;
		case 'D':
			Dflag = 1;
			break;
		case 'E':
			noescape = 1;
			break;
		case 'K':
#ifdef KERBEROS
			use_kerberos = 0;
#endif
			break;
		case 'L':
			litout = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'e':
			noescape = 0;
			escapechar = getescape(optarg);
			break;
		case 'i':
			if (getuid() != 0)
				errx(1, "-i user: permission denied");
			localname = optarg;
			break;
#ifdef KERBEROS
		case 'k':
			dest_realm = dst_realm_buf;
			(void)strncpy(dest_realm, optarg, REALM_SZ);
			break;
#endif
		case 'l':
			user = optarg;
			break;
#ifdef CRYPT
#ifdef KERBEROS
		case 'x':
			doencrypt = 1;
			break;
#endif
#endif
		case '?':
		default:
			usage();
		}
	optind += argoff;

	/* if haven't gotten a host yet, do so */
	if (!host && !(host = argv[optind++]))
		usage();

	if (argv[optind])
		usage();

	if (!(pw = getpwuid(uid = getuid())))
		errx(1, "unknown user id");
	if (!user)
		user = pw->pw_name;
	if (!localname)
		localname = pw->pw_name;

	sp = NULL;
#ifdef KERBEROS
	k = auth_getval("auth_list");
	if (k && !strstr(k, "kerberos"))
	    use_kerberos = 0;
	if (use_kerberos) {
		sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp");
		if (sp == NULL) {
			use_kerberos = 0;
			warn("can't get entry for %s/tcp service",
			    doencrypt ? "eklogin" : "klogin");
		}
	}
#endif
	if (sp == NULL)
		sp = getservbyname("login", "tcp");
	if (sp == NULL)
		errx(1, "login/tcp: unknown service");

#define	MAX_TERM_LENGTH	(sizeof(term) - 1 - MAX_SPEED_LENGTH - 1)

	(void)strncpy(term, (p = getenv("TERM")) ? p : "network",
		      MAX_TERM_LENGTH);
	term[MAX_TERM_LENGTH] = '\0';
	if (ioctl(0, TIOCGETP, &ttyb) == 0) {
		(void)strcat(term, "/");
		(void)strcat(term, speeds[(int)ttyb.sg_ospeed]);
	}

	(void)get_window_size(0, &winsize);

	(void)signal(SIGPIPE, lostpeer);
	/* will use SIGUSR1 for window size hack, so hold it off */
	omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
	/*
	 * We set SIGURG and SIGUSR1 below so that an
	 * incoming signal will be held pending rather than being
	 * discarded. Note that these routines will be ready to get
	 * a signal by the time that they are unblocked below.
	 */
	(void)signal(SIGURG, copytochild);
	(void)signal(SIGUSR1, writeroob);

#ifdef KERBEROS
	if (use_kerberos) {
		setuid(getuid());
		rem = KSUCCESS;
		errno = 0;
		if (dest_realm == NULL)
			dest_realm = krb_realmofhost(host);

#ifdef CRYPT
		if (doencrypt) {
			rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
			    dest_realm, &cred, schedule);
			des_set_key(&cred.session, schedule);
		} else
#endif /* CRYPT */
			rem = krcmd(&host, sp->s_port, user, term, 0,
			    dest_realm);
		if (rem < 0) {
			int i;
			char **newargv;

			sp = getservbyname("login", "tcp");
			if (sp == NULL)
				errx(1, "unknown service login/tcp");
			if (errno == ECONNREFUSED)
				warn("remote host doesn't support Kerberos");
			if (errno == ENOENT)
				warn("can't provide Kerberos auth data");
			newargv = malloc((argc + 2) * sizeof(*newargv));
			if (newargv == NULL)
				err(1, "malloc");
			newargv[0] = argv[0];
			newargv[1] = "-K";
			for(i = 1; i < argc; ++i)
				newargv[i + 1] = argv[i];
			newargv[argc + 1] = NULL;
			execv(_PATH_RLOGIN, newargv);
		}
	} else {
#ifdef CRYPT
		if (doencrypt)
			errx(1, "the -x flag requires Kerberos authentication");
#endif /* CRYPT */
		rem = rcmd_af(&host, sp->s_port, localname, user, term, 0,
			      family);
	}
#else
	rem = rcmd_af(&host, sp->s_port, localname, user, term, 0, family);
#endif /* KERBEROS */

	if (rem < 0)
		exit(1);

	if (dflag &&
	    setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0)
		warn("setsockopt");
	if (Dflag &&
	    setsockopt(rem, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
		warn("setsockopt NODELAY (ignored)");

	sslen = sizeof(ss);
	one = IPTOS_LOWDELAY;
	if (getsockname(rem, (struct sockaddr *)&ss, &sslen) == 0 &&
	    ss.ss_family == AF_INET) {
		if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one,
			       sizeof(int)) < 0)
			warn("setsockopt TOS (ignored)");
	} else
		if (ss.ss_family == AF_INET)
			warn("setsockopt getsockname failed");

	(void)setuid(uid);
	doit(omask);
	/*NOTREACHED*/
}
コード例 #5
0
ファイル: cfdecrypt.c プロジェクト: disccomp/cfdecrypt
int main(int argc, char *argv[])
{
	FILE *infile, *outfile;

	char *header = "Allaire Cold Fusion Template\012Header Size: ";
	char buffer[54];
	int headsize, outlen;
	int skip_header;
	int len, i;

	char *keystr = "Error: cannot open template file--\"%s\". Please, try again!\012\012";
	des_cblock key;
	des_cblock input; 
	des_cblock output;
	des_key_schedule schedule;

	switch (argc)
	{
	case 2:
		outfile = stdout;
		break;

	case 3:
		if (!(outfile = fopen(argv[2], "wb")))
		{
			fprintf(stderr, "Error opening output file %s\n", argv[2]);
			return 1;
		}
		break;

	default:
		fprintf(stderr, "Usage: cfdecrypt <encrypted template> [output file]\n");
		return 1;
	}

	if (!(infile = fopen(argv[1], "rb")))
	{
		fprintf(stderr, "Error opening input file %s\n", argv[1]);
		return 1;
	}

	if ((fread(buffer, 1, 54, infile) < 54) || (memcmp(buffer, header, 42)))
	{
		fprintf(stderr, "File is not an encrypted template\n");
		return 1;
	}

	if (!memcmp(&buffer[42], "New Version", 11))
	{
		headsize = 69;
		skip_header = 1;
	}
	else
	{
		headsize = atoi(&buffer[42]);
		skip_header = 0;
	}

	if ((headsize < 54) || (fseek(infile, headsize, SEEK_SET) < 0))
	{
		fprintf(stderr, "Error in file format\n");
		return 1;
	}

	des_string_to_key(keystr, &key);
	des_set_key(&key, schedule);
	outlen = 0;

	while ((len = fread(input, 1, 8, infile)) == 8)
	{
		des_ecb_encrypt(&input, &output, schedule, 0);
		outlen += 8;
		i = 0;

		if (skip_header)
		{
			while (i < 8)
			{
				if (output[i++] == 0x1A)
				{
					skip_header = 0;
					break;
				}
			}
		}

		fwrite(output + i, 1, 8 - i, outfile);
	}

	for (i = 0; i < len; i++)
	{
		output[i] = input[i] ^ (outlen + i);
	}

	fwrite(output, 1, len, outfile);

	fclose(outfile);
	fclose(infile);
	return 0;
}
コード例 #6
0
ファイル: cipher.c プロジェクト: frankmorgner/gnutls
static int
wrap_nettle_cipher_setkey (void *_ctx, const void *key, size_t keysize)
{
  struct nettle_cipher_ctx *ctx = _ctx;
  uint8_t des_key[DES3_KEY_SIZE];

  switch (ctx->algo)
    {
    case GNUTLS_CIPHER_AES_128_GCM:
    case GNUTLS_CIPHER_AES_256_GCM:
      gcm_aes_set_key(&ctx->ctx.aes_gcm, keysize, key);
      break;
    case GNUTLS_CIPHER_AES_128_CBC:
    case GNUTLS_CIPHER_AES_192_CBC:
    case GNUTLS_CIPHER_AES_256_CBC:
      if (ctx->enc)
        aes_set_encrypt_key (ctx->ctx_ptr, keysize, key);
      else
        aes_set_decrypt_key (ctx->ctx_ptr, keysize, key);
      break;
    case GNUTLS_CIPHER_CAMELLIA_128_CBC:
    case GNUTLS_CIPHER_CAMELLIA_192_CBC:
    case GNUTLS_CIPHER_CAMELLIA_256_CBC:
      if (ctx->enc)
        camellia_set_encrypt_key (ctx->ctx_ptr, keysize, key);
      else
        camellia_set_decrypt_key (ctx->ctx_ptr, keysize, key);
      break;
    case GNUTLS_CIPHER_3DES_CBC:
      if (keysize != DES3_KEY_SIZE)
        {
          gnutls_assert ();
          return GNUTLS_E_INTERNAL_ERROR;
        }

      des_fix_parity (keysize, des_key, key);

      /* this fails on weak keys */
      if (des3_set_key (ctx->ctx_ptr, des_key) != 1)
        {
          gnutls_assert ();
          return GNUTLS_E_INTERNAL_ERROR;
        }
      break;
    case GNUTLS_CIPHER_DES_CBC:
      if (keysize != DES_KEY_SIZE)
        {
          gnutls_assert ();
          return GNUTLS_E_INTERNAL_ERROR;
        }

      des_fix_parity (keysize, des_key, key);

      if (des_set_key (ctx->ctx_ptr, des_key) != 1)
        {
          gnutls_assert ();
          return GNUTLS_E_INTERNAL_ERROR;
        }
      break;
    case GNUTLS_CIPHER_ARCFOUR_128:
    case GNUTLS_CIPHER_ARCFOUR_40:
      arcfour_set_key (ctx->ctx_ptr, keysize, key);
      break;
    case GNUTLS_CIPHER_SALSA20_256:
    case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
      salsa20_set_key (ctx->ctx_ptr, keysize, key);
      break;
    case GNUTLS_CIPHER_RC2_40_CBC:
      arctwo_set_key (ctx->ctx_ptr, keysize, key);
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  return 0;
}
コード例 #7
0
ファイル: cipher.c プロジェクト: long5313828/ythtbbs
void cipher_set_key(CipherContext * context, int cipher, const unsigned char *key, int keylen, int for_encryption)
{
    unsigned char padded[32];

    /* Clear the context to remove any traces of old keys. */
    memset(context, 0, sizeof(*context));

    /* Set cipher type. */
    context->type = cipher;

    /* Get 32 bytes of key data.  Pad if necessary.  (So that code below does
       not need to worry about key size). */
    memset(padded, 0, sizeof(padded));
    memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));

    /* Initialize the initialization vector. */
    switch (cipher) {
    case SSH_CIPHER_NONE:
        break;

#ifdef WITH_IDEA
    case SSH_CIPHER_IDEA:
        if (keylen < 16)
            error("Key length %d is insufficient for IDEA.", keylen);
        idea_set_key(&context->u.idea.key, padded);
        memset(context->u.idea.iv, 0, sizeof(context->u.idea.iv));
        break;
#endif                          /* WITH_IDEA */

#ifdef WITH_DES
    case SSH_CIPHER_DES:
        /* Note: the least significant bit of each byte of key is parity, 
           and must be ignored by the implementation.  8 bytes of key are
           used. */
        if (keylen < 8)
            error("Key length %d is insufficient for DES.", keylen);
        des_set_key(padded, &context->u.des.key);
        memset(context->u.des.iv, 0, sizeof(context->u.des.iv));
        break;
#endif                          /* WITH_DES */

    case SSH_CIPHER_3DES:
        /* Note: the least significant bit of each byte of key is parity, 
           and must be ignored by the implementation.  16 bytes of key are
           used (first and last keys are the same). */
        if (keylen < 16)
            error("Key length %d is insufficient for 3DES.", keylen);
        des_set_key(padded, &context->u.des3.key1);
        des_set_key(padded + 8, &context->u.des3.key2);
        if (keylen <= 16)
            des_set_key(padded, &context->u.des3.key3);
        else
            des_set_key(padded + 16, &context->u.des3.key3);
        memset(context->u.des3.iv1, 0, sizeof(context->u.des3.iv1));
        memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
        memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
        break;

#ifdef WITH_ARCFOUR
    case SSH_CIPHER_ARCFOUR:
        arcfour_init(&context->u.arcfour, key, keylen);
        break;
#endif                          /* WITH_ARCFOUR */

#ifdef WITH_BLOWFISH
    case SSH_CIPHER_BLOWFISH:
        if (keylen < 8)
            error("Key length %d is insufficient for Blowfish", keylen);
        blowfish_set_key(&context->u.blowfish, key, keylen, for_encryption);
        break;
#endif                          /* WITH_BLOWFISH */
    default:
        fatal("cipher_set_key: unknown cipher: %d", cipher);
    }
    memset(padded, 0, sizeof(padded));
}