/**
   * Perform an NTLMv2 check
   *
   * @param md4hash String
   * @param challenge byte[]
   * @param type3Msg Type3NTLMMessage
   * @return boolean
   */
  protected final boolean checkNTLMv2(String md4hash, byte[] challenge, Type3NTLMMessage type3Msg) {
    if (getLogger().isDebugEnabled()) getLogger().debug(("Perform an NTLMv2 check."));
    boolean ntlmv2OK = false;
    boolean lmv2OK = false;

    try {
      // Generate the v2 hash using the challenge that was sent to the client
      byte[] v2hash =
          m_encryptor.doNTLM2Encryption(
              m_md4Encoder.decodeHash(md4hash), type3Msg.getUserName(), type3Msg.getDomain());

      // Get the NTLMv2 blob sent by the client and the challenge that was sent by the server
      NTLMv2Blob v2blob = new NTLMv2Blob(type3Msg.getNTLMHash());

      // Calculate the HMAC of the received blob and compare
      byte[] srvHmac = v2blob.calculateHMAC(challenge, v2hash);
      byte[] clientHmac = v2blob.getHMAC();

      if (clientHmac != null && srvHmac != null && clientHmac.length == srvHmac.length) {
        int i = 0;

        while (i < clientHmac.length && clientHmac[i] == srvHmac[i]) {
          i++;
        }

        if (i == clientHmac.length) {
          if (getLogger().isDebugEnabled())
            getLogger().debug(("HMAC matches the client, user authenticated."));
          ntlmv2OK = true;
        }
      }

      // NTLMv2 check failed, try the LMv2 value

      if (ntlmv2OK == false) {
        byte[] lmv2 = type3Msg.getLMHash();
        byte[] clChallenge = v2blob.getClientChallenge();

        if (lmv2 != null && lmv2.length == 24 && clChallenge != null && clChallenge.length == 8) {
          // Check that the LM hash contains the client challenge as the last 8 bytes

          int i = 0;

          while (i < clChallenge.length && lmv2[i + 16] == clChallenge[i]) i++;

          if (i == clChallenge.length) {
            // Calculate the LMv2 value

            byte[] lmv2Hmac = v2blob.calculateLMv2HMAC(v2hash, challenge, clChallenge);

            // Check if the LMv2 HMAC matches

            i = 0;

            while (i < lmv2Hmac.length && lmv2[i] == lmv2Hmac[i]) i++;

            if (i == lmv2Hmac.length) {
              if (getLogger().isDebugEnabled())
                getLogger().debug(("LMv2 HMAC matches the client, user authenticated."));

              // return true;
              lmv2OK = true;
            }
          }
        }
      }
    } catch (Exception ex) {
      if (getLogger().isDebugEnabled()) getLogger().debug(ex);
    }

    // Check if either of the NTLMv2 checks passed

    if (ntlmv2OK || lmv2OK) return true;
    return false;
  }