Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: runTests

on:
push:
branches: [ main ]
pull_request:
workflow_dispatch:

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
submodules: recursive
lfs: true

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build libzstd-dev zlib1g-dev libyaml-dev

- name: Build Confluence
run: |
git clone https://github.com/Linifadomra/Confluence.git
cmake -B Confluence/build -S Confluence \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build Confluence/build
sudo cmake --install Confluence/build

- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DSIPHON_BUILD_TESTS=ON

- name: Build
run: cmake --build build

- name: Test
run: ctest --test-dir build/test --output-on-failure

- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-output
path: test/out/
retention-days: 1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
**/build*/
**/out*/
15 changes: 5 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ add_library(gc_disc STATIC
src/disc/gc_wia.c
src/disc/gc_wbfs.c
src/disc/gc_rvz.c
src/disc/aes.c
src/disc/gc_wii.c
src/disc/lzma.c
)

target_include_directories(gc_disc PUBLIC include PRIVATE src/disc)
Expand Down Expand Up @@ -82,13 +85,5 @@ else()
endif()

if(SIPHON_BUILD_TESTS)
enable_testing()

add_executable(test_rarc test/test_rarc.c)
target_link_libraries(test_rarc PRIVATE gc_disc)
add_test(
NAME test_rarc
COMMAND test_rarc
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
add_subdirectory(test)
endif()
103 changes: 103 additions & 0 deletions src/disc/aes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <string.h>
#include "aes.h"
#define Nb 4
#define Nk 4
#define Nr 10
typedef uint8_t state_t[4][4];
static const uint8_t sbox[256]={
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16};
static const uint8_t rsbox[256]={
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d};
static const uint8_t Rcon[11]={0x8d,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
#define getSBoxValue(num) (sbox[(num)])
#define getSBoxInvert(num) (rsbox[(num)])
static void KeyExpansion(uint8_t*RoundKey,const uint8_t*Key){
unsigned i,j,k;uint8_t tempa[4];
for(i=0;i<Nk;++i){RoundKey[(i*4)+0]=Key[(i*4)+0];RoundKey[(i*4)+1]=Key[(i*4)+1];RoundKey[(i*4)+2]=Key[(i*4)+2];RoundKey[(i*4)+3]=Key[(i*4)+3];}
for(i=Nk;i<Nb*(Nr+1);++i){
k=(i-1)*4;tempa[0]=RoundKey[k+0];tempa[1]=RoundKey[k+1];tempa[2]=RoundKey[k+2];tempa[3]=RoundKey[k+3];
if(i%Nk==0){
uint8_t t=tempa[0];tempa[0]=tempa[1];tempa[1]=tempa[2];tempa[2]=tempa[3];tempa[3]=t;
tempa[0]=getSBoxValue(tempa[0]);tempa[1]=getSBoxValue(tempa[1]);tempa[2]=getSBoxValue(tempa[2]);tempa[3]=getSBoxValue(tempa[3]);
tempa[0]=tempa[0]^Rcon[i/Nk];
}
j=i*4;k=(i-Nk)*4;
RoundKey[j+0]=RoundKey[k+0]^tempa[0];RoundKey[j+1]=RoundKey[k+1]^tempa[1];RoundKey[j+2]=RoundKey[k+2]^tempa[2];RoundKey[j+3]=RoundKey[k+3]^tempa[3];
}
}
void AES_init_ctx_iv(struct AES_ctx*ctx,const uint8_t*key,const uint8_t*iv){KeyExpansion(ctx->RoundKey,key);memcpy(ctx->Iv,iv,AES_BLOCKLEN);}
static void AddRoundKey(uint8_t round,state_t*state,const uint8_t*RoundKey){
uint8_t i,j;for(i=0;i<4;++i)for(j=0;j<4;++j)(*state)[i][j]^=RoundKey[(round*Nb*4)+(i*Nb)+j];
}
static uint8_t xtime(uint8_t x){return((x<<1)^(((x>>7)&1)*0x1b));}
#define Multiply(x,y) (((y&1)*x)^((y>>1&1)*xtime(x))^((y>>2&1)*xtime(xtime(x)))^((y>>3&1)*xtime(xtime(xtime(x))))^((y>>4&1)*xtime(xtime(xtime(xtime(x))))))
static void InvMixColumns(state_t*state){
int i;uint8_t a,b,c,d;
for(i=0;i<4;++i){
a=(*state)[i][0];b=(*state)[i][1];c=(*state)[i][2];d=(*state)[i][3];
(*state)[i][0]=Multiply(a,0x0e)^Multiply(b,0x0b)^Multiply(c,0x0d)^Multiply(d,0x09);
(*state)[i][1]=Multiply(a,0x09)^Multiply(b,0x0e)^Multiply(c,0x0b)^Multiply(d,0x0d);
(*state)[i][2]=Multiply(a,0x0d)^Multiply(b,0x09)^Multiply(c,0x0e)^Multiply(d,0x0b);
(*state)[i][3]=Multiply(a,0x0b)^Multiply(b,0x0d)^Multiply(c,0x09)^Multiply(d,0x0e);
}
}
static void InvSubBytes(state_t*state){
uint8_t i,j;for(i=0;i<4;++i)for(j=0;j<4;++j)(*state)[j][i]=getSBoxInvert((*state)[j][i]);
}
static void InvShiftRows(state_t*state){
uint8_t temp;
temp=(*state)[3][1];(*state)[3][1]=(*state)[2][1];(*state)[2][1]=(*state)[1][1];(*state)[1][1]=(*state)[0][1];(*state)[0][1]=temp;
temp=(*state)[0][2];(*state)[0][2]=(*state)[2][2];(*state)[2][2]=temp;
temp=(*state)[1][2];(*state)[1][2]=(*state)[3][2];(*state)[3][2]=temp;
temp=(*state)[0][3];(*state)[0][3]=(*state)[1][3];(*state)[1][3]=(*state)[2][3];(*state)[2][3]=(*state)[3][3];(*state)[3][3]=temp;
}
static void InvCipher(state_t*state,const uint8_t*RoundKey){
uint8_t round;
AddRoundKey(Nr,state,RoundKey);
for(round=(Nr-1);;--round){
InvShiftRows(state);InvSubBytes(state);AddRoundKey(round,state,RoundKey);
if(round==0)break;
InvMixColumns(state);
}
}
static void XorWithIv(uint8_t*buf,const uint8_t*Iv){uint8_t i;for(i=0;i<AES_BLOCKLEN;++i)buf[i]^=Iv[i];}
void AES_CBC_decrypt_buffer(struct AES_ctx*ctx,uint8_t*buf,size_t length){
size_t i;uint8_t storeNextIv[AES_BLOCKLEN];
for(i=0;i<length;i+=AES_BLOCKLEN){
memcpy(storeNextIv,buf,AES_BLOCKLEN);
InvCipher((state_t*)buf,ctx->RoundKey);
XorWithIv(buf,ctx->Iv);
memcpy(ctx->Iv,storeNextIv,AES_BLOCKLEN);
buf+=AES_BLOCKLEN;
}
}
10 changes: 10 additions & 0 deletions src/disc/aes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef SIPHON_AES_H
#define SIPHON_AES_H
#include <stdint.h>
#include <stddef.h>
#define AES_BLOCKLEN 16
#define AES_keyExpSize 176
struct AES_ctx{uint8_t RoundKey[AES_keyExpSize];uint8_t Iv[AES_BLOCKLEN];};
void AES_init_ctx_iv(struct AES_ctx*ctx,const uint8_t*key,const uint8_t*iv);
void AES_CBC_decrypt_buffer(struct AES_ctx*ctx,uint8_t*buf,size_t length);
#endif
1 change: 1 addition & 0 deletions src/disc/gc_disc.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ GCDisc* gc_disc_open(const char* path) {
void gc_disc_close(GCDisc* disc) {
if (!disc) return;
if (disc->close) disc->close(disc);
gc_wii_free(disc);
gc_disc_free_parsed(disc);
if (disc->file) fclose(disc->file);
free(disc);
Expand Down
9 changes: 5 additions & 4 deletions src/disc/gc_disc_fst.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ static void mkdirs(const char* path) {
}

int gc_disc_parse_fst(GCDisc* disc) {
if (gc_wii_wrap(disc) != 0) return -1;
if (disc->read(disc, 0, disc->boot, 0x440) < 0) return -1;

memcpy(disc->gameId, disc->boot, 6);
disc->gameId[6] = '\0';

disc->dolOffset = gc_be32(disc->boot + 0x420);
disc->fstOffset = gc_be32(disc->boot + 0x424);
disc->fstSize = gc_be32(disc->boot + 0x428);
disc->dolOffset = gc_be32(disc->boot + 0x420) << disc->offsetShift;
disc->fstOffset = gc_be32(disc->boot + 0x424) << disc->offsetShift;
disc->fstSize = gc_be32(disc->boot + 0x428) << disc->offsetShift;

if (disc->read(disc, 0x440, disc->bi2, 0x2000) < 0) return -1;

Expand Down Expand Up @@ -128,7 +129,7 @@ int gc_disc_parse_fst(GCDisc* disc) {
*pathWrite++ = '\0';

disc->entries[i].name = pathStart;
disc->entries[i].discOffset = gc_be32(e + 4);
disc->entries[i].discOffset = gc_be32(e + 4) << disc->offsetShift;
disc->entries[i].size = gc_be32(e + 8);

if (e[0]) {
Expand Down
5 changes: 5 additions & 0 deletions src/disc/gc_disc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ struct GCDisc {

GCEntry* entries;
char* pathBuf;

uint32_t offsetShift;
void* wii;
};

static inline uint16_t gc_be16(const uint8_t* p) {
Expand All @@ -57,5 +60,7 @@ int gc_ciso_open(GCDisc* disc);
int gc_gcz_open(GCDisc* disc);
int gc_wbfs_open(GCDisc* disc);
int gc_wia_open(GCDisc* disc, int isRVZ);
int gc_wii_wrap(GCDisc* disc);
void gc_wii_free(GCDisc* disc);

#endif
Loading
Loading