Index: uspace/lib/crypto/Makefile
===================================================================
--- uspace/lib/crypto/Makefile	(revision 1dcc0b9aaf9f79f759ef62cc27bccd9e6b7c8d80)
+++ uspace/lib/crypto/Makefile	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -32,5 +32,6 @@
 SOURCES = \
 	crypto.c \
-	aes.c
+	aes.c \
+	rc4.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/crypto/aes.c
===================================================================
--- uspace/lib/crypto/aes.c	(revision 1dcc0b9aaf9f79f759ef62cc27bccd9e6b7c8d80)
+++ uspace/lib/crypto/aes.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -29,10 +29,10 @@
 /** @file aes.c
  * 
- * Implementation of AES algorithm.
+ * Implementation of AES-128 symmetric cipher cryptographic algorithm.
  * 
  * Based on FIPS 197.
  */
 
-#include <stdio.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <mem.h>
@@ -60,5 +60,5 @@
 
 /* Precomputed values for AES sub_byte transformation. */
-static const uint8_t sub_byte_array[BLOCK_LEN][BLOCK_LEN] = {
+static const uint8_t sbox[BLOCK_LEN][BLOCK_LEN] = {
 	{
 		0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 
@@ -128,5 +128,5 @@
 
 /* Precomputed values for AES inv_sub_byte transformation. */
-static uint8_t inv_sub_byte_array[BLOCK_LEN][BLOCK_LEN] = {
+static uint8_t inv_sbox[BLOCK_LEN][BLOCK_LEN] = {
 	{
 		0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 
@@ -202,4 +202,12 @@
 };
 
+/**
+ * Perform substitution transformation on given byte.
+ * 
+ * @param byte Input byte.
+ * @param inv Flag indicating whether to use inverse table.
+ * 
+ * @return Substituted value.
+ */
 static uint8_t sub_byte(uint8_t byte, bool inv)
 {
@@ -208,10 +216,16 @@
 	
 	if(!inv) {
-		return sub_byte_array[i][j];
+		return sbox[i][j];
 	} else {
-		return inv_sub_byte_array[i][j];
-	}
-}
-
+		return inv_sbox[i][j];
+	}
+}
+
+/**
+ * Perform substitution transformation on state table.
+ * 
+ * @param state State table to be modified.
+ * @param inv Flag indicating whether to use inverse table.
+ */
 static void sub_bytes(uint8_t state[ELEMS][ELEMS], bool inv)
 {
@@ -226,4 +240,9 @@
 }
 
+/**
+ * Perform shift rows transformation on state table.
+ * 
+ * @param state State table to be modified.
+ */
 static void shift_rows(uint8_t state[ELEMS][ELEMS])
 {
@@ -237,4 +256,9 @@
 }
 
+/**
+ * Perform inverted shift rows transformation on state table.
+ * 
+ * @param state State table to be modified.
+ */
 static void inv_shift_rows(uint8_t state[ELEMS][ELEMS])
 {
@@ -248,4 +272,12 @@
 }
 
+/**
+ * Multiplication in GF(2^8).
+ * 
+ * @param x First factor.
+ * @param y Second factor.
+ * 
+ * @return Multiplication of given factors in GF(2^8).
+ */
 static uint8_t galois_mult(uint8_t x, uint8_t y) {
         uint8_t result = 0;
@@ -265,4 +297,9 @@
 }
 
+/**
+ * Perform mix columns transformation on state table.
+ * 
+ * @param state State table to be modified.
+ */
 static void mix_columns(uint8_t state[ELEMS][ELEMS])
 {
@@ -294,4 +331,9 @@
 }
 
+/**
+ * Perform inverted mix columns transformation on state table.
+ * 
+ * @param state State table to be modified.
+ */
 static void inv_mix_columns(uint8_t state[ELEMS][ELEMS])
 {
@@ -323,4 +365,10 @@
 }
 
+/**
+ * Perform round key transformation on state table.
+ * 
+ * @param state State table to be modified.
+ * @param round_key Round key to be applied on state table.
+ */
 static void add_round_key(uint8_t state[ELEMS][ELEMS], uint32_t *round_key)
 {
@@ -338,4 +386,11 @@
 }
 
+/**
+ * Perform substitution transformation on given word.
+ * 
+ * @param byte Input word.
+ * 
+ * @return Substituted word.
+ */
 static uint32_t sub_word(uint32_t word)
 {
@@ -350,4 +405,11 @@
 }
 
+/**
+ * Perform left rotation by one byte on given word.
+ * 
+ * @param byte Input word.
+ * 
+ * @return Rotated word.
+ */
 static uint32_t rot_word(uint32_t word)
 {
@@ -355,4 +417,10 @@
 }
 
+/**
+ * Key expansion procedure for AES algorithm.
+ * 
+ * @param key Input key.
+ * @param key_exp Result key expansion.
+ */
 static void key_expansion(uint8_t *key, uint32_t *key_exp)
 {
@@ -379,4 +447,14 @@
 }
 
+/**
+ * AES-128 encryption algorithm.
+ * 
+ * @param key Input key.
+ * @param input Input data sequence to be encrypted.
+ * @param output Encrypted data sequence.
+ * 
+ * @return EINVAL when input or key not specified, ENOMEM when pointer for 
+ * output is not allocated, otherwise EOK.  
+ */
 int aes_encrypt(uint8_t *key, uint8_t *input, uint8_t *output)
 {
@@ -404,15 +482,5 @@
 	for(size_t k = 1; k <= ROUNDS; k++) {
 		sub_bytes(state, false);
-		for(size_t i = 0; i < ELEMS; i++) {
-			for(size_t j = 0; j < ELEMS; j++) {
-				printf("STATE SUB %d %d : %x\n", i, j, state[i][j]);
-			}
-		}
 		shift_rows(state);
-		for(size_t i = 0; i < ELEMS; i++) {
-			for(size_t j = 0; j < ELEMS; j++) {
-				printf("STATE SHIFT %d %d : %x\n", i, j, state[i][j]);
-			}
-		}
 		if(k < ROUNDS)
 			mix_columns(state);
@@ -430,4 +498,14 @@
 }
 
+/**
+ * AES-128 decryption algorithm.
+ * 
+ * @param key Input key.
+ * @param input Input data sequence to be decrypted.
+ * @param output Decrypted data sequence.
+ * 
+ * @return EINVAL when input or key not specified, ENOMEM when pointer for 
+ * output is not allocated, otherwise EOK.  
+ */
 int aes_decrypt(uint8_t *key, uint8_t *input, uint8_t *output)
 {
Index: uspace/lib/crypto/crypto.c
===================================================================
--- uspace/lib/crypto/crypto.c	(revision 1dcc0b9aaf9f79f759ef62cc27bccd9e6b7c8d80)
+++ uspace/lib/crypto/crypto.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -40,81 +40,170 @@
 #include "crypto.h"
 
-typedef int (*HASH_FUNC)(uint8_t*, size_t, uint8_t*);
-
+/* Hash function procedure definition. */
+typedef void (*HASH_FUNC)(uint32_t*, uint32_t*);
+
+/* Length of HMAC block. */
+#define HMAC_BLOCK_LENGTH 64
+
+/* Ceiling for UINT32. */
 #define ceil_uint32(val) (((val) - (uint32_t)(val)) > 0 ? \
 	(uint32_t)((val) + 1) : (uint32_t)(val))
+
+/* Floor for UINT32. */
 #define floor_uint32(val) (((val) - (uint32_t)(val)) < 0 ? \
 	(uint32_t)((val) - 1) : (uint32_t)(val))
+
+/* Left rotation for UINT32. */
 #define rotl_uint32(val, shift) (((val) << shift) | ((val) >> (32 - shift)))
+
+/* Pick value at specified index from array or zero if out of bounds. */
 #define get_at(input, size, i) (i < size ? input[i] : 0)
 
-/**
- * Setup hash function properties for use in crypto functions.
- * 
+/* Init values used in SHA1 and MD5 functions. */
+static const uint32_t hash_init[] = {
+	0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
+};
+
+/* Shift amount array for MD5 algorithm. */
+static const uint32_t md5_shift[] = {
+	7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
+	5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
+	4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
+	6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21
+};
+
+/* Substitution box for MD5 algorithm. */
+static const uint32_t md5_sbox[] = {
+	0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+	0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+	0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+	0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+	0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+	0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+	0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+	0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+	0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+	0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+	0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+	0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+	0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+	0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+	0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+	0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+/**
+ * Working procedure of MD5 cryptographic hash function.
+ * 
+ * @param h Working array with interim hash parts values.
+ * @param sched_arr Input array with scheduled values from input string.
+ */
+static void md5_proc(uint32_t *h, uint32_t *sched_arr)
+{
+	uint32_t f, g, temp;
+	uint32_t w[HASH_MD5/4];
+	
+	memcpy(w, h, (HASH_MD5/4) * sizeof(uint32_t));
+	
+	for(size_t k = 0; k < 64; k++) {
+		if(k < 16) {
+			f = (w[1] & w[2]) | (~w[1] & w[3]);
+			g = k;
+		} else if(k >= 16 && k < 32) {
+			f = (w[1] & w[3]) | (w[2] & ~w[3]);
+			g = (5*k + 1) % 16;
+		} else if(k >= 32 && k < 48) {
+			f = w[1] ^ w[2] ^ w[3];
+			g = (3*k + 5) % 16;
+		} else {
+			f = w[2] ^ (w[1] | ~w[3]);
+			g = 7*k % 16;
+		}
+		temp = w[3];
+		w[3] = w[2];
+		w[2] = w[1];
+		w[1] += rotl_uint32(w[0] + f + md5_sbox[k] + 
+			uint32_t_byteorder_swap(sched_arr[g]),	
+			md5_shift[k]);
+		w[0] = temp;
+	}
+	
+	for(uint8_t k = 0; k < HASH_MD5/4; k++)
+		h[k] += w[k];
+}
+
+/**
+ * Working procedure of SHA-1 cryptographic hash function.
+ * 
+ * @param h Working array with interim hash parts values.
+ * @param sched_arr Input array with scheduled values from input string.
+ */
+static void sha1_proc(uint32_t *h, uint32_t *sched_arr)
+{
+	uint32_t f, cf, temp;
+	uint32_t w[HASH_SHA1/4];
+	
+	for(size_t k = 16; k < 80; k++) {
+		sched_arr[k] = rotl_uint32(
+			sched_arr[k-3] ^
+			sched_arr[k-8] ^
+			sched_arr[k-14] ^
+			sched_arr[k-16], 
+			1);
+	}
+
+	memcpy(w, h, (HASH_SHA1/4) * sizeof(uint32_t));
+	
+	for(size_t k = 0; k < 80; k++) {
+		if(k < 20) {
+			f = (w[1] & w[2]) | (~w[1] & w[3]);
+			cf = 0x5A827999;
+		} else if(k >= 20 && k < 40) {
+			f = w[1] ^ w[2] ^ w[3];
+			cf = 0x6ED9EBA1;
+		} else if(k >= 40 && k < 60) {
+			f = (w[1] & w[2]) | (w[1] & w[3]) | (w[2] & w[3]);
+			cf = 0x8F1BBCDC;
+		} else {
+			f = w[1] ^ w[2] ^ w[3];
+			cf = 0xCA62C1D6;
+		}
+
+		temp = rotl_uint32(w[0], 5) + f + w[4] + cf + sched_arr[k];
+
+		w[4] = w[3];
+		w[3] = w[2];
+		w[2] = rotl_uint32(w[1], 30);
+		w[1] = w[0];
+		w[0] = temp;
+	}
+
+	for(uint8_t k = 0; k < HASH_SHA1/4; k++)
+		h[k] += w[k];
+}
+
+/**
+ * Create hash based on selected algorithm.
+ * 
+ * @param input Input message byte sequence.
+ * @param input_size Size of message sequence.
+ * @param output Result hash byte sequence.
  * @param hash_sel Hash function selector.
- * @param hash_func Output parameter where hash function pointer is stored.
- * @param hash_length Output parameter for setup result hash length.
- */
-static void config_hash_func(hash_func_t hash_sel, HASH_FUNC *hash_func,
-	size_t *hash_length)
-{
-	switch(hash_sel) {
-		case HASH_MD5:
-			if(hash_func) *hash_func = md5;
-			*hash_length = MD5_HASH_LENGTH;
-			break;
-		case HASH_SHA1:
-			if(hash_func) *hash_func = sha1;
-			*hash_length = SHA1_HASH_LENGTH;
-			break;
-	}
-}
-
-/**
- * MD5 cryptographic hash function.
- * 
- * @param input Input sequence to be encrypted.
- * @param input_size Size of input sequence.
- * @param hash Output parameter for result hash (32 byte value).
- * 
- * @return EINVAL when input not specified, ENOMEM when pointer for output
- * hash result is not allocated, otherwise EOK.
- */
-int md5(uint8_t *input, size_t input_size, uint8_t *hash)
+ * 
+ * @return EINVAL when input not specified, ENOMEM when pointer for 
+ * output hash result is not allocated, otherwise EOK. 
+ */
+int create_hash(uint8_t *input, size_t input_size, uint8_t *output,
+	hash_func_t hash_sel)
 {
 	if(!input)
 		return EINVAL;
 	
-	if(!hash)
+	if(!output)
 		return ENOMEM;
 	
-	// TODO
-	
-	return EOK;
-}
-
-/**
- * SHA-1 cryptographic hash function.
- * 
- * @param input Input sequence to be encrypted.
- * @param input_size Size of input sequence.
- * @param hash Output parameter for result hash (20 byte value).
- * 
- * @return EINVAL when input not specified, ENOMEM when pointer for output
- * hash result is not allocated, otherwise EOK.
- */
-int sha1(uint8_t *input, size_t input_size, uint8_t *hash)
-{
-	if(!input)
-		return EINVAL;
-	
-	if(!hash)
-		return ENOMEM;
-	
-	uint32_t a, b, c, d, e, f, cf, temp;
-	uint32_t h[5] = {
-		0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
-	};
-	
+	HASH_FUNC hash_func = (hash_sel == HASH_MD5) ? md5_proc : sha1_proc;
+	
+	/* Prepare scheduled input. */
 	uint8_t work_input[input_size + 1];
 	memcpy(work_input, input, input_size);
@@ -122,6 +211,5 @@
 	
 	size_t blocks = ceil_uint32((((double)input_size + 1) / 4 + 2) / 16);
-	
-	uint32_t work_arr[blocks * 16 * sizeof(uint32_t)];
+	uint32_t work_arr[blocks * 16];
 	for(size_t i = 0; i < blocks; i++) {
 		for(size_t j = 0; j < 16; j++) {
@@ -134,8 +222,15 @@
 	}
 	
-	work_arr[(blocks - 1) * 16 + 14] = (uint64_t)(input_size * 8) >> 32;
-	work_arr[(blocks - 1) * 16 + 15] = (input_size * 8) & 0xFFFFFFFF;
-
-	uint32_t sched_arr[80 * sizeof(uint32_t)];
+	uint64_t bits_size = (uint64_t)(input_size * 8);
+	if(hash_sel == HASH_MD5)
+		bits_size = uint64_t_byteorder_swap(bits_size);
+	
+	work_arr[(blocks - 1) * 16 + 14] = bits_size >> 32;
+	work_arr[(blocks - 1) * 16 + 15] = bits_size & 0xFFFFFFFF;
+	
+	/* Hash computation. */
+	uint32_t h[hash_sel/4];
+	memcpy(h, hash_init, (hash_sel/4) * sizeof(uint32_t));
+	uint32_t sched_arr[80];
 	for(size_t i = 0; i < blocks; i++) {
 		for(size_t k = 0; k < 16; k++) {
@@ -143,51 +238,12 @@
 		}
 		
-		for(size_t k = 16; k < 80; k++) {
-			sched_arr[k] = 
-				rotl_uint32(
-				sched_arr[k-3] ^
-				sched_arr[k-8] ^
-				sched_arr[k-14] ^
-				sched_arr[k-16], 
-				1);
-		}
-		
-		a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4];
-		
-		for(size_t k = 0; k < 80; k++) {
-			if(k < 20) {
-				f = (b & c) | (~b & d);
-				cf = 0x5A827999;
-			} else if(k >= 20 && k < 40) {
-				f = b ^ c ^ d;
-				cf = 0x6ED9EBA1;
-			} else if(k >= 40 && k < 60) {
-				f = (b & c) | (b & d) | (c & d);
-				cf = 0x8F1BBCDC;
-			} else {
-				f = b ^ c ^ d;
-				cf = 0xCA62C1D6;
-			}
-				
-			temp = (rotl_uint32(a, 5) + f + e + cf + sched_arr[k]) &
-				0xFFFFFFFF;
-			
-			e = d;
-			d = c;
-			c = rotl_uint32(b, 30);
-			b = a;
-			a = temp;
-		}
-		
-		h[0] = (h[0] + a) & 0xFFFFFFFF;
-		h[1] = (h[1] + b) & 0xFFFFFFFF;
-		h[2] = (h[2] + c) & 0xFFFFFFFF;
-		h[3] = (h[3] + d) & 0xFFFFFFFF;
-		h[4] = (h[4] + e) & 0xFFFFFFFF;
-	}
-	
-	for(size_t i = 0; i < 5; i++) {
-		h[i] = uint32_t_be2host(h[i]);
-		memcpy(hash + i*sizeof(uint32_t), &h[i], sizeof(uint32_t));
+		hash_func(h, sched_arr);
+	}
+	
+	/* Copy hash parts into final result. */
+	for(size_t i = 0; i < hash_sel/4; i++) {
+		if(hash_sel == HASH_SHA1)
+			h[i] = uint32_t_byteorder_swap(h[i]);
+		memcpy(output + i*sizeof(uint32_t), &h[i], sizeof(uint32_t));
 	}
 	
@@ -217,16 +273,12 @@
 		return ENOMEM;
 	
-	size_t hash_length = 0;
-	HASH_FUNC hash_func = NULL;
-	config_hash_func(hash_sel, &hash_func, &hash_length);
-	
 	uint8_t work_key[HMAC_BLOCK_LENGTH];
 	uint8_t o_key_pad[HMAC_BLOCK_LENGTH];
 	uint8_t i_key_pad[HMAC_BLOCK_LENGTH];
-	uint8_t temp_hash[hash_length];
+	uint8_t temp_hash[hash_sel];
 	memset(work_key, 0, HMAC_BLOCK_LENGTH);
 	
 	if(key_size > HMAC_BLOCK_LENGTH) {
-		hash_func(key, key_size, work_key);
+		create_hash(key, key_size, work_key, hash_sel);
 	} else {
 		memcpy(work_key, key, key_size);
@@ -242,10 +294,11 @@
 	memcpy(temp_work + HMAC_BLOCK_LENGTH, msg, msg_size);
 	
-	hash_func(temp_work, HMAC_BLOCK_LENGTH + msg_size, temp_hash);
+	create_hash(temp_work, HMAC_BLOCK_LENGTH + msg_size, temp_hash, 
+		hash_sel);
 	
 	memcpy(temp_work, o_key_pad, HMAC_BLOCK_LENGTH);
-	memcpy(temp_work + HMAC_BLOCK_LENGTH, temp_hash, hash_length);
-	
-	hash_func(temp_work, HMAC_BLOCK_LENGTH + hash_length, hash);
+	memcpy(temp_work + HMAC_BLOCK_LENGTH, temp_hash, hash_sel);
+	
+	create_hash(temp_work, HMAC_BLOCK_LENGTH + hash_sel, hash, hash_sel);
 	
 	return EOK;
@@ -276,13 +329,10 @@
 		return ENOMEM;
 	
-	size_t hash_length = 0;
-	config_hash_func(hash_sel, NULL, &hash_length);
-
 	uint8_t work_salt[salt_size + sizeof(uint32_t)];
 	memcpy(work_salt, salt, salt_size);
-	uint8_t work_hmac[hash_length];
-	uint8_t temp_hmac[hash_length];
-	uint8_t xor_hmac[hash_length];
-	uint8_t temp_hash[hash_length*2];
+	uint8_t work_hmac[hash_sel];
+	uint8_t temp_hmac[hash_sel];
+	uint8_t xor_hmac[hash_sel];
+	uint8_t temp_hash[hash_sel*2];
 	
 	for(size_t i = 0; i < 2; i++) {
@@ -291,14 +341,14 @@
 		hmac(pass, pass_size, work_salt, salt_size + sizeof(uint32_t),
 			work_hmac, hash_sel);
-		memcpy(xor_hmac, work_hmac, hash_length);
+		memcpy(xor_hmac, work_hmac, hash_sel);
 		for(size_t k = 1; k < 4096; k++) {
-			memcpy(temp_hmac, work_hmac, hash_length);
-			hmac(pass, pass_size, temp_hmac, hash_length, 
+			memcpy(temp_hmac, work_hmac, hash_sel);
+			hmac(pass, pass_size, temp_hmac, hash_sel, 
 				work_hmac, hash_sel);
-			for(size_t t = 0; t < hash_length; t++) {
+			for(size_t t = 0; t < hash_sel; t++) {
 				xor_hmac[t] ^= work_hmac[t];
 			}
 		}
-		memcpy(temp_hash + i*hash_length, xor_hmac, hash_length);
+		memcpy(temp_hash + i*hash_sel, xor_hmac, hash_sel);
 	}
 	
Index: uspace/lib/crypto/crypto.h
===================================================================
--- uspace/lib/crypto/crypto.h	(revision 1dcc0b9aaf9f79f759ef62cc27bccd9e6b7c8d80)
+++ uspace/lib/crypto/crypto.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -33,19 +33,18 @@
 
 #define AES_CIPHER_LENGTH 16
-#define MD5_HASH_LENGTH 16
-#define SHA1_HASH_LENGTH 20
-#define HMAC_BLOCK_LENGTH 64
 #define PBKDF2_KEY_LENGTH 32
 
-/** Hash function selector. */
+/** Hash function selector and also result hash length indicator. */
 typedef enum {
-	HASH_MD5,
-	HASH_SHA1
+	HASH_MD5 =	16,
+	HASH_SHA1 =	20
 } hash_func_t;
 
+extern int rc4(uint8_t *key, size_t key_size, uint8_t *input, 
+	size_t input_size, uint8_t *output);
 extern int aes_encrypt(uint8_t *key, uint8_t *input, uint8_t *output);
 extern int aes_decrypt(uint8_t *key, uint8_t *input, uint8_t *output);
-extern int sha1(uint8_t *input, size_t input_size, uint8_t *hash);
-extern int md5(uint8_t *input, size_t input_size, uint8_t *hash);
+extern int create_hash(uint8_t *input, size_t input_size, uint8_t *output, 
+	hash_func_t hash_sel);
 extern int hmac(uint8_t *key, size_t key_size, uint8_t *msg, size_t msg_size, 
 	uint8_t *hash, hash_func_t hash_sel);
Index: uspace/lib/crypto/rc4.c
===================================================================
--- uspace/lib/crypto/rc4.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/crypto/rc4.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file rc4.c
+ * 
+ * Implementation of ARC4 symmetric cipher cryptographic algorithm.
+ * 
+ */
+
+#include <errno.h>
+#include <mem.h>
+
+#include "crypto.h"
+
+/* Sbox table size. */
+#define SBOX_SIZE 256
+
+/**
+ * Swap two values in sbox.
+ * 
+ * @param i First index of value in sbox to be swapped.
+ * @param j Second index of value in sbox to be swapped.
+ * @param sbox Sbox to be modified.
+ */
+static void swap(size_t i, size_t j, uint8_t *sbox)
+{
+	uint8_t temp = sbox[i];
+	sbox[i] = sbox[j];
+	sbox[j] = temp;
+}
+
+/**
+ * Sbox initialization procedure.
+ * 
+ * @param key Input key.
+ * @param key_size Size of key sequence.
+ * @param sbox Place for result sbox.
+ */
+static void create_sbox(uint8_t *key, size_t key_size, uint8_t *sbox)
+{
+	for(size_t i = 0; i < SBOX_SIZE; i++) {
+		sbox[i] = i;
+	}
+	
+	uint8_t j = 0;
+	for(size_t i = 0; i < SBOX_SIZE; i++) {
+		j = j + sbox[i] + key[i % key_size];
+		swap(i, j, sbox);
+	}
+}
+
+/**
+ * ARC4 encryption/decryption algorithm.
+ * 
+ * @param key Input key.
+ * @param key_size Size of key sequence.
+ * @param input Input data sequence to be processed.
+ * @param input_size Size of input data sequence.
+ * @param output Result data sequence.
+ * 
+ * @return EINVAL when input or key not specified, ENOMEM when pointer for 
+ * output is not allocated, otherwise EOK.  
+ */
+int rc4(uint8_t *key, size_t key_size, uint8_t *input, size_t input_size, 
+	uint8_t *output)
+{
+	if(!key || !input)
+		return EINVAL;
+	
+	if(!output)
+		return ENOMEM;
+	
+	/* Initialize sbox. */
+	uint8_t sbox[SBOX_SIZE];
+	create_sbox(key, key_size, sbox);
+	
+	/* Processing loop. */
+	uint8_t i = 0, j = 0, val;
+	for(size_t k = 0; k < input_size; k++) {
+		i = i+1;
+		j = j + sbox[i];
+		swap(i, j, sbox);
+		val = sbox[sbox[i] + sbox[j]];
+		output[k] = val ^ input[k];
+	}
+	
+	return EOK;
+}
