示例#1
0
/*
 * Move a successfully used entry to level2. If already at level2,
 * move it to the end of the LRU queue..
 */
static inline void move_to_level2(struct dir_cache_entry * old_de, struct hash_list * hash)
{
	struct dir_cache_entry * de;

	if (old_de->lru_head == &level2_head) {
		update_lru(old_de);
		return;
	}	
	de = level2_head;
	level2_head = de->next_lru;
	remove_hash(de);
	COPYDATA(old_de, de);
	add_hash(de, hash);
}
示例#2
0
/*
 * Apply a symmetric encryption/decryption algorithm.
 */
static int
swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
    int outtype)
{
	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
	unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
	struct enc_xform *exf;
	int i, k, j, blks;

	exf = sw->sw_exf;
	blks = exf->blocksize;

	/* Check for non-padded data */
	if (crd->crd_len % blks)
		return EINVAL;

	/* Initialize the IV */
	if (crd->crd_flags & CRD_F_ENCRYPT) {
		/* IV explicitly provided ? */
		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crd->crd_iv, iv, blks);
		else {
			/* Get random IV */
			for (i = 0;
			    i + sizeof (u_int32_t) < EALG_MAX_BLOCK_LEN;
			    i += sizeof (u_int32_t)) {
				u_int32_t temp = arc4random();

				bcopy(&temp, iv + i, sizeof(u_int32_t));
			}
			/*
			 * What if the block size is not a multiple
			 * of sizeof (u_int32_t), which is the size of
			 * what arc4random() returns ?
			 */
			if (EALG_MAX_BLOCK_LEN % sizeof (u_int32_t) != 0) {
				u_int32_t temp = arc4random();

				bcopy (&temp, iv + i,
				    EALG_MAX_BLOCK_LEN - i);
			}
		}

		/* Do we need to write the IV */
		if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
			COPYBACK(outtype, buf, crd->crd_inject, blks, iv);
		}

	} else {	/* Decryption */
			/* IV explicitly provided ? */
		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crd->crd_iv, iv, blks);
		else {
			/* Get IV off buf */
			COPYDATA(outtype, buf, crd->crd_inject, blks, iv);
		}
	}

	ivp = iv;

	if (outtype == CRYPTO_BUF_CONTIG) {
		if (crd->crd_flags & CRD_F_ENCRYPT) {
			for (i = crd->crd_skip;
			    i < crd->crd_skip + crd->crd_len; i += blks) {
				/* XOR with the IV/previous block, as appropriate. */
				if (i == crd->crd_skip)
					for (k = 0; k < blks; k++)
						buf[i + k] ^= ivp[k];
				else
					for (k = 0; k < blks; k++)
						buf[i + k] ^= buf[i + k - blks];
				exf->encrypt(sw->sw_kschedule, buf + i);
			}
		} else {		/* Decrypt */
			/*
			 * Start at the end, so we don't need to keep the encrypted
			 * block as the IV for the next block.
			 */
			for (i = crd->crd_skip + crd->crd_len - blks;
			    i >= crd->crd_skip; i -= blks) {
				exf->decrypt(sw->sw_kschedule, buf + i);

				/* XOR with the IV/previous block, as appropriate */
				if (i == crd->crd_skip)
					for (k = 0; k < blks; k++)
						buf[i + k] ^= ivp[k];
				else
					for (k = 0; k < blks; k++)
						buf[i + k] ^= buf[i + k - blks];
			}
		}

		return 0;
	} else if (outtype == CRYPTO_BUF_MBUF) {
		struct mbuf *m = (struct mbuf *) buf;

		/* Find beginning of data */
		m = m_getptr(m, crd->crd_skip, &k);
		if (m == NULL)
			return EINVAL;

		i = crd->crd_len;

		while (i > 0) {
			/*
			 * If there's insufficient data at the end of
			 * an mbuf, we have to do some copying.
			 */
			if (m->m_len < k + blks && m->m_len != k) {
				m_copydata(m, k, blks, blk);

				/* Actual encryption/decryption */
				if (crd->crd_flags & CRD_F_ENCRYPT) {
					/* XOR with previous block */
					for (j = 0; j < blks; j++)
						blk[j] ^= ivp[j];

					exf->encrypt(sw->sw_kschedule, blk);

					/*
					 * Keep encrypted block for XOR'ing
					 * with next block
					 */
					bcopy(blk, iv, blks);
					ivp = iv;
				} else {	/* decrypt */
					/*	
					 * Keep encrypted block for XOR'ing
					 * with next block
					 */
					if (ivp == iv)
						bcopy(blk, piv, blks);
					else
						bcopy(blk, iv, blks);

					exf->decrypt(sw->sw_kschedule, blk);

					/* XOR with previous block */
					for (j = 0; j < blks; j++)
						blk[j] ^= ivp[j];

					if (ivp == iv)
						bcopy(piv, iv, blks);
					else
						ivp = iv;
				}

				/* Copy back decrypted block */
				m_copyback(m, k, blks, blk);

				/* Advance pointer */
				m = m_getptr(m, k + blks, &k);
				if (m == NULL)
					return EINVAL;

				i -= blks;

				/* Could be done... */
				if (i == 0)
					break;
			}

			/* Skip possibly empty mbufs */
			if (k == m->m_len) {
				for (m = m->m_next; m && m->m_len == 0;
				    m = m->m_next)
					;
				k = 0;
			}

			/* Sanity check */
			if (m == NULL)
				return EINVAL;

			/*
			 * Warning: idat may point to garbage here, but
			 * we only use it in the while() loop, only if
			 * there are indeed enough data.
			 */
			idat = mtod(m, unsigned char *) + k;

	   		while (m->m_len >= k + blks && i > 0) {
				if (crd->crd_flags & CRD_F_ENCRYPT) {
					/* XOR with previous block/IV */
					for (j = 0; j < blks; j++)
						idat[j] ^= ivp[j];

					exf->encrypt(sw->sw_kschedule, idat);
					ivp = idat;
				} else {	/* decrypt */
					/*
					 * Keep encrypted block to be used
					 * in next block's processing.
					 */
					if (ivp == iv)
						bcopy(idat, piv, blks);
					else
						bcopy(idat, iv, blks);

					exf->decrypt(sw->sw_kschedule, idat);

					/* XOR with previous block/IV */
					for (j = 0; j < blks; j++)
						idat[j] ^= ivp[j];

					if (ivp == iv)
						bcopy(piv, iv, blks);
					else
						ivp = iv;
				}

				idat += blks;
				k += blks;
				i -= blks;
			}
		}

		return 0; /* Done with mbuf encryption/decryption */
	} else if (outtype == CRYPTO_BUF_IOV) {
示例#3
0
/*
 * Try and build up the next PPTP message in the TCP stream and if we can
 * build it up completely (fits in our buffer) then pass it off to the message
 * parsing function.
 */
int
ippr_pptp_nextmessage(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp, int rev)
{
	static const char *funcname = "ippr_pptp_nextmessage";
	pptp_side_t *pptps;
	u_32_t start, end;
	pptp_hdr_t *hdr;
	tcphdr_t *tcp;
	int dlen, off;
	u_short len;
	char *msg;

	tcp = fin->fin_dp;
	dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
	start = ntohl(tcp->th_seq);
	pptps = &pptp->pptp_side[rev];
	off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
	      fin->fin_ipoff;

	if (dlen <= 0)
		return 0;
	/*
	 * If the complete data packet is before what we expect to see
	 * "next", just ignore it as the chances are we've already seen it.
	 * The next if statement following this one really just causes packets
	 * ahead of what we've seen to be dropped, implying that something in
	 * the middle went missing and we want to see that first.
	 */
	end = start + dlen;
	if (pptps->pptps_next > end && pptps->pptps_next > start)
		return 0;

	if (pptps->pptps_next != start) {
		if (ippr_pptp_debug > 5)
			printf("%s: next (%x) != start (%x)\n", funcname,
				pptps->pptps_next, start);
		return -1;
	}

	msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);

	while (dlen > 0) {
		off += pptps->pptps_bytes;
		if (pptps->pptps_gothdr == 0) {
			/*
			 * PPTP has an 8 byte header that inclues the cookie.
			 * The start of every message should include one and
			 * it should match 1a2b3c4d.  Byte order is ignored,
			 * deliberately, when printing out the error.
			 */
			len = MIN(8 - pptps->pptps_bytes, dlen);
			COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
			pptps->pptps_bytes += len;
			pptps->pptps_wptr += len;
			hdr = (pptp_hdr_t *)pptps->pptps_buffer;
			if (pptps->pptps_bytes == 8) {
				pptps->pptps_next += 8;
				if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
					if (ippr_pptp_debug > 1)
						printf("%s: bad cookie (%x)\n",
						       funcname,
						       hdr->pptph_cookie);
					return -1;
				}
			}
			dlen -= len;
			msg += len;
			off += len;

			pptps->pptps_gothdr = 1;
			len = ntohs(hdr->pptph_len);
			pptps->pptps_len = len;
			pptps->pptps_nexthdr += len;

			/*
			 * If a message is too big for the buffer, just set
			 * the fields for the next message to come along.
			 * The messages defined in RFC 2637 will not exceed
			 * 512 bytes (in total length) so this is likely a
			 * bad data packet, anyway.
			 */
			if (len > sizeof(pptps->pptps_buffer)) {
				if (ippr_pptp_debug > 3)
					printf("%s: message too big (%d)\n",
					       funcname, len);
				pptps->pptps_next = pptps->pptps_nexthdr;
				pptps->pptps_wptr = pptps->pptps_buffer;
				pptps->pptps_gothdr = 0;
				pptps->pptps_bytes = 0;
				pptps->pptps_len = 0;
				break;
			}
		}

		len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
		COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
		pptps->pptps_bytes += len;
		pptps->pptps_wptr += len;
		pptps->pptps_next += len;

		if (pptps->pptps_len > pptps->pptps_bytes)
			break;

		ippr_pptp_message(fin, nat, pptp, pptps);
		pptps->pptps_wptr = pptps->pptps_buffer;
		pptps->pptps_gothdr = 0;
		pptps->pptps_bytes = 0;
		pptps->pptps_len = 0;

		start += len;
		msg += len;
		dlen -= len;
	}

	return 0;
}
示例#4
0
/*
 * Apply a symmetric encryption/decryption algorithm.
 */
int
swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
    int outtype)
{
	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
	unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
	struct enc_xform *exf;
	int i, k, j, blks, ind, count, ivlen;
	struct mbuf *m = NULL;
	struct uio *uio = NULL;

	exf = sw->sw_exf;
	blks = exf->blocksize;
	ivlen = exf->ivsize;

	/* Check for non-padded data */
	if (crd->crd_len % blks)
		return EINVAL;

	if (outtype == CRYPTO_BUF_MBUF)
		m = (struct mbuf *) buf;
	else
		uio = (struct uio *) buf;

	/* Initialize the IV */
	if (crd->crd_flags & CRD_F_ENCRYPT) {
		/* IV explicitly provided ? */
		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crd->crd_iv, iv, ivlen);
		else
			arc4random_bytes(iv, ivlen);

		/* Do we need to write the IV */
		if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
			COPYBACK(outtype, buf, crd->crd_inject, ivlen, iv);
		}

	} else {	/* Decryption */
			/* IV explicitly provided ? */
		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crd->crd_iv, iv, ivlen);
		else {
			/* Get IV off buf */
			COPYDATA(outtype, buf, crd->crd_inject, ivlen, iv);
		}
	}

	ivp = iv;

	if (exf->reinit)
		exf->reinit(sw->sw_kschedule, iv);

	if (outtype == CRYPTO_BUF_MBUF) {
		/* Find beginning of data */
		m = m_getptr(m, crd->crd_skip, &k);
		if (m == NULL)
			return EINVAL;

		i = crd->crd_len;

		while (i > 0) {
			/*
			 * If there's insufficient data at the end of
			 * an mbuf, we have to do some copying.
			 */
			if (m->m_len < k + blks && m->m_len != k) {
				m_copydata(m, k, blks, blk);

				/* Actual encryption/decryption */
				if (exf->reinit) {
					exf->encrypt(sw->sw_kschedule, blk);
				} else if (crd->crd_flags & CRD_F_ENCRYPT) {
					/* XOR with previous block */
					for (j = 0; j < blks; j++)
						blk[j] ^= ivp[j];

					exf->encrypt(sw->sw_kschedule, blk);

					/*
					 * Keep encrypted block for XOR'ing
					 * with next block
					 */
					bcopy(blk, iv, blks);
					ivp = iv;
				} else {	/* decrypt */
					/*
					 * Keep encrypted block for XOR'ing
					 * with next block
					 */
					if (ivp == iv)
						bcopy(blk, piv, blks);
					else
						bcopy(blk, iv, blks);

					exf->decrypt(sw->sw_kschedule, blk);

					/* XOR with previous block */
					for (j = 0; j < blks; j++)
						blk[j] ^= ivp[j];

					if (ivp == iv)
						bcopy(piv, iv, blks);
					else
						ivp = iv;
				}

				/* Copy back decrypted block */
				m_copyback(m, k, blks, blk);

				/* Advance pointer */
				m = m_getptr(m, k + blks, &k);
				if (m == NULL)
					return EINVAL;

				i -= blks;

				/* Could be done... */
				if (i == 0)
					break;
			}

			/* Skip possibly empty mbufs */
			if (k == m->m_len) {
				for (m = m->m_next; m && m->m_len == 0;
				    m = m->m_next)
					;
				k = 0;
			}

			/* Sanity check */
			if (m == NULL)
				return EINVAL;

			/*
			 * Warning: idat may point to garbage here, but
			 * we only use it in the while() loop, only if
			 * there are indeed enough data.
			 */
			idat = mtod(m, unsigned char *) + k;

			while (m->m_len >= k + blks && i > 0) {
				if (exf->reinit) {
					exf->encrypt(sw->sw_kschedule, idat);
				} else if (crd->crd_flags & CRD_F_ENCRYPT) {
					/* XOR with previous block/IV */
					for (j = 0; j < blks; j++)
						idat[j] ^= ivp[j];

					exf->encrypt(sw->sw_kschedule, idat);
					ivp = idat;
				} else {	/* decrypt */
					/*
					 * Keep encrypted block to be used
					 * in next block's processing.
					 */
					if (ivp == iv)
						bcopy(idat, piv, blks);
					else
						bcopy(idat, iv, blks);

					exf->decrypt(sw->sw_kschedule, idat);

					/* XOR with previous block/IV */
					for (j = 0; j < blks; j++)
						idat[j] ^= ivp[j];

					if (ivp == iv)
						bcopy(piv, iv, blks);
					else
						ivp = iv;
				}

				idat += blks;
				k += blks;
				i -= blks;
			}
		}
	} else {