Crypt-Bear

 view release on metacpan or  search on metacpan

src/ssl/ssl_engine.c  view on Meta::CPAN

		 * in the server-specific code, not here.
		 */
		rc->record_type_in = rc->ibuf[0];
		version = br_dec16be(rc->ibuf + 1);
		if ((version >> 8) != 3) {
			br_ssl_engine_fail(rc, BR_ERR_UNSUPPORTED_VERSION);
			return;
		}

		/*
		 * We ensure that successive records have the same
		 * version. The handshake code must check and adjust the
		 * variables when necessary to accommodate the protocol
		 * negotiation details.
		 */
		if (rc->version_in != 0 && rc->version_in != version) {
			br_ssl_engine_fail(rc, BR_ERR_BAD_VERSION);
			return;
		}
		rc->version_in = version;

		/*
		 * Decode record length. We must check that the length
		 * is valid (relatively to the current encryption mode)
		 * and also (if encryption is active) that the record
		 * will fit in our buffer.
		 *
		 * When no encryption is active, we can process records
		 * by chunks, and thus accept any record up to the
		 * maximum allowed plaintext length (16384 bytes).
		 */
		rlen = br_dec16be(rc->ibuf + 3);
		if (rc->incrypt) {
			if (!rc->in.vtable->check_length(
				&rc->in.vtable, rlen))
			{
				br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
				return;
			}
			if (rlen > (rc->ibuf_len - 5)) {
				br_ssl_engine_fail(rc, BR_ERR_TOO_LARGE);
				return;
			}
		} else {
			if (rlen > 16384) {
				br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
				return;
			}
		}

		/*
		 * If the record is completely empty then we must switch
		 * to a new record. Note that, in that case, we
		 * completely ignore the record type, which is fitting
		 * since we received no actual data of that type.
		 *
		 * A completely empty record is technically allowed as
		 * long as encryption/MAC is not active, i.e. before
		 * completion of the first handshake. It it still weird;
		 * it might conceptually be useful as a heartbeat or
		 * keep-alive mechanism while some lengthy operation is
		 * going on, e.g. interaction with a human user.
		 */
		if (rlen == 0) {
			make_ready_in(rc);
		} else {
			rc->ixa = rc->ixb = 5;
			rc->ixc = rlen;
		}
		return;
	}

	/*
	 * If there is no active encryption, then the data can be read
	 * right away. Note that we do not receive bytes from the
	 * transport medium when we still have payload bytes to be
	 * acknowledged.
	 */
	if (!rc->incrypt) {
		rc->ixa = 5;
		return;
	}

	/*
	 * Since encryption is active, we must wait for a full record
	 * before processing it.
	 */
	if (rc->ixc != 0) {
		return;
	}

	/*
	 * We got the full record. Decrypt it.
	 */
	pbuf_len = rc->ixa - 5;
	pbuf = rc->in.vtable->decrypt(&rc->in.vtable,
		rc->record_type_in, rc->version_in, rc->ibuf + 5, &pbuf_len);
	if (pbuf == 0) {
		br_ssl_engine_fail(rc, BR_ERR_BAD_MAC);
		return;
	}
	rc->ixa = (size_t)(pbuf - rc->ibuf);
	rc->ixb = rc->ixa + pbuf_len;

	/*
	 * Decryption may have yielded an empty record, in which case
	 * we get back to "ready" state immediately.
	 */
	if (rc->ixa == rc->ixb) {
		make_ready_in(rc);
	}
}

/* see inner.h */
int
br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc)
{
	switch (rc->iomode) {
	case BR_IO_IN:
	case BR_IO_INOUT:
		return rc->ixc == 0 || rc->ixa < 5;



( run in 1.131 second using v1.01-cache-2.11-cpan-39bf76dae61 )