@Override
    public int generateBytes(final byte[] out, final int outOff, final int len)
        throws DataLengthException, IllegalArgumentException {
      checkArgument(len >= 0, "length to fill cannot be negative");

      if ((out.length - len) < outOff) {
        throw new DataLengthException("output buffer too small");
      }

      final int outLen = digest.getDigestSize();
      final int cThreshold = (len + outLen - 1) / outLen;
      final byte[] dig = new byte[digestSize];
      final byte[] C = Pack.intToBigEndian(COUNTER_START);
      int counterBase = 0; // COUNTER_START & ~0xFF is always zero
      int offset = outOff;
      int length = len;

      for (int i = 0; i < cThreshold; i++) {
        // Ethereum peculiarity: Ethereum requires digesting the counter and the shared secret is
        // inverse order
        // that of the standard BaseKDFBytesGenerator in Bouncy Castle.
        digest.update(C, 0, C.length);
        digest.update(shared, 0, shared.length);

        if (iv != null) {
          digest.update(iv, 0, iv.length);
        }

        digest.doFinal(dig, 0);

        if (length > outLen) {
          System.arraycopy(dig, 0, out, offset, outLen);
          offset += outLen;
          length -= outLen;
        } else {
          System.arraycopy(dig, 0, out, offset, length);
        }

        if (++C[3] == 0) {
          counterBase += 0x100;
          Pack.intToBigEndian(counterBase, C, 0);
        }
      }

      digest.reset();
      return length;
    }
Fills <code>len</code> bytes of the output buffer with bytes generated from the derivation
function.

@throws IllegalArgumentException If the size of the request will cause an overflow.
@throws DataLengthException If the out buffer is too small.
ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/handshake/ecies/ECIESEncryptionEngine.java