cop = (struct crypt_op *)data;
cryptof_ioctl(fp, cmd, data, p)	struct file *fp;	u_long cmd;	caddr_t data;	struct proc *p;{	struct cryptoini cria, crie;	struct fcrypt *fcr = (struct fcrypt *)fp->f_data;	struct csession *cse;	struct session_op *sop;	struct crypt_op *cop;	struct enc_xform *txform = NULL;	struct auth_hash *thash = NULL;	u_int64_t sid;	u_int32_t ses;	int error = 0;	switch (cmd) {	case CIOCGSESSION:		sop = (struct session_op *)data;		switch (sop->cipher) {		case 0:			break;		case CRYPTO_DES_CBC:			txform = &enc_xform_des;			break;		case CRYPTO_3DES_CBC:			txform = &enc_xform_3des;			break;		case CRYPTO_BLF_CBC:			txform = &enc_xform_blf;			break;		case CRYPTO_CAST_CBC:			txform = &enc_xform_cast5;			break;		case CRYPTO_SKIPJACK_CBC:			txform = &enc_xform_skipjack;			break;		case CRYPTO_AES_CBC:			txform = &enc_xform_rijndael128;			break;		default:			return (EINVAL);		}		switch (sop->mac) {		case 0:			break;		case CRYPTO_MD5_HMAC:			thash = &auth_hash_hmac_md5_96;			break;		case CRYPTO_SHA1_HMAC:			thash = &auth_hash_hmac_sha1_96;			break;		case CRYPTO_RIPEMD160_HMAC:			thash = &auth_hash_hmac_ripemd_160_96;			break;		default:			return (EINVAL);		}		bzero(&crie, sizeof(crie));		bzero(&cria, sizeof(cria));		if (txform) {			crie.cri_alg = txform->type;			crie.cri_klen = sop->keylen * 8;	/* XXX range check */			MALLOC(crie.cri_key, u_int8_t *,			    crie.cri_klen / 8, M_XDATA, M_WAITOK);			if ((error = copyin(sop->key, crie.cri_key,			    crie.cri_klen / 8)))				goto bail;			if (thash)				crie.cri_next = &cria;		}		if (thash) {			cria.cri_alg = thash->type;			cria.cri_klen = sop->mackeylen * 8;	/* XXX range check */			MALLOC(cria.cri_key, u_int8_t *,			    cria.cri_klen / 8, M_XDATA, M_WAITOK);			if ((error = copyin(sop->mackey, cria.cri_key,			    cria.cri_klen / 8)))				goto bail;		}		error = crypto_newsession(&sid, (txform ? &crie : &cria), 1);bail:		if (error) {			if (crie.cri_key)				FREE(crie.cri_key, M_XDATA);			if (cria.cri_key)				FREE(cria.cri_key, M_XDATA);			return (error);		}		cse = csecreate(fcr, sid, crie.cri_key, cria.cri_key);		sop->ses = cse->ses;		break;	case CIOCFSESSION:		ses = *(u_int32_t *)data;		cse = csefind(fcr, ses);		if (cse == NULL)			return (EINVAL);		error = crypto_freesession(cse->sid);		csedelete(fcr, cse);		csefree(cse);		break;	case CIOCCRYPT:		cse = csefind(fcr, cop->ses);		if (cse == NULL)			return (EINVAL);		error = crypto_op(cse, cop, p);		break;	default:		error = EINVAL;	}	return (error);}