void CPDF_StandardSecurityHandler::AES256_SetPassword( CPDF_Dictionary* pEncryptDict, const uint8_t* password, FX_DWORD size, FX_BOOL bOwner, const uint8_t* key) { uint8_t sha[128]; CRYPT_SHA1Start(sha); CRYPT_SHA1Update(sha, key, 32); CRYPT_SHA1Update(sha, (uint8_t*)"hello", 5); uint8_t digest[20]; CRYPT_SHA1Finish(sha, digest); CFX_ByteString ukey = pEncryptDict->GetString(FX_BSTRC("U")); uint8_t digest1[48]; if (m_Revision >= 6) { Revision6_Hash(password, size, digest, (bOwner ? (const uint8_t*)ukey : NULL), digest1); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, digest, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); } CRYPT_SHA256Finish(sha, digest1); } FXSYS_memcpy(digest1 + 32, digest, 16); pEncryptDict->SetAtString(bOwner ? FX_BSTRC("O") : FX_BSTRC("U"), CFX_ByteString(digest1, 48)); if (m_Revision >= 6) { Revision6_Hash(password, size, digest + 8, (bOwner ? (const uint8_t*)ukey : NULL), digest1); } else { CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, digest + 8, 8); if (bOwner) { CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); } CRYPT_SHA256Finish(sha, digest1); } uint8_t* aes = FX_Alloc(uint8_t, 2048); CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); uint8_t iv[16]; FXSYS_memset(iv, 0, 16); CRYPT_AESSetIV(aes, iv); CRYPT_AESEncrypt(aes, digest1, key, 32); FX_Free(aes); pEncryptDict->SetAtString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"), CFX_ByteString(digest1, 32)); }
void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, const uint8_t* user_pass, uint32_t user_size, const uint8_t* owner_pass, uint32_t owner_size, FX_BOOL bDefault, uint32_t type) { int cipher = 0, key_len = 0; if (!LoadDict(pEncryptDict, type, cipher, key_len)) { return; } if (bDefault && (!owner_pass || owner_size == 0)) { owner_pass = user_pass; owner_size = user_size; } if (m_Revision >= 5) { int t = (int)time(nullptr); uint8_t sha[128]; CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, (uint8_t*)&t, sizeof t); CRYPT_SHA256Update(sha, m_EncryptKey, 32); CRYPT_SHA256Update(sha, (uint8_t*)"there", 5); CRYPT_SHA256Finish(sha, m_EncryptKey); AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); if (bDefault) { AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey); AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBooleanBy("EncryptMetadata", true), m_EncryptKey); } return; } if (bDefault) { uint8_t passcode[32]; for (uint32_t i = 0; i < 32; i++) { passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; } uint8_t digest[16]; CRYPT_MD5Generate(passcode, 32, digest); if (m_Revision >= 3) { for (uint32_t i = 0; i < 50; i++) CRYPT_MD5Generate(digest, 16, digest); } uint8_t enckey[32]; FXSYS_memcpy(enckey, digest, key_len); for (uint32_t i = 0; i < 32; i++) { passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; } CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); uint8_t tempkey[32]; if (m_Revision >= 3) { for (uint8_t i = 1; i <= 19; i++) { for (int j = 0; j < key_len; j++) tempkey[j] = enckey[j] ^ i; CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); } } pEncryptDict->SetAtString("O", CFX_ByteString(passcode, 32)); } CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray); if (m_Revision < 3) { uint8_t tempbuf[32]; FXSYS_memcpy(tempbuf, defpasscode, 32); CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); pEncryptDict->SetAtString("U", CFX_ByteString(tempbuf, 32)); } else { uint8_t md5[100]; CRYPT_MD5Start(md5); CRYPT_MD5Update(md5, defpasscode, 32); if (pIdArray) { CFX_ByteString id = pIdArray->GetStringAt(0); CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength()); } uint8_t digest[32]; CRYPT_MD5Finish(md5, digest); CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); uint8_t tempkey[32]; for (uint8_t i = 1; i <= 19; i++) { for (int j = 0; j < key_len; j++) { tempkey[j] = m_EncryptKey[j] ^ i; } CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); } CRYPT_MD5Generate(digest, 16, digest + 16); pEncryptDict->SetAtString("U", CFX_ByteString(digest, 32)); } }
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; }
void Revision6_Hash(const uint8_t* password, uint32_t size, const uint8_t* salt, const uint8_t* vector, uint8_t* hash) { int iBlockSize = 32; uint8_t sha[128]; CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, password, size); CRYPT_SHA256Update(sha, salt, 8); if (vector) { CRYPT_SHA256Update(sha, vector, 48); } uint8_t digest[32]; CRYPT_SHA256Finish(sha, digest); CFX_ByteTextBuf buf; uint8_t* input = digest; uint8_t* key = input; uint8_t* iv = input + 16; uint8_t* E = buf.GetBuffer(); int iBufLen = buf.GetLength(); CFX_ByteTextBuf interDigest; int i = 0; uint8_t* aes = FX_Alloc(uint8_t, 2048); while (i < 64 || i < E[iBufLen - 1] + 32) { int iRoundSize = size + iBlockSize; if (vector) { iRoundSize += 48; } iBufLen = iRoundSize * 64; buf.EstimateSize(iBufLen); E = buf.GetBuffer(); CFX_ByteTextBuf content; for (int j = 0; j < 64; ++j) { content.AppendBlock(password, size); content.AppendBlock(input, iBlockSize); if (vector) { content.AppendBlock(vector, 48); } } CRYPT_AESSetKey(aes, 16, key, 16, TRUE); CRYPT_AESSetIV(aes, iv); CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); int iHash = 0; switch (BigOrder64BitsMod3(E)) { case 0: iHash = 0; iBlockSize = 32; break; case 1: iHash = 1; iBlockSize = 48; break; default: iHash = 2; iBlockSize = 64; break; } interDigest.EstimateSize(iBlockSize); input = interDigest.GetBuffer(); if (iHash == 0) { CRYPT_SHA256Generate(E, iBufLen, input); } else if (iHash == 1) { CRYPT_SHA384Generate(E, iBufLen, input); } else if (iHash == 2) { CRYPT_SHA512Generate(E, iBufLen, input); } key = input; iv = input + 16; ++i; } FX_Free(aes); if (hash) { FXSYS_memcpy(hash, input, 32); } }
void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, FX_LPCBYTE user_pass, FX_DWORD user_size, FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type) { int cipher = 0, key_len = 0; if (!LoadDict(pEncryptDict, type, cipher, key_len)) { return; } if (bDefault && (owner_pass == NULL || owner_size == 0)) { owner_pass = user_pass; owner_size = user_size; } if (m_Revision >= 5) { int t = (int)time(NULL); FX_BYTE sha[128]; CRYPT_SHA256Start(sha); CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t); CRYPT_SHA256Update(sha, m_EncryptKey, 32); CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5); CRYPT_SHA256Finish(sha, m_EncryptKey); AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); if (bDefault) { AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey); AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey); } return; } if (bDefault) { FX_BYTE passcode[32]; FX_DWORD i; for (i = 0; i < 32; i ++) { passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; } FX_BYTE digest[16]; CRYPT_MD5Generate(passcode, 32, digest); if (m_Revision >= 3) { for (int i = 0; i < 50; i ++) { CRYPT_MD5Generate(digest, 16, digest); } } FX_BYTE enckey[32]; FXSYS_memcpy32(enckey, digest, key_len); for (i = 0; i < 32; i ++) { passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; } CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); FX_BYTE tempkey[32]; if (m_Revision >= 3) { for (i = 1; i <= 19; i ++) { for (int j = 0; j < key_len; j ++) { tempkey[j] = enckey[j] ^ (FX_BYTE)i; } CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); } } pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32)); } CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray); if (m_Revision < 3) { FX_BYTE tempbuf[32]; FXSYS_memcpy32(tempbuf, defpasscode, 32); CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32)); } else { FX_BYTE md5[100]; CRYPT_MD5Start(md5); CRYPT_MD5Update(md5, defpasscode, 32); if (pIdArray) { CFX_ByteString id = pIdArray->GetString(0); CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); } FX_BYTE digest[32]; CRYPT_MD5Finish(md5, digest); CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); FX_BYTE tempkey[32]; for (int i = 1; i <= 19; i ++) { for (int j = 0; j < key_len; j ++) { tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i; } CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); } CRYPT_MD5Generate(digest, 16, digest + 16); pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32)); } }
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; }