xboxkrnl: Add a bunch of crypto functions

This commit is contained in:
Dr. Chat 2016-07-11 10:34:33 -05:00
parent 99f3c61fc1
commit fb87b7a3c3
14 changed files with 1506 additions and 14 deletions

View File

@ -14,6 +14,12 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#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 kernel {
@ -70,22 +76,17 @@ void XeCryptShaFinal(pointer_t<XECRYPT_SHA_STATE> sha_state,
sha1::SHA1 sha;
InitSha1(&sha, sha_state);
uint32_t digest[5];
uint8_t digest[0x14];
sha.finalize(digest);
for (int i = 0; i < 5; i++) {
sha_state->state[i] = digest[i];
}
for (uint32_t i = 0; i < out_size / 4; i++) {
out[i] = digest[i];
}
std::memcpy(out, digest, std::min((uint32_t)out_size, 0x14u));
std::memcpy(sha_state->state, digest, 0x14);
}
DECLARE_XBOXKRNL_EXPORT(XeCryptShaFinal, ExportTag::kImplemented);
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,
pointer_t<xe::be<uint32_t>> output, dword_t output_size) {
lpvoid_t output, dword_t output_size) {
sha1::SHA1 sha;
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);
}
uint32_t digest[5];
uint8_t digest[0x14];
sha.finalize(digest);
for (uint32_t i = 0; i < output_size / 4; i++) {
output[i] = digest[i];
}
std::memcpy(output, digest, std::min((uint32_t)output_size, 0x14u));
}
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?
dword_result_t XeCryptBnQw_SwapDwQwLeBe(lpqword_t qw_inp, lpqword_t qw_out,
dword_t size) {
@ -128,6 +177,161 @@ dword_result_t XeCryptBnDwLePkcs1Verify(lpvoid_t hash, lpvoid_t sig,
}
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,
KernelState* kernel_state) {}

22
third_party/crypto/des/LICENSE vendored Normal file
View File

@ -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.

6
third_party/crypto/des/README.md vendored Normal file
View File

@ -0,0 +1,6 @@
cppDES
======
Taken from [this repository](https://github.com/fffaraz/cppDES)
Modified for use by Xenia.

177
third_party/crypto/des/des.cpp vendored Normal file
View File

@ -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

51
third_party/crypto/des/des.h vendored Normal file
View File

@ -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

40
third_party/crypto/des/des3.h vendored Normal file
View File

@ -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

121
third_party/crypto/des/des_data.h vendored Normal file
View File

@ -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

38
third_party/crypto/des/des_key.h vendored Normal file
View File

@ -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

4
third_party/crypto/des/des_lookup.h vendored Normal file
View File

@ -0,0 +1,4 @@
#ifndef DES_LOOKUP_H
#define DES_LOOKUP_H
#endif // DES_LOOKUP_H

34
third_party/crypto/des/descbc.h vendored Normal file
View File

@ -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

90
third_party/crypto/rc4.c vendored Normal file
View File

@ -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];
}
}

50
third_party/crypto/rc4.h vendored Normal file
View File

@ -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

576
third_party/crypto/sha256.cpp vendored Normal file
View File

@ -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();
}
}

79
third_party/crypto/sha256.h vendored Normal file
View File

@ -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