/* * 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); }
/* * 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) {
/* * 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; }
/* * 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 {