1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file.
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <time.h>
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../include/fpdfapi/fpdf_parser.h"
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../include/fdrm/fx_crypt.h"
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovconst FX_BYTE defpasscode[32] = {
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CalcEncryptKey(CPDF_Dictionary* pEncrypt, FX_LPCBYTE password, FX_DWORD pass_size,
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_LPBYTE key, int keylen, FX_BOOL bIgnoreMeta, CPDF_Array* pIdArray)
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int revision = pEncrypt->GetInteger(FX_BSTRC("R"));
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE passcode[32];
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (FX_DWORD i = 0; i < 32; i ++) {
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size];
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE md5[100];
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Start(md5);
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Update(md5, passcode, 32);
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString okey = pEncrypt->GetString(FX_BSTRC("O"));
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)okey, okey.GetLength());
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD perm = pEncrypt->GetInteger(FX_BSTRC("P"));
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Update(md5, (FX_LPBYTE)&perm, 4);
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pIdArray) {
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteString id = pIdArray->GetString(0);
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!bIgnoreMeta && revision >= 3 && !pEncrypt->GetInteger(FX_BSTRC("EncryptMetadata"), 1)) {
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD tag = (FX_DWORD) - 1;
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Update(md5, (FX_LPBYTE)&tag, 4);
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest[16];
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Finish(md5, digest);
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD copy_len = keylen;
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (copy_len > sizeof(digest)) {
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        copy_len = sizeof(digest);
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (revision >= 3) {
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 0; i < 50; i ++) {
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_MD5Generate(digest, copy_len, digest);
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(key, 0, keylen);
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(key, digest, copy_len);
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler()
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FX_NEW CPDF_StandardCryptoHandler;
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _PDF_CRYPTOITEM : public CFX_Object {
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_INT32	m_Cipher;
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_INT32	m_KeyLen;
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL		m_bChecked;
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CPDF_StandardCryptoHandler*	m_pCryptoHandler;
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} PDF_CRYPTOITEM;
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler()
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Version = 0;
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Revision = 0;
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pParser = NULL;
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pEncryptDict = NULL;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bOwner = FALSE;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Permissions = 0;
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Cipher = FXCIPHER_NONE;
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_KeyLen = 0;
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler()
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict)
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pParser = pParser;
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!LoadDict(pEncryptDict)) {
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_NONE) {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CheckSecurity(m_KeyLen);
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::CheckSecurity(FX_INT32 key_len)
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString password = m_pParser->GetPassword();
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CheckPassword(password, password.GetLength(), TRUE, m_EncryptKey, key_len)) {
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (password.IsEmpty()) {
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len)) {
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_bOwner = TRUE;
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len);
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CPDF_StandardSecurityHandler::GetPermissions()
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return m_Permissions;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, FX_BSTR name, int& cipher, int& keylen)
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Version = pEncryptDict->GetInteger(FX_BSTRC("V"));
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cipher = FXCIPHER_RC4;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    keylen = 0;
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Version >= 4) {
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDict(FX_BSTRC("CF"));
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pCryptFilters == NULL) {
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (name == FX_BSTRC("Identity")) {
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cipher = FXCIPHER_NONE;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CPDF_Dictionary* pDefFilter = pCryptFilters->GetDict(name);
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pDefFilter == NULL) {
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int nKeyBits = 0;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Version == 4) {
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                nKeyBits = pDefFilter->GetInteger(FX_BSTRC("Length"), 0);
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (nKeyBits == 0) {
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 128);
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 256);
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (nKeyBits < 40) {
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                nKeyBits *= 8;
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            keylen = nKeyBits / 8;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFX_ByteString cipher_name = pDefFilter->GetString(FX_BSTRC("CFM"));
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (cipher_name == FX_BSTRC("AESV2") || cipher_name == FX_BSTRC("AESV3")) {
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cipher = FXCIPHER_AES;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        keylen = Version > 1 ? pEncryptDict->GetInteger(FX_BSTRC("Length"), 40) / 8 : 5;
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (keylen > 32 || keylen < 0) {
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict)
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pEncryptDict = pEncryptDict;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bOwner = FALSE;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Version = pEncryptDict->GetInteger(FX_BSTRC("V"));
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1);
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Version < 4) {
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return _LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen);
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF"));
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString strf_name = pEncryptDict->GetString(FX_BSTRC("StrF"));
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (stmf_name != strf_name) {
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen)) {
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, FX_DWORD type, int& cipher, int& key_len)
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pEncryptDict = pEncryptDict;
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bOwner = FALSE;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Version = pEncryptDict->GetInteger(FX_BSTRC("V"));
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R"));
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1);
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString strf_name, stmf_name;
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Version >= 4) {
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF"));
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        strf_name = pEncryptDict->GetString(FX_BSTRC("StrF"));
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (stmf_name != strf_name) {
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len)) {
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Cipher = cipher;
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_KeyLen = key_len;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::GetCryptInfo(int& cipher, FX_LPCBYTE& buffer, int& keylen)
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cipher = m_Cipher;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buffer = m_EncryptKey;
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    keylen = m_KeyLen;
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GET_32WORD(n,b,i)								\
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {														\
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        (n) = (FX_DWORD)(( (FX_UINT64) (b)[(i)] << 24 )			\
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         | ( (FX_UINT64) (b)[(i) + 1] << 16 )					\
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         | ( (FX_UINT64) (b)[(i) + 2] <<  8 )					\
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         | ( (FX_UINT64) (b)[(i) + 3]       ));					\
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint BigOrder64BitsMod3(FX_LPBYTE data)
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_UINT64 ret = 0;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (int i = 0; i < 4; ++i) {
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD value;
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_GET_32WORD(value, data, 4 * i);
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ret <<= 32;
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ret |= value;
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ret %= 3;
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (int)ret;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Revision6_Hash(FX_LPCBYTE password, FX_DWORD size, FX_LPCBYTE salt, FX_LPCBYTE vector, FX_LPBYTE hash)
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int iBlockSize = 32;
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE sha[128];
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA256Start(sha);
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA256Update(sha, password, size);
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA256Update(sha, salt, 8);
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (vector) {
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, vector, 48);
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest[32];
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA256Finish(sha, digest);
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteTextBuf buf;
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE input = digest;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE key = input;
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE iv = input + 16;
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE E = buf.GetBuffer();
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int iBufLen = buf.GetLength();
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteTextBuf interDigest;
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i = 0;
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE aes = FX_Alloc(FX_BYTE, 2048);
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (i < 64 || i < E[iBufLen - 1]  + 32) {
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int iRoundSize = size + iBlockSize;
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (vector) {
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            iRoundSize += 48;
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        iBufLen = iRoundSize * 64;
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        buf.EstimateSize(iBufLen);
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        E = buf.GetBuffer();
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteTextBuf content;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int j = 0; j < 64; ++j) {
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            content.AppendBlock(password, size);
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            content.AppendBlock(input, iBlockSize);
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (vector) {
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                content.AppendBlock(vector, 48);
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESSetKey(aes, 16, key, 16, TRUE);
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESSetIV(aes, iv);
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen);
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int iHash = 0;
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        switch (BigOrder64BitsMod3(E)) {
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case 0:
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iHash = 0;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iBlockSize = 32;
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case 1:
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iHash = 1;
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iBlockSize = 48;
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iHash = 2;
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iBlockSize = 64;
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        interDigest.EstimateSize(iBlockSize);
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        input = interDigest.GetBuffer();
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (iHash == 0) {
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA256Generate(E, iBufLen, input);
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (iHash == 1) {
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA384Generate(E, iBufLen, input);
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (iHash == 2) {
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA512Generate(E, iBufLen, input);
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key = input;
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        iv = input + 16;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ++i;
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(aes);
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (hash) {
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(hash, input, 32);
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword(FX_LPCBYTE password, FX_DWORD size,
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bOwner, FX_LPBYTE key)
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O"));
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (okey.GetLength() < 48) {
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U"));
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ukey.GetLength() < 48) {
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPCBYTE pkey = bOwner ? (FX_LPCBYTE)okey : (FX_LPCBYTE)ukey;
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE sha[128];
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest[32];
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 6) {
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 32, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Start(sha);
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, password, size);
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, pkey + 32, 8);
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bOwner) {
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA256Update(sha, ukey, 48);
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Finish(sha, digest);
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXSYS_memcmp32(digest, pkey, 32) != 0) {
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (key == NULL) {
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 6) {
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 40, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest);
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Start(sha);
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, password, size);
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, pkey + 40, 8);
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bOwner) {
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA256Update(sha, ukey, 48);
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Finish(sha, digest);
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString ekey = m_pEncryptDict->GetString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"));
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ekey.GetLength() < 32) {
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetKey(aes, 16, digest, 32, FALSE);
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE iv[16];
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(iv, 0, 16);
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetIV(aes, iv);
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESDecrypt(aes, key, ekey, 32);
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetKey(aes, 16, key, 32, FALSE);
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetIV(aes, iv);
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString perms = m_pEncryptDict->GetString(FX_BSTRC("Perms"));
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (perms.IsEmpty()) {
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE perms_buf[16];
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(perms_buf, 0, sizeof(perms_buf));
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD copy_len = sizeof(perms_buf);
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (copy_len > (FX_DWORD)perms.GetLength()) {
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        copy_len = perms.GetLength();
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(perms_buf, (FX_LPCBYTE)perms, copy_len);
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE buf[16];
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESDecrypt(aes, buf, perms_buf, 16);
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(aes);
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) {
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) {
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD pass_size, FX_BOOL bOwner, FX_LPBYTE key)
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CheckPassword(password, pass_size, bOwner, key, m_KeyLen);
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPBYTE key, FX_INT32 key_len)
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 5) {
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return AES256_CheckPassword(password, size, bOwner, key);
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE keybuf[32];
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (key == NULL) {
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key = keybuf;
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bOwner) {
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CheckOwnerPassword(password, size, key, key_len);
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CheckUserPassword(password, size, FALSE, key, key_len) || CheckUserPassword(password, size, TRUE, key, key_len);
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::CheckUserPassword(FX_LPCBYTE password, FX_DWORD pass_size,
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bIgnoreEncryptMeta, FX_LPBYTE key, FX_INT32 key_len)
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, bIgnoreEncryptMeta,
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   m_pParser->GetIDArray());
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U"));
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ukey.GetLength() < 16) {
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE ukeybuf[32];
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision == 2) {
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(ukeybuf, defpasscode, 32);
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len);
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE test[32], tmpkey[32];
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD copy_len = sizeof(test);
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (copy_len > (FX_DWORD)ukey.GetLength()) {
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            copy_len = ukey.GetLength();
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memset32(test, 0, sizeof(test));
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(test, (FX_LPCSTR)ukey, copy_len);
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 19; i >= 0; i --) {
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int j = 0; j < key_len; j ++) {
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                tmpkey[j] = key[j] ^ i;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len);
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE md5[100];
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Start(md5);
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Update(md5, defpasscode, 32);
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CPDF_Array* pIdArray = m_pParser->GetIDArray();
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pIdArray) {
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFX_ByteString id = pIdArray->GetString(0);
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Finish(md5, ukeybuf);
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FXSYS_memcmp32(test, ukeybuf, 16) == 0;
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FXSYS_memcmp32((FX_LPVOID)(FX_LPCSTR)ukey, ukeybuf, 16) == 0) {
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size)
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return GetUserPassword(owner_pass, pass_size, m_KeyLen);
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size, FX_INT32 key_len)
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O"));
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE passcode[32];
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD i;
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i = 0; i < 32; i ++) {
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size];
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest[16];
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Generate(passcode, 32, digest);
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 3) {
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 0; i < 50; i ++) {
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_MD5Generate(digest, 16, digest);
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE enckey[32];
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(enckey, 0, sizeof(enckey));
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD copy_len = key_len;
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (copy_len > sizeof(digest)) {
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        copy_len = sizeof(digest);
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(enckey, digest, copy_len);
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int okeylen = okey.GetLength();
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (okeylen > 32) {
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        okeylen = 32;
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE okeybuf[64];
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(okeybuf, (FX_LPCSTR)okey, okeylen);
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision == 2) {
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len);
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 19; i >= 0; i --) {
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_BYTE tempkey[32];
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int j = 0; j < m_KeyLen; j ++) {
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                tempkey[j] = enckey[j] ^ i;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len);
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int len = 32;
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (len && defpasscode[len - 1] == okeybuf[len - 1]) {
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        len --;
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CFX_ByteString(okeybuf, len);
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::CheckOwnerPassword(FX_LPCBYTE password, FX_DWORD pass_size,
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE key, FX_INT32 key_len)
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len);
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CheckUserPassword(user_pass, user_pass.GetLength(), FALSE, key, key_len)) {
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CheckUserPassword(user_pass, user_pass.GetLength(), TRUE, key, key_len);
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardSecurityHandler::IsMetadataEncrypted()
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return m_pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE);
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler()
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FX_NEW CPDF_StandardSecurityHandler;
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray,
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPCBYTE user_pass, FX_DWORD user_size,
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type)
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int cipher = 0, key_len = 0;
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!LoadDict(pEncryptDict, type, cipher, key_len)) {
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bDefault && (owner_pass == NULL || owner_size == 0)) {
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        owner_pass = user_pass;
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        owner_size = user_size;
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 5) {
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int t = (int)time(NULL);
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE sha[128];
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Start(sha);
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t);
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, m_EncryptKey, 32);
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5);
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Finish(sha, m_EncryptKey);
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey);
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bDefault) {
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey);
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey);
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bDefault) {
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE passcode[32];
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD i;
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i = 0; i < 32; i ++) {
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE digest[16];
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Generate(passcode, 32, digest);
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_Revision >= 3) {
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int i = 0; i < 50; i ++) {
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                CRYPT_MD5Generate(digest, 16, digest);
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE enckey[32];
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(enckey, digest, key_len);
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i = 0; i < 32; i ++) {
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE tempkey[32];
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_Revision >= 3) {
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (i = 1; i <= 19; i ++) {
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int j = 0; j < key_len; j ++) {
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    tempkey[j] = enckey[j] ^ (FX_BYTE)i;
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32));
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray);
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision < 3) {
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE tempbuf[32];
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(tempbuf, defpasscode, 32);
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32));
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE md5[100];
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Start(md5);
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Update(md5, defpasscode, 32);
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pIdArray) {
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFX_ByteString id = pIdArray->GetString(0);
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE digest[32];
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Finish(md5, digest);
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE tempkey[32];
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 1; i <= 19; i ++) {
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int j = 0; j < key_len; j ++) {
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i;
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Generate(digest, 16, digest + 16);
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32));
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray,
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPCBYTE user_pass, FX_DWORD user_size,
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_DWORD type)
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, TRUE, type);
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, FX_LPCBYTE user_pass, FX_DWORD user_size, FX_DWORD type)
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type);
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardSecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPCBYTE key)
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE sha[128];
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA1Start(sha);
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA1Update(sha, key, 32);
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA1Update(sha, (FX_BYTE*)"hello", 5);
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest[20];
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_SHA1Finish(sha, digest);
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString ukey = pEncryptDict->GetString(FX_BSTRC("U"));
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE digest1[48];
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 6) {
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Revision6_Hash(password, size, digest, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1);
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Start(sha);
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, password, size);
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, digest, 8);
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bOwner) {
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA256Update(sha, ukey, ukey.GetLength());
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Finish(sha, digest1);
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(digest1 + 32, digest, 16);
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pEncryptDict->SetAtString(bOwner ? FX_BSTRC("O") : FX_BSTRC("U"), CFX_ByteString(digest1, 48));
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Revision >= 6) {
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Revision6_Hash(password, size, digest + 8, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1);
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Start(sha);
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, password, size);
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Update(sha, digest + 8, 8);
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bOwner) {
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_SHA256Update(sha, ukey, ukey.GetLength());
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_SHA256Finish(sha, digest1);
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE);
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE iv[16];
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(iv, 0, 16);
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetIV(aes, iv);
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESEncrypt(aes, digest1, key, 32);
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(aes);
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pEncryptDict->SetAtString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"), CFX_ByteString(digest1, 32));
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardSecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, FX_DWORD permissions,
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bEncryptMetadata, FX_LPCBYTE key)
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE buf[16];
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[0] = (FX_BYTE)permissions;
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[1] = (FX_BYTE)(permissions >> 8);
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[2] = (FX_BYTE)(permissions >> 16);
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[3] = (FX_BYTE)(permissions >> 24);
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[4] = 0xff;
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[5] = 0xff;
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[6] = 0xff;
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[7] = 0xff;
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[8] = bEncryptMetadata ? 'T' : 'F';
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[9] = 'a';
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[10] = 'd';
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    buf[11] = 'b';
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048);
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetKey(aes, 16, key, 32, TRUE);
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE iv[16], buf1[16];
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(iv, 0, 16);
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESSetIV(aes, iv);
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_AESEncrypt(aes, buf1, buf, 16);
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(aes);
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pEncryptDict->SetAtString(FX_BSTRC("Perms"), CFX_ByteString(buf1, 16));
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size,
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_buf, FX_DWORD& dest_size)
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_NONE) {
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(dest_buf, src_buf, src_size);
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE realkey[16];
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int realkeylen = 16;
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) {
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE key1[32];
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen);
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key1[m_KeyLen + 0] = (FX_BYTE)objnum;
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key1[m_KeyLen + 1] = (FX_BYTE)(objnum >> 8);
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key1[m_KeyLen + 2] = (FX_BYTE)(objnum >> 16);
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key1[m_KeyLen + 3] = (FX_BYTE)gennum;
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        key1[m_KeyLen + 4] = (FX_BYTE)(gennum >> 8);
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3);
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2);
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_Cipher == FXCIPHER_AES) {
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4);
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        realkeylen = m_KeyLen + 5;
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (realkeylen > 16) {
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            realkeylen = 16;
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen, bEncrypt);
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bEncrypt) {
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_BYTE iv[16];
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int i = 0; i < 16; i ++) {
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                iv[i] = (FX_BYTE)rand();
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESSetIV(m_pAESContext, iv);
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memcpy32(dest_buf, iv, 16);
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int nblocks = src_size / 16;
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16);
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_BYTE padding[16];
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memcpy32(padding, src_buf + nblocks * 16, src_size % 16);
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memset8(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16);
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, 16);
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_size = 32 + nblocks * 16;
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESSetIV(m_pAESContext, src_buf);
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16);
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_size = src_size - 16;
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_size -= dest_buf[dest_size - 1];
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(dest_size == src_size);
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (dest_buf != src_buf) {
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FXSYS_memcpy32(dest_buf, src_buf, src_size);
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen);
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _AESCryptContext {
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE		m_Context[2048];
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL		m_bIV;
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE		m_Block[16];
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD	m_BlockOffset;
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} AESCryptContext;
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, FX_DWORD gennum, FX_BOOL bEncrypt)
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_NONE) {
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return this;
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) {
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_bIV = TRUE;
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_BlockOffset = 0;
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt);
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bEncrypt) {
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int i = 0; i < 16; i ++) {
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pContext->m_Block[i] = (FX_BYTE)rand();
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return pContext;
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE key1[48];
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen);
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3);
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2);
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4);
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE realkey[16];
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey);
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int realkeylen = m_KeyLen + 5;
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (realkeylen > 16) {
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        realkeylen = 16;
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_bIV = TRUE;
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_BlockOffset = 0;
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt);
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bEncrypt) {
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int i = 0; i < 16; i ++) {
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pContext->m_Block[i] = (FX_BYTE)rand();
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return pContext;
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void* pContext = FX_Alloc(FX_BYTE, 1040);
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CRYPT_ArcFourSetup(pContext, realkey, realkeylen);
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return pContext;
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::CryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt)
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!context) {
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_NONE) {
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_buf.AppendBlock(src_buf, src_size);
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_RC4) {
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int old_size = dest_buf.GetSize();
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_buf.AppendBlock(src_buf, src_size);
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size);
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    AESCryptContext* pContext = (AESCryptContext*)context;
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pContext->m_bIV && bEncrypt) {
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_buf.AppendBlock(pContext->m_Block, 16);
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_bIV = FALSE;
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD src_off = 0;
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD src_left = src_size;
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (1) {
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_DWORD copy_size = 16 - pContext->m_BlockOffset;
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (copy_size > src_left) {
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            copy_size = src_left;
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, copy_size);
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        src_off += copy_size;
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        src_left -= copy_size;
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pContext->m_BlockOffset += copy_size;
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pContext->m_BlockOffset == 16) {
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!bEncrypt && pContext->m_bIV) {
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block);
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pContext->m_bIV = FALSE;
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pContext->m_BlockOffset = 0;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else if (src_off < src_size) {
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_BYTE block_buf[16];
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (bEncrypt) {
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_buf.AppendBlock(block_buf, 16);
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pContext->m_BlockOffset = 0;
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!src_left) {
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::CryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt)
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!context) {
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_NONE) {
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_RC4) {
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(context);
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    AESCryptContext* pContext = (AESCryptContext*)context;
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bEncrypt) {
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE block_buf[16];
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pContext->m_BlockOffset == 16) {
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_buf.AppendBlock(block_buf, 16);
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pContext->m_BlockOffset = 0;
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memset8(pContext->m_Block + pContext->m_BlockOffset, (FX_BYTE)(16 - pContext->m_BlockOffset), 16 - pContext->m_BlockOffset);
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_buf.AppendBlock(block_buf, 16);
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (pContext->m_BlockOffset == 16) {
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BYTE block_buf[16];
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16);
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (block_buf[15] <= 16) {
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_buf.AppendBlock(block_buf, 16 - block_buf[15]);
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(pContext);
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPVOID CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, FX_DWORD gennum)
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CryptStart(objnum, gennum, FALSE);
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size)
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size;
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::Init(CPDF_Dictionary* pEncryptDict, CPDF_SecurityHandler* pSecurityHandler)
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPCBYTE key;
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) {
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_KeyLen > 32 || m_KeyLen < 0) {
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher != FXCIPHER_NONE) {
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXSYS_memcpy32(m_EncryptKey, key, m_KeyLen);
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pAESContext = FX_Alloc(FX_BYTE, 2048);
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::Init(int cipher, FX_LPCBYTE key, int keylen)
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cipher == FXCIPHER_AES) {
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        switch(keylen) {
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case 16:
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case 24:
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case 32:
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (cipher == FXCIPHER_AES2) {
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (keylen != 32) {
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (cipher == FXCIPHER_RC4) {
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (keylen < 5 || keylen > 16) {
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (keylen > 32) {
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            keylen = 32;
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Cipher = cipher;
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_KeyLen = keylen;
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memcpy32(m_EncryptKey, key, keylen);
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pAESContext = FX_Alloc(FX_BYTE, 2048);
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::DecryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size,
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_BinaryBuf& dest_buf)
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CryptStream(context, src_buf, src_size, dest_buf, FALSE);
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf)
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CryptFinish(context, dest_buf, FALSE);
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, FX_DWORD version, FX_LPCBYTE src_buf, FX_DWORD src_size)
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_Cipher == FXCIPHER_AES) {
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return src_size + 32;
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return src_size;
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size,
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_buf, FX_DWORD& dest_size)
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size);
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_CryptoHandler::Decrypt(FX_DWORD objnum, FX_DWORD gennum, CFX_ByteString& str)
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_BinaryBuf dest_buf;
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPVOID context = DecryptStart(objnum, gennum);
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DecryptStream(context, (FX_LPCBYTE)str, str.GetLength(), dest_buf);
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DecryptFinish(context, dest_buf);
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    str = dest_buf;
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler()
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pAESContext = NULL;
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_Cipher = FXCIPHER_NONE;
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_KeyLen = 0;
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler()
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pAESContext) {
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(m_pAESContext);
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
958