/* Abiword * Copyright (C) 2002 Christian Biesinger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ /** @file * implementation of staroffice decryption routines, very much inspired by * openoffice's sw/source/core/sw3io/sw3imp.cxx#L2721 and sw/source/core/sw3io/crypter.cxx#L77 */ #include "sdw_cryptor.h" #include "ut_debugmsg.h" #include "ut_string_class.h" // random values for encrypting the password static const UT_uint8 gEncode[] = { 0xab, 0x9e, 0x43, 0x05, 0x38, 0x12, 0x4d, 0x44, 0xd5, 0x7e, 0xe3, 0x84, 0x98, 0x23, 0x3f, 0xba }; SDWCryptor::SDWCryptor(UT_uint32 aDate, UT_uint32 aTime, const UT_uint8* aFilePass) : mDate(aDate), mTime(aTime) { if (aFilePass) memcpy(mFilePass, aFilePass, maxPWLen); else memset(mFilePass, 0, maxPWLen); } SDWCryptor::~SDWCryptor() { } bool SDWCryptor::SetPassword(const char* aPassword) { // Set the new password char pw[maxPWLen]; strncpy(pw, aPassword, maxPWLen); size_t len = strlen(aPassword); // fill with spaces. only executed if len < maxPWLen for (int i = len; i < maxPWLen; i++) pw[i] = ' '; // the password needs to be encrypted memcpy(mPassword, gEncode, maxPWLen); Encrypt(pw, mPassword, maxPWLen); // Check password if we have valid date and/or time if (mDate || mTime) { char testString[17]; UT_String needle = UT_String_sprintf("%08x%08x", mDate, mTime); Encrypt(needle.c_str(), testString, 16); if (memcmp(testString, mFilePass, 16) != 0) { return false; // wrong password } } return true; } // almost literally taken from openoffice code (crypter.cxx) void SDWCryptor::Decrypt(const char* aEncrypted, char* aBuffer, UT_uint32 aLen) const { size_t nCryptPtr = 0; UT_uint8 cBuf[maxPWLen]; memcpy(cBuf, mPassword, maxPWLen); UT_uint8* p = cBuf; if (!aLen) aLen = strlen(aEncrypted); while (aLen--) { *aBuffer++ = *aEncrypted++ ^ ( *p ^ static_cast ( cBuf[ 0 ] * nCryptPtr ) ); *p += ( nCryptPtr < (maxPWLen-1) ) ? *(p+1) : cBuf[ 0 ]; if( !*p ) *p += 1; p++; if( ++nCryptPtr >= maxPWLen ) { nCryptPtr = 0; p = cBuf; } } }