Beispiel #1
0
int
ssh_msg_recv(int fd, Buffer *m)
{
	u_char buf[4];
	ssize_t res;
	u_int msg_len;

	debug3("ssh_msg_recv entering");

	res = atomicio(read, fd, buf, sizeof(buf));
	if (res != sizeof(buf)) {
		if (res == 0)
			return -1;
		fatal("ssh_msg_recv: read: header %ld", (long)res);
	}
	msg_len = GET_32BIT(buf);
	if (msg_len > 256 * 1024)
		fatal("ssh_msg_recv: read: bad msg_len %u", msg_len);
	buffer_clear(m);
	buffer_append_space(m, msg_len);
	res = atomicio(read, fd, buffer_ptr(m), msg_len);
	if (res != msg_len)
		fatal("ssh_msg_recv: read: %ld != msg_len", (long)res);
	return 0;
}
Beispiel #2
0
static void answer_msg(void *msgv)
{
  unsigned char *msg = (unsigned char *)msgv;
  unsigned msglen;
  void *reply;
  int replylen;

  msglen = GET_32BIT(msg);
  if (msglen > AGENT_MAX_MSGLEN) {
    reply = pageant_failure_msg(&replylen);
  } else {
    reply = pageant_handle_msg(msg + 4, msglen, &replylen, NULL, NULL);
    if (replylen > AGENT_MAX_MSGLEN) {
      smemclr(reply, replylen);
      sfree(reply);
      reply = pageant_failure_msg(&replylen);
    }
  }

  /*
   * Windows Pageant answers messages in place, by overwriting the
   * input message buffer.
   */
  memcpy(msg, reply, replylen);
  smemclr(reply, replylen);
  sfree(reply);
}
Beispiel #3
0
static int agent_select_result(int fd, int event)
{
    int ret;
    struct agent_connection *conn;

    assert(event == 1);		       /* not selecting for anything but R */

    conn = find234(agent_connections, &fd, agent_connfind);
    if (!conn) {
	uxsel_del(fd);
	return 1;
    }

    ret = read(fd, conn->retbuf+conn->retlen, conn->retsize-conn->retlen);
    if (ret <= 0) {
	if (conn->retbuf != conn->sizebuf) sfree(conn->retbuf);
	conn->retbuf = NULL;
	conn->retlen = 0;
	goto done;
    }
    conn->retlen += ret;
    if (conn->retsize == 4 && conn->retlen == 4) {
	conn->retsize = GET_32BIT(conn->retbuf);
	if (conn->retsize <= 0) {
	    conn->retbuf = NULL;
	    conn->retlen = 0;
	    goto done;
	}
	conn->retsize += 4;
	assert(conn->retbuf == conn->sizebuf);
	conn->retbuf = snewn(conn->retsize, char);
	memcpy(conn->retbuf, conn->sizebuf, 4);
    }
Beispiel #4
0
int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
{
	struct user_desc info;
	struct n_desc_struct *desc;
	int idx;

	if (get_user(idx, &u_info->entry_number))
		return -EFAULT;
	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
		return -EINVAL;

	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;

	memset(&info, 0, sizeof(struct user_desc));
	info.entry_number = idx;
	info.base_addr = GET_BASE(desc);
	info.limit = GET_LIMIT(desc);
	info.seg_32bit = GET_32BIT(desc);
	info.contents = GET_CONTENTS(desc);
	info.read_exec_only = !GET_WRITABLE(desc);
	info.limit_in_pages = GET_LIMIT_PAGES(desc);
	info.seg_not_present = !GET_PRESENT(desc);
	info.useable = GET_USEABLE(desc);
	info.lm = GET_LONGMODE(desc);

	if (copy_to_user(u_info, &info, sizeof(info)))
		return -EFAULT;
	return 0;
}
static void
get_msg(int fd, Buffer *m)
{
	u_int len, msg_len;
	unsigned char buf[4096];

	len = atomicio(read, fd, buf, 4);
	if (len == 0)
		fatal("Connection closed");
	else if (len == -1)
		fatal("Couldn't read packet: %s", strerror(errno));

	msg_len = GET_32BIT(buf);
	if (msg_len > 256 * 1024)
		fatal("Received message too long %u", msg_len);

	while (msg_len) {
		len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf)));
		if (len == 0)
			fatal("Connection closed");
		else if (len == -1)
			fatal("Couldn't read packet: %s", strerror(errno));

		msg_len -= len;
		buffer_append(m, buf, len);
	}
}
static int
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
{
	int l, len;
	char buf[1024];

	/* Get the length of the message, and format it in the buffer. */
	len = buffer_len(request);
	PUT_32BIT(buf, len);

	/* Send the length and then the packet to the agent. */
	if (atomicio(write, auth->fd, buf, 4) != 4 ||
	    atomicio(write, auth->fd, buffer_ptr(request),
	    buffer_len(request)) != buffer_len(request)) {
		error("Error writing to authentication socket.");
		return 0;
	}
	/*
	 * Wait for response from the agent.  First read the length of the
	 * response packet.
	 */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, buf + 4 - len, len);
		if (l == -1 && (errno == EAGAIN || errno == EINTR))
			continue;
		if (l <= 0) {
			error("Error reading response length from authentication socket.");
			return 0;
		}
		len -= l;
	}

	/* Extract the length, and check it for sanity. */
	len = GET_32BIT(buf);
	if (len > 256 * 1024)
		fatal("Authentication response too long: %d", len);

	/* Read the rest of the response in to the buffer. */
	buffer_clear(reply);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		l = read(auth->fd, buf, l);
		if (l == -1 && (errno == EAGAIN || errno == EINTR))
			continue;
		if (l <= 0) {
			error("Error reading response from authentication socket.");
			return 0;
		}
		buffer_append(reply, buf, l);
		len -= l;
	}
	return 1;
}
Beispiel #7
0
int
buffer_get_int_ret(u_int *ret, Buffer *buffer)
{
	u_char buf[4];

	if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
		return (-1);
	*ret = GET_32BIT(buf);
	return (0);
}
Beispiel #8
0
static int
_read_int(struct iovec *iov, int *ival)
{
	iov->iov_len -= 4;
	if (iov->iov_len < 0)
		return (-1);
	*ival = GET_32BIT((u_char *)iov->iov_base);
	iov->iov_base += 4;

	return (0);
}
/*
 * This parses an exported name, extracting the mechanism specific portion
 * to use for ACL checking. It verifies that the name belongs the mechanism
 * originally selected.
 */
static OM_uint32
ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
{
	u_char *tok;
	OM_uint32 offset;
	OM_uint32 oidl;

	tok = ename->value;

	/*
	 * Check that ename is long enough for all of the fixed length
	 * header, and that the initial ID bytes are correct
	 */

	if (ename->length < 6 || memcmp(tok, "\x04\x01", 2) != 0)
		return GSS_S_FAILURE;

	/*
	 * Extract the OID, and check it. Here GSSAPI breaks with tradition
	 * and does use the OID type and length bytes. To confuse things
	 * there are two lengths - the first including these, and the
	 * second without.
	 */

	oidl = GET_16BIT(tok+2); /* length including next two bytes */
	oidl = oidl-2; /* turn it into the _real_ length of the variable OID */

	/*
	 * Check the BER encoding for correct type and length, that the
	 * string is long enough and that the OID matches that in our context
	 */
	if (tok[4] != 0x06 || tok[5] != oidl ||
	    ename->length < oidl+6 ||
	    !ssh_gssapi_check_oid(ctx, tok+6, oidl))
		return GSS_S_FAILURE;

	offset = oidl+6;

	if (ename->length < offset+4)
		return GSS_S_FAILURE;

	name->length = GET_32BIT(tok+offset);
	offset += 4;

	if (ename->length < offset+name->length)
		return GSS_S_FAILURE;

	name->value = xmalloc(name->length+1);
	memcpy(name->value, tok+offset,name->length);
	((char *)name->value)[name->length] = 0;

	return GSS_S_COMPLETE;
}
static int
handle_from_string(char *handle, u_int hlen)
{
	int val;

	if (hlen != sizeof(int32_t))
		return -1;
	val = GET_32BIT(handle);
	if (handle_is_ok(val, HANDLE_FILE) ||
	    handle_is_ok(val, HANDLE_DIR))
		return val;
	return -1;
}
Beispiel #11
0
static void getstring(char **data, int *datalen, char **p, int *length) {
    *p = NULL;
    if (*datalen < 4)
        return;
    *length = GET_32BIT(*data);
    *datalen -= 4;
    *data += 4;
    if (*datalen < *length)
        return;
    *p = *data;
    *data += *length;
    *datalen -= *length;
}
Beispiel #12
0
void mp_unlinearize_msb_first(MP_INT * value, const unsigned char *buf, unsigned int len)
{
    unsigned int i;

    mpz_set_ui(value, 0);
    for (i = 0; i + 4 <= len; i += 4) {
        unsigned long limb = GET_32BIT(buf + i);

        mpz_mul_2exp(value, value, 32);
        mpz_add_ui(value, value, limb);
    }
    for (; i < len; i++) {
        mpz_mul_2exp(value, value, 8);
        mpz_add_ui(value, value, buf[i]);
    }
}
Beispiel #13
0
void
mm_request_receive(int socket, Buffer *m)
{
	u_char buf[4];
	u_int msg_len;
	ssize_t res;

	debug3("%s entering", __func__);

	res = atomicio(read, socket, buf, sizeof(buf));
	if (res != sizeof(buf)) {
		if (res == 0)
			fatal_cleanup();
		fatal("%s: read: %ld", __func__, (long)res);
	}
	msg_len = GET_32BIT(buf);
	if (msg_len > 256 * 1024)
		fatal("%s: read: bad msg_len %d", __func__, msg_len);
	buffer_clear(m);
	buffer_append_space(m, msg_len);
	res = atomicio(read, socket, buffer_ptr(m), msg_len);
	if (res != msg_len)
		fatal("%s: read: %ld != msg_len", __func__, (long)res);
}
Beispiel #14
0
static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
			   char **commentptr, char *passphrase,
			   const char **error)
{
    unsigned char buf[16384];
    unsigned char keybuf[16];
    int len;
    int i, j, ciphertype;
    int ret = 0;
    struct MD5Context md5c;
    char *comment;

    *error = NULL;

    /* Slurp the whole file (minus the header) into a buffer. */
    len = fread(buf, 1, sizeof(buf), fp);
    fclose(fp);
    if (len < 0 || len == sizeof(buf)) {
	*error = "error reading file";
	goto end;		       /* file too big or not read */
    }

    i = 0;
    *error = "file format error";

    /*
     * A zero byte. (The signature includes a terminating NUL.)
     */
    if (len - i < 1 || buf[i] != 0)
	goto end;
    i++;

    /* One byte giving encryption type, and one reserved uint32. */
    if (len - i < 1)
	goto end;
    ciphertype = buf[i];
    if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
	goto end;
    i++;
    if (len - i < 4)
	goto end;		       /* reserved field not present */
    if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0
	|| buf[i + 3] != 0) goto end;  /* reserved field nonzero, panic! */
    i += 4;

    /* Now the serious stuff. An ordinary SSH-1 public key. */
    j = makekey(buf + i, len - i, key, NULL, 1);
    if (j < 0)
	goto end;		       /* overran */
    i += j;

    /* Next, the comment field. */
    j = toint(GET_32BIT(buf + i));
    i += 4;
    if (j < 0 || len - i < j)
	goto end;
    comment = snewn(j + 1, char);
    if (comment) {
	memcpy(comment, buf + i, j);
	comment[j] = '\0';
    }
    i += j;
    if (commentptr)
	*commentptr = dupstr(comment);
    if (key)
	key->comment = comment;
    else
	sfree(comment);

    if (pub_only) {
	ret = 1;
	goto end;
    }

    if (!key) {
	ret = ciphertype != 0;
	*error = NULL;
	goto end;
    }

    /*
     * Decrypt remainder of buffer.
     */
    if (ciphertype) {
	MD5Init(&md5c);
	MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
	MD5Final(keybuf, &md5c);
	des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
	smemclr(keybuf, sizeof(keybuf));	/* burn the evidence */
    }

    /*
     * We are now in the secret part of the key. The first four
     * bytes should be of the form a, b, a, b.
     */
    if (len - i < 4)
	goto end;
    if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
	*error = "wrong passphrase";
	ret = -1;
	goto end;
    }
    i += 4;

    /*
     * After that, we have one further bignum which is our
     * decryption exponent, and then the three auxiliary values
     * (iqmp, q, p).
     */
    j = makeprivate(buf + i, len - i, key);
    if (j < 0) goto end;
    i += j;
    j = ssh1_read_bignum(buf + i, len - i, &key->iqmp);
    if (j < 0) goto end;
    i += j;
    j = ssh1_read_bignum(buf + i, len - i, &key->q);
    if (j < 0) goto end;
    i += j;
    j = ssh1_read_bignum(buf + i, len - i, &key->p);
    if (j < 0) goto end;
    i += j;

    if (!rsa_verify(key)) {
	*error = "rsa_verify failed";
	freersakey(key);
	ret = 0;
    } else
	ret = 1;

  end:
    smemclr(buf, sizeof(buf));       /* burn the evidence */
    return ret;
}
static void
process(void)
{
	u_int msg_len;
	u_int buf_len;
	u_int consumed;
	u_int type;
	u_char *cp;

	buf_len = buffer_len(&iqueue);
	if (buf_len < 5)
		return;		/* Incomplete message. */
	cp = buffer_ptr(&iqueue);
	msg_len = GET_32BIT(cp);
	if (msg_len > 256 * 1024) {
		error("bad message ");
		exit(11);
	}
	if (buf_len < msg_len + 4)
		return;
	buffer_consume(&iqueue, 4);
	buf_len -= 4;
	type = buffer_get_char(&iqueue);
	switch (type) {
	case SSH2_FXP_INIT:
		process_init();
		break;
	case SSH2_FXP_OPEN:
		process_open();
		break;
	case SSH2_FXP_CLOSE:
		process_close();
		break;
	case SSH2_FXP_READ:
		process_read();
		break;
	case SSH2_FXP_WRITE:
		process_write();
		break;
	case SSH2_FXP_LSTAT:
		process_lstat();
		break;
	case SSH2_FXP_FSTAT:
		process_fstat();
		break;
	case SSH2_FXP_SETSTAT:
		process_setstat();
		break;
	case SSH2_FXP_FSETSTAT:
		process_fsetstat();
		break;
	case SSH2_FXP_OPENDIR:
		process_opendir();
		break;
	case SSH2_FXP_READDIR:
		process_readdir();
		break;
	case SSH2_FXP_REMOVE:
		process_remove();
		break;
	case SSH2_FXP_MKDIR:
		process_mkdir();
		break;
	case SSH2_FXP_RMDIR:
		process_rmdir();
		break;
	case SSH2_FXP_REALPATH:
		process_realpath();
		break;
	case SSH2_FXP_STAT:
		process_stat();
		break;
	case SSH2_FXP_RENAME:
		process_rename();
		break;
	case SSH2_FXP_READLINK:
		process_readlink();
		break;
	case SSH2_FXP_SYMLINK:
		process_symlink();
		break;
	case SSH2_FXP_EXTENDED:
		process_extended();
		break;
	default:
		error("Unknown message %d", type);
		break;
	}
	/* discard the remaining bytes from the current packet */
	if (buf_len < buffer_len(&iqueue))
		fatal("iqueue grows");
	consumed = buf_len - buffer_len(&iqueue);
	if (msg_len < consumed)
		fatal("msg_len %d < consumed %d", msg_len, consumed);
	if (msg_len > consumed)
		buffer_consume(&iqueue, msg_len - consumed);
}
Beispiel #16
0
int main (int argc, const char* argv[]) {
  HWND hwnd;
  char *mapname;
  HANDLE filemap;
  unsigned char *p, *ret;
  int id, retlen, inlen, n, rmode, r = RET_NORESPONSE;
  COPYDATASTRUCT cds;
  void *in;

  if (argc < 2)
    return RET_ERR_BADARGS;

  hwnd = FindWindow("Pageant", "Pageant");
  if (!hwnd)
    return RET_ERR_UNAVAILABLE;

  rmode = _setmode(_fileno(stdin), _O_BINARY);
  if (rmode == -1)
    return RET_ERR_BINSTDIN;

  rmode = _setmode(_fileno(stdout), _O_BINARY);
  if (rmode == -1)
    return RET_ERR_BINSTDOUT;

  inlen = atoi(argv[1]);
  in = malloc(inlen);
  n = fread(in, 1, inlen, stdin);
  if (n != inlen) {
    free(in);
    return RET_ERR_BADLEN;
  }

  mapname = malloc(32);
  n = sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());

  filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
                              0, AGENT_MAX_MSGLEN, mapname);
  if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
    free(in);
    free(mapname);
    return RET_ERR_NOMAP;
  }

  p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
  memcpy(p, in, inlen);
  cds.dwData = AGENT_COPYDATA_ID;
  cds.cbData = 1 + n;
  cds.lpData = mapname;

  id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
  if (id > 0) {
    r = RET_RESPONSE;
    retlen = 4 + GET_32BIT(p);
    fwrite(p, 1, retlen, stdout);
  }

  free(in);
  free(mapname);
  UnmapViewOfFile(p);
  CloseHandle(filemap);

  return r;
}
Beispiel #17
0
// "in" means "to pageant", "out" means "from pageant". Sorry.
int
send_request_to_pageant(byte *inbuf, int inbytes, byte *outbuf, int outbuflen)
{
    EPRINTF(3, "Sending %d bytes to pageant.\n", inbytes);

    if (inbytes < 4) {
        EPRINTF(0, "Pageant-bound message too short (%d bytes).\n", inbytes);
        return 0;
    }
    int claimed_inbytes = GET_32BIT(inbuf);
    if (inbytes != claimed_inbytes + 4) {
        EPRINTF(0, "Pageant-bound message is %d bytes long, but it "
                "*says* it has %d=%d+4 bytes in it.\n",
                inbytes, claimed_inbytes+4, claimed_inbytes);
        return 0;
    }

    EPRINTF(5, "Message to pageant (%d bytes):\n", inbytes);
    print_buf(5, inbuf, inbytes);

    HWND hwnd;
    hwnd = FindWindow("Pageant", "Pageant");
    if (!hwnd) {
        EPRINTF(0, "Can't FindWindow(\"Pageant\"...) - "
                   "is pageant running?. (GetLastError is %x)\n",
                   (unsigned) GetLastError());
        return 0;
    }

    char mapname[512];
    sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());

    PSECURITY_ATTRIBUTES psa = NULL;
#ifndef NO_SECURITY
    SECURITY_ATTRIBUTES sa = {0};
    if (advapi_initialised || init_advapi()) {
        /*
         * Set the security info for the file mapping to the same as Pageant's
         * process, to make sure Pageant's SID check will pass.
         */

        DWORD dwProcId = 0;
        GetWindowThreadProcessId(hwnd, &dwProcId);
        HANDLE proc = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcId);
        if (proc != NULL) {
			sa.nLength = sizeof(sa);
			sa.bInheritHandle = TRUE;
			sa.lpSecurityDescriptor = NULL;
			GetSecurityInfo(proc, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION,
					NULL, NULL, NULL, NULL, (PSECURITY_DESCRIPTOR*)&sa.lpSecurityDescriptor);
			if (sa.lpSecurityDescriptor) {
				psa = &sa;
			}
        }
		CloseHandle(proc);
    } else {
        EPRINTF(0, "Couldn't initialize advapi.\n");
    }
#endif /* NO_SECURITY */

    HANDLE filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, 
                                       PAGE_READWRITE, 0, 
                                       AGENT_MAX_MSGLEN, mapname);
    if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
        EPRINTF(0, "Can't CreateFileMapping.\n");
        return 0;
    }

    byte *shmem = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
    memcpy(shmem, inbuf, inbytes);
    COPYDATASTRUCT cds;
    cds.dwData = AGENT_COPYDATA_ID;
    cds.cbData = 1 + strlen(mapname);
    cds.lpData = mapname;

    int id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
    int retlen = 0;
    if (id > 0) {
        retlen = 4 + GET_32BIT(shmem);
        if (retlen > outbuflen) {
            EPRINTF(0, "Buffer too small to contain reply from pageant.\n");
            return 0;
        }

        memcpy(outbuf, shmem, retlen);

        EPRINTF(5, "Reply from pageant (%d bytes):\n", retlen);
        print_buf(5, outbuf, retlen);
    } else {
        EPRINTF(0, "Couldn't SendMessage().\n");
        return 0;
    }

    // enum_windows();


    UnmapViewOfFile(shmem);
    CloseHandle(filemap);
#ifndef NO_SECURITY
    if (sa.lpSecurityDescriptor)
        LocalFree(sa.lpSecurityDescriptor);
#endif

    EPRINTF(3, "Got %d bytes back from pageant.\n", retlen);

    return retlen;
}
Beispiel #18
0
void random_xor_noise(RandomState * state, unsigned int i, word32 value)
{
    value ^= GET_32BIT(state->state + 4 * i);
    PUT_32BIT(state->state + 4 * i, value);
}
Beispiel #19
0
void random_stir(RandomState * state)
{
    word32 iv[4];
    unsigned int i;

    /* Start IV from last block of random pool. */
    iv[0] = GET_32BIT(state->state);
    iv[1] = GET_32BIT(state->state + 4);
    iv[2] = GET_32BIT(state->state + 8);
    iv[3] = GET_32BIT(state->state + 12);

    /* First CFB pass. */
    for (i = 0; i < RANDOM_STATE_BYTES; i += 16) {
        MD5Transform((md5_uint32 *)(char*)iv, state->stir_key);
        iv[0] ^= GET_32BIT(state->state + i);
        PUT_32BIT(state->state + i, iv[0]);
        iv[1] ^= GET_32BIT(state->state + i + 4);
        PUT_32BIT(state->state + i + 4, iv[1]);
        iv[2] ^= GET_32BIT(state->state + i + 8);
        PUT_32BIT(state->state + i + 8, iv[2]);
        iv[3] ^= GET_32BIT(state->state + i + 12);
        PUT_32BIT(state->state + i + 12, iv[3]);
    }

    /* Get new key. */
    memcpy(state->stir_key, state->state, sizeof(state->stir_key));

    /* Second CFB pass. */
    for (i = 0; i < RANDOM_STATE_BYTES; i += 16) {
        MD5Transform((md5_uint32 *)(char*)iv, state->stir_key);
        iv[0] ^= GET_32BIT(state->state + i);
        PUT_32BIT(state->state + i, iv[0]);
        iv[1] ^= GET_32BIT(state->state + i + 4);
        PUT_32BIT(state->state + i + 4, iv[1]);
        iv[2] ^= GET_32BIT(state->state + i + 8);
        PUT_32BIT(state->state + i + 8, iv[2]);
        iv[3] ^= GET_32BIT(state->state + i + 12);
        PUT_32BIT(state->state + i + 12, iv[3]);
    }

    memset(iv, 0, sizeof(iv));

    state->add_position = 0;

    /* Some data in the beginning is not returned to aboid giving an observer
       complete knowledge of the contents of our random pool. */
    state->next_available_byte = sizeof(state->stir_key);
}