// Copyright 2005-2019 The Mumble Developers. All rights reserved. // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file at the root of the // Mumble source tree or at . /* * 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 "murmur_pch.h" #include "CryptState.h" #include "ByteSwap.h" CryptState::CryptState() { for (int i=0;i<0x100;i++) decrypt_history[i] = 0; bInit = false; memset(raw_key, 0, AES_KEY_SIZE_BYTES); memset(encrypt_iv, 0, AES_BLOCK_SIZE); memset(decrypt_iv, 0, AES_BLOCK_SIZE); uiGood=uiLate=uiLost=uiResync=0; uiRemoteGood=uiRemoteLate=uiRemoteLost=uiRemoteResync=0; } bool CryptState::isValid() const { return bInit; } void CryptState::genKey() { RAND_bytes(raw_key, AES_KEY_SIZE_BYTES); RAND_bytes(encrypt_iv, AES_BLOCK_SIZE); RAND_bytes(decrypt_iv, AES_BLOCK_SIZE); AES_set_encrypt_key(raw_key, AES_KEY_SIZE_BITS, &encrypt_key); AES_set_decrypt_key(raw_key, AES_KEY_SIZE_BITS, &decrypt_key); bInit = true; } void CryptState::setKey(const unsigned char *rkey, const unsigned char *eiv, const unsigned char *div) { memcpy(raw_key, rkey, AES_KEY_SIZE_BYTES); memcpy(encrypt_iv, eiv, AES_BLOCK_SIZE); memcpy(decrypt_iv, div, AES_BLOCK_SIZE); AES_set_encrypt_key(raw_key, AES_KEY_SIZE_BITS, &encrypt_key); AES_set_decrypt_key(raw_key, AES_KEY_SIZE_BITS, &decrypt_key); bInit = true; } void CryptState::setDecryptIV(const unsigned char *iv) { memcpy(decrypt_iv, iv, AES_BLOCK_SIZE); } void CryptState::encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) { unsigned char tag[AES_BLOCK_SIZE]; // First, increase our IV. for (int i=0;i decrypt_iv[0]) { decrypt_iv[0] = ivbyte; } else if (ivbyte < decrypt_iv[0]) { decrypt_iv[0] = ivbyte; for (int i=1;i 128) diff = diff-256; else if (diff < -128) diff = diff+256; if ((ivbyte < decrypt_iv[0]) && (diff > -30) && (diff < 0)) { // Late packet, but no wraparound. late = 1; lost = -1; decrypt_iv[0] = ivbyte; restore = true; } else if ((ivbyte > decrypt_iv[0]) && (diff > -30) && (diff < 0)) { // Last was 0x02, here comes 0xff from last round late = 1; lost = -1; decrypt_iv[0] = ivbyte; for (int i=1;i decrypt_iv[0]) && (diff > 0)) { // Lost a few packets, but beyond that we're good. lost = ivbyte - decrypt_iv[0] - 1; decrypt_iv[0] = ivbyte; } else if ((ivbyte < decrypt_iv[0]) && (diff > 0)) { // Lost a few packets, and wrapped around lost = 256 - decrypt_iv[0] + ivbyte - 1; decrypt_iv[0] = ivbyte; for (int i=1;i> SHIFTBITS; for (int i=0;i> SHIFTBITS)); block[BLOCKSIZE-1] = SWAPPED((SWAPPED(block[BLOCKSIZE-1]) << 1) ^(carry * 0x87)); } static void inline S3(subblock *block) { subblock carry = SWAPPED(block[0]) >> SHIFTBITS; for (int i=0;i> SHIFTBITS)); block[BLOCKSIZE-1] ^= SWAPPED((SWAPPED(block[BLOCKSIZE-1]) << 1) ^(carry * 0x87)); } static void inline ZERO(keyblock &block) { for (int i=0;i(src),reinterpret_cast(dst), key); #define AESdecrypt(src,dst,key) AES_decrypt(reinterpret_cast(src),reinterpret_cast(dst), key); void CryptState::ocb_encrypt(const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag) { keyblock checksum, delta, tmp, pad; // Initialize AESencrypt(nonce, delta, &encrypt_key); ZERO(checksum); while (len > AES_BLOCK_SIZE) { S2(delta); XOR(tmp, delta, reinterpret_cast(plain)); AESencrypt(tmp, tmp, &encrypt_key); XOR(reinterpret_cast(encrypted), delta, tmp); XOR(checksum, checksum, reinterpret_cast(plain)); len -= AES_BLOCK_SIZE; plain += AES_BLOCK_SIZE; encrypted += AES_BLOCK_SIZE; } S2(delta); ZERO(tmp); tmp[BLOCKSIZE - 1] = SWAPPED(len * 8); XOR(tmp, tmp, delta); AESencrypt(tmp, pad, &encrypt_key); memcpy(tmp, plain, len); memcpy(reinterpret_cast(tmp)+len, reinterpret_cast(pad)+len, AES_BLOCK_SIZE - len); XOR(checksum, checksum, tmp); XOR(tmp, pad, tmp); memcpy(encrypted, tmp, len); S3(delta); XOR(tmp, delta, checksum); AESencrypt(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) { keyblock checksum, delta, tmp, pad; // Initialize AESencrypt(nonce, delta, &encrypt_key); ZERO(checksum); while (len > AES_BLOCK_SIZE) { S2(delta); XOR(tmp, delta, reinterpret_cast(encrypted)); AESdecrypt(tmp, tmp, &decrypt_key); XOR(reinterpret_cast(plain), delta, tmp); XOR(checksum, checksum, reinterpret_cast(plain)); len -= AES_BLOCK_SIZE; plain += AES_BLOCK_SIZE; encrypted += AES_BLOCK_SIZE; } S2(delta); ZERO(tmp); tmp[BLOCKSIZE - 1] = SWAPPED(len * 8); XOR(tmp, tmp, delta); AESencrypt(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); AESencrypt(tmp, tag, &encrypt_key); }