Add SHA1 calculation for DS mode

This commit is contained in:
RocketRobz 2024-02-11 21:11:01 -07:00
parent 457a82481d
commit a52576bf67
11 changed files with 370 additions and 183 deletions

View File

@ -1,5 +1,6 @@
#include <stdint.h>
#include "../mbedtls/aes.h"
#include "sha1.h"
#include "crypto.h"
//#include "ticket0.h"
#include "utils.h"
@ -117,7 +118,7 @@ static void dsi_aes_set_key(uint32_t *rk, const uint32_t *console_id, key_mode_t
int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len) {
uint8_t digest[SHA1_LEN];
my_swiSHA1Calc(digest, data, len);
SHA1((char*)digest, data, len);
// return type of swiSHA1Verify() is declared void, so how exactly should we use it?
int ret = memcmp(digest, digest_verify, SHA1_LEN);
if (ret != 0) {
@ -153,7 +154,7 @@ void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int i
aes_set_key_enc_128_be(boot2_rk, (uint8_t*)DSi_BOOT2_KEY);
uint32_t digest[SHA1_LEN / sizeof(uint32_t)];
my_swiSHA1Calc(digest, emmc_cid, 16);
SHA1((char*)digest, (char*)emmc_cid, 16);
nand_ctr_iv[0] = digest[0];
nand_ctr_iv[1] = digest[1];
nand_ctr_iv[2] = digest[2];

View File

@ -17,9 +17,6 @@ typedef enum {
ES
} key_mode_t;
// don't want to include nds.h just for this
void my_swiSHA1Calc(void *digest, const void *buf, size_t len);
int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len);
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS);

View File

@ -5,7 +5,7 @@
#include <dirent.h>
#include <vector>
#include "my_sha1.h"
#include "sha1.h"
#include "file_browse.h"
#include "font.h"
#include "ndsheaderbanner.h"
@ -15,7 +15,8 @@
#define copyBufSize 0x8000
#define shaChunkSize 0x10000
u8* copyBuf = (u8*)0x02004000;
// u8* copyBuf = (u8*)0x02004000;
u8 copyBuf[copyBufSize];
std::vector<ClipboardFile> clipboard;
bool clipboardOn = false;
@ -88,9 +89,8 @@ bool calculateSHA1(const char *fileName, u8 *sha1) {
return false;
}
memset(sha1, 0, 20);
swiSHA1context_t ctx;
ctx.sha_block=0; //this is weird but it has to be done
my_swiSHA1Init(&ctx);
SHA1_CTX ctx;
SHA1Init(&ctx);
font->clear(false);
font->printf(firstCol, 0, false, alignStart, Palette::white, STR_CALCULATING_SHA1.c_str(), fileName);
@ -105,7 +105,7 @@ bool calculateSHA1(const char *fileName, u8 *sha1) {
while (true) {
size_t ret = fread(buf, 1, shaChunkSize, fp);
if (!ret) break;
my_swiSHA1Update(&ctx, buf, ret);
SHA1Update(&ctx, buf, ret);
scanKeys();
int keys = keysHeld();
if (keys & KEY_START) {
@ -121,7 +121,7 @@ bool calculateSHA1(const char *fileName, u8 *sha1) {
font->printf(firstCol, nameHeight + 6, false, alignStart, Palette::white, STR_N_OF_N_BYTES_PROCESSED.c_str(), ftell(fp), fsize);
font->update(false);
}
my_swiSHA1Final(sha1, &ctx);
SHA1Final(sha1, &ctx);
free(buf);
fclose(fp);
return true;

View File

@ -204,12 +204,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) {
}
operations.push_back(FileOperation::hexEdit);
// The bios SHA1 functions are only available on the DSi
// https://problemkaputt.de/gbatek.htm#biossha1functionsdsionly
if (bios9iEnabled) {
operations.push_back(FileOperation::calculateSHA1);
}
operations.push_back(FileOperation::calculateSHA1);
}
operations.push_back(FileOperation::showInfo);

View File

@ -33,7 +33,7 @@ bool screenSwapped = false;
bool arm7SCFGLocked = false;
bool isRegularDS = true;
bool bios9iEnabled = false;
// bool bios9iEnabled = false;
bool is3DS = false;
int ownNitroFSMounted;
std::string prevTime;
@ -124,7 +124,7 @@ int main(int argc, char **argv) {
fifoSendValue32(FIFO_USER_07, 0);
if (isDSiMode()) {
bios9iEnabled = true;
// bios9iEnabled = true;
if (!arm7SCFGLocked) {
//font->print(-2, -4, false, " Held - Disable NAND access", Alignment::right);
font->print(-2, -3, false, " Held - Disable cart access", Alignment::right);
@ -183,7 +183,7 @@ int main(int argc, char **argv) {
is3DS = fifoGetValue32(FIFO_USER_05) != 0xD2;
}
FILE* bios = fopen("sd:/_nds/bios9i.bin", "rb");
/* FILE* bios = fopen("sd:/_nds/bios9i.bin", "rb");
if (!bios) {
bios = fopen("sd:/_nds/bios9i_part1.bin", "rb");
}
@ -229,10 +229,10 @@ int main(int argc, char **argv) {
}
setVectorBase(0);
bios9iEnabled = true;
bios9iEnabled = true; */
nandMount(); // Returns corrupt data for some reason
}
nandMount();
// }
} else if (isRegularDS && (io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS)) {
ramdriveMount(false);
}

View File

@ -10,7 +10,7 @@ extern bool screenSwapped;
extern bool arm7SCFGLocked;
extern bool isRegularDS;
extern bool bios9iEnabled;
// extern bool bios9iEnabled;
extern bool is3DS;
extern int ownNitroFSMounted;

View File

@ -1,65 +0,0 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2017
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
#include <nds/sha1.h>
#include <nds/system.h>
extern bool bios9iEnabled;
void my_swiSHA1InitTWL(swiSHA1context_t *ctx);
void my_swiSHA1UpdateTWL(swiSHA1context_t *ctx, const void *data, size_t len);
void my_swiSHA1FinalTWL(void *digest, swiSHA1context_t *ctx);
void my_swiSHA1CalcTWL(void *digest, const void *data, size_t len);
void my_swiSHA1VerifyTWL(const void *digest1, const void *digest2);
//---------------------------------------------------------------------------------
void my_swiSHA1Init(swiSHA1context_t *ctx) {
//---------------------------------------------------------------------------------
if (bios9iEnabled) my_swiSHA1InitTWL(ctx);
}
//---------------------------------------------------------------------------------
void my_swiSHA1Update(swiSHA1context_t *ctx, const void *data, size_t len) {
//---------------------------------------------------------------------------------
if (bios9iEnabled) my_swiSHA1UpdateTWL(ctx, data, len);
}
//---------------------------------------------------------------------------------
void my_swiSHA1Final(void *digest, swiSHA1context_t *ctx) {
//---------------------------------------------------------------------------------
if (bios9iEnabled) my_swiSHA1FinalTWL(digest, ctx);
}
//---------------------------------------------------------------------------------
void my_swiSHA1Calc(void *digest, const void *data, size_t len) {
//---------------------------------------------------------------------------------
if (bios9iEnabled) my_swiSHA1CalcTWL(digest, data, len);
}
//---------------------------------------------------------------------------------
void my_swiSHA1Verify(const void *digest1, const void *digest2) {
//---------------------------------------------------------------------------------
if (bios9iEnabled) my_swiSHA1VerifyTWL(digest1, digest2);
}

View File

@ -1,87 +0,0 @@
/*---------------------------------------------------------------------------------
DSi sha1 functions
Copyright (C) 2017
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
/*! \file sha1.h
\brief DSi SHA1 functions.
*/
#ifndef MY_SHA1_H_INCLUDE
#define MY_SHA1_H_INCLUDE
#ifdef __cplusplus
extern "C" {
#endif
#include <nds/ndstypes.h>
#include <nds/sha1.h>
#include <stddef.h>
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void my_swiSHA1Init(swiSHA1context_t *ctx);
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param data buffer to process
* \param len length of data
*/
void my_swiSHA1Update(swiSHA1context_t *ctx, const void *data, size_t len);
/**
* \brief SHA-1 final digest
*
* \param digest buffer to hold SHA-1 checksum result
* \param ctx SHA-1 context
*/
void my_swiSHA1Final(void *digest, swiSHA1context_t *ctx);
/**
* \brief SHA-1 checksum
*
* \param digest buffer to hold SHA-1 checksum result
* \param data buffer to process
* \param len length of data
*/
void my_swiSHA1Calc(void *digest, const void *data, size_t len);
/**
* \brief SHA-1 verify
*
* \param digest1 buffer containing hash to verify
* \param digest2 buffer containing hash to verify
*/
void my_swiSHA1Verify(const void *digest1, const void *digest2);
#ifdef __cplusplus
}
#endif
#endif // MY_SHA1_H_INCLUDE

295
arm9/source/sha1.c Normal file
View File

@ -0,0 +1,295 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include <stdio.h>
#include <string.h>
/* for uint32_t */
#include <stdint.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(
uint32_t state[5],
const unsigned char buffer[64]
)
{
uint32_t a, b, c, d, e;
typedef union
{
unsigned char c[64];
uint32_t l[16];
} CHAR64LONG16;
#ifdef SHA1HANDSOFF
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
memcpy(block, buffer, 64);
#else
/* The following had better never be used because it causes the
* pointer-to-const buffer to be cast into a pointer to non-const.
* And the result is written through. I threw a "const" in, hoping
* this will cause a diagnostic.
*/
CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a, b, c, d, e, 0);
R0(e, a, b, c, d, 1);
R0(d, e, a, b, c, 2);
R0(c, d, e, a, b, 3);
R0(b, c, d, e, a, 4);
R0(a, b, c, d, e, 5);
R0(e, a, b, c, d, 6);
R0(d, e, a, b, c, 7);
R0(c, d, e, a, b, 8);
R0(b, c, d, e, a, 9);
R0(a, b, c, d, e, 10);
R0(e, a, b, c, d, 11);
R0(d, e, a, b, c, 12);
R0(c, d, e, a, b, 13);
R0(b, c, d, e, a, 14);
R0(a, b, c, d, e, 15);
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
memset(block, '\0', sizeof(block));
#endif
}
/* SHA1Init - Initialize new context */
void SHA1Init(
SHA1_CTX * context
)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(
SHA1_CTX * context,
const unsigned char *data,
uint32_t len
)
{
uint32_t i;
uint32_t j;
j = context->count[0];
if ((context->count[0] += len << 3) < j)
context->count[1]++;
context->count[1] += (len >> 29);
j = (j >> 3) & 63;
if ((j + len) > 63)
{
memcpy(&context->buffer[j], data, (i = 64 - j));
SHA1Transform(context->state, context->buffer);
for (; i + 63 < len; i += 64)
{
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else
i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(
unsigned char digest[20],
SHA1_CTX * context
)
{
unsigned i;
unsigned char finalcount[8];
unsigned char c;
#if 0 /* untested "improvement" by DHR */
/* Convert context->count to a sequence of bytes
* in finalcount. Second element first, but
* big-endian order within element.
* But we do it all backwards.
*/
unsigned char *fcp = &finalcount[8];
for (i = 0; i < 2; i++)
{
uint32_t t = context->count[i];
int j;
for (j = 0; j < 4; t >>= 8, j++)
*--fcp = (unsigned char) t}
#else
for (i = 0; i < 8; i++)
{
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
}
#endif
c = 0200;
SHA1Update(context, &c, 1);
while ((context->count[0] & 504) != 448)
{
c = 0000;
SHA1Update(context, &c, 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++)
{
digest[i] = (unsigned char)
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
/* Wipe variables */
memset(context, '\0', sizeof(*context));
memset(&finalcount, '\0', sizeof(finalcount));
}
void SHA1(
char *hash_out,
const char *str,
uint32_t len)
{
SHA1_CTX ctx;
unsigned int ii;
SHA1Init(&ctx);
for (ii=0; ii<len; ii+=1)
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
SHA1Final((unsigned char *)hash_out, &ctx);
}

52
arm9/source/sha1.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef SHA1_H
#define SHA1_H
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
*/
#include "stdint.h"
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct
{
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Transform(
uint32_t state[5],
const unsigned char buffer[64]
);
void SHA1Init(
SHA1_CTX * context
);
void SHA1Update(
SHA1_CTX * context,
const unsigned char *data,
uint32_t len
);
void SHA1Final(
unsigned char digest[20],
SHA1_CTX * context
);
void SHA1(
char *hash_out,
const char *str,
uint32_t len);
#if defined(__cplusplus)
}
#endif
#endif /* SHA1_H */

View File

@ -2,10 +2,10 @@
#include <stdio.h>
#include <sys/statvfs.h>
#include <nds.h>
#include "my_sha1.h"
#include "sha1.h"
#include "utils.h"
swiSHA1context_t sha1ctx;
SHA1_CTX sha1ctx;
static inline int htoi(char a){
if(a >= '0' && a <= '9'){
@ -63,9 +63,8 @@ int save_file(const char *filename, const void *buffer, size_t size, int save_sh
//iprintf("saved %s\n", filename);
}
if (save_sha1) {
sha1ctx.sha_block = 0;
my_swiSHA1Init(&sha1ctx);
my_swiSHA1Update(&sha1ctx, buffer, size);
SHA1Init(&sha1ctx);
SHA1Update(&sha1ctx, buffer, size);
save_sha1_file(filename);
}
return 0;
@ -147,7 +146,7 @@ int save_sha1_file(const char *filename) {
char *sha1_buf = (char *)malloc(len_buf + 1); // extra for \0
char *p = sha1_buf;
char *digest = (char *)malloc(20);
my_swiSHA1Final(digest, &sha1ctx);
SHA1Final(digest, &sha1ctx);
for (int i = 0; i < 20; ++i) {
p += siprintf(p, "%02X", digest[i]);
}