459 lines
12 KiB
C++
459 lines
12 KiB
C++
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* This library 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
|
|
* Library Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, Novell, Inc.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "CryptManager.h"
|
|
|
|
|
|
|
|
void CryptManager::SetupFunctions(void *funList[])
|
|
{
|
|
|
|
//PK11SetPasswordFunc = (PK11_SetPasswordFunc) funList[0];
|
|
PK11GetInternalKeySlot = (PK11_GetInternalKeySlot) funList[1];
|
|
PK11FreeSlot = (PK11_FreeSlot) funList[2];
|
|
PK11Authenticate = (PK11_Authenticate) funList[3];
|
|
PK11CheckUserPassword =(PK11_CheckUserPassword) funList[4];
|
|
PK11SDRDecrypt = (PK11SDR_Decrypt) funList[5];
|
|
PK11SDREncrypt = (PK11SDR_Encrypt) funList[6];
|
|
PLBase64Encode = (PL_Base64Encode) funList[7];
|
|
PLBase64Decode = (PL_Base64Decode) funList[8];
|
|
|
|
}
|
|
|
|
int CryptManager::GetEncryptionPref()
|
|
{
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* This function encrypts the clear text data. First it performs TRIPLE DES encryption
|
|
* and then performs base64 encoding on the encrypted data.
|
|
*
|
|
* @param(in) clearData clear text data to be encrypted
|
|
* @param(out) finalData encrypted data ( null terminated)
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
int CryptManager::EncryptString (char *clearData, char **finalData)
|
|
{
|
|
int encryptDataLen = 0;
|
|
char *encryptData = NULL;
|
|
char *encodeData = NULL;
|
|
int retValue;
|
|
|
|
|
|
if( clearData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n EncryptString : Text Data is NULL");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
// Do the encryption if encryption pref is set otherwise just do base64 encoding...
|
|
if ( GetEncryptionPref() )
|
|
{
|
|
PrintMessage(MESG_DEBUG, "\n EncryptString : Performing PK11 Encryption...");
|
|
|
|
retValue = FPM_FALSE;
|
|
if( ((retValue = CryptPK11EncryptString(clearData, strlen(clearData), &encryptData, &encryptDataLen)) != FPM_TRUE) || ( encryptData == NULL) )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n EncryptString : Failed to encrypt the string : %s ", clearData);
|
|
return retValue;
|
|
}
|
|
|
|
if( (CryptBase64Encode(encryptData, encryptDataLen, finalData) != FPM_TRUE) || (*finalData == NULL) )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n EncryptString : BASE64 encoding failed");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
PrintMessage(MESG_DEBUG, "\n EncryptString : Success ");
|
|
|
|
// WARNING : If you uncomment , then be ready for side effects , crashes..etc
|
|
// Need full analysis of malloc for this data..
|
|
// Free the allocated blocks...
|
|
|
|
//if( encryptData )
|
|
// free( encryptData);
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
// otherwise do our own obscuring using Base64 encoding
|
|
PrintMessage(MESG_DEBUG, "\n EncryptString : Performing JUST base64 encoding...");
|
|
|
|
if( (CryptBase64Encode(clearData, strlen(clearData), &encodeData) == FPM_FALSE) || (encodeData == NULL) )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n EncryptString : BASE64 encoding failed");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
// We need to add the CRYPT_PREFIX at the begining of encoded data...
|
|
// This will help during decrption process to identify type of encryption
|
|
|
|
int prefixLen = strlen( CRYPT_PREFIX );
|
|
int encodeLen = strlen( encodeData );
|
|
*finalData = (char *)malloc( prefixLen + encodeLen + 1);
|
|
|
|
if( *finalData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n EncryptString : Insufficient memory");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
// FinalData = CRYPT_PREFIX + Encoded Data + '\0'
|
|
strcpy(*finalData, CRYPT_PREFIX);
|
|
strcat(*finalData, encodeData);
|
|
*(*finalData + prefixLen + encodeLen) = 0;
|
|
|
|
free(encodeData);
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* This function decrypts the encrypted data. First it performs base64 decoding and
|
|
* then performs TRIPLE DES decryption.
|
|
*
|
|
* @param(in) cryptData encrypted data
|
|
* @param(out) clearData clear text data ( null terminated)
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
|
|
int CryptManager::DecryptString(char *cryptData, char **clearData)
|
|
{
|
|
int decodeLen = 0;
|
|
int finalLen = 0;
|
|
char *decodeData = NULL;
|
|
char *finalData = NULL;
|
|
int retValue;
|
|
|
|
if( cryptData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n DecryptString: CryptData is NULL...");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
// treat zero-length crypt string as a special case
|
|
if(cryptData[0] == '\0')
|
|
{
|
|
*clearData = (char*) malloc(1);
|
|
**clearData = 0;
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
// use PK11 encryption stuff if crypt doesn't starts with prefix
|
|
if( cryptData[0] != CRYPT_PREFIX[0] )
|
|
{
|
|
|
|
PrintMessage(MESG_DEBUG, "\n Performing PK11 Decryption ");
|
|
|
|
// First do base64 decoding.....
|
|
if( (CryptBase64Decode(cryptData, &decodeData, &decodeLen) != FPM_TRUE) || (decodeData == NULL) )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n DecryptString : Base64 decoding of crypt data failed ");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
PrintMessage(MESG_DEBUG, "\n DecryptString : base64data (%d) = %s ", decodeLen, decodeData);
|
|
|
|
// Now do actual PK11 decryption
|
|
retValue = FPM_FALSE;
|
|
retValue = CryptPK11DecryptString(decodeData, decodeLen, &finalData, &finalLen);
|
|
|
|
if( retValue != FPM_TRUE )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n DecryptString : Failed to decrypt the string ");
|
|
return retValue;
|
|
}
|
|
|
|
|
|
// WARNING : Decrypted string is not NULL terminated
|
|
// So we will create new NULL terminated string here...
|
|
|
|
*clearData = (char*) malloc( finalLen + 1 );
|
|
|
|
if( *clearData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n DecryptString :Insufficient memory... ");
|
|
return FPM_INSUFFICIENT_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
PrintMessage(MESG_DEBUG, "\n DecryptString : Copying new data ....");
|
|
memcpy(*clearData, finalData, finalLen);
|
|
*(*clearData + finalLen) = 0; // Null terminate the string....
|
|
}
|
|
|
|
/*
|
|
// Free the allocated memory
|
|
// This is causing the problems currently...Later point we have to reanalyze the cause for this
|
|
|
|
if( decodeData )
|
|
free(decodeData);
|
|
|
|
if( finalData )
|
|
free(finalData);
|
|
*/
|
|
|
|
PrintMessage(MESG_DEBUG, "\n decryptString : finalLen = %d ", finalLen);
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
// otherwise do our own de-obscuring
|
|
PrintMessage(MESG_DEBUG, "\n DecryptString : Performing simple Base64 Decoding ");
|
|
|
|
unsigned int PREFIX_Len = strlen(CRYPT_PREFIX);
|
|
if( strlen(cryptData) == PREFIX_Len )
|
|
{
|
|
*clearData = (char *)malloc(1);
|
|
**clearData = '\0';
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
if( CryptBase64Decode(&cryptData[PREFIX_Len], clearData, &decodeLen) == FPM_FALSE )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n DecryptString : Base64 decoding of crypt data failed ");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Performs base64 encoding of the encrypted data..
|
|
*
|
|
* @param(in) cryptData encrypted data
|
|
* @param(in) cryptDataLen length of encrypted data
|
|
* @param(out) encodeData base64 encoded data
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
|
|
int CryptManager::CryptBase64Encode(char *cryptData, int cryptDataLen, char **encodeData)
|
|
{
|
|
|
|
*encodeData = (*PLBase64Encode)((const char *)cryptData, cryptDataLen, NULL);
|
|
|
|
if ( *encodeData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n Base64 encoding failed ...");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Performs base64 decoding of the encrypted data..
|
|
*
|
|
* @param(in) cryptData encrypted data
|
|
* @param(out) decodeData base64 decoded data
|
|
* @param(out) decodeLen length of base64 decoded data
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
int CryptManager::CryptBase64Decode(char *cryptData, char **decodeData, int *decodeLen)
|
|
{
|
|
int len = strlen( cryptData );
|
|
int adjust = 0;
|
|
|
|
PrintMessage(MESG_DEBUG, "\n CryptBase64Decode : Length of crypt data = %d", len);
|
|
|
|
// Compute length adjustment
|
|
if (cryptData[len-1] == '=')
|
|
{
|
|
adjust++;
|
|
if (cryptData[len-2] == '=')
|
|
adjust++;
|
|
}
|
|
|
|
*decodeData = ( char *)(*PLBase64Decode)(cryptData, len, NULL);
|
|
|
|
if( *decodeData == NULL )
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n Base64 decoding failed ...");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
*decodeLen = (len*3)/4 - adjust;
|
|
|
|
PrintMessage(MESG_DEBUG, "\n CryptBase64Decode : Length of decoded data = %d", *decodeLen);
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Performs TRIPLE DES encryption of clear text data
|
|
*
|
|
* @param(in) clearData clear text data to be encrypted
|
|
* @param(in) clearDataLen length of clear text data
|
|
* @param(out) cryptData TRIPLE DES encrypted data
|
|
* @param(out) cryptDataLen length of encrypted data
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
int CryptManager::CryptPK11EncryptString(char *clearData, int clearDataLen, char **cryptData, int *cryptDataLen)
|
|
{
|
|
PK11SlotInfo *slot = 0;
|
|
SECItem keyid;
|
|
SECItem request;
|
|
SECItem reply;
|
|
SECStatus status;
|
|
|
|
slot = (*PK11GetInternalKeySlot)();
|
|
|
|
if (!slot)
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n CryptPK11EncryptString : PK11_GetInternalKeySlot failed ...");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
// PK11 authentication
|
|
if ( (*PK11Authenticate)(slot, PR_TRUE, NULL) != SECSuccess)
|
|
{
|
|
// since we have specified password callback function , we won't come here...
|
|
PrintMessage(MESG_ERROR, "\n CryptPK11EncryptString : PK11_Authenticate failed, possibly master password is wrong");
|
|
(*PK11FreeSlot) (slot);
|
|
return FPM_MASTERPASSWORD_WRONG;
|
|
}
|
|
|
|
|
|
// Use default key id
|
|
keyid.data = 0;
|
|
keyid.len = 0;
|
|
request.data = (unsigned char *)clearData;
|
|
request.len = clearDataLen;
|
|
reply.data = 0;
|
|
reply.len = 0;
|
|
|
|
status = (*PK11SDREncrypt)(&keyid, &request, &reply, NULL);
|
|
|
|
if (status != SECSuccess)
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n CryptPK11EncryptString : PK11SDR_Encrypt failed ...");
|
|
(*PK11FreeSlot) (slot);
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
|
|
*cryptData = (char*)reply.data;
|
|
*cryptDataLen = reply.len;
|
|
|
|
(*PK11FreeSlot) (slot);
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Performs TRIPLE DES decryption of base64 decoded data
|
|
*
|
|
* @param(in) decodeData base64 decoded data
|
|
* @param(in) decodeLen length of base64 decoded data
|
|
* @param(out) clearData decrypted data
|
|
* @param(out) finalLen length of decrypted data
|
|
*
|
|
* @return FPM_TRUE on success and FPM_FALSE on error.
|
|
*
|
|
*/
|
|
int CryptManager::CryptPK11DecryptString(char *decodeData, int decodeLen, char **clearData, int *finalLen)
|
|
{
|
|
PK11SlotInfo *slot = 0;
|
|
SECStatus status;
|
|
SECItem request;
|
|
SECItem reply;
|
|
|
|
PrintMessage(MESG_DEBUG, "\n CryptPK11DecryptString entered ...");
|
|
|
|
// Find token with SDR key
|
|
slot = (*PK11GetInternalKeySlot)();
|
|
|
|
if (!slot)
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n PK11_GetInternalKeySlot failed ...");
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
PrintMessage(MESG_DEBUG, "\n PK11_GetInternalKeySlot SUCCESS ...");
|
|
|
|
// Force authentication
|
|
if ( (*PK11Authenticate)(slot, PR_TRUE, NULL) != SECSuccess)
|
|
{
|
|
// since we have specified password callback function , we won't come here...
|
|
PrintMessage(MESG_ERROR, "\n PK11_Authenticate failed, Probably master password is wrong");
|
|
(*PK11FreeSlot) (slot);
|
|
return FPM_MASTERPASSWORD_WRONG;
|
|
}
|
|
|
|
PrintMessage(MESG_DEBUG, "\n PK11_Authenticate SUCCESS ...");
|
|
|
|
// Decrypt the string
|
|
request.data = (unsigned char *)decodeData;
|
|
request.len = decodeLen;
|
|
reply.data = 0;
|
|
reply.len = 0;
|
|
|
|
PrintMessage(MESG_DEBUG, "\n calling PK11SDR_Decrypt ...");
|
|
|
|
status = (*PK11SDRDecrypt)(&request, &reply, NULL);
|
|
|
|
if (status != SECSuccess)
|
|
{
|
|
PrintMessage(MESG_ERROR, "\n PK11SDR_Decrypt failed ...");
|
|
(*PK11FreeSlot) (slot);
|
|
return FPM_FALSE;
|
|
}
|
|
|
|
PrintMessage(MESG_DEBUG, "\n PK11SDR_Decrypt SUCCESS ");
|
|
|
|
// WARNING : This string is not NULL terminated..
|
|
*clearData = (char*)reply.data;
|
|
*finalLen = reply.len;
|
|
|
|
// Free the slot
|
|
(*PK11FreeSlot) (slot);
|
|
|
|
return FPM_TRUE;
|
|
}
|
|
|
|
|