Sun, 05 May 2013 18:25:31 +0200
ciphers cleanup: fix perl compilation; better purple_cipher_digest_region
--- a/libpurple/cipher.c Sun May 05 16:29:14 2013 +0200 +++ b/libpurple/cipher.c Sun May 05 18:25:31 2013 +0200 @@ -120,34 +120,42 @@ return caps; } -gboolean +ssize_t purple_cipher_digest_region(const gchar *name, const guchar *data, size_t data_len, guchar digest[], size_t out_size) { PurpleCipher *cipher; PurpleCipherContext *context; - gboolean ret = FALSE; + ssize_t digest_size; + gboolean succ; - g_return_val_if_fail(name, FALSE); - g_return_val_if_fail(data, FALSE); + g_return_val_if_fail(name, -1); + g_return_val_if_fail(data, -1); cipher = purple_ciphers_find_cipher(name); - g_return_val_if_fail(cipher, FALSE); + g_return_val_if_fail(cipher, -1); - if(!cipher->ops->append || !cipher->ops->digest) { + if(!cipher->ops->append || !cipher->ops->digest || !cipher->ops->get_digest_size) { purple_debug_warning("cipher", "purple_cipher_region failed: " "the %s cipher does not support appending and or " "digesting.", cipher->name); - return FALSE; + return -1; } context = purple_cipher_context_new(cipher, NULL); + digest_size = purple_cipher_context_get_digest_size(context); + if (out_size < digest_size) { + purple_debug_error("cipher", "purple_cipher_region failed: " + "provided output buffer too small\n"); + purple_cipher_context_destroy(context); + return -1; + } purple_cipher_context_append(context, data, data_len); - ret = purple_cipher_context_digest(context, digest, out_size); + succ = purple_cipher_context_digest(context, digest, out_size); purple_cipher_context_destroy(context); - return ret; + return succ ? digest_size : -1; } /******************************************************************************
--- a/libpurple/cipher.h Sun May 05 16:29:14 2013 +0200 +++ b/libpurple/cipher.h Sun May 05 18:25:31 2013 +0200 @@ -169,9 +169,9 @@ * @param digest The returned digest * @param out_size The size of digest buffer * - * @return @c TRUE if successful, @c FALSE otherwise + * @return The count of bytes written, or -1 if failed */ -gboolean purple_cipher_digest_region(const gchar *name, const guchar *data, size_t data_len, guchar digest[], size_t out_size); +ssize_t purple_cipher_digest_region(const gchar *name, const guchar *data, size_t data_len, guchar digest[], size_t out_size); /*@}*/ /******************************************************************************/
--- a/libpurple/plugins/perl/common/Cipher.xs Sun May 05 16:29:14 2013 +0200 +++ b/libpurple/plugins/perl/common/Cipher.xs Sun May 05 18:25:31 2013 +0200 @@ -25,6 +25,7 @@ const_iv(SET_IV), const_iv(APPEND), const_iv(DIGEST), + const_iv(GET_DIGEST_SIZE), const_iv(ENCRYPT), const_iv(DECRYPT), const_iv(SET_SALT), @@ -34,7 +35,6 @@ const_iv(SET_BATCH_MODE), const_iv(GET_BATCH_MODE), const_iv(GET_BLOCK_SIZE), - const_iv(SET_KEY_WITH_LEN), const_iv(UNKNOWN), #undef const_iv }; @@ -54,28 +54,30 @@ purple_cipher_get_capabilities(cipher) Purple::Cipher cipher -size_t -purple_cipher_digest_region(name, data_sv, in_len, digest) +gboolean +purple_cipher_digest_region(name, data_sv, data_len, digest) const gchar *name SV *data_sv - size_t in_len + size_t data_len SV *digest PREINIT: - gboolean ret; guchar *buff = NULL; guchar *data = NULL; - size_t data_len; + ssize_t digest_len; + size_t max_digest_len = 100; CODE: data = (guchar *)SvPV(data_sv, data_len); SvUPGRADE(digest, SVt_PV); - buff = (guchar *)SvGROW(digest, in_len); - ret = purple_cipher_digest_region(name, data, data_len, in_len, buff, &RETVAL); - if(!ret) { + buff = (guchar *)SvGROW(digest, max_digest_len); + digest_len = purple_cipher_digest_region(name, data, data_len, buff, max_digest_len); + if(digest_len == -1) { SvSetSV_nosteal(digest, &PL_sv_undef); - XSRETURN_UNDEF; + RETVAL = 0; + } else { + SvCUR_set(digest, digest_len); + SvPOK_only(digest); + RETVAL = 1; } - SvCUR_set(digest, RETVAL); - SvPOK_only(digest); OUTPUT: RETVAL @@ -171,110 +173,120 @@ purple_cipher_context_append(Purple::Cipher::Context context, guchar *data, size_t length(data)) PROTOTYPE: $$ -size_t -purple_cipher_context_digest(context, in_len, digest) +gboolean +purple_cipher_context_digest(context, digest) Purple::Cipher::Context context - size_t in_len SV *digest PREINIT: - gboolean ret; guchar *buff = NULL; + size_t digest_size; CODE: + digest_size = purple_cipher_context_get_digest_size(context); SvUPGRADE(digest, SVt_PV); - buff = (guchar *)SvGROW(digest, in_len); - ret = purple_cipher_context_digest(context, in_len, buff, &RETVAL); - if(!ret) { + buff = (guchar *)SvGROW(digest, digest_size); + if (purple_cipher_context_digest(context, buff, digest_size)) { + SvCUR_set(digest, digest_size); + SvPOK_only(digest); + RETVAL = 1; + } else { SvSetSV_nosteal(digest, &PL_sv_undef); - XSRETURN_UNDEF; + RETVAL = 0; } - SvCUR_set(digest, RETVAL); - SvPOK_only(digest); OUTPUT: RETVAL -size_t -purple_cipher_context_digest_to_str(context, in_len, digest_s) +gboolean +purple_cipher_context_digest_to_str(context, digest_s) Purple::Cipher::Context context - size_t in_len SV *digest_s PREINIT: - gboolean ret; gchar *buff = NULL; + size_t digest_size, str_len; CODE: - in_len += 1; /* perl shouldn't need to care about '\0' at the end */ + digest_size = purple_cipher_context_get_digest_size(context); + str_len = 2 * digest_size; SvUPGRADE(digest_s, SVt_PV); - buff = SvGROW(digest_s, in_len); - ret = purple_cipher_context_digest_to_str(context, in_len, buff, &RETVAL); - if(!ret) { + buff = SvGROW(digest_s, str_len + 1); + if (purple_cipher_context_digest_to_str(context, buff, str_len + 1)) { + SvCUR_set(digest_s, str_len); + SvPOK_only(digest_s); + RETVAL = 1; + } else { SvSetSV_nosteal(digest_s, &PL_sv_undef); - XSRETURN_UNDEF; + RETVAL = 0; } - SvCUR_set(digest_s, RETVAL); - SvPOK_only(digest_s); OUTPUT: RETVAL -gint -purple_cipher_context_encrypt(context, data_sv, output, OUTLIST size_t outlen) +gboolean +purple_cipher_context_encrypt(context, input, output) Purple::Cipher::Context context - SV *data_sv + SV *input SV *output - PROTOTYPE: $$$ PREINIT: - size_t datalen; + size_t input_len, output_len; + ssize_t ret; guchar *buff = NULL; guchar *data = NULL; CODE: - data = (guchar *)SvPV(data_sv, datalen); + data = (guchar *)SvPV(input, input_len); + output_len = input_len + purple_cipher_context_get_block_size(context); SvUPGRADE(output, SVt_PV); - buff = (guchar *)SvGROW(output, datalen); - RETVAL = purple_cipher_context_encrypt(context, data, datalen, buff, &outlen); - if(outlen != 0) { + buff = (guchar *)SvGROW(output, output_len); + ret = purple_cipher_context_encrypt(context, data, input_len, buff, output_len); + if (ret >= 0) { + RETVAL = 1; SvPOK_only(output); - SvCUR_set(output, outlen); + SvCUR_set(output, ret); } else { + RETVAL = 0; SvSetSV_nosteal(output, &PL_sv_undef); } OUTPUT: RETVAL -gint -purple_cipher_context_decrypt(context, data_sv, output, OUTLIST size_t outlen) +gboolean +purple_cipher_context_decrypt(context, input, output) Purple::Cipher::Context context - SV *data_sv + SV *input SV *output - PROTOTYPE: $$$ PREINIT: - size_t datalen; + size_t input_len, output_len; + ssize_t ret; guchar *buff = NULL; guchar *data = NULL; CODE: - data = (guchar *)SvPV(data_sv, datalen); + data = (guchar *)SvPV(input, input_len); + output_len = input_len + purple_cipher_context_get_block_size(context); SvUPGRADE(output, SVt_PV); - buff = (guchar *)SvGROW(output, datalen); - RETVAL = purple_cipher_context_decrypt(context, data, datalen, buff, &outlen); - if(outlen != 0) { + buff = (guchar *)SvGROW(output, output_len); + ret = purple_cipher_context_decrypt(context, data, input_len, buff, output_len); + if (ret >= 0) { + RETVAL = 1; SvPOK_only(output); - SvCUR_set(output, outlen); + SvCUR_set(output, ret); } else { + RETVAL = 0; SvSetSV_nosteal(output, &PL_sv_undef); } OUTPUT: RETVAL void -purple_cipher_context_set_salt(context, salt) +purple_cipher_context_set_salt(context, salt, len) Purple::Cipher::Context context guchar *salt + size_t len size_t purple_cipher_context_get_salt_size(context) Purple::Cipher::Context context void -purple_cipher_context_set_key(context, key) +purple_cipher_context_set_key(context, key, len) Purple::Cipher::Context context guchar *key + size_t len size_t purple_cipher_context_get_key_size(context) @@ -302,7 +314,3 @@ Purple::Cipher::Context context Purple::Cipher::BatchMode mode -void -purple_cipher_context_set_key_with_len(Purple::Cipher::Context context, guchar *key, size_t length(key)) - PROTOTYPE: $$ -