> -----Original Message-----
> From: owner-openssl-dev@openssl.org
> [mailtowner-openssl-dev@openssl.org] On Behalf Of Shaw Graham George
> Sent: Wednesday, March 12, 2008 6:01 PM
> To: openssl-dev@openssl.org
> Subject: RE: crypto library in openssl
>
>
> Encrypted values are byte arrays, not strings. They may
> contain null characters. So you can't use strlen(). It's a
> common error.


But how to explain that passwords like "$dlkins02", "$flkins02", and "$Elki=
ns02" can be decrypted correctly? Only "$elkins02" is decrypted into empty =
string.

To be more specific, this is the code to decrypt:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
bool_t esscrypto_decryptString(unsigned char *toDecrypt,
unsigned char *passPhrase,
int sizeOfStrToDecrypt,
int maxDecryptedStringSize,
int *sizeOfDecryptedString,
unsigned char **decryptedString)
{
EVP_CIPHER_CTX openSSLDecryptionStructure;
int tempOutputLength =3D 0;
int i =3D 0;
int tmpOutputBufferPosition =3D 0;
int tmpOffset =3D 0;
char *tempPassPhrase =3D NULL;
int currentDecryptedStrLength =3D 0;
char *tempPtr =3D NULL;

LOGLIBENTER(__FUNCTION__);

tempPtr =3D ess_crypto_get_hex_string_from_string(toDecrypt);
if (tempPtr !=3D NULL)
{
LOGFORCE("Decrypting string (in hex) [%s]", tempPtr);
free(tempPtr);
}

/* initialize return values */
*sizeOfDecryptedString =3D 0;
*decryptedString =3D NULL;

/*
* Paranoia, if we get "really" big strings to decrypt, we should rejec=
t
* them in favor of a buffered string decryption method (like what is
* done for files). So spit out a warning and return false.
******/
if ( sizeOfStrToDecrypt > ESS_CRYPTO_MAX_TO_DECRYPT_STR_SIZE )
{
LOGWARN("Decrypting string of size [%d] is too big to decrypt",
sizeOfStrToDecrypt=
);
LOGLIBRETURN(__FUNCTION__);
return (FALSE);
}

tempPassPhrase =3D essCrypto_setupPassPhrase(passPhrase);

if (tempPassPhrase =3D=3D NULL)
{
LOGWARN("PassPhrase is null");
LOGLIBRETURN(__FUNCTION__);
return(FALSE);
}

EVP_DecryptInit(&openSSLDecryptionStructure, EVP_des_cbc(), tempPassPh=
rase,
(char *) NU=
LL);

/****
* Since we are using DES, we don't need to set the key length always
set to 64 bits, but if we use other ciphers, we need to do the follo=
wing:
EVP_CIPHER_CTX_set_key_length(&openSSLDecryptionStructure, );
// re-init
EVP_DecryptInit(&openSSLDecryptionStructure, NULL, passPhrase,
(char *)NULL);
****/
tempOutputLength =3D sizeOfStrToDecrypt +
EVP_CIPHER_CTX_block_size(&openSSLDecryptionStructure)=
+ 1;

/*
* If the caller put in a non-negative or zero value for the max decryp=
ted
* size, then the caller cares about how big of a string will be retur=
ned
* to it. So check to make sure it can handle the size of string that=
will
* be returned for decrypted data.
******/
if (maxDecryptedStringSize > 0)
{
/*
* If we are going to need more memory than the caller wants to use=
for
* the decrypted string, spit out an error and return false (since
* we cannot decrypt the string to the callers limitations).
******/
if (tempOutputLength > maxDecryptedStringSize)
{
LOGERROR(
"Cannot decrypt data, decrypted Size [%d] is going to be too b=
ig!",
tempOutputLength);
essCrypto_freePassPhrase(tempPassPhrase);
LOGLIBRETURN(__FUNCTION__);
return(FALSE);
}
}

/* malloc memory for the decrypted string */
*decryptedString =3D malloc(tempOutputLength);

/*
* Make sure we successfully malloced memory for the decryptedString st=
ring
******/
if (*decryptedString =3D=3D NULL)
{
LOGERROR("Unable to malloc memory for decryption");
essCrypto_freePassPhrase(tempPassPhrase);
LOGLIBRETURN(__FUNCTION__);
return (FALSE);
}

/* clean out the memory for the returned string */
memset(*decryptedString, 0, tempOutputLength);

/*
* Loop around decrypting the string with the buffer allocated for
* decryption till we cannot fill up the buffer with data anymore.
******/
for (i =3D 0; i < sizeOfStrToDecrypt/ ESS_CRYPTO_CRYPT_BUFFER_SIZE; i++=
)
{
/* decrypt the contents of the buffer */
EVP_DecryptUpdate(&openSSLDecryptionStructure,
&((*decryptedString)[tmpOutputBufferPosition]),
&tmpOffset,
&toDecrypt[tmpOutputBufferPosition],
ESS_CRYPTO_CRYPT_BUFFER_SIZE);

/* Increment the position we are at in decrypting the string */
tmpOutputBufferPosition =3D tmpOutputBufferPosition + tmpOffset;
}

/*
* if there is data left to decrypt that did not fit exactly within
* the buffer, decrypt that remaining bit.
******/
if ( sizeOfStrToDecrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)
{
/* decrypt the contents of the buffer */
EVP_DecryptUpdate(&openSSLDecryptionStructure,
&((*decryptedString)[tmpOutputBufferPosition]),
&tmpOffset,
&toDecrypt[tmpOutputBufferPosition],
sizeOfStrToDecrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)=
;

/* Increment the position we are at in decrypting the string */
tmpOutputBufferPosition =3D tmpOutputBufferPosition + tmpOffset;

}

/* finalize the results from decryption (check CRC) */
EVP_DecryptFinal(&openSSLDecryptionStructure,
&((*decryptedString)[tmpOutputBufferPosition]),
&tmpOffset);

/* set the final length of the decrypted string */
*sizeOfDecryptedString =3D tmpOutputBufferPosition + tmpOffset;

/* see what the length is according to strlen */
currentDecryptedStrLength =3D strlen(*decryptedString);
LOGFORCE("lenght of decrypted string is %d", currentDecryptedStrLength);=
//xq


/*
* If we have the room in memory, NULL terminate the string (just in cas=
e
* it has not already been done). Even thought we null out the entire
* string when memory was malloc'ed for it.
******/
if (*sizeOfDecryptedString < tempOutputLength)
{
(*decryptedString)[*sizeOfDecryptedString] =3D (char) 0;
}

/*
* If the OpenSSL length (sizeOfDecryptedString is less than the determi=
ned
* strlen, it means OpenSSL didn't clean up after itself and it left th=
e
* encryption "salt" in the string. If this is the case, remove the
* salt from memory (since it could contain sensitive information).
******/
if (*sizeOfDecryptedString < currentDecryptedStrLength)
{
LOGDEBUG("Cleaning up Salt in Decrypted String");

/*
* loop around and null out each "salt" character in the string
******/
for (i =3D *sizeOfDecryptedString; i < currentDecryptedStrLength; i+=
+)
{
(*decryptedString)[i] =3D (char) 0;
}
}

LOGREALLYSECURE("Decrypted String is [%s]", *decryptedString);

essCrypto_freePassPhrase(tempPassPhrase);
LOGLIBRETURN(__FUNCTION__);
return (TRUE);
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Here, the decrypted byte array is re-arranged into a character string repre=
senting the decrypted string. As far as I can see, EVP_DecryptInit(), EVP_D=
ecryptUpdate(), and EVP_DecryptFinal() are all library functions in OpenSSL=
(in crypto library?).


The code to encrypt is:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
bool_t esscrypto_encryptString(unsigned char *toEncrypt,
unsigned char *passPhrase,
int sizeOfStrToEncrypt,
int maxEncryptedStringSize,
int *sizeofEncryptedString,
unsigned char **encryptedString)
{
EVP_CIPHER_CTX openSSLEncryptionStructure;
int tempOutputLength =3D 0;
int i =3D 0;
int tmpOutputBufferPosition =3D 0;
int tmpOffset =3D 0;
char *tempPassPhrase =3D NULL;
char *tempStrPtr =3D NULL;

LOGLIBENTER(__FUNCTION__);

LOGFORCE("Encrypting [%s] ", toEncrypt);

/* initialize return values */
*sizeofEncryptedString =3D 0;
*encryptedString =3D NULL;

/*
* Paranoia, if we get "really" big strings to encrypt, we should rejec=
t
* them in favor of a buffered string encryption method (like what is
* done for files). So spit out a warning and return false.
******/
if ( sizeOfStrToEncrypt > ESS_CRYPTO_MAX_TO_ENCRYPT_STR_SIZE )
{
LOGWARN("Encrypting string of size [%d] is too big to encrypt",
sizeOfStrToEncrypt=
);
LOGLIBRETURN(__FUNCTION__);
return (FALSE);
}

/* format the password to be OpenSSL friendly */
tempPassPhrase =3D essCrypto_setupPassPhrase(passPhrase);

/*
* If we have a null password, something is not right, spit out a warni=
ng
* and return false.
******/
if (tempPassPhrase =3D=3D NULL)
{
LOGWARN("PassPhrase is NULL");
LOGLIBRETURN(__FUNCTION__);
return(FALSE);
}

/* Initialize OpenSSL for DES encryption */

EVP_EncryptInit(&openSSLEncryptionStructure, EVP_des_cbc(), tempPassPhr=
ase,
(char *)NULL);

/****
* Since we are using DES, we don't need to set the key length always
set to 64 bits, but if we use other ciphers, we need to do the follo=
wing:
EVP_CIPHER_CTX_set_key_length(&openSSLEncryptionStructure, );
// re-init
EVP_EncryptInit(&openSSLEncryptionStructure, NULL, passPhrase,
(char *)NULL);
****/


/* Get potential size of the output data with a null terminator*/
tempOutputLength =3D sizeOfStrToEncrypt +
EVP_CIPHER_CTX_block_size(&openSSLEncryptionStructure)=
+ 1;

/*
* If the caller put in a non-negative or zero value for the max encryp=
ted
* size, then the caller cares about how big of a string will be retur=
ned
* to it. So check to make sure it can handle the size of string that =
will
* be returned for encrypted data.
******/
if (maxEncryptedStringSize > 0)
{
/*
* If we are going to need more memory than the caller wants to use=
for
* the encrypted string, spit out an error and return false (since
* we cannot encrypt the string to the callers limitations).
******/
if (tempOutputLength > maxEncryptedStringSize)
{
LOGERROR(
"Cannot Encrypt data, Encrypted Size is going to be too big=
!");
essCrypto_freePassPhrase(tempPassPhrase);
LOGLIBRETURN(__FUNCTION__);
return(FALSE);
}
}

/* malloc memory for the encrypted string */
*encryptedString =3D malloc(tempOutputLength);

/*
* Make sure we successfully malloced memory for the encrypted string
******/
if (*encryptedString =3D=3D NULL)
{
LOGERROR("Unable to malloc memory for encryption");
LOGLIBRETURN(__FUNCTION__);
essCrypto_freePassPhrase(tempPassPhrase);
return (FALSE);
}

/* clean out the memory for the returned string */
memset(*encryptedString, 0, tempOutputLength);

/*
* Loop around encrypting the string with the buffer allocated for
* encryption till we cannot fill up the buffer with data anymore.
******/
for (i =3D 0; i < sizeOfStrToEncrypt/ ESS_CRYPTO_CRYPT_BUFFER_SIZE; i++=
)
{
/* encrypt the buffer contents) */
EVP_EncryptUpdate(&openSSLEncryptionStructure,
&((*encryptedString)[tmpOutputBufferPosition]),
&tmpOffset,
&toEncrypt[tmpOutputBufferPosition],
ESS_CRYPTO_CRYPT_BUFFER_SIZE);

/* Increment the position we are at in encrypting the string */
tmpOutputBufferPosition =3D tmpOutputBufferPosition + tmpOffset;
}

/*
* if there is data left to encrypt that did not fit exactly within
* the buffer, encrypt that remaining bit.
******/
if ( sizeOfStrToEncrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)
{
/* encrypt the buffer contents) */
EVP_EncryptUpdate(&openSSLEncryptionStructure,
&((*encryptedString)[tmpOutputBufferPosition]),
&tmpOffset,
&toEncrypt[tmpOutputBufferPosition],
sizeOfStrToEncrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)=
;

/* Increment the position we are at in encrypting the string */
tmpOutputBufferPosition =3D tmpOutputBufferPosition + tmpOffset;

}

/* Finalize the encryption results (generate CRC for example) */
EVP_EncryptFinal(&openSSLEncryptionStructure,
&((*encryptedString)[tmpOutputBufferPosition]),
&tmpOffset);

/* set the total size of the string encrypted */
*sizeofEncryptedString =3D tmpOutputBufferPosition + tmpOffset;

tempStrPtr =3D ess_crypto_get_hex_string_from_string(*encryptedSt ring);

if (tempStrPtr !=3D NULL)
{
LOGFORCE("Encrypted String (in HEX) is [%s]", tempStrPtr);
free(tempStrPtr);
}
essCrypto_freePassPhrase(tempPassPhrase);

LOGLIBRETURN(__FUNCTION__);
return (TRUE);
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
I am not sure whether some algorithm in these functions would go awry when =
dealing with the password "$elkins02".

Thanks,
Xu Qiang
__________________________________________________ ____________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org