Commit 7adfec05 authored by hybrid's avatar hybrid

Start port of aes lib to c++.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2977 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 77405cc5
...@@ -37,13 +37,7 @@ ...@@ -37,13 +37,7 @@
#ifndef _AES_H #ifndef _AES_H
#define _AES_H #define _AES_H
/* This include is used to find 8 & 32 bit unsigned integer types */ #include "irrMath.h"
#include "limits.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define AES_128 /* define if AES with 128 bit keys is needed */ #define AES_128 /* define if AES with 128 bit keys is needed */
#define AES_192 /* define if AES with 192 bit keys is needed */ #define AES_192 /* define if AES with 192 bit keys is needed */
...@@ -53,22 +47,11 @@ extern "C" ...@@ -53,22 +47,11 @@ extern "C"
/* The following must also be set in assembler files if being used */ /* The following must also be set in assembler files if being used */
#define AES_ENCRYPT /* if support for encryption is needed */ #define AES_ENCRYPT /* if support for encryption is needed */
//#define AES_DECRYPT /* if support for decryption is needed */ #define AES_DECRYPT /* if support for decryption is needed */
#define AES_ERR_CHK /* for parameter checks & error return codes */ #define AES_ERR_CHK /* for parameter checks & error return codes */
#if UCHAR_MAX == 0xff /* an unsigned 8 bit type */ typedef irr::u8 aes_08t;
typedef unsigned char aes_08t; typedef irr::u32 aes_32t;
#else
#error Please define aes_08t as an 8-bit unsigned integer type in aes.h
#endif
#if UINT_MAX == 0xffffffff /* an unsigned 32 bit type */
typedef unsigned int aes_32t;
#elif ULONG_MAX == 0xffffffff
typedef unsigned long aes_32t;
#else
#error Please define aes_32t as a 32-bit unsigned integer type in aes.h
#endif
#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ #define AES_BLOCK_SIZE 16 /* the AES block size in bytes */
#define N_COLS 4 /* the number of columns in the state */ #define N_COLS 4 /* the number of columns in the state */
...@@ -101,7 +84,8 @@ void gen_tabs(void); ...@@ -101,7 +84,8 @@ void gen_tabs(void);
#ifdef AES_ENCRYPT #ifdef AES_ENCRYPT
typedef struct typedef struct
{ aes_32t ks[KS_LENGTH]; {
aes_32t ks[KS_LENGTH];
} aes_encrypt_ctx; } aes_encrypt_ctx;
#if defined(AES_128) || defined(AES_VAR) #if defined(AES_128) || defined(AES_VAR)
...@@ -126,7 +110,8 @@ aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx ...@@ -126,7 +110,8 @@ aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx
#ifdef AES_DECRYPT #ifdef AES_DECRYPT
typedef struct typedef struct
{ aes_32t ks[KS_LENGTH]; {
aes_32t ks[KS_LENGTH];
} aes_decrypt_ctx; } aes_decrypt_ctx;
#if defined(AES_128) || defined(AES_VAR) #if defined(AES_128) || defined(AES_VAR)
...@@ -148,8 +133,5 @@ aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]) ...@@ -148,8 +133,5 @@ aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]); aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]);
#endif #endif
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -38,11 +38,6 @@ ...@@ -38,11 +38,6 @@
#include "aesopt.h" #include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
#define so(y,x,c) word_out(y, c, s(x,c)) #define so(y,x,c) word_out(y, c, s(x,c))
...@@ -306,6 +301,3 @@ aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx ...@@ -306,6 +301,3 @@ aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx
#endif #endif
#if defined(__cplusplus)
}
#endif
...@@ -37,11 +37,6 @@ ...@@ -37,11 +37,6 @@
#include "aesopt.h" #include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* Initialise the key schedule from the user supplied key. The key /* Initialise the key schedule from the user supplied key. The key
length can be specified in bytes, with legal values of 16, 24 length can be specified in bytes, with legal values of 16, 24
and 32, or in bits, with legal values of 128, 192 and 256. These and 32, or in bits, with legal values of 128, 192 and 256. These
...@@ -458,6 +453,3 @@ aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]) ...@@ -458,6 +453,3 @@ aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
#endif #endif
#if defined(__cplusplus)
}
#endif
...@@ -727,11 +727,6 @@ ...@@ -727,11 +727,6 @@
#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) #define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c)
#endif #endif
#if defined(__cplusplus)
extern "C"
{
#endif
/* If there are no global variables, the definitions here can be /* If there are no global variables, the definitions here can be
used to put the AES tables in a structure so that a pointer used to put the AES tables in a structure so that a pointer
can then be added to the AES context to pass them to the AES can then be added to the AES context to pass them to the AES
...@@ -1034,8 +1029,4 @@ extern aes_32t t_dec(r,c)[RC_LENGTH]; ...@@ -1034,8 +1029,4 @@ extern aes_32t t_dec(r,c)[RC_LENGTH];
d_4(aes_32t, t_dec(i,m), mm_data, v); d_4(aes_32t, t_dec(i,m), mm_data, v);
#endif #endif
#if defined(__cplusplus)
}
#endif
#endif #endif
...@@ -32,11 +32,6 @@ ...@@ -32,11 +32,6 @@
*/ */
#if defined(__cplusplus)
extern "C"
{
#endif
#define DO_TABLES #define DO_TABLES
#include "aesopt.h" #include "aesopt.h"
...@@ -226,7 +221,3 @@ void gen_tabs(void) ...@@ -226,7 +221,3 @@ void gen_tabs(void)
#endif #endif
#if defined(__cplusplus)
}
#endif
...@@ -62,10 +62,6 @@ ...@@ -62,10 +62,6 @@
#ifndef _BZLIB_H #ifndef _BZLIB_H
#define _BZLIB_H #define _BZLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define BZ_RUN 0 #define BZ_RUN 0
#define BZ_FLUSH 1 #define BZ_FLUSH 1
#define BZ_FINISH 2 #define BZ_FINISH 2
...@@ -310,12 +306,5 @@ BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( ...@@ -310,12 +306,5 @@ BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
); );
#endif #endif
#ifdef __cplusplus
}
#endif
#endif #endif
/*-------------------------------------------------------------*/
/*--- end bzlib.h ---*/
/*-------------------------------------------------------------*/
...@@ -40,17 +40,13 @@ ...@@ -40,17 +40,13 @@
#include "fileenc.h" #include "fileenc.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* subroutine for data encryption/decryption */ /* subroutine for data encryption/decryption */
/* this could be speeded up a lot by aligning */ /* this could be speeded up a lot by aligning */
/* buffers and using 32 bit operations */ /* buffers and using 32 bit operations */
static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1]) static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1])
{ unsigned long i = 0, pos = cx->encr_pos; {
unsigned long i = 0, pos = cx->encr_pos;
while(i < d_len) while(i < d_len)
{ {
...@@ -79,7 +75,8 @@ int fcrypt_init( ...@@ -79,7 +75,8 @@ int fcrypt_init(
unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */
#endif #endif
fcrypt_ctx cx[1]) /* the file encryption context (output) */ fcrypt_ctx cx[1]) /* the file encryption context (output) */
{ unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; {
unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH];
if(pwd_len > MAX_PWD_LENGTH) if(pwd_len > MAX_PWD_LENGTH)
return PASSWORD_TOO_LONG; return PASSWORD_TOO_LONG;
...@@ -92,13 +89,13 @@ int fcrypt_init( ...@@ -92,13 +89,13 @@ int fcrypt_init(
/* initialise the encryption nonce and buffer pos */ /* initialise the encryption nonce and buffer pos */
cx->encr_pos = BLOCK_SIZE; cx->encr_pos = BLOCK_SIZE;
/* if we need a random component in the encryption */ /* if we need a random component in the encryption */
/* nonce, this is where it would have to be set */ /* nonce, this is where it would have to be set */
memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char)); memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char));
/* initialise for authentication */ /* initialise for authentication */
hmac_sha_begin(cx->auth_ctx); hmac_sha_begin(cx->auth_ctx);
/* derive the encryption and authetication keys and the password verifier */ /* derive the encryption and authetication keys and the password verifier */
derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS,
kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH);
/* set the encryption key */ /* set the encryption key */
...@@ -108,10 +105,10 @@ int fcrypt_init( ...@@ -108,10 +105,10 @@ int fcrypt_init(
#ifdef PASSWORD_VERIFIER #ifdef PASSWORD_VERIFIER
memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH);
#endif #endif
/* clear the buffer holding the derived key values */ /* clear the buffer holding the derived key values */
memset(kbuf, 0, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); memset(kbuf, 0, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH);
return GOOD_RETURN; return GOOD_RETURN;
} }
/* perform 'in place' encryption and authentication */ /* perform 'in place' encryption and authentication */
...@@ -133,13 +130,11 @@ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1 ...@@ -133,13 +130,11 @@ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1
/* close encryption/decryption and return the MAC value */ /* close encryption/decryption and return the MAC value */
int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1])
{ unsigned int res = cx->mode; {
unsigned int res = cx->mode;
hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx);
memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */ memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */
return MAC_LENGTH(res); /* return MAC length in bytes */ return MAC_LENGTH(res); /* return MAC length in bytes */
} }
#if defined(__cplusplus)
}
#endif
...@@ -77,15 +77,10 @@ ...@@ -77,15 +77,10 @@
/* the context for file encryption */ /* the context for file encryption */
#if defined(__cplusplus)
extern "C"
{
#endif
typedef struct typedef struct
{ unsigned char nonce[BLOCK_SIZE]; /* the CTR nonce */ { unsigned char nonce[BLOCK_SIZE]; /* the CTR nonce */
unsigned char encr_bfr[BLOCK_SIZE]; /* encrypt buffer */ unsigned char encr_bfr[BLOCK_SIZE]; /* encrypt buffer */
aes_encrypt_ctx encr_ctx[1]; /* encryption context */ aes_encrypt_ctx encr_ctx[1]; /* encryption context */
hmac_ctx auth_ctx[1]; /* authentication context */ hmac_ctx auth_ctx[1]; /* authentication context */
unsigned int encr_pos; /* block position (enc) */ unsigned int encr_pos; /* block position (enc) */
unsigned int pwd_len; /* password length */ unsigned int pwd_len; /* password length */
...@@ -115,8 +110,5 @@ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1 ...@@ -115,8 +110,5 @@ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1
int fcrypt_end(unsigned char mac[], /* the MAC value (output) */ int fcrypt_end(unsigned char mac[], /* the MAC value (output) */
fcrypt_ctx cx[1]); /* the context (input) */ fcrypt_ctx cx[1]); /* the context (input) */
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -35,11 +35,6 @@ ...@@ -35,11 +35,6 @@
#include "hmac.h" #include "hmac.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* initialise the HMAC context to zero */ /* initialise the HMAC context to zero */
void hmac_sha_begin(hmac_ctx cx[1]) void hmac_sha_begin(hmac_ctx cx[1])
{ {
...@@ -140,6 +135,3 @@ void hmac_sha(const unsigned char key[], unsigned long key_len, ...@@ -140,6 +135,3 @@ void hmac_sha(const unsigned char key[], unsigned long key_len,
hmac_sha_end(mac, mac_len, cx); hmac_sha_end(mac, mac_len, cx);
} }
#if defined(__cplusplus)
}
#endif
...@@ -38,10 +38,6 @@ ...@@ -38,10 +38,6 @@
#include <memory.h> #include <memory.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#define USE_SHA1 #define USE_SHA1
#if !defined(USE_SHA1) && !defined(USE_SHA256) #if !defined(USE_SHA1) && !defined(USE_SHA256)
#error define USE_SHA1 or USE_SHA256 to set the HMAC hash algorithm #error define USE_SHA1 or USE_SHA256 to set the HMAC hash algorithm
...@@ -78,7 +74,8 @@ extern "C" ...@@ -78,7 +74,8 @@ extern "C"
#define HMAC_IN_DATA 0xffffffff #define HMAC_IN_DATA 0xffffffff
typedef struct typedef struct
{ unsigned char key[HASH_INPUT_SIZE]; {
unsigned char key[HASH_INPUT_SIZE];
sha_ctx ctx[1]; sha_ctx ctx[1];
unsigned long klen; unsigned long klen;
} hmac_ctx; } hmac_ctx;
...@@ -95,8 +92,5 @@ void hmac_sha(const unsigned char key[], unsigned long key_len, ...@@ -95,8 +92,5 @@ void hmac_sha(const unsigned char key[], unsigned long key_len,
const unsigned char data[], unsigned long data_len, const unsigned char data[], unsigned long data_len,
unsigned char mac[], unsigned long mac_len); unsigned char mac[], unsigned long mac_len);
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -41,11 +41,6 @@ ...@@ -41,11 +41,6 @@
#include <memory.h> #include <memory.h>
#include "prng.h" #include "prng.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* mix a random data pool using the SHA1 compression function (as */ /* mix a random data pool using the SHA1 compression function (as */
/* suggested by Peter Gutmann in his paper on random pools) */ /* suggested by Peter Gutmann in his paper on random pools) */
...@@ -149,7 +144,3 @@ void prng_end(prng_ctx ctx[1]) ...@@ -149,7 +144,3 @@ void prng_end(prng_ctx ctx[1])
memset(ctx, 0, sizeof(prng_ctx)); memset(ctx, 0, sizeof(prng_ctx));
} }
#if defined(__cplusplus)
}
#endif
...@@ -46,11 +46,6 @@ ...@@ -46,11 +46,6 @@
#define PRNG_POOL_SIZE (SHA1_DIGEST_SIZE * (1 + (PRNG_POOL_LEN - 1) / SHA1_DIGEST_SIZE)) #define PRNG_POOL_SIZE (SHA1_DIGEST_SIZE * (1 + (PRNG_POOL_LEN - 1) / SHA1_DIGEST_SIZE))
#if defined(__cplusplus)
extern "C"
{
#endif
/* A function for providing entropy is a parameter in the prng_init() */ /* A function for providing entropy is a parameter in the prng_init() */
/* call. This function has the following form and returns a maximum */ /* call. This function has the following form and returns a maximum */
/* of 'len' bytes of pseudo random data in the buffer 'buf'. It can */ /* of 'len' bytes of pseudo random data in the buffer 'buf'. It can */
...@@ -75,8 +70,5 @@ void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]); ...@@ -75,8 +70,5 @@ void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]);
/* close the random stream generator */ /* close the random stream generator */
void prng_end(prng_ctx ctx[1]); void prng_end(prng_ctx ctx[1]);
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -37,11 +37,6 @@ ...@@ -37,11 +37,6 @@
#include <memory.h> #include <memory.h>
#include "hmac.h" #include "hmac.h"
#if defined(__cplusplus)
extern "C"
{
#endif
void derive_key(const unsigned char pwd[], /* the PASSWORD */ void derive_key(const unsigned char pwd[], /* the PASSWORD */
unsigned int pwd_len, /* and its length */ unsigned int pwd_len, /* and its length */
const unsigned char salt[], /* the SALT and its */ const unsigned char salt[], /* the SALT and its */
...@@ -187,8 +182,5 @@ int main() ...@@ -187,8 +182,5 @@ int main()
return 0; return 0;
} }
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -37,11 +37,6 @@ ...@@ -37,11 +37,6 @@
#ifndef PWD2KEY_H #ifndef PWD2KEY_H
#define PWD2KEY_H #define PWD2KEY_H
#if defined(__cplusplus)
extern "C"
{
#endif
void derive_key( void derive_key(
const unsigned char pwd[], /* the PASSWORD, and */ const unsigned char pwd[], /* the PASSWORD, and */
unsigned int pwd_len, /* its length */ unsigned int pwd_len, /* its length */
...@@ -51,8 +46,5 @@ void derive_key( ...@@ -51,8 +46,5 @@ void derive_key(
unsigned char key[], /* space for the output key */ unsigned char key[], /* space for the output key */
unsigned int key_len); /* and its required length */ unsigned int key_len); /* and its required length */
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -39,11 +39,6 @@ ...@@ -39,11 +39,6 @@
#include "sha1.h" #include "sha1.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* /*
To obtain the highest speed on processors with 32-bit words, this code To obtain the highest speed on processors with 32-bit words, this code
needs to determine the order in which bytes are packed into such words. needs to determine the order in which bytes are packed into such words.
...@@ -318,6 +313,3 @@ void sha1(unsigned char hval[], const unsigned char data[], unsigned long len) ...@@ -318,6 +313,3 @@ void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
} }
#if defined(__cplusplus)
}
#endif
...@@ -39,11 +39,6 @@ ...@@ -39,11 +39,6 @@
#define SHA1_BLOCK_SIZE 64 #define SHA1_BLOCK_SIZE 64
#define SHA1_DIGEST_SIZE 20 #define SHA1_DIGEST_SIZE 20
#if defined(__cplusplus)
extern "C"
{
#endif
/* define an unsigned 32-bit type */ /* define an unsigned 32-bit type */
#if UINT_MAX == 0xffffffff #if UINT_MAX == 0xffffffff
...@@ -69,8 +64,5 @@ void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]); ...@@ -69,8 +64,5 @@ void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]); void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len); void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif #endif
#endif
...@@ -86,11 +86,6 @@ ...@@ -86,11 +86,6 @@
#include "sha2.h" #include "sha2.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* PLATFORM SPECIFIC INCLUDES */ /* PLATFORM SPECIFIC INCLUDES */
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ ) #if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
...@@ -706,8 +701,3 @@ sha2_int sha2(unsigned char hval[], unsigned long size, ...@@ -706,8 +701,3 @@ sha2_int sha2(unsigned char hval[], unsigned long size,
#endif #endif
#if defined(__cplusplus)
}
#endif
...@@ -80,11 +80,6 @@ ...@@ -80,11 +80,6 @@
#endif #endif
#endif #endif
#if defined(__cplusplus)
extern "C"
{
#endif
#define SHA256_DIGEST_SIZE 32 #define SHA256_DIGEST_SIZE 32
#define SHA384_DIGEST_SIZE 48 #define SHA384_DIGEST_SIZE 48
#define SHA512_DIGEST_SIZE 64 #define SHA512_DIGEST_SIZE 64
...@@ -157,8 +152,5 @@ sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[ ...@@ -157,8 +152,5 @@ sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[
sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
sha2_int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len); sha2_int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif #endif
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment