FX_BOOL CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password,
                                                   uint32_t size,
                                                   FX_BOOL bOwner,
                                                   uint8_t* key) {
  CFX_ByteString okey =
      m_pEncryptDict ? m_pEncryptDict->GetStringBy("O") : CFX_ByteString();
  if (okey.GetLength() < 48) {
    return FALSE;
  }
  CFX_ByteString ukey =
      m_pEncryptDict ? m_pEncryptDict->GetStringBy("U") : CFX_ByteString();
  if (ukey.GetLength() < 48) {
    return FALSE;
  }
  const uint8_t* pkey = (bOwner ? okey : ukey).raw_str();
  uint8_t sha[128];
  uint8_t digest[32];
  if (m_Revision >= 6) {
    Revision6_Hash(password, size, (const uint8_t*)pkey + 32,
                   bOwner ? ukey.raw_str() : nullptr, digest);
  } else {
    CRYPT_SHA256Start(sha);
    CRYPT_SHA256Update(sha, password, size);
    CRYPT_SHA256Update(sha, pkey + 32, 8);
    if (bOwner) {
      CRYPT_SHA256Update(sha, ukey.raw_str(), 48);
    }
    CRYPT_SHA256Finish(sha, digest);
  }
  if (FXSYS_memcmp(digest, pkey, 32) != 0) {
    return FALSE;
  }
  if (!key) {
    return TRUE;
  }
  if (m_Revision >= 6) {
    Revision6_Hash(password, size, (const uint8_t*)pkey + 40,
                   bOwner ? ukey.raw_str() : nullptr, digest);
  } else {
    CRYPT_SHA256Start(sha);
    CRYPT_SHA256Update(sha, password, size);
    CRYPT_SHA256Update(sha, pkey + 40, 8);
    if (bOwner) {
      CRYPT_SHA256Update(sha, ukey.raw_str(), 48);
    }
    CRYPT_SHA256Finish(sha, digest);
  }
  CFX_ByteString ekey = m_pEncryptDict
                            ? m_pEncryptDict->GetStringBy(bOwner ? "OE" : "UE")
                            : CFX_ByteString();
  if (ekey.GetLength() < 32) {
    return FALSE;
  }
  uint8_t* aes = FX_Alloc(uint8_t, 2048);
  CRYPT_AESSetKey(aes, 16, digest, 32, FALSE);
  uint8_t iv[16];
  FXSYS_memset(iv, 0, 16);
  CRYPT_AESSetIV(aes, iv);
  CRYPT_AESDecrypt(aes, key, ekey.raw_str(), 32);
  CRYPT_AESSetKey(aes, 16, key, 32, FALSE);
  CRYPT_AESSetIV(aes, iv);
  CFX_ByteString perms = m_pEncryptDict->GetStringBy("Perms");
  if (perms.IsEmpty()) {
    return FALSE;
  }
  uint8_t perms_buf[16];
  FXSYS_memset(perms_buf, 0, sizeof(perms_buf));
  uint32_t copy_len = sizeof(perms_buf);
  if (copy_len > (uint32_t)perms.GetLength()) {
    copy_len = perms.GetLength();
  }
  FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len);
  uint8_t buf[16];
  CRYPT_AESDecrypt(aes, buf, perms_buf, 16);
  FX_Free(aes);
  if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {
    return FALSE;
  }
  if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) {
    return FALSE;
  }
  if ((buf[8] == 'T' && !IsMetadataEncrypted()) ||
      (buf[8] == 'F' && IsMetadataEncrypted())) {
    return FALSE;
  }
  return TRUE;
}
FX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword(FX_LPCBYTE password, FX_DWORD size,
        FX_BOOL bOwner, FX_LPBYTE key)
{
    CFX_ByteString okey = m_pEncryptDict ? m_pEncryptDict->GetString(FX_BSTRC("O")) : CFX_ByteString();
    if (okey.GetLength() < 48) {
        return FALSE;
    }
    CFX_ByteString ukey = m_pEncryptDict ? m_pEncryptDict->GetString(FX_BSTRC("U")) : CFX_ByteString();
    if (ukey.GetLength() < 48) {
        return FALSE;
    }
    FX_LPCBYTE pkey = bOwner ? (FX_LPCBYTE)okey : (FX_LPCBYTE)ukey;
    FX_BYTE sha[128];
    FX_BYTE digest[32];
    if (m_Revision >= 6) {
        Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 32, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);
    } else {
        CRYPT_SHA256Start(sha);
        CRYPT_SHA256Update(sha, password, size);
        CRYPT_SHA256Update(sha, pkey + 32, 8);
        if (bOwner) {
            CRYPT_SHA256Update(sha, ukey, 48);
        }
        CRYPT_SHA256Finish(sha, digest);
    }
    if (FXSYS_memcmp32(digest, pkey, 32) != 0) {
        return FALSE;
    }
    if (key == NULL) {
        return TRUE;
    }
    if (m_Revision >= 6) {
        Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 40, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);
    } else {
        CRYPT_SHA256Start(sha);
        CRYPT_SHA256Update(sha, password, size);
        CRYPT_SHA256Update(sha, pkey + 40, 8);
        if (bOwner) {
            CRYPT_SHA256Update(sha, ukey, 48);
        }
        CRYPT_SHA256Finish(sha, digest);
    }
    CFX_ByteString ekey = m_pEncryptDict ? m_pEncryptDict->GetString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE")) : CFX_ByteString();
    if (ekey.GetLength() < 32) {
        return FALSE;
    }
    FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);
    CRYPT_AESSetKey(aes, 16, digest, 32, FALSE);
    FX_BYTE iv[16];
    FXSYS_memset32(iv, 0, 16);
    CRYPT_AESSetIV(aes, iv);
    CRYPT_AESDecrypt(aes, key, ekey, 32);
    CRYPT_AESSetKey(aes, 16, key, 32, FALSE);
    CRYPT_AESSetIV(aes, iv);
    CFX_ByteString perms = m_pEncryptDict->GetString(FX_BSTRC("Perms"));
    if (perms.IsEmpty()) {
        return FALSE;
    }
    FX_BYTE perms_buf[16];
    FXSYS_memset32(perms_buf, 0, sizeof(perms_buf));
    FX_DWORD copy_len = sizeof(perms_buf);
    if (copy_len > (FX_DWORD)perms.GetLength()) {
        copy_len = perms.GetLength();
    }
    FXSYS_memcpy32(perms_buf, (FX_LPCBYTE)perms, copy_len);
    FX_BYTE buf[16];
    CRYPT_AESDecrypt(aes, buf, perms_buf, 16);
    FX_Free(aes);
    if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {
        return FALSE;
    }
    if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) {
        return FALSE;
    }
    if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) {
        return FALSE;
    }
    return TRUE;
}