xboxkrnl: Add a bunch of crypto functions
This commit is contained in:
parent
99f3c61fc1
commit
fb87b7a3c3
|
@ -14,6 +14,12 @@
|
||||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||||
|
|
||||||
#include "third_party/crypto/TinySHA1.hpp"
|
#include "third_party/crypto/TinySHA1.hpp"
|
||||||
|
#include "third_party/crypto/des/des.cpp"
|
||||||
|
#include "third_party/crypto/des/des.h"
|
||||||
|
#include "third_party/crypto/des/des3.h"
|
||||||
|
#include "third_party/crypto/des/descbc.h"
|
||||||
|
#include "third_party/crypto/sha256.cpp"
|
||||||
|
#include "third_party/crypto/sha256.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
@ -70,22 +76,17 @@ void XeCryptShaFinal(pointer_t<XECRYPT_SHA_STATE> sha_state,
|
||||||
sha1::SHA1 sha;
|
sha1::SHA1 sha;
|
||||||
InitSha1(&sha, sha_state);
|
InitSha1(&sha, sha_state);
|
||||||
|
|
||||||
uint32_t digest[5];
|
uint8_t digest[0x14];
|
||||||
sha.finalize(digest);
|
sha.finalize(digest);
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
std::memcpy(out, digest, std::min((uint32_t)out_size, 0x14u));
|
||||||
sha_state->state[i] = digest[i];
|
std::memcpy(sha_state->state, digest, 0x14);
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < out_size / 4; i++) {
|
|
||||||
out[i] = digest[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT(XeCryptShaFinal, ExportTag::kImplemented);
|
DECLARE_XBOXKRNL_EXPORT(XeCryptShaFinal, ExportTag::kImplemented);
|
||||||
|
|
||||||
void XeCryptSha(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2,
|
void XeCryptSha(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2,
|
||||||
dword_t input_2_size, lpvoid_t input_3, dword_t input_3_size,
|
dword_t input_2_size, lpvoid_t input_3, dword_t input_3_size,
|
||||||
pointer_t<xe::be<uint32_t>> output, dword_t output_size) {
|
lpvoid_t output, dword_t output_size) {
|
||||||
sha1::SHA1 sha;
|
sha1::SHA1 sha;
|
||||||
|
|
||||||
if (input_1 && input_1_size) {
|
if (input_1 && input_1_size) {
|
||||||
|
@ -98,15 +99,63 @@ void XeCryptSha(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2,
|
||||||
sha.processBytes(input_3, input_3_size);
|
sha.processBytes(input_3, input_3_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t digest[5];
|
uint8_t digest[0x14];
|
||||||
sha.finalize(digest);
|
sha.finalize(digest);
|
||||||
|
std::memcpy(output, digest, std::min((uint32_t)output_size, 0x14u));
|
||||||
for (uint32_t i = 0; i < output_size / 4; i++) {
|
|
||||||
output[i] = digest[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT(XeCryptSha, ExportTag::kImplemented);
|
DECLARE_XBOXKRNL_EXPORT(XeCryptSha, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
// TODO: Size of this struct hasn't been confirmed yet.
|
||||||
|
typedef struct {
|
||||||
|
xe::be<uint32_t> count; // 0x0
|
||||||
|
xe::be<uint32_t> state[8]; // 0x4
|
||||||
|
uint8_t buffer[64]; // 0x24
|
||||||
|
} XECRYPT_SHA256_STATE;
|
||||||
|
|
||||||
|
void XeCryptSha256Init(pointer_t<XECRYPT_SHA256_STATE> sha_state) {
|
||||||
|
sha_state.Zero();
|
||||||
|
|
||||||
|
sha_state->state[0] = 0x6a09e667;
|
||||||
|
sha_state->state[1] = 0xbb67ae85;
|
||||||
|
sha_state->state[2] = 0x3c6ef372;
|
||||||
|
sha_state->state[3] = 0xa54ff53a;
|
||||||
|
sha_state->state[4] = 0x510e527f;
|
||||||
|
sha_state->state[5] = 0x9b05688c;
|
||||||
|
sha_state->state[6] = 0x1f83d9ab;
|
||||||
|
sha_state->state[7] = 0x5be0cd19;
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptSha256Init, ExportTag::kStub);
|
||||||
|
|
||||||
|
void XeCryptSha256Update(pointer_t<XECRYPT_SHA256_STATE> sha_state,
|
||||||
|
lpvoid_t input, dword_t input_size) {
|
||||||
|
sha256::SHA256 sha;
|
||||||
|
std::memcpy(sha.getHashValues(), sha_state->state, 8 * 4);
|
||||||
|
std::memcpy(sha.getBuffer(), sha_state->buffer, 64);
|
||||||
|
sha.setTotalSize(sha_state->count);
|
||||||
|
|
||||||
|
sha.add(input, input_size);
|
||||||
|
|
||||||
|
std::memcpy(sha_state->state, sha.getHashValues(), 8 * 4);
|
||||||
|
std::memcpy(sha_state->buffer, sha.getBuffer(), 64);
|
||||||
|
sha_state->count = uint32_t(sha.getTotalSize());
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptSha256Update, ExportTag::kStub);
|
||||||
|
|
||||||
|
void XeCryptSha256Final(pointer_t<XECRYPT_SHA256_STATE> sha_state,
|
||||||
|
pointer_t<xe::be<uint32_t>> out, dword_t out_size) {
|
||||||
|
sha256::SHA256 sha;
|
||||||
|
std::memcpy(sha.getHashValues(), sha_state->state, 8 * 4);
|
||||||
|
std::memcpy(sha.getBuffer(), sha_state->buffer, 64);
|
||||||
|
sha.setTotalSize(sha_state->count);
|
||||||
|
|
||||||
|
uint32_t hash[8];
|
||||||
|
sha.getHash(reinterpret_cast<uint8_t*>(hash));
|
||||||
|
|
||||||
|
std::memcpy(out, hash, std::min(uint32_t(out_size), 32u));
|
||||||
|
std::memcpy(sha_state->buffer, hash, 32);
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptSha256Final, ExportTag::kStub);
|
||||||
|
|
||||||
// Byteswap?
|
// Byteswap?
|
||||||
dword_result_t XeCryptBnQw_SwapDwQwLeBe(lpqword_t qw_inp, lpqword_t qw_out,
|
dword_result_t XeCryptBnQw_SwapDwQwLeBe(lpqword_t qw_inp, lpqword_t qw_out,
|
||||||
dword_t size) {
|
dword_t size) {
|
||||||
|
@ -128,6 +177,161 @@ dword_result_t XeCryptBnDwLePkcs1Verify(lpvoid_t hash, lpvoid_t sig,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT(XeCryptBnDwLePkcs1Verify, ExportTag::kStub);
|
DECLARE_XBOXKRNL_EXPORT(XeCryptBnDwLePkcs1Verify, ExportTag::kStub);
|
||||||
|
|
||||||
|
void XeCryptRandom(lpvoid_t buf, dword_t buf_size) {
|
||||||
|
std::memset(buf, 0xFD, buf_size);
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptRandom, ExportTag::kStub);
|
||||||
|
|
||||||
|
struct XECRYPT_DES_STATE {
|
||||||
|
uint32_t keytab[16][2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sets bit 0 to make the parity odd
|
||||||
|
void XeCryptDesParity(lpvoid_t inp, dword_t inp_size, lpvoid_t out_ptr) {
|
||||||
|
DES::set_parity(inp, inp_size, out_ptr);
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptDesParity, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
struct XECRYPT_DES3_STATE {
|
||||||
|
XECRYPT_DES_STATE des_state[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
void XeCryptDes3Key(pointer_t<XECRYPT_DES3_STATE> state_ptr, lpqword_t key) {
|
||||||
|
DES3 des3(key[0], key[1], key[2]);
|
||||||
|
DES* des = des3.getDES();
|
||||||
|
|
||||||
|
// Store our DES state into the state.
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
std::memcpy(state_ptr->des_state[i].keytab, des[i].get_sub_key(), 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptDes3Key, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
void XeCryptDes3Ecb(pointer_t<XECRYPT_DES3_STATE> state_ptr, lpqword_t inp,
|
||||||
|
lpqword_t out, dword_t encrypt) {
|
||||||
|
DES3 des3((ui64*)state_ptr->des_state[0].keytab,
|
||||||
|
(ui64*)state_ptr->des_state[1].keytab,
|
||||||
|
(ui64*)state_ptr->des_state[2].keytab);
|
||||||
|
|
||||||
|
if (encrypt) {
|
||||||
|
*out = des3.encrypt(*inp);
|
||||||
|
} else {
|
||||||
|
*out = des3.decrypt(*inp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptDes3Ecb, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
void XeCryptDes3Cbc(pointer_t<XECRYPT_DES3_STATE> state_ptr, lpqword_t inp,
|
||||||
|
dword_t inp_size, lpqword_t out, lpqword_t feed,
|
||||||
|
dword_t encrypt) {
|
||||||
|
DES3 des3((ui64*)state_ptr->des_state[0].keytab,
|
||||||
|
(ui64*)state_ptr->des_state[1].keytab,
|
||||||
|
(ui64*)state_ptr->des_state[2].keytab);
|
||||||
|
|
||||||
|
// DES can only do 8-byte chunks at a time!
|
||||||
|
assert_true(inp_size % 8 == 0);
|
||||||
|
|
||||||
|
uint64_t last_block = *feed;
|
||||||
|
for (uint32_t i = 0; i < inp_size / 8; i++) {
|
||||||
|
uint64_t block = inp[i];
|
||||||
|
if (encrypt) {
|
||||||
|
last_block = des3.encrypt(block ^ last_block);
|
||||||
|
out[i] = last_block;
|
||||||
|
} else {
|
||||||
|
out[i] = des3.decrypt(block) ^ last_block;
|
||||||
|
last_block = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*feed = last_block;
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptDes3Cbc, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
void XeCryptHmacSha(lpvoid_t key, dword_t key_size_in, lpvoid_t inp_1,
|
||||||
|
dword_t inp_1_size, lpvoid_t inp_2, dword_t inp_2_size,
|
||||||
|
lpvoid_t inp_3, dword_t inp_3_size, lpvoid_t out,
|
||||||
|
dword_t out_size) {
|
||||||
|
uint32_t key_size = key_size_in;
|
||||||
|
sha1::SHA1 sha;
|
||||||
|
uint8_t kpad_i[0x40];
|
||||||
|
uint8_t kpad_o[0x40];
|
||||||
|
uint8_t tmp_key[0x40];
|
||||||
|
std::memset(kpad_i, 0x36, 0x40);
|
||||||
|
std::memset(kpad_o, 0x5C, 0x40);
|
||||||
|
|
||||||
|
// Setup HMAC key
|
||||||
|
// If > block size, use its hash
|
||||||
|
if (key_size > 0x40) {
|
||||||
|
sha1::SHA1 sha_key;
|
||||||
|
sha_key.processBytes(key, key_size);
|
||||||
|
sha_key.finalize((uint8_t*)tmp_key);
|
||||||
|
|
||||||
|
key_size = 0x14u;
|
||||||
|
} else {
|
||||||
|
std::memcpy(tmp_key, key, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < key_size; i++) {
|
||||||
|
kpad_i[i] = tmp_key[i] ^ 0x36;
|
||||||
|
kpad_o[i] = tmp_key[i] ^ 0x5C;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner
|
||||||
|
sha.processBytes(kpad_i, 0x40);
|
||||||
|
|
||||||
|
if (inp_1_size) {
|
||||||
|
sha.processBytes(inp_1, inp_1_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inp_2_size) {
|
||||||
|
sha.processBytes(inp_2, inp_2_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inp_3_size) {
|
||||||
|
sha.processBytes(inp_3, inp_3_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t digest[0x14];
|
||||||
|
sha.finalize(digest);
|
||||||
|
sha.reset();
|
||||||
|
|
||||||
|
// Outer
|
||||||
|
sha.processBytes(kpad_o, 0x40);
|
||||||
|
sha.processBytes(digest, 0x14);
|
||||||
|
sha.finalize(digest);
|
||||||
|
|
||||||
|
std::memcpy(out, digest, std::min((uint32_t)out_size, 0x14u));
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeCryptHmacSha, ExportTag::kImplemented);
|
||||||
|
|
||||||
|
// Keys
|
||||||
|
// TODO: Array of keys we need
|
||||||
|
|
||||||
|
// Retail key 0x19
|
||||||
|
static const uint8_t key19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1, 0xEA, 0xE9,
|
||||||
|
0xAB, 0x31, 0x70, 0xF3, 0xAD, 0x47, 0xEB, 0xF3};
|
||||||
|
|
||||||
|
dword_result_t XeKeysHmacSha(dword_t key_num, lpvoid_t inp_1,
|
||||||
|
dword_t inp_1_size, lpvoid_t inp_2,
|
||||||
|
dword_t inp_2_size, lpvoid_t inp_3,
|
||||||
|
dword_t inp_3_size, lpvoid_t out,
|
||||||
|
dword_t out_size) {
|
||||||
|
const uint8_t* key = nullptr;
|
||||||
|
if (key_num == 0x19) {
|
||||||
|
key = key19;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
XeCryptHmacSha((void*)key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size,
|
||||||
|
inp_3, inp_3_size, out, out_size);
|
||||||
|
|
||||||
|
return X_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return X_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(XeKeysHmacSha, ExportTag::kStub);
|
||||||
|
|
||||||
void RegisterCryptExports(xe::cpu::ExportResolver* export_resolver,
|
void RegisterCryptExports(xe::cpu::ExportResolver* export_resolver,
|
||||||
KernelState* kernel_state) {}
|
KernelState* kernel_state) {}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Faraz Fallahi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
cppDES
|
||||||
|
======
|
||||||
|
|
||||||
|
Taken from [this repository](https://github.com/fffaraz/cppDES)
|
||||||
|
|
||||||
|
Modified for use by Xenia.
|
|
@ -0,0 +1,177 @@
|
||||||
|
#include "des.h"
|
||||||
|
#include "des_key.h"
|
||||||
|
#include "des_data.h"
|
||||||
|
#include "des_lookup.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
//#pragma GCC push_options
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#pragma GCC optimize ("unroll-loops")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DES::DES(ui64 key)
|
||||||
|
{
|
||||||
|
keygen(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
DES::DES(ui64* sub_key)
|
||||||
|
{
|
||||||
|
set_sub_key(sub_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DES::set_sub_key(ui64 *sub_key)
|
||||||
|
{
|
||||||
|
std::memcpy(this->sub_key, sub_key, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::encrypt(ui64 block)
|
||||||
|
{
|
||||||
|
return des(block, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::decrypt(ui64 block)
|
||||||
|
{
|
||||||
|
return des(block, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::encrypt(ui64 block, ui64 key)
|
||||||
|
{
|
||||||
|
DES des(key);
|
||||||
|
return des.des(block, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::decrypt(ui64 block, ui64 key)
|
||||||
|
{
|
||||||
|
DES des(key);
|
||||||
|
return des.des(block, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DES::keygen(ui64 key)
|
||||||
|
{
|
||||||
|
// initial key schedule calculation
|
||||||
|
ui64 permuted_choice_1 = 0; // 56 bits
|
||||||
|
for (ui8 i = 0; i < 56; i++)
|
||||||
|
{
|
||||||
|
permuted_choice_1 <<= 1;
|
||||||
|
permuted_choice_1 |= (key >> (64-PC1[i])) & LB64_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 28 bits
|
||||||
|
ui32 C = (ui32) ((permuted_choice_1 >> 28) & 0x000000000fffffff);
|
||||||
|
ui32 D = (ui32) (permuted_choice_1 & 0x000000000fffffff);
|
||||||
|
|
||||||
|
// Calculation of the 16 keys
|
||||||
|
for (ui8 i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
// key schedule, shifting Ci and Di
|
||||||
|
for (ui8 j = 0; j < ITERATION_SHIFT[i]; j++)
|
||||||
|
{
|
||||||
|
C = (0x0fffffff & (C << 1)) | (0x00000001 & (C >> 27));
|
||||||
|
D = (0x0fffffff & (D << 1)) | (0x00000001 & (D >> 27));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 permuted_choice_2 = (((ui64) C) << 28) | (ui64) D;
|
||||||
|
|
||||||
|
sub_key[i] = 0; // 48 bits (2*24)
|
||||||
|
for (ui8 j = 0; j < 48; j++)
|
||||||
|
{
|
||||||
|
sub_key[i] <<= 1;
|
||||||
|
sub_key[i] |= (permuted_choice_2 >> (56-PC2[j])) & LB64_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::des(ui64 block, bool mode)
|
||||||
|
{
|
||||||
|
// applying initial permutation
|
||||||
|
block = ip(block);
|
||||||
|
|
||||||
|
// dividing T' into two 32-bit parts
|
||||||
|
ui32 L = (ui32) (block >> 32) & L64_MASK;
|
||||||
|
ui32 R = (ui32) (block & L64_MASK);
|
||||||
|
|
||||||
|
// 16 rounds
|
||||||
|
for (ui8 i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
ui32 F = mode ? f(R, sub_key[15-i]) : f(R, sub_key[i]);
|
||||||
|
feistel(L, R, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
// swapping the two parts
|
||||||
|
block = (((ui64) R) << 32) | (ui64) L;
|
||||||
|
// applying final permutation
|
||||||
|
return fp(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::ip(ui64 block)
|
||||||
|
{
|
||||||
|
// initial permutation
|
||||||
|
ui64 result = 0;
|
||||||
|
for (ui8 i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
result <<= 1;
|
||||||
|
result |= (block >> (64-IP[i])) & LB64_MASK;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 DES::fp(ui64 block)
|
||||||
|
{
|
||||||
|
// inverse initial permutation
|
||||||
|
ui64 result = 0;
|
||||||
|
for (ui8 i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
result <<= 1;
|
||||||
|
result |= (block >> (64-FP[i])) & LB64_MASK;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DES::feistel(ui32 &L, ui32 &R, ui32 F)
|
||||||
|
{
|
||||||
|
ui32 temp = R;
|
||||||
|
R = L ^ F;
|
||||||
|
L = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui32 DES::f(ui32 R, ui64 k) // f(R,k) function
|
||||||
|
{
|
||||||
|
// applying expansion permutation and returning 48-bit data
|
||||||
|
ui64 s_input = 0;
|
||||||
|
for (ui8 i = 0; i < 48; i++)
|
||||||
|
{
|
||||||
|
s_input <<= 1;
|
||||||
|
s_input |= (ui64) ((R >> (32-EXPANSION[i])) & LB32_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XORing expanded Ri with Ki, the round key
|
||||||
|
s_input = s_input ^ k;
|
||||||
|
|
||||||
|
// applying S-Boxes function and returning 32-bit data
|
||||||
|
ui32 s_output = 0;
|
||||||
|
for (ui8 i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
// Outer bits
|
||||||
|
char row = (char) ((s_input & (0x0000840000000000 >> 6*i)) >> (42-6*i));
|
||||||
|
row = (row >> 4) | (row & 0x01);
|
||||||
|
|
||||||
|
// Middle 4 bits of input
|
||||||
|
char column = (char) ((s_input & (0x0000780000000000 >> 6*i)) >> (43-6*i));
|
||||||
|
|
||||||
|
s_output <<= 4;
|
||||||
|
s_output |= (ui32) (SBOX[i][16*row + column] & 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// applying the round permutation
|
||||||
|
ui32 f_result = 0;
|
||||||
|
for (ui8 i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
f_result <<= 1;
|
||||||
|
f_result |= (s_output >> (32 - PBOX[i])) & LB32_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#pragma GCC pop_options
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef DES_H
|
||||||
|
#define DES_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
typedef uint64_t ui64;
|
||||||
|
typedef uint32_t ui32;
|
||||||
|
typedef uint8_t ui8;
|
||||||
|
|
||||||
|
class DES
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DES(ui64 key);
|
||||||
|
DES(ui64 *sub_key);
|
||||||
|
ui64 des(ui64 block, bool mode);
|
||||||
|
|
||||||
|
ui64 encrypt(ui64 block);
|
||||||
|
ui64 decrypt(ui64 block);
|
||||||
|
|
||||||
|
static ui64 encrypt(ui64 block, ui64 key);
|
||||||
|
static ui64 decrypt(ui64 block, ui64 key);
|
||||||
|
|
||||||
|
static void set_parity(ui8 *key, int length, ui8 *out) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
ui8 parity = key[i];
|
||||||
|
|
||||||
|
parity ^= parity >> 4;
|
||||||
|
parity ^= parity >> 2;
|
||||||
|
parity ^= parity >> 1;
|
||||||
|
|
||||||
|
out[i] = (key[i] & 0xFE) | (~parity & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ui64 *get_sub_key() const { return sub_key; }
|
||||||
|
void set_sub_key(ui64 *key);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keygen(ui64 key);
|
||||||
|
|
||||||
|
ui64 ip(ui64 block);
|
||||||
|
ui64 fp(ui64 block);
|
||||||
|
|
||||||
|
void feistel(ui32 &L, ui32 &R, ui32 F);
|
||||||
|
ui32 f(ui32 R, ui64 k);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ui64 sub_key[16]; // 48 bits each
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DES_H
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef DES3_H
|
||||||
|
#define DES3_H
|
||||||
|
|
||||||
|
#include "des.h"
|
||||||
|
|
||||||
|
class DES3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DES3(ui64 k1, ui64 k2, ui64 k3) : des{ DES(k1), DES(k2), DES(k3) } {}
|
||||||
|
DES3(ui64* sk1, ui64* sk2, ui64* sk3) : des{ DES(sk1), DES(sk2), DES(sk3) } {}
|
||||||
|
|
||||||
|
inline ui64 encrypt(ui64 block)
|
||||||
|
{
|
||||||
|
return des[2].encrypt(des[1].decrypt(des[0].encrypt(block)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui64 decrypt(ui64 block)
|
||||||
|
{
|
||||||
|
return des[0].decrypt(des[1].encrypt(des[2].decrypt(block)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui64 crypt(ui64 block, bool bEncrypt)
|
||||||
|
{
|
||||||
|
if (bEncrypt)
|
||||||
|
{
|
||||||
|
return encrypt(block);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return decrypt(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DES* getDES() { return des; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DES des[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DES3_H
|
|
@ -0,0 +1,121 @@
|
||||||
|
#ifndef DES_DATA_H
|
||||||
|
#define DES_DATA_H
|
||||||
|
|
||||||
|
#define LB32_MASK 0x00000001
|
||||||
|
#define LB64_MASK 0x0000000000000001
|
||||||
|
#define L64_MASK 0x00000000ffffffff
|
||||||
|
|
||||||
|
// Initial Permutation Table [8*8]
|
||||||
|
static const char IP[] =
|
||||||
|
{
|
||||||
|
58, 50, 42, 34, 26, 18, 10, 2,
|
||||||
|
60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
|
62, 54, 46, 38, 30, 22, 14, 6,
|
||||||
|
64, 56, 48, 40, 32, 24, 16, 8,
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1,
|
||||||
|
59, 51, 43, 35, 27, 19, 11, 3,
|
||||||
|
61, 53, 45, 37, 29, 21, 13, 5,
|
||||||
|
63, 55, 47, 39, 31, 23, 15, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inverse Initial Permutation Table [8*8]
|
||||||
|
static const char FP[] =
|
||||||
|
{
|
||||||
|
40, 8, 48, 16, 56, 24, 64, 32,
|
||||||
|
39, 7, 47, 15, 55, 23, 63, 31,
|
||||||
|
38, 6, 46, 14, 54, 22, 62, 30,
|
||||||
|
37, 5, 45, 13, 53, 21, 61, 29,
|
||||||
|
36, 4, 44, 12, 52, 20, 60, 28,
|
||||||
|
35, 3, 43, 11, 51, 19, 59, 27,
|
||||||
|
34, 2, 42, 10, 50, 18, 58, 26,
|
||||||
|
33, 1, 41, 9, 49, 17, 57, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expansion table [6*8]
|
||||||
|
static const char EXPANSION[] =
|
||||||
|
{
|
||||||
|
32, 1, 2, 3, 4, 5,
|
||||||
|
4, 5, 6, 7, 8, 9,
|
||||||
|
8, 9, 10, 11, 12, 13,
|
||||||
|
12, 13, 14, 15, 16, 17,
|
||||||
|
16, 17, 18, 19, 20, 21,
|
||||||
|
20, 21, 22, 23, 24, 25,
|
||||||
|
24, 25, 26, 27, 28, 29,
|
||||||
|
28, 29, 30, 31, 32, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// The S-Box tables [8*16*4]
|
||||||
|
static const char SBOX[8][64] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// S1
|
||||||
|
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||||
|
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||||
|
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||||
|
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S2
|
||||||
|
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||||
|
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||||
|
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||||
|
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S3
|
||||||
|
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||||
|
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||||
|
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||||
|
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S4
|
||||||
|
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||||
|
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||||
|
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||||
|
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S5
|
||||||
|
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||||
|
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||||
|
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||||
|
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S6
|
||||||
|
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||||
|
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||||
|
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||||
|
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S7
|
||||||
|
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||||
|
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||||
|
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||||
|
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// S8
|
||||||
|
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||||
|
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||||
|
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||||
|
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Post S-Box permutation [4*8]
|
||||||
|
static const char PBOX[] =
|
||||||
|
{
|
||||||
|
16, 7, 20, 21,
|
||||||
|
29, 12, 28, 17,
|
||||||
|
1, 15, 23, 26,
|
||||||
|
5, 18, 31, 10,
|
||||||
|
2, 8, 24, 14,
|
||||||
|
32, 27, 3, 9,
|
||||||
|
19, 13, 30, 6,
|
||||||
|
22, 11, 4, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DES_DATA_H
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef DES_KEY_H
|
||||||
|
#define DES_KEY_H
|
||||||
|
|
||||||
|
// Permuted Choice 1 Table [7*8]
|
||||||
|
static const char PC1[] =
|
||||||
|
{
|
||||||
|
57, 49, 41, 33, 25, 17, 9,
|
||||||
|
1, 58, 50, 42, 34, 26, 18,
|
||||||
|
10, 2, 59, 51, 43, 35, 27,
|
||||||
|
19, 11, 3, 60, 52, 44, 36,
|
||||||
|
|
||||||
|
63, 55, 47, 39, 31, 23, 15,
|
||||||
|
7, 62, 54, 46, 38, 30, 22,
|
||||||
|
14, 6, 61, 53, 45, 37, 29,
|
||||||
|
21, 13, 5, 28, 20, 12, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
// Permuted Choice 2 Table [6*8]
|
||||||
|
static const char PC2[] =
|
||||||
|
{
|
||||||
|
14, 17, 11, 24, 1, 5,
|
||||||
|
3, 28, 15, 6, 21, 10,
|
||||||
|
23, 19, 12, 4, 26, 8,
|
||||||
|
16, 7, 27, 20, 13, 2,
|
||||||
|
41, 52, 31, 37, 47, 55,
|
||||||
|
30, 40, 51, 45, 33, 48,
|
||||||
|
44, 49, 39, 56, 34, 53,
|
||||||
|
46, 42, 50, 36, 29, 32
|
||||||
|
};
|
||||||
|
|
||||||
|
// Iteration Shift Array
|
||||||
|
static const char ITERATION_SHIFT[] =
|
||||||
|
{
|
||||||
|
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||||
|
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DES_KEY_H
|
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef DES_LOOKUP_H
|
||||||
|
#define DES_LOOKUP_H
|
||||||
|
|
||||||
|
#endif // DES_LOOKUP_H
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef DESCBC_H
|
||||||
|
#define DESCBC_H
|
||||||
|
|
||||||
|
#include "des.h"
|
||||||
|
|
||||||
|
class DESCBC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DESCBC(ui64 key, ui64 iv) : des(key), iv(iv), last_block(iv) {}
|
||||||
|
inline ui64 encrypt(ui64 block)
|
||||||
|
{
|
||||||
|
last_block = des.encrypt(block ^ last_block);
|
||||||
|
return last_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ui64 decrypt(ui64 block)
|
||||||
|
{
|
||||||
|
ui64 result = des.decrypt(block) ^ last_block;
|
||||||
|
last_block = block;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reset()
|
||||||
|
{
|
||||||
|
last_block = iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DES des;
|
||||||
|
ui64 iv;
|
||||||
|
ui64 last_block;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DESCBC_H
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* rc4.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2000 Whistle Communications, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Subject to the following obligations and disclaimer of warranty, use and
|
||||||
|
* redistribution of this software, in source or object code forms, with or
|
||||||
|
* without modifications are expressly permitted by Whistle Communications;
|
||||||
|
* provided, however, that:
|
||||||
|
* 1. Any and all reproductions of the source or object code must include the
|
||||||
|
* copyright notice above and the following disclaimer of warranties; and
|
||||||
|
* 2. No rights are granted, in any manner or form, to use Whistle
|
||||||
|
* Communications, Inc. trademarks, including the mark "WHISTLE
|
||||||
|
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
|
||||||
|
* such appears in the above copyright notice or in the software.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
|
||||||
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
|
||||||
|
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||||
|
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
|
||||||
|
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
|
||||||
|
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
|
||||||
|
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
|
||||||
|
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
|
||||||
|
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rc4.h"
|
||||||
|
|
||||||
|
static __inline void swap_bytes(uint8_t *a, uint8_t *b) {
|
||||||
|
uint8_t temp;
|
||||||
|
|
||||||
|
temp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize an RC4 state buffer using the supplied key,
|
||||||
|
* which can have arbitrary length.
|
||||||
|
*/
|
||||||
|
void rc4_init(struct rc4_state *const state, const uint8_t *key, int keylen) {
|
||||||
|
uint8_t j;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Initialize state with identity permutation */
|
||||||
|
for (i = 0; i < 256; i++) state->perm[i] = (uint8_t)i;
|
||||||
|
state->index1 = 0;
|
||||||
|
state->index2 = 0;
|
||||||
|
|
||||||
|
/* Randomize the permutation using key data */
|
||||||
|
for (j = i = 0; i < 256; i++) {
|
||||||
|
j += state->perm[i] + key[i % keylen];
|
||||||
|
swap_bytes(&state->perm[i], &state->perm[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encrypt some data using the supplied RC4 state buffer.
|
||||||
|
* The input and output buffers may be the same buffer.
|
||||||
|
* Since RC4 is a stream cypher, this function is used
|
||||||
|
* for both encryption and decryption.
|
||||||
|
*/
|
||||||
|
void rc4_crypt(struct rc4_state *const state, const uint8_t *inbuf,
|
||||||
|
uint8_t *outbuf, int buflen) {
|
||||||
|
int i;
|
||||||
|
uint8_t j;
|
||||||
|
|
||||||
|
for (i = 0; i < buflen; i++) {
|
||||||
|
/* Update modification indicies */
|
||||||
|
state->index1++;
|
||||||
|
state->index2 += state->perm[state->index1];
|
||||||
|
|
||||||
|
/* Modify permutation */
|
||||||
|
swap_bytes(&state->perm[state->index1], &state->perm[state->index2]);
|
||||||
|
|
||||||
|
/* Encrypt/decrypt next byte */
|
||||||
|
j = state->perm[state->index1] + state->perm[state->index2];
|
||||||
|
outbuf[i] = inbuf[i] ^ state->perm[j];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* rc4.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2000 Whistle Communications, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Subject to the following obligations and disclaimer of warranty, use and
|
||||||
|
* redistribution of this software, in source or object code forms, with or
|
||||||
|
* without modifications are expressly permitted by Whistle Communications;
|
||||||
|
* provided, however, that:
|
||||||
|
* 1. Any and all reproductions of the source or object code must include the
|
||||||
|
* copyright notice above and the following disclaimer of warranties; and
|
||||||
|
* 2. No rights are granted, in any manner or form, to use Whistle
|
||||||
|
* Communications, Inc. trademarks, including the mark "WHISTLE
|
||||||
|
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
|
||||||
|
* such appears in the above copyright notice or in the software.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
|
||||||
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
|
||||||
|
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||||
|
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
|
||||||
|
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
|
||||||
|
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
|
||||||
|
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
|
||||||
|
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
|
||||||
|
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_CRYPTO_RC4_RC4_H_
|
||||||
|
#define _SYS_CRYPTO_RC4_RC4_H_
|
||||||
|
|
||||||
|
struct rc4_state {
|
||||||
|
uint8_t perm[256];
|
||||||
|
uint8_t index1;
|
||||||
|
uint8_t index2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void rc4_init(struct rc4_state *state, const uint8_t *key, int keylen);
|
||||||
|
void rc4_crypt(struct rc4_state *state, const uint8_t *inbuf, uint8_t *outbuf,
|
||||||
|
int buflen);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,576 @@
|
||||||
|
// //////////////////////////////////////////////////////////
|
||||||
|
// sha256.cpp
|
||||||
|
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||||
|
// see http://create.stephan-brumme.com/disclaimer.html
|
||||||
|
//
|
||||||
|
// Altered for use in Xenia. Licensed under zlib license when acquired.
|
||||||
|
|
||||||
|
#include "sha256.h"
|
||||||
|
|
||||||
|
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sha256 {
|
||||||
|
|
||||||
|
/// same as reset()
|
||||||
|
SHA256::SHA256() { reset(); }
|
||||||
|
|
||||||
|
/// restart
|
||||||
|
void SHA256::reset() {
|
||||||
|
m_numBytes = 0;
|
||||||
|
m_bufferSize = 0;
|
||||||
|
|
||||||
|
// according to RFC 1321
|
||||||
|
m_hash[0] = 0x6a09e667;
|
||||||
|
m_hash[1] = 0xbb67ae85;
|
||||||
|
m_hash[2] = 0x3c6ef372;
|
||||||
|
m_hash[3] = 0xa54ff53a;
|
||||||
|
m_hash[4] = 0x510e527f;
|
||||||
|
m_hash[5] = 0x9b05688c;
|
||||||
|
m_hash[6] = 0x1f83d9ab;
|
||||||
|
m_hash[7] = 0x5be0cd19;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
inline uint32_t rotate(uint32_t a, uint32_t c) {
|
||||||
|
return (a >> c) | (a << (32 - c));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t swap(uint32_t x) {
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_bswap32(x);
|
||||||
|
#endif
|
||||||
|
#ifdef MSC_VER
|
||||||
|
return _byteswap_ulong(x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (x >> 24) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 0x00FF0000) |
|
||||||
|
(x << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mix functions for processBlock()
|
||||||
|
inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g) {
|
||||||
|
uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
|
||||||
|
uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
|
||||||
|
return term1 + term2;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c) {
|
||||||
|
uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
|
||||||
|
uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
|
||||||
|
return term1 + term2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// process 64 bytes
|
||||||
|
void SHA256::processBlock(const void* data) {
|
||||||
|
// get last hash
|
||||||
|
uint32_t a = m_hash[0];
|
||||||
|
uint32_t b = m_hash[1];
|
||||||
|
uint32_t c = m_hash[2];
|
||||||
|
uint32_t d = m_hash[3];
|
||||||
|
uint32_t e = m_hash[4];
|
||||||
|
uint32_t f = m_hash[5];
|
||||||
|
uint32_t g = m_hash[6];
|
||||||
|
uint32_t h = m_hash[7];
|
||||||
|
|
||||||
|
// data represented as 16x 32-bit words
|
||||||
|
const uint32_t* input = (uint32_t*)data;
|
||||||
|
// convert to big endian
|
||||||
|
uint32_t words[64];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && \
|
||||||
|
(__BYTE_ORDER == __BIG_ENDIAN)
|
||||||
|
words[i] = input[i];
|
||||||
|
#else
|
||||||
|
words[i] = swap(input[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t x, y; // temporaries
|
||||||
|
|
||||||
|
// first round
|
||||||
|
x = h + f1(e, f, g) + 0x428a2f98 + words[0];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0x71374491 + words[1];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0xb5c0fbcf + words[2];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0xe9b5dba5 + words[3];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x3956c25b + words[4];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0x59f111f1 + words[5];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x923f82a4 + words[6];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0xab1c5ed5 + words[7];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// secound round
|
||||||
|
x = h + f1(e, f, g) + 0xd807aa98 + words[8];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0x12835b01 + words[9];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0x243185be + words[10];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0x550c7dc3 + words[11];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x72be5d74 + words[12];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0x80deb1fe + words[13];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x9bdc06a7 + words[14];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0xc19bf174 + words[15];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 24 words
|
||||||
|
for (; i < 24; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// third round
|
||||||
|
x = h + f1(e, f, g) + 0xe49b69c1 + words[16];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0xefbe4786 + words[17];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0x0fc19dc6 + words[18];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0x240ca1cc + words[19];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x2de92c6f + words[20];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0x4a7484aa + words[21];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x5cb0a9dc + words[22];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0x76f988da + words[23];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 32 words
|
||||||
|
for (; i < 32; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// fourth round
|
||||||
|
x = h + f1(e, f, g) + 0x983e5152 + words[24];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0xa831c66d + words[25];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0xb00327c8 + words[26];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0xbf597fc7 + words[27];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0xc6e00bf3 + words[28];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0xd5a79147 + words[29];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x06ca6351 + words[30];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0x14292967 + words[31];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 40 words
|
||||||
|
for (; i < 40; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// fifth round
|
||||||
|
x = h + f1(e, f, g) + 0x27b70a85 + words[32];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0x2e1b2138 + words[33];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0x4d2c6dfc + words[34];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0x53380d13 + words[35];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x650a7354 + words[36];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0x766a0abb + words[37];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x81c2c92e + words[38];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0x92722c85 + words[39];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 48 words
|
||||||
|
for (; i < 48; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// sixth round
|
||||||
|
x = h + f1(e, f, g) + 0xa2bfe8a1 + words[40];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0xa81a664b + words[41];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0xc24b8b70 + words[42];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0xc76c51a3 + words[43];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0xd192e819 + words[44];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0xd6990624 + words[45];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0xf40e3585 + words[46];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0x106aa070 + words[47];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 56 words
|
||||||
|
for (; i < 56; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// seventh round
|
||||||
|
x = h + f1(e, f, g) + 0x19a4c116 + words[48];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0x1e376c08 + words[49];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0x2748774c + words[50];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0x34b0bcb5 + words[51];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x391c0cb3 + words[52];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0x4ed8aa4a + words[53];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0x5b9cca4f + words[54];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0x682e6ff3 + words[55];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// extend to 64 words
|
||||||
|
for (; i < 64; i++)
|
||||||
|
words[i] = words[i - 16] +
|
||||||
|
(rotate(words[i - 15], 7) ^ rotate(words[i - 15], 18) ^
|
||||||
|
(words[i - 15] >> 3)) +
|
||||||
|
words[i - 7] + (rotate(words[i - 2], 17) ^
|
||||||
|
rotate(words[i - 2], 19) ^ (words[i - 2] >> 10));
|
||||||
|
|
||||||
|
// eigth round
|
||||||
|
x = h + f1(e, f, g) + 0x748f82ee + words[56];
|
||||||
|
y = f2(a, b, c);
|
||||||
|
d += x;
|
||||||
|
h = x + y;
|
||||||
|
x = g + f1(d, e, f) + 0x78a5636f + words[57];
|
||||||
|
y = f2(h, a, b);
|
||||||
|
c += x;
|
||||||
|
g = x + y;
|
||||||
|
x = f + f1(c, d, e) + 0x84c87814 + words[58];
|
||||||
|
y = f2(g, h, a);
|
||||||
|
b += x;
|
||||||
|
f = x + y;
|
||||||
|
x = e + f1(b, c, d) + 0x8cc70208 + words[59];
|
||||||
|
y = f2(f, g, h);
|
||||||
|
a += x;
|
||||||
|
e = x + y;
|
||||||
|
x = d + f1(a, b, c) + 0x90befffa + words[60];
|
||||||
|
y = f2(e, f, g);
|
||||||
|
h += x;
|
||||||
|
d = x + y;
|
||||||
|
x = c + f1(h, a, b) + 0xa4506ceb + words[61];
|
||||||
|
y = f2(d, e, f);
|
||||||
|
g += x;
|
||||||
|
c = x + y;
|
||||||
|
x = b + f1(g, h, a) + 0xbef9a3f7 + words[62];
|
||||||
|
y = f2(c, d, e);
|
||||||
|
f += x;
|
||||||
|
b = x + y;
|
||||||
|
x = a + f1(f, g, h) + 0xc67178f2 + words[63];
|
||||||
|
y = f2(b, c, d);
|
||||||
|
e += x;
|
||||||
|
a = x + y;
|
||||||
|
|
||||||
|
// update hash
|
||||||
|
m_hash[0] += a;
|
||||||
|
m_hash[1] += b;
|
||||||
|
m_hash[2] += c;
|
||||||
|
m_hash[3] += d;
|
||||||
|
m_hash[4] += e;
|
||||||
|
m_hash[5] += f;
|
||||||
|
m_hash[6] += g;
|
||||||
|
m_hash[7] += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// add arbitrary number of bytes
|
||||||
|
void SHA256::add(const void* data, size_t numBytes) {
|
||||||
|
const uint8_t* current = (const uint8_t*)data;
|
||||||
|
|
||||||
|
if (m_bufferSize > 0) {
|
||||||
|
while (numBytes > 0 && m_bufferSize < BlockSize) {
|
||||||
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
|
numBytes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// full buffer
|
||||||
|
if (m_bufferSize == BlockSize) {
|
||||||
|
processBlock(m_buffer);
|
||||||
|
m_numBytes += BlockSize;
|
||||||
|
m_bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no more data ?
|
||||||
|
if (numBytes == 0) return;
|
||||||
|
|
||||||
|
// process full blocks
|
||||||
|
while (numBytes >= BlockSize) {
|
||||||
|
processBlock(current);
|
||||||
|
current += BlockSize;
|
||||||
|
m_numBytes += BlockSize;
|
||||||
|
numBytes -= BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep remaining bytes in buffer
|
||||||
|
while (numBytes > 0) {
|
||||||
|
m_buffer[m_bufferSize++] = *current++;
|
||||||
|
numBytes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// process final block, less than 64 bytes
|
||||||
|
void SHA256::processBuffer() {
|
||||||
|
// the input bytes are considered as bits strings, where the first bit is the
|
||||||
|
// most significant bit of the byte
|
||||||
|
|
||||||
|
// - append "1" bit to message
|
||||||
|
// - append "0" bits until message length in bit mod 512 is 448
|
||||||
|
// - append length as 64 bit integer
|
||||||
|
|
||||||
|
// number of bits
|
||||||
|
size_t paddedLength = m_bufferSize * 8;
|
||||||
|
|
||||||
|
// plus one bit set to 1 (always appended)
|
||||||
|
paddedLength++;
|
||||||
|
|
||||||
|
// number of bits must be (numBits % 512) = 448
|
||||||
|
size_t lower11Bits = paddedLength & 511;
|
||||||
|
if (lower11Bits <= 448)
|
||||||
|
paddedLength += 448 - lower11Bits;
|
||||||
|
else
|
||||||
|
paddedLength += 512 + 448 - lower11Bits;
|
||||||
|
// convert from bits to bytes
|
||||||
|
paddedLength /= 8;
|
||||||
|
|
||||||
|
// only needed if additional data flows over into a second block
|
||||||
|
unsigned char extra[BlockSize];
|
||||||
|
|
||||||
|
// append a "1" bit, 128 => binary 10000000
|
||||||
|
if (m_bufferSize < BlockSize)
|
||||||
|
m_buffer[m_bufferSize] = 128;
|
||||||
|
else
|
||||||
|
extra[0] = 128;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = m_bufferSize + 1; i < BlockSize; i++) m_buffer[i] = 0;
|
||||||
|
for (; i < paddedLength; i++) extra[i - BlockSize] = 0;
|
||||||
|
|
||||||
|
// add message length in bits as 64 bit number
|
||||||
|
uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
|
||||||
|
// find right position
|
||||||
|
unsigned char* addLength;
|
||||||
|
if (paddedLength < BlockSize)
|
||||||
|
addLength = m_buffer + paddedLength;
|
||||||
|
else
|
||||||
|
addLength = extra + paddedLength - BlockSize;
|
||||||
|
|
||||||
|
// must be big endian
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
|
||||||
|
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
|
||||||
|
*addLength = (unsigned char)(msgBits & 0xFF);
|
||||||
|
|
||||||
|
// process blocks
|
||||||
|
processBlock(m_buffer);
|
||||||
|
// flowed over into a second block ?
|
||||||
|
if (paddedLength > BlockSize) processBlock(extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return latest hash as 64 hex characters
|
||||||
|
std::string SHA256::getHash() {
|
||||||
|
// compute hash (as raw bytes)
|
||||||
|
unsigned char rawHash[HashBytes];
|
||||||
|
getHash(rawHash);
|
||||||
|
|
||||||
|
// convert to hex string
|
||||||
|
std::string result;
|
||||||
|
result.reserve(2 * HashBytes);
|
||||||
|
for (int i = 0; i < HashBytes; i++) {
|
||||||
|
static const char dec2hex[16 + 1] = "0123456789abcdef";
|
||||||
|
result += dec2hex[(rawHash[i] >> 4) & 15];
|
||||||
|
result += dec2hex[rawHash[i] & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return latest hash as bytes
|
||||||
|
void SHA256::getHash(unsigned char buffer[SHA256::HashBytes]) {
|
||||||
|
// save old hash if buffer is partially filled
|
||||||
|
uint32_t oldHash[HashValues];
|
||||||
|
for (int i = 0; i < HashValues; i++) oldHash[i] = m_hash[i];
|
||||||
|
|
||||||
|
// process remaining bytes
|
||||||
|
processBuffer();
|
||||||
|
|
||||||
|
unsigned char* current = buffer;
|
||||||
|
for (int i = 0; i < HashValues; i++) {
|
||||||
|
*current++ = (m_hash[i] >> 24) & 0xFF;
|
||||||
|
*current++ = (m_hash[i] >> 16) & 0xFF;
|
||||||
|
*current++ = (m_hash[i] >> 8) & 0xFF;
|
||||||
|
*current++ = m_hash[i] & 0xFF;
|
||||||
|
|
||||||
|
// restore old hash
|
||||||
|
m_hash[i] = oldHash[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// compute SHA256 of a memory block
|
||||||
|
std::string SHA256::operator()(const void* data, size_t numBytes) {
|
||||||
|
reset();
|
||||||
|
add(data, numBytes);
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// compute SHA256 of a string, excluding final zero
|
||||||
|
std::string SHA256::operator()(const std::string& text) {
|
||||||
|
reset();
|
||||||
|
add(text.c_str(), text.size());
|
||||||
|
return getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
// //////////////////////////////////////////////////////////
|
||||||
|
// sha256.h
|
||||||
|
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
|
||||||
|
// see http://create.stephan-brumme.com/disclaimer.html
|
||||||
|
//
|
||||||
|
// Altered for use in Xenia. Licensed under zlib license when acquired.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace sha256 {
|
||||||
|
|
||||||
|
/// compute SHA256 hash
|
||||||
|
/** Usage:
|
||||||
|
SHA256 sha256;
|
||||||
|
std::string myHash = sha256("Hello World"); // std::string
|
||||||
|
std::string myHash2 = sha256("How are you", 11); // arbitrary data, 11 bytes
|
||||||
|
|
||||||
|
// or in a streaming fashion:
|
||||||
|
|
||||||
|
SHA256 sha256;
|
||||||
|
while (more data available)
|
||||||
|
sha256.add(pointer to fresh data, number of new bytes);
|
||||||
|
std::string myHash3 = sha256.getHash();
|
||||||
|
*/
|
||||||
|
class SHA256 {
|
||||||
|
public:
|
||||||
|
/// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
|
||||||
|
enum { BlockSize = 512 / 8, HashBytes = 32 };
|
||||||
|
|
||||||
|
/// same as reset()
|
||||||
|
SHA256();
|
||||||
|
|
||||||
|
/// compute SHA256 of a memory block
|
||||||
|
std::string operator()(const void* data, size_t numBytes);
|
||||||
|
/// compute SHA256 of a string, excluding final zero
|
||||||
|
std::string operator()(const std::string& text);
|
||||||
|
|
||||||
|
/// add arbitrary number of bytes
|
||||||
|
void add(const void* data, size_t numBytes);
|
||||||
|
|
||||||
|
/// return latest hash as 64 hex characters
|
||||||
|
std::string getHash();
|
||||||
|
/// return latest hash as bytes
|
||||||
|
void getHash(unsigned char buffer[HashBytes]);
|
||||||
|
|
||||||
|
uint8_t* getBuffer() { return m_buffer; }
|
||||||
|
uint32_t* getHashValues() { return m_hash; }
|
||||||
|
|
||||||
|
size_t getTotalSize() const { return m_numBytes + m_bufferSize; }
|
||||||
|
void setTotalSize(size_t size) {
|
||||||
|
m_bufferSize = size & (BlockSize - 1);
|
||||||
|
m_numBytes = size & ~(BlockSize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// restart
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// process 64 bytes
|
||||||
|
void processBlock(const void* data);
|
||||||
|
/// process everything left in the internal buffer
|
||||||
|
void processBuffer();
|
||||||
|
|
||||||
|
/// size of processed data in bytes
|
||||||
|
uint64_t m_numBytes;
|
||||||
|
/// valid bytes in m_buffer
|
||||||
|
size_t m_bufferSize;
|
||||||
|
/// bytes not processed yet
|
||||||
|
uint8_t m_buffer[BlockSize];
|
||||||
|
|
||||||
|
enum { HashValues = HashBytes / 4 };
|
||||||
|
/// hash, stored as integers
|
||||||
|
uint32_t m_hash[HashValues];
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace sha256
|
Loading…
Reference in New Issue