docs: public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
              IllegalArgumentException
      {
          if ((out.length - len) < outOff)
          {
              throw new DataLengthException("output buffer too small");
          }
  
          long oBytes = len;
          int outLen = digest.getDigestSize();
  
          //
          // this is at odds with the standard implementation, the
          // maximum value should be hBits * (2^32 - 1) where hBits
          // is the digest output size in bits. We can't have an
          // array with a long index at the moment...
          //
          if (oBytes > ((2L << 32) - 1))
          {
              throw new IllegalArgumentException("Output length too large");
          }
  
          int cThreshold = (int)((oBytes + outLen - 1) / outLen);
  
          byte[] dig = new byte[digest.getDigestSize()];
  
          byte[] C = new byte[4];
          Pack.intToBigEndian(counterStart, C, 0);
  
          int counterBase = counterStart & ~0xFF;
  
          for (int i = 0; i < cThreshold; i++)
          {
              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 (len > outLen)
              {
                  System.arraycopy(dig, 0, out, outOff, outLen);
                  outOff += outLen;
                  len -= outLen;
              }
              else
              {
                  System.arraycopy(dig, 0, out, outOff, len);
              }
  
              if (++C[3] == 0)
              {
                  counterBase += 0x100;
                  Pack.intToBigEndian(counterBase, C, 0);
              }
          }
  
          digest.reset();
  
          return (int)oBytes;
      }