pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Better fix for this
2016-12-12, Gary Kramlich
ee5f6e1f76bb
Better fix for this
/*
* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
"internal.h"
#include
"glibcompat.h"
#include
"rc4cipher.h"
/*******************************************************************************
* Structs
******************************************************************************/
#define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate))
typedef
struct
{
guchar
state
[
256
];
guchar
x
;
guchar
y
;
gint
key_len
;
}
PurpleRC4CipherPrivate
;
/******************************************************************************
* Enums
*****************************************************************************/
enum
{
PROP_ZERO
,
PROP_KEY_LEN
,
PROP_KEY
,
PROP_LAST
,
};
/******************************************************************************
* Globals
*****************************************************************************/
static
GObjectClass
*
parent_class
=
NULL
;
static
GParamSpec
*
properties
[
PROP_LAST
];
/******************************************************************************
* Cipher Stuff
*****************************************************************************/
static
void
purple_rc4_cipher_reset
(
PurpleCipher
*
cipher
)
{
PurpleRC4Cipher
*
rc4_cipher
=
PURPLE_RC4_CIPHER
(
cipher
);
PurpleRC4CipherPrivate
*
priv
=
PURPLE_RC4_CIPHER_GET_PRIVATE
(
rc4_cipher
);
guint
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
priv
->
state
[
i
]
=
i
;
priv
->
x
=
0
;
priv
->
y
=
0
;
/* default is 5 bytes (40bit key) */
priv
->
key_len
=
5
;
}
static
void
purple_rc4_cipher_set_key
(
PurpleCipher
*
cipher
,
const
guchar
*
key
,
size_t
len
)
{
PurpleRC4Cipher
*
rc4_cipher
=
PURPLE_RC4_CIPHER
(
cipher
);
PurpleRC4CipherPrivate
*
priv
=
PURPLE_RC4_CIPHER_GET_PRIVATE
(
rc4_cipher
);
guchar
*
state
;
guchar
temp_swap
;
guchar
x
,
y
;
guint
i
;
x
=
0
;
y
=
0
;
state
=
&
priv
->
state
[
0
];
priv
->
key_len
=
len
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
y
=
(
key
[
x
]
+
state
[
i
]
+
y
)
%
256
;
temp_swap
=
state
[
i
];
state
[
i
]
=
state
[
y
];
state
[
y
]
=
temp_swap
;
x
=
(
x
+
1
)
%
len
;
}
g_object_notify_by_pspec
(
G_OBJECT
(
cipher
),
properties
[
PROP_KEY
]);
}
static
ssize_t
purple_rc4_cipher_encrypt
(
PurpleCipher
*
cipher
,
const
guchar
input
[],
size_t
in_len
,
guchar
output
[],
size_t
out_size
)
{
PurpleRC4Cipher
*
rc4_cipher
=
PURPLE_RC4_CIPHER
(
cipher
);
guchar
temp_swap
;
guchar
x
,
y
,
z
;
guchar
*
state
;
guint
i
;
PurpleRC4CipherPrivate
*
priv
=
PURPLE_RC4_CIPHER_GET_PRIVATE
(
rc4_cipher
);
x
=
priv
->
x
;
y
=
priv
->
y
;
state
=
&
priv
->
state
[
0
];
for
(
i
=
0
;
i
<
in_len
;
i
++
)
{
x
=
(
x
+
1
)
%
256
;
y
=
(
state
[
x
]
+
y
)
%
256
;
temp_swap
=
state
[
x
];
state
[
x
]
=
state
[
y
];
state
[
y
]
=
temp_swap
;
z
=
state
[
x
]
+
(
state
[
y
])
%
256
;
output
[
i
]
=
input
[
i
]
^
state
[
z
];
}
priv
->
x
=
x
;
priv
->
y
=
y
;
return
in_len
;
}
/******************************************************************************
* Object Stuff
*****************************************************************************/
static
void
purple_rc4_cipher_set_property
(
GObject
*
obj
,
guint
param_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleCipher
*
cipher
=
PURPLE_CIPHER
(
obj
);
PurpleRC4Cipher
*
rc4_cipher
=
PURPLE_RC4_CIPHER
(
obj
);
switch
(
param_id
)
{
case
PROP_KEY_LEN
:
purple_rc4_cipher_set_key_len
(
rc4_cipher
,
g_value_get_int
(
value
));
break
;
case
PROP_KEY
:
{
guchar
*
key
=
(
guchar
*
)
g_value_get_string
(
value
);
purple_rc4_cipher_set_key
(
cipher
,
key
,
strlen
((
gchar
*
)
key
));
}
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
static
void
purple_rc4_cipher_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleRC4Cipher
*
rc4_cipher
=
PURPLE_RC4_CIPHER
(
obj
);
switch
(
param_id
)
{
case
PROP_KEY_LEN
:
g_value_set_int
(
value
,
purple_rc4_cipher_get_key_len
(
rc4_cipher
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
static
void
purple_rc4_cipher_class_init
(
PurpleRC4CipherClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
PurpleCipherClass
*
cipher_class
=
PURPLE_CIPHER_CLASS
(
klass
);
parent_class
=
g_type_class_peek_parent
(
klass
);
obj_class
->
set_property
=
purple_rc4_cipher_set_property
;
obj_class
->
get_property
=
purple_rc4_cipher_get_property
;
cipher_class
->
reset
=
purple_rc4_cipher_reset
;
cipher_class
->
encrypt
=
purple_rc4_cipher_encrypt
;
cipher_class
->
set_key
=
purple_rc4_cipher_set_key
;
g_type_class_add_private
(
klass
,
sizeof
(
PurpleRC4CipherPrivate
));
properties
[
PROP_KEY_LEN
]
=
g_param_spec_int
(
"key-len"
,
"key-len"
,
"key-len"
,
G_MININT
,
G_MAXINT
,
0
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_KEY
]
=
g_param_spec_string
(
"key"
,
"key"
,
"key"
,
NULL
,
G_PARAM_WRITABLE
|
G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties
(
obj_class
,
PROP_LAST
,
properties
);
}
static
void
purple_rc4_cipher_init
(
PurpleCipher
*
cipher
)
{
purple_rc4_cipher_reset
(
cipher
);
}
/******************************************************************************
* API
*****************************************************************************/
GType
purple_rc4_cipher_get_type
(
void
)
{
static
GType
type
=
0
;
if
(
type
==
0
)
{
static
const
GTypeInfo
info
=
{
sizeof
(
PurpleRC4CipherClass
),
NULL
,
NULL
,
(
GClassInitFunc
)
purple_rc4_cipher_class_init
,
NULL
,
NULL
,
sizeof
(
PurpleRC4Cipher
),
0
,
(
GInstanceInitFunc
)
purple_rc4_cipher_init
,
NULL
,
};
type
=
g_type_register_static
(
PURPLE_TYPE_CIPHER
,
"PurpleRC4Cipher"
,
&
info
,
0
);
}
return
type
;
}
PurpleCipher
*
purple_rc4_cipher_new
(
void
)
{
return
g_object_new
(
PURPLE_TYPE_RC4_CIPHER
,
NULL
);
}
void
purple_rc4_cipher_set_key_len
(
PurpleRC4Cipher
*
rc4_cipher
,
gint
key_len
)
{
PurpleRC4CipherPrivate
*
priv
;
g_return_if_fail
(
PURPLE_IS_RC4_CIPHER
(
rc4_cipher
));
priv
=
PURPLE_RC4_CIPHER_GET_PRIVATE
(
rc4_cipher
);
priv
->
key_len
=
key_len
;
g_object_notify_by_pspec
(
G_OBJECT
(
rc4_cipher
),
properties
[
PROP_KEY_LEN
]);
}
gint
purple_rc4_cipher_get_key_len
(
PurpleRC4Cipher
*
rc4_cipher
)
{
PurpleRC4CipherPrivate
*
priv
;
g_return_val_if_fail
(
PURPLE_IS_RC4_CIPHER
(
rc4_cipher
),
0
);
priv
=
PURPLE_RC4_CIPHER_GET_PRIVATE
(
rc4_cipher
);
return
priv
->
key_len
;
}