CASA/c_adlib/ad_ff/native/CryptManager.cpp

459 lines
12 KiB
C++
Raw Normal View History

2006-03-10 19:39:22 +01:00
/***********************************************************************
*
* 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.
*
***********************************************************************/
2006-02-28 12:17:08 +01:00
#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");
2006-03-06 10:54:36 +01:00
(*PK11FreeSlot) (slot);
2006-02-28 12:17:08 +01:00
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 ...");
2006-03-06 10:54:36 +01:00
(*PK11FreeSlot) (slot);
2006-02-28 12:17:08 +01:00
return FPM_FALSE;
}
*cryptData = (char*)reply.data;
*cryptDataLen = reply.len;
2006-03-06 10:54:36 +01:00
(*PK11FreeSlot) (slot);
2006-02-28 12:17:08 +01:00
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");
2006-03-06 10:54:36 +01:00
(*PK11FreeSlot) (slot);
2006-02-28 12:17:08 +01:00
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 ...");
2006-03-06 10:54:36 +01:00
(*PK11FreeSlot) (slot);
2006-02-28 12:17:08 +01:00
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;
}