Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorvald Natvig <slicer@users.sourceforge.net>2007-08-04 21:08:38 +0400
committerThorvald Natvig <slicer@users.sourceforge.net>2007-08-04 21:08:38 +0400
commit7ed5e47f6f0ae0085af4c5c7cf96d15fd97b884b (patch)
tree631f5397c5adcae95fe1b2da0f5d4869e9189815 /src/CryptState.cpp
parenta6376f88941e6151ad5ea1dbb03a2fc23b3b7ce5 (diff)
Testing UDP crypt
git-svn-id: https://mumble.svn.sourceforge.net/svnroot/mumble/trunk@686 05730e5d-ab1b-0410-a4ac-84af385074fa
Diffstat (limited to 'src/CryptState.cpp')
-rw-r--r--src/CryptState.cpp137
1 files changed, 121 insertions, 16 deletions
diff --git a/src/CryptState.cpp b/src/CryptState.cpp
index 465826901..23f1c52f5 100644
--- a/src/CryptState.cpp
+++ b/src/CryptState.cpp
@@ -28,6 +28,15 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * This code implements OCB-AES128.
+ * In the US, OCB is covered by patents. The inventor has given a license
+ * to all programs distributed under the GPL.
+ * Mumble is BSD (revised) licensed, meaning you can use the code in a
+ * closed-source program. If you do, you'll have to either replace
+ * OCB with something else or get yourself a license.
+ */
+
#include "CryptState.h"
CryptState::CryptState() {
@@ -42,7 +51,8 @@ void CryptState::genKey() {
RAND_bytes(raw_key, AES_BLOCK_SIZE);
RAND_bytes(encrypt_iv, AES_BLOCK_SIZE);
RAND_bytes(decrypt_iv, AES_BLOCK_SIZE);
- AES_set_encrypt_key(raw_key, 128, &crypt_key);
+ AES_set_encrypt_key(raw_key, 128, &encrypt_key);
+ AES_set_decrypt_key(raw_key, 128, &decrypt_key);
bInit = true;
}
@@ -50,7 +60,8 @@ void CryptState::setKey(const unsigned char *rkey, const unsigned char *eiv, con
memcpy(raw_key, rkey, AES_BLOCK_SIZE);
memcpy(encrypt_iv, eiv, AES_BLOCK_SIZE);
memcpy(decrypt_iv, div, AES_BLOCK_SIZE);
- AES_set_encrypt_key(raw_key, 128, &crypt_key);
+ AES_set_encrypt_key(raw_key, 128, &encrypt_key);
+ AES_set_decrypt_key(raw_key, 128, &decrypt_key);
bInit = true;
}
@@ -59,20 +70,19 @@ void CryptState::setDecryptIV(const unsigned char *iv) {
}
void CryptState::encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) {
- unsigned int crypted_length = plain_length + 4;
-
+ unsigned char tag[AES_BLOCK_SIZE];
+
// First, increase our IV.
- for(int i=0;i<AES_BLOCK_SIZE;i++)
+ for (int i=0;i<AES_BLOCK_SIZE;i++)
if (++encrypt_iv[i])
break;
-
+
+ ocb_encrypt(source, dst+4, plain_length, encrypt_iv, tag);
+
dst[0] = encrypt_iv[0];
-
- // Checksum (cheeze it)
- dst[1] = encrypt_iv[1];
- dst[2] = encrypt_iv[2];
- dst[3] = encrypt_iv[3];
- memcpy(dst + 4, source, plain_length);
+ dst[1] = tag[0];
+ dst[2] = tag[1];
+ dst[3] = tag[2];
}
bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsigned int crypted_length) {
@@ -80,7 +90,7 @@ bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsign
return false;
unsigned int plain_length = crypted_length - 4;
-
+
unsigned char saveiv[AES_BLOCK_SIZE];
unsigned char ivbyte = source[0];
@@ -89,19 +99,114 @@ bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsign
if (ivbyte > decrypt_iv[0]) {
decrypt_iv[0] = ivbyte;
} else if (ivbyte < decrypt_iv[0]) {
- for(int i=1;i<AES_BLOCK_SIZE;i++)
+ for (int i=1;i<AES_BLOCK_SIZE;i++)
if (++decrypt_iv[i])
break;
decrypt_iv[0] = ivbyte;
} else {
return false;
}
- if (memcmp(source+1, & decrypt_iv[1], 3) != 0) {
+
+ unsigned char tag[AES_BLOCK_SIZE];
+ ocb_decrypt(source+4, dst, plain_length, decrypt_iv, tag);
+
+ if (memcmp(tag, source+1, 3) != 0) {
memcpy(decrypt_iv, saveiv, AES_BLOCK_SIZE);
return false;
}
- memcpy(dst, source + 4, plain_length);
tLastGood.restart();
return true;
}
+static void inline XOR(unsigned char *dst, const unsigned char *a, const unsigned char *b) {
+ for (int i=0;i<AES_BLOCK_SIZE;i++)
+ dst[i] = a[i] ^ b[i];
+}
+
+static void inline S2(unsigned char *block) {
+ unsigned char carry = block[0] >> 7;
+ for (int i=0;i<AES_BLOCK_SIZE-1;i++)
+ block[i] = (block[i] << 1) | (block[i+1] >> 7);
+ block[AES_BLOCK_SIZE-1] = (block[AES_BLOCK_SIZE-1] << 1) ^(carry * 0x87);
+}
+
+static void inline S3(unsigned char *block) {
+ unsigned char carry = block[0] >> 7;
+ for (int i=0;i<AES_BLOCK_SIZE-1;i++)
+ block[i] ^= (block[i] << 1) | (block[i+1] >> 7);
+ block[AES_BLOCK_SIZE-1] ^= (block[AES_BLOCK_SIZE-1] << 1) ^(carry * 0x87);
+}
+
+void CryptState::ocb_encrypt(const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag) {
+ unsigned char checksum[AES_BLOCK_SIZE];
+ unsigned char delta[AES_BLOCK_SIZE];
+ unsigned char tmp[AES_BLOCK_SIZE];
+ unsigned char pad[AES_BLOCK_SIZE];
+
+ // Initialize
+ AES_encrypt(nonce, delta, &encrypt_key);
+ memset(checksum, 0, AES_BLOCK_SIZE);
+
+ while (len > AES_BLOCK_SIZE) {
+ S2(delta);
+ XOR(tmp, delta, plain);
+ AES_encrypt(tmp, tmp, &encrypt_key);
+ XOR(encrypted, delta, tmp);
+ XOR(checksum, checksum, plain);
+ len -= AES_BLOCK_SIZE;
+ plain += AES_BLOCK_SIZE;
+ encrypted += AES_BLOCK_SIZE;
+ }
+
+ S2(delta);
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ tmp[AES_BLOCK_SIZE - 1] = len * 8;
+ XOR(tmp, tmp, delta);
+ AES_encrypt(tmp, pad, &encrypt_key);
+ memcpy(tmp, plain, len);
+ memcpy(tmp+len, pad+len, AES_BLOCK_SIZE - len);
+ XOR(checksum, checksum, tmp);
+ XOR(tmp, pad, tmp);
+ memcpy(encrypted, tmp, len);
+
+ S3(delta);
+ XOR(tmp, delta, checksum);
+ AES_encrypt(tmp, tag, &encrypt_key);
+}
+
+void CryptState::ocb_decrypt(const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag) {
+ unsigned char checksum[AES_BLOCK_SIZE];
+ unsigned char delta[AES_BLOCK_SIZE];
+ unsigned char tmp[AES_BLOCK_SIZE];
+ unsigned char pad[AES_BLOCK_SIZE];
+
+ // Initialize
+ AES_encrypt(nonce, delta, &encrypt_key);
+ memset(checksum, 0, AES_BLOCK_SIZE);
+
+ while (len > AES_BLOCK_SIZE) {
+ S2(delta);
+ XOR(tmp, delta, encrypted);
+ AES_decrypt(tmp, tmp, &decrypt_key);
+ XOR(plain, delta, tmp);
+ XOR(checksum, checksum, plain);
+ len -= AES_BLOCK_SIZE;
+ plain += AES_BLOCK_SIZE;
+ encrypted += AES_BLOCK_SIZE;
+ }
+
+ S2(delta);
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ tmp[AES_BLOCK_SIZE - 1] = len * 8;
+ XOR(tmp, tmp, delta);
+ AES_encrypt(tmp, pad, &encrypt_key);
+ memset(tmp, 0, AES_BLOCK_SIZE);
+ memcpy(tmp, encrypted, len);
+ XOR(tmp, tmp, pad);
+ XOR(checksum, checksum, tmp);
+ memcpy(plain, tmp, len);
+
+ S3(delta);
+ XOR(tmp, delta, checksum);
+ AES_encrypt(tmp, tag, &encrypt_key);
+}