diff --git a/ctrtool/LICENSE b/ctrtool/LICENSE deleted file mode 100644 index 3768595..0000000 --- a/ctrtool/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2012 neimod -Copyright (c) 2014 3DSGuy - -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. \ No newline at end of file diff --git a/ctrtool/Makefile b/ctrtool/Makefile deleted file mode 100644 index cd515a4..0000000 --- a/ctrtool/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Sources -SRC_DIR = . polarssl tinyxml -OBJS = $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) - -# Compiler Settings -OUTPUT = ctrtool -CXXFLAGS = -I. -CFLAGS = -O2 -Wall -Wno-unused-variable -Wno-unused-result -I. -std=c11 -CC = gcc -CXX = g++ -SYS := $(shell gcc -dumpmachine) -ifneq (, $(findstring linux, $(SYS))) - # Linux - CFLAGS += -Wno-unused-but-set-variable -else ifneq (, $(findstring cygwin, $(SYS))) - # Cygwin - CFLAGS += -Wno-unused-but-set-variable -DUSE_FILE32API - LIBS += -liconv -static-libgcc -static-libstdc++ -else ifneq (, $(findstring darwin, $(SYS))) - # OS X - LIBS += -liconv -else - #Windows Build CFG - CFLAGS += -Wno-unused-but-set-variable - LIBS += -static-libgcc -static-libstdc++ -static -lpthread -endif - -main: $(OBJS) - $(CXX) -o $(OUTPUT) $(OBJS) $(LIBS) - -clean: - rm -rf $(OUTPUT) $(OBJS) diff --git a/ctrtool/aes_keygen.c b/ctrtool/aes_keygen.c deleted file mode 100644 index eb81bdf..0000000 --- a/ctrtool/aes_keygen.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "aes_keygen.h" - -// 128bit wrap-around math -int32_t wrap_index(int32_t i) -{ - return i < 0 ? ((i % 16) + 16) % 16 : (i > 15 ? i % 16 : i); -} - -void n128_rrot(const uint8_t *in, uint32_t rot, uint8_t *out) -{ - uint32_t bit_shift, byte_shift; - - rot = rot % 128; - byte_shift = rot / 8; - bit_shift = rot % 8; - - for (int32_t i = 0; i < 16; i++) { - out[i] = (in[wrap_index(i - byte_shift)] >> bit_shift) | (in[wrap_index(i - byte_shift - 1)] << (8 - bit_shift)); - } - -} - -void n128_lrot(const uint8_t *in, uint32_t rot, uint8_t *out) -{ - uint32_t bit_shift, byte_shift; - - rot = rot % 128; - byte_shift = rot / 8; - bit_shift = rot % 8; - - for (int32_t i = 0; i < 16; i++) { - out[i] = (in[wrap_index(i + byte_shift)] << bit_shift) | (in[wrap_index(i + byte_shift + 1)] >> (8 - bit_shift)); - } -} - -/* out = a + b -*/ -void n128_add(const uint8_t *a, const uint8_t *b, uint8_t *out) -{ - uint8_t carry = 0; - uint32_t sum = 0; - - for (int i = 15; i >= 0; i--) { - sum = a[i] + b[i] + carry; - carry = sum >> 8; - out[i] = sum & 0xff; - } -} - -/* out = a - b -*/ -void n128_sub(const uint8_t *a, const uint8_t *b, uint8_t *out) -{ - uint8_t carry = 0; - uint32_t sum = 0; - - for (int i = 15; i >= 0; i--) { - sum = a[i] - (b[i] + carry); - - // check to see if anything was borrowed from next byte - if (a[i] < (b[i] + carry)) { - sum += 0x100; - carry = 1; - } - else { - carry = 0; - } - - // set value - out[i] = sum & 0xff; - } -} - -void n128_xor(const uint8_t *a, const uint8_t *b, uint8_t *out) -{ - for (int i = 0; i < 16; i++) { - out[i] = a[i] ^ b[i]; - } -} - -// keygen algorithm -void ctr_aes_keygen(const uint8_t *x, const uint8_t *y, uint8_t *key) -{ - static const uint8_t KEYGEN_CONST[16] = { 0x1F, 0xF9, 0xE9, 0xAA, 0xC5, 0xFE, 0x04, 0x08, 0x02, 0x45, 0x91, 0xDC, 0x5D, 0x52, 0x76, 0x8A }; - - // overall algo: - // key = (((x <<< 2) ^ y) + KEYGEN_CONST) >>> 41 - uint8_t x_rot[16], key_xy[16], key_xyc[16]; - - // x_rot = x <<< 2 - n128_lrot(x, 2, x_rot); - - // key_xy = x_rot ^ y - n128_xor(x_rot, y, key_xy); - - // key_xyc = key_xy + KEYGEN_CONST - n128_add(key_xy, KEYGEN_CONST, key_xyc); - - n128_rrot(key_xyc, 41, key); -} \ No newline at end of file diff --git a/ctrtool/aes_keygen.h b/ctrtool/aes_keygen.h deleted file mode 100644 index dae87a3..0000000 --- a/ctrtool/aes_keygen.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -/* - AES Key generator for the Nintendo 3DS (CTR) Consoles -*/ - -void ctr_aes_keygen(const uint8_t *x, const uint8_t *y, uint8_t *key); diff --git a/ctrtool/cia.c b/ctrtool/cia.c deleted file mode 100644 index 85b16b8..0000000 --- a/ctrtool/cia.c +++ /dev/null @@ -1,317 +0,0 @@ -#include -#include -#include -#include "types.h" -#include "utils.h" -#include "cia.h" -#include - - -void cia_init(cia_context* ctx) -{ - memset(ctx, 0, sizeof(cia_context)); - - tik_init(&ctx->tik); - tmd_init(&ctx->tmd); -} - -void cia_set_file(cia_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void cia_set_offset(cia_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void cia_set_size(cia_context* ctx, u64 size) -{ - ctx->size = size; -} - - -void cia_set_usersettings(cia_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - - -void cia_save(cia_context* ctx, u32 type, u32 flags) -{ - u64 offset; - u64 size; - u16 contentflags; - u16 contentindex; - u8 docrypto; - filepath* path = 0; - ctr_tmd_body *body; - ctr_tmd_contentchunk *chunk; - unsigned int i; - char tmpname[255]; - - switch(type) - { - case CIATYPE_CERTS: - offset = ctx->offsetcerts; - size = ctx->sizecert; - path = settings_get_certs_path(ctx->usersettings); - break; - - case CIATYPE_TIK: - offset = ctx->offsettik; - size = ctx->sizetik; - path = settings_get_tik_path(ctx->usersettings); - break; - - case CIATYPE_TMD: - offset = ctx->offsettmd; - size = ctx->sizetmd; - path = settings_get_tmd_path(ctx->usersettings); - break; - - case CIATYPE_CONTENT: - offset = ctx->offsetcontent; - size = ctx->sizecontent; - path = settings_get_content_path(ctx->usersettings); - - break; - - case CIATYPE_META: - offset = ctx->offsetmeta; - size = ctx->sizemeta; - path = settings_get_meta_path(ctx->usersettings);; - break; - - default: - fprintf(stderr, "Error, unknown CIA type specified\n"); - return; - break; - } - - if (path == 0 || path->valid == 0) - return; - - switch(type) - { - case CIATYPE_CERTS: fprintf(stdout, "Saving certs to %s\n", path->pathname); break; - case CIATYPE_TIK: fprintf(stdout, "Saving tik to %s\n", path->pathname); break; - case CIATYPE_TMD: fprintf(stdout, "Saving tmd to %s\n", path->pathname); break; - case CIATYPE_CONTENT: - - body = tmd_get_body(&ctx->tmd); - chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS)); - - for(i = 0; i < getbe16(body->contentcount); i++) { - contentflags = getbe16(chunk->type); - contentindex = getbe16(chunk->index); - docrypto = (contentflags & 1) && !(flags & PlainFlag); - - if(ctx->header.contentindex[contentindex >> 3] & (0x80 >> (contentindex & 7))) { - sprintf(tmpname, "%s.%04x.%08x", path->pathname, contentindex, getbe32(chunk->id)); - fprintf(stdout, "Saving content #%04x to %s\n", contentindex, tmpname); - - if(docrypto) // Decrypt if needed - { - ctx->iv[0] = (contentindex >> 8) & 0xff; - ctx->iv[1] = contentindex & 0xff; - - ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv); - } - - cia_save_blob(ctx, tmpname, offset, getbe64(chunk->size) & 0xffffffff, docrypto); - - offset += getbe64(chunk->size) & 0xffffffff; - } - chunk++; - } - - memset(ctx->iv, 0, 16); - - return; - break; - - case CIATYPE_META: fprintf(stdout, "Saving meta to %s\n", path->pathname); break; - } - - cia_save_blob(ctx, path->pathname, offset, size, 0); -} - -void cia_save_blob(cia_context *ctx, char *out_path, u64 offset, u64 size, int do_cbc) -{ - FILE *fout = 0; - u8 buffer[16*1024]; - - fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); - - fout = fopen(out_path, "wb"); - if (fout == NULL) - { - fprintf(stdout, "Error opening out file %s\n", out_path); - goto clean; - } - - while(size) - { - u32 max = sizeof(buffer); - if (max > size) - max = (u32) size; - - if (max != fread(buffer, 1, max, ctx->file)) - { - fprintf(stdout, "Error reading file\n"); - goto clean; - } - - if (do_cbc == 1) - ctr_decrypt_cbc(&ctx->aes, buffer, buffer, max); - - if (max != fwrite(buffer, 1, max, fout)) - { - fprintf(stdout, "Error writing file\n"); - goto clean; - } - - size -= max; - } - -clean: - if (fout) - fclose(fout); -} - - -void cia_process(cia_context* ctx, u32 actions) -{ - fseeko64(ctx->file, 0, SEEK_SET); - - if (fread(&ctx->header, 1, sizeof(ctr_ciaheader), ctx->file) != sizeof(ctr_ciaheader)) - { - fprintf(stderr, "Error reading CIA header\n"); - goto clean; - } - - ctx->sizeheader = getle32(ctx->header.headersize); - ctx->sizecert = getle32(ctx->header.certsize); - ctx->sizetik = getle32(ctx->header.ticketsize); - ctx->sizetmd = getle32(ctx->header.tmdsize); - ctx->sizecontent = getle64(ctx->header.contentsize); - ctx->sizemeta = getle32(ctx->header.metasize); - - ctx->offsetcerts = align(ctx->sizeheader, 64); - ctx->offsettik = align((u32) (ctx->offsetcerts + ctx->sizecert), 64); - ctx->offsettmd = align((u32) (ctx->offsettik + ctx->sizetik), 64); - ctx->offsetcontent = align((u32) (ctx->offsettmd + ctx->sizetmd), 64); - ctx->offsetmeta = align64(ctx->offsetcontent + ctx->sizecontent, 64); - - if (actions & InfoFlag) - cia_print(ctx); - - - tik_set_file(&ctx->tik, ctx->file); - tik_set_offset(&ctx->tik, ctx->offsettik); - tik_set_size(&ctx->tik, ctx->sizetik); - tik_set_usersettings(&ctx->tik, ctx->usersettings); - - tik_process(&ctx->tik, actions); - memset(ctx->iv, 0, 16); - - if (tik_get_titlekey(&ctx->tik)) - memcpy(ctx->titlekey, tik_get_titlekey(&ctx->tik), 16); - else if (settings_get_title_key(ctx->usersettings)) - memcpy(ctx->titlekey, settings_get_title_key(ctx->usersettings), 16); - - tmd_set_file(&ctx->tmd, ctx->file); - tmd_set_offset(&ctx->tmd, ctx->offsettmd); - tmd_set_size(&ctx->tmd, ctx->sizetmd); - tmd_set_usersettings(&ctx->tmd, ctx->usersettings); - tmd_process(&ctx->tmd, (actions & ~InfoFlag)); - - if (actions & VerifyFlag) - { - cia_verify_contents(ctx, actions); - } - - if (actions & InfoFlag || actions & VerifyFlag) - tmd_print(&ctx->tmd); - - if (actions & ExtractFlag) - { - cia_save(ctx, CIATYPE_CERTS, actions); - cia_save(ctx, CIATYPE_TMD, actions); - cia_save(ctx, CIATYPE_TIK, actions); - cia_save(ctx, CIATYPE_META, actions); - cia_save(ctx, CIATYPE_CONTENT, actions); - } - -clean: - return; -} - -void cia_verify_contents(cia_context *ctx, u32 actions) -{ - u16 contentflags; - u16 contentindex; - ctr_tmd_body *body; - ctr_tmd_contentchunk *chunk; - u8 *verify_buf; - u32 content_size=0; - unsigned i; - - // verify TMD content hashes, requires decryption .. - body = tmd_get_body(&ctx->tmd); - chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS)); - - fseeko64(ctx->file, ctx->offset + ctx->offsetcontent, SEEK_SET); - for(i = 0; i < getbe16(body->contentcount); i++) - { - contentindex = getbe16(chunk->index); - - if(ctx->header.contentindex[contentindex >> 3] & (0x80 >> (contentindex & 7))) - { - content_size = getbe64(chunk->size) & 0xffffffff; - - contentflags = getbe16(chunk->type); - - verify_buf = malloc(content_size); - fread(verify_buf, content_size, 1, ctx->file); - - if(contentflags & 1 && !(actions & PlainFlag)) // Decrypt if needed - { - ctx->iv[0] = (contentindex >> 8) & 0xff; - ctx->iv[1] = contentindex & 0xff; - - ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv); - - ctr_decrypt_cbc(&ctx->aes, verify_buf, verify_buf, content_size); - } - - if (ctr_sha_256_verify(verify_buf, content_size, chunk->hash) == Good) - ctx->tmd.content_hash_stat[i] = 1; - else - ctx->tmd.content_hash_stat[i] = 2; - - free(verify_buf); - } - chunk++; - } -} - -void cia_print(cia_context* ctx) -{ - ctr_ciaheader* header = &ctx->header; - - fprintf(stdout, "Header size 0x%08x\n", getle32(header->headersize)); - fprintf(stdout, "Type %04x\n", getle16(header->type)); - fprintf(stdout, "Version %04x\n", getle16(header->version)); - fprintf(stdout, "Certificates offset: 0x%"PRIx64"\n", ctx->offsetcerts); - fprintf(stdout, "Certificates size: 0x%x\n", ctx->sizecert); - fprintf(stdout, "Ticket offset: 0x%"PRIx64"\n", ctx->offsettik); - fprintf(stdout, "Ticket size 0x%x\n", ctx->sizetik); - fprintf(stdout, "TMD offset: 0x%"PRIx64"\n", ctx->offsettmd); - fprintf(stdout, "TMD size: 0x%x\n", ctx->sizetmd); - fprintf(stdout, "Meta offset: 0x%"PRIx64"\n", ctx->offsetmeta); - fprintf(stdout, "Meta size: 0x%x\n", ctx->sizemeta); - fprintf(stdout, "Content offset: 0x%"PRIx64"\n", ctx->offsetcontent); - fprintf(stdout, "Content size: 0x%"PRIx64"\n", ctx->sizecontent); -} diff --git a/ctrtool/cia.h b/ctrtool/cia.h deleted file mode 100644 index 52b0152..0000000 --- a/ctrtool/cia.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _CIA_H_ -#define _CIA_H_ - -#include "types.h" -#include "filepath.h" -#include "tik.h" -#include "tmd.h" -#include "ctr.h" -#include "settings.h" - -typedef enum -{ - CIATYPE_CERTS, - CIATYPE_TMD, - CIATYPE_TIK, - CIATYPE_CONTENT, - CIATYPE_META, -} cia_types; - -typedef struct -{ - u8 headersize[4]; - u8 type[2]; - u8 version[2]; - u8 certsize[4]; - u8 ticketsize[4]; - u8 tmdsize[4]; - u8 metasize[4]; - u8 contentsize[8]; - u8 contentindex[0x2000]; -} ctr_ciaheader; - -typedef struct -{ - FILE* file; - u64 offset; - u64 size; - u8 titlekey[16]; - u8 iv[16]; - ctr_ciaheader header; - ctr_aes_context aes; - settings* usersettings; - - tik_context tik; - tmd_context tmd; - - u32 sizeheader; - u32 sizecert; - u32 sizetik; - u32 sizetmd; - u64 sizecontent; - u32 sizemeta; - - u64 offsetcerts; - u64 offsettik; - u64 offsettmd; - u64 offsetcontent; - u64 offsetmeta; -} cia_context; - -void cia_init(cia_context* ctx); -void cia_set_file(cia_context* ctx, FILE* file); -void cia_set_offset(cia_context* ctx, u64 offset); -void cia_set_size(cia_context* ctx, u64 size); -void cia_set_usersettings(cia_context* ctx, settings* usersettings); -void cia_print(cia_context* ctx); -void cia_save(cia_context* ctx, u32 type, u32 flags); -void cia_process(cia_context* ctx, u32 actions); -void cia_save_blob(cia_context *ctx, char *out_path, u64 offset, u64 size, int do_cbc); -void cia_verify_contents(cia_context *ctx, u32 actions); - -#endif // _CIA_H_ diff --git a/ctrtool/ctr.c b/ctrtool/ctr.c deleted file mode 100644 index 54cfc0f..0000000 --- a/ctrtool/ctr.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include -#include - -#include "ctr.h" -#include "utils.h" - - -void ctr_set_iv( ctr_aes_context* ctx, - u8 iv[16] ) -{ - memcpy(ctx->iv, iv, 16); -} - -void ctr_add_counter( ctr_aes_context* ctx, - u32 block_num ) -{ - u32 ctr[4]; - ctr[3] = getbe32(&ctx->ctr[0]); - ctr[2] = getbe32(&ctx->ctr[4]); - ctr[1] = getbe32(&ctx->ctr[8]); - ctr[0] = getbe32(&ctx->ctr[12]); - - for (u32 i = 0; i < 4; i++) { - u64 total = ctr[i] + block_num; - // if there wasn't a wrap around, add the two together and exit - if (total <= 0xffffffff) { - ctr[i] += block_num; - break; - } - - // add the difference - ctr[i] = (u32)(total - 0x100000000); - // carry to next word - block_num = (u32)(total >> 32); - } - - putbe32(ctx->ctr + 0x00, ctr[3]); - putbe32(ctx->ctr + 0x04, ctr[2]); - putbe32(ctx->ctr + 0x08, ctr[1]); - putbe32(ctx->ctr + 0x0C, ctr[0]); -} - -void ctr_set_counter( ctr_aes_context* ctx, - u8 ctr[16] ) -{ - memcpy(ctx->ctr, ctr, 16); -} - - -void ctr_init_key(ctr_aes_context* ctx, - u8 key[16]) -{ - aes_setkey_enc(&ctx->aes, key, 128); -} - -void ctr_init_counter( ctr_aes_context* ctx, - u8 ctr[16] ) -{ - ctr_set_counter(ctx, ctr); -} - - -void ctr_crypt_counter_block( ctr_aes_context* ctx, - u8 input[16], - u8 output[16] ) -{ - int i; - u8 stream[16]; - - - aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream); - - - if (input) - { - for(i=0; i<16; i++) - { - output[i] = stream[i] ^ input[i]; - } - } - else - { - for(i=0; i<16; i++) - output[i] = stream[i]; - } - - ctr_add_counter(ctx, 1); -} - - -void ctr_crypt_counter( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ) -{ - u8 stream[16]; - u32 i; - - while(size >= 16) - { - ctr_crypt_counter_block(ctx, input, output); - - if (input) - input += 16; - if (output) - output += 16; - - size -= 16; - } - - if (size) - { - memset(stream, 0, 16); - ctr_crypt_counter_block(ctx, stream, stream); - - if (input) - { - for(i=0; iaes, key, 128); - ctr_set_iv(ctx, iv); -} - -void ctr_init_cbc_decrypt( ctr_aes_context* ctx, - u8 key[16], - u8 iv[16] ) -{ - aes_setkey_dec(&ctx->aes, key, 128); - ctr_set_iv(ctx, iv); -} - -void ctr_encrypt_cbc( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ) -{ - aes_crypt_cbc(&ctx->aes, AES_ENCRYPT, size, ctx->iv, input, output); -} - -void ctr_decrypt_cbc( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ) -{ - aes_crypt_cbc(&ctx->aes, AES_DECRYPT, size, ctx->iv, input, output); -} - -void ctr_sha_256( const u8* data, - u32 size, - u8 hash[0x20] ) -{ - sha2(data, size, hash, 0); -} - -int ctr_sha_256_verify( const u8* data, - u32 size, - const u8 checkhash[0x20] ) -{ - u8 hash[0x20]; - - sha2(data, size, hash, 0); - - if (memcmp(hash, checkhash, 0x20) == 0) - return Good; - else - return Fail; -} - -void ctr_sha_256_init( ctr_sha256_context* ctx ) -{ - sha2_starts(&ctx->sha, 0); -} - -void ctr_sha_256_update( ctr_sha256_context* ctx, - const u8* data, - u32 size ) -{ - sha2_update(&ctx->sha, data, size); -} - - -void ctr_sha_256_finish( ctr_sha256_context* ctx, - u8 hash[0x20] ) -{ - sha2_finish(&ctx->sha, hash); -} - - -void ctr_rsa_init_key_pubmodulus(rsakey2048* key, u8 modulus[0x100]) -{ - u8 exponent[3] = {0x01, 0x00, 0x01}; - - ctr_rsa_init_key_pub(key, modulus, exponent); -} - -void ctr_rsa_init_key_pub(rsakey2048* key, u8 modulus[0x100], u8 exponent[3]) -{ - key->keytype = RSAKEY_PUB; - memcpy(key->n, modulus, 0x100); - memcpy(key->e, exponent, 3); -} - -int ctr_rsa_init(ctr_rsa_context* ctx, rsakey2048* key) -{ - rsa_init(&ctx->rsa, RSA_PKCS_V15, 0); - ctx->rsa.len = 0x100; - - if (key->keytype == RSAKEY_INVALID) - goto clean; - - if (mpi_read_binary(&ctx->rsa.N, key->n, sizeof(key->n))) - goto clean; - if (mpi_read_binary(&ctx->rsa.E, key->e, sizeof(key->e))) - goto clean; - if (rsa_check_pubkey(&ctx->rsa)) - goto clean; - - if (key->keytype == RSAKEY_PRIV) - { - if (mpi_read_binary(&ctx->rsa.D, key->d, sizeof(key->d))) - goto clean; - if (mpi_read_binary(&ctx->rsa.P, key->p, sizeof(key->p))) - goto clean; - if (mpi_read_binary(&ctx->rsa.Q, key->q, sizeof(key->q))) - goto clean; - if (mpi_read_binary(&ctx->rsa.DP, key->dp, sizeof(key->dp))) - goto clean; - if (mpi_read_binary(&ctx->rsa.DQ, key->dq, sizeof(key->dq))) - goto clean; - if (mpi_read_binary(&ctx->rsa.QP, key->qp, sizeof(key->qp))) - goto clean; - if (rsa_check_privkey(&ctx->rsa)) - goto clean; - } - - return 1; -clean: - return 0; -} - -int ctr_rsa_verify_hash(const u8 signature[0x100], const u8 hash[0x20], rsakey2048* key) -{ - ctr_rsa_context ctx; - u32 result; -// u8 output[0x100]; - - if (key->keytype == RSAKEY_INVALID) - return Fail; - - ctr_rsa_init(&ctx, key); -// memset(output, 0, 0x100); -// result = ctr_rsa_public(signature, output, key); -// printf("Result = %d\n", result); -// memdump(stdout, "output: ", output, 0x100); - - result = rsa_pkcs1_verify(&ctx.rsa, RSA_PUBLIC, SIG_RSA_SHA256, 0x20, hash, (u8*)signature); - - ctr_rsa_free(&ctx); - - if (result == 0) - return Good; - else - return Fail; -} - - -int ctr_rsa_sign_hash(const u8 hash[0x20], u8 signature[0x100], rsakey2048* key) -{ - ctr_rsa_context ctx; - u32 result; - - ctr_rsa_init(&ctx, key); - - result = rsa_pkcs1_verify(&ctx.rsa, RSA_PUBLIC, SIG_RSA_SHA256, 0x20, hash, (u8*)signature); - result = rsa_pkcs1_sign(&ctx.rsa, RSA_PRIVATE, SIG_RSA_SHA256, 0x20, hash, signature); - - ctr_rsa_free(&ctx); - - if (result == 0) - return 1; - else - return 0; -} - -int ctr_rsa_public(const u8 signature[0x100], u8 output[0x100], rsakey2048* key) -{ - ctr_rsa_context ctx; - u32 result; - - ctr_rsa_init(&ctx, key); - - result = rsa_public(&ctx.rsa, signature, output); - - ctr_rsa_free(&ctx); - - if (result == 0) - return 1; - else - return 0; -} - - -void ctr_rsa_free(ctr_rsa_context* ctx) -{ - rsa_free(&ctx->rsa); -} - -/* - * Generate DP, DQ, QP based on private key - */ -#if 0 -static int ctr_rsa_key_init(ctr_rsa_context* ctx ) -{ - int ret; - mpi P1, Q1; - - mpi_init( &P1, &Q1, NULL ); - - MPI_CHK( mpi_sub_int( &P1, &ctx->rsa.P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->rsa.Q, 1 ) ); - - /* - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MPI_CHK( mpi_mod_mpi( &ctx->rsa.DP, &ctx->rsa.D, &P1 ) ); - MPI_CHK( mpi_mod_mpi( &ctx->rsa.DQ, &ctx->rsa.D, &Q1 ) ); - MPI_CHK( mpi_inv_mod( &ctx->rsa.QP, &ctx->rsa.Q, &ctx->rsa.P ) ); - -cleanup: - - mpi_free(&Q1, &P1, NULL ); - - if( ret != 0 ) - { - rsa_free( &ctx->rsa ); - return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret ); - } - - return( 0 ); -} -#endif \ No newline at end of file diff --git a/ctrtool/ctr.h b/ctrtool/ctr.h deleted file mode 100644 index 48b61e5..0000000 --- a/ctrtool/ctr.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef _CTR_H_ -#define _CTR_H_ - -#include "polarssl/aes.h" -#include "polarssl/rsa.h" -#include "polarssl/sha2.h" -#include "types.h" -#include "keyset.h" - -#define MAGIC_NCCH 0x4843434E -#define MAGIC_NCSD 0x4453434E -#define MAGIC_FIRM 0x4D524946 -#define MAGIC_CWAV 0x56415743 -#define MAGIC_IVFC 0x43465649 - -#define SIZE_128MB (128 * 1024 * 1024) - -typedef enum -{ - FILETYPE_UNKNOWN = 0, - FILETYPE_CCI, - FILETYPE_CXI, - FILETYPE_CIA, - FILETYPE_EXHEADER, - FILETYPE_TMD, - FILETYPE_LZSS, - FILETYPE_FIRM, - FILETYPE_CWAV, - FILETYPE_EXEFS, - FILETYPE_ROMFS -} ctr_filetypes; - -typedef struct -{ - u8 ctr[16]; - u8 iv[16]; - aes_context aes; -} ctr_aes_context; - -typedef struct -{ - rsa_context rsa; -} ctr_rsa_context; - -typedef struct -{ - sha2_context sha; -} ctr_sha256_context; - - -#ifdef __cplusplus -extern "C" { -#endif - -void ctr_set_iv( ctr_aes_context* ctx, - u8 iv[16] ); - -void ctr_add_counter( ctr_aes_context* ctx, - u32 block_num ); - -void ctr_set_counter( ctr_aes_context* ctx, - u8 ctr[16] ); - -void ctr_init_key(ctr_aes_context* ctx, - u8 key[16]); - - -void ctr_init_counter( ctr_aes_context* ctx, - u8 ctr[16] ); - - -void ctr_crypt_counter_block( ctr_aes_context* ctx, - u8 input[16], - u8 output[16] ); - - -void ctr_crypt_counter( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ); - - -void ctr_init_cbc_encrypt( ctr_aes_context* ctx, - u8 key[16], - u8 iv[16] ); - -void ctr_init_cbc_decrypt( ctr_aes_context* ctx, - u8 key[16], - u8 iv[16] ); - -void ctr_encrypt_cbc( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ); - -void ctr_decrypt_cbc( ctr_aes_context* ctx, - u8* input, - u8* output, - u32 size ); - -void ctr_rsa_init_key_pubmodulus( rsakey2048* key, - u8 modulus[0x100] ); - -void ctr_rsa_init_key_pub( rsakey2048* key, - u8 modulus[0x100], - u8 exponent[3] ); - -int ctr_rsa_init( ctr_rsa_context* ctx, - rsakey2048* key ); - - -void ctr_rsa_free( ctr_rsa_context* ctx ); - -int ctr_rsa_verify_hash( const u8 signature[0x100], - const u8 hash[0x20], - rsakey2048* key); - -int ctr_rsa_sign_hash( const u8 hash[0x20], - u8 signature[0x100], - rsakey2048* key ); - -int ctr_rsa_public( const u8 signature[0x100], - u8 output[0x100], - rsakey2048* key ); - -void ctr_sha_256( const u8* data, - u32 size, - u8 hash[0x20] ); - -int ctr_sha_256_verify( const u8* data, - u32 size, - const u8 checkhash[0x20] ); - - -void ctr_sha_256_init( ctr_sha256_context* ctx ); - -void ctr_sha_256_update( ctr_sha256_context* ctx, - const u8* data, - u32 size ); - - -void ctr_sha_256_finish( ctr_sha256_context* ctx, - u8 hash[0x20] ); - -#ifdef __cplusplus -} -#endif - -#endif // _CTR_H_ diff --git a/ctrtool/ctrtool.sln b/ctrtool/ctrtool.sln deleted file mode 100644 index ab9464c..0000000 --- a/ctrtool/ctrtool.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ctrtool", "ctrtool.vcxproj", "{96F5CA15-30DA-4DF5-9DFF-523D58D38001}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96F5CA15-30DA-4DF5-9DFF-523D58D38001}.Debug|Win32.ActiveCfg = Debug|Win32 - {96F5CA15-30DA-4DF5-9DFF-523D58D38001}.Debug|Win32.Build.0 = Debug|Win32 - {96F5CA15-30DA-4DF5-9DFF-523D58D38001}.Release|Win32.ActiveCfg = Release|Win32 - {96F5CA15-30DA-4DF5-9DFF-523D58D38001}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/ctrtool/ctrtool.vcproj b/ctrtool/ctrtool.vcproj deleted file mode 100644 index d3e8b0d..0000000 --- a/ctrtool/ctrtool.vcproj +++ /dev/null @@ -1,442 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ctrtool/ctrtool.vcxproj b/ctrtool/ctrtool.vcxproj deleted file mode 100644 index 21abef9..0000000 --- a/ctrtool/ctrtool.vcxproj +++ /dev/null @@ -1,164 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {96F5CA15-30DA-4DF5-9DFF-523D58D38001} - ctrtooltje - Win32Proj - - - - Application - v140 - Unicode - true - - - Application - v140 - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>11.0.50727.1 - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - - - - Disabled - windows;.;%(AdditionalIncludeDirectories) - WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - Level3 - EditAndContinue - 4996;%(DisableSpecificWarnings) - false - - - true - Console - MachineX86 - - - - - MaxSpeed - true - windows;.;%(AdditionalIncludeDirectories) - WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - true - - Level3 - ProgramDatabase - - - true - Console - true - true - MachineX86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ctrtool/ctrtool.vcxproj.filters b/ctrtool/ctrtool.vcxproj.filters deleted file mode 100644 index 8f0b392..0000000 --- a/ctrtool/ctrtool.vcxproj.filters +++ /dev/null @@ -1,225 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {dfec7c2d-ac92-481f-a1eb-732b0669b7d1} - - - {dd509a5e-b804-4879-b0b7-876718c9621a} - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {d16b9918-7159-4a81-a0b7-521c2b2f8a30} - - - {492dc50f-e790-426b-b991-86306ad69fd4} - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\polarssl - - - Source Files\polarssl - - - Source Files\polarssl - - - Source Files\polarssl - - - Source Files\tinyxml - - - Source Files\tinyxml - - - Source Files\tinyxml - - - Source Files\tinyxml - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\polarssl - - - Header Files\polarssl - - - Header Files\polarssl - - - Header Files\polarssl - - - Header Files\polarssl - - - Header Files\polarssl - - - Header Files\tinyxml - - - Header Files\tinyxml - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/ctrtool/cwav.c b/ctrtool/cwav.c deleted file mode 100644 index cfe39d8..0000000 --- a/ctrtool/cwav.c +++ /dev/null @@ -1,1003 +0,0 @@ -#include -#include -#include - -#include "types.h" -#include "cwav.h" -#include "utils.h" -#include "stream.h" - -#define BUFFERSIZE (4*1024) -#define SAMPLECOUNT 1024 - -static const int ima_adpcm_step_table[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 -}; - -static const int ima_adpcm_index_table[16] = { - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8 -}; - -void cwav_init(cwav_context* ctx) -{ - memset(ctx, 0, sizeof(cwav_context)); -} - -void cwav_set_file(cwav_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void cwav_set_offset(cwav_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void cwav_set_size(cwav_context* ctx, u64 size) -{ - ctx->size = size; -} - -void cwav_set_usersettings(cwav_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void cwav_process(cwav_context* ctx, u32 actions) -{ - u32 i; - u32 infoheaderoffset; - - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, sizeof(cwav_header), ctx->file); - - infoheaderoffset = getle32(ctx->header.infoblockref.offset); - - fseeko64(ctx->file, ctx->offset + infoheaderoffset, SEEK_SET); - fread(&ctx->infoheader, 1, sizeof(cwav_infoheader), ctx->file); - - ctx->channelcount = getle32(ctx->infoheader.channelcount); - if (ctx->channelcount) - { - ctx->channel = malloc(ctx->channelcount * sizeof(cwav_channel)); - - for(i=0; ichannelcount; i++) - { - fread(&ctx->channel[i].inforef, sizeof(cwav_reference), 1, ctx->file); - } - - for(i=0; ichannelcount; i++) - { - u32 channeloffset = infoheaderoffset + 0x1C + getle32(ctx->channel[i].inforef.offset); - - fseeko64(ctx->file, ctx->offset + channeloffset, SEEK_SET); - fread(&ctx->channel[i].info, sizeof(cwav_channelinfo), 1, ctx->file); - - if (ctx->infoheader.encoding == CWAV_ENCODING_DSPADPCM) - { - if (getle16(ctx->channel[i].info.codecref.idtype) == 0x300) - { - u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset); - - fseeko64(ctx->file, ctx->offset + codecoffset, SEEK_SET); - fread(&ctx->channel[i].infodspadpcm, sizeof(cwav_dspadpcminfo), 1, ctx->file); - } - } - else if (ctx->infoheader.encoding == CWAV_ENCODING_IMAADPCM) - { - if (getle16(ctx->channel[i].info.codecref.idtype) == 0x301) - { - u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset); - - fseeko64(ctx->file, ctx->offset + codecoffset, SEEK_SET); - fread(&ctx->channel[i].infoimaadpcm, sizeof(cwav_imaadpcminfo), 1, ctx->file); - } - } - } - } - - - if (actions & InfoFlag) - { - cwav_print(ctx); - } - - if (actions & ExtractFlag) - { - filepath* path = settings_get_wav_path(ctx->usersettings); - - if (path && path->valid) - cwav_save_to_wav(ctx, path->pathname); - } - - - free(ctx->channel); -} - - -void cwav_write_wav_header(cwav_context* ctx, stream_out_context* outstreamctx, u32 size) -{ - wav_pcm_header header; - u32 samplerate = getle32(ctx->infoheader.samplerate); - u32 channelcount = ctx->channelcount; - - - putle32(header.chunkid, 0x46464952); - putle32(header.chunksize, 36 + size); - putle32(header.format, 0x45564157); - putle32(header.subchunk1id, 0x20746d66); - putle32(header.subchunk1size, 16); - putle16(header.audioformat, 1); - putle16(header.numchannels, channelcount); - putle32(header.samplerate, samplerate); - putle32(header.byterate, samplerate * channelcount * 2); - putle16(header.blockalign, channelcount * 2); - putle16(header.bitspersample, 16); - - putle32(header.subchunk2id, 0x61746164); - putle32(header.subchunk2size, size); - - stream_out_buffer(outstreamctx, &header, sizeof(wav_pcm_header)); -} - -int cwav_dspadpcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx) -{ - u32 s, c, i; - int result = 0; - cwav_dspadpcmstate state; - u32 loopcount = settings_get_cwav_loopcount(ctx->usersettings); - - cwav_dspadpcm_init(&state); - - if (0 == cwav_dspadpcm_allocate(&state, ctx)) - goto clean; - - for(i=0; i<1+loopcount; i++) - { - int isloop = (i != 0); - - if (0 == cwav_dspadpcm_setup(&state, ctx, isloop)) - goto clean; - - while(1) - { - if (0 == cwav_dspadpcm_decode(&state, ctx)) - goto clean; - - if (state.samplecountavailable == 0) - break; - - for(s=0; schannelcount; c++) - { - s16 sampledata = state.channelstate[c].samplebuffer[s]; - - if (!stream_out_byte(outstreamctx, 0xFF & sampledata) || !stream_out_byte(outstreamctx, 0xFF & (sampledata>>8))) - { - fprintf(stderr, "Error writing output stream\n"); - goto clean; - } - } - } - } - } - - result = 1; - -clean: - cwav_dspadpcm_destroy(&state); - - return result; -} - - -int cwav_imaadpcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx) -{ - u32 s, c, i; - int result = 0; - cwav_imaadpcmstate state; - u32 loopcount = settings_get_cwav_loopcount(ctx->usersettings); - - - cwav_imaadpcm_init(&state); - if (0 == cwav_imaadpcm_allocate(&state, ctx)) - goto clean; - - for(i=0; i<1+loopcount; i++) - { - int isloop = (i != 0); - - if (0 == cwav_imaadpcm_setup(&state, ctx, isloop)) - goto clean; - - while(1) - { - if (0 == cwav_imaadpcm_decode(&state, ctx)) - goto clean; - - if (state.samplecountavailable == 0) - break; - - for(s=0; schannelcount; c++) - { - s16 sampledata = state.channelstate[c].samplebuffer[s]; - - if (!stream_out_byte(outstreamctx, 0xFF & sampledata) || !stream_out_byte(outstreamctx, 0xFF & (sampledata>>8))) - { - fprintf(stderr, "Error writing output stream\n"); - goto clean; - } - } - } - } - } - - result = 1; - -clean: - cwav_imaadpcm_destroy(&state); - - return result; -} - - -int cwav_pcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx) -{ - u32 s, c, i; - int result = 0; - cwav_pcmstate state; - u32 loopcount = settings_get_cwav_loopcount(ctx->usersettings); - - - cwav_pcm_init(&state); - - - if (0 == cwav_pcm_allocate(&state, ctx)) - goto clean; - - for(i=0; i<1+loopcount; i++) - { - int isloop = (i != 0); - - if (0 == cwav_pcm_setup(&state, ctx, isloop)) - goto clean; - - while(1) - { - if (0 == cwav_pcm_decode(&state, ctx)) - goto clean; - - if (state.samplecountavailable == 0) - break; - - for(s=0; schannelcount; c++) - { - s16 sampledata = state.channelstate[c].samplebuffer[s]; - - if (!stream_out_byte(outstreamctx, 0xFF & sampledata) || !stream_out_byte(outstreamctx, 0xFF & (sampledata>>8))) - { - fprintf(stderr, "Error writing output stream\n"); - goto clean; - } - } - } - } - } - - result = 1; - -clean: - cwav_pcm_destroy(&state); - - return result; -} - -int cwav_save_to_wav(cwav_context* ctx, const char* filepath) -{ - u32 startposition = 0; - u32 endposition = 0; - int result = 0; - FILE* outfile = 0; - stream_out_context outstreamctx; - - - stream_out_init(&outstreamctx); - - if (ctx->channelcount == 0) - goto clean; - - fprintf(stdout, "Saving sound data to %s...\n", filepath); - outfile = fopen(filepath, "wb"); - if (!outfile) - { - fprintf(stderr, "Error could not open file %s for writing.\n", filepath); - goto clean; - } - - stream_out_allocate(&outstreamctx, BUFFERSIZE, outfile); - stream_out_skip(&outstreamctx, sizeof(wav_pcm_header)); - stream_out_position(&outstreamctx, &startposition); - - if (ctx->infoheader.encoding == CWAV_ENCODING_DSPADPCM) - result = cwav_dspadpcm_decode_to_wav(ctx, &outstreamctx); - else if (ctx->infoheader.encoding == CWAV_ENCODING_IMAADPCM) - result = cwav_imaadpcm_decode_to_wav(ctx, &outstreamctx); - else if (ctx->infoheader.encoding == CWAV_ENCODING_PCM16) - result = cwav_pcm_decode_to_wav(ctx, &outstreamctx); - else if (ctx->infoheader.encoding == CWAV_ENCODING_PCM8) - result = cwav_pcm_decode_to_wav(ctx, &outstreamctx); - - if (!result) - goto clean; - - stream_out_position(&outstreamctx, &endposition); - - stream_out_seek(&outstreamctx, 0); - cwav_write_wav_header(ctx, &outstreamctx, endposition-startposition); - stream_out_flush(&outstreamctx); - result = 1; - -clean: - stream_out_destroy(&outstreamctx); - - if (outfile) - fclose(outfile); - - return result; -} - -void cwav_dspadpcm_init(cwav_dspadpcmstate* state) -{ - memset(state, 0, sizeof(cwav_dspadpcmstate)); -} - -int cwav_dspadpcm_allocate(cwav_dspadpcmstate* state, cwav_context* ctx) -{ - u32 channelcount = ctx->channelcount; - - - state->samplebuffer = malloc(sizeof(s16) * SAMPLECOUNT * channelcount); - state->channelstate = malloc(sizeof(cwav_dspadpcmchannelstate) * channelcount); - state->samplecountcapacity = SAMPLECOUNT; - state->samplecountavailable = 0; - state->samplecountremaining = 0; - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - { - fprintf(stderr, "Error allocating memory\n"); - return 0; - } - - return 1; -} - -int cwav_dspadpcm_setup(cwav_dspadpcmstate* state, cwav_context* ctx, int isloop) -{ - u32 channelcount = ctx->channelcount; - u32 i; - u32 startoffset = 0; - - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - return 0; - - state->samplecountavailable = 0; - - if (isloop) - { - state->samplecountremaining = getle32(ctx->infoheader.loopend) - getle32(ctx->infoheader.loopstart); - - startoffset = getle32(ctx->infoheader.loopstart) * 8 / 14; - } - else - { - state->samplecountremaining = getle32(ctx->infoheader.loopend); - startoffset = 0; - } - - - - for(i=0; ichannel[i]; - cwav_dspadpcminfo* adpcminfo = &adpcmchannel->infodspadpcm; - - if (getle16(adpcmchannel->info.codecref.idtype) != 0x300) - { - fprintf(stderr, "Error, not DSP-ADPCM format.\n"); - return 0; - } - - state->channelstate[i].samplebuffer = state->samplebuffer + SAMPLECOUNT * i; - state->channelstate[i].sampleoffset = (u32) (ctx->offset + getle32(adpcmchannel->info.sampleref.offset) + getle32(ctx->header.datablockref.offset) + 8 + startoffset); - if (isloop) - { - state->channelstate[i].yn1 = getle16(adpcminfo->loopyn1); - state->channelstate[i].yn2 = getle16(adpcminfo->loopyn2); - } - else - { - state->channelstate[i].yn1 = getle16(adpcminfo->yn1); - state->channelstate[i].yn2 = getle16(adpcminfo->yn2); - } - stream_in_allocate(&state->channelstate[i].instreamctx, BUFFERSIZE, ctx->file); - stream_in_seek(&state->channelstate[i].instreamctx, state->channelstate[i].sampleoffset); - } - - return 1; -} - -// decode dsp-adpcm to pcm signed 16-bit -int cwav_dspadpcm_decode(cwav_dspadpcmstate* state, cwav_context* ctx) -{ - u32 i, c; - u32 maxsamplecount; - u32 channelcount = ctx->channelcount; - - if (ctx->channel == 0 || state->samplebuffer == 0 || state->channelstate == 0) - return 0; - - - state->samplecountavailable = 0; - if (state->samplecountremaining <= 0) - { - return 1; - } - - while(state->samplecountremaining > 0) - { - u32 samplecountavailable = state->samplecountcapacity - state->samplecountavailable; - - if (state->samplecountremaining < 14) - maxsamplecount = state->samplecountremaining; - else - maxsamplecount = 14; - - if (samplecountavailable < maxsamplecount) - break; - - for(c=0; cchannelstate[c]; - - s16* samplebuffer = channelstate->samplebuffer + state->samplecountavailable; - stream_in_context* instreamctx = &channelstate->instreamctx; - s16 yn1 = channelstate->yn1; - s16 yn2 = channelstate->yn2; - cwav_channel* adpcmchannel = &ctx->channel[c]; - cwav_dspadpcminfo* adpcminfo = &adpcmchannel->infodspadpcm; - - u8 data; - u8 lonibble; - u8 hinibble; - s16 coef1; - s16 coef2; - u32 shift; - s16 table[14]; - - stream_in_reseek(instreamctx); - - - if (0 == stream_in_byte(instreamctx, &data)) - { - fprintf(stderr, "Error reading input stream\n"); - return 1; - } - - lonibble = data & 0xF; - hinibble = data>>4; - - coef1 = getle16(adpcminfo->coef[hinibble*2+0]); - coef2 = getle16(adpcminfo->coef[hinibble*2+1]); - shift = 17 - lonibble; - - for(i=0; i<7; i++) - { - stream_in_byte(instreamctx, &data); - table[i*2+0] = data>>4; - table[i*2+1] = data & 0xF; - } - - - for(i=0; i> shift; - - s32 prediction = (yn1 * coef1 + yn2 * coef2 + xshifted + 0x400)>>11; - - if (prediction < -0x8000) - prediction = -0x8000; - if (prediction > 0x7FFF) - prediction = 0x7FFF; - - yn2 = yn1; - yn1 = prediction; - - samplebuffer[i] = prediction; - } - - channelstate->yn1 = yn1; - channelstate->yn2 = yn2; - } - - state->samplecountremaining -= maxsamplecount; - state->samplecountavailable += maxsamplecount; - } - - return 1; -} - -void cwav_dspadpcm_destroy(cwav_dspadpcmstate* state) -{ - free(state->channelstate); - free(state->samplebuffer); - - state->channelstate = 0; - state->samplebuffer = 0; -} - -void cwav_imaadpcm_init(cwav_imaadpcmstate* state) -{ - memset(state, 0, sizeof(cwav_imaadpcmstate)); -} - - -int cwav_imaadpcm_allocate(cwav_imaadpcmstate* state, cwav_context* ctx) -{ - u32 channelcount = ctx->channelcount; - - - state->samplebuffer = malloc(sizeof(s16) * SAMPLECOUNT * channelcount); - state->channelstate = malloc(sizeof(cwav_imaadpcmchannelstate) * channelcount); - state->samplecountcapacity = SAMPLECOUNT; - state->samplecountavailable = 0; - state->samplecountremaining = 0; - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - { - fprintf(stderr, "Error allocating memory\n"); - return 0; - } - - return 1; -} - -int cwav_imaadpcm_setup(cwav_imaadpcmstate* state, cwav_context* ctx, int isloop) -{ - u32 channelcount = ctx->channelcount; - u32 i; - u32 startoffset = 0; - - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - { - fprintf(stderr, "Error allocating memory\n"); - return 0; - } - - state->samplecountavailable = 0; - if (isloop) - { - state->samplecountremaining = getle32(ctx->infoheader.loopend) - getle32(ctx->infoheader.loopstart); - - startoffset = getle32(ctx->infoheader.loopstart) / 2; - } - else - { - state->samplecountremaining = getle32(ctx->infoheader.loopend); - startoffset = 0; - } - - for(i=0; ichannel[i]; - cwav_imaadpcminfo* adpcminfo = &adpcmchannel->infoimaadpcm; - - if (getle16(adpcmchannel->info.codecref.idtype) != 0x301) - { - fprintf(stderr, "Error, not IMA-ADPCM format.\n"); - return 0; - } - - state->channelstate[i].samplebuffer = state->samplebuffer + SAMPLECOUNT * i; - state->channelstate[i].sampleoffset = (u32) (ctx->offset + getle32(adpcmchannel->info.sampleref.offset) + getle32(ctx->header.datablockref.offset) + 8 + startoffset); - if (isloop) - { - state->channelstate[i].data = getle16(adpcminfo->loopdata); - state->channelstate[i].tableindex = adpcminfo->looptableindex; - } - else - { - state->channelstate[i].data = getle16(adpcminfo->data); - state->channelstate[i].tableindex = adpcminfo->tableindex; - } - stream_in_allocate(&state->channelstate[i].instreamctx, BUFFERSIZE, ctx->file); - stream_in_seek(&state->channelstate[i].instreamctx, state->channelstate[i].sampleoffset); - } - - return 1; -} - -u8 cwav_imaadpcm_clamp_tableindex(u8 tableindex, int inc) -{ - int unclamped = tableindex + inc; - - if (unclamped < 0) - unclamped = 0; - if (unclamped > 88) - unclamped = 88; - - return unclamped; -} - -// decode ima-adpcm to pcm signed 16-bit -int cwav_imaadpcm_decode(cwav_imaadpcmstate* state, cwav_context* ctx) -{ - u32 i, c; - u32 maxsamplecount; - u32 channelcount = ctx->channelcount; - - if (ctx->channel == 0 || state->samplebuffer == 0 || state->channelstate == 0) - return 0; - - - state->samplecountavailable = 0; - if (state->samplecountremaining <= 0) - { - return 1; - } - - while(state->samplecountremaining > 0) - { - u32 samplecountavailable = state->samplecountcapacity - state->samplecountavailable; - - if (state->samplecountremaining < 2) - maxsamplecount = state->samplecountremaining; - else - maxsamplecount = 2; - - if (samplecountavailable < maxsamplecount) - break; - - for(c=0; cchannelstate[c]; - - s16* samplebuffer = channelstate->samplebuffer + state->samplecountavailable; - stream_in_context* instreamctx = &channelstate->instreamctx; - s16 prediction = channelstate->data; - u8 tableindex = channelstate->tableindex; - cwav_channel* adpcmchannel = &ctx->channel[c]; - cwav_imaadpcminfo* adpcminfo = &adpcmchannel->infoimaadpcm; - u8 data; - - - stream_in_reseek(instreamctx); - - - if (0 == stream_in_byte(instreamctx, &data)) - { - fprintf(stderr, "Error reading input stream\n"); - return 1; - } - - - for(i=0; i 0x7FFF) - prediction = 0x7FFF; - - samplebuffer[i] = prediction; - data >>= 4; - } - - channelstate->data = prediction; - channelstate->tableindex = tableindex; - } - - state->samplecountremaining -= maxsamplecount; - state->samplecountavailable += maxsamplecount; - } - - return 1; -} - -void cwav_imaadpcm_destroy(cwav_imaadpcmstate* state) -{ - free(state->channelstate); - free(state->samplebuffer); - - state->channelstate = 0; - state->samplebuffer = 0; -} - - -void cwav_pcm_init(cwav_pcmstate* state) -{ - memset(state, 0, sizeof(cwav_pcmstate)); -} - -int cwav_pcm_allocate(cwav_pcmstate* state, cwav_context* ctx) -{ - u32 channelcount = ctx->channelcount; - - - state->samplebuffer = malloc(sizeof(s16) * SAMPLECOUNT * channelcount); - state->channelstate = malloc(sizeof(cwav_pcmchannelstate) * channelcount); - state->samplecountcapacity = SAMPLECOUNT; - state->samplecountavailable = 0; - state->samplecountremaining = 0; - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - { - fprintf(stderr, "Error allocating memory\n"); - return 0; - } - - return 1; -} - -int cwav_pcm_setup(cwav_pcmstate* state, cwav_context* ctx, int isloop) -{ - u32 channelcount = ctx->channelcount; - u32 i; - u32 startoffset = 0; - - - if (ctx->channel == 0) - return 0; - - if (state->samplebuffer == 0 || state->channelstate == 0) - { - fprintf(stderr, "Error allocating memory\n"); - return 0; - } - - state->samplecountavailable = 0; - state->samplecountcapacity = SAMPLECOUNT; - if (isloop) - { - state->samplecountremaining = getle32(ctx->infoheader.loopend) - getle32(ctx->infoheader.loopstart); - - if (ctx->infoheader.encoding == CWAV_ENCODING_PCM8) - startoffset = getle32(ctx->infoheader.loopstart); - else if (ctx->infoheader.encoding == CWAV_ENCODING_PCM16) - startoffset = getle32(ctx->infoheader.loopstart) * 2; - else - startoffset = 0; - } - else - { - state->samplecountremaining = getle32(ctx->infoheader.loopend); - startoffset = 0; - } - - for(i=0; ichannel[i]; - - state->channelstate[i].samplebuffer = state->samplebuffer + SAMPLECOUNT * i; - state->channelstate[i].sampleoffset = (u32) (ctx->offset + getle32(pcmchannel->info.sampleref.offset) + getle32(ctx->header.datablockref.offset) + 8 + startoffset); - stream_in_allocate(&state->channelstate[i].instreamctx, BUFFERSIZE, ctx->file); - stream_in_seek(&state->channelstate[i].instreamctx, state->channelstate[i].sampleoffset); - } - - return 1; -} - -// decode pcm to pcm signed 16-bit -int cwav_pcm_decode(cwav_pcmstate* state, cwav_context* ctx) -{ - u32 i, c; - u32 maxsamplecount; - u32 channelcount = ctx->channelcount; - - if (ctx->channel == 0 || state->samplebuffer == 0 || state->channelstate == 0) - return 0; - - - state->samplecountavailable = 0; - if (state->samplecountremaining <= 0) - { - return 1; - } - - while(state->samplecountremaining > 0) - { - u32 samplecountavailable = state->samplecountcapacity - state->samplecountavailable; - - if (state->samplecountremaining < 1) - maxsamplecount = state->samplecountremaining; - else - maxsamplecount = 1; - - if (samplecountavailable < maxsamplecount) - break; - - for(c=0; cchannelstate[c]; - - s16* samplebuffer = channelstate->samplebuffer + state->samplecountavailable; - stream_in_context* instreamctx = &channelstate->instreamctx; - cwav_channel* pcmchannel = &ctx->channel[c]; - - - stream_in_reseek(instreamctx); - - for(i=0; iinfoheader.encoding == CWAV_ENCODING_PCM16) - { - if (0 == stream_in_byte(instreamctx, &datalo) || 0 == stream_in_byte(instreamctx, &datahi)) - { - fprintf(stderr, "Error reading input stream\n"); - return 1; - } - samplebuffer[i] = (datahi << 8) | datalo; - } - else if (ctx->infoheader.encoding == CWAV_ENCODING_PCM8) - { - if (0 == stream_in_byte(instreamctx, &datahi)) - { - fprintf(stderr, "Error reading input stream\n"); - return 1; - } - samplebuffer[i] = (datahi << 8); - } - } - } - - state->samplecountremaining -= maxsamplecount; - state->samplecountavailable += maxsamplecount; - } - - return 1; -} - -void cwav_pcm_destroy(cwav_pcmstate* state) -{ - free(state->channelstate); - free(state->samplebuffer); - - state->channelstate = 0; - state->samplebuffer = 0; -} - -const char* cwav_encoding_string(u8 encoding) -{ - switch(encoding) - { - case CWAV_ENCODING_DSPADPCM: return "DSP-ADPCM"; - case CWAV_ENCODING_IMAADPCM: return "IMA-ADPCM"; - case CWAV_ENCODING_PCM8: return "PCM8"; - case CWAV_ENCODING_PCM16: return "PCM16"; - default: return "UNKNOWN"; - } -} - -void cwav_print(cwav_context* ctx) -{ - cwav_header* header = &ctx->header; - cwav_infoheader* infoheader = &ctx->infoheader; - u32 i; - u32 infoheaderoffset = (u32) (ctx->offset + getle32(ctx->header.infoblockref.offset)); - u32 channelcount = getle32(infoheader->channelcount); - - fprintf(stdout, "Header: %c%c%c%c\n", header->magic[0], header->magic[1], header->magic[2], header->magic[3]); - fprintf(stdout, "Byte order mark: 0x%04X\n", getle16(header->byteordermark)); - fprintf(stdout, "Header size: 0x%04X\n", getle16(header->headersize)); - fprintf(stdout, "Version: 0x%08X\n", getle32(header->version)); - fprintf(stdout, "Total size: 0x%08X\n", getle32(header->totalsize)); - fprintf(stdout, "Data blocks: 0x%04X\n", getle16(header->datablocks)); - fprintf(stdout, "Info block idtype: 0x%04X\n", getle16(header->infoblockref.idtype)); - fprintf(stdout, "Info block offset: 0x%08X\n", getle32(header->infoblockref.offset)); - fprintf(stdout, "Info block size: 0x%08X\n", getle32(header->infoblockref.size)); - fprintf(stdout, "Data block idtype: 0x%04X\n", getle16(header->datablockref.idtype)); - fprintf(stdout, "Data block offset: 0x%08X\n", getle32(header->datablockref.offset)); - fprintf(stdout, "Data block size: 0x%08X\n", getle32(header->datablockref.size)); - fprintf(stdout, "\n"); - fprintf(stdout, "Header: %c%c%c%c\n", infoheader->magic[0], infoheader->magic[1], infoheader->magic[2], infoheader->magic[3]); - fprintf(stdout, "Size: 0x%08X\n", getle32(infoheader->size)); - fprintf(stdout, "Encoding: 0x%02X (%s)\n", infoheader->encoding, cwav_encoding_string(infoheader->encoding)); - fprintf(stdout, "Looped: 0x%02X\n", infoheader->looped); - fprintf(stdout, "Samplerate: %d\n", getle32(infoheader->samplerate)); - fprintf(stdout, "Loop start: 0x%08X\n", getle32(infoheader->loopstart)); - fprintf(stdout, "Loop end: 0x%08X\n", getle32(infoheader->loopend)); - fprintf(stdout, "Channels: %d\n", channelcount); - if (ctx->channel != 0) - { - for(i=0; ichannel[i].inforef.offset); - u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset); - u32 sampleoffset = (u32) (ctx->offset + getle32(ctx->channel[i].info.sampleref.offset) + getle32(ctx->header.datablockref.offset) + 8); - - fprintf(stdout, "Channel %d:\n", i); - fprintf(stdout, " > Channel ref idtype: 0x%04X\n", getle16(ctx->channel[i].inforef.idtype)); - fprintf(stdout, " > Channel ref offset: 0x%08X\n", channeloffset); - fprintf(stdout, " > Sample ref idtype: 0x%04X\n", getle16(ctx->channel[i].info.sampleref.idtype)); - fprintf(stdout, " > Sample ref offset: 0x%08X\n", sampleoffset); - fprintf(stdout, " > Codec ref idtype: 0x%04X\n", getle16(ctx->channel[i].info.codecref.idtype)); - fprintf(stdout, " > Codec ref offset: 0x%08X\n", codecoffset); - - -#ifdef CWAV_CODEC_PRINT - if (ctx->infoheader.encoding == CWAV_ENCODING_DSPADPCM && getle16(ctx->channel[i].info.codecref.idtype) == 0x300) - { - u32 j; - - for(j=0; j<16; j++) - fprintf(stdout, " > Adpcm coef %02d: 0x%04X\n", j, getle16(ctx->channel[i].infodspadpcm.coef[j])); - fprintf(stdout, " > Adpcm scale: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.scale)); - fprintf(stdout, " > Adpcm yn1: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.yn1)); - fprintf(stdout, " > Adpcm yn2: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.yn2)); - fprintf(stdout, " > Adpcm loop scale: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.loopscale)); - fprintf(stdout, " > Adpcm loop yn1: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.loopyn1)); - fprintf(stdout, " > Adpcm loop yn2: 0x%04X\n", getle16(ctx->channel[i].infodspadpcm.loopyn2)); - } - - if (ctx->infoheader.encoding == CWAV_ENCODING_IMAADPCM && getle16(ctx->channel[i].info.codecref.idtype) == 0x301) - { - fprintf(stdout, " > Adpcm data: 0x%04X\n", getle16(ctx->channel[i].infoimaadpcm.data)); - fprintf(stdout, " > Adpcm tblindex: 0x%02X\n", ctx->channel[i].infoimaadpcm.tableindex); - fprintf(stdout, " > Adpcm loopdata: 0x%04X\n", getle16(ctx->channel[i].infoimaadpcm.loopdata)); - fprintf(stdout, " > Adpcm looptblindex: 0x%02X\n", ctx->channel[i].infoimaadpcm.looptableindex); - } -#endif - } - } -} diff --git a/ctrtool/cwav.h b/ctrtool/cwav.h deleted file mode 100644 index 180f4b0..0000000 --- a/ctrtool/cwav.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef _CWAV_H_ -#define _CWAV_H_ - -#include -#include "types.h" -#include "settings.h" -#include "stream.h" - -#define CWAV_ENCODING_PCM8 0 -#define CWAV_ENCODING_PCM16 1 -#define CWAV_ENCODING_DSPADPCM 2 -#define CWAV_ENCODING_IMAADPCM 3 - -typedef struct -{ - u8 idtype[2]; - u8 padding[2]; - u8 offset[4]; -} cwav_reference; - -typedef struct -{ - u8 idtype[2]; - u8 padding[2]; - u8 offset[4]; - u8 size[4]; -} cwav_sizedreference; - - -typedef struct -{ - u8 magic[4]; - u8 byteordermark[2]; - u8 headersize[2]; - u8 version[4]; - u8 totalsize[4]; - u8 datablocks[2]; - u8 reserved[2]; - cwav_sizedreference infoblockref; - cwav_sizedreference datablockref; -} cwav_header; - -typedef struct -{ - u8 magic[4]; - u8 size[4]; - u8 encoding; - u8 looped; - u8 padding[2]; - u8 samplerate[4]; - u8 loopstart[4]; - u8 loopend[4]; - u8 reserved[4]; - u8 channelcount[4]; -} cwav_infoheader; - -typedef struct -{ - cwav_reference sampleref; - cwav_reference codecref; - u8 reserved[4]; -} cwav_channelinfo; - -typedef struct -{ - u8 coef[16][2]; - u8 scale[2]; - u8 yn1[2]; - u8 yn2[2]; - u8 loopscale[2]; - u8 loopyn1[2]; - u8 loopyn2[2]; -} cwav_dspadpcminfo; - -typedef struct -{ - u8 data[2]; - u8 tableindex; - u8 padding; - u8 loopdata[2]; - u8 looptableindex; - u8 looppadding; -} cwav_imaadpcminfo; - - -typedef struct -{ - s16 yn1; - s16 yn2; - u32 sampleoffset; - s16* samplebuffer; - stream_in_context instreamctx; -} cwav_dspadpcmchannelstate; - -typedef struct -{ - cwav_dspadpcmchannelstate* channelstate; - s16* samplebuffer; - u32 samplecountavailable; - u32 samplecountcapacity; - u32 samplecountremaining; -} cwav_dspadpcmstate; - -typedef struct -{ - s16 data; - u8 tableindex; - u32 sampleoffset; - s16* samplebuffer; - stream_in_context instreamctx; -} cwav_imaadpcmchannelstate; - -typedef struct -{ - cwav_imaadpcmchannelstate* channelstate; - s16* samplebuffer; - u32 samplecountavailable; - u32 samplecountcapacity; - u32 samplecountremaining; -} cwav_imaadpcmstate; - -typedef struct -{ - u32 sampleoffset; - s16* samplebuffer; - stream_in_context instreamctx; -} cwav_pcmchannelstate; - -typedef struct -{ - cwav_pcmchannelstate* channelstate; - s16* samplebuffer; - u32 samplecountavailable; - u32 samplecountcapacity; - u32 samplecountremaining; -} cwav_pcmstate; - - -typedef struct -{ - cwav_reference inforef; - cwav_channelinfo info; - cwav_dspadpcminfo infodspadpcm; - cwav_imaadpcminfo infoimaadpcm; -} cwav_channel; - -typedef struct -{ - u8 chunkid[4]; - u8 chunksize[4]; - u8 format[4]; - u8 subchunk1id[4]; - u8 subchunk1size[4]; - u8 audioformat[2]; - u8 numchannels[2]; - u8 samplerate[4]; - u8 byterate[4]; - u8 blockalign[2]; - u8 bitspersample[2]; - u8 subchunk2id[4]; - u8 subchunk2size[4]; -} wav_pcm_header; - -typedef struct -{ - FILE* file; - settings* usersettings; - u64 offset; - u64 size; - u32 channelcount; - cwav_header header; - cwav_infoheader infoheader; - cwav_channel* channel; -} cwav_context; - -void cwav_init(cwav_context* ctx); -void cwav_set_file(cwav_context* ctx, FILE* file); -void cwav_set_offset(cwav_context* ctx, u64 offset); -void cwav_set_size(cwav_context* ctx, u64 size); -void cwav_set_usersettings(cwav_context* ctx, settings* usersettings); -void cwav_process(cwav_context* ctx, u32 actions); -void cwav_dspadpcm_init(cwav_dspadpcmstate* state); -int cwav_dspadpcm_allocate(cwav_dspadpcmstate* state, cwav_context* ctx); -int cwav_dspadpcm_setup(cwav_dspadpcmstate* state, cwav_context* ctx, int isloop); -int cwav_dspadpcm_decode(cwav_dspadpcmstate* state, cwav_context* ctx); -int cwav_dspadpcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx); -void cwav_dspadpcm_destroy(cwav_dspadpcmstate* state); -void cwav_imaadpcm_init(cwav_imaadpcmstate* state); -int cwav_imaadpcm_allocate(cwav_imaadpcmstate* state, cwav_context* ctx); -int cwav_imaadpcm_setup(cwav_imaadpcmstate* state, cwav_context* ctx, int isloop); -int cwav_imaadpcm_decode(cwav_imaadpcmstate* state, cwav_context* ctx); -int cwav_imaadpcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx); -u8 cwav_imaadpcm_clamp_tableindex(u8 tableindex, int inc); -void cwav_imaadpcm_destroy(cwav_imaadpcmstate* state); -void cwav_pcm_init(cwav_pcmstate* state); -int cwav_pcm_allocate(cwav_pcmstate* state, cwav_context* ctx); -int cwav_pcm_setup(cwav_pcmstate* state, cwav_context* ctx, int isloop); -int cwav_pcm_decode(cwav_pcmstate* state, cwav_context* ctx); -int cwav_pcm_decode_to_wav(cwav_context* ctx, stream_out_context* outstreamctx); -void cwav_pcm_destroy(cwav_pcmstate* state); -void cwav_write_wav_header(cwav_context* ctx, stream_out_context* outstreamctx, u32 size); -int cwav_save_to_wav(cwav_context* ctx, const char* filepath); -void cwav_print(cwav_context* ctx); - -#endif // _CWAV_H_ diff --git a/ctrtool/exefs.c b/ctrtool/exefs.c deleted file mode 100644 index 465bc8b..0000000 --- a/ctrtool/exefs.c +++ /dev/null @@ -1,342 +0,0 @@ -#include -#include -#include - -#include "types.h" -#include "exefs.h" -#include "utils.h" -#include "ncch.h" -#include "lzss.h" - -void exefs_init(exefs_context* ctx) -{ - memset(ctx, 0, sizeof(exefs_context)); -} - -void exefs_set_file(exefs_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void exefs_set_offset(exefs_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void exefs_set_size(exefs_context* ctx, u64 size) -{ - ctx->size = size; -} - -void exefs_set_usersettings(exefs_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void exefs_set_titleid(exefs_context* ctx, u8 titleid[8]) -{ - memcpy(ctx->titleid, titleid, 8); -} - -void exefs_set_compressedflag(exefs_context* ctx, int compressedflag) -{ - ctx->compressedflag = compressedflag; -} - -void exefs_set_encrypted(exefs_context* ctx, u32 encrypted) -{ - ctx->encrypted = encrypted; -} - -void exefs_set_keys(exefs_context* ctx, u8 key0[16], u8 key1[16]) -{ - memcpy(ctx->key[0], key0, 16); - memcpy(ctx->key[1], key1, 16); -} - -void exefs_set_counter(exefs_context* ctx, u8 counter[16]) -{ - memcpy(ctx->counter, counter, 16); -} - -void exefs_save(exefs_context* ctx, u32 index, u32 flags) -{ - exefs_sectionheader* section = (exefs_sectionheader*)(ctx->header.section + index); - char outfname[MAX_PATH]; - char name[64]; - u32 offset; - u32 size; - FILE* fout; - u32 compressedsize = 0; - u32 decompressedsize = 0; - u8* compressedbuffer = 0; - u8* decompressedbuffer = 0; - filepath* dirpath = 0; - - // determine offset/size of target - offset = getle32(section->offset) + sizeof(exefs_header); - size = getle32(section->size); - dirpath = settings_get_exefs_dir_path(ctx->usersettings); - - if (size == 0 || dirpath == 0 || dirpath->valid == 0) - return; - - if (size >= ctx->size) - { - fprintf(stderr, "Error, ExeFS section %d size invalid\n", index); - return; - } - - // create new file - memset(name, 0, sizeof(name)); - memcpy(name, section->name, 8); - - - memcpy(outfname, dirpath->pathname, MAX_PATH); - strcat(outfname, "/"); - - if (name[0] == '.') - strcat(outfname, name+1); - else - strcat(outfname, name); - strcat(outfname, ".bin"); - - fout = fopen(outfname, "wb"); - - if (fout == 0) - { - fprintf(stderr, "Error, failed to create file %s\n", outfname); - goto clean; - } - - // seek in source file to location of target data - fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); - - // do decryption prep - if (ctx->encrypted) - { - // setup aes counter - ctr_init_counter(&ctx->aes, ctx->counter); - ctr_add_counter(&ctx->aes, offset / 0x10); - - // setup key - if (strncmp((const char*)section->name, "icon", 8) == 0 || strncmp((const char*)section->name, "banner", 8) == 0) - ctr_init_key(&ctx->aes, ctx->key[0]); - else - ctr_init_key(&ctx->aes, ctx->key[1]); - } - - // if this is file0, and compression is set or forced: decompress section - if (index == 0 && (ctx->compressedflag || (flags & DecompressCodeFlag)) && ((flags & RawFlag) == 0)) - { - fprintf(stdout, "Decompressing section %s to %s...\n", name, outfname); - - compressedsize = size; - compressedbuffer = malloc(compressedsize); - - if (compressedbuffer == 0) - { - fprintf(stdout, "Error allocating memory\n"); - goto clean; - } - if (compressedsize != fread(compressedbuffer, 1, compressedsize, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - // decrypt if required - if (ctx->encrypted) - ctr_crypt_counter(&ctx->aes, compressedbuffer, compressedbuffer, compressedsize); - - - decompressedsize = lzss_get_decompressed_size(compressedbuffer, compressedsize); - decompressedbuffer = malloc(decompressedsize); - if (decompressedbuffer == 0) - { - fprintf(stdout, "Error allocating memory\n"); - goto clean; - } - - if (0 == lzss_decompress(compressedbuffer, compressedsize, decompressedbuffer, decompressedsize)) - goto clean; - - if (decompressedsize != fwrite(decompressedbuffer, 1, decompressedsize, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - } - else - { - u8 buffer[16 * 1024]; - - fprintf(stdout, "Saving section %s to %s...\n", name, outfname); - - while(size) - { - u32 max = sizeof(buffer); - if (max > size) - max = size; - - if (max != fread(buffer, 1, max, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - if (ctx->encrypted) - ctr_crypt_counter(&ctx->aes, buffer, buffer, max); - - if (max != fwrite(buffer, 1, max, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - - size -= max; - } - } - -clean: - if (fout) - fclose(fout); - free(compressedbuffer); - free(decompressedbuffer); - return; -} - -void exefs_read_header(exefs_context* ctx, u32 flags) -{ - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, sizeof(exefs_header), ctx->file); - - if (ctx->encrypted) { - ctr_init_key(&ctx->aes, ctx->key[0]); - ctr_init_counter(&ctx->aes, ctx->counter); - ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exefs_header)); - } - -} - -void exefs_calculate_hash(exefs_context* ctx, u8 hash[32]) -{ - ctr_sha_256((const u8*)&ctx->header, sizeof(exefs_header), hash); -} - -void exefs_process(exefs_context* ctx, u32 actions) -{ - u32 i; - - exefs_read_header(ctx, actions); - - if (actions & VerifyFlag) - { - for(i=0; i<8; i++) - ctx->hashcheck[i] = exefs_verify(ctx, i, actions)? Good : Fail; - } - - if (actions & InfoFlag) - { - exefs_print(ctx); - } - - if (actions & ExtractFlag) - { - filepath* dirpath = settings_get_exefs_dir_path(ctx->usersettings); - - if (dirpath && dirpath->valid) - { - makedir(dirpath->pathname); - for(i=0; i<8; i++) - exefs_save(ctx, i, actions); - } - } -} - -int exefs_verify(exefs_context* ctx, u32 index, u32 flags) -{ - exefs_sectionheader* section = (exefs_sectionheader*)(ctx->header.section + index); - u32 offset; - u32 size; - u8 buffer[16 * 1024]; - u8 hash[0x20]; - - - offset = getle32(section->offset) + sizeof(exefs_header); - size = getle32(section->size); - - if (size == 0) - return 0; - - fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); - if (strncmp((const char*)section->name, "icon", 8) == 0 || strncmp((const char*)section->name, "banner", 8) == 0) - ctr_init_key(&ctx->aes, ctx->key[0]); - else - ctr_init_key(&ctx->aes, ctx->key[1]); - ctr_init_counter(&ctx->aes, ctx->counter); - ctr_add_counter(&ctx->aes, offset / 0x10); - - ctr_sha_256_init(&ctx->sha); - - while(size) - { - u32 max = sizeof(buffer); - if (max > size) - max = size; - - if (max != fread(buffer, 1, max, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - if (ctx->encrypted) - ctr_crypt_counter(&ctx->aes, buffer, buffer, max); - - ctr_sha_256_update(&ctx->sha, buffer, max); - - size -= max; - } - - ctr_sha_256_finish(&ctx->sha, hash); - - if (memcmp(hash, ctx->header.hashes[7-index], 0x20) == 0) - return 1; -clean: - return 0; -} - -void exefs_print(exefs_context* ctx) -{ - u32 i; - char sectname[9]; - u32 sectoffset; - u32 sectsize; - - fprintf(stdout, "\nExeFS:\n"); - for(i=0; iheader.section + i); - - - memset(sectname, 0, sizeof(sectname)); - memcpy(sectname, section->name, 8); - - sectoffset = getle32(section->offset); - sectsize = getle32(section->size); - - if (sectsize) - { - fprintf(stdout, "Section name: %s\n", sectname); - fprintf(stdout, "Section offset: 0x%08x\n", sectoffset + 0x200); - fprintf(stdout, "Section size: 0x%08x\n", sectsize); - if (ctx->hashcheck[i] == Good) - memdump(stdout, "Section hash (GOOD): ", ctx->header.hashes[7-i], 0x20); - else if (ctx->hashcheck[i] == Fail) - memdump(stdout, "Section hash (FAIL): ", ctx->header.hashes[7-i], 0x20); - else - memdump(stdout, "Section hash: ", ctx->header.hashes[7-i], 0x20); - } - } -} diff --git a/ctrtool/exefs.h b/ctrtool/exefs.h deleted file mode 100644 index fd6e8f0..0000000 --- a/ctrtool/exefs.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _EXEFS_H_ -#define _EXEFS_H_ - -#include "types.h" -#include "info.h" -#include "ctr.h" -#include "filepath.h" -#include "settings.h" - -#define EXEFS_SECTION_NUM 8 - -typedef struct -{ - u8 name[8]; - u8 offset[4]; - u8 size[4]; -} exefs_sectionheader; - - -typedef struct -{ - exefs_sectionheader section[EXEFS_SECTION_NUM]; - u8 reserved[0x80]; - u8 hashes[EXEFS_SECTION_NUM][0x20]; -} exefs_header; - -typedef struct -{ - FILE* file; - settings* usersettings; - u8 titleid[8]; - u8 counter[16]; - u8 key[2][16]; - u64 offset; - u64 size; - exefs_header header; - ctr_aes_context aes; - ctr_sha256_context sha; - int hashcheck[EXEFS_SECTION_NUM]; - int compressedflag; - int encrypted; -} exefs_context; - -void exefs_init(exefs_context* ctx); -void exefs_set_file(exefs_context* ctx, FILE* file); -void exefs_set_offset(exefs_context* ctx, u64 offset); -void exefs_set_size(exefs_context* ctx, u64 size); -void exefs_set_usersettings(exefs_context* ctx, settings* usersettings); -void exefs_set_titleid(exefs_context* ctx, u8 titleid[8]); -void exefs_set_counter(exefs_context* ctx, u8 counter[16]); -void exefs_set_compressedflag(exefs_context* ctx, int compressedflag); -void exefs_set_keys(exefs_context* ctx, u8 key[16], u8 special_key[16]); -void exefs_set_encrypted(exefs_context* ctx, u32 encrypted); -void exefs_read_header(exefs_context* ctx, u32 flags); -void exefs_calculate_hash(exefs_context* ctx, u8 hash[32]); -void exefs_process(exefs_context* ctx, u32 actions); -void exefs_print(exefs_context* ctx); -void exefs_save(exefs_context* ctx, u32 index, u32 flags); -int exefs_verify(exefs_context* ctx, u32 index, u32 flags); -void exefs_determine_key(exefs_context* ctx, u32 actions); -#endif // _EXEFS_H_ diff --git a/ctrtool/exheader.c b/ctrtool/exheader.c deleted file mode 100644 index 86609d8..0000000 --- a/ctrtool/exheader.c +++ /dev/null @@ -1,704 +0,0 @@ -#include -#include -#include - -#include "types.h" -#include "exheader.h" -#include "utils.h" -#include "ncch.h" -#include "syscalls.h" -#include - -void exheader_init(exheader_context* ctx) -{ - memset(ctx, 0, sizeof(exheader_context)); -} - -void exheader_set_file(exheader_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void exheader_set_offset(exheader_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void exheader_set_size(exheader_context* ctx, u64 size) -{ - ctx->size = size; -} - -void exheader_set_usersettings(exheader_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void exheader_set_titleid(exheader_context* ctx, u8 titleid[8]) -{ - memcpy(ctx->titleid, titleid, 8); -} - -void exheader_set_programid(exheader_context* ctx, u8 programid[8]) -{ - memcpy(ctx->programid, programid, 8); -} - -void exheader_set_hash(exheader_context* ctx, u8 hash[32]) -{ - memcpy(ctx->hash, hash, 32); -} - -void exheader_set_counter(exheader_context* ctx, u8 counter[16]) -{ - memcpy(ctx->counter, counter, 16); -} - -int exheader_get_compressedflag(exheader_context* ctx) -{ - return ctx->compressedflag; -} - -void exheader_set_encrypted(exheader_context* ctx, u32 encrypted) -{ - ctx->encrypted = encrypted; -} - -void exheader_set_key(exheader_context* ctx, u8 key[16]) -{ - memcpy(ctx->key, key, 16); -} - - -void exheader_read(exheader_context* ctx, u32 actions) -{ - if (ctx->haveread == 0) - { - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, sizeof(exheader_header), ctx->file); - - ctr_init_key(&ctx->aes, ctx->key); - ctr_init_counter(&ctx->aes, ctx->counter); - if (ctx->encrypted) - ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exheader_header)); - - ctx->haveread = 1; - } -} - -int exheader_hash_valid(exheader_context* ctx) -{ - u8 hash[32]; - ctr_sha_256((u8*)&ctx->header, 0x400, hash); - - if(memcmp(ctx->hash,hash,0x20)){ - fprintf(stderr, "Error, exheader hash mismatch. Wrong key?\n"); - return 0; - } - - return 1; -} - -int exheader_programid_valid(exheader_context* ctx) -{ - if (!settings_get_ignore_programid(ctx->usersettings)) - { - if (memcmp(ctx->header.arm11systemlocalcaps.programid, ctx->programid, 8)) - { - fprintf(stderr, "Error, program id mismatch. Wrong key?\n"); - return 0; - } - } - - return 1; -} - -void exheader_deserialise_arm11localcaps_permissions(exheader_arm11systemlocalcaps_deserialised *caps, const exheader_arm11systemlocalcaps *arm11) -{ - int i; - - memset(caps, 0, sizeof(exheader_arm11systemlocalcaps_deserialised)); - - memcpy(caps->program_id, arm11->programid, 8); - caps->core_version = getle32(arm11->coreversion); - - caps->enable_l2_cache = (arm11->flag[0] >> 0) & 1; - caps->new3ds_cpu_speed = (arm11->flag[0] >> 1) & 1; - caps->new3ds_systemmode = (arm11->flag[1] >> 0) & 15; - - caps->ideal_processor = (arm11->flag[2] >> 0) & 3; - caps->affinity_mask = (arm11->flag[2] >> 2) & 3; - caps->old3ds_systemmode = (arm11->flag[2] >> 4) & 15; - - caps->priority = (s8)arm11->flag[3]; - - // storage info - if (arm11->storageinfo.otherattributes & 2) { - caps->extdata_id = 0; - for (i = 0; i < 3; i++) - caps->other_user_saveid[i] = 0; - caps->use_other_variation_savedata = 0; - - for (i = 0; i < 3; i++) - caps->accessible_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i)); - for (i = 0; i < 3; i++) - caps->accessible_saveid[i+3] = 0xfffff & (getle64(arm11->storageinfo.extsavedataid) >> 20 * (2 - i)); - } - else { - caps->extdata_id = getle64(arm11->storageinfo.extsavedataid); - for (i = 0; i < 3; i++) - caps->other_user_saveid[i] = 0xfffff & (getle64(arm11->storageinfo.accessibleuniqueids) >> 20 * (2 - i)); - caps->use_other_variation_savedata = (getle64(arm11->storageinfo.accessibleuniqueids) >> 60) & 1; - - for (i = 0; i < 6; i++) - caps->accessible_saveid[i] = 0; - } - - caps->system_saveid[0] = getle32(arm11->storageinfo.systemsavedataid); - caps->system_saveid[1] = getle32(arm11->storageinfo.systemsavedataid + 4); - caps->accessinfo = getle64(arm11->storageinfo.accessinfo) & ~((u64)0xff00000000000000); - - // Service Access Control - for (i = 0; i < 34; i++) - strncpy(caps->service_access_control[i], (char*)arm11->serviceaccesscontrol[i], 8); - - caps->resource_limit_category = arm11->resourcelimitcategory; -} - -int exheader_process(exheader_context* ctx, u32 actions) -{ - exheader_read(ctx, actions); - - if (ctx->header.codesetinfo.flags.flag & 1) - ctx->compressedflag = 1; - - exheader_deserialise_arm11localcaps_permissions(&ctx->system_local_caps, &ctx->header.arm11systemlocalcaps); - - if (actions & VerifyFlag) - exheader_verify(ctx); - - if (actions & InfoFlag) - exheader_print(ctx, actions); - - return 1; -} - -void exheader_print_arm9accesscontrol(exheader_context* ctx) -{ - unsigned int i; - unsigned int flags[15*8]; - - fprintf(stdout, "ARM9 Desc. version: 0x%X\n", ctx->header.arm9accesscontrol.descversion); - - for(i=0; i<15*8; i++) - { - if (ctx->header.arm9accesscontrol.descriptors[i/8] & (1<<(i&7))) - flags[i] = 1; - else - flags[i] = 0; - } - - fprintf(stdout, "Mount NAND fs: %s\n", flags[0]? "YES" : "NO"); - fprintf(stdout, "Mount NAND RO write fs: %s\n", flags[1]? "YES" : "NO"); - fprintf(stdout, "Mount NAND TWL fs: %s\n", flags[2]? "YES" : "NO"); - fprintf(stdout, "Mount NAND W fs: %s\n", flags[3]? "YES" : "NO"); - fprintf(stdout, "Mount CARD SPI fs: %s\n", flags[4]? "YES" : "NO"); - fprintf(stdout, "Use SDIF3: %s\n", flags[5]? "YES" : "NO"); - fprintf(stdout, "Create seed: %s\n", flags[6]? "YES" : "NO"); - fprintf(stdout, "Use CARD SPI: %s\n", flags[7]? "YES" : "NO"); - fprintf(stdout, "SD Application: %s\n", flags[8]? "YES" : "NO"); - fprintf(stdout, "Use Direct SDMC: %s\n", flags[9]? "YES" : "NO"); - - for(i=10; i<15*8; i++) - { - if (flags[i]) - fprintf(stdout, "Unknown flag: %d\n", i); - } -} - -void exheader_print_arm11kernelcapabilities(exheader_context* ctx, u32 actions) -{ - unsigned int i, j; - unsigned int systemcallmask[8]; - unsigned int unknowndescriptor[28]; - unsigned int svccount = 0; - unsigned int svcmask = 0; - unsigned int interrupt[0x80]; - unsigned int interruptcount = 0; - - memset(systemcallmask, 0, sizeof(systemcallmask)); - memset(interrupt, 0, sizeof(interrupt)); - - for(i=0; i<28; i++) - { - unsigned int descriptor = getle32(ctx->header.arm11kernelcaps.descriptors[i]); - - unknowndescriptor[i] = 0; - - if ((descriptor & (0x1f<<27)) == (0x1e<<27)) - systemcallmask[(descriptor>>24) & 7] = descriptor & 0x00FFFFFF; - else if ((descriptor & (0x7f<<25)) == (0x7e<<25)) - fprintf(stdout, "Kernel release version: %d.%d\n", (descriptor>>8)&0xFF, (descriptor>>0)&0xFF); - else if ((descriptor & (0xf<<28)) == (0xe<<28)) - { - for(j=0; j<4; j++) - interrupt[(descriptor >> (j*7)) & 0x7F] = 1; - } - else if ((descriptor & (0xff<<24)) == (0xfe<<24)) - fprintf(stdout, "Handle table size: 0x%X\n", descriptor & 0x3FF); - else if ((descriptor & (0xfff<<20)) == (0xffe<<20)) - fprintf(stdout, "Mapping IO address: 0x%X (%s)\n", (descriptor & 0xFFFFF)<<12, (descriptor&(1<<20))?"RO":"RW"); - else if ((descriptor & (0x7ff<<21)) == (0x7fc<<21)) - fprintf(stdout, "Mapping static address: 0x%X (%s)\n", (descriptor & 0x1FFFFF)<<12, (descriptor&(1<<20))?"RO":"RW"); - else if ((descriptor & (0x1ff<<23)) == (0x1fe<<23)) - { - unsigned int memorytype = (descriptor>>8)&15; - fprintf(stdout, "Kernel flags: \n"); - fprintf(stdout, " > Allow debug: %s\n", (descriptor&(1<<0))?"YES":"NO"); - fprintf(stdout, " > Force debug: %s\n", (descriptor&(1<<1))?"YES":"NO"); - fprintf(stdout, " > Allow non-alphanum: %s\n", (descriptor&(1<<2))?"YES":"NO"); - fprintf(stdout, " > Shared page writing: %s\n", (descriptor&(1<<3))?"YES":"NO"); - fprintf(stdout, " > Privilege priority: %s\n", (descriptor&(1<<4))?"YES":"NO"); - fprintf(stdout, " > Allow main() args: %s\n", (descriptor&(1<<5))?"YES":"NO"); - fprintf(stdout, " > Shared device mem: %s\n", (descriptor&(1<<6))?"YES":"NO"); - fprintf(stdout, " > Runnable on sleep: %s\n", (descriptor&(1<<7))?"YES":"NO"); - fprintf(stdout, " > Special memory: %s\n", (descriptor&(1<<12))?"YES":"NO"); - fprintf(stdout, " > Access Core 2: %s\n", (descriptor&(1<<13))?"YES":"NO"); - - - switch(memorytype) - { - case 1: fprintf(stdout, " > Memory type: APPLICATION\n"); break; - case 2: fprintf(stdout, " > Memory type: SYSTEM\n"); break; - case 3: fprintf(stdout, " > Memory type: BASE\n"); break; - default: fprintf(stdout, " > Memory type: Unknown (%d)\n", memorytype); break; - } - } - else if (descriptor != 0xFFFFFFFF) - unknowndescriptor[i] = 1; - } - - fprintf(stdout, "Allowed systemcalls: "); - if(!(actions & ShowSyscallsFlag)) - { - for(i=0; i<8; i++) - { - for(j=0; j<24; j++) - { - svcmask = systemcallmask[i]; - - if (svcmask & (1< 0x%02X %s\n", svcid, svcname); - } - } - } - } - - fprintf(stdout, "Allowed interrupts: "); - for(i=0; i<0x7F; i++) - { - if (interrupt[i]) - { - if (interruptcount == 0) - { - fprintf(stdout, "0x%02X", i); - } - else if ( (interruptcount & 7) == 0) - { - fprintf(stdout, " "); - fprintf(stdout, "0x%02X", i); - } - else - { - fprintf(stdout, ", 0x%02X", i); - } - - interruptcount++; - if ( (interruptcount & 7) == 0) - { - fprintf(stdout, "\n"); - } - } - } - if (interruptcount & 7) - fprintf(stdout, "\n"); - if (interruptcount == 0) - fprintf(stdout, "none\n"); - - for(i=0; i<28; i++) - { - unsigned int descriptor = getle32(ctx->header.arm11kernelcaps.descriptors[i]); - - if (unknowndescriptor[i]) - fprintf(stdout, "Unknown descriptor: %08X\n", descriptor); - } -} - -char* exheader_print_accessinfobit(u32 bit, char *str) -{ - switch(bit) - { - case 0 : - sprintf(str,"Category System Application"); - break; - case 1 : - sprintf(str,"Category Hardware Check"); - break; - case 2 : - sprintf(str,"Category File System Tool"); - break; - case 3 : - sprintf(str,"Debug"); - break; - case 4 : - sprintf(str,"TWL Card Backup"); - break; - case 5 : - sprintf(str,"TWL Nand Data"); - break; - case 6 : - sprintf(str,"BOSS"); - break; - case 7 : - sprintf(str,"Direct SDMC"); - break; - case 8 : - sprintf(str,"Core"); - break; - case 9 : - sprintf(str,"CTR NAND RO"); - break; - case 10 : - sprintf(str,"CTR NAND RW"); - break; - case 11 : - sprintf(str,"CTR NAND RO (Write Access)"); - break; - case 12 : - sprintf(str,"Category System Settings"); - break; - case 13 : - sprintf(str,"CARD BOARD"); - break; - case 14 : - sprintf(str,"Export Import IVS"); - break; - case 15 : - sprintf(str,"Direct SDMC (Write Only)"); - break; - case 16 : - sprintf(str,"Switch Cleanup"); - break; - case 17 : - sprintf(str,"Save Data Move"); - break; - case 18 : - sprintf(str,"Shop"); - break; - case 19 : - sprintf(str,"Shell"); - break; - case 20 : - sprintf(str,"Category HomeMenu"); - break; - case 21 : - sprintf(str,"Seed DB"); - break; - default : - sprintf(str,"Bit %d (unknown)",bit); - break; - } - - return str; -} - -void exheader_print_arm11accessinfo(exheader_context* ctx) -{ - char str[100]; - u64 i, bit; - for(i = 0; i < 56; i++) - { - bit = ((u64)1 << i); - if((ctx->system_local_caps.accessinfo & bit) == bit) - fprintf(stdout, " > %s\n",exheader_print_accessinfobit((u32)i,str)); - } -} - -void exheader_print_arm11storageinfo(exheader_context* ctx) -{ - u32 i; - - fprintf(stdout, "Ext savedata id: 0x%"PRIx64"\n",ctx->system_local_caps.extdata_id); - for(i = 0; i < 2; i++) - fprintf(stdout, "System savedata id %d: 0x%x %s\n",i+1, ctx->system_local_caps.system_saveid[i],exheader_getvalidstring(ctx->validsystemsaveID[i])); - for(i = 0; i < 3; i++) - fprintf(stdout, "OtherUserSaveDataId%d: 0x%x\n",i+1, ctx->system_local_caps.other_user_saveid[i]); - fprintf(stdout, "Accessible Savedata Ids:\n"); - for(i = 0; i < 6; i++) - { - if(ctx->system_local_caps.accessible_saveid[i] != 0x00000) - fprintf(stdout, " > 0x%05x\n", ctx->system_local_caps.accessible_saveid[i]); - } - - fprintf(stdout, "Other Variation Saves: %s\n", ctx->system_local_caps.use_other_variation_savedata ? "Accessible" : "Inaccessible"); - fprintf(stdout, "Access info: 0x%"PRIx64" %s\n", ctx->system_local_caps.accessinfo,exheader_getvalidstring(ctx->validaccessinfo)); - exheader_print_arm11accessinfo(ctx); -} - -int exheader_signature_verify(exheader_context* ctx, rsakey2048* key) -{ - u8 hash[0x20]; - - ctr_sha_256(ctx->header.accessdesc.ncchpubkeymodulus, 0x300, hash); - return ctr_rsa_verify_hash(ctx->header.accessdesc.signature, hash, key); -} - -void exheader_verify(exheader_context* ctx) -{ - unsigned int i, j; - exheader_arm11systemlocalcaps_deserialised accessdesc; - - exheader_deserialise_arm11localcaps_permissions(&accessdesc, &ctx->header.accessdesc.arm11systemlocalcaps); - - ctx->validsystemsaveID[0] = Good; - ctx->validsystemsaveID[1] = Good; - ctx->validaccessinfo = Good; - ctx->validcoreversion = Good; - ctx->validprogramid = Good; - ctx->validpriority = Good; - ctx->validaffinitymask = Good; - ctx->valididealprocessor = Good; - ctx->validold3dssystemmode = Good; - ctx->validnew3dssystemmode = Good; - ctx->validenablel2cache = Good; - ctx->validnew3dscpuspeed = Good; - ctx->validservicecontrol = Good; - - for(i=0; i<8; i++) - { - if (ctx->system_local_caps.program_id[i] == accessdesc.program_id[i] || accessdesc.program_id[i] == 0xFF) - continue; - ctx->validprogramid = Fail; - break; - } - - if (ctx->system_local_caps.core_version != accessdesc.core_version) - ctx->validcoreversion = Fail; - - if (ctx->system_local_caps.priority < accessdesc.priority) - ctx->validpriority = Fail; - - if((1<system_local_caps.ideal_processor & accessdesc.ideal_processor) == 0) - ctx->valididealprocessor = Fail; - - if (ctx->system_local_caps.affinity_mask & ~accessdesc.affinity_mask) - ctx->validaffinitymask = Fail; - - if (ctx->system_local_caps.old3ds_systemmode > accessdesc.old3ds_systemmode) - ctx->validold3dssystemmode = Fail; - - if (ctx->system_local_caps.new3ds_systemmode > accessdesc.new3ds_systemmode) - ctx->validnew3dssystemmode = Fail; - - if (ctx->system_local_caps.enable_l2_cache != accessdesc.enable_l2_cache) - ctx->validenablel2cache = Fail; - - if (ctx->system_local_caps.new3ds_cpu_speed != accessdesc.new3ds_cpu_speed) - ctx->validnew3dscpuspeed = Fail; - - - - - // Storage Info Verify - if(ctx->system_local_caps.system_saveid[0] & ~accessdesc.system_saveid[0]) - ctx->validsystemsaveID[0] = Fail; - if(ctx->system_local_caps.system_saveid[1] & ~accessdesc.system_saveid[1]) - ctx->validsystemsaveID[1] = Fail; - - - if (ctx->system_local_caps.accessinfo & ~accessdesc.accessinfo) - ctx->validaccessinfo = Fail; - - // Service Access Control - for (i = 0; i < 34; i++) { - if (strlen(ctx->system_local_caps.service_access_control[i]) == 0) - continue; - - for (j = 0; j < 34; j++) { - if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0) - break; - } - - if (strcmp(ctx->system_local_caps.service_access_control[i], accessdesc.service_access_control[j]) == 0) - continue; - - ctx->validservicecontrol = Fail; - } - - if (ctx->usersettings) - ctx->validsignature = exheader_signature_verify(ctx, &ctx->usersettings->keys.ncchdescrsakey); -} - -const char* exheader_getvalidstring(int valid) -{ - if (valid == 0) - return ""; - else if (valid == 1) - return "(GOOD)"; - else - return "(FAIL)"; -} - -const char* exheader_getsystemmodestring(u8 systemmode) -{ - switch (systemmode) - { - case (sysmode_64MB) : - return "64MB"; - case (sysmode_96MB) : - return "96MB"; - case (sysmode_80MB) : - return "80MB"; - case (sysmode_72MB) : - return "72MB"; - case (sysmode_32MB) : - return "32MB"; - default: - return "Unknown"; - } -} - -const char* exheader_getsystemmodeextstring(u8 systemmodeext, u8 systemmode) -{ - switch (systemmodeext) - { - case (sysmode_ext_LEGACY) : - return exheader_getsystemmodestring(systemmode); - case (sysmode_ext_124MB) : - return "124MB"; - case (sysmode_ext_178MB) : - return "178MB"; - default: - return "124MB"; - } -} - - -void exheader_print(exheader_context* ctx, u32 actions) -{ - u32 i; - u64 savedatasize = getle64(ctx->header.systeminfo.savedatasize); - exheader_codesetinfo* codesetinfo = &ctx->header.codesetinfo; - - - fprintf(stdout, "\nExtended header:\n"); - if (ctx->validsignature == Unchecked) - memdump(stdout, "Signature: ", ctx->header.accessdesc.signature, 0x100); - else if (ctx->validsignature == Good) - memdump(stdout, "Signature (GOOD): ", ctx->header.accessdesc.signature, 0x100); - else if (ctx->validsignature == Fail) - memdump(stdout, "Signature (FAIL): ", ctx->header.accessdesc.signature, 0x100); - printf("\n"); - memdump(stdout, "NCCH Hdr RSA Modulus: ", ctx->header.accessdesc.ncchpubkeymodulus, 0x100); - fprintf(stdout, "Name: %.8s\n", codesetinfo->name); - fprintf(stdout, "Flag: %02X ", codesetinfo->flags.flag); - if (codesetinfo->flags.flag & 1) - fprintf(stdout, "[compressed]"); - if (codesetinfo->flags.flag & 2) - fprintf(stdout, "[sd app]"); - fprintf(stdout, "\n"); - fprintf(stdout, "Remaster version: %04X\n", getle16(codesetinfo->flags.remasterversion)); - - fprintf(stdout, "Code text address: 0x%08X\n", getle32(codesetinfo->text.address)); - fprintf(stdout, "Code text size: 0x%08X\n", getle32(codesetinfo->text.codesize)); - fprintf(stdout, "Code text max pages: 0x%08X (0x%08X)\n", getle32(codesetinfo->text.nummaxpages), getle32(codesetinfo->text.nummaxpages)*0x1000); - fprintf(stdout, "Code ro address: 0x%08X\n", getle32(codesetinfo->ro.address)); - fprintf(stdout, "Code ro size: 0x%08X\n", getle32(codesetinfo->ro.codesize)); - fprintf(stdout, "Code ro max pages: 0x%08X (0x%08X)\n", getle32(codesetinfo->ro.nummaxpages), getle32(codesetinfo->ro.nummaxpages)*0x1000); - fprintf(stdout, "Code data address: 0x%08X\n", getle32(codesetinfo->data.address)); - fprintf(stdout, "Code data size: 0x%08X\n", getle32(codesetinfo->data.codesize)); - fprintf(stdout, "Code data max pages: 0x%08X (0x%08X)\n", getle32(codesetinfo->data.nummaxpages), getle32(codesetinfo->data.nummaxpages)*0x1000); - fprintf(stdout, "Code bss size: 0x%08X\n", getle32(codesetinfo->bsssize)); - fprintf(stdout, "Code stack size: 0x%08X\n", getle32(codesetinfo->stacksize)); - - for(i=0; i<0x30; i++) - { - if (getle64(ctx->header.deplist.programid[i]) != 0x0000000000000000UL) - fprintf(stdout, "Dependency: %016"PRIx64"\n", getle64(ctx->header.deplist.programid[i])); - } - if(savedatasize < sizeKB) - fprintf(stdout, "Savedata size: 0x%"PRIx64"\n", savedatasize); - else if(savedatasize < sizeMB) - fprintf(stdout, "Savedata size: %"PRIu64"K\n", savedatasize/sizeKB); - else - fprintf(stdout, "Savedata size: %"PRIu64"M\n", savedatasize/sizeMB); - fprintf(stdout, "Jump id: %016"PRIx64"\n", getle64(ctx->header.systeminfo.jumpid)); - - fprintf(stdout, "Program id: %016"PRIx64" %s\n", getle64(ctx->header.arm11systemlocalcaps.programid), exheader_getvalidstring(ctx->validprogramid)); - fprintf(stdout, "Core version: 0x%X\n", getle32(ctx->header.arm11systemlocalcaps.coreversion)); - fprintf(stdout, "System mode: %s %s\n", exheader_getsystemmodestring(ctx->system_local_caps.old3ds_systemmode), exheader_getvalidstring(ctx->validold3dssystemmode)); - fprintf(stdout, "System mode (New3DS): %s %s\n", exheader_getsystemmodeextstring(ctx->system_local_caps.new3ds_systemmode, ctx->system_local_caps.old3ds_systemmode), exheader_getvalidstring(ctx->validnew3dssystemmode)); - fprintf(stdout, "CPU Speed (New3DS): %s %s\n", ctx->system_local_caps.new3ds_cpu_speed? "804MHz" : "268MHz", exheader_getvalidstring(ctx->validnew3dscpuspeed)); - fprintf(stdout, "Enable L2 Cache: %s %s\n", ctx->system_local_caps.enable_l2_cache ? "YES" : "NO", exheader_getvalidstring(ctx->validnew3dscpuspeed)); - fprintf(stdout, "Ideal processor: %d %s\n", ctx->system_local_caps.ideal_processor, exheader_getvalidstring(ctx->valididealprocessor)); - fprintf(stdout, "Affinity mask: %d %s\n", ctx->system_local_caps.affinity_mask, exheader_getvalidstring(ctx->validaffinitymask)); - fprintf(stdout, "Main thread priority: %d %s\n", ctx->system_local_caps.priority, exheader_getvalidstring(ctx->validpriority)); - // print resource limit descriptor too? currently mostly zeroes... - exheader_print_arm11storageinfo(ctx); - exheader_print_arm11kernelcapabilities(ctx, actions); - exheader_print_arm9accesscontrol(ctx); - - fprintf(stdout, "Service access: %s\n", exheader_getvalidstring(ctx->validservicecontrol)); - for(i=0; i<34; i++) - { - if (strlen(ctx->system_local_caps.service_access_control[i]) > 0) - fprintf(stdout, " > %s\n", ctx->system_local_caps.service_access_control[i]); - } - fprintf(stdout, "Reslimit category: %02X\n", ctx->header.arm11systemlocalcaps.resourcelimitcategory); -} diff --git a/ctrtool/exheader.h b/ctrtool/exheader.h deleted file mode 100644 index 7f4ce49..0000000 --- a/ctrtool/exheader.h +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef _EXHEADER_H_ -#define _EXHEADER_H_ - -#include -#include "types.h" -#include "ctr.h" -#include "settings.h" - -typedef enum -{ - sysmode_64MB, - sysmode_UNK, - sysmode_96MB, - sysmode_80MB, - sysmode_72MB, - sysmode_32MB, -} exheader_systemmode; - -typedef enum -{ - sysmode_ext_LEGACY, - sysmode_ext_124MB, - sysmode_ext_178MB, -} exheader_systemmodeext; - -typedef struct -{ - u8 reserved[5]; - u8 flag; - u8 remasterversion[2]; -} exheader_systeminfoflags; - -typedef struct -{ - u8 address[4]; - u8 nummaxpages[4]; - u8 codesize[4]; -} exheader_codesegmentinfo; - -typedef struct -{ - u8 name[8]; - exheader_systeminfoflags flags; - exheader_codesegmentinfo text; - u8 stacksize[4]; - exheader_codesegmentinfo ro; - u8 reserved[4]; - exheader_codesegmentinfo data; - u8 bsssize[4]; -} exheader_codesetinfo; - -typedef struct -{ - u8 programid[0x30][8]; -} exheader_dependencylist; - -typedef struct -{ - u8 savedatasize[8]; - u8 jumpid[8]; - u8 reserved2[0x30]; -} exheader_systeminfo; - -typedef struct -{ - u8 extsavedataid[8]; - u8 systemsavedataid[8]; - u8 accessibleuniqueids[8]; - u8 accessinfo[7]; - u8 otherattributes; -} exheader_storageinfo; - -typedef struct -{ - u8 programid[8]; - u8 coreversion[4]; - u8 flag[4]; - u8 resourcelimitdescriptor[0x10][2]; - exheader_storageinfo storageinfo; - u8 serviceaccesscontrol[34][8]; - u8 reserved[0xf]; - u8 resourcelimitcategory; -} exheader_arm11systemlocalcaps; - -typedef struct -{ - u8 program_id[8]; - u32 core_version; - - // flag - u8 enable_l2_cache; - u8 new3ds_cpu_speed; - u8 new3ds_systemmode; - u8 ideal_processor; - u8 affinity_mask; - u8 old3ds_systemmode; - s8 priority; - - // storageinfo - u64 extdata_id; - u32 other_user_saveid[3]; - u8 use_other_variation_savedata; - u32 accessible_saveid[6]; - u32 system_saveid[2]; - u64 accessinfo; - - - char service_access_control[34][10]; - u8 resource_limit_category; -} exheader_arm11systemlocalcaps_deserialised; - -typedef struct -{ - u8 descriptors[28][4]; - u8 reserved[0x10]; -} exheader_arm11kernelcapabilities; - -typedef struct -{ - u8 descriptors[15]; - u8 descversion; -} exheader_arm9accesscontrol; - -typedef struct -{ - // systemcontrol info { - // coreinfo { - exheader_codesetinfo codesetinfo; - exheader_dependencylist deplist; - // } - exheader_systeminfo systeminfo; - // } - // accesscontrolinfo { - exheader_arm11systemlocalcaps arm11systemlocalcaps; - exheader_arm11kernelcapabilities arm11kernelcaps; - exheader_arm9accesscontrol arm9accesscontrol; - // } - struct { - u8 signature[0x100]; - u8 ncchpubkeymodulus[0x100]; - exheader_arm11systemlocalcaps arm11systemlocalcaps; - exheader_arm11kernelcapabilities arm11kernelcaps; - exheader_arm9accesscontrol arm9accesscontrol; - } accessdesc; -} exheader_header; - -typedef struct -{ - int haveread; - FILE* file; - settings* usersettings; - u8 titleid[8]; - u8 programid[8]; - u8 hash[32]; - u8 counter[16]; - u8 key[16]; - u64 offset; - u64 size; - exheader_header header; - - exheader_arm11systemlocalcaps_deserialised system_local_caps; - - ctr_aes_context aes; - ctr_rsa_context rsa; - int compressedflag; - int encrypted; - int validprogramid; - int validpriority; - int validaffinitymask; - int valididealprocessor; - int validold3dssystemmode; - int validnew3dssystemmode; - int validenablel2cache; - int validnew3dscpuspeed; - int validcoreversion; - int validsystemsaveID[2]; - int validaccessinfo; - int validservicecontrol; - int validsignature; -} exheader_context; - -void exheader_init(exheader_context* ctx); -void exheader_set_file(exheader_context* ctx, FILE* file); -void exheader_set_offset(exheader_context* ctx, u64 offset); -void exheader_set_size(exheader_context* ctx, u64 size); -void exheader_set_titleid(exheader_context* ctx, u8 titleid[8]); -void exheader_set_counter(exheader_context* ctx, u8 counter[16]); -void exheader_set_programid(exheader_context* ctx, u8 programid[8]); -void exheader_set_hash(exheader_context* ctx, u8 hash[32]); -void exheader_set_encrypted(exheader_context* ctx, u32 encrypted); -void exheader_set_key(exheader_context* ctx, u8 key[16]); -void exheader_set_usersettings(exheader_context* ctx, settings* usersettings); -int exheader_get_compressedflag(exheader_context* ctx); -void exheader_read(exheader_context* ctx, u32 actions); -int exheader_process(exheader_context* ctx, u32 actions); -const char* exheader_getvalidstring(int valid); -void exheader_print(exheader_context* ctx, u32 actions); -void exheader_verify(exheader_context* ctx); -int exheader_hash_valid(exheader_context* ctx); -int exheader_programid_valid(exheader_context* ctx); - -#endif // _EXHEADER_H_ diff --git a/ctrtool/filepath.c b/ctrtool/filepath.c deleted file mode 100644 index 366bb65..0000000 --- a/ctrtool/filepath.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -#include "types.h" -#include "filepath.h" - -void filepath_init(filepath* fpath) -{ - fpath->valid = 0; -} - -void filepath_copy(filepath* fpath, filepath* copy) -{ - if (copy != 0 && copy->valid) - memcpy(fpath, copy, sizeof(filepath)); - else - memset(fpath, 0, sizeof(filepath)); -} - -void filepath_append_utf16(filepath* fpath, const u8* name) -{ - u32 size; - - - if (fpath->valid == 0) - return; - - size = strlen(fpath->pathname); - - if (size > 0 && size < (MAX_PATH-1)) - { - if (fpath->pathname[size-1] != PATH_SEPERATOR) - fpath->pathname[size++] = PATH_SEPERATOR; - } - - while(size < (MAX_PATH-1)) - { - u8 lo = *name++; - u8 hi = *name++; - u16 code = (hi<<8) | lo; - - if (code == 0) - break; - - // convert non-ANSI to '#', because unicode support is too much work - if (code > 0x7F) - code = '#'; - - fpath->pathname[size++] = (char) code; - } - - fpath->pathname[size] = 0; - - if (size >= (MAX_PATH-1)) - fpath->valid = 0; -} - -void filepath_append(filepath* fpath, const char* format, ...) -{ - char tmppath[MAX_PATH]; - va_list args; - - if (fpath->valid == 0) - return; - - memset(tmppath, 0, MAX_PATH); - - va_start(args, format); - vsprintf(tmppath, format, args); - va_end(args); - - strcat(fpath->pathname, "/"); - strcat(fpath->pathname, tmppath); -} - -void filepath_set(filepath* fpath, const char* path) -{ - fpath->valid = 1; - memset(fpath->pathname, 0, MAX_PATH); - strncpy(fpath->pathname, path, MAX_PATH); -} - -const char* filepath_get(filepath* fpath) -{ - if (fpath->valid == 0) - return 0; - else - return fpath->pathname; -} diff --git a/ctrtool/filepath.h b/ctrtool/filepath.h deleted file mode 100644 index 9f6d72c..0000000 --- a/ctrtool/filepath.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _FILEPATH_H_ -#define _FILEPATH_H_ - -#include "types.h" -#include "utils.h" - -typedef struct -{ - char pathname[MAX_PATH]; - int valid; -} filepath; - -void filepath_init(filepath* fpath); -void filepath_copy(filepath* fpath, filepath* copy); -void filepath_append_utf16(filepath* fpath, const u8* name); -void filepath_append(filepath* fpath, const char* format, ...); -void filepath_set(filepath* fpath, const char* path); -const char* filepath_get(filepath* fpath); - -#endif // _FILEPATH_H_ diff --git a/ctrtool/firm.c b/ctrtool/firm.c deleted file mode 100644 index 491f4a7..0000000 --- a/ctrtool/firm.c +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include -#include - -#include "types.h" -#include "firm.h" -#include "utils.h" - -void firm_init(firm_context* ctx) -{ - memset(ctx, 0, sizeof(firm_context)); -} - -void firm_set_file(firm_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void firm_set_offset(firm_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void firm_set_size(firm_context* ctx, u32 size) -{ - ctx->size = size; -} - -void firm_set_usersettings(firm_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void firm_save(firm_context* ctx, u32 index, u32 flags) -{ - firm_sectionheader* section = (firm_sectionheader*)(ctx->header.section + index); - u32 offset; - u32 size; - u32 address; - FILE* fout; - filepath outpath; - u8 buffer[16 * 1024]; - - - offset = getle32(section->offset); - size = getle32(section->size); - address = getle32(section->address); - filepath_copy(&outpath, settings_get_firm_dir_path(ctx->usersettings)); - filepath_append(&outpath, "firm_%d_%08X.bin", index, address); - - if (size == 0 || outpath.valid == 0) - return; - - if (size >= ctx->size) - { - fprintf(stderr, "Error, firm section %d size invalid\n", index); - return; - } - - fout = fopen(outpath.pathname, "wb"); - if (fout == 0) - { - fprintf(stderr, "Error, failed to create file %s\n", outpath.pathname); - goto clean; - } - - - - fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); - fprintf(stdout, "Saving section %d to %s...\n", index, outpath.pathname); - - while(size) - { - u32 max = sizeof(buffer); - if (max > size) - max = size; - - if (max != fread(buffer, 1, max, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - if (max != fwrite(buffer, 1, max, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - - size -= max; - } - - -clean: - return; -} - - -void firm_process(firm_context* ctx, u32 actions) -{ - u32 i; - - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, sizeof(firm_header), ctx->file); - - if (getle32(ctx->header.magic) != MAGIC_FIRM) - { - fprintf(stdout, "Error, FIRM segment corrupted\n"); - return; - } - - - if (actions & VerifyFlag) - { - firm_verify(ctx, actions); - firm_signature_verify(ctx); - } - - if (actions & InfoFlag) - { - firm_print(ctx); - } - - if (actions & ExtractFlag) - { - filepath* dirpath = settings_get_firm_dir_path(ctx->usersettings); - - if (dirpath && dirpath->valid) - { - makedir(dirpath->pathname); - for(i=0; i<4; i++) - firm_save(ctx, i, actions); - } - } -} - -int firm_verify(firm_context* ctx, u32 flags) -{ - unsigned int i; - u32 offset; - u32 size; - u8 buffer[16 * 1024]; - u8 hash[0x20]; - - - for(i=0; i<4; i++) - { - firm_sectionheader* section = (firm_sectionheader*)(ctx->header.section + i); - - - offset = getle32(section->offset); - size = getle32(section->size); - - if (size == 0) - return 0; - - fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); - - ctr_sha_256_init(&ctx->sha); - - while(size) - { - u32 max = sizeof(buffer); - if (max > size) - max = size; - - if (max != fread(buffer, 1, max, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - ctr_sha_256_update(&ctx->sha, buffer, max); - - size -= max; - } - - ctr_sha_256_finish(&ctx->sha, hash); - - - if (memcmp(hash, section->hash, 0x20) == 0) - ctx->hashcheck[i] = Good; - else - ctx->hashcheck[i] = Fail; - } - - -clean: - return 0; -} - - -void firm_signature_verify(firm_context* ctx) -{ - u8 hash[0x20]; - - if (ctx->usersettings) - { - ctr_sha_256(ctx->header.magic, 0x100, hash); - ctx->headersigcheck = ctr_rsa_verify_hash(ctx->header.signature, hash, &ctx->usersettings->keys.firmrsakey); - } -} - - -void firm_print(firm_context* ctx) -{ - u32 i; - u32 address; - u32 copyMethod; - u32 offset; - u32 size; - u32 priority = getle32(ctx->header.priority); - u32 entrypointarm11 = getle32(ctx->header.entrypointarm11); - u32 entrypointarm9 = getle32(ctx->header.entrypointarm9); - - fprintf(stdout, "\nFIRM:\n"); - if (ctx->headersigcheck == Unchecked) - memdump(stdout, "Signature: ", ctx->header.signature, 0x100); - else if (ctx->headersigcheck == Good) - memdump(stdout, "Signature (GOOD): ", ctx->header.signature, 0x100); - else - memdump(stdout, "Signature (FAIL): ", ctx->header.signature, 0x100); - - fprintf(stdout, "\n"); - fprintf(stdout, "Priority: %u\n", priority); - fprintf(stdout, "Entrypoint ARM9: 0x%08X\n", entrypointarm9); - fprintf(stdout, "Entrypoint ARM11: 0x%08X\n", entrypointarm11); - fprintf(stdout, "\n"); - - - for(i=0; i<4; i++) - { - firm_sectionheader* section = (firm_sectionheader*)(ctx->header.section + i); - - - offset = getle32(section->offset); - size = getle32(section->size); - address = getle32(section->address); - copyMethod = getle32(section->copyMethod); - - if (size) - { - fprintf(stdout, "Section %d \n", i); - fprintf(stdout, " Copy Method: %s\n", copyMethod==0 ? "NDMA" : copyMethod==1 ? "XDMA" : - copyMethod==2 ? "memcpy" : "UNKNOWN"); - fprintf(stdout, " Address: 0x%08X\n", address); - fprintf(stdout, " Offset: 0x%08X\n", offset); - fprintf(stdout, " Size: 0x%08X\n", size); - if (ctx->hashcheck[i] == Good) - memdump(stdout, " Hash (GOOD): ", section->hash, 0x20); - else if (ctx->hashcheck[i] == Fail) - memdump(stdout, " Hash (FAIL): ", section->hash, 0x20); - else - memdump(stdout, " Hash: ", section->hash, 0x20); - } - } -} diff --git a/ctrtool/firm.h b/ctrtool/firm.h deleted file mode 100644 index 5d1ebbc..0000000 --- a/ctrtool/firm.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _FIRM_H_ -#define _FIRM_H_ - -#include "types.h" -#include "info.h" -#include "ctr.h" -#include "filepath.h" -#include "settings.h" - - -typedef struct -{ - u8 offset[4]; - u8 address[4]; - u8 size[4]; - u8 copyMethod[4]; - u8 hash[32]; -} firm_sectionheader; - - - - -typedef struct -{ - u8 magic[4]; - u8 priority[4]; - u8 entrypointarm11[4]; - u8 entrypointarm9[4]; - u8 reserved1[0x30]; - firm_sectionheader section[4]; - u8 signature[0x100]; -} firm_header; - -typedef struct -{ - FILE* file; - settings* usersettings; - u64 offset; - u32 size; - firm_header header; - ctr_sha256_context sha; - int hashcheck[4]; - int headersigcheck; -} firm_context; - -void firm_init(firm_context* ctx); -void firm_set_file(firm_context* ctx, FILE* file); -void firm_set_offset(firm_context* ctx, u64 offset); -void firm_set_size(firm_context* ctx, u32 size); -void firm_set_usersettings(firm_context* ctx, settings* usersettings); -void firm_process(firm_context* ctx, u32 actions); -void firm_print(firm_context* ctx); -void firm_save(firm_context* ctx, u32 index, u32 flags); -int firm_verify(firm_context* ctx, u32 flags); -void firm_signature_verify(firm_context* ctx); - -#endif // _FIRM_H_ diff --git a/ctrtool/info.h b/ctrtool/info.h deleted file mode 100644 index fac4117..0000000 --- a/ctrtool/info.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _INFO_H_ -#define _INFO_H_ - -#include "types.h" -#include "keyset.h" - -typedef struct -{ - FILE* file; - keyset* keys; - u32 offset; - const u8* blob; - u32 blobsize; -} infocontext; - -#endif // _INFO_H_ diff --git a/ctrtool/ivfc.c b/ctrtool/ivfc.c deleted file mode 100644 index 4a77a67..0000000 --- a/ctrtool/ivfc.c +++ /dev/null @@ -1,247 +0,0 @@ -#include -#include -#include -#include "types.h" -#include "utils.h" -#include "ivfc.h" -#include "ctr.h" - -void ivfc_init(ivfc_context* ctx) -{ - memset(ctx, 0, sizeof(ivfc_context)); -} - -void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void ivfc_set_offset(ivfc_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void ivfc_set_size(ivfc_context* ctx, u64 size) -{ - ctx->size = size; -} - -void ivfc_set_file(ivfc_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted) -{ - ctx->encrypted = encrypted; -} - -void ivfc_set_key(ivfc_context* ctx, u8 key[16]) -{ - ctr_init_key(&ctx->aes, key); -} - -void ivfc_set_counter(ivfc_context* ctx, u8 counter[16]) -{ - memcpy(ctx->counter, counter, 16); -} - -void ivfc_fseek(ivfc_context* ctx, u64 offset) -{ - u64 data_pos = offset - ctx->offset; - fseeko64(ctx->file, offset, SEEK_SET); - - if (ctx->encrypted) { - //printf("start fseek encrypted prep\n"); - ctr_init_counter(&ctx->aes, ctx->counter); - //printf("middle fseek encrypted prep\n"); - ctr_add_counter(&ctx->aes, (u32)(data_pos / 0x10)); - //printf("finish fseek encrypted prep\n"); - } -} - -size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count) -{ - size_t read; - if ((read = fread(buffer, size, count, ctx->file)) != count) { - //printf("ivfc_fread() fail\n"); - return read; - } - if (ctx->encrypted) { - ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read); - } - return read; -} - - -void ivfc_process(ivfc_context* ctx, u32 actions) -{ - ivfc_fseek(ctx, ctx->offset); - ivfc_fread(ctx, &ctx->header, 1, sizeof(ivfc_header)); - - if (getle32(ctx->header.magic) != MAGIC_IVFC) - { - fprintf(stdout, "Error, IVFC segment corrupted\n"); - return; - } - - if (getle32(ctx->header.id) == 0x10000) - { - ctx->levelcount = 3; - - ctx->level[2].hashblocksize = 1 << getle32(ctx->header.level3.blocksize); - ctx->level[1].hashblocksize = 1 << getle32(ctx->header.level2.blocksize); - ctx->level[0].hashblocksize = 1 << getle32(ctx->header.level1.blocksize); - - ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->header.masterhashsize), ctx->level[2].hashblocksize); - ctx->bodysize = getle64(ctx->header.level3.hashdatasize); - - ctx->level[2].dataoffset = ctx->bodyoffset; - ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize); - - ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize; - ctx->level[0].datasize = align64(getle64(ctx->header.level1.hashdatasize), ctx->level[0].hashblocksize); - - ctx->level[1].dataoffset = ctx->level[0].dataoffset + ctx->level[0].datasize; - ctx->level[1].datasize = align64(getle64(ctx->header.level2.hashdatasize), ctx->level[1].hashblocksize); - - ctx->level[0].hashoffset = IVFC_HEADER_SIZE; - ctx->level[1].hashoffset = ctx->level[0].dataoffset; - ctx->level[2].hashoffset = ctx->level[1].dataoffset; - } - - if (actions & VerifyFlag) - ivfc_verify(ctx, actions); - - if (actions & InfoFlag) - ivfc_print(ctx); - -} - -void ivfc_verify(ivfc_context* ctx, u32 flags) -{ - u32 i, j; - u32 blockcount; - - for(i=0; ilevelcount; i++) - { - ivfc_level* level = ctx->level + i; - - level->hashcheck = Fail; - } - - // Import IVFC level hashes - uint8_t *levelhash[IVFC_MAX_LEVEL] = { NULL }; - - for (i=0; ilevelcount; i++) - { - blockcount = (u32)(ctx->level[i].datasize / ctx->level[i].hashblocksize); - u32 read_size = align(blockcount * 0x20, ctx->level[i].hashblocksize); - levelhash[i] = malloc(read_size); - ivfc_read(ctx, ctx->level[i].hashoffset, read_size, levelhash[i]); - } - - // Verify blocks - for (i=0; ilevelcount; i++) - { - blockcount = (u32) (ctx->level[i].datasize / ctx->level[i].hashblocksize); - if (ctx->level[i].datasize % ctx->level[i].hashblocksize != 0) - { - fprintf(stderr, "Error, IVFC block size mismatch\n"); - return; - } - - ctx->level[i].hashcheck = Good; - - for (j=0; jlevel[i].hashblocksize * j, ctx->level[i].hashblocksize, calchash); - } - // a data level - else { - ivfc_read(ctx, ctx->level[i].dataoffset + j * ctx->level[i].hashblocksize, ctx->level[i].hashblocksize, ctx->buffer); - ctr_sha_256(ctx->buffer, (u32)ctx->level[i].hashblocksize, calchash); - } - - if (memcmp(calchash, levelhash[i] + 0x20 * j, 0x20) != 0) { - ctx->level[i].hashcheck = Fail; - } - - } - } - - // Free level hashes - for (int i = 0; i < 3; i++) { - free(levelhash[i]); - } -} - -void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer) -{ - if ( (offset > ctx->size) || (offset+size > ctx->size) ) - { - fprintf(stderr, "Error, IVFC offset out of range (offset=0x%08"PRIx64", size=0x%08"PRIx64")\n", offset, size); - return; - } - - ivfc_fseek(ctx, ctx->offset + offset); - if (size != ivfc_fread(ctx, buffer, 1, (size_t) size)) - { - fprintf(stderr, "Error, IVFC could not read file\n"); - return; - } -} - -void ivfc_hash(ivfc_context* ctx, u64 offset, u64 size, u8* hash) -{ - if (size > IVFC_MAX_BUFFERSIZE) - { - fprintf(stderr, "Error, IVFC hash block size too big.\n"); - return; - } - - ivfc_read(ctx, offset, size, ctx->buffer); - - ctr_sha_256(ctx->buffer, (u32) size, hash); -} - -void ivfc_print(ivfc_context* ctx) -{ - u32 i; - ivfc_header* header = &ctx->header; - - fprintf(stdout, "\nIVFC:\n"); - - fprintf(stdout, "Header: %.4s\n", header->magic); - fprintf(stdout, "Id: %08x\n", getle32(header->id)); - - for(i=0; ilevelcount; i++) - { - ivfc_level* level = ctx->level + i; - - fprintf(stdout, "\n"); - if (level->hashcheck == Unchecked) - fprintf(stdout, "Level %d: \n", i); - else - fprintf(stdout, "Level %d (%s): \n", i, level->hashcheck == Good? "GOOD" : "FAIL"); - fprintf(stdout, " Data offset: 0x%08"PRIx64"\n", ctx->offset + level->dataoffset); - fprintf(stdout, " Data size: 0x%08"PRIx64"\n", level->datasize); - fprintf(stdout, " Hash offset: 0x%08"PRIx64"\n", ctx->offset + level->hashoffset); - fprintf(stdout, " Hash block size: 0x%08x\n", level->hashblocksize); - } -} - -u64 ivfc_get_body_offset(ivfc_context* ctx) -{ - return ctx->bodyoffset; -} - -u64 ivfc_get_body_size(ivfc_context* ctx) -{ - return ctx->bodysize; -} - diff --git a/ctrtool/ivfc.h b/ctrtool/ivfc.h deleted file mode 100644 index 67b5c7e..0000000 --- a/ctrtool/ivfc.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __IVFC_H__ -#define __IVFC_H__ - -#include "types.h" -#include "ctr.h" -#include "settings.h" - -#define IVFC_HEADER_SIZE 0x60 -#define IVFC_MAX_LEVEL 4 -#define IVFC_MAX_BUFFERSIZE 0x4000 - -typedef struct -{ - u8 logicaloffset[8]; - u8 hashdatasize[8]; - u8 blocksize[4]; - u8 reserved[4]; -} ivfc_levelheader; - -typedef struct -{ - u64 dataoffset; - u64 datasize; - u64 hashoffset; - u32 hashblocksize; - int hashcheck; -} ivfc_level; - -typedef struct -{ - u8 magic[4]; - u8 id[4]; - u8 masterhashsize[4]; - ivfc_levelheader level1; - ivfc_levelheader level2; - ivfc_levelheader level3; - u8 reserved[4]; - u8 optionalsize[4]; -} ivfc_header; - -typedef struct -{ - FILE* file; - u64 offset; - u64 size; - settings* usersettings; - u8 counter[16]; - ctr_aes_context aes; - int encrypted; - - ivfc_header header; - - u32 levelcount; - ivfc_level level[IVFC_MAX_LEVEL]; - u64 bodyoffset; - u64 bodysize; - u8 buffer[IVFC_MAX_BUFFERSIZE]; -} ivfc_context; - -void ivfc_init(ivfc_context* ctx); -void ivfc_process(ivfc_context* ctx, u32 actions); -void ivfc_set_offset(ivfc_context* ctx, u64 offset); -void ivfc_set_size(ivfc_context* ctx, u64 size); -void ivfc_set_file(ivfc_context* ctx, FILE* file); -void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings); -void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted); -void ivfc_set_key(ivfc_context* ctx, u8 key[16]); -void ivfc_set_counter(ivfc_context* ctx, u8 counter[16]); -void ivfc_fseek(ivfc_context* ctx, u64 offset); -size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count); - -void ivfc_verify(ivfc_context* ctx, u32 flags); -void ivfc_print(ivfc_context* ctx); - -void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer); -void ivfc_hash(ivfc_context* ctx, u64 offset, u64 size, u8* hash); - -#endif // __IVFC_H__ diff --git a/ctrtool/keyset.cpp b/ctrtool/keyset.cpp deleted file mode 100644 index b4e6763..0000000 --- a/ctrtool/keyset.cpp +++ /dev/null @@ -1,395 +0,0 @@ -#include -#include "keyset.h" -#include "utils.h" -#include "tinyxml/tinyxml.h" - -static void keyset_set_key128(key128* key, unsigned char* keydata); -static void keyset_parse_key128(key128* key, char* keytext, int keylen); -static int keyset_parse_key(const char* text, unsigned int textlen, unsigned char* key, unsigned int size, int* valid); -static int keyset_load_rsakey2048(TiXmlElement* elem, rsakey2048* key); -static int keyset_load_key128(TiXmlHandle node, key128* key); -static int keyset_load_key(TiXmlHandle node, unsigned char* key, unsigned int maxsize, int* valid); - -static int ishex(char c) -{ - if (c >= '0' && c <= '9') - return 1; - if (c >= 'A' && c <= 'F') - return 1; - if (c >= 'a' && c <= 'f') - return 1; - return 0; - -} - -static unsigned char hextobin(char c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - if (c >= 'A' && c <= 'F') - return c-'A'+0xA; - if (c >= 'a' && c <= 'f') - return c-'a'+0xA; - return 0; -} - -void keyset_init(keyset* keys, u32 actions) -{ - const key128 defaultkeys_retail[] = { - // fixed system key - unknown if used/correct? - {{0x52, 0x7c, 0xe6, 0x30, 0xa9, 0xca, 0x30, 0x5f, 0x36, 0x96, 0xf3, 0xcd, 0xe9, 0x54, 0x19, 0x4b}, 1}, - // NCCH 0x2c keyX - {{0xb9, 0x8e, 0x95, 0xce, 0xca, 0x3e, 0x4d, 0x17, 0x1f, 0x76, 0xa9, 0x4d, 0xe9, 0x34, 0xc0, 0x53}, 1}, - // NCCH 0x25 keyX 7.x - {{0xce, 0xe7, 0xd8, 0xab, 0x30, 0xc0, 0x0d, 0xae, 0x85, 0x0e, 0xf5, 0xe3, 0x82, 0xac, 0x5a, 0xf3}, 1}, - // NCCH 0x18 keyX N9.3 - {{0x82, 0xe9, 0xc9, 0xbe, 0xbf, 0xb8, 0xbd, 0xb8, 0x75, 0xec, 0xc0, 0xa0, 0x7d, 0x47, 0x43, 0x74}, 1}, - // NCCH 0x1B keyX N9.6 - {{0x45, 0xad, 0x04, 0x95, 0x39, 0x92, 0xc7, 0xc8, 0x93, 0x72, 0x4a, 0x9a, 0x7b, 0xce, 0x61, 0x82}, 1}, - // common key index0 (application) - {{0x64, 0xC5, 0xFD, 0x55, 0xDD, 0x3A, 0xD9, 0x88, 0x32, 0x5B, 0xAA, 0xEC, 0x52, 0x43, 0xDB, 0x98}, 1}, - // common key index1 (system) - {{0x4A, 0xAA, 0x3D, 0x0E, 0x27, 0xD4, 0xD7, 0x28, 0xD0, 0xB1, 0xB4, 0x33, 0xF0, 0xF9, 0xCB, 0xC8}, 1}, - // common key index2 - {{0xFB, 0xB0, 0xEF, 0x8C, 0xDB, 0xB0, 0xD8, 0xE4, 0x53, 0xCD, 0x99, 0x34, 0x43, 0x71, 0x69, 0x7F}, 1}, - // common key index3 - {{0x25, 0x95, 0x9B, 0x7A, 0xD0, 0x40, 0x9F, 0x72, 0x68, 0x41, 0x98, 0xBA, 0x2E, 0xCD, 0x7D, 0xC6}, 1}, - // common key index4 - {{0x7A, 0xDA, 0x22, 0xCA, 0xFF, 0xC4, 0x76, 0xCC, 0x82, 0x97, 0xA0, 0xC7, 0xCE, 0xEE, 0xEE, 0xBE}, 1}, - // common key index5 - {{0xA5, 0x05, 0x1C, 0xA1, 0xB3, 0x7D, 0xCF, 0x3A, 0xFB, 0xCF, 0x8C, 0xC1, 0xED, 0xD9, 0xCE, 0x02}, 1}, - }; - const key128 defaultkeys_dev[] = { - // fixed system key - {{0x52, 0x7c, 0xe6, 0x30, 0xa9, 0xca, 0x30, 0x5f, 0x36, 0x96, 0xf3, 0xcd, 0xe9, 0x54, 0x19, 0x4b}, 1}, - // NCCH 0x2c keyX - {{0x51, 0x02, 0x07, 0x51, 0x55, 0x07, 0xcb, 0xb1, 0x8e, 0x24, 0x3d, 0xcb, 0x85, 0xe2, 0x3a, 0x1d}, 1}, - // NCCH 0x25 keyX 7.x - {{0x81, 0x90, 0x7a, 0x4b, 0x6f, 0x1b, 0x47, 0x32, 0x3a, 0x67, 0x79, 0x74, 0xce, 0x4a, 0xd7, 0x1b}, 1}, - // NCCH 0x18 keyX N9.3 - {{0x30, 0x4b, 0xf1, 0x46, 0x83, 0x72, 0xee, 0x64, 0x11, 0x5e, 0xbd, 0x40, 0x93, 0xd8, 0x42, 0x76}, 1}, - // NCCH 0x1B keyX N9.6 - {{0x6c, 0x8b, 0x29, 0x44, 0xa0, 0x72, 0x60, 0x35, 0xf9, 0x41, 0xdf, 0xc0, 0x18, 0x52, 0x4f, 0xb6}, 1}, - // common key index0 - {{0x55, 0xA3, 0xF8, 0x72, 0xBD, 0xC8, 0x0C, 0x55, 0x5A, 0x65, 0x43, 0x81, 0x13, 0x9E, 0x15, 0x3B}, 1}, - // common key index1 - {{0x44, 0x34, 0xED, 0x14, 0x82, 0x0C, 0xA1, 0xEB, 0xAB, 0x82, 0xC1, 0x6E, 0x7B, 0xEF, 0x0C, 0x25}, 1}, - // common key index2 - {{0xF6, 0x2E, 0x3F, 0x95, 0x8E, 0x28, 0xA2, 0x1F, 0x28, 0x9E, 0xEC, 0x71, 0xA8, 0x66, 0x29, 0xDC}, 1}, - // common key index3 - {{0x2B, 0x49, 0xCB, 0x6F, 0x99, 0x98, 0xD9, 0xAD, 0x94, 0xF2, 0xED, 0xE7, 0xB5, 0xDA, 0x3E, 0x27}, 1}, - // common key index4 - {{0x75, 0x05, 0x52, 0xBF, 0xAA, 0x1C, 0x04, 0x07, 0x55, 0xC8, 0xD5, 0x9A, 0x55, 0xF9, 0xAD, 0x1F}, 1}, - // common key index5 - {{0xAA, 0xDA, 0x4C, 0xA8, 0xF6, 0xE5, 0xA9, 0x77, 0xE0, 0xA0, 0xF9, 0xE4, 0x76, 0xCF, 0x0D, 0x63}, 1}, - }; - - memset(keys, 0, sizeof(keyset)); - - if (actions & PlainFlag) - return; - - // select keyset - const key128* default_keys = (actions & DevFlag)? defaultkeys_dev : defaultkeys_retail; - - u32 key_index = 0; - // set ncch keys - memcpy(&keys->ncchfixedsystemkey, &default_keys[key_index++], sizeof(key128)); - memcpy(&keys->ncchkeyX_old, &default_keys[key_index++], sizeof(key128)); - memcpy(&keys->ncchkeyX_seven, &default_keys[key_index++], sizeof(key128)); - memcpy(&keys->ncchkeyX_ninethree, &default_keys[key_index++], sizeof(key128)); - memcpy(&keys->ncchkeyX_ninesix, &default_keys[key_index++], sizeof(key128)); - - // set common keys - for (u32 i = 0; i < COMMONKEY_NUM; i++) - { - memcpy(&keys->commonkey[i], &default_keys[key_index++], sizeof(key128)); - } - -} - -int keyset_load_key(TiXmlHandle node, unsigned char* key, unsigned int size, int* valid) -{ - TiXmlElement* elem = node.ToElement(); - - if (valid) - *valid = 0; - - if (!elem) - return 0; - - const char* text = elem->GetText(); - unsigned int textlen = strlen(text); - - int status = keyset_parse_key(text, textlen, key, size, valid); - - if (status == KEY_ERR_LEN_MISMATCH) - { - fprintf(stderr, "Error size mismatch for key \"%s/%s\"\n", elem->Parent()->Value(), elem->Value()); - return 0; - } - - return 1; -} - - -int keyset_parse_key(const char* text, unsigned int textlen, unsigned char* key, unsigned int size, int* valid) -{ - unsigned int i, j; - unsigned int hexcount = 0; - - - if (valid) - *valid = 0; - - for(i=0; idata, sizeof(key->data), &key->valid); -} - -int keyset_load_rsakey2048(TiXmlHandle node, rsakey2048* key) -{ - key->keytype = RSAKEY_INVALID; - - if (!keyset_load_key(node.FirstChild("N"), key->n, sizeof(key->n), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("E"), key->e, sizeof(key->e), 0)) - goto clean; - key->keytype = RSAKEY_PUB; - - if (!keyset_load_key(node.FirstChild("D"), key->d, sizeof(key->d), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("P"), key->p, sizeof(key->p), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("Q"), key->q, sizeof(key->q), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("DP"), key->dp, sizeof(key->dp), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("DQ"), key->dq, sizeof(key->dq), 0)) - goto clean; - if (!keyset_load_key(node.FirstChild("QP"), key->qp, sizeof(key->qp), 0)) - goto clean; - - key->keytype = RSAKEY_PRIV; -clean: - return (key->keytype != RSAKEY_INVALID); -} - -int keyset_load(keyset* keys, const char* fname, int verbose) -{ - TiXmlDocument doc(fname); - bool loadOkay = doc.LoadFile(); - - if (!loadOkay) - { - if (verbose) - fprintf(stderr, "Could not load keyset file \"%s\", error: %s.\n", fname, doc.ErrorDesc() ); - - return 0; - } - - TiXmlHandle root = doc.FirstChild("document"); - - keyset_load_rsakey2048(root.FirstChild("ncsdrsakey"), &keys->ncsdrsakey); - keyset_load_rsakey2048(root.FirstChild("ncchrsakey"), &keys->ncchrsakey); - keyset_load_rsakey2048(root.FirstChild("ncchdescrsakey"), &keys->ncchdescrsakey); - keyset_load_rsakey2048(root.FirstChild("firmrsakey"), &keys->firmrsakey); - /* - keyset_load_key128(root.FirstChild("ncchfixedsystemkey"), &keys->ncchfixedsystemkey); - keyset_load_key128(root.FirstChild("ncchkeyxold"), &keys->ncchkeyX_old); - keyset_load_key128(root.FirstChild("ncchkeyxseven"), &keys->ncchkeyX_seven); - keyset_load_key128(root.FirstChild("ncchkeyxninethree"), &keys->ncchkeyX_ninethree); - keyset_load_key128(root.FirstChild("ncchkeyxninesix"), &keys->ncchkeyX_ninesix); - */ - - return 1; -} - - -void keyset_merge(keyset* keys, keyset* src) -{ -#define COPY_IF_VALID(v) do {\ - if (src->v.valid && !keys->v.valid)\ - keyset_set_key128(&keys->v, src->v.data);\ -} while (0) - - // todo complete key copy - /* COPY_IF_VALID(commonkey[0]); */ - //if () - for (size_t i = 0; i < COMMONKEY_NUM; i++) - { - COPY_IF_VALID(commonkey[i]); - } - COPY_IF_VALID(titlekey); - COPY_IF_VALID(seed_fallback); - COPY_IF_VALID(ncchfixedsystemkey); - COPY_IF_VALID(ncchkeyX_old); - COPY_IF_VALID(ncchkeyX_seven); - COPY_IF_VALID(ncchkeyX_ninethree); - COPY_IF_VALID(ncchkeyX_ninesix); - if (src->seed_num > 0) - { - keys->seed_num = src->seed_num; - keys->seed_db = (seeddb_entry*)calloc(keys->seed_num, sizeof(seeddb_entry)); - memcpy(keys->seed_db, src->seed_db, keys->seed_num * sizeof(seeddb_entry)); - } - -#undef COPY_IF_VALID -} - -void keyset_set_key128(key128* key, unsigned char* keydata) -{ - memcpy(key->data, keydata, 16); - key->valid = 1; -} - -void keyset_parse_key128(key128* key, char* keytext, int keylen) -{ - keyset_parse_key(keytext, keylen, key->data, 16, &key->valid); -} - -void keyset_parse_titlekey(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->titlekey, keytext, keylen); -} - -void keyset_parse_ncchkeyX_old(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->ncchkeyX_old, keytext, keylen); -} - -void keyset_parse_ncchfixedsystemkey(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->ncchfixedsystemkey, keytext, keylen); -} - -void keyset_parse_ncchkeyX_seven(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->ncchkeyX_seven, keytext, keylen); -} - -void keyset_parse_ncchkeyX_ninethree(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->ncchkeyX_ninethree, keytext, keylen); -} - -void keyset_parse_ncchkeyX_ninesix(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->ncchkeyX_ninesix, keytext, keylen); -} - -void keyset_parse_seeddb(keyset* keys, char* path) -{ - //keyset_parse_key128(&keys->seed, keytext, keylen); - FILE* fp = fopen(path, "rb"); - if (fp == NULL) - { - printf("[ERROR] Failed to load SeedDB (failed to open file)\n"); - return; - } - - seeddb_header hdr; - fread(&hdr, sizeof(seeddb_header), 1, fp); - - keys->seed_num = getle32(hdr.n_entries); - for (u32 i = 0; i < 0xC; i++) - { - if (hdr.padding[i] != 0x00) - { - printf("[ERROR] SeedDB is corrupt. (padding malformed)\n"); - return; - } - } - - keys->seed_db = (seeddb_entry*)calloc(keys->seed_num, sizeof(seeddb_entry)); - fread(keys->seed_db, keys->seed_num * sizeof(seeddb_entry), 1, fp); -} - -void keyset_parse_seed_fallback(keyset* keys, char* keytext, int keylen) -{ - keyset_parse_key128(&keys->seed_fallback, keytext, keylen); -} - - -void keyset_dump_rsakey(rsakey2048* key, const char* keytitle) -{ - if (key->keytype == RSAKEY_INVALID) - return; - - - fprintf(stdout, "%s\n", keytitle); - - memdump(stdout, "Modulus: ", key->n, 256); - memdump(stdout, "Exponent: ", key->e, 3); - - if (key->keytype == RSAKEY_PRIV) - { - memdump(stdout, "P: ", key->p, 128); - memdump(stdout, "Q: ", key->q, 128); - } - fprintf(stdout, "\n"); -} - -void keyset_dump_key128(key128* key, const char* keytitle) -{ - if (key->valid) - { - fprintf(stdout, "%s\n", keytitle); - memdump(stdout, "", key->data, 16); - fprintf(stdout, "\n"); - } -} - -void keyset_dump(keyset* keys) -{ -#define DUMP_KEY(n, s) do {\ - keyset_dump_key128(&keys->n, (s));\ -} while(0) - fprintf(stdout, "Current keyset: \n"); - DUMP_KEY(ncchkeyX_old, "NCCH OLD KEYX"); - DUMP_KEY(ncchkeyX_seven, "NCCH 7.0 KEYX"); - DUMP_KEY(ncchkeyX_ninethree, "NCCH N9.3 KEYX"); - DUMP_KEY(ncchkeyX_ninesix, "NCCH N9.6 KEYX"); - DUMP_KEY(ncchfixedsystemkey, "NCCH FIXEDSYSTEMKEY"); -#undef DUMP_KEY - - keyset_dump_rsakey(&keys->ncsdrsakey, "NCSD RSA KEY"); - keyset_dump_rsakey(&keys->ncchdescrsakey, "NCCH DESC RSA KEY"); - - fprintf(stdout, "\n"); -} - diff --git a/ctrtool/keyset.h b/ctrtool/keyset.h deleted file mode 100644 index 4d9235d..0000000 --- a/ctrtool/keyset.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef _KEYSET_H_ -#define _KEYSET_H_ - -#include "types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define COMMONKEY_NUM 6 - -typedef enum -{ - KEY_ERR_LEN_MISMATCH, - KEY_ERR_INVALID_NODE, - KEY_OK -} keystatus; - -typedef enum -{ - RSAKEY_INVALID, - RSAKEY_PRIV, - RSAKEY_PUB -} rsakeytype; - -typedef struct -{ - u8 title_id[8]; - u8 seed[0x10]; - u8 padding[0x8]; -} seeddb_entry; - -typedef struct -{ - u8 n_entries[4]; - u8 padding[0xC]; -} seeddb_header; - - -typedef struct -{ - unsigned char n[256]; - unsigned char e[3]; - unsigned char d[256]; - unsigned char p[128]; - unsigned char q[128]; - unsigned char dp[128]; - unsigned char dq[128]; - unsigned char qp[128]; - rsakeytype keytype; -} rsakey2048; - -typedef struct -{ - unsigned char data[16]; - int valid; -} key128; - -typedef struct -{ - u32 seed_num; - seeddb_entry* seed_db; - - key128 commonkey[COMMONKEY_NUM]; - key128 titlekey; - key128 seed_fallback; - key128 ncchfixedsystemkey; - key128 ncchkeyX_old; - key128 ncchkeyX_seven; - key128 ncchkeyX_ninethree; - key128 ncchkeyX_ninesix; - rsakey2048 ncsdrsakey; - rsakey2048 ncchrsakey; - rsakey2048 ncchdescrsakey; - rsakey2048 firmrsakey; -} keyset; - -void keyset_init(keyset* keys, u32 actions); -int keyset_load(keyset* keys, const char* fname, int verbose); -void keyset_merge(keyset* keys, keyset* src); -void keyset_parse_titlekey(keyset* keys, char* keytext, int keylen); -void keyset_parse_ncchkeyX_old(keyset* keys, char* keytext, int keylen); -void keyset_parse_ncchfixedsystemkey(keyset* keys, char* keytext, int keylen); -void keyset_parse_ncchkeyX_seven(keyset* keys, char* keytext, int keylen); -void keyset_parse_ncchkeyX_ninethree(keyset* keys, char* keytext, int keylen); -void keyset_parse_ncchkeyX_ninesix(keyset* keys, char* keytext, int keylen); -void keyset_parse_seeddb(keyset* keys, char* path); -void keyset_parse_seed_fallback(keyset* keys, char* keytext, int keylen); -void keyset_dump(keyset* keys); - -#ifdef __cplusplus -} -#endif - - -#endif // _KEYSET_H_ diff --git a/ctrtool/lzss.c b/ctrtool/lzss.c deleted file mode 100644 index 1a853a5..0000000 --- a/ctrtool/lzss.c +++ /dev/null @@ -1,195 +0,0 @@ -#include -#include -#include -#include "types.h" -#include "utils.h" -#include "lzss.h" - -void lzss_init(lzss_context* ctx) -{ - memset(ctx, 0, sizeof(lzss_context)); -} - -void lzss_set_usersettings(lzss_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void lzss_set_offset(lzss_context* ctx, u32 offset) -{ - ctx->offset = offset; -} - -void lzss_set_size(lzss_context* ctx, u32 size) -{ - ctx->size = size; -} - -void lzss_set_file(lzss_context* ctx, FILE* file) -{ - ctx->file = file; -} - - -void lzss_process(lzss_context* ctx, u32 actions) -{ - unsigned int compressedsize; - unsigned char* compressedbuffer = 0; - unsigned int decompressedsize; - unsigned char* decompressedbuffer = 0; - FILE* fout = 0; - - - fseeko64(ctx->file, ctx->offset, SEEK_SET); - - - if (actions & ExtractFlag) - { - - filepath* path = settings_get_lzss_path(ctx->usersettings); - - if (path == 0 || path->valid == 0) - goto clean; - - fout = fopen(path->pathname, "wb"); - if (0 == fout) - { - fprintf(stdout, "Error opening out file %s\n", path->pathname); - goto clean; - } - compressedsize = ctx->size; - compressedbuffer = malloc(compressedsize); - if (1 != fread(compressedbuffer, compressedsize, 1, ctx->file)) - { - fprintf(stdout, "Error read input file\n"); - goto clean; - } - - decompressedsize = lzss_get_decompressed_size(compressedbuffer, compressedsize); - decompressedbuffer = malloc(decompressedsize); - - printf("Compressed: %d\n", compressedsize); - printf("Decompressed: %d\n", decompressedsize); - - if (decompressedbuffer == 0) - { - fprintf(stdout, "Error allocating memory\n"); - goto clean; - } - - if (0 == lzss_decompress(compressedbuffer, compressedsize, decompressedbuffer, decompressedsize)) - goto clean; - - printf("Saving decompressed lzss blob to %s...\n", path->pathname); - if (decompressedsize != fwrite(decompressedbuffer, 1, decompressedsize, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - } - -clean: - free(decompressedbuffer); - free(compressedbuffer); - if (fout) - fclose(fout); -} - - -u32 lzss_get_decompressed_size(u8* compressed, u32 compressedsize) -{ - u8* footer = compressed + compressedsize - 8; - - //u32 buffertopandbottom = getle32(footer+0); - u32 originalbottom = getle32(footer+4); - - return originalbottom + compressedsize; -} - -int lzss_decompress(u8* compressed, u32 compressedsize, u8* decompressed, u32 decompressedsize) -{ - u8* footer = compressed + compressedsize - 8; - u32 buffertopandbottom = getle32(footer+0); - //u32 originalbottom = getle32(footer+4); - u32 i, j; - u32 out = decompressedsize; - u32 index = compressedsize - ((buffertopandbottom>>24)&0xFF); - u32 segmentoffset; - u32 segmentsize; - u8 control; - u32 stopindex = compressedsize - (buffertopandbottom&0xFFFFFF); - - memset(decompressed, 0, decompressedsize); - memcpy(decompressed, compressed, compressedsize); - - - while(index > stopindex) - { - control = compressed[--index]; - - - for(i=0; i<8; i++) - { - if (index <= stopindex) - break; - - if (index <= 0) - break; - - if (out <= 0) - break; - - if (control & 0x80) - { - if (index < 2) - { - fprintf(stderr, "Error, compression out of bounds\n"); - goto clean; - } - - index -= 2; - - segmentoffset = compressed[index] | (compressed[index+1]<<8); - segmentsize = ((segmentoffset >> 12)&15)+3; - segmentoffset &= 0x0FFF; - segmentoffset += 2; - - - if (out < segmentsize) - { - fprintf(stderr, "Error, compression out of bounds\n"); - goto clean; - } - - for(j=0; j= decompressedsize) - { - fprintf(stderr, "Error, compression out of bounds\n"); - goto clean; - } - - data = decompressed[out+segmentoffset]; - decompressed[--out] = data; - } - } - else - { - if (out < 1) - { - fprintf(stderr, "Error, compression out of bounds\n"); - goto clean; - } - decompressed[--out] = compressed[--index]; - } - - control <<= 1; - } - } - - return 1; -clean: - return 0; -} diff --git a/ctrtool/lzss.h b/ctrtool/lzss.h deleted file mode 100644 index 64a5b2f..0000000 --- a/ctrtool/lzss.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LZSS_H_ -#define _LZSS_H_ - -#include "types.h" -#include "settings.h" - -typedef struct -{ - FILE* file; - u32 offset; - u32 size; - settings* usersettings; -} lzss_context; - -void lzss_init(lzss_context* ctx); -void lzss_process(lzss_context* ctx, u32 actions); -void lzss_set_offset(lzss_context* ctx, u32 offset); -void lzss_set_size(lzss_context* ctx, u32 size); -void lzss_set_file(lzss_context* ctx, FILE* file); -void lzss_set_usersettings(lzss_context* ctx, settings* usersettings); - -u32 lzss_get_decompressed_size(u8* compressed, u32 compressedsize); -int lzss_decompress(u8* compressed, u32 compressedsize, u8* decompressed, u32 decompressedsize); - - -#endif // _LZSS_H_ diff --git a/ctrtool/main.c b/ctrtool/main.c deleted file mode 100644 index 1cbc04b..0000000 --- a/ctrtool/main.c +++ /dev/null @@ -1,488 +0,0 @@ -#include -#include -#include -#include -#include "utils.h" -#include "ctr.h" -#include "ncch.h" -#include "ncsd.h" -#include "cia.h" -#include "tmd.h" -#include "tik.h" -#include "lzss.h" -#include "keyset.h" -#include "exefs.h" -#include "info.h" -#include "settings.h" -#include "firm.h" -#include "cwav.h" -#include "romfs.h" - -enum cryptotype -{ - Plain, - CTR, - CBC -}; - - -typedef struct -{ - int actions; - u32 filetype; - FILE* infile; - u64 infilesize; - settings usersettings; -} toolcontext; - -static void usage(const char *argv0) -{ - fprintf(stderr, - "CTRTOOL v0.7 (c) neimod, 3DSGuy.\n" - "Built: %s %s\n" - "\n" - "Usage: %s [options...] \n" - "Options:\n" - " -i, --info Show file info.\n" - " This is the default action.\n" - " -x, --extract Extract data from file.\n" - " This is also the default action.\n" - " -p, --plain Extract data without decrypting.\n" - " -r, --raw Keep raw data, don't unpack.\n" - " -k, --keyset=file Specify keyset file.\n" - " -v, --verbose Give verbose output.\n" - " -y, --verify Verify hashes and signatures.\n" - " -d, --dev Decrypt with development keys instead of retail.\n" - " --unitsize=size Set media unit size (default 0x200).\n" -// " --commonkey=key Set common key.\n" - " --titlekey=key Set tik title key.\n" -// " --ncchkey=key Set ncch key.\n" -// " --ncchsyskey=key Set ncch fixed system key.\n" - " --seeddb=file Set seeddb for ncch seed crypto.\n" - " --seed=key Set specific seed for ncch seed crypto.\n" - " --showkeys Show the keys being used.\n" - " --showsyscalls Show system call names instead of numbers.\n" - " -t, --intype=type Specify input file type [ncsd, ncch, exheader, cia, tmd, lzss,\n" - " firm, cwav, exefs, romfs]\n" - "LZSS options:\n" - " --lzssout=file Specify lzss output file\n" - "CXI/CCI options:\n" - " -n, --ncch=index Specify NCCH partition index.\n" - " --exheader=file Specify Extended Header file path.\n" - " --logo=file Specify Logo file path.\n" - " --plainrgn=file Specify Plain region file path\n" - " --exefs=file Specify ExeFS file path.\n" - " --exefsdir=dir Specify ExeFS directory path.\n" - " --romfs=file Specify RomFS file path.\n" - " --romfsdir=dir Specify RomFS directory path.\n" - " --listromfs List files in RomFS.\n" - "CIA options:\n" - " --certs=file Specify Certificate chain file path.\n" - " --tik=file Specify Ticket file path.\n" - " --tmd=file Specify TMD file path.\n" - " --contents=file Specify Contents file path.\n" - " --meta=file Specify Meta file path.\n" - "FIRM options:\n" - " --firmdir=dir Specify Firm directory path.\n" - "CWAV options:\n" - " --wav=file Specify wav output file.\n" - " --wavloops=count Specify wav loop count, default 0.\n" - "EXEFS options:\n" - " --decompresscode Decompress .code section\n" - " (only needed when using raw EXEFS file)\n" - "\n", - __TIME__, __DATE__, argv0); - exit(1); -} - - -int main(int argc, char* argv[]) -{ - toolcontext ctx; - u8 magic[4]; - char infname[512]; - int c; - u32 ncchindex = 0; - char keysetfname[512] = "keys.xml"; - keyset tmpkeys; - unsigned int checkkeysetfile = 0; - - memset(&ctx, 0, sizeof(toolcontext)); - ctx.actions = InfoFlag | ExtractFlag; - ctx.filetype = FILETYPE_UNKNOWN; - - settings_init(&ctx.usersettings); - keyset_init(&tmpkeys, 0); - - - while (1) - { - int option_index; - static struct option long_options[] = - { - {"extract", 0, NULL, 'x'}, - {"plain", 0, NULL, 'p'}, - {"info", 0, NULL, 'i'}, - {"exefs", 1, NULL, 0}, - {"romfs", 1, NULL, 1}, - {"exheader", 1, NULL, 2}, - {"certs", 1, NULL, 3}, - {"tik", 1, NULL, 4}, - {"tmd", 1, NULL, 5}, - {"contents", 1, NULL, 6}, - {"meta", 1, NULL, 7}, - {"exefsdir", 1, NULL, 8}, - {"keyset", 1, NULL, 'k'}, - {"ncch", 1, NULL, 'n'}, - {"verbose", 0, NULL, 'v'}, - {"verify", 0, NULL, 'y'}, - {"raw", 0, NULL, 'r'}, - {"unitsize", 1, NULL, 9}, - {"showkeys", 0, NULL, 10}, - //{"commonkeyx", 1, NULL, 11}, - //{"ncchkeyxold", 1, NULL, 12}, - {"intype", 1, NULL, 't'}, - {"lzssout", 1, NULL, 13}, - {"firmdir", 1, NULL, 14}, - {"ncchsyskey", 1, NULL, 15}, - {"wav", 1, NULL, 16}, - {"romfsdir", 1, NULL, 17}, - {"listromfs", 0, NULL, 18}, - {"wavloops", 1, NULL, 19}, - {"logo", 1, NULL, 20}, - {"decompresscode", 0, NULL, 21}, - {"titlekey", 1, NULL, 22}, - {"plainrgn", 1, NULL, 23}, - {"showsyscalls", 0, NULL, 24}, - //{"ncchkeyxseven", 1, NULL, 25}, - //{"ncchkeyxninethree", 1, NULL, 26}, - //{"ncchkeyxninesix", 1, NULL, 27}, - {"seeddb", 1, NULL, 28}, - {"seed", 1, NULL, 29 }, - {NULL}, - }; - - c = getopt_long(argc, argv, "dryxivpk:n:t:", long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 'x': - ctx.actions |= ExtractFlag; - break; - - case 'v': - ctx.actions |= VerboseFlag; - break; - - case 'y': - ctx.actions |= VerifyFlag; - break; - - case 'd': - ctx.actions |= DevFlag; - break; - - case 'p': - ctx.actions |= PlainFlag; - break; - - case 'r': - ctx.actions |= RawFlag; - break; - - case 'i': - ctx.actions |= InfoFlag; - break; - - case 'n': - ncchindex = strtoul(optarg, 0, 0); - break; - - case 'k': - strncpy(keysetfname, optarg, sizeof(keysetfname)); - checkkeysetfile = 1; - break; - - case 't': - if (!strcmp(optarg, "exheader")) - ctx.filetype = FILETYPE_EXHEADER; - else if (!strcmp(optarg, "ncch")) - ctx.filetype = FILETYPE_CXI; - else if (!strcmp(optarg, "ncsd")) - ctx.filetype = FILETYPE_CCI; - else if (!strcmp(optarg, "cia")) - ctx.filetype = FILETYPE_CIA; - else if (!strcmp(optarg, "tmd")) - ctx.filetype = FILETYPE_TMD; - else if (!strcmp(optarg, "lzss")) - ctx.filetype = FILETYPE_LZSS; - else if (!strcmp(optarg, "firm")) - ctx.filetype = FILETYPE_FIRM; - else if (!strcmp(optarg, "cwav")) - ctx.filetype = FILETYPE_CWAV; - else if (!strcmp(optarg, "exefs")) - ctx.filetype = FILETYPE_EXEFS; - else if (!strcmp(optarg, "romfs")) - ctx.filetype = FILETYPE_ROMFS; - break; - - case 0: settings_set_exefs_path(&ctx.usersettings, optarg); break; - case 1: settings_set_romfs_path(&ctx.usersettings, optarg); break; - case 2: settings_set_exheader_path(&ctx.usersettings, optarg); break; - case 3: settings_set_certs_path(&ctx.usersettings, optarg); break; - case 4: settings_set_tik_path(&ctx.usersettings, optarg); break; - case 5: settings_set_tmd_path(&ctx.usersettings, optarg); break; - case 6: settings_set_content_path(&ctx.usersettings, optarg); break; - case 7: settings_set_meta_path(&ctx.usersettings, optarg); break; - case 8: settings_set_exefs_dir_path(&ctx.usersettings, optarg); break; - case 9: settings_set_mediaunit_size(&ctx.usersettings, strtoul(optarg, 0, 0)); break; - case 10: ctx.actions |= ShowKeysFlag; break; - //case 11: keyset_parse_commonkeyX(&tmpkeys, optarg, strlen(optarg)); break; - //case 12: keyset_parse_ncchkeyX_old(&tmpkeys, optarg, strlen(optarg)); break; - case 13: settings_set_lzss_path(&ctx.usersettings, optarg); break; - case 14: settings_set_firm_dir_path(&ctx.usersettings, optarg); break; - //case 15: keyset_parse_ncchfixedsystemkey(&tmpkeys, optarg, strlen(optarg)); break; - case 16: settings_set_wav_path(&ctx.usersettings, optarg); break; - case 17: settings_set_romfs_dir_path(&ctx.usersettings, optarg); break; - case 18: settings_set_list_romfs_files(&ctx.usersettings, 1); break; - case 19: settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0)); break; - case 20: settings_set_logo_path(&ctx.usersettings, optarg); break; - case 21: ctx.actions |= DecompressCodeFlag; break; - case 22: keyset_parse_titlekey(&tmpkeys, optarg, strlen(optarg)); break; - case 23: settings_set_plainrgn_path(&ctx.usersettings, optarg); break; - case 24: ctx.actions |= ShowSyscallsFlag; break; - //case 25: keyset_parse_ncchkeyX_seven(&tmpkeys, optarg, strlen(optarg)); break; - //case 26: keyset_parse_ncchkeyX_ninethree(&tmpkeys, optarg, strlen(optarg)); break; - //case 27: keyset_parse_ncchkeyX_ninesix(&tmpkeys, optarg, strlen(optarg)); break; - case 28: keyset_parse_seeddb(&tmpkeys, optarg); break; - case 29: keyset_parse_seed_fallback(&tmpkeys, optarg, strlen(optarg)); break; - - default: - usage(argv[0]); - } - } - - if (optind == argc - 1) - { - // Exactly one extra argument - an input file - strncpy(infname, argv[optind], sizeof(infname)); - } - else if ( (optind < argc) || (argc == 1) ) - { - // Too many extra args - usage(argv[0]); - } - - keyset_init(&ctx.usersettings.keys, ctx.actions); - keyset_load(&ctx.usersettings.keys, keysetfname, (ctx.actions & VerboseFlag) | checkkeysetfile); - keyset_merge(&ctx.usersettings.keys, &tmpkeys); - if (ctx.actions & ShowKeysFlag) - keyset_dump(&ctx.usersettings.keys); - - ctx.infilesize = _fsize(infname); - ctx.infile = fopen(infname, "rb"); - - if (ctx.infile == 0) - { - fprintf(stderr, "error: could not open input file!\n"); - return -1; - } - - if (ctx.filetype == FILETYPE_UNKNOWN) - { - fseeko64(ctx.infile, 0x100, SEEK_SET); - fread(&magic, 1, 4, ctx.infile); - - switch(getle32(magic)) - { - case MAGIC_NCCH: - ctx.filetype = FILETYPE_CXI; - break; - - case MAGIC_NCSD: - ctx.filetype = FILETYPE_CCI; - break; - - default: - break; - } - } - - if (ctx.filetype == FILETYPE_UNKNOWN) - { - fseeko64(ctx.infile, 0, SEEK_SET); - fread(magic, 1, 4, ctx.infile); - - switch(getle32(magic)) - { - case 0x2020: - ctx.filetype = FILETYPE_CIA; - break; - - case MAGIC_FIRM: - ctx.filetype = FILETYPE_FIRM; - break; - - case MAGIC_CWAV: - ctx.filetype = FILETYPE_CWAV; - break; - - case MAGIC_IVFC: - ctx.filetype = FILETYPE_ROMFS; // TODO: need to determine more here.. savegames use IVFC too, but is not ROMFS. - break; - } - } - - if (ctx.filetype == FILETYPE_UNKNOWN) - { - fprintf(stdout, "Unknown file\n"); - exit(1); - } - - - switch(ctx.filetype) - { - case FILETYPE_CCI: - { - ncsd_context ncsdctx; - - ncsd_init(&ncsdctx); - ncsd_set_file(&ncsdctx, ctx.infile); - ncsd_set_size(&ncsdctx, ctx.infilesize); - ncsd_set_ncch_index(&ncsdctx, ncchindex); - ncsd_set_usersettings(&ncsdctx, &ctx.usersettings); - ncsd_process(&ncsdctx, ctx.actions); - - break; - } - - case FILETYPE_FIRM: - { - firm_context firmctx; - - firm_init(&firmctx); - firm_set_file(&firmctx, ctx.infile); - firm_set_size(&firmctx, (u32) ctx.infilesize); - firm_set_usersettings(&firmctx, &ctx.usersettings); - firm_process(&firmctx, ctx.actions); - - break; - } - - case FILETYPE_CXI: - { - ncch_context ncchctx; - - ncch_init(&ncchctx); - ncch_set_file(&ncchctx, ctx.infile); - ncch_set_size(&ncchctx, ctx.infilesize); - ncch_set_usersettings(&ncchctx, &ctx.usersettings); - ncch_process(&ncchctx, ctx.actions); - - break; - } - - - case FILETYPE_CIA: - { - cia_context ciactx; - - cia_init(&ciactx); - cia_set_file(&ciactx, ctx.infile); - cia_set_size(&ciactx, ctx.infilesize); - cia_set_usersettings(&ciactx, &ctx.usersettings); - cia_process(&ciactx, ctx.actions); - - break; - } - - case FILETYPE_EXHEADER: - { - exheader_context exheaderctx; - - exheader_init(&exheaderctx); - exheader_set_file(&exheaderctx, ctx.infile); - exheader_set_size(&exheaderctx, ctx.infilesize); - settings_set_ignore_programid(&ctx.usersettings, 1); - - exheader_set_usersettings(&exheaderctx, &ctx.usersettings); - exheader_process(&exheaderctx, ctx.actions); - - break; - } - - case FILETYPE_TMD: - { - tmd_context tmdctx; - - tmd_init(&tmdctx); - tmd_set_file(&tmdctx, ctx.infile); - tmd_set_size(&tmdctx, (u32) ctx.infilesize); - tmd_set_usersettings(&tmdctx, &ctx.usersettings); - tmd_process(&tmdctx, ctx.actions); - - break; - } - - case FILETYPE_LZSS: - { - lzss_context lzssctx; - - lzss_init(&lzssctx); - lzss_set_file(&lzssctx, ctx.infile); - lzss_set_size(&lzssctx, (u32) ctx.infilesize); - lzss_set_usersettings(&lzssctx, &ctx.usersettings); - lzss_process(&lzssctx, ctx.actions); - - break; - } - - - case FILETYPE_CWAV: - { - cwav_context cwavctx; - - cwav_init(&cwavctx); - cwav_set_file(&cwavctx, ctx.infile); - cwav_set_size(&cwavctx, ctx.infilesize); - cwav_set_usersettings(&cwavctx, &ctx.usersettings); - cwav_process(&cwavctx, ctx.actions); - - break; - } - - case FILETYPE_EXEFS: - { - exefs_context exefsctx; - - exefs_init(&exefsctx); - exefs_set_file(&exefsctx, ctx.infile); - exefs_set_size(&exefsctx, ctx.infilesize); - exefs_set_usersettings(&exefsctx, &ctx.usersettings); - exefs_process(&exefsctx, ctx.actions); - - break; - } - - case FILETYPE_ROMFS: - { - romfs_context romfsctx; - - romfs_init(&romfsctx); - romfs_set_file(&romfsctx, ctx.infile); - romfs_set_size(&romfsctx, ctx.infilesize); - romfs_set_usersettings(&romfsctx, &ctx.usersettings); - romfs_set_encrypted(&romfsctx, 0); - romfs_process(&romfsctx, ctx.actions); - - break; - } - } - - if (ctx.infile) - fclose(ctx.infile); - - return 0; -} diff --git a/ctrtool/ncch.c b/ctrtool/ncch.c deleted file mode 100644 index a5516dd..0000000 --- a/ctrtool/ncch.c +++ /dev/null @@ -1,880 +0,0 @@ -#include -#include -#include -#include "types.h" -#include "ncch.h" -#include "utils.h" -#include "ctr.h" -#include "settings.h" -#include "aes_keygen.h" -#include - -static int programid_is_system(u8 programid[8]) -{ - u32 hiprogramid = getle32(programid+4); - - if ( ((hiprogramid >> 14) == 0x10) && (hiprogramid & 0x10) ) - return 1; - else - return 0; -} - - -void ncch_init(ncch_context* ctx) -{ - memset(ctx, 0, sizeof(ncch_context)); - exefs_init(&ctx->exefs); -} - -void ncch_set_usersettings(ncch_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void ncch_set_offset(ncch_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void ncch_set_size(ncch_context* ctx, u64 size) -{ - ctx->size = size; -} - -void ncch_set_file(ncch_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type) -{ - u32 version = getle16(ctx->header.version); - u32 mediaunitsize = (u32) ncch_get_mediaunit_size(ctx); - u8* titleid = ctx->header.titleid; - u32 i; - u64 x = 0; - - memset(counter, 0, 16); - - if (version == 2 || version == 0) - { - for(i=0; i<8; i++) - counter[i] = titleid[7-i]; - counter[8] = type; - } - else if (version == 1) - { - if (type == NCCHTYPE_EXHEADER) - x = 0x200; - else if (type == NCCHTYPE_EXEFS) - x = getle32(ctx->header.exefsoffset) * mediaunitsize; - else if (type == NCCHTYPE_ROMFS) - x = getle32(ctx->header.romfsoffset) * mediaunitsize; - - for(i=0; i<8; i++) - counter[i] = titleid[i]; - for(i=0; i<4; i++) - counter[12+i] = (u8) (x>>((3-i)*8)); - } -} - - -/* this is broken */ -int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags) -{ - u64 offset = 0; - u64 size = 0; - u8 counter[16]; - - - switch(type) - { - case NCCHTYPE_EXEFS: - { - offset = ncch_get_exefs_offset(ctx); - size = ncch_get_exefs_size(ctx); - ctr_init_key(&ctx->aes, ctx->key[0]); - } - break; - - case NCCHTYPE_ROMFS: - { - offset = ncch_get_romfs_offset(ctx); - size = ncch_get_romfs_size(ctx); - ctr_init_key(&ctx->aes, ctx->key[1]); - } - break; - - case NCCHTYPE_EXHEADER: - { - offset = ncch_get_exheader_offset(ctx); - size = ncch_get_exheader_size(ctx) * 2; - ctr_init_key(&ctx->aes, ctx->key[0]); - } - break; - - case NCCHTYPE_LOGO: - { - offset = ncch_get_logo_offset(ctx); - size = ncch_get_logo_size(ctx); - } - break; - - case NCCHTYPE_PLAINRGN: - { - offset = ncch_get_plainrgn_offset(ctx); - size = ncch_get_plainrgn_size(ctx); - } - break; - - default: - { - fprintf(stderr, "Error invalid NCCH type\n"); - goto clean; - } - break; - } - - ctx->extractsize = size; - ctx->extractflags = flags; - fseeko64(ctx->file, offset, SEEK_SET); - ncch_get_counter(ctx, counter, type); - - ctr_init_counter(&ctx->aes, counter); - - return 1; - -clean: - return 0; -} - -int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto) -{ - u32 read_len = buffersize; - - if (read_len > ctx->extractsize) - read_len = (u32) ctx->extractsize; - - *outsize = read_len; - - if (ctx->extractsize) - { - if (read_len != fread(buffer, 1, read_len, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - if (ctx->encrypted && !nocrypto) - ctr_crypt_counter(&ctx->aes, buffer, buffer, read_len); - - ctx->extractsize -= read_len; - } - - return 1; - -clean: - return 0; -} - -void ncch_save(ncch_context* ctx, u32 type, u32 flags) -{ - FILE* fout = 0; - filepath* path = 0; - u8 buffer[16*1024]; - exefs_header exefs_hdr; - - - if (0 == ncch_extract_prepare(ctx, type, flags)) - goto clean; - - switch(type) - { - case NCCHTYPE_EXEFS: path = settings_get_exefs_path(ctx->usersettings); break; - case NCCHTYPE_ROMFS: path = settings_get_romfs_path(ctx->usersettings); break; - case NCCHTYPE_EXHEADER: path = settings_get_exheader_path(ctx->usersettings); break; - case NCCHTYPE_LOGO: path = settings_get_logo_path(ctx->usersettings); break; - case NCCHTYPE_PLAINRGN: path = settings_get_plainrgn_path(ctx->usersettings); break; - } - - if (path == 0 || path->valid == 0) - goto clean; - - fout = fopen(path->pathname, "wb"); - if (0 == fout) - { - fprintf(stdout, "Error opening out file %s\n", path->pathname); - goto clean; - } - - switch(type) - { - case NCCHTYPE_EXEFS: fprintf(stdout, "Saving ExeFS...\n"); break; - case NCCHTYPE_ROMFS: fprintf(stdout, "Saving RomFS...\n"); break; - case NCCHTYPE_EXHEADER: fprintf(stdout, "Saving Extended Header...\n"); break; - case NCCHTYPE_LOGO: fprintf(stdout, "Saving Logo...\n"); break; - case NCCHTYPE_PLAINRGN: fprintf(stdout, "Saving Plain Region...\n"); break; - } - - // special crypto considerations for exefs when two keys are used - if (type == NCCHTYPE_EXEFS && ctx->header.flags[3] > 0 && ctx->encrypted) - { - u32 read_len; - - // read header - if (0 == ncch_extract_buffer(ctx, (u8*)&exefs_hdr, sizeof(exefs_hdr), &read_len, 0)) - goto clean; - - if (read_len != fwrite(&exefs_hdr, 1, read_len, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - - for (int i = 0; i < 8; i++) - { - - // get section size - u32 section_size = getle32(exefs_hdr.section[i].size); - u32 section_padding = align(section_size, 0x200)-section_size; - - // skip empty sections - if (section_size == 0) - continue; - - // select correct key - if (strncmp((char*)exefs_hdr.section[i].name, "icon", 8) == 0 || strncmp((char*)exefs_hdr.section[i].name, "banner", 8) == 0) - ctr_init_key(&ctx->aes, ctx->key[0]); - else - ctr_init_key(&ctx->aes, ctx->key[1]); - - // set counter - u8 ctr[16]; - ncch_get_counter(ctx, ctr, NCCHTYPE_EXEFS); - ctr_init_counter(&ctx->aes, ctr); - ctr_add_counter(&ctx->aes, (getle32(exefs_hdr.section[i].offset) + sizeof(exefs_header)) / 0x10); - - // extract data - while (section_size > 0) - { - read_len = sizeof(buffer); - if (read_len > section_size) - read_len = section_size; - - - if (read_len != fread(buffer, 1, read_len, ctx->file)) - { - fprintf(stdout, "Error reading input file\n"); - goto clean; - } - - ctr_crypt_counter(&ctx->aes, buffer, buffer, read_len); - - if (read_len != fwrite(buffer, 1, read_len, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - - - section_size -= read_len; - } - - // skip the padding - if (section_padding) - { - fseeko64(ctx->file, section_padding, SEEK_CUR); - memset(buffer, 0, section_padding); - if (section_padding != fwrite(buffer, 1, section_padding, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - - } - - ctx->extractsize -= section_size + section_padding; - } - } - else - { - while (1) - { - u32 read_len; - - if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, (type == NCCHTYPE_LOGO || type == NCCHTYPE_PLAINRGN))) - goto clean; - - if (read_len == 0) - break; - - if (read_len != fwrite(buffer, 1, read_len, fout)) - { - fprintf(stdout, "Error writing output file\n"); - goto clean; - } - } - } - -clean: - if (fout) - fclose(fout); - return; -} - -void ncch_verify(ncch_context* ctx, u32 flags) -{ - u32 mediaunitsize = (u32) ncch_get_mediaunit_size(ctx); - u32 exefshashregionsize = getle32(ctx->header.exefshashregionsize) * mediaunitsize; - u32 romfshashregionsize = getle32(ctx->header.romfshashregionsize) * mediaunitsize; - u32 exheaderhashregionsize = getle32(ctx->header.extendedheadersize); - u32 logohashregionsize = getle32(ctx->header.logosize) * mediaunitsize; - u8* exefshashregion = 0; - u8* romfshashregion = 0; - u8* exheaderhashregion = 0; - u8* logohashregion = 0; - u8* tmphash = 0; - rsakey2048 ncchrsakey; - - if (exefshashregionsize >= SIZE_128MB || romfshashregionsize >= SIZE_128MB || exheaderhashregionsize >= SIZE_128MB || logohashregionsize >= SIZE_128MB) - goto clean; - - exefshashregion = malloc(exefshashregionsize); - romfshashregion = malloc(romfshashregionsize); - exheaderhashregion = malloc(exheaderhashregionsize); - logohashregion = malloc(logohashregionsize); - - - if (ctx->usersettings) - { - if ( (ctx->header.flags[5] & 3) == 1) - ctx->headersigcheck = ncch_signature_verify(ctx, &ctx->usersettings->keys.ncchrsakey); - else - { - ctr_rsa_init_key_pubmodulus(&ncchrsakey, ctx->exheader.header.accessdesc.ncchpubkeymodulus); - ctx->headersigcheck = ncch_signature_verify(ctx, &ncchrsakey); - } - } - - if (exefshashregionsize) - { - if (0 == ncch_extract_prepare(ctx, NCCHTYPE_EXEFS, flags)) - goto clean; - if (0 == ncch_extract_buffer(ctx, exefshashregion, exefshashregionsize, &exefshashregionsize,0)) - goto clean; - ctx->exefshashcheck = ctr_sha_256_verify(exefshashregion, exefshashregionsize, ctx->header.exefssuperblockhash); - } - if (romfshashregionsize) - { - if (0 == ncch_extract_prepare(ctx, NCCHTYPE_ROMFS, flags)) - goto clean; - if (0 == ncch_extract_buffer(ctx, romfshashregion, romfshashregionsize, &romfshashregionsize,0)) - goto clean; - ctx->romfshashcheck = ctr_sha_256_verify(romfshashregion, romfshashregionsize, ctx->header.romfssuperblockhash); - } - if (exheaderhashregionsize) - { - if (0 == ncch_extract_prepare(ctx, NCCHTYPE_EXHEADER, flags)) - goto clean; - if (0 == ncch_extract_buffer(ctx, exheaderhashregion, exheaderhashregionsize, &exheaderhashregionsize,0)) - goto clean; - ctx->exheaderhashcheck = ctr_sha_256_verify(exheaderhashregion, exheaderhashregionsize, ctx->header.extendedheaderhash); - } - if (logohashregionsize) - { - if (0 == ncch_extract_prepare(ctx, NCCHTYPE_LOGO, flags)) - goto clean; - if (0 == ncch_extract_buffer(ctx, logohashregion, logohashregionsize, &logohashregionsize,1)) - goto clean; - ctx->logohashcheck = ctr_sha_256_verify(logohashregion, logohashregionsize, ctx->header.logohash); - } - - - free(exefshashregion); - free(romfshashregion); - free(exheaderhashregion); - free(logohashregion); -clean: - return; -} - - -void ncch_process(ncch_context* ctx, u32 actions) -{ - u8 exheadercounter[16]; - u8 exefscounter[16]; - u8 romfscounter[16]; - int result = 1; - - - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, 0x200, ctx->file); - - if (getle32(ctx->header.magic) != MAGIC_NCCH) - { - fprintf(stdout, "Error, NCCH segment corrupted\n"); - return; - } - - const u32 exheaderSize = getle32(ctx->header.extendedheadersize); - if (exheaderSize != 0x400 && exheaderSize != 0) - { - fprintf(stdout, "Error, exheader is 0x%02x bytes long, expected 0x400 or 0\n", getle32(ctx->header.extendedheadersize)); - return; - } - - ncch_determine_key(ctx, actions); - - ncch_get_counter(ctx, exheadercounter, NCCHTYPE_EXHEADER); - ncch_get_counter(ctx, exefscounter, NCCHTYPE_EXEFS); - ncch_get_counter(ctx, romfscounter, NCCHTYPE_ROMFS); - - if (actions & ShowKeysFlag) - { - fprintf(stdout, "Counter(s):\n"); - memdump(stdout, " exheader: ", exheadercounter, 0x10); - memdump(stdout, " ExeFS: ", exefscounter, 0x10); - memdump(stdout, " RomFS: ", romfscounter, 0x10); - } - - - exheader_set_file(&ctx->exheader, ctx->file); - exheader_set_offset(&ctx->exheader, ncch_get_exheader_offset(ctx) ); - exheader_set_size(&ctx->exheader, ncch_get_exheader_size(ctx) ); - exheader_set_usersettings(&ctx->exheader, ctx->usersettings); - exheader_set_titleid(&ctx->exheader, ctx->header.titleid); - exheader_set_programid(&ctx->exheader, ctx->header.programid); - exheader_set_hash(&ctx->exheader, ctx->header.extendedheaderhash); - exheader_set_counter(&ctx->exheader, exheadercounter); - exheader_set_key(&ctx->exheader, ctx->key[0]); - exheader_set_encrypted(&ctx->exheader, ctx->encrypted); - - exefs_set_file(&ctx->exefs, ctx->file); - exefs_set_offset(&ctx->exefs, ncch_get_exefs_offset(ctx) ); - exefs_set_size(&ctx->exefs, ncch_get_exefs_size(ctx) ); - exefs_set_titleid(&ctx->exefs, ctx->header.titleid); - exefs_set_usersettings(&ctx->exefs, ctx->usersettings); - exefs_set_counter(&ctx->exefs, exefscounter); - exefs_set_keys(&ctx->exefs, ctx->key[0], ctx->key[1]); - exefs_set_encrypted(&ctx->exefs, ctx->encrypted); - - romfs_set_file(&ctx->romfs, ctx->file); - romfs_set_offset(&ctx->romfs, ncch_get_romfs_offset(ctx)); - romfs_set_size(&ctx->romfs, ncch_get_romfs_size(ctx)); - romfs_set_usersettings(&ctx->romfs, ctx->usersettings); - romfs_set_counter(&ctx->romfs, romfscounter); - romfs_set_key(&ctx->romfs, ctx->key[1]); - romfs_set_encrypted(&ctx->romfs, ctx->encrypted); - - exheader_read(&ctx->exheader, actions); - - - if (actions & VerifyFlag) - ncch_verify(ctx, actions); - - if (actions & InfoFlag) - ncch_print(ctx); - - if (ctx->encrypted == NCCHCRYPTO_BROKEN) - { - fprintf(stderr, "Error, NCCH encryption broken.\n"); - return; - } - - if ((actions & ShowKeysFlag) && ctx->encrypted) - { - fprintf(stdout, "Using key(s):\n"); - if (ctx->encrypted == NCCHCRYPTO_FIXED) - { - memdump(stdout, " Key: ", ctx->key[0], 0x10); - } - else - { - memdump(stdout, " 0x2C: ", ctx->key[0], 0x10); - if (memcmp(ctx->key[0], ctx->key[1], 0x10) != 0) - { - fprintf(stdout, " special (%02x): ", ctx->header.flags[3]); - memdump(stdout, "", ctx->key[1], 0x10); - } - } - } - - if (actions & ExtractFlag) - { - ncch_save(ctx, NCCHTYPE_EXEFS, actions); - ncch_save(ctx, NCCHTYPE_ROMFS, actions); - ncch_save(ctx, NCCHTYPE_EXHEADER, actions); - ncch_save(ctx, NCCHTYPE_LOGO, actions); - ncch_save(ctx, NCCHTYPE_PLAINRGN, actions); - } - - - if (result && ncch_get_exheader_size(ctx)) - { - if (!exheader_hash_valid(&ctx->exheader)) - return; - - result = exheader_process(&ctx->exheader, actions); - } - - if (result && ncch_get_exefs_size(ctx)) - { - if(ncch_get_exheader_size(ctx)) - exefs_set_compressedflag(&ctx->exefs, exheader_get_compressedflag(&ctx->exheader)); - exefs_process(&ctx->exefs, actions); - } - - if (result && ncch_get_romfs_size(ctx)) - { - romfs_process(&ctx->romfs, actions); - } -} - -int ncch_signature_verify(ncch_context* ctx, rsakey2048* key) -{ - u8 hash[0x20]; - - ctr_sha_256(ctx->header.magic, 0x100, hash); - return ctr_rsa_verify_hash(ctx->header.signature, hash, key); -} - - -u64 ncch_get_exefs_offset(ncch_context* ctx) -{ - return ctx->offset + getle32(ctx->header.exefsoffset) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_exefs_size(ncch_context* ctx) -{ - return getle32(ctx->header.exefssize) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_romfs_offset(ncch_context* ctx) -{ - return ctx->offset + getle32(ctx->header.romfsoffset) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_romfs_size(ncch_context* ctx) -{ - return getle32(ctx->header.romfssize) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_exheader_offset(ncch_context* ctx) -{ - return ctx->offset + 0x200; -} - -u64 ncch_get_exheader_size(ncch_context* ctx) -{ - return getle32(ctx->header.extendedheadersize); -} - -u64 ncch_get_logo_offset(ncch_context* ctx) -{ - return ctx->offset + getle32(ctx->header.logooffset) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_logo_size(ncch_context* ctx) -{ - return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_plainrgn_offset(ncch_context* ctx) -{ - return ctx->offset + getle32(ctx->header.plainregionoffset) * ncch_get_mediaunit_size(ctx); -} - -u64 ncch_get_plainrgn_size(ncch_context* ctx) -{ - return getle32(ctx->header.plainregionsize) * ncch_get_mediaunit_size(ctx); -} - - -u64 ncch_get_mediaunit_size(ncch_context* ctx) -{ - unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings); - - if (mediaunitsize == 0) - { - unsigned short version = getle16(ctx->header.version); - if (version == 1) - mediaunitsize = 1; - else if (version == 2 || version == 0) - mediaunitsize = 1 << (ctx->header.flags[6] + 9); - } - - return mediaunitsize; -} - - -void ncch_determine_key(ncch_context* ctx, u32 actions) -{ - u8 exheader_buffer[0x400]; - u8 seedbuf[0x20]; - u8* seed; - u8* keyX = NULL; - u8 hash[0x20] = {0}; - ctr_ncchheader* header = &ctx->header; - const u32 exheaderSize = getle32(header->extendedheadersize); - struct sNcchKeyslot - { - u8 x[0x10]; - u8 y[0x10]; - u8 key[0x10]; - } key[2]; - - - // Check if the NCCH is already decrypted, by checking if the exheader hash matches - // Otherwise, use determination rules - fseeko64(ctx->file, ncch_get_exheader_offset(ctx), SEEK_SET); - memset(exheader_buffer, 0, exheaderSize); - fread(exheader_buffer, 1, exheaderSize, ctx->file); - ctr_sha_256(exheader_buffer, exheaderSize, hash); - if (!memcmp(hash, header->extendedheaderhash, 32)) - { - // exheader hash matches, so probably decrypted - ctx->encrypted = NCCHCRYPTO_NONE; - if (!(header->flags[7] & 4)) - fprintf(stderr, "Warning, exheader is decrypted but the NCCH says it isn't.\n" - "This NCCH will likely break on console.\n"); - return; - } - - // if not plain flag set and not ncch unencrypted flag set - // determine the keys - if (!(actions & PlainFlag) && !(header->flags[7] & 4)) - { - // fixed key crypto - if (header->flags[7] & 1) - { - ctx->encrypted = NCCHCRYPTO_FIXED; - if (programid_is_system(header->programid)) - { - if (settings_get_ncch_fixedsystemkey(ctx->usersettings) == NULL) - { - fprintf(stderr, "Error, could not read system fixed key.\n"); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - memcpy(key[0].key, settings_get_ncch_fixedsystemkey(ctx->usersettings), 0x10); - } - else - { - memset(key[0].key, 0x00, 0x10); - } - - memcpy(key[1].key, key[0].key, 0x10); - } - // secure crypto - else - { - ctx->encrypted = NCCHCRYPTO_SECURE; - if (settings_get_ncchkeyX_old(ctx->usersettings) == NULL) - { - fprintf(stderr, "Error, could not read NCCH base keyX.\n"); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - // setup regular keyslot seeds (exheader, exefs:icon|banner) - memcpy(key[0].x, settings_get_ncchkeyX_old(ctx->usersettings), 0x10); - memcpy(key[0].y, header->signature, 0x10); - - // setup second keyslot seed (romfs, exefs:!(icon|banner)) - // - get keyX - - switch (header->flags[3]) - { - case(0): - keyX = settings_get_ncchkeyX_old(ctx->usersettings); - break; - case(1): - keyX = settings_get_ncchkeyX_seven(ctx->usersettings); - break; - case(10): - keyX = settings_get_ncchkeyX_ninethree(ctx->usersettings); - break; - case(11): - keyX = settings_get_ncchkeyX_ninesix(ctx->usersettings); - break; - default: - fprintf(stderr, "Warning, unknown NCCH crypto method.\n"); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - if (keyX == NULL) - { - fprintf(stderr, "Error, could not read NCCH keyX.\n"); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - memcpy(key[1].x, keyX, 0x10); - - // - get keyY - if (header->flags[7] & 0x20) - { - seed = settings_get_seed(ctx->usersettings, getle64(header->programid)); - if (!seed) - { - fprintf(stderr, "This title uses seed crypto, but no seed is set, unable to decrypt.\n" - "Use -p to avoid decryption or use --seeddb=dbfile or --seed=SEEDHERE.\n"); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - memcpy(seedbuf, seed, 0x10); - // Assumes running on little endian - memcpy(seedbuf + 0x10, header->programid, sizeof(header->programid)); - ctr_sha_256(seedbuf, 0x18, hash); - if (memcmp(hash, header->seedcheck, sizeof(header->seedcheck))) { - fprintf(stderr, "Seed check mismatch. (Got: %02x%02x%02x%02x, expected: %02x%02x%02x%02x)\n", - hash[0], hash[1], hash[2], hash[3], - header->seedcheck[0], header->seedcheck[1], header->seedcheck[2], header->seedcheck[3]); - ctx->encrypted = NCCHCRYPTO_BROKEN; - return; - } - - memcpy(seedbuf, header->signature, 0x10); - memcpy(seedbuf + 0x10, seed, 0x10); - ctr_sha_256(seedbuf, 0x20, hash); - memcpy(key[1].y, hash, 0x10); - } - else - { - memcpy(key[1].y, key[0].y, 0x10); - } - - - // generate keys - ctr_aes_keygen(key[0].x, key[0].y, key[0].key); - ctr_aes_keygen(key[1].x, key[1].y, key[1].key); - } - - // save keys - memcpy(ctx->key[0], key[0].key, 0x10); - memcpy(ctx->key[1], key[1].key, 0x10); - } - else - { - ctx->encrypted = NCCHCRYPTO_NONE; - } -} - -static const char* formtypetostring(unsigned char flags) -{ - unsigned char formtype = flags & 3; - - switch(formtype) - { - case 0: return "Not assigned"; - case 1: return "Simple content"; - case 2: return "Executable content without RomFS"; - case 3: return "Executable content"; - default: return "Unknown"; - } -} - -static const char* contenttypetostring(unsigned char flags) -{ - unsigned char contenttype = flags>>2; - - switch(contenttype) - { - case 0: return "Application"; - case 1: return "System Update"; - case 2: return "Manual"; - case 3: return "Child"; - case 4: return "Trial"; - case 5: return "Extended System Update"; - default: return "Unknown"; - } -} - -static const char* contentplatformtostring(unsigned char platform) -{ - switch (platform) - { - case 1: return "CTR"; - case 2: return "SNAKE"; - default: return "Unknown"; - } -} - - - -void ncch_print(ncch_context* ctx) -{ - ctr_ncchheader *header = &ctx->header; - u64 offset = ctx->offset; - u64 mediaunitsize = ncch_get_mediaunit_size(ctx); - - fprintf(stdout, "\nNCCH:\n"); - - fprintf(stdout, "Header: %.4s\n", header->magic); - if (ctx->headersigcheck == Unchecked) - memdump(stdout, "Signature: ", header->signature, 0x100); - else if (ctx->headersigcheck == Good) - memdump(stdout, "Signature (GOOD): ", header->signature, 0x100); - else - memdump(stdout, "Signature (FAIL): ", header->signature, 0x100); - fprintf(stdout, "Content size: 0x%08"PRIx64"\n", getle32(header->contentsize)*mediaunitsize); - fprintf(stdout, "Title id: %016"PRIx64"\n", getle64(header->titleid)); - fprintf(stdout, "Maker code: %.2s\n", header->makercode); - fprintf(stdout, "Version: %d\n", getle16(header->version)); - fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck)); - fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid)); - if(ctx->logohashcheck == Unchecked) - memdump(stdout, "Logo hash: ", header->logohash, 0x20); - else if(ctx->logohashcheck == Good) - memdump(stdout, "Logo hash (GOOD): ", header->logohash, 0x20); - else - memdump(stdout, "Logo hash (FAIL): ", header->logohash, 0x20); - fprintf(stdout, "Product code: %.16s\n", header->productcode); - fprintf(stdout, "Exheader size: 0x%x\n", getle32(header->extendedheadersize)); - if (ctx->exheaderhashcheck == Unchecked) - memdump(stdout, "Exheader hash: ", header->extendedheaderhash, 0x20); - else if (ctx->exheaderhashcheck == Good) - memdump(stdout, "Exheader hash (GOOD): ", header->extendedheaderhash, 0x20); - else - memdump(stdout, "Exheader hash (FAIL): ", header->extendedheaderhash, 0x20); - fprintf(stdout, "Flags: %016"PRIx64"\n", getle64(header->flags)); - fprintf(stdout, " > Mediaunit size: 0x%x\n", (u32)mediaunitsize); - if (header->flags[7] & 4) - fprintf(stdout, " > Crypto key: None\n"); - else if (header->flags[7] & 1) - fprintf(stdout, " > Crypto key: %s\n", programid_is_system(header->programid)? "Fixed":"Zeros"); - else - fprintf(stdout, " > Crypto key: Secure (%d)%s\n", header->flags[3], header->flags[7] & 32? " (KeyY seeded)" : ""); - fprintf(stdout, " > Form type: %s\n", formtypetostring(header->flags[5])); - fprintf(stdout, " > Content type: %s\n", contenttypetostring(header->flags[5])); - fprintf(stdout, " > Content platform: %s\n", contentplatformtostring(header->flags[4])); - if (header->flags[7] & 2) - fprintf(stdout, " > No RomFS mount\n"); - - - fprintf(stdout, "Plain region offset: 0x%08"PRIx64"\n", getle32(header->plainregionsize)? offset+getle32(header->plainregionoffset)*mediaunitsize : 0); - fprintf(stdout, "Plain region size: 0x%08"PRIx64"\n", getle32(header->plainregionsize)*mediaunitsize); - fprintf(stdout, "Logo offset: 0x%08"PRIx64"\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0); - fprintf(stdout, "Logo size: 0x%08"PRIx64"\n", getle32(header->logosize)*mediaunitsize); - fprintf(stdout, "ExeFS offset: 0x%08"PRIx64"\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0); - fprintf(stdout, "ExeFS size: 0x%08"PRIx64"\n", getle32(header->exefssize)*mediaunitsize); - fprintf(stdout, "ExeFS hash region size: 0x%08"PRIx64"\n", getle32(header->exefshashregionsize)*mediaunitsize); - fprintf(stdout, "RomFS offset: 0x%08"PRIx64"\n", getle32(header->romfssize)? offset+getle32(header->romfsoffset)*mediaunitsize : 0); - fprintf(stdout, "RomFS size: 0x%08"PRIx64"\n", getle32(header->romfssize)*mediaunitsize); - fprintf(stdout, "RomFS hash region size: 0x%08"PRIx64"\n", getle32(header->romfshashregionsize)*mediaunitsize); - if (ctx->exefshashcheck == Unchecked) - memdump(stdout, "ExeFS Hash: ", header->exefssuperblockhash, 0x20); - else if (ctx->exefshashcheck == Good) - memdump(stdout, "ExeFS Hash (GOOD): ", header->exefssuperblockhash, 0x20); - else - memdump(stdout, "ExeFS Hash (FAIL): ", header->exefssuperblockhash, 0x20); - if (ctx->romfshashcheck == Unchecked) - memdump(stdout, "RomFS Hash: ", header->romfssuperblockhash, 0x20); - else if (ctx->romfshashcheck == Good) - memdump(stdout, "RomFS Hash (GOOD): ", header->romfssuperblockhash, 0x20); - else - memdump(stdout, "RomFS Hash (FAIL): ", header->romfssuperblockhash, 0x20); -} diff --git a/ctrtool/ncch.h b/ctrtool/ncch.h deleted file mode 100644 index 94d2968..0000000 --- a/ctrtool/ncch.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef _NCCH_H_ -#define _NCCH_H_ - -#include -#include "types.h" -#include "keyset.h" -#include "filepath.h" -#include "ctr.h" -#include "exefs.h" -#include "romfs.h" -#include "exheader.h" -#include "settings.h" - -typedef enum -{ - NCCHTYPE_EXHEADER = 1, - NCCHTYPE_EXEFS = 2, - NCCHTYPE_ROMFS = 3, - NCCHTYPE_LOGO = 4, - NCCHTYPE_PLAINRGN = 5, -} ctr_ncchtypes; - -typedef enum -{ - NCCHCRYPTO_NONE = 0, //< already decrypted - NCCHCRYPTO_FIXED = 1, //< fixed key crypto, used for SDK-made application titles and very very old system titles - NCCHCRYPTO_SECURE = (1<<1), //< hardware generated key - NCCHCRYPTO_BROKEN = 0xFF //< Internal: failed to generate key, but encryption still used -} ctr_ncchcryptotype; - -typedef struct -{ - u8 signature[0x100]; - u8 magic[4]; - u8 contentsize[4]; - u8 titleid[8]; - u8 makercode[2]; - u8 version[2]; - u8 seedcheck[4]; - u8 programid[8]; - u8 reserved1[0x10]; - u8 logohash[0x20]; - u8 productcode[0x10]; - u8 extendedheaderhash[0x20]; - u8 extendedheadersize[4]; - u8 reserved2[4]; - u8 flags[8]; - u8 plainregionoffset[4]; - u8 plainregionsize[4]; - u8 logooffset[4]; - u8 logosize[4]; - u8 exefsoffset[4]; - u8 exefssize[4]; - u8 exefshashregionsize[4]; - u8 reserved4[4]; - u8 romfsoffset[4]; - u8 romfssize[4]; - u8 romfshashregionsize[4]; - u8 reserved5[4]; - u8 exefssuperblockhash[0x20]; - u8 romfssuperblockhash[0x20]; -} ctr_ncchheader; - - -typedef struct -{ - FILE* file; - u8 key[2][16]; - u8 seed[16]; - u32 encrypted; - u64 offset; - u64 size; - settings* usersettings; - ctr_ncchheader header; - ctr_aes_context aes; - exefs_context exefs; - romfs_context romfs; - exheader_context exheader; - int exefshashcheck; - int romfshashcheck; - int exheaderhashcheck; - int logohashcheck; - int headersigcheck; - u64 extractsize; - u32 extractflags; -} ncch_context; - -void ncch_init(ncch_context* ctx); -void ncch_process(ncch_context* ctx, u32 actions); -void ncch_set_offset(ncch_context* ctx, u64 offset); -void ncch_set_size(ncch_context* ctx, u64 size); -void ncch_set_file(ncch_context* ctx, FILE* file); -void ncch_set_usersettings(ncch_context* ctx, settings* usersettings); -u64 ncch_get_exefs_offset(ncch_context* ctx); -u64 ncch_get_exefs_size(ncch_context* ctx); -u64 ncch_get_romfs_offset(ncch_context* ctx); -u64 ncch_get_romfs_size(ncch_context* ctx); -u64 ncch_get_exheader_offset(ncch_context* ctx); -u64 ncch_get_exheader_size(ncch_context* ctx); -u64 ncch_get_logo_offset(ncch_context* ctx); -u64 ncch_get_logo_size(ncch_context* ctx); -u64 ncch_get_plainrgn_offset(ncch_context* ctx); -u64 ncch_get_plainrgn_size(ncch_context* ctx); -void ncch_print(ncch_context* ctx); -int ncch_signature_verify(ncch_context* ctx, rsakey2048* key); -void ncch_verify(ncch_context* ctx, u32 flags); -void ncch_save(ncch_context* ctx, u32 type, u32 flags); -int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags); -int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto); -u64 ncch_get_mediaunit_size(ncch_context* ctx); -void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type); -void ncch_determine_key(ncch_context* ctx, u32 actions); -#endif // _NCCH_H_ diff --git a/ctrtool/ncsd.c b/ctrtool/ncsd.c deleted file mode 100644 index ab9fae8..0000000 --- a/ctrtool/ncsd.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include - -#include "types.h" -#include "ncsd.h" -#include "utils.h" -#include "ctr.h" -#include - - -void ncsd_init(ncsd_context* ctx) -{ - memset(ctx, 0, sizeof(ncsd_context)); -} - -void ncsd_set_offset(ncsd_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void ncsd_set_file(ncsd_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void ncsd_set_size(ncsd_context* ctx, u64 size) -{ - ctx->size = size; -} - -void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index) -{ - ctx->ncch_index = ncch_index; -} - -void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -int ncsd_signature_verify(const void* blob, rsakey2048* key) -{ - u8* message = (u8*)blob + 0x100; - u8* sig = (u8*)blob; - u8 hash[0x20]; - - ctr_sha_256(message, 0x100, hash); - return ctr_rsa_verify_hash(sig, hash, key); -} - -u64 ncsd_get_mediaunit_size(ncsd_context* ctx) -{ - unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings); - - if (mediaunitsize == 0) - mediaunitsize = 1<<(9+ctx->header.flags[6]); - - return mediaunitsize; -} - -void ncsd_process(ncsd_context* ctx, u32 actions) -{ - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(&ctx->header, 1, 0x200, ctx->file); - - if (getle32(ctx->header.magic) != MAGIC_NCSD) - { - fprintf(stdout, "Error, NCSD segment corrupted\n"); - return; - } - - - if (actions & VerifyFlag) - { - if (ctx->usersettings) - ctx->headersigcheck = ncsd_signature_verify(&ctx->header, &ctx->usersettings->keys.ncsdrsakey); - } - - if (actions & InfoFlag) - ncsd_print(ctx); - - if(ctx->ncch_index > 7 || ctx->header.partitiongeometry[ctx->ncch_index].size == 0) - { - fprintf(stderr," ERROR NCSD partition %d, does not exist\n",ctx->ncch_index); - return; - } - - ncch_set_file(&ctx->ncch, ctx->file); - ncch_set_offset(&ctx->ncch, ctx->header.partitiongeometry[ctx->ncch_index].offset * ncsd_get_mediaunit_size(ctx)); - ncch_set_size(&ctx->ncch, ctx->header.partitiongeometry[ctx->ncch_index].size * ncsd_get_mediaunit_size(ctx)); - ncch_set_usersettings(&ctx->ncch, ctx->usersettings); - ncch_process(&ctx->ncch, actions); -} - -const char* ncsd_print_mediatype(u8 type) -{ - switch(type) - { - case 0 : return "Internal Device"; - case 1 : return "Card1"; - case 2 : return "Card2"; - case 3 : return "Extended Device"; - default: return "Unknown"; - } -} - -const char* ncsd_print_carddevice(u8 type) -{ - switch(type) - { - case 1 : return "NorFlash"; - case 2 : return "None"; - case 3 : return "BT"; - default: return "Unknown"; - } -} - -void ncsd_print(ncsd_context* ctx) -{ - char magic[5]; - ctr_ncsdheader* header = &ctx->header; - unsigned int i; - unsigned int mediaunitsize = (unsigned int) ncsd_get_mediaunit_size(ctx); - - - memcpy(magic, header->magic, 4); - magic[4] = 0; - - fprintf(stdout, "Header: %s\n", magic); - if (ctx->headersigcheck == Unchecked) - memdump(stdout, "Signature: ", header->signature, 0x100); - else if (ctx->headersigcheck == Good) - memdump(stdout, "Signature (GOOD): ", header->signature, 0x100); - else - memdump(stdout, "Signature (FAIL): ", header->signature, 0x100); - fprintf(stdout, "Media size: 0x%08x\n", getle32(header->mediasize)); - fprintf(stdout, "Media id: %016"PRIx64"\n", getle64(header->mediaid)); - //memdump(stdout, "Partition FS type: ", header->partitionfstype, 8); - //memdump(stdout, "Partition crypt type: ", header->partitioncrypttype, 8); - //memdump(stdout, "Partition offset/size: ", header->partitionoffsetandsize, 0x40); - fprintf(stdout, "\n"); - for(i=0; i<8; i++) - { - u32 partitionoffset = header->partitiongeometry[i].offset * mediaunitsize; - u32 partitionsize = header->partitiongeometry[i].size * mediaunitsize; - - if (partitionsize != 0) - { - fprintf(stdout, "Partition %d \n", i); - memdump(stdout, " Id: ", header->titleid+i*8, 8); - fprintf(stdout, " Area: 0x%08X-0x%08X\n", partitionoffset, partitionoffset+partitionsize); - fprintf(stdout, " Filesystem: %02X\n", header->partitionfstype[i]); - fprintf(stdout, " Encryption: %02X\n", header->partitioncrypttype[i]); - fprintf(stdout, "\n"); - } - } - memdump(stdout, "Extended header hash: ", header->extendedheaderhash, 0x20); - memdump(stdout, "Additional header size: ", header->additionalheadersize, 4); - memdump(stdout, "Sector zero offset: ", header->sectorzerooffset, 4); - memdump(stdout, "Flags: ", header->flags, 8); - fprintf(stdout, " > Mediaunit size: 0x%X\n", mediaunitsize); - fprintf(stdout, " > Mediatype: %s\n", ncsd_print_mediatype(header->flags[5])); - fprintf(stdout, " > Card Device: %s\n", ncsd_print_carddevice(header->flags[3] | header->flags[7])); - -} diff --git a/ctrtool/ncsd.h b/ctrtool/ncsd.h deleted file mode 100644 index 2d6ee53..0000000 --- a/ctrtool/ncsd.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _NCSD_H_ -#define _NCSD_H_ - -#include "types.h" -#include "keyset.h" -#include "settings.h" -#include "ncch.h" - -typedef struct -{ - u32 offset; - u32 size; -} ncsd_partition_geometry; - -typedef struct -{ - u8 signature[0x100]; - u8 magic[4]; - u8 mediasize[4]; - u8 mediaid[8]; - u8 partitionfstype[8]; - u8 partitioncrypttype[8]; - ncsd_partition_geometry partitiongeometry[8]; - u8 extendedheaderhash[0x20]; - u8 additionalheadersize[4]; - u8 sectorzerooffset[4]; - u8 flags[8]; - u8 titleid[0x40]; - u8 reserved[0x30]; -} ctr_ncsdheader; - - -typedef struct -{ - FILE* file; - u64 offset; - u64 size; - u32 ncch_index; - ctr_ncsdheader header; - settings* usersettings; - int headersigcheck; - ncch_context ncch; -} ncsd_context; - - -void ncsd_init(ncsd_context* ctx); -void ncsd_set_offset(ncsd_context* ctx, u64 offset); -void ncsd_set_size(ncsd_context* ctx, u64 size); -void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index); -void ncsd_set_file(ncsd_context* ctx, FILE* file); -void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings); -int ncsd_signature_verify(const void* blob, rsakey2048* key); -void ncsd_process(ncsd_context* ctx, u32 actions); -void ncsd_print(ncsd_context* ctx); -u64 ncsd_get_mediaunit_size(ncsd_context* ctx); - -#endif // _NCSD_H_ diff --git a/ctrtool/oschar.c b/ctrtool/oschar.c deleted file mode 100644 index ac8ddcc..0000000 --- a/ctrtool/oschar.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#ifndef _WIN32 -#ifndef __CYGWIN__ -#define LIBICONV_PLUG -#endif -#include -#endif -#include "oschar.h" - -int os_fstat(const oschar_t *path) -{ - struct _osstat st; - return os_stat(path, &st); -} - -uint64_t os_fsize(const oschar_t *path) -{ - struct _osstat st; - if (os_stat(path, &st) != 0) - return 0; - else - return st.st_size; -} - -int os_makedir(const oschar_t *dir) -{ -#ifdef _WIN32 - return _wmkdir(dir); -#else - return mkdir(dir, 0777); -#endif -} - -uint32_t utf16_strlen(const utf16char_t *str) -{ - uint32_t i; - for (i = 0; str[i] != 0x0; i++); - return i; -} - -void utf16_fputs(const utf16char_t *str, FILE *out) -{ - oschar_t *_str = os_CopyConvertUTF16Str(str); - os_fputs(_str, out); - free(_str); -} - -char* strcopy_8to8(const char *src) -{ - uint32_t src_len; - char *dst; - - if (!src) - return NULL; - - src_len = strlen(src); - - // Allocate memory for expanded string - dst = calloc(src_len + 1, sizeof(char)); - if (!dst) - return NULL; - - // Copy elements from src into dst - strncpy(dst, src, src_len); - - return dst; -} - -utf16char_t* strcopy_8to16(const char *src) -{ - uint32_t src_len, i; - utf16char_t *dst; - - if (!src) - return NULL; - - src_len = strlen(src); - - // Allocate memory for expanded string - dst = calloc(src_len + 1, sizeof(utf16char_t)); - if (!dst) - return NULL; - - // Copy elements from src into dst - for (i = 0; i < src_len; i++) - dst[i] = src[i]; - - return dst; -} - - -utf16char_t* strcopy_16to16(const utf16char_t *src) -{ - uint32_t src_len, i; - utf16char_t *dst; - - if (!src) - return NULL; - - src_len = utf16_strlen(src); - - // Allocate memory for expanded string - dst = calloc(src_len + 1, sizeof(utf16char_t)); - if (!dst) - return NULL; - - // Copy elements from src into dst - for (i = 0; i < src_len; i++) - dst[i] = src[i]; - - return dst; -} - -#ifndef _WIN32 -utf16char_t* strcopy_UTF8toUTF16(const char *src) -{ - uint32_t src_len, dst_len; - size_t in_bytes, out_bytes; - utf16char_t *dst; - char *in, *out; - - if (!src) - return NULL; - - src_len = strlen(src); - dst_len = src_len + 1; - - // Allocate memory for string - dst = calloc(dst_len, sizeof(utf16char_t)); - if (!dst) - return NULL; - - in = (char*)src; - out = (char*)dst; - in_bytes = src_len*sizeof(char); - out_bytes = dst_len*sizeof(utf16char_t); - - iconv_t cd = iconv_open("UTF-16LE", "UTF-8"); - iconv(cd, &in, &in_bytes, &out, &out_bytes); - iconv_close(cd); - return dst; -} - -char* strcopy_UTF16toUTF8(const utf16char_t *src) -{ - uint32_t src_len, dst_len; - size_t in_bytes, out_bytes; - char *dst; - char *in, *out; - - if (!src) - return NULL; - - src_len = utf16_strlen(src); - // UTF-8 can use up to 3 bytes per UTF-16 code unit, or four for a surrogate pair - dst_len = src_len * 3; - - // Allocate memory for string - dst = calloc(dst_len, sizeof(char)); - if (!dst) - return NULL; - - in = (char*)src; - out = (char*)dst; - in_bytes = src_len*sizeof(uint16_t); - out_bytes = dst_len*sizeof(char); - - iconv_t cd = iconv_open("UTF-8", "UTF-16LE"); - iconv(cd, &in, &in_bytes, &out, &out_bytes); - iconv_close(cd); - return dst; -} -#endif - -oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add) -{ - uint32_t len; - oschar_t *new_path; - - len = os_strlen(src) + os_strlen(add) + 0x10; - new_path = calloc(len, sizeof(oschar_t)); - -#ifdef _WIN32 - _snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, add); -#else - snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, add); -#endif - - return new_path; -} - -oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add) -{ - uint32_t len; - oschar_t *new_path, *_add; - - _add = os_CopyConvertUTF16Str(add); - - len = os_strlen(src) + os_strlen(_add) + 0x10; - new_path = calloc(len, sizeof(oschar_t)); - -#ifdef _WIN32 - _snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, _add); -#else - snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, _add); -#endif - - free(_add); - return new_path; -} diff --git a/ctrtool/oschar.h b/ctrtool/oschar.h deleted file mode 100644 index 9c788b0..0000000 --- a/ctrtool/oschar.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once -#include -#include -#include -#include -#ifdef _WIN32 -#include -#endif - -// Nintendo uses UTF16-LE chars for extended ASCII support -typedef uint16_t utf16char_t; - -// Native OS char type for unicode support -#ifdef _WIN32 -typedef wchar_t oschar_t; // UTF16-LE -#else -typedef char oschar_t; // UTF8 -#endif - -// Simple redirect macros for functions and types -#ifdef _WIN32 -#define os_strlen wcslen -#define os_strcmp wcscmp -#define os_fputs fputws - -#define os_CopyStr strcopy_16to16 -#define os_CopyConvertCharStr strcopy_8to16 -#define os_CopyConvertUTF16Str strcopy_16to16 -#define utf16_CopyStr strcopy_16to16 -#define utf16_CopyConvertOsStr strcopy_16to16 - -#define _osdirent _wdirent -#define _OSDIR _WDIR -#define os_readdir _wreaddir -#define os_opendir _wopendir -#define os_closedir _wclosedir -#define os_chdir _wchdir - -#define _osstat _stat64 -#define os_stat _wstat64 - -#define os_fopen _wfopen -#define OS_MODE_READ L"rb" -#define OS_MODE_WRITE L"wb" -#define OS_MODE_EDIT L"rb+" -#define OS_PATH_SEPARATOR '\\' -#else -#define os_strlen strlen -#define os_strcmp strcmp -#define os_fputs fputs - -#define os_CopyStr strcopy_8to8 -#define os_CopyConvertUTF16Str strcopy_UTF16toUTF8 -#define os_CopyConvertCharStr strcopy_8to8 -#define utf16_CopyStr strcopy_16to16 -#define utf16_CopyConvertOsStr strcopy_UTF8toUTF16 - -#define _osdirent dirent -#define _OSDIR DIR -#define os_readdir readdir -#define os_opendir opendir -#define os_closedir closedir -#define os_chdir chdir - -#define _osstat stat -#define os_stat stat - -#define os_fopen fopen -#define OS_MODE_READ "rb" -#define OS_MODE_WRITE "wb" -#define OS_MODE_EDIT "rb+" -#define OS_PATH_SEPARATOR '/' -#endif - -/* File related */ -int os_fstat(const oschar_t* path); -uint64_t os_fsize(const oschar_t* path); -int os_makedir(const oschar_t *dir); - -/* UTF16 String property functions */ -uint32_t utf16_strlen(const utf16char_t* str); -void utf16_fputs(const utf16char_t *str, FILE *out); - -/* String Copy and Conversion */ -char* strcopy_8to8(const char *src); -utf16char_t* strcopy_8to16(const char *src); -utf16char_t* strcopy_16to16(const utf16char_t *src); -#ifndef _WIN32 -utf16char_t* strcopy_UTF8toUTF16(const char *src); -char* strcopy_UTF16toUTF8(const utf16char_t *src); -#endif - -/* String Append and Create */ -oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add); -oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add); \ No newline at end of file diff --git a/ctrtool/polarssl/aes.c b/ctrtool/polarssl/aes.c deleted file mode 100644 index 45f74a6..0000000 --- a/ctrtool/polarssl/aes.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * FIPS-197 compliant AES implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. - * - * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_AES_C) - -#include "polarssl/aes.h" -#include "polarssl/padlock.h" - -#include - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -#if defined(POLARSSL_AES_ROM_TABLES) -/* - * Forward S-box - */ -static const unsigned char FSb[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 -}; - -/* - * Forward tables - */ -#define FT \ -\ - V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ - V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ - V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ - V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ - V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ - V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ - V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ - V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ - V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ - V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ - V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ - V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ - V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ - V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ - V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ - V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ - V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ - V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ - V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ - V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ - V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ - V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ - V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ - V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ - V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ - V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ - V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ - V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ - V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ - V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ - V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ - V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ - V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ - V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ - V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ - V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ - V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ - V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ - V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ - V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ - V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ - V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ - V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ - V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ - V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ - V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ - V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ - V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ - V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ - V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ - V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ - V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ - V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ - V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ - V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ - V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ - V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ - V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ - V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ - V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ - V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ - V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ - V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ - V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) - -#define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const unsigned long FT3[256] = { FT }; -#undef V - -#undef FT - -/* - * Reverse S-box - */ -static const unsigned char RSb[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 -}; - -/* - * Reverse tables - */ -#define RT \ -\ - V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ - V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ - V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ - V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ - V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ - V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ - V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ - V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ - V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ - V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ - V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ - V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ - V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ - V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ - V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ - V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ - V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ - V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ - V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ - V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ - V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ - V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ - V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ - V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ - V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ - V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ - V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ - V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ - V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ - V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ - V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ - V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ - V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ - V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ - V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ - V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ - V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ - V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ - V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ - V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ - V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ - V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ - V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ - V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ - V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ - V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ - V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ - V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ - V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ - V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ - V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ - V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ - V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ - V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ - V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ - V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ - V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ - V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ - V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ - V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ - V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ - V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ - V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ - V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) - -#define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const unsigned long RT3[256] = { RT }; -#undef V - -#undef RT - -/* - * Round constants - */ -static const unsigned long RCON[10] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x0000001B, 0x00000036 -}; - -#else - -/* - * Forward S-box & tables - */ -static unsigned char FSb[256]; -static unsigned long FT0[256]; -static unsigned long FT1[256]; -static unsigned long FT2[256]; -static unsigned long FT3[256]; - -/* - * Reverse S-box & tables - */ -static unsigned char RSb[256]; -static unsigned long RT0[256]; -static unsigned long RT1[256]; -static unsigned long RT2[256]; -static unsigned long RT3[256]; - -/* - * Round constants - */ -static unsigned long RCON[10]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -static int aes_init_done = 0; - -static void aes_gen_tables( void ) -{ - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for( i = 0, x = 1; i < 256; i++ ) - { - pow[i] = x; - log[x] = i; - x = ( x ^ XTIME( x ) ) & 0xFF; - } - - /* - * calculate the round constants - */ - for( i = 0, x = 1; i < 10; i++ ) - { - RCON[i] = (unsigned long) x; - x = XTIME( x ) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; - - y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char) x; - RSb[x] = (unsigned char) i; - } - - /* - * generate the forward and reverse tables - */ - for( i = 0; i < 256; i++ ) - { - x = FSb[i]; - y = XTIME( x ) & 0xFF; - z = ( y ^ x ) & 0xFF; - - FT0[i] = ( (unsigned long) y ) ^ - ( (unsigned long) x << 8 ) ^ - ( (unsigned long) x << 16 ) ^ - ( (unsigned long) z << 24 ); - - FT1[i] = ROTL8( FT0[i] ); - FT2[i] = ROTL8( FT1[i] ); - FT3[i] = ROTL8( FT2[i] ); - - x = RSb[i]; - - RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^ - ( (unsigned long) MUL( 0x09, x ) << 8 ) ^ - ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^ - ( (unsigned long) MUL( 0x0B, x ) << 24 ); - - RT1[i] = ROTL8( RT0[i] ); - RT2[i] = ROTL8( RT1[i] ); - RT3[i] = ROTL8( RT2[i] ); - } -} - -#endif - -/* - * AES key schedule (encryption) - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize ) -{ - int i; - unsigned long *RK; - -#if !defined(POLARSSL_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - } -#endif - - switch( keysize ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(PADLOCK_ALIGN16) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); -#else - ctx->rk = RK = ctx->buf; -#endif - - for( i = 0; i < (keysize >> 5); i++ ) - { - GET_ULONG_LE( RK[i], key, i << 2 ); - } - - switch( ctx->nr ) - { - case 10: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 12: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 14: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - - default: - - break; - } - - return( 0 ); -} - -/* - * AES key schedule (decryption) - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize ) -{ - int i, j; - aes_context cty; - unsigned long *RK; - unsigned long *SK; - int ret; - - switch( keysize ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(PADLOCK_ALIGN16) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); -#else - ctx->rk = RK = ctx->buf; -#endif - - ret = aes_setkey_enc( &cty, key, keysize ); - if( ret != 0 ) - return( ret ); - - SK = cty.rk + cty.nr * 4; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) - { - for( j = 0; j < 4; j++, SK++ ) - { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; - } - } - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - memset( &cty, 0, sizeof( aes_context ) ); - - return( 0 ); -} - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ -} - -/* - * AES-ECB block encryption/decryption - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( padlock_supports( PADLOCK_ACE ) ) - { - if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - RK = ctx->rk; - - GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; - GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; - GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; - GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; - - if( mode == AES_DECRYPT ) - { - for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) - { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - } - else /* AES_ENCRYPT */ - { - for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) - { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - } - - PUT_ULONG_LE( X0, output, 0 ); - PUT_ULONG_LE( X1, output, 4 ); - PUT_ULONG_LE( X2, output, 8 ); - PUT_ULONG_LE( X3, output, 12 ); - - return( 0 ); -} - -/* - * AES-CBC buffer encryption/decryption - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - int length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( padlock_supports( PADLOCK_ACE ) ) - { - if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == AES_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - aes_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - aes_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} - -/* - * AES-CFB128 buffer encryption/decryption - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - int length, - int *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, n = *iv_off; - - if( mode == AES_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = (n + 1) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = (n + 1) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * AES test vectors from: - * - * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip - */ -static const unsigned char aes_test_ecb_dec[3][16] = -{ - { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, - 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, - { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, - 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, - { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, - 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } -}; - -static const unsigned char aes_test_ecb_enc[3][16] = -{ - { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, - 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, - { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, - 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, - { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, - 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } -}; - -static const unsigned char aes_test_cbc_dec[3][16] = -{ - { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, - 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, - { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, - 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, - { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, - 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } -}; - -static const unsigned char aes_test_cbc_enc[3][16] = -{ - { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, - 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, - { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, - 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, - { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, - 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } -}; - -/* - * AES-CFB128 test vectors from: - * - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - */ -static const unsigned char aes_test_cfb128_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char aes_test_cfb128_iv[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - -static const unsigned char aes_test_cfb128_pt[64] = -{ - 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 -}; - -static const unsigned char aes_test_cfb128_ct[3][64] = -{ - { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, - 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, - 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, - 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, - 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, - 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, - 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, - 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, - { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, - 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, - 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, - 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, - 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, - 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, - 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, - 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, - { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, - 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, - 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, - 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, - 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, - 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, - 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, - 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } -}; - -/* - * Checkup routine - */ -int aes_self_test( int verbose ) -{ - int i, j, u, v, offset; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char prv[16]; - unsigned char iv[16]; - aes_context ctx; - - memset( key, 0, 32 ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( iv , 0, 16 ); - memset( prv, 0, 16 ); - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[16]; - - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - memcpy( tmp, prv, 16 ); - memcpy( prv, buf, 16 ); - memcpy( buf, tmp, 16 ); - } - - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - /* - * CFB128 mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); - - offset = 0; - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - if( v == AES_DECRYPT ) - { - memcpy( buf, aes_test_cfb128_ct[u], 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - else - { - memcpy( buf, aes_test_cfb128_pt, 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/ctrtool/polarssl/aes.h b/ctrtool/polarssl/aes.h deleted file mode 100644 index 5576680..0000000 --- a/ctrtool/polarssl/aes.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * \file aes.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_AES_H -#define POLARSSL_AES_H - -#define AES_ENCRYPT 1 -#define AES_DECRYPT 0 - -#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0800 -#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0810 - -/** - * \brief AES context structure - */ -typedef struct -{ - int nr; /*!< number of rounds */ - unsigned long *rk; /*!< AES round keys */ - unsigned long buf[68]; /*!< unaligned data */ -} -aes_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES key schedule (encryption) - * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize ); - -/** - * \brief AES-ECB block encryption/decryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - int length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief AES-CFB128 buffer encryption/decryption. - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - int length, - int *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int aes_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* aes.h */ diff --git a/ctrtool/polarssl/bignum.c b/ctrtool/polarssl/bignum.c deleted file mode 100644 index 78e9384..0000000 --- a/ctrtool/polarssl/bignum.c +++ /dev/null @@ -1,2038 +0,0 @@ -/* - * Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * This MPI implementation is based on: - * - * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf - * http://www.stillhq.com/extracted/gnupg-api/mpi/ - * http://math.libtomcrypt.com/files/tommath.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_BIGNUM_C) - -#include "polarssl/bignum.h" -#include "polarssl/bn_mul.h" - -#include -#include -#include - -#define ciL ((int) sizeof(t_int)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -/* - * Convert between bits/chars and number of limbs - */ -#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) -#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) - -/* - * Initialize one or more mpi - */ -void mpi_init( mpi *X, ... ) -{ - va_list args; - - va_start( args, X ); - - while( X != NULL ) - { - X->s = 1; - X->n = 0; - X->p = NULL; - - X = va_arg( args, mpi* ); - } - - va_end( args ); -} - -/* - * Unallocate one or more mpi - */ -void mpi_free( mpi *X, ... ) -{ - va_list args; - - va_start( args, X ); - - while( X != NULL ) - { - if( X->p != NULL ) - { - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; - - X = va_arg( args, mpi* ); - } - - va_end( args ); -} - -/* - * Enlarge to the specified number of limbs - */ -int mpi_grow( mpi *X, int nblimbs ) -{ - t_int *p; - - if( X->n < nblimbs ) - { - if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL ) - return( 1 ); - - memset( p, 0, nblimbs * ciL ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mpi_copy( mpi *X, const mpi *Y ) -{ - int ret, i; - - if( X == Y ) - return( 0 ); - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MPI_CHK( mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mpi_swap( mpi *X, mpi *Y ) -{ - mpi T; - - memcpy( &T, X, sizeof( mpi ) ); - memcpy( X, Y, sizeof( mpi ) ); - memcpy( Y, &T, sizeof( mpi ) ); -} - -/* - * Set value from integer - */ -int mpi_lset( mpi *X, int z ) -{ - int ret; - - MPI_CHK( mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Return the number of least significant bits - */ -int mpi_lsb( const mpi *X ) -{ - int i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < (int) biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Return the number of most significant bits - */ -int mpi_msb( const mpi *X ) -{ - int i, j; - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - for( j = biL - 1; j >= 0; j-- ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - break; - - return( ( i * biL ) + j + 1 ); -} - -/* - * Return the total size in bytes - */ -int mpi_size( const mpi *X ) -{ - return( ( mpi_msb( X ) + 7 ) >> 3 ); -} - -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( t_int *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (t_int) radix ) - return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mpi_read_string( mpi *X, int radix, const char *s ) -{ - int ret, i, j, n, slen; - t_int d; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &T, NULL ); - - slen = strlen( s ); - - if( radix == 16 ) - { - n = BITS_TO_LIMBS( slen << 2 ); - - MPI_CHK( mpi_grow( X, n ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = slen - 1, j = 0; i >= 0; i--, j++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - break; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 ); - } - } - else - { - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MPI_CHK( mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MPI_CHK( mpi_add_int( X, &T, d ) ); - } - else - { - MPI_CHK( mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mpi_free( &T, NULL ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mpi *X, int radix, char **p ) -{ - int ret; - t_int r; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - MPI_CHK( mpi_mod_int( &r, X, radix ) ); - MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); - - if( mpi_cmp_int( X, 0 ) != 0 ) - MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mpi_write_string( const mpi *X, int radix, char *s, int *slen ) -{ - int ret = 0, n; - char *p; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - n = mpi_msb( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - n += 3; - - if( *slen < n ) - { - *slen = n; - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = s; - mpi_init( &T, NULL ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c, i, j, k; - - for( i = X->n - 1, k = 0; i >= 0; i-- ) - { - for( j = ciL - 1; j >= 0; j-- ) - { - c = ( X->p[i] >> (j << 3) ) & 0xFF; - - if( c == 0 && k == 0 && (i + j) != 0 ) - continue; - - p += sprintf( p, "%02X", c ); - k = 1; - } - } - } - else - { - MPI_CHK( mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *slen = p - s; - -cleanup: - - mpi_free( &T, NULL ); - - return( ret ); -} - -/* - * Read X from an opened file - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ) -{ - t_int d; - int slen; - char *p; - char s[1024]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( --p >= s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ) -{ - int n, ret; - size_t slen; - size_t plen; - char s[2048]; - - n = sizeof( s ); - memset( s, 0, n ); - n -= 2; - - MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - } - else - printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} - -/* - * Import X from unsigned binary data, big endian - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen ) -{ - int ret, i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = buflen - 1, j = 0; i >= n; i--, j++ ) - X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen ) -{ - int i, j, n; - - n = mpi_size( X ); - - if( buflen < n ) - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mpi_shift_l( mpi *X, int count ) -{ - int ret, i, v0, t1; - t_int r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mpi_msb( X ) + count; - - if( X->n * (int) biL < i ) - MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n - 1; i >= v0; i-- ) - X->p[i] = X->p[i - v0]; - - for( ; i >= 0; i-- ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mpi_shift_r( mpi *X, int count ) -{ - int i, v0, v1; - t_int r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n - 1; i >= 0; i-- ) - { - r1 = X->p[i] << (biL - v1); - X->p[i] >>= v1; - X->p[i] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ) -{ - int i, j; - - for( i = X->n - 1; i >= 0; i-- ) - if( X->p[i] != 0 ) - break; - - for( j = Y->n - 1; j >= 0; j-- ) - if( Y->p[j] != 0 ) - break; - - if( i < 0 && j < 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i >= 0; i-- ) - { - if( X->p[i] > Y->p[i] ) return( 1 ); - if( X->p[i] < Y->p[i] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ) -{ - int i, j; - - for( i = X->n - 1; i >= 0; i-- ) - if( X->p[i] != 0 ) - break; - - for( j = Y->n - 1; j >= 0; j-- ) - if( Y->p[j] != 0 ) - break; - - if( i < 0 && j < 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -X->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i >= 0; i-- ) - { - if( X->p[i] > Y->p[i] ) return( X->s ); - if( X->p[i] < Y->p[i] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_int( const mpi *X, int z ) -{ - mpi Y; - t_int p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, i, j; - t_int *o, *p, c; - - if( X == B ) - { - const mpi *T = A; A = X; B = T; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n - 1; j >= 0; j-- ) - if( B->p[j] != 0 ) - break; - - MPI_CHK( mpi_grow( X, j + 1 ) ); - - o = B->p; p = X->p; c = 0; - - for( i = 0; i <= j; i++, o++, p++ ) - { - *p += c; c = ( *p < c ); - *p += *o; c += ( *p < *o ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MPI_CHK( mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mpi substraction - */ -static void mpi_sub_hlp( int n, t_int *s, t_int *d ) -{ - int i; - t_int c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned substraction: X = |A| - |B| (HAC 14.9) - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) -{ - mpi TB; - int ret, n; - - if( mpi_cmp_abs( A, B ) < 0 ) - return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); - - mpi_init( &TB, NULL ); - - if( X == B ) - { - MPI_CHK( mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned substractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n - 1; n >= 0; n-- ) - if( B->p[n] != 0 ) - break; - - mpi_sub_hlp( n + 1, B->p, X->p ); - -cleanup: - - mpi_free( &TB, NULL ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed substraction: X = A - B - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mpi_add_int( mpi *X, const mpi *A, int b ) -{ - mpi _B; - t_int p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed substraction: X = A - b - */ -int mpi_sub_int( mpi *X, const mpi *A, int b ) -{ - mpi _B; - t_int p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_sub_mpi( X, A, &_B ) ); -} - -/* - * Helper for mpi multiplication - */ -static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b ) -{ - t_int c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, i, j; - mpi TA, TB; - - mpi_init( &TA, &TB, NULL ); - - if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n - 1; i >= 0; i-- ) - if( A->p[i] != 0 ) - break; - - for( j = B->n - 1; j >= 0; j-- ) - if( B->p[j] != 0 ) - break; - - MPI_CHK( mpi_grow( X, i + j + 2 ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i++; j >= 0; j-- ) - mpi_mul_hlp( i, A->p, X->p + j, B->p[j] ); - - X->s = A->s * B->s; - -cleanup: - - mpi_free( &TB, &TA, NULL ); - - return( ret ); -} - -/* - * Baseline multiplication: X = A * b - */ -int mpi_mul_int( mpi *X, const mpi *A, t_int b ) -{ - mpi _B; - t_int p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Division by mpi: A = Q * B + R (HAC 14.20) - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) -{ - int ret, i, n, t, k; - mpi X, Y, Z, T1, T2; - - if( mpi_cmp_int( B, 0 ) == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - mpi_init( &X, &Y, &Z, &T1, &T2, NULL ); - - if( mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); - if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); - return( 0 ); - } - - MPI_CHK( mpi_copy( &X, A ) ); - MPI_CHK( mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); - MPI_CHK( mpi_lset( &Z, 0 ) ); - MPI_CHK( mpi_grow( &T1, 2 ) ); - MPI_CHK( mpi_grow( &T2, 3 ) ); - - k = mpi_msb( &Y ) % biL; - if( k < (int) biL - 1 ) - { - k = biL - 1 - k; - MPI_CHK( mpi_shift_l( &X, k ) ); - MPI_CHK( mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - mpi_shift_l( &Y, biL * (n - t) ); - - while( mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - mpi_sub_mpi( &X, &X, &Y ); - } - mpi_shift_r( &Y, biL * (n - t) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { -#if defined(POLARSSL_HAVE_LONGLONG) - t_dbl r; - - r = (t_dbl) X.p[i] << biL; - r |= (t_dbl) X.p[i - 1]; - r /= Y.p[t]; - if( r > ((t_dbl) 1 << biL) - 1) - r = ((t_dbl) 1 << biL) - 1; - - Z.p[i - t - 1] = (t_int) r; -#else - /* - * __udiv_qrnnd_c, from gmp/longlong.h - */ - t_int q0, q1, r0, r1; - t_int d0, d1, d, m; - - d = Y.p[t]; - d0 = ( d << biH ) >> biH; - d1 = ( d >> biH ); - - q1 = X.p[i] / d1; - r1 = X.p[i] - d1 * q1; - r1 <<= biH; - r1 |= ( X.p[i - 1] >> biH ); - - m = q1 * d0; - if( r1 < m ) - { - q1--, r1 += d; - while( r1 >= d && r1 < m ) - q1--, r1 += d; - } - r1 -= m; - - q0 = r1 / d1; - r0 = r1 - d1 * q0; - r0 <<= biH; - r0 |= ( X.p[i - 1] << biH ) >> biH; - - m = q0 * d0; - if( r0 < m ) - { - q0--, r0 += d; - while( r0 >= d && r0 < m ) - q0--, r0 += d; - } - r0 -= m; - - Z.p[i - t - 1] = ( q1 << biH ) | q0; -#endif - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MPI_CHK( mpi_lset( &T1, 0 ) ); - T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MPI_CHK( mpi_lset( &T2, 0 ) ); - T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; - T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mpi_cmp_int( &X, 0 ) < 0 ) - { - MPI_CHK( mpi_copy( &T1, &Y ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - mpi_copy( Q, &Z ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - mpi_shift_r( &X, k ); - mpi_copy( R, &X ); - - R->s = A->s; - if( mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mpi_free( &X, &Y, &Z, &T1, &T2, NULL ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - * - * Returns 0 if successful - * 1 if memory allocation failed - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b ) -{ - mpi _B; - t_int p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) -{ - int ret; - - if( mpi_cmp_int( B, 0 ) < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); - - while( mpi_cmp_int( R, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( R, R, B ) ); - - while( mpi_cmp_mpi( R, B ) >= 0 ) - MPI_CHK( mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mpi_mod_int( t_int *r, const mpi *A, int b ) -{ - int i; - t_int x, y, z; - - if( b == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n - 1, y = 0; i >= 0; i-- ) - { - x = A->p[i]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( t_int *mm, const mpi *N ) -{ - t_int x, m0 = N->p[0]; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - x *= ( 2 - ( m0 * x ) ); - - if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_int mm, const mpi *T ) -{ - int i, n, m; - t_int u0, u1, *d; - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, (n + 1) * ciL ); - - if( mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static void mpi_montred( mpi *A, const mpi *N, t_int mm, const mpi *T ) -{ - t_int z = 1; - mpi U; - - U.n = U.s = z; - U.p = &z; - - mpi_montmul( A, &U, N, mm, T ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) -{ - int ret, i, j, wsize, wbits; - int bufsize, nblimbs, nbits; - t_int ei, mm, state; - mpi RR, T, W[64]; - - if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mpi_init( &RR, &T, NULL ); - memset( W, 0, sizeof( W ) ); - - i = mpi_msb( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - j = N->n + 1; - MPI_CHK( mpi_grow( X, j ) ); - MPI_CHK( mpi_grow( &W[1], j ) ); - MPI_CHK( mpi_grow( &T, j * 2 ) ); - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MPI_CHK( mpi_lset( &RR, 1 ) ); - MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); - MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mpi_cmp_mpi( A, N ) >= 0 ) - mpi_mod_mpi( &W[1], A, N ); - else mpi_copy( &W[1], A ); - - mpi_montmul( &W[1], &RR, N, mm, &T ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MPI_CHK( mpi_copy( X, &RR ) ); - mpi_montred( X, N, mm, &T ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = 1 << (wsize - 1); - - MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - mpi_montmul( &W[j], &W[j], N, mm, &T ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < (1 << wsize); i++ ) - { - MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); - - mpi_montmul( &W[i], &W[1], N, mm, &T ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs-- == 0 ) - break; - - bufsize = sizeof( t_int ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - mpi_montmul( X, X, N, mm, &T ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= (ei << (wsize - nbits)); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - mpi_montmul( X, X, N, mm, &T ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - mpi_montmul( X, &W[wbits], N, mm, &T ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - mpi_montmul( X, X, N, mm, &T ); - - wbits <<= 1; - - if( (wbits & (1 << wsize)) != 0 ) - mpi_montmul( X, &W[1], N, mm, &T ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - mpi_montred( X, N, mm, &T ); - -cleanup: - - for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ ) - mpi_free( &W[i], NULL ); - - if( _RR != NULL ) - mpi_free( &W[1], &T, NULL ); - else mpi_free( &W[1], &T, &RR, NULL ); - - return( ret ); -} - -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) -{ - int ret, lz, lzt; - mpi TG, TA, TB; - - mpi_init( &TG, &TA, &TB, NULL ); - - MPI_CHK( mpi_copy( &TA, A ) ); - MPI_CHK( mpi_copy( &TB, B ) ); - - lz = mpi_lsb( &TA ); - lzt = mpi_lsb( &TB ); - - if ( lzt < lz ) - lz = lzt; - - MPI_CHK( mpi_shift_r( &TA, lz ) ); - MPI_CHK( mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mpi_cmp_int( &TA, 0 ) != 0 ) - { - MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); - MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); - - if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); - MPI_CHK( mpi_shift_r( &TA, 1 ) ); - } - else - { - MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); - MPI_CHK( mpi_shift_r( &TB, 1 ) ); - } - } - - MPI_CHK( mpi_shift_l( &TB, lz ) ); - MPI_CHK( mpi_copy( G, &TB ) ); - -cleanup: - - mpi_free( &TB, &TA, &TG, NULL ); - - return( ret ); -} - -#if defined(POLARSSL_GENPRIME) - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) -{ - int ret; - mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mpi_cmp_int( N, 0 ) <= 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &TA, &TU, &U1, &U2, &G, - &TB, &TV, &V1, &V2, NULL ); - - MPI_CHK( mpi_gcd( &G, A, N ) ); - - if( mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); - MPI_CHK( mpi_copy( &TU, &TA ) ); - MPI_CHK( mpi_copy( &TB, N ) ); - MPI_CHK( mpi_copy( &TV, N ) ); - - MPI_CHK( mpi_lset( &U1, 1 ) ); - MPI_CHK( mpi_lset( &U2, 0 ) ); - MPI_CHK( mpi_lset( &V1, 0 ) ); - MPI_CHK( mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &U1, 1 ) ); - MPI_CHK( mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &V1, 1 ) ); - MPI_CHK( mpi_shift_r( &V2, 1 ) ); - } - - if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); - MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); - MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mpi_cmp_int( &V1, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); - - while( mpi_cmp_mpi( &V1, N ) >= 0 ) - MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); - - MPI_CHK( mpi_copy( X, &V1 ) ); - -cleanup: - - mpi_free( &V2, &V1, &TV, &TB, &G, - &U2, &U1, &TU, &TA, NULL ); - - return( ret ); -} - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Miller-Rabin primality test (HAC 4.24) - */ -int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ) -{ - int ret, i, j, n, s, xs; - mpi W, R, T, A, RR; - unsigned char *p; - - if( mpi_cmp_int( X, 0 ) == 0 || - mpi_cmp_int( X, 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - if( mpi_cmp_int( X, 2 ) == 0 ) - return( 0 ); - - mpi_init( &W, &R, &T, &A, &RR, NULL ); - - xs = X->s; X->s = 1; - - /* - * test trivial factors first - */ - if( ( X->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - t_int r; - - if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 0 ); - - MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - } - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MPI_CHK( mpi_sub_int( &W, X, 1 ) ); - s = mpi_lsb( &W ); - MPI_CHK( mpi_copy( &R, &W ) ); - MPI_CHK( mpi_shift_r( &R, s ) ); - - i = mpi_msb( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MPI_CHK( mpi_grow( &A, X->n ) ); - - p = (unsigned char *) A.p; - for( j = 0; j < A.n * ciL; j++ ) - *p++ = (unsigned char) f_rng( p_rng ); - - j = mpi_msb( &A ) - mpi_msb( &W ); - MPI_CHK( mpi_shift_r( &A, j + 1 ) ); - A.p[0] |= 3; - - /* - * A = A^R mod |X| - */ - MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mpi_cmp_mpi( &A, &W ) == 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); - MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); - - if( mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mpi_cmp_mpi( &A, &W ) != 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - - X->s = xs; - - mpi_free( &RR, &A, &T, &R, &W, NULL ); - - return( ret ); -} - -/* - * Prime number generation - */ -int mpi_gen_prime( mpi *X, int nbits, int dh_flag, - int (*f_rng)(void *), void *p_rng ) -{ - int ret, k, n; - unsigned char *p; - mpi Y; - - if( nbits < 3 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &Y, NULL ); - - n = BITS_TO_LIMBS( nbits ); - - MPI_CHK( mpi_grow( X, n ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - p = (unsigned char *) X->p; - for( k = 0; k < X->n * ciL; k++ ) - *p++ = (unsigned char) f_rng( p_rng ); - - k = mpi_msb( X ); - if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); - if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); - - X->p[0] |= 3; - - if( dh_flag == 0 ) - { - while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( X, X, 2 ) ); - } - } - else - { - MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 ) - { - if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 ) - break; - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - } - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( &Y, X, 1 ) ); - MPI_CHK( mpi_add_int( X, X, 2 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - } - } - -cleanup: - - mpi_free( &Y, NULL ); - - return( ret ); -} - -#endif - -#if defined(POLARSSL_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mpi_self_test( int verbose ) -{ - int ret, i; - mpi A, E, N, X, Y, U, V; - - mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL ); - - MPI_CHK( mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MPI_CHK( mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MPI_CHK( mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - printf( " MPI test #1 (mul_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MPI_CHK( mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - printf( " MPI test #2 (div_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 || - mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - printf( " MPI test #3 (exp_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - printf( " MPI test #4 (inv_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - if( verbose != 0 ) - printf( " MPI test #5 (simple gcd): " ); - - for ( i = 0; i < GCD_PAIR_COUNT; i++) - { - MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); - MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MPI_CHK( mpi_gcd( &A, &X, &Y ) ); - - if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - printf( "failed at %d\n", i ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - printf( "Unexpected error, return code = %08X\n", ret ); - - mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL ); - - if( verbose != 0 ) - printf( "\n" ); - - return( ret ); -} - -#endif - -#endif diff --git a/ctrtool/polarssl/bignum.h b/ctrtool/polarssl/bignum.h deleted file mode 100644 index 80399a2..0000000 --- a/ctrtool/polarssl/bignum.h +++ /dev/null @@ -1,533 +0,0 @@ -/** - * \file bignum.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_BIGNUM_H -#define POLARSSL_BIGNUM_H - -#include - -#define POLARSSL_ERR_MPI_FILE_IO_ERROR 0x0002 -#define POLARSSL_ERR_MPI_BAD_INPUT_DATA 0x0004 -#define POLARSSL_ERR_MPI_INVALID_CHARACTER 0x0006 -#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL 0x0008 -#define POLARSSL_ERR_MPI_NEGATIVE_VALUE 0x000A -#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO 0x000C -#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE 0x000E - -#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup - -/* - * Define the base integer type, architecture-wise - */ -#if defined(POLARSSL_HAVE_INT8) -typedef unsigned char t_int; -typedef unsigned short t_dbl; -#else -#if defined(POLARSSL_HAVE_INT16) -typedef unsigned short t_int; -typedef unsigned long t_dbl; -#else - typedef unsigned long t_int; - #if defined(_MSC_VER) && defined(_M_IX86) - typedef unsigned __int64 t_dbl; - #else - #if defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) - typedef unsigned int t_dbl __attribute__((mode(TI))); - #else - #if defined(POLARSSL_HAVE_LONGLONG) - typedef unsigned long long t_dbl; - #endif - #endif - #endif -#endif -#endif - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - int n; /*!< total # of limbs */ - t_int *p; /*!< pointer to limbs */ -} -mpi; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize one or more mpi - */ -void mpi_init( mpi *X, ... ); - -/** - * \brief Unallocate one or more mpi - */ -void mpi_free( mpi *X, ... ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_grow( mpi *X, int nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_copy( mpi *X, const mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mpi_swap( mpi *X, mpi *Y ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_lset( mpi *X, int z ); - -/** - * \brief Return the number of least significant bits - * - * \param X MPI to use - */ -int mpi_lsb( const mpi *X ); - -/** - * \brief Return the number of most significant bits - * - * \param X MPI to use - */ -int mpi_msb( const mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -int mpi_size( const mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_string( mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param s String buffer - * \param slen String buffer size - * - * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code. - * *slen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *slen = 0 to obtain the - * minimum required buffer size in *slen. - */ -int mpi_write_string( const mpi *X, int radix, char *s, int *slen ); - -/** - * \brief Read X from an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen ); - -/** - * \brief Export X into unsigned binary data, big endian - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_shift_l( mpi *X, int count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_shift_r( mpi *X, int count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mpi_cmp_int( const mpi *X, int z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Unsigned substraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed substraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_add_int( mpi *X, const mpi *A, int b ); - -/** - * \brief Signed substraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_sub_int( mpi *X, const mpi *A, int b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * Note: b is an unsigned integer type, thus - * Negative values of b are ignored. - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to multiply with - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_mul_int( mpi *X, const mpi *A, t_int b ); - -/** - * \brief Division by mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination t_int - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mpi_mod_int( t_int *r, const mpi *A, int b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil - POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * 1 if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mpi_gen_prime( mpi *X, int nbits, int dh_flag, - int (*f_rng)(void *), void *p_rng ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/ctrtool/polarssl/bn_mul.h b/ctrtool/polarssl/bn_mul.h deleted file mode 100644 index a73d5fb..0000000 --- a/ctrtool/polarssl/bn_mul.h +++ /dev/null @@ -1,736 +0,0 @@ -/** - * \file bn_mul.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef POLARSSL_BN_MUL_H -#define POLARSSL_BN_MUL_H - -#include "polarssl/config.h" - -#if defined(POLARSSL_HAVE_ASM) - -#if defined(__GNUC__) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( " \ - movl %%ebx, %0; \ - movl %5, %%esi; \ - movl %6, %%edi; \ - movl %7, %%ecx; \ - movl %8, %%ebx; \ - " - -#define MULADDC_CORE \ - " \ - lodsl; \ - mull %%ebx; \ - addl %%ecx, %%eax; \ - adcl $0, %%edx; \ - addl (%%edi), %%eax; \ - adcl $0, %%edx; \ - movl %%edx, %%ecx; \ - stosl; \ - " - -#if defined(POLARSSL_HAVE_SSE2) - -#define MULADDC_HUIT \ - " \ - movd %%ecx, %%mm1; \ - movd %%ebx, %%mm0; \ - movd (%%edi), %%mm3; \ - paddq %%mm3, %%mm1; \ - movd (%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - movd 4(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - movd 8(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd 12(%%esi), %%mm7; \ - pmuludq %%mm0, %%mm7; \ - paddq %%mm2, %%mm1; \ - movd 4(%%edi), %%mm3; \ - paddq %%mm4, %%mm3; \ - movd 8(%%edi), %%mm5; \ - paddq %%mm6, %%mm5; \ - movd 12(%%edi), %%mm4; \ - paddq %%mm4, %%mm7; \ - movd %%mm1, (%%edi); \ - movd 16(%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - psrlq $32, %%mm1; \ - movd 20(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - paddq %%mm3, %%mm1; \ - movd 24(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd %%mm1, 4(%%edi); \ - psrlq $32, %%mm1; \ - movd 28(%%esi), %%mm3; \ - pmuludq %%mm0, %%mm3; \ - paddq %%mm5, %%mm1; \ - movd 16(%%edi), %%mm5; \ - paddq %%mm5, %%mm2; \ - movd %%mm1, 8(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm7, %%mm1; \ - movd 20(%%edi), %%mm5; \ - paddq %%mm5, %%mm4; \ - movd %%mm1, 12(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm2, %%mm1; \ - movd 24(%%edi), %%mm5; \ - paddq %%mm5, %%mm6; \ - movd %%mm1, 16(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm4, %%mm1; \ - movd 28(%%edi), %%mm5; \ - paddq %%mm5, %%mm3; \ - movd %%mm1, 20(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm6, %%mm1; \ - movd %%mm1, 24(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm3, %%mm1; \ - movd %%mm1, 28(%%edi); \ - addl $32, %%edi; \ - addl $32, %%esi; \ - psrlq $32, %%mm1; \ - movd %%mm1, %%ecx; \ - " - -#define MULADDC_STOP \ - " \ - emms; \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - " \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( "movq %0, %%rsi " :: "m" (s)); \ - asm( "movq %0, %%rdi " :: "m" (d)); \ - asm( "movq %0, %%rcx " :: "m" (c)); \ - asm( "movq %0, %%rbx " :: "m" (b)); \ - asm( "xorq %r8, %r8 " ); - -#define MULADDC_CORE \ - asm( "movq (%rsi),%rax " ); \ - asm( "mulq %rbx " ); \ - asm( "addq $8, %rsi " ); \ - asm( "addq %rcx, %rax " ); \ - asm( "movq %r8, %rcx " ); \ - asm( "adcq $0, %rdx " ); \ - asm( "nop " ); \ - asm( "addq %rax, (%rdi) " ); \ - asm( "adcq %rdx, %rcx " ); \ - asm( "addq $8, %rdi " ); - -#define MULADDC_STOP \ - asm( "movq %%rcx, %0 " : "=m" (c)); \ - asm( "movq %%rdi, %0 " : "=m" (d)); \ - asm( "movq %%rsi, %0 " : "=m" (s) :: \ - "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( "movl %0, %%a2 " :: "m" (s)); \ - asm( "movl %0, %%a3 " :: "m" (d)); \ - asm( "movl %0, %%d3 " :: "m" (c)); \ - asm( "movl %0, %%d2 " :: "m" (b)); \ - asm( "moveq #0, %d0 " ); - -#define MULADDC_CORE \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "moveq #0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d4, %d3 " ); - -#define MULADDC_STOP \ - asm( "movl %%d3, %0 " : "=m" (c)); \ - asm( "movl %%a3, %0 " : "=m" (d)); \ - asm( "movl %%a2, %0 " : "=m" (s) :: \ - "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); - -#define MULADDC_HUIT \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d0, %d3 " ); - -#endif /* MC68000 */ - -#if defined(__powerpc__) || defined(__ppc__) -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "ld r3, %0 " :: "m" (s)); \ - asm( "ld r4, %0 " :: "m" (d)); \ - asm( "ld r5, %0 " :: "m" (c)); \ - asm( "ld r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -8 " ); \ - asm( "addi r4, r4, -8 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu r7, 8(r3) " ); \ - asm( "mulld r8, r7, r6 " ); \ - asm( "mulhdu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "ld r7, 8(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stdu r8, 8(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 8 " ); \ - asm( "addi r3, r3, 8 " ); \ - asm( "std r5, %0 " : "=m" (c)); \ - asm( "std r4, %0 " : "=m" (d)); \ - asm( "std r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "ld %%r3, %0 " :: "m" (s)); \ - asm( "ld %%r4, %0 " :: "m" (d)); \ - asm( "ld %%r5, %0 " :: "m" (c)); \ - asm( "ld %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -8 " ); \ - asm( "addi %r4, %r4, -8 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu %r7, 8(%r3) " ); \ - asm( "mulld %r8, %r7, %r6 " ); \ - asm( "mulhdu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "ld %r7, 8(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stdu %r8, 8(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 8 " ); \ - asm( "addi %r3, %r3, 8 " ); \ - asm( "std %%r5, %0 " : "=m" (c)); \ - asm( "std %%r4, %0 " : "=m" (d)); \ - asm( "std %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#else /* PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "lwz r3, %0 " :: "m" (s)); \ - asm( "lwz r4, %0 " :: "m" (d)); \ - asm( "lwz r5, %0 " :: "m" (c)); \ - asm( "lwz r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -4 " ); \ - asm( "addi r4, r4, -4 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu r7, 4(r3) " ); \ - asm( "mullw r8, r7, r6 " ); \ - asm( "mulhwu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "lwz r7, 4(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stwu r8, 4(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 4 " ); \ - asm( "addi r3, r3, 4 " ); \ - asm( "stw r5, %0 " : "=m" (c)); \ - asm( "stw r4, %0 " : "=m" (d)); \ - asm( "stw r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "lwz %%r3, %0 " :: "m" (s)); \ - asm( "lwz %%r4, %0 " :: "m" (d)); \ - asm( "lwz %%r5, %0 " :: "m" (c)); \ - asm( "lwz %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -4 " ); \ - asm( "addi %r4, %r4, -4 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu %r7, 4(%r3) " ); \ - asm( "mullw %r8, %r7, %r6 " ); \ - asm( "mulhwu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "lwz %r7, 4(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stwu %r8, 4(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 4 " ); \ - asm( "addi %r3, %r3, 4 " ); \ - asm( "stw %%r5, %0 " : "=m" (c)); \ - asm( "stw %%r4, %0 " : "=m" (d)); \ - asm( "stw %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#endif /* PPC32 */ -#endif /* PPC64 */ - -#if defined(__sparc__) - -#define MULADDC_INIT \ - asm( "ld %0, %%o0 " :: "m" (s)); \ - asm( "ld %0, %%o1 " :: "m" (d)); \ - asm( "ld %0, %%o2 " :: "m" (c)); \ - asm( "ld %0, %%o3 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ld [%o0], %o4 " ); \ - asm( "inc 4, %o0 " ); \ - asm( "ld [%o1], %o5 " ); \ - asm( "umul %o3, %o4, %o4 " ); \ - asm( "addcc %o4, %o2, %o4 " ); \ - asm( "rd %y, %g1 " ); \ - asm( "addx %g1, 0, %g1 " ); \ - asm( "addcc %o4, %o5, %o4 " ); \ - asm( "st %o4, [%o1] " ); \ - asm( "addx %g1, 0, %o2 " ); \ - asm( "inc 4, %o1 " ); - -#define MULADDC_STOP \ - asm( "st %%o2, %0 " : "=m" (c)); \ - asm( "st %%o1, %0 " : "=m" (d)); \ - asm( "st %%o0, %0 " : "=m" (s) :: \ - "g1", "o0", "o1", "o2", "o3", "o4", "o5" ); - -#endif /* SPARCv8 */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( "lwi r3, %0 " :: "m" (s)); \ - asm( "lwi r4, %0 " :: "m" (d)); \ - asm( "lwi r5, %0 " :: "m" (c)); \ - asm( "lwi r6, %0 " :: "m" (b)); \ - asm( "andi r7, r6, 0xffff" ); \ - asm( "bsrli r6, r6, 16 " ); - -#define MULADDC_CORE \ - asm( "lhui r8, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "lhui r9, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "mul r10, r9, r6 " ); \ - asm( "mul r11, r8, r7 " ); \ - asm( "mul r12, r9, r7 " ); \ - asm( "mul r13, r8, r6 " ); \ - asm( "bsrli r8, r10, 16 " ); \ - asm( "bsrli r9, r11, 16 " ); \ - asm( "add r13, r13, r8 " ); \ - asm( "add r13, r13, r9 " ); \ - asm( "bslli r10, r10, 16 " ); \ - asm( "bslli r11, r11, 16 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r11 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "lwi r10, r4, 0 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r5 " ); \ - asm( "addc r5, r13, r0 " ); \ - asm( "swi r12, r4, 0 " ); \ - asm( "addi r4, r4, 4 " ); - -#define MULADDC_STOP \ - asm( "swi r5, %0 " : "=m" (c)); \ - asm( "swi r4, %0 " : "=m" (d)); \ - asm( "swi r3, %0 " : "=m" (s) :: \ - "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ - "r9", "r10", "r11", "r12", "r13" ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( "ld.a %%a2, %0 " :: "m" (s)); \ - asm( "ld.a %%a3, %0 " :: "m" (d)); \ - asm( "ld.w %%d4, %0 " :: "m" (c)); \ - asm( "ld.w %%d1, %0 " :: "m" (b)); \ - asm( "xor %d5, %d5 " ); - -#define MULADDC_CORE \ - asm( "ld.w %d0, [%a2+] " ); \ - asm( "madd.u %e2, %e4, %d0, %d1 " ); \ - asm( "ld.w %d0, [%a3] " ); \ - asm( "addx %d2, %d2, %d0 " ); \ - asm( "addc %d3, %d3, 0 " ); \ - asm( "mov %d4, %d3 " ); \ - asm( "st.w [%a3+], %d2 " ); - -#define MULADDC_STOP \ - asm( "st.w %0, %%d4 " : "=m" (c)); \ - asm( "st.a %0, %%a3 " : "=m" (d)); \ - asm( "st.a %0, %%a2 " : "=m" (s) :: \ - "d0", "d1", "e2", "d4", "a2", "a3" ); - -#endif /* TriCore */ - -#if defined(__arm__) - -#define MULADDC_INIT \ - asm( "ldr r0, %0 " :: "m" (s)); \ - asm( "ldr r1, %0 " :: "m" (d)); \ - asm( "ldr r2, %0 " :: "m" (c)); \ - asm( "ldr r3, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ldr r4, [r0], #4 " ); \ - asm( "mov r5, #0 " ); \ - asm( "ldr r6, [r1] " ); \ - asm( "umlal r2, r5, r3, r4 " ); \ - asm( "adds r7, r6, r2 " ); \ - asm( "adc r2, r5, #0 " ); \ - asm( "str r7, [r1], #4 " ); - -#define MULADDC_STOP \ - asm( "str r2, %0 " : "=m" (c)); \ - asm( "str r1, %0 " : "=m" (d)); \ - asm( "str r0, %0 " : "=m" (s) :: \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" ); - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( "ldq $1, %0 " :: "m" (s)); \ - asm( "ldq $2, %0 " :: "m" (d)); \ - asm( "ldq $3, %0 " :: "m" (c)); \ - asm( "ldq $4, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ldq $6, 0($1) " ); \ - asm( "addq $1, 8, $1 " ); \ - asm( "mulq $6, $4, $7 " ); \ - asm( "umulh $6, $4, $6 " ); \ - asm( "addq $7, $3, $7 " ); \ - asm( "cmpult $7, $3, $3 " ); \ - asm( "ldq $5, 0($2) " ); \ - asm( "addq $7, $5, $7 " ); \ - asm( "cmpult $7, $5, $5 " ); \ - asm( "stq $7, 0($2) " ); \ - asm( "addq $2, 8, $2 " ); \ - asm( "addq $6, $3, $3 " ); \ - asm( "addq $5, $3, $3 " ); - -#define MULADDC_STOP \ - asm( "stq $3, %0 " : "=m" (c)); \ - asm( "stq $2, %0 " : "=m" (d)); \ - asm( "stq $1, %0 " : "=m" (s) :: \ - "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); - -#endif /* Alpha */ - -#if defined(__mips__) - -#define MULADDC_INIT \ - asm( "lw $10, %0 " :: "m" (s)); \ - asm( "lw $11, %0 " :: "m" (d)); \ - asm( "lw $12, %0 " :: "m" (c)); \ - asm( "lw $13, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "lw $14, 0($10) " ); \ - asm( "multu $13, $14 " ); \ - asm( "addi $10, $10, 4 " ); \ - asm( "mflo $14 " ); \ - asm( "mfhi $9 " ); \ - asm( "addu $14, $12, $14 " ); \ - asm( "lw $15, 0($11) " ); \ - asm( "sltu $12, $14, $12 " ); \ - asm( "addu $15, $14, $15 " ); \ - asm( "sltu $14, $15, $14 " ); \ - asm( "addu $12, $12, $9 " ); \ - asm( "sw $15, 0($11) " ); \ - asm( "addu $12, $12, $14 " ); \ - asm( "addi $11, $11, 4 " ); - -#define MULADDC_STOP \ - asm( "sw $12, %0 " : "=m" (c)); \ - asm( "sw $11, %0 " : "=m" (d)); \ - asm( "sw $10, %0 " : "=m" (s) :: \ - "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(POLARSSL_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* POLARSSL_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(POLARSSL_HAVE_LONGLONG) - -#define MULADDC_INIT \ -{ \ - t_dbl r; \ - t_int r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (t_dbl) b; \ - r0 = r; \ - r1 = r >> biL; \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - t_int s0, s1, b0, b1; \ - t_int r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/ctrtool/polarssl/config.h b/ctrtool/polarssl/config.h deleted file mode 100644 index 267e2dd..0000000 --- a/ctrtool/polarssl/config.h +++ /dev/null @@ -1,336 +0,0 @@ -/** - * \file config.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/* - * Uncomment if native integers are 8-bit wide. - * -#define POLARSSL_HAVE_INT8 - */ - -/* - * Uncomment if native integers are 16-bit wide. - * -#define POLARSSL_HAVE_INT16 - */ - -/* - * Uncomment if the compiler supports long long. - * -#define POLARSSL_HAVE_LONGLONG - */ - -/* - * Uncomment to enable the use of assembly code. - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - */ -//#define POLARSSL_HAVE_ASM - -/* - * Uncomment if the CPU supports SSE2 (IA-32 specific). - * -#define POLARSSL_HAVE_SSE2 - */ - -/* - * Enable all SSL/TLS debugging messages. - */ -#define POLARSSL_DEBUG_MSG - -/* - * Enable the checkup functions (*_self_test). - */ -//#define POLARSSL_SELF_TEST - -/* - * Enable run-time version information functions - */ -#define POLARSSL_VERSION_C - -/* - * Enable the prime-number generation code. - */ -#define POLARSSL_GENPRIME - -/* - * Uncomment this macro to store the AES tables in ROM. - * -#define POLARSSL_AES_ROM_TABLES - */ - -/* - * Module: library/aes.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * SSL_RSA_AES_128_SHA - * SSL_RSA_AES_256_SHA - * SSL_EDH_RSA_AES_256_SHA - */ -#define POLARSSL_AES_C - -/* - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * SSL_RSA_RC4_128_MD5 - * SSL_RSA_RC4_128_SHA - */ -#define POLARSSL_ARC4_C - -/* - * Module: library/base64.c - * Caller: library/x509parse.c - * - * This module is required for X.509 support. - */ -#define POLARSSL_BASE64_C - -/* - * Module: library/bignum.c - * Caller: library/dhm.c - * library/rsa.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for RSA and DHM support. - */ -#define POLARSSL_BIGNUM_C - -/* - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enabled the following cipher suites: - * SSL_RSA_CAMELLIA_128_SHA - * SSL_RSA_CAMELLIA_256_SHA - * SSL_EDH_RSA_CAMELLIA_256_SHA - */ -#define POLARSSL_CAMELLIA_C - -/* - * Module: library/certs.c - * Caller: - * - * This module is used for testing (ssl_client/server). - */ -#define POLARSSL_CERTS_C - -/* - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define POLARSSL_DEBUG_C - -/* - * Module: library/des.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * SSL_RSA_DES_168_SHA - * SSL_EDH_RSA_DES_168_SHA - */ -#define POLARSSL_DES_C - -/* - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module enables the following ciphersuites: - * SSL_EDH_RSA_DES_168_SHA - * SSL_EDH_RSA_AES_256_SHA - * SSL_EDH_RSA_CAMELLIA_256_SHA - */ -#define POLARSSL_DHM_C - -/* - * Module: library/havege.c - * Caller: - * - * This module enables the HAVEGE random number generator. - */ -#define POLARSSL_HAVEGE_C - -/* - * Module: library/md2.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - * -#define POLARSSL_MD2_C - */ - -/* - * Module: library/md4.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - * -#define POLARSSL_MD4_C - */ - -/* - * Module: library/md5.c - * Caller: library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and X.509. - */ -#define POLARSSL_MD5_C - -/* - * Module: library/net.c - * Caller: - * - * This module provides TCP/IP networking routines. - */ -#define POLARSSL_NET_C - -/* - * Module: library/padlock.c - * Caller: library/aes.c - * - * This modules adds support for the VIA PadLock on x86. - */ -#define POLARSSL_PADLOCK_C - -/* - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is required for SSL/TLS and MD5-signed certificates. - */ -#define POLARSSL_RSA_C - -/* - * Module: library/sha1.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/* - * Module: library/sha2.c - * Caller: - * - * This module adds support for SHA-224 and SHA-256. - */ -#define POLARSSL_SHA2_C - -/* - * Module: library/sha4.c - * Caller: - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA4_C - -/* - * Module: library/ssl_cli.c - * Caller: - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/* - * Module: library/ssl_srv.c - * Caller: - * - * This module is required for SSL/TLS server support. - */ -#define POLARSSL_SSL_SRV_C - -/* - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/* - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -#define POLARSSL_TIMING_C - -/* - * Module: library/x509parse.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_PARSE_C - -/* - * Module: library/x509_write.c - * Caller: - * - * This module is required for X.509 certificate writing. - */ -#define POLARSSL_X509_WRITE_C - -/* - * Module: library/xtea.c - * Caller: - */ -#define POLARSSL_XTEA_C - -#endif /* config.h */ diff --git a/ctrtool/polarssl/padlock.h b/ctrtool/polarssl/padlock.h deleted file mode 100644 index 12fa7d3..0000000 --- a/ctrtool/polarssl/padlock.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * \file padlock.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_PADLOCK_H -#define POLARSSL_PADLOCK_H - -#include "polarssl/aes.h" - -#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) - -#ifndef POLARSSL_HAVE_X86 -#define POLARSSL_HAVE_X86 -#endif - -#define PADLOCK_RNG 0x000C -#define PADLOCK_ACE 0x00C0 -#define PADLOCK_PHE 0x0C00 -#define PADLOCK_PMM 0x3000 - -#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15)) - -#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x08E0 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PadLock detection routine - * - * \param The feature to detect - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int padlock_supports( int feature ); - -/** - * \brief PadLock AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if success, 1 if operation failed - */ -int padlock_xcryptecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief PadLock AES-CBC buffer en(de)cryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if success, 1 if operation failed - */ -int padlock_xcryptcbc( aes_context *ctx, - int mode, - int length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_X86 */ - -#endif /* padlock.h */ diff --git a/ctrtool/polarssl/rsa.c b/ctrtool/polarssl/rsa.c deleted file mode 100644 index 77404fc..0000000 --- a/ctrtool/polarssl/rsa.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * The RSA public-key cryptosystem - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. - * - * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf - * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_RSA_C) - -#include "polarssl/rsa.h" - -#include -#include -#include - -/* - * Initialize an RSA context - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id ) -{ - memset( ctx, 0, sizeof( rsa_context ) ); - - ctx->padding = padding; - ctx->hash_id = hash_id; -} - -#if defined(POLARSSL_GENPRIME) - -/* - * Generate an RSA keypair - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *), - void *p_rng, - int nbits, int exponent ) -{ - int ret; - mpi P1, Q1, H, G; - - if( f_rng == NULL || nbits < 128 || exponent < 3 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - mpi_init( &P1, &Q1, &H, &G, NULL ); - - /* - * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 - */ - MPI_CHK( mpi_lset( &ctx->E, exponent ) ); - - do - { - MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mpi_swap( &ctx->P, &ctx->Q ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) - continue; - - MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mpi_msb( &ctx->N ) != nbits ) - continue; - - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mpi_cmp_int( &G, 1 ) != 0 ); - - /* - * D = E^-1 mod ((P-1)*(Q-1)) - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); - - ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; - -cleanup: - - mpi_free( &G, &H, &Q1, &P1, NULL ); - - if( ret != 0 ) - { - rsa_free( ctx ); - return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret ); - } - - return( 0 ); -} - -#endif - -/* - * Check a public RSA key - */ -int rsa_check_pubkey( const rsa_context *ctx ) -{ - if( !ctx->N.p || !ctx->E.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->N ) < 128 || - mpi_msb( &ctx->N ) > 4096 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->E ) < 2 || - mpi_msb( &ctx->E ) > 64 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - return( 0 ); -} - -/* - * Check a private RSA key - */ -int rsa_check_privkey( const rsa_context *ctx ) -{ - int ret; - mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2; - - if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, &G2, &L1, &L2, NULL ); - - MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - - MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); - MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); - - /* - * Check for a valid PKCS1v2 private key - */ - if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 && - mpi_cmp_int( &L2, 0 ) == 0 && - mpi_cmp_int( &I, 1 ) == 0 && - mpi_cmp_int( &G, 1 ) == 0 ) - { - mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL ); - return( 0 ); - } - - -cleanup: - - mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL ); - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret ); -} - -/* - * Do an RSA public key operation - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret, olen; - mpi T; - - mpi_init( &T, NULL ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T, NULL ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - olen = ctx->len; - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T, NULL ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret ); - - return( 0 ); -} - -/* - * Do an RSA private key operation - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret, olen; - mpi T, T1, T2; - - mpi_init( &T, &T1, &T2, NULL ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T, NULL ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - -#if 0 - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); -#else - /* - * faster decryption using the CRT - * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q - */ - MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); - - /* - * T = (T1 - T2) * (Q^-1 mod P) mod P - */ - MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); - - /* - * output = T2 + T * Q - */ - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); -#endif - - olen = ctx->len; - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T, &T1, &T2, NULL ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret ); - - return( 0 ); -} - -/* - * Add the message padding, then do an RSA operation - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *), - void *p_rng, - int mode, int ilen, - const unsigned char *input, - unsigned char *output ) -{ - int nb_pad, olen; - unsigned char *p = output; - - olen = ctx->len; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( ilen < 0 || olen < ilen + 11 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad = olen - 3 - ilen; - - *p++ = 0; - *p++ = RSA_CRYPT; - - while( nb_pad-- > 0 ) - { - int rng_dl = 100; - - do { - *p = (unsigned char) f_rng( p_rng ); - } while( *p == 0 && --rng_dl ); - - // Check if RNG failed to generate data - // - if( rng_dl == 0 ) - return POLARSSL_ERR_RSA_RNG_FAILED; - - p++; - } - *p++ = 0; - memcpy( p, input, ilen ); - break; - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, output, output ) - : rsa_private( ctx, output, output ) ); -} - -/* - * Do an RSA operation, then remove the message padding - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, int *olen, - const unsigned char *input, - unsigned char *output, - int output_max_len) -{ - int ret, ilen; - unsigned char *p; - unsigned char buf[1024]; - - ilen = ctx->len; - - if( ilen < 16 || ilen > (int) sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, input, buf ) - : rsa_private( ctx, input, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( *p++ != 0 || *p++ != RSA_CRYPT ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + ilen - 1 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - break; - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - if (ilen - (int)(p - buf) > output_max_len) - return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (int)(p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} - -/* - * Do an RSA operation to sign the message digest - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int mode, - int hash_id, - int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - int nb_pad, olen; - unsigned char *p = sig; - - olen = ctx->len; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - switch( hash_id ) - { - case SIG_RSA_RAW: - nb_pad = olen - 3 - hashlen; - break; - - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - nb_pad = olen - 3 - 34; - break; - - case SIG_RSA_SHA1: - nb_pad = olen - 3 - 35; - break; - - case SIG_RSA_SHA224: - nb_pad = olen - 3 - 47; - break; - - case SIG_RSA_SHA256: - nb_pad = olen - 3 - 51; - break; - - case SIG_RSA_SHA384: - nb_pad = olen - 3 - 67; - break; - - case SIG_RSA_SHA512: - nb_pad = olen - 3 - 83; - break; - - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - if( nb_pad < 8 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - break; - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - switch( hash_id ) - { - case SIG_RSA_RAW: - memcpy( p, hash, hashlen ); - break; - - case SIG_RSA_MD2: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 2; break; - - case SIG_RSA_MD4: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 4; break; - - case SIG_RSA_MD5: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 5; break; - - case SIG_RSA_SHA1: - memcpy( p, ASN1_HASH_SHA1, 15 ); - memcpy( p + 15, hash, 20 ); - break; - - case SIG_RSA_SHA224: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 28 ); - p[1] += 28; p[14] = 4; p[18] += 28; break; - - case SIG_RSA_SHA256: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 32 ); - p[1] += 32; p[14] = 1; p[18] += 32; break; - - case SIG_RSA_SHA384: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 48 ); - p[1] += 48; p[14] = 2; p[18] += 48; break; - - case SIG_RSA_SHA512: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 64 ); - p[1] += 64; p[14] = 3; p[18] += 64; break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, sig ) - : rsa_private( ctx, sig, sig ) ); -} - -/* - * Do an RSA operation and check the message digest - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - int ret, len, siglen; - unsigned char *p, c; - unsigned char buf[1024]; - - siglen = ctx->len; - - if( siglen < 16 || siglen > (int) sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, buf ) - : rsa_private( ctx, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - switch( ctx->padding ) - { - case RSA_PKCS_V15: - - if( *p++ != 0 || *p++ != RSA_SIGN ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - break; - - default: - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - len = siglen - (int)( p - buf ); - - if( len == 34 ) - { - c = p[13]; - p[13] = 0; - - if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - - if( ( c == 2 && hash_id == SIG_RSA_MD2 ) || - ( c == 4 && hash_id == SIG_RSA_MD4 ) || - ( c == 5 && hash_id == SIG_RSA_MD5 ) ) - { - if( memcmp( p + 18, hash, 16 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - } - - if( len == 35 && hash_id == SIG_RSA_SHA1 ) - { - if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && - memcmp( p + 15, hash, 20 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || - ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || - ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || - ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) - { - c = p[1] - 17; - p[1] = 17; - p[14] = 0; - - if( p[18] == c && - memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && - memcmp( p + 19, hash, c ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - if( len == hashlen && hash_id == SIG_RSA_RAW ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); -} - -/* - * Free the components of an RSA key - */ -void rsa_free( rsa_context *ctx ) -{ - mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN, - &ctx->QP, &ctx->DQ, &ctx->DP, - &ctx->Q, &ctx->P, &ctx->D, - &ctx->E, &ctx->N, NULL ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include "polarssl/sha1.h" - -/* - * Example RSA-1024 keypair, for test purposes - */ -#define KEY_LEN 128 - -#define RSA_N "9292758453063D803DD603D5E777D788" \ - "8ED1D5BF35786190FA2F23EBC0848AEA" \ - "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ - "7130B9CED7ACDF54CFC7555AC14EEBAB" \ - "93A89813FBF3C4F8066D2D800F7C38A8" \ - "1AE31942917403FF4946B0A83D3D3E05" \ - "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ - "5E94BB77B07507233A0BC7BAC8F90F79" - -#define RSA_E "10001" - -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - -#define PT_LEN 24 -#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ - "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" - -static int myrand( void *rng_state ) -{ - if( rng_state != NULL ) - rng_state = NULL; - - return( rand() ); -} - -/* - * Checkup routine - */ -int rsa_self_test( int verbose ) -{ - int len; - rsa_context rsa; - unsigned char sha1sum[20]; - unsigned char rsa_plaintext[PT_LEN]; - unsigned char rsa_decrypted[PT_LEN]; - unsigned char rsa_ciphertext[KEY_LEN]; - - rsa_init( &rsa, RSA_PKCS_V15, 0 ); - - rsa.len = KEY_LEN; - mpi_read_string( &rsa.N , 16, RSA_N ); - mpi_read_string( &rsa.E , 16, RSA_E ); - mpi_read_string( &rsa.D , 16, RSA_D ); - mpi_read_string( &rsa.P , 16, RSA_P ); - mpi_read_string( &rsa.Q , 16, RSA_Q ); - mpi_read_string( &rsa.DP, 16, RSA_DP ); - mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mpi_read_string( &rsa.QP, 16, RSA_QP ); - - if( verbose != 0 ) - printf( " RSA key validation: " ); - - if( rsa_check_pubkey( &rsa ) != 0 || - rsa_check_privkey( &rsa ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 encryption : " ); - - memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - - if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 decryption : " ); - - if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 data sign : " ); - - sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 sig. verify: " ); - - if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n\n" ); - - rsa_free( &rsa ); - - return( 0 ); -} - -#endif - -#endif diff --git a/ctrtool/polarssl/rsa.h b/ctrtool/polarssl/rsa.h deleted file mode 100644 index 5fae794..0000000 --- a/ctrtool/polarssl/rsa.h +++ /dev/null @@ -1,353 +0,0 @@ -/** - * \file rsa.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_RSA_H -#define POLARSSL_RSA_H - -#include "polarssl/bignum.h" - -/* - * RSA Error codes - */ -#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x0400 -#define POLARSSL_ERR_RSA_INVALID_PADDING -0x0410 -#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x0420 -#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430 -#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440 -#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450 -#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460 -#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x0470 -#define POLARSSL_ERR_RSA_RNG_FAILED -0x0480 - -/* - * PKCS#1 constants - */ -#define SIG_RSA_RAW 0 -#define SIG_RSA_MD2 2 -#define SIG_RSA_MD4 3 -#define SIG_RSA_MD5 4 -#define SIG_RSA_SHA1 5 -#define SIG_RSA_SHA224 14 -#define SIG_RSA_SHA256 11 -#define SIG_RSA_SHA384 12 -#define SIG_RSA_SHA512 13 - -#define RSA_PUBLIC 0 -#define RSA_PRIVATE 1 - -#define RSA_PKCS_V15 0 -#define RSA_PKCS_V21 1 - -#define RSA_SIGN 1 -#define RSA_CRYPT 2 - -#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30" -#define ASN1_STR_NULL "\x05" -#define ASN1_STR_OID "\x06" -#define ASN1_STR_OCTET_STRING "\x04" - -#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00" -#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a" -#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00" - -#define OID_ISO_MEMBER_BODIES "\x2a" -#define OID_ISO_IDENTIFIED_ORG "\x2b" - -/* - * ISO Member bodies OID parts - */ -#define OID_COUNTRY_US "\x86\x48" -#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d" - -/* - * ISO Identified organization OID parts - */ -#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a" - -/* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ -#define ASN1_HASH_MDX \ -( \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \ - ASN1_STR_OID "\x08" \ - OID_DIGEST_ALG_MDX \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x10" \ -) - -#define ASN1_HASH_SHA1 \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \ - ASN1_STR_OID "\x05" \ - OID_HASH_ALG_SHA1 \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x14" - -#define ASN1_HASH_SHA2X \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \ - ASN1_STR_OID "\x09" \ - OID_HASH_ALG_SHA2X \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x00" - -/** - * \brief RSA context structure - */ -typedef struct -{ - int ver; /*!< always 0 */ - int len; /*!< size(N) in chars */ - - mpi N; /*!< public modulus */ - mpi E; /*!< public exponent */ - - mpi D; /*!< private exponent */ - mpi P; /*!< 1st prime factor */ - mpi Q; /*!< 2nd prime factor */ - mpi DP; /*!< D % (P - 1) */ - mpi DQ; /*!< D % (Q - 1) */ - mpi QP; /*!< 1 / (Q % P) */ - - mpi RN; /*!< cached R^2 mod N */ - mpi RP; /*!< cached R^2 mod P */ - mpi RQ; /*!< cached R^2 mod Q */ - - int padding; /*!< 1.5 or OAEP/PSS */ - int hash_id; /*!< hash identifier */ -} -rsa_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize an RSA context - * - * \param ctx RSA context to be initialized - * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 - * \param hash_id RSA_PKCS_V21 hash identifier - * - * \note The hash_id parameter is actually ignored - * when using RSA_PKCS_V15 padding. - * - * \note Currently, RSA_PKCS_V21 padding - * is not supported. - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id); - -/** - * \brief Generate an RSA keypair - * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) - * - * \note rsa_init() must be called beforehand to setup - * the RSA context. - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *), - void *p_rng, - int nbits, int exponent ); - -/** - * \brief Check a public RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_pubkey( const rsa_context *ctx ); - -/** - * \brief Check a private RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_privkey( const rsa_context *ctx ); - -/** - * \brief Do an RSA public key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or assure that - * input is smaller than N. - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA private key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Add the message padding, then do an RSA operation - * - * \param ctx RSA context - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *), - void *p_rng, - int mode, int ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA operation, then remove the message padding - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param olen will contain the plaintext length - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, int *olen, - const unsigned char *input, - unsigned char *output, - int output_max_len ); - -/** - * \brief Do a private RSA to sign a message digest - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int mode, - int hash_id, - int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Do a public RSA and check the message digest - * - * \param ctx points to an RSA public key - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Free the components of an RSA key - * - * \param ctx RSA Context to free - */ -void rsa_free( rsa_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int rsa_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* rsa.h */ diff --git a/ctrtool/polarssl/sha2.c b/ctrtool/polarssl/sha2.c deleted file mode 100644 index dd5ae98..0000000 --- a/ctrtool/polarssl/sha2.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-256 implementation - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * The SHA-256 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#include "polarssl/config.h" - -#if defined(POLARSSL_SHA2_C) - -#include "polarssl/sha2.h" - -#include -#include - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-256 context setup - */ -void sha2_starts( sha2_context *ctx, int is224 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is224 == 0 ) - { - /* SHA-256 */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; - } - else - { - /* SHA-224 */ - ctx->state[0] = 0xC1059ED8; - ctx->state[1] = 0x367CD507; - ctx->state[2] = 0x3070DD17; - ctx->state[3] = 0xF70E5939; - ctx->state[4] = 0xFFC00B31; - ctx->state[5] = 0x68581511; - ctx->state[6] = 0x64F98FA7; - ctx->state[7] = 0xBEFA4FA4; - } - - ctx->is224 = is224; -} - -static void sha2_process( sha2_context *ctx, const unsigned char data[64] ) -{ - unsigned long temp1, temp2, W[64]; - unsigned long A, B, C, D, E, F, G, H; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - - P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); - P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); - P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); - P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); - P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); - P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); - P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); - P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); - P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); - P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); - P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); - P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); - P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); - P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); - P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); - P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); - P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); - P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); - P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); - P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); - P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); - P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); - P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); - P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); - P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); - P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); - P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); - P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); - P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); - P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); - P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); - P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); - P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); - P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); - P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); - P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); - P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); - P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); - P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); - P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); - P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); - P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); - P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); - P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); - P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); - P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); - P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); - P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); - P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); - P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); - P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); - P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); - P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); - P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); - P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); - P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); - P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); - P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); - P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); - P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); - P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); - P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); - P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); - P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -/* - * SHA-256 process buffer - */ -void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - sha2_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - sha2_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char sha2_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-256 final digest - */ -void sha2_finish( sha2_context *ctx, unsigned char output[32] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha2_update( ctx, (unsigned char *) sha2_padding, padn ); - sha2_update( ctx, msglen, 8 ); - - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); - PUT_ULONG_BE( ctx->state[5], output, 20 ); - PUT_ULONG_BE( ctx->state[6], output, 24 ); - - if( ctx->is224 == 0 ) - PUT_ULONG_BE( ctx->state[7], output, 28 ); -} - -/* - * output = SHA-256( input buffer ) - */ -void sha2( const unsigned char *input, int ilen, - unsigned char output[32], int is224 ) -{ - sha2_context ctx; - - sha2_starts( &ctx, is224 ); - sha2_update( &ctx, input, ilen ); - sha2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); -} - -/* - * output = SHA-256( file contents ) - */ -int sha2_file( const char *path, unsigned char output[32], int is224 ) -{ - FILE *f; - size_t n; - sha2_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( 1 ); - - sha2_starts( &ctx, is224 ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - sha2_update( &ctx, buf, (int) n ); - - sha2_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( 2 ); - } - - fclose( f ); - return( 0 ); -} - -/* - * SHA-256 HMAC context setup - */ -void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen, - int is224 ) -{ - int i; - unsigned char sum[32]; - - if( keylen > 64 ) - { - sha2( key, keylen, sum, is224 ); - keylen = ( is224 ) ? 28 : 32; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - sha2_starts( ctx, is224 ); - sha2_update( ctx, ctx->ipad, 64 ); - - memset( sum, 0, sizeof( sum ) ); -} - -/* - * SHA-256 HMAC process buffer - */ -void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen ) -{ - sha2_update( ctx, input, ilen ); -} - -/* - * SHA-256 HMAC final digest - */ -void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ) -{ - int is224, hlen; - unsigned char tmpbuf[32]; - - is224 = ctx->is224; - hlen = ( is224 == 0 ) ? 32 : 28; - - sha2_finish( ctx, tmpbuf ); - sha2_starts( ctx, is224 ); - sha2_update( ctx, ctx->opad, 64 ); - sha2_update( ctx, tmpbuf, hlen ); - sha2_finish( ctx, output ); - - memset( tmpbuf, 0, sizeof( tmpbuf ) ); -} - -/* - * SHA-256 HMAC context reset - */ -void sha2_hmac_reset( sha2_context *ctx ) -{ - sha2_starts( ctx, ctx->is224 ); - sha2_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-SHA-256( hmac key, input buffer ) - */ -void sha2_hmac( const unsigned char *key, int keylen, - const unsigned char *input, int ilen, - unsigned char output[32], int is224 ) -{ - sha2_context ctx; - - sha2_hmac_starts( &ctx, key, keylen, is224 ); - sha2_hmac_update( &ctx, input, ilen ); - sha2_hmac_finish( &ctx, output ); - - memset( &ctx, 0, sizeof( sha2_context ) ); -} - -#if defined(POLARSSL_SELF_TEST) -/* - * FIPS-180-2 test vectors - */ -static unsigned char sha2_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha2_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha2_test_sum[6][32] = -{ - /* - * SHA-224 test vectors - */ - { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, - 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, - 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, - 0xE3, 0x6C, 0x9D, 0xA7 }, - { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, - 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, - 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, - 0x52, 0x52, 0x25, 0x25 }, - { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, - 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, - 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, - 0x4E, 0xE7, 0xAD, 0x67 }, - - /* - * SHA-256 test vectors - */ - { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, - 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, - 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, - 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, - { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, - 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, - 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, - 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, - { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, - 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, - 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, - 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } -}; - -/* - * RFC 4231 test vectors - */ -static unsigned char sha2_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 131 times */ - { "" } -}; - -static const int sha2_hmac_test_keylen[7] = -{ - 20, 4, 20, 25, 20, 131, 131 -}; - -static unsigned char sha2_hmac_test_buf[7][153] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "This is a test using a larger than block-size key " - "and a larger than block-size data. The key needs to " - "be hashed before being used by the HMAC algorithm." } -}; - -static const int sha2_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 152 -}; - -static const unsigned char sha2_hmac_test_sum[14][32] = -{ - /* - * HMAC-SHA-224 test vectors - */ - { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, - 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, - 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, - 0x53, 0x68, 0x4B, 0x22 }, - { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, - 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, - 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, - 0x8F, 0xD0, 0x5E, 0x44 }, - { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, - 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, - 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, - 0xEC, 0x83, 0x33, 0xEA }, - { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, - 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, - 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, - 0xE7, 0xAF, 0xEC, 0x5A }, - { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, - 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, - { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, - 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, - 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, - 0x3F, 0xA6, 0x87, 0x0E }, - { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, - 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, - 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, - 0xF6, 0xF5, 0x65, 0xD1 }, - - /* - * HMAC-SHA-256 test vectors - */ - { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, - 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, - 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, - 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, - { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, - 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, - 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, - 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, - { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, - 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, - 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, - 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, - { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, - 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, - 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, - 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, - { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, - 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, - { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, - 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, - 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, - 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, - { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, - 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, - 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, - 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } -}; - -/* - * Checkup routine - */ -int sha2_self_test( int verbose ) -{ - int i, j, k, buflen; - unsigned char buf[1024]; - unsigned char sha2sum[32]; - sha2_context ctx; - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - sha2_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - sha2_update( &ctx, buf, buflen ); - } - else - sha2_update( &ctx, sha2_test_buf[j], - sha2_test_buflen[j] ); - - sha2_finish( &ctx, sha2sum ); - - if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - for( i = 0; i < 14; i++ ) - { - j = i % 7; - k = i < 7; - - if( verbose != 0 ) - printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - if( j == 5 || j == 6 ) - { - memset( buf, '\xAA', buflen = 131 ); - sha2_hmac_starts( &ctx, buf, buflen, k ); - } - else - sha2_hmac_starts( &ctx, sha2_hmac_test_key[j], - sha2_hmac_test_keylen[j], k ); - - sha2_hmac_update( &ctx, sha2_hmac_test_buf[j], - sha2_hmac_test_buflen[j] ); - - sha2_hmac_finish( &ctx, sha2sum ); - - buflen = ( j == 4 ) ? 16 : 32 - k * 4; - - if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - } - - if( verbose != 0 ) - printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/ctrtool/polarssl/sha2.h b/ctrtool/polarssl/sha2.h deleted file mode 100644 index be4ae56..0000000 --- a/ctrtool/polarssl/sha2.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * \file sha2.h - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SHA2_H -#define POLARSSL_SHA2_H - -/** - * \brief SHA-256 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ - int is224; /*!< 0 => SHA-256, else SHA-224 */ -} -sha2_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_starts( sha2_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void sha2_finish( sha2_context *ctx, unsigned char output[32] ); - -/** - * \brief Output = SHA-256( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2( const unsigned char *input, int ilen, - unsigned char output[32], int is224 ); - -/** - * \brief Output = SHA-256( file contents ) - * - * \param path input file name - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - * - * \return 0 if successful, 1 if fopen failed, - * or 2 if fread failed - */ -int sha2_file( const char *path, unsigned char output[32], int is224 ); - -/** - * \brief SHA-256 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen, - int is224 ); - -/** - * \brief SHA-256 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief SHA-256 HMAC final digest - * - * \param ctx HMAC context - * \param output SHA-224/256 HMAC checksum result - */ -void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ); - -/** - * \brief SHA-256 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void sha2_hmac_reset( sha2_context *ctx ); - -/** - * \brief Output = HMAC-SHA-256( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-SHA-224/256 result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void sha2_hmac( const unsigned char *key, int keylen, - const unsigned char *input, int ilen, - unsigned char output[32], int is224 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int sha2_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* sha2.h */ diff --git a/ctrtool/romfs.c b/ctrtool/romfs.c deleted file mode 100644 index 6f00467..0000000 --- a/ctrtool/romfs.c +++ /dev/null @@ -1,406 +0,0 @@ -#include -#include -#include "types.h" -#include "romfs.h" -#include "utils.h" - -void romfs_init(romfs_context* ctx) -{ - memset(ctx, 0, sizeof(romfs_context)); - ivfc_init(&ctx->ivfc); -} - -void romfs_set_file(romfs_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void romfs_set_offset(romfs_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void romfs_set_size(romfs_context* ctx, u64 size) -{ - ctx->size = size; -} - -void romfs_set_usersettings(romfs_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void romfs_set_encrypted(romfs_context* ctx, u32 encrypted) -{ - ctx->encrypted = encrypted; -} - -void romfs_set_key(romfs_context* ctx, u8 key[16]) -{ - memcpy(ctx->key, key, 16); - ctr_init_key(&ctx->aes, key); -} - -void romfs_set_counter(romfs_context* ctx, u8 counter[16]) -{ - memcpy(ctx->counter, counter, 16); -} - -void romfs_fseek(romfs_context* ctx, u64 offset) -{ - u64 data_pos = offset - ctx->offset; - fseeko64(ctx->file, offset, SEEK_SET); - - if (ctx->encrypted) { - ctr_init_counter(&ctx->aes, ctx->counter); - ctr_add_counter(&ctx->aes, (u32)(data_pos / 0x10)); - } -} - -size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count) -{ - size_t read; - if ((read = fread(buffer, size, count, ctx->file)) != count) { - //printf("romfs_fread() fail\n"); - return read; - } - if (ctx->encrypted) { - ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read); - } - return read; -} - -void romfs_process(romfs_context* ctx, u32 actions) -{ - u32 dirblockoffset = 0; - u32 dirblocksize = 0; - u32 fileblockoffset = 0; - u32 fileblocksize = 0; - - ivfc_set_offset(&ctx->ivfc, ctx->offset); - ivfc_set_size(&ctx->ivfc, ctx->size); - ivfc_set_file(&ctx->ivfc, ctx->file); - ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings); - ivfc_set_counter(&ctx->ivfc, ctx->counter); - ivfc_set_key(&ctx->ivfc, ctx->key); - ivfc_set_encrypted(&ctx->ivfc, ctx->encrypted); - ivfc_process(&ctx->ivfc, actions); - - romfs_fseek(ctx, ctx->offset); - romfs_fread(ctx, &ctx->header, 1, sizeof(romfs_header)); - - if (getle32(ctx->header.magic) != MAGIC_IVFC) - { - fprintf(stdout, "Error, RomFS corrupted\n"); - return; - } - - ctx->infoblockoffset = (u32) (ctx->offset + 0x1000); - - romfs_fseek(ctx, ctx->infoblockoffset); - romfs_fread(ctx, &ctx->infoheader, 1, sizeof(romfs_infoheader)); - - if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader)) - { - fprintf(stderr, "Error, info header mismatch\n"); - return; - } - - dirblockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.section[1].offset); - dirblocksize = getle32(ctx->infoheader.section[1].size); - fileblockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.section[3].offset); - fileblocksize = getle32(ctx->infoheader.section[3].size); - - u32 hdrsize = getle32(ctx->infoheader.dataoffset); - u8 *block = malloc(hdrsize); - romfs_fseek(ctx, ctx->infoblockoffset); - romfs_fread(ctx, block, hdrsize, 1); - - ctx->dirblock = malloc(dirblocksize); - ctx->dirblocksize = dirblocksize; - if(ctx->dirblock) - memcpy(ctx->dirblock, block + getle32(ctx->infoheader.section[1].offset), dirblocksize); - - ctx->fileblock = malloc(fileblocksize); - ctx->fileblocksize = fileblocksize; - if (ctx->fileblock) - memcpy(ctx->fileblock, block + getle32(ctx->infoheader.section[3].offset), fileblocksize); - - free(block); - - ctx->datablockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.dataoffset); - - if (actions & InfoFlag) - romfs_print(ctx); - - if (settings_get_romfs_dir_path(ctx->usersettings)->valid) - ctx->extractdir = os_CopyConvertCharStr(settings_get_romfs_dir_path(ctx->usersettings)->pathname); - else - ctx->extractdir = NULL; - - romfs_visit_dir(ctx, 0, 0, actions, ctx->extractdir); - free(ctx->extractdir); -} - -int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer) -{ - if (!ctx->dirblock) - return 0; - - if (diroffset+dirsize > ctx->dirblocksize) - return 0; - - memcpy(buffer, ctx->dirblock + diroffset, dirsize); - return 1; -} - -int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry) -{ - u32 size_without_name = sizeof(romfs_direntry) - ROMFS_MAXNAMESIZE; - u32 namesize; - - - if (!ctx->dirblock) - return 0; - - if (!romfs_dirblock_read(ctx, diroffset, size_without_name, entry)) - return 0; - - namesize = getle32(entry->namesize); - if (namesize > (ROMFS_MAXNAMESIZE-2)) - namesize = (ROMFS_MAXNAMESIZE-2); - memset(entry->name + namesize, 0, 2); - if (!romfs_dirblock_read(ctx, diroffset + size_without_name, namesize, entry->name)) - return 0; - - return 1; -} - - -int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer) -{ - if (!ctx->fileblock) - return 0; - - if (fileoffset+filesize > ctx->fileblocksize) - return 0; - - memcpy(buffer, ctx->fileblock + fileoffset, filesize); - return 1; -} - -int romfs_fileblock_readentry(romfs_context* ctx, u32 fileoffset, romfs_fileentry* entry) -{ - u32 size_without_name = sizeof(romfs_fileentry) - ROMFS_MAXNAMESIZE; - u32 namesize; - - - if (!ctx->fileblock) - return 0; - - if (!romfs_fileblock_read(ctx, fileoffset, size_without_name, entry)) - return 0; - - namesize = getle32(entry->namesize); - if (namesize > (ROMFS_MAXNAMESIZE-2)) - namesize = (ROMFS_MAXNAMESIZE-2); - memset(entry->name + namesize, 0, 2); - if (!romfs_fileblock_read(ctx, fileoffset + size_without_name, namesize, entry->name)) - return 0; - - return 1; -} - - - -void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, const oschar_t* rootpath) -{ - u32 siblingoffset; - u32 childoffset; - u32 fileoffset; - oschar_t* currentpath; - romfs_direntry* entry = &ctx->direntry; - - - if (!romfs_dirblock_readentry(ctx, diroffset, entry)) - return; - - -// fprintf(stdout, "%08X %08X %08X %08X %08X ", -// getle32(entry->parentoffset), getle32(entry->siblingoffset), getle32(entry->childoffset), -// getle32(entry->fileoffset), getle32(entry->weirdoffset)); -// fwprintf(stdout, L"%ls\n", entry->name); - - - if (rootpath && os_strlen(rootpath)) - { - if (utf16_strlen((const utf16char_t*)entry->name) > 0) - currentpath = os_AppendUTF16StrToPath(rootpath, (const utf16char_t*)entry->name); - else // root dir, use the provided extract path instead of the empty root name. - currentpath = os_CopyStr(rootpath); - - if (currentpath) - { - os_makedir(currentpath); - } - else - { - fputs("Error creating directory in root ", stderr); - os_fputs(rootpath, stderr); - fputs("\n", stderr); - return; - } - } - else - { - currentpath = os_CopyConvertUTF16Str((const utf16char_t*)entry->name); - if (settings_get_list_romfs_files(ctx->usersettings)) - { - u32 i; - - for(i=0; isiblingoffset); - childoffset = getle32(entry->childoffset); - fileoffset = getle32(entry->fileoffset); - - if (fileoffset != (~0)) - romfs_visit_file(ctx, fileoffset, depth+1, actions, currentpath); - - if (childoffset != (~0)) - romfs_visit_dir(ctx, childoffset, depth+1, actions, currentpath); - - if (siblingoffset != (~0)) - romfs_visit_dir(ctx, siblingoffset, depth, actions, rootpath); - - free(currentpath); -} - - -void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, const oschar_t* rootpath) -{ - u32 siblingoffset = 0; - oschar_t* currentpath = NULL; - romfs_fileentry* entry = &ctx->fileentry; - - - if (!romfs_fileblock_readentry(ctx, fileoffset, entry)) - return; - - -// fprintf(stdout, "%08X %08X %016llX %016llX %08X ", -// getle32(entry->parentdiroffset), getle32(entry->siblingoffset), ctx->datablockoffset+getle64(entry->dataoffset), -// getle64(entry->datasize), getle32(entry->unknown)); -// fwprintf(stdout, L"%ls\n", entry->name); - - if (rootpath && os_strlen(rootpath)) - { - currentpath = os_AppendUTF16StrToPath(rootpath, (const utf16char_t*)entry->name); - if (currentpath) - { - fputs("Saving ", stdout); - os_fputs(currentpath, stdout); - fputs("...\n", stdout); - romfs_extract_datafile(ctx, getle64(entry->dataoffset), getle64(entry->datasize), currentpath); - } - else - { - fputs("Error creating file in root ", stderr); - os_fputs(rootpath, stderr); - fputs("\n", stderr); - return; - } - } - else - { - currentpath = os_CopyConvertUTF16Str((const utf16char_t*)entry->name); - if (settings_get_list_romfs_files(ctx->usersettings)) - { - u32 i; - - for(i=0; isiblingoffset); - - if (siblingoffset != (~0)) - romfs_visit_file(ctx, siblingoffset, depth, actions, rootpath); - - free(currentpath); -} - -void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const oschar_t* path) -{ - FILE* outfile = 0; - u32 max; - u8 buffer[4096]; - - - if (path == NULL || os_strlen(path) == 0) - goto clean; - - offset += ctx->datablockoffset; - - romfs_fseek(ctx, offset); - outfile = os_fopen(path, OS_MODE_WRITE); - if (outfile == NULL) - { - fprintf(stderr, "Error opening file for writing\n"); - goto clean; - } - - while(size) - { - max = sizeof(buffer); - if (max > size) - max = (u32) size; - - if (max != romfs_fread(ctx, buffer, 1, max)) - { - fprintf(stderr, "Error reading file\n"); - goto clean; - } - - if (max != fwrite(buffer, 1, max, outfile)) - { - fprintf(stderr, "Error writing file\n"); - goto clean; - } - - size -= max; - } -clean: - if (outfile) - fclose(outfile); -} - - -void romfs_print(romfs_context* ctx) -{ - u32 i; - - fprintf(stdout, "\nRomFS:\n"); - - fprintf(stdout, "Header size: 0x%08X\n", getle32(ctx->infoheader.headersize)); - for(i=0; i<4; i++) - { - fprintf(stdout, "Section %d offset: 0x%08"PRIX64"\n", i, ctx->offset + 0x1000 + getle32(ctx->infoheader.section[i].offset)); - fprintf(stdout, "Section %d size: 0x%08X\n", i, getle32(ctx->infoheader.section[i].size)); - } - - fprintf(stdout, "Data offset: 0x%08"PRIX64"\n", ctx->offset + 0x1000 + getle32(ctx->infoheader.dataoffset)); -} diff --git a/ctrtool/romfs.h b/ctrtool/romfs.h deleted file mode 100644 index 7706be5..0000000 --- a/ctrtool/romfs.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef __ROMFS_H__ -#define __ROMFS_H__ - -#include "types.h" -#include "info.h" -#include "ctr.h" -#include "oschar.h" -#include "settings.h" -#include "ivfc.h" - -#define ROMFS_MAXNAMESIZE 254 // limit set by ctrtool - -typedef struct -{ - u8 magic[4]; -} romfs_header; - -typedef struct -{ - u8 offset[4]; - u8 size[4]; -} romfs_sectionheader; - -typedef struct -{ - u8 headersize[4]; - romfs_sectionheader section[4]; - u8 dataoffset[4]; -} romfs_infoheader; - - -typedef struct -{ - u8 parentoffset[4]; - u8 siblingoffset[4]; - u8 childoffset[4]; - u8 fileoffset[4]; - u8 weirdoffset[4]; // this one is weird. it always points to a dir entry, but seems unrelated to the romfs structure. - u8 namesize[4]; - u8 name[ROMFS_MAXNAMESIZE]; -} romfs_direntry; - -typedef struct -{ - u8 parentdiroffset[4]; - u8 siblingoffset[4]; - u8 dataoffset[8]; - u8 datasize[8]; - u8 weirdoffset[4]; // this one is also weird. it always points to a file entry, but seems unrelated to the romfs structure. - u8 namesize[4]; - u8 name[ROMFS_MAXNAMESIZE]; -} romfs_fileentry; - - -typedef struct -{ - FILE* file; - oschar_t* extractdir; - settings* usersettings; - u8 counter[16]; - u8 key[16]; - u64 offset; - u64 size; - romfs_header header; - romfs_infoheader infoheader; - u8* dirblock; - u32 dirblocksize; - u8* fileblock; - u32 fileblocksize; - u32 datablockoffset; - u32 infoblockoffset; - romfs_direntry direntry; - romfs_fileentry fileentry; - ivfc_context ivfc; - ctr_aes_context aes; - int encrypted; -} romfs_context; - -void romfs_init(romfs_context* ctx); -void romfs_set_file(romfs_context* ctx, FILE* file); -void romfs_set_offset(romfs_context* ctx, u64 offset); -void romfs_set_size(romfs_context* ctx, u64 size); -void romfs_set_usersettings(romfs_context* ctx, settings* usersettings); -void romfs_set_encrypted(romfs_context* ctx, u32 encrypted); -void romfs_set_key(romfs_context* ctx, u8 key[16]); -void romfs_set_counter(romfs_context* ctx, u8 counter[16]); -void romfs_fseek(romfs_context* ctx, u64 offset); -size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count); -int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer); -int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry); -int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer); -int romfs_fileblock_readentry(romfs_context* ctx, u32 fileoffset, romfs_fileentry* entry); -void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, const oschar_t* rootpath); -void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, const oschar_t* rootpath); -void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const oschar_t* path); -void romfs_process(romfs_context* ctx, u32 actions); -void romfs_print(romfs_context* ctx); - -#endif // __ROMFS_H__ diff --git a/ctrtool/settings.c b/ctrtool/settings.c deleted file mode 100644 index 9fbf056..0000000 --- a/ctrtool/settings.c +++ /dev/null @@ -1,314 +0,0 @@ -#include -#include -#include "settings.h" - -void settings_init(settings* usersettings) -{ - memset(usersettings, 0, sizeof(settings)); -} - -filepath* settings_get_wav_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->wavpath; - else - return 0; -} - -filepath* settings_get_lzss_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->lzsspath; - else - return 0; -} - -filepath* settings_get_exefs_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->exefspath; - else - return 0; -} - -filepath* settings_get_romfs_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->romfspath; - else - return 0; -} - -filepath* settings_get_exheader_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->exheaderpath; - else - return 0; -} - -filepath* settings_get_logo_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->logopath; - else - return 0; -} - -filepath* settings_get_exefs_dir_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->exefsdirpath; - else - return 0; -} - -filepath* settings_get_romfs_dir_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->romfsdirpath; - else - return 0; -} - -filepath* settings_get_firm_dir_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->firmdirpath; - else - return 0; -} - - -filepath* settings_get_certs_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->certspath; - else - return 0; -} - -filepath* settings_get_tik_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->tikpath; - else - return 0; -} - -filepath* settings_get_tmd_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->tmdpath; - else - return 0; -} - -filepath* settings_get_content_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->contentpath; - else - return 0; -} - -filepath* settings_get_meta_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->metapath; - else - return 0; -} - -filepath* settings_get_plainrgn_path(settings* usersettings) -{ - if (usersettings) - return &usersettings->plainrgnpath; - else - return 0; -} - -unsigned int settings_get_mediaunit_size(settings* usersettings) -{ - if (usersettings) - return usersettings->mediaunitsize; - else - return 0; -} - -#define GETKEY(s, k) do {\ - if ((s) && (s)->keys.k.valid)\ - return (s)->keys.k.data;\ - else\ - return NULL;\ -} while (0) - -unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings) -{ - GETKEY(usersettings, ncchfixedsystemkey); -} - -unsigned char* settings_get_ncchkeyX_old(settings* usersettings) -{ - GETKEY(usersettings, ncchkeyX_old); -} - -unsigned char* settings_get_ncchkeyX_seven(settings* usersettings) -{ - GETKEY(usersettings, ncchkeyX_seven); -} - -unsigned char* settings_get_ncchkeyX_ninethree(settings* usersettings) -{ - GETKEY(usersettings, ncchkeyX_ninethree); -} - -unsigned char* settings_get_ncchkeyX_ninesix(settings* usersettings) -{ - GETKEY(usersettings, ncchkeyX_ninesix); -} - -unsigned char* settings_get_common_key(settings* usersettings, u8 index) -{ - if (index > (COMMONKEY_NUM - 1)) return NULL; - GETKEY(usersettings, commonkey[index]); -} - -unsigned char* settings_get_seed(settings* usersettings, u64 title_id) -{ - for (u32 i = 0; i < usersettings->keys.seed_num; i++) - { - if (title_id == getle64(usersettings->keys.seed_db[i].title_id)) - { - return usersettings->keys.seed_db[i].seed; - } - } - GETKEY(usersettings, seed_fallback); -} - -unsigned char* settings_get_title_key(settings* usersettings) -{ - GETKEY(usersettings, titlekey); -} - -#undef GETKEY - -int settings_get_ignore_programid(settings* usersettings) -{ - if (usersettings) - return usersettings->ignoreprogramid; - else - return 0; -} - -int settings_get_list_romfs_files(settings* usersettings) -{ - if (usersettings) - return usersettings->listromfs; - else - return 0; -} - -int settings_get_cwav_loopcount(settings* usersettings) -{ - if (usersettings) - return usersettings->cwavloopcount; - else - return 0; -} - -void settings_set_wav_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->wavpath, path); -} - -void settings_set_lzss_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->lzsspath, path); -} - -void settings_set_exefs_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->exefspath, path); -} - -void settings_set_romfs_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->romfspath, path); -} - -void settings_set_firm_dir_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->firmdirpath, path); -} - - -void settings_set_exheader_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->exheaderpath, path); -} - -void settings_set_logo_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->logopath, path); -} - -void settings_set_certs_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->certspath, path); -} - -void settings_set_tik_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->tikpath, path); -} - -void settings_set_tmd_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->tmdpath, path); -} - -void settings_set_content_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->contentpath, path); -} - -void settings_set_meta_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->metapath, path); -} - -void settings_set_exefs_dir_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->exefsdirpath, path); -} - -void settings_set_romfs_dir_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->romfsdirpath, path); -} - -void settings_set_plainrgn_path(settings* usersettings, const char* path) -{ - filepath_set(&usersettings->plainrgnpath, path); -} - -void settings_set_mediaunit_size(settings* usersettings, unsigned int size) -{ - usersettings->mediaunitsize = size; -} - -void settings_set_ignore_programid(settings* usersettings, int enable) -{ - usersettings->ignoreprogramid = enable; -} - -void settings_set_list_romfs_files(settings* usersettings, int enable) -{ - usersettings->listromfs = enable; -} - -void settings_set_cwav_loopcount(settings* usersettings, u32 loopcount) -{ - usersettings->cwavloopcount = loopcount; -} diff --git a/ctrtool/settings.h b/ctrtool/settings.h deleted file mode 100644 index e634eaa..0000000 --- a/ctrtool/settings.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef _SETTINGS_H_ -#define _SETTINGS_H_ - -#include "types.h" -#include "keyset.h" -#include "filepath.h" - -typedef struct -{ - keyset keys; - filepath exefspath; - filepath exefsdirpath; - filepath firmdirpath; - filepath romfspath; - filepath romfsdirpath; - filepath exheaderpath; - filepath logopath; - filepath plainrgnpath; - filepath certspath; - filepath contentpath; - filepath tikpath; - filepath tmdpath; - filepath metapath; - filepath lzsspath; - filepath wavpath; - unsigned int mediaunitsize; - int ignoreprogramid; - int listromfs; - u32 cwavloopcount; -} settings; - -void settings_init(settings* usersettings); -filepath* settings_get_lzss_path(settings* usersettings); -filepath* settings_get_exefs_path(settings* usersettings); -filepath* settings_get_romfs_path(settings* usersettings); -filepath* settings_get_exheader_path(settings* usersettings); -filepath* settings_get_logo_path(settings* usersettings); -filepath* settings_get_certs_path(settings* usersettings); -filepath* settings_get_tik_path(settings* usersettings); -filepath* settings_get_tmd_path(settings* usersettings); -filepath* settings_get_content_path(settings* usersettings); -filepath* settings_get_meta_path(settings* usersettings); -filepath* settings_get_exefs_dir_path(settings* usersettings); -filepath* settings_get_romfs_dir_path(settings* usersettings); -filepath* settings_get_firm_dir_path(settings* usersettings); -filepath* settings_get_wav_path(settings* usersettings); -filepath* settings_get_plainrgn_path(settings* usersettings); -unsigned int settings_get_mediaunit_size(settings* usersettings); -unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings); -unsigned char* settings_get_ncchkeyX_old(settings* usersettings); -unsigned char* settings_get_ncchkeyX_seven(settings* usersettings); -unsigned char* settings_get_ncchkeyX_ninethree(settings* usersettings); -unsigned char* settings_get_ncchkeyX_ninesix(settings* usersettings); -unsigned char* settings_get_common_key(settings* usersettings, u8 index); -unsigned char* settings_get_seed(settings* usersettings, u64 title_id); -unsigned char* settings_get_title_key(settings* usersettings); -int settings_get_ignore_programid(settings* usersettings); -int settings_get_list_romfs_files(settings* usersettings); -int settings_get_cwav_loopcount(settings* usersettings); - -void settings_set_lzss_path(settings* usersettings, const char* path); -void settings_set_exefs_path(settings* usersettings, const char* path); -void settings_set_romfs_path(settings* usersettings, const char* path); -void settings_set_exheader_path(settings* usersettings, const char* path); -void settings_set_logo_path(settings* usersettings, const char* path); -void settings_set_certs_path(settings* usersettings, const char* path); -void settings_set_tik_path(settings* usersettings, const char* path); -void settings_set_tmd_path(settings* usersettings, const char* path); -void settings_set_content_path(settings* usersettings, const char* path); -void settings_set_meta_path(settings* usersettings, const char* path); -void settings_set_exefs_dir_path(settings* usersettings, const char* path); -void settings_set_romfs_dir_path(settings* usersettings, const char* path); -void settings_set_firm_dir_path(settings* usersettings, const char* path); -void settings_set_wav_path(settings* usersettings, const char* path); -void settings_set_plainrgn_path(settings* usersettings, const char* path); -void settings_set_mediaunit_size(settings* usersettings, unsigned int size); -void settings_set_ignore_programid(settings* usersettings, int enable); -void settings_set_list_romfs_files(settings* usersettings, int enable); -void settings_set_cwav_loopcount(settings* usersettings, u32 loopcount); - -#endif // _SETTINGS_H_ diff --git a/ctrtool/stream.c b/ctrtool/stream.c deleted file mode 100644 index dfb1ac6..0000000 --- a/ctrtool/stream.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include - - -#include "types.h" -#include "stream.h" - - -void stream_in_init(stream_in_context* ctx) -{ - memset(ctx, 0, sizeof(stream_in_context)); -} - -void stream_out_init(stream_out_context* ctx) -{ - memset(ctx, 0, sizeof(stream_out_context)); -} - -void stream_in_allocate(stream_in_context* ctx, u32 buffersize, FILE* file) -{ - ctx->inbuffer = malloc(buffersize); - ctx->inbuffersize = buffersize; - ctx->infile = file; - ctx->infileposition = 0; -} - -void stream_out_allocate(stream_out_context* ctx, u32 buffersize, FILE* file) -{ - ctx->outbuffer = malloc(buffersize); - ctx->outbuffersize = buffersize; - ctx->outfile = file; -} - -void stream_in_destroy(stream_in_context* ctx) -{ - free(ctx->inbuffer); - ctx->inbuffer = 0; -} - -void stream_out_destroy(stream_out_context* ctx) -{ - free(ctx->outbuffer); - ctx->outbuffer = 0; -} - -int stream_in_byte(stream_in_context* ctx, u8* byte) -{ - if (ctx->inbufferpos >= ctx->inbufferavailable) - { - size_t readbytes = fread(ctx->inbuffer, 1, ctx->inbuffersize, ctx->infile); - if (readbytes <= 0) - return 0; - - ctx->inbufferavailable = readbytes; - ctx->inbufferpos = 0; - ctx->infileposition += readbytes; - } - - *byte = ctx->inbuffer[ctx->inbufferpos++]; - return 1; -} - -void stream_in_seek(stream_in_context* ctx, u32 position) -{ - fseek(ctx->infile, position, SEEK_SET); - ctx->infileposition = position; - ctx->inbufferpos = 0; - ctx->inbufferavailable = 0; -} - -void stream_in_reseek(stream_in_context* ctx) -{ - fseek(ctx->infile, ctx->infileposition, SEEK_SET); -} - - -void stream_out_seek(stream_out_context* ctx, u32 position) -{ - stream_out_flush(ctx); - - fseek(ctx->outfile, position, SEEK_SET); -} - -void stream_out_skip(stream_out_context* ctx, u32 size) -{ - stream_out_flush(ctx); - - fseek(ctx->outfile, size, SEEK_CUR); -} - -int stream_out_byte(stream_out_context* ctx, u8 byte) -{ - if (ctx->outbufferpos >= ctx->outbuffersize) - { - if (stream_out_flush(ctx) == 0) - return 0; - } - - ctx->outbuffer[ctx->outbufferpos++] = byte; - return 1; -} - -int stream_out_buffer(stream_out_context* ctx, const void* buffer, u32 size) -{ - u32 i; - - for(i=0; ioutbufferpos > 0) - { - size_t writtenbytes = fwrite(ctx->outbuffer, 1, ctx->outbufferpos, ctx->outfile); - if (writtenbytes == 0) // will be zero if nothing is written - return 0; - - - ctx->outbufferpos = 0; - } - return 1; -} - -void stream_out_position(stream_out_context* ctx, u32* position) -{ - stream_out_flush(ctx); - - *position = ftell(ctx->outfile); -} - - diff --git a/ctrtool/stream.h b/ctrtool/stream.h deleted file mode 100644 index df5bcbc..0000000 --- a/ctrtool/stream.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __STREAM_H__ -#define __STREAM_H__ - -#include -#include "types.h" - -typedef struct -{ - FILE* infile; - u32 infileposition; - u8* inbuffer; - u32 inbuffersize; - u32 inbufferavailable; - u32 inbufferpos; -} stream_in_context; - -typedef struct -{ - FILE* outfile; - u8* outbuffer; - u32 outbuffersize; - u32 outbufferpos; -} stream_out_context; - -// create/destroy -void stream_in_init(stream_in_context* ctx); -void stream_in_allocate(stream_in_context* ctx, u32 buffersize, FILE* file); -void stream_in_destroy(stream_in_context* ctx); -void stream_out_init(stream_out_context* ctx); -void stream_out_allocate(stream_out_context* ctx, u32 buffersize, FILE* file); -void stream_out_destroy(stream_out_context* ctx); - -// read/write operations -int stream_in_byte(stream_in_context* ctx, u8* byte); -void stream_in_seek(stream_in_context* ctx, u32 position); -void stream_in_reseek(stream_in_context* ctx); - -int stream_out_byte(stream_out_context* ctx, u8 byte); -int stream_out_buffer(stream_out_context* ctx, const void* buffer, u32 size); -int stream_out_flush(stream_out_context* ctx); -void stream_out_seek(stream_out_context* ctx, u32 position); -void stream_out_skip(stream_out_context* ctx, u32 size); -void stream_out_position(stream_out_context* ctx, u32* position); - -#endif // __STREAM_H__ diff --git a/ctrtool/syscalls.c b/ctrtool/syscalls.c deleted file mode 100644 index f450535..0000000 --- a/ctrtool/syscalls.c +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include -#include -#include "syscalls.h" - -// List of 3DS system calls. NULL indicates unknown. -static const char *const syscall_list[NUM_SYSCALLS] = -{ - NULL, // 00 - "ControlMemory", // 01 - "QueryMemory", // 02 - "ExitProcess", // 03 - "GetProcessAffinityMask", // 04 - "SetProcessAffinityMask", // 05 - "GetProcessIdealProcessor", // 06 - "SetProcessIdealProcessor", // 07 - "CreateThread", // 08 - "ExitThread", // 09 - "SleepThread", // 0A - "GetThreadPriority", // 0B - "SetThreadPriority", // 0C - "GetThreadAffinityMask", // 0D - "SetThreadAffinityMask", // 0E - "GetThreadIdealProcessor", // 0F - "SetThreadIdealProcessor", // 10 - "GetCurrentProcessorNumber", // 11 - "Run", // 12 - "CreateMutex", // 13 - "ReleaseMutex", // 14 - "CreateSemaphore", // 15 - "ReleaseSemaphore", // 16 - "CreateEvent", // 17 - "SignalEvent", // 18 - "ClearEvent", // 19 - "CreateTimer", // 1A - "SetTimer", // 1B - "CancelTimer", // 1C - "ClearTimer", // 1D - "CreateMemoryBlock", // 1E - "MapMemoryBlock", // 1F - "UnmapMemoryBlock", // 20 - "CreateAddressArbiter", // 21 - "ArbitrateAddress", // 22 - "CloseHandle", // 23 - "WaitSynchronization1", // 24 - "WaitSynchronizationN", // 25 - "SignalAndWait", // 26 - "DuplicateHandle", // 27 - "GetSystemTick", // 28 - "GetHandleInfo", // 29 - "GetSystemInfo", // 2A - "GetProcessInfo", // 2B - "GetThreadInfo", // 2C - "ConnectToPort", // 2D - "SendSyncRequest1", // 2E - "SendSyncRequest2", // 2F - "SendSyncRequest3", // 30 - "SendSyncRequest4", // 31 - "SendSyncRequest", // 32 - "OpenProcess", // 33 - "OpenThread", // 34 - "GetProcessId", // 35 - "GetProcessIdOfThread", // 36 - "GetThreadId", // 37 - "GetResourceLimit", // 38 - "GetResourceLimitLimitValues", // 39 - "GetResourceLimitCurrentValues", // 3A - "GetThreadContext", // 3B - "Break", // 3C - "OutputDebugString", // 3D - "ControlPerformanceCounter", // 3E - NULL, // 3F - NULL, // 40 - NULL, // 41 - NULL, // 42 - NULL, // 43 - NULL, // 44 - NULL, // 45 - NULL, // 46 - "CreatePort", // 47 - "CreateSessionToPort", // 48 - "CreateSession", // 49 - "AcceptSession", // 4A - "ReplyAndReceive1", // 4B - "ReplyAndReceive2", // 4C - "ReplyAndReceive3", // 4D - "ReplyAndReceive4", // 4E - "ReplyAndReceive", // 4F - "BindInterrupt", // 50 - "UnbindInterrupt", // 51 - "InvalidateProcessDataCache", // 52 - "StoreProcessDataCache", // 53 - "FlushProcessDataCache", // 54 - "StartInterProcessDma", // 55 - "StopDma", // 56 - "GetDmaState", // 57 - "RestartDma", // 58 - "SetGpuProt", // 59 - "SetWifiEnabled", // 5A - NULL, // 5B - NULL, // 5C - NULL, // 5D - NULL, // 5E - NULL, // 5F - "DebugActiveProcess", // 60 - "BreakDebugProcess", // 61 - "TerminateDebugProcess", // 62 - "GetProcessDebugEvent", // 63 - "ContinueDebugEvent", // 64 - "GetProcessList", // 65 - "GetThreadList", // 66 - "GetDebugThreadContext", // 67 - "SetDebugThreadContext", // 68 - "QueryDebugProcessMemory", // 69 - "ReadProcessMemory", // 6A - "WriteProcessMemory", // 6B - "SetHardwareBreakPoint", // 6C - "GetDebugThreadParam", // 6D - NULL, // 6E - NULL, // 6F - "ControlProcessMemory", // 70 - "MapProcessMemory", // 71 - "UnmapProcessMemory", // 72 - "CreateCodeSet", // 73 - NULL, // 74 - "CreateProcess", // 75 - "TerminateProcess", // 76 - "SetProcessResourceLimits", // 77 - "CreateResourceLimit", // 78 - "SetResourceLimitValues", // 79 - "AddCodeSegment", // 7A - "Backdoor", // 7B - "KernelSetState", // 7C - "QueryProcessMemory", // 7D - NULL, // 7E - NULL, // 7F -}; - - -void syscall_get_name(char *output, size_t size, unsigned int call_num) -{ -#ifdef _MSC_VER - typedef char StaticAssert[sizeof(syscall_list) / sizeof(syscall_list[0]) == NUM_SYSCALLS ? 1 : -1]; -#else - _Static_assert(sizeof(syscall_list) / sizeof(syscall_list[0]) == NUM_SYSCALLS, - "syscall table length mismatch"); -#endif - - - if (size == 0) - { - return; - } - - const char *name = NULL; - if (call_num < (unsigned int) NUM_SYSCALLS) - { - name = syscall_list[call_num]; - } - - char name_buf[] = "UnknownXX"; - sprintf(&name_buf[sizeof(name_buf) - 3], "%02X", call_num & 0xFFu); - - name = name ? name : name_buf; - - size_t length = strlen(name); - length = (length > (size - 1)) ? (size - 1) : length; - - memcpy(output, name, length); - output[length] = '\0'; -} diff --git a/ctrtool/syscalls.h b/ctrtool/syscalls.h deleted file mode 100644 index 5afca89..0000000 --- a/ctrtool/syscalls.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _SYSCALLS_H_ -#define _SYSCALLS_H_ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -enum { NUM_SYSCALLS = 0x80 }; - -void syscall_get_name(char *output, size_t size, unsigned int call_num); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/ctrtool/tik.c b/ctrtool/tik.c deleted file mode 100644 index 285f403..0000000 --- a/ctrtool/tik.c +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include - -#include "aes_keygen.h" -#include "tik.h" -#include "ctr.h" -#include "utils.h" - -void tik_init(tik_context* ctx) -{ - memset(ctx, 0, sizeof(tik_context)); -} - -void tik_set_file(tik_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void tik_set_offset(tik_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void tik_set_size(tik_context* ctx, u32 size) -{ - ctx->size = size; -} - -void tik_set_usersettings(tik_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -const unsigned char* tik_get_titlekey(tik_context* ctx) -{ - return ctx->titlekey.valid ? ctx->titlekey.data : NULL; -} - -void tik_get_titleid(tik_context* ctx, u8 titleid[8]) -{ - memcpy(titleid, ctx->tik.title_id, 8); -} - -void tik_get_iv(tik_context* ctx, u8 iv[16]) -{ - memset(iv, 0, 16); - memcpy(iv, ctx->tik.title_id, 8); -} - -int tik_decrypt_titlekey(tik_context* ctx, u8 decryptedkey[0x10]) -{ - u8 iv[16]; - u8* commonkey = settings_get_common_key(ctx->usersettings, ctx->tik.commonkey_idx); - - memset(decryptedkey, 0, 0x10); - if (!commonkey) - { - fprintf(stdout, "Error, could not read common key.\n"); - return 1; - } - - memset(iv, 0, 0x10); - memcpy(iv, ctx->tik.title_id, 8); - - ctr_init_cbc_decrypt(&ctx->aes, commonkey, iv); - ctr_decrypt_cbc(&ctx->aes, ctx->tik.encrypted_title_key, decryptedkey, 0x10); - return 0; -} - -void tik_process(tik_context* ctx, u32 actions) -{ - if (ctx->size < sizeof(eticket)) - { - fprintf(stderr, "Error, ticket size too small\n"); - goto clean; - } - - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread((u8*)&ctx->tik, 1, sizeof(eticket), ctx->file); - - ctx->titlekey.valid = tik_decrypt_titlekey(ctx, ctx->titlekey.data) == 0 ? 1 : 0; - - if (actions & InfoFlag) - { - tik_print(ctx); - } - -clean: - return; -} - -void tik_print(tik_context* ctx) -{ - int i; - eticket* tik = &ctx->tik; - - fprintf(stdout, "\nTicket content:\n"); - fprintf(stdout, - "Signature Type: %08x\n" - "Issuer: %s\n", - getle32(tik->sig_type), tik->issuer - ); - - fprintf(stdout, "Signature:\n"); - hexdump(tik->signature, 0x100); - fprintf(stdout, "\n"); - - memdump(stdout, "Encrypted Titlekey: ", tik->encrypted_title_key, 0x10); - - if (ctx->titlekey.valid) - memdump(stdout, "Decrypted Titlekey: ", ctx->titlekey.data, 0x10); - - memdump(stdout, "Ticket ID: ", tik->ticket_id, 0x08); - fprintf(stdout, "Ticket Version: %d\n", getle16(tik->ticket_version)); - memdump(stdout, "Title ID: ", tik->title_id, 0x08); - fprintf(stdout, "Common Key Index: %d\n", tik->commonkey_idx); - - fprintf(stdout, "Content permission map:\n"); - for(i = 0; i < 0x40; i++) { - printf(" %02x", tik->content_permissions[i]); - - if ((i+1) % 8 == 0) - printf("\n"); - } - printf("\n"); -} diff --git a/ctrtool/tik.h b/ctrtool/tik.h deleted file mode 100644 index 4d85aaa..0000000 --- a/ctrtool/tik.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __TIK_H__ -#define __TIK_H__ - -#include "types.h" -#include "keyset.h" -#include "ctr.h" -#include "settings.h" - -typedef struct -{ - u8 enable_timelimit[4]; - u8 timelimit_seconds[4]; -} timelimit_entry; - -typedef struct -{ - u8 sig_type[4]; - u8 signature[0x100]; - u8 padding1[0x3c]; - u8 issuer[0x40]; - u8 ecdsa[0x3c]; - u8 padding2[0x03]; - u8 encrypted_title_key[0x10]; - u8 unknown; - u8 ticket_id[8]; - u8 console_id[4]; - u8 title_id[8]; - u8 sys_access[2]; - u8 ticket_version[2]; - u8 time_mask[4]; - u8 permit_mask[4]; - u8 title_export; - u8 commonkey_idx; - u8 unknown_buf[0x30]; - u8 content_permissions[0x40]; - u8 padding0[2]; - - timelimit_entry timelimits[8]; -} eticket; - -typedef struct -{ - FILE* file; - u64 offset; - u32 size; - key128 titlekey; - eticket tik; - ctr_aes_context aes; - settings* usersettings; -} tik_context; - -void tik_init(tik_context* ctx); -void tik_set_file(tik_context* ctx, FILE* file); -void tik_set_offset(tik_context* ctx, u64 offset); -void tik_set_size(tik_context* ctx, u32 size); -void tik_set_usersettings(tik_context* ctx, settings* usersettings); -const unsigned char* tik_get_titlekey(tik_context* ctx); -void tik_get_titleid(tik_context* ctx, u8 titleid[8]); -void tik_get_iv(tik_context* ctx, u8 iv[0x10]); -int tik_decrypt_titlekey(tik_context* ctx, u8 decryptedkey[0x10]); -void tik_print(tik_context* ctx); -void tik_process(tik_context* ctx, u32 actions); - -#endif diff --git a/ctrtool/tinyxml/tinystr.cpp b/ctrtool/tinyxml/tinystr.cpp deleted file mode 100644 index 6ca4dc8..0000000 --- a/ctrtool/tinyxml/tinystr.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -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. -*/ - - -#ifndef TIXML_USE_STL - -#include "tinyxml/tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/ctrtool/tinyxml/tinystr.h b/ctrtool/tinyxml/tinystr.h deleted file mode 100644 index 89cca33..0000000 --- a/ctrtool/tinyxml/tinystr.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -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. -*/ - - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/ctrtool/tinyxml/tinyxml.cpp b/ctrtool/tinyxml/tinyxml.cpp deleted file mode 100644 index cec7b8c..0000000 --- a/ctrtool/tinyxml/tinyxml.cpp +++ /dev/null @@ -1,1886 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -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 - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml/tinyxml.h" - -FILE* TiXmlFOpen( const char* filename, const char* mode ); - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; - target->location = location; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( !replaceThis ) - return 0; - - if ( replaceThis->parent != this ) - return 0; - - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( !removeThis ) { - return false; - } - - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); - return *this; -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} - - -int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; -} - - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; -} - - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} -#endif - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; - } - } - else { - *q++ = *p++; - } - } - assert( q <= (buf+length) ); - *q = 0; - - Parse( buf, 0, encoding ); - - delete [] buf; - return !Error(); -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); - #else - sprintf (buf, "%g", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); - return *this; -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - copy.CopyTo( this ); -} - - -TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} -#endif - - -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} - - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/ctrtool/tinyxml/tinyxml.h b/ctrtool/tinyxml/tinyxml.h deleted file mode 100644 index eea0f06..0000000 --- a/ctrtool/tinyxml/tinyxml.h +++ /dev/null @@ -1,1805 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -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. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinyxml/tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 6; -const int TIXML_PATCH_VERSION = 2; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); - -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif - - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - TiXmlElement& operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -#include - -#include "tinyxml/tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() const { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p && *p ) - p += strlen( endTag ); - return ( p && *p ) ? p : 0; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p && *p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i -#include -#include -#include -#include "tmd.h" -#include "utils.h" -#include - - -void tmd_init(tmd_context* ctx) -{ - memset(ctx, 0, sizeof(tmd_context)); -} - -void tmd_set_file(tmd_context* ctx, FILE* file) -{ - ctx->file = file; -} - -void tmd_set_offset(tmd_context* ctx, u64 offset) -{ - ctx->offset = offset; -} - -void tmd_set_size(tmd_context* ctx, u32 size) -{ - ctx->size = size; -} - -void tmd_set_usersettings(tmd_context* ctx, settings* usersettings) -{ - ctx->usersettings = usersettings; -} - -void tmd_process(tmd_context* ctx, u32 actions) -{ - if (ctx->buffer == 0) - ctx->buffer = malloc(ctx->size); - - if (ctx->buffer) - { - fseeko64(ctx->file, ctx->offset, SEEK_SET); - fread(ctx->buffer, 1, ctx->size, ctx->file); - - if (actions & InfoFlag) - { - tmd_print(ctx); - } - } -} - -ctr_tmd_body *tmd_get_body(tmd_context *ctx) -{ - unsigned int type = getbe32(ctx->buffer); - ctr_tmd_body *body = NULL; - - if (type == TMD_RSA_2048_SHA256 || type == TMD_RSA_2048_SHA1) - { - body = (ctr_tmd_body*)(ctx->buffer + sizeof(ctr_tmd_header_2048)); - } - else if (type == TMD_RSA_4096_SHA256 || type == TMD_RSA_4096_SHA1) - { - body = (ctr_tmd_body*)(ctx->buffer + sizeof(ctr_tmd_header_4096)); - } - - return body; -} - -const char* tmd_get_type_string(unsigned int type) -{ - switch(type) - { - case TMD_RSA_2048_SHA256: return "RSA 2048 - SHA256"; - case TMD_RSA_4096_SHA256: return "RSA 4096 - SHA256"; - case TMD_RSA_2048_SHA1: return "RSA 2048 - SHA1"; - case TMD_RSA_4096_SHA1: return "RSA 4096 - SHA1"; - default: - return "unknown"; - } -} - -void tmd_print(tmd_context* ctx) -{ - unsigned int type = getbe32(ctx->buffer); - ctr_tmd_header_4096* header4096 = 0; - ctr_tmd_header_2048* header2048 = 0; - ctr_tmd_body* body = 0; - unsigned int contentcount = 0; - unsigned int savesize = 0; - unsigned int titlever = 0; - unsigned int i; - - if (type == TMD_RSA_2048_SHA256 || type == TMD_RSA_2048_SHA1) - { - header2048 = (ctr_tmd_header_2048*)ctx->buffer; - } - else if (type == TMD_RSA_4096_SHA256 || type == TMD_RSA_4096_SHA1) - { - header4096 = (ctr_tmd_header_4096*)ctx->buffer; - } - else - { - return; - } - - body = tmd_get_body(ctx); - - contentcount = getbe16(body->contentcount); - savesize = getle32(body->savedatasize); - titlever = getbe16(body->titleversion); - - fprintf(stdout, "\nTMD header:\n"); - fprintf(stdout, "Signature type: %s\n", tmd_get_type_string(type)); - fprintf(stdout, "Issuer: %s\n", body->issuer); - fprintf(stdout, "Version: %d\n", body->version); - fprintf(stdout, "CA CRL version: %d\n", body->ca_crl_version); - fprintf(stdout, "Signer CRL version: %d\n", body->signer_crl_version); - memdump(stdout, "System version: ", body->systemversion, 8); - memdump(stdout, "Title id: ", body->titleid, 8); - fprintf(stdout, "Title type: %08x\n", getbe32(body->titletype)); - fprintf(stdout, "Group id: %04x\n", getbe16(body->groupid)); - if(savesize < sizeKB) - fprintf(stdout, "Save Size: %08x\n", savesize); - else if(savesize < sizeMB) - fprintf(stdout, "Save Size: %dKB (%08x)\n", savesize/sizeKB, savesize); - else - fprintf(stdout, "Save Size: %dMB (%08x)\n", savesize/sizeMB, savesize); - fprintf(stdout, "Access rights: %08x\n", getbe32(body->accessrights)); - fprintf(stdout, "Title version: %d.%d.%d (v%d)\n", (titlever >> 10) & 0x3F, (titlever >> 4) & 0x3F, titlever & 0xF, titlever); - fprintf(stdout, "Content count: %04x\n", getbe16(body->contentcount)); - fprintf(stdout, "Boot content: %04x\n", getbe16(body->bootcontent)); - memdump(stdout, "Hash: ", body->hash, 32); - - fprintf(stdout, "\nTMD content info:\n"); - for(i = 0; i < TMD_MAX_CONTENTS; i++) - { - ctr_tmd_contentinfo* info = (ctr_tmd_contentinfo*)(body->contentinfo + sizeof(ctr_tmd_contentinfo)*i); - - if (getbe16(info->commandcount) == 0) - continue; - - fprintf(stdout, "Content index: %04x\n", getbe16(info->index)); - fprintf(stdout, "Command count: %04x\n", getbe16(info->commandcount)); - memdump(stdout, "Unknown: ", info->unk, 32); - } - fprintf(stdout, "\nTMD contents:\n"); - for(i = 0; i < contentcount; i++) - { - ctr_tmd_contentchunk* chunk = (ctr_tmd_contentchunk*)(body->contentinfo + 36*64 + i*48); - unsigned short type = getbe16(chunk->type); - - fprintf(stdout, "Content id: %08x\n", getbe32(chunk->id)); - fprintf(stdout, "Content index: %04x\n", getbe16(chunk->index)); - fprintf(stdout, "Content type: %04x", getbe16(chunk->type)); - if (type) - { - fprintf(stdout, " "); - if (type & 1) - fprintf(stdout, "[encrypted]"); - if (type & 2) - fprintf(stdout, "[disc]"); - if (type & 4) - fprintf(stdout, "[cfm]"); - if (type & 0x4000) - fprintf(stdout, "[optional]"); - if (type & 0x8000) - fprintf(stdout, "[shared]"); - } - fprintf(stdout, "\n"); - fprintf(stdout, "Content size: %016"PRIx64"\n", getbe64(chunk->size)); - - switch(ctx->content_hash_stat[i]) { - case 1: memdump(stdout, "Content hash [OK]: ", chunk->hash, 32); break; - case 2: memdump(stdout, "Content hash [FAIL]: ", chunk->hash, 32); break; - default: memdump(stdout, "Content hash: ", chunk->hash, 32); break; - } - - fprintf(stdout, "\n"); - } -} diff --git a/ctrtool/tmd.h b/ctrtool/tmd.h deleted file mode 100644 index d9701a7..0000000 --- a/ctrtool/tmd.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef _TMD_H_ -#define _TMD_H_ - -#include "types.h" -#include "settings.h" - -#define TMD_MAX_CONTENTS 64 - -typedef enum -{ - TMD_RSA_2048_SHA256 = 0x00010004, - TMD_RSA_4096_SHA256 = 0x00010003, - TMD_RSA_2048_SHA1 = 0x00010001, - TMD_RSA_4096_SHA1 = 0x00010000 -} ctr_tmdtype; - - -typedef struct -{ - unsigned char padding[60]; - unsigned char issuer[64]; - unsigned char version; - unsigned char ca_crl_version; - unsigned char signer_crl_version; - unsigned char padding2; - unsigned char systemversion[8]; - unsigned char titleid[8]; - unsigned char titletype[4]; - unsigned char groupid[2]; - unsigned char savedatasize[4]; - unsigned char privsavedatasize[4]; - unsigned char padding3[4]; - unsigned char twlflag; - unsigned char padding4[0x31]; - unsigned char accessrights[4]; - unsigned char titleversion[2]; - unsigned char contentcount[2]; - unsigned char bootcontent[2]; - unsigned char padding5[2]; - unsigned char hash[32]; - unsigned char contentinfo[36*64]; -} ctr_tmd_body; - -typedef struct -{ - unsigned char index[2]; - unsigned char commandcount[2]; - unsigned char unk[32]; -} ctr_tmd_contentinfo; - - -typedef struct -{ - unsigned char id[4]; - unsigned char index[2]; - unsigned char type[2]; - unsigned char size[8]; - unsigned char hash[32]; -} ctr_tmd_contentchunk; - - -typedef struct -{ - unsigned char signaturetype[4]; - unsigned char signature[256]; -} ctr_tmd_header_2048; - -typedef struct -{ - unsigned char signaturetype[4]; - unsigned char signature[512]; -} ctr_tmd_header_4096; - -typedef struct -{ - FILE* file; - u64 offset; - u32 size; - u8* buffer; - u8 content_hash_stat[64]; - settings* usersettings; -} tmd_context; - - - -#ifdef __cplusplus -extern "C" { -#endif - -void tmd_init(tmd_context* ctx); -void tmd_set_file(tmd_context* ctx, FILE* file); -void tmd_set_offset(tmd_context* ctx, u64 offset); -void tmd_set_size(tmd_context* ctx, u32 size); -void tmd_set_usersettings(tmd_context* ctx, settings* usersettings); -void tmd_print(tmd_context* ctx); -void tmd_process(tmd_context* ctx, u32 actions); -ctr_tmd_body *tmd_get_body(tmd_context *ctx); - -#ifdef __cplusplus -} -#endif - -#endif // _TMD_H_ diff --git a/ctrtool/types.h b/ctrtool/types.h deleted file mode 100644 index c35e2ba..0000000 --- a/ctrtool/types.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __TYPES_H__ -#define __TYPES_H__ - -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -enum flags -{ - ExtractFlag = (1<<0), - InfoFlag = (1<<1), - PlainFlag = (1<<2), - VerboseFlag = (1<<3), - VerifyFlag = (1<<4), - RawFlag = (1<<5), - ShowKeysFlag = (1<<6), - DecompressCodeFlag = (1<<7), - ShowSyscallsFlag = (1<<8), - DevFlag = (1<<9), -}; - -enum validstate -{ - Unchecked = 0, - Good = 1, - Fail = 2, -}; - -enum sizeunits -{ - sizeKB = 0x400, - sizeMB = 0x100000, -}; - -#endif diff --git a/ctrtool/utils.c b/ctrtool/utils.c deleted file mode 100644 index 92125e5..0000000 --- a/ctrtool/utils.c +++ /dev/null @@ -1,239 +0,0 @@ -#include -#include -#include -#ifdef _WIN32 -#include -#endif -#include "utils.h" - - - -u32 align(u32 offset, u32 alignment) -{ - u32 mask = ~(alignment-1); - - return (offset + (alignment-1)) & mask; -} - -u64 align64(u64 offset, u32 alignment) -{ - u64 mask = ~(u64)(alignment-1); - - return (offset + (alignment-1)) & mask; -} - -u64 getle64(const u8* p) -{ - u64 n = p[0]; - - n |= (u64)p[1]<<8; - n |= (u64)p[2]<<16; - n |= (u64)p[3]<<24; - n |= (u64)p[4]<<32; - n |= (u64)p[5]<<40; - n |= (u64)p[6]<<48; - n |= (u64)p[7]<<56; - return n; -} - -u64 getbe64(const u8* p) -{ - u64 n = 0; - - n |= (u64)p[0]<<56; - n |= (u64)p[1]<<48; - n |= (u64)p[2]<<40; - n |= (u64)p[3]<<32; - n |= (u64)p[4]<<24; - n |= (u64)p[5]<<16; - n |= (u64)p[6]<<8; - n |= (u64)p[7]<<0; - return n; -} - -u32 getle32(const u8* p) -{ - return (p[0]<<0) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); -} - -u32 getbe32(const u8* p) -{ - return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | (p[3]<<0); -} - -u32 getle16(const u8* p) -{ - return (p[0]<<0) | (p[1]<<8); -} - -u32 getbe16(const u8* p) -{ - return (p[0]<<8) | (p[1]<<0); -} - -void putle16(u8* p, u16 n) -{ - p[0] = (u8) n; - p[1] = (u8) (n>>8); -} - -void putle32(u8* p, u32 n) -{ - p[0] = (u8) n; - p[1] = (u8) (n>>8); - p[2] = (u8) (n>>16); - p[3] = (u8) (n>>24); -} - -void putle64(u8* p, u64 n) -{ - p[0] = (u8) n; - p[1] = (u8) (n >> 8); - p[2] = (u8) (n >> 16); - p[3] = (u8) (n >> 24); - p[4] = (u8) (n >> 32); - p[5] = (u8) (n >> 40); - p[6] = (u8) (n >> 48); - p[7] = (u8) (n >> 56); -} - -void putbe16(u8* p, u16 n) -{ - p[1] = (u8) n; - p[0] = (u8) (n >> 8); -} - -void putbe32(u8* p, u32 n) -{ - p[3] = (u8) n; - p[2] = (u8) (n >> 8); - p[1] = (u8) (n >> 16); - p[0] = (u8) (n >> 24); -} - -void putbe64(u8* p, u64 n) -{ - p[7] = (u8) n; - p[6] = (u8) (n >> 8); - p[5] = (u8) (n >> 16); - p[4] = (u8) (n >> 24); - p[3] = (u8) (n >> 32); - p[2] = (u8) (n >> 40); - p[1] = (u8) (n >> 48); - p[0] = (u8) (n >> 56); -} - -void readkeyfile(u8* key, const char* keyfname) -{ - u64 keysize = _fsize(keyfname); - FILE* f = fopen(keyfname, "rb"); - - if (0 == f) - { - fprintf(stdout, "Error opening key file\n"); - goto clean; - } - - if (keysize != 16) - { - fprintf(stdout, "Error key size mismatch, got %"PRIu64", expected %d\n", keysize, 16); - goto clean; - } - - if (16 != fread(key, 1, 16, f)) - { - fprintf(stdout, "Error reading key file\n"); - goto clean; - } - -clean: - if (f) - fclose(f); -} - -void hexdump(void *ptr, int buflen) -{ - u8 *buf = (u8*)ptr; - int i, j; - - for (i=0; i= 0x20 && buf[i+j] <= 0x7e) ? buf[i+j] : '.'); - } - } - printf("\n"); - } -} - -void memdump(FILE* fout, const char* prefix, const u8* data, u32 size) -{ - u32 i; - u32 prefixlen = strlen(prefix); - u32 offs = 0; - u32 line = 0; - while(size) - { - u32 max = 32; - - if (max > size) - max = size; - - if (line==0) - fprintf(fout, "%s", prefix); - else - fprintf(fout, "%*s", prefixlen, ""); - - - for(i=0; i. - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -# define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -# ifndef const -# define const -# endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include -# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -# include -# include -#endif /* GNU C library. */ - -#ifdef VMS -# include -# if HAVE_STRING_H - 0 -# include -# endif -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -# ifdef HAVE_LIBINTL_H -# include -# define _(msgid) gettext (msgid) -# else -# define _(msgid) (msgid) -# endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -# include -# define my_index strchr -#else - -#include - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -#ifndef getenv -extern char *getenv (); -#endif - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -# if (!defined __STDC__ || !__STDC__) && !defined strlen -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -# endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -# ifdef text_set_element -text_set_element (__libc_subinit, store_args_and_env); -# endif /* text_set_element */ - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined __STDC__ && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#ifdef _LIBC -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/ctrtool/windows/getopt.h b/ctrtool/windows/getopt.h deleted file mode 100644 index b65740d..0000000 --- a/ctrtool/windows/getopt.h +++ /dev/null @@ -1,172 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _GETOPT_H - -#ifndef __need_getopt -# define _GETOPT_H 1 -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - - extern char *optarg; - - /* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - - extern int optind; - - /* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - - extern int opterr; - - /* Set to an option character which was unrecognized. */ - - extern int optopt; - -#ifndef __need_getopt - /* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - - struct option { -# if defined __STDC__ && __STDC__ - const char *name; -# else - - char *name; -# endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; - }; - - /* Names for the values of the `has_arg' field of `struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - - /* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. - - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more - options. - - If OPTS begins with `--', then non-option arguments are treated as - arguments to the option '\0'. This behavior is specific to the GNU - `getopt'. */ - -#if defined __STDC__ && __STDC__ -# ifdef __GNU_LIBRARY__ - /* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ - extern int getopt (int __argc, char *const *__argv, const char *__shortopts); -# else /* not __GNU_LIBRARY__ */ - extern int getopt (); -# endif /* __GNU_LIBRARY__ */ - -# ifndef __need_getopt - - extern int getopt_long (int argc, char ** argv, const char * shortopts, - const struct option * longopts, int * longind); - - extern int getopt_long_only (int __argc, char *const *__argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); - - /* Internal only. Users should not call this directly. */ - extern int _getopt_internal (int __argc, char *const *__argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only); -# endif -#else /* not __STDC__ */ - extern int getopt (); -# ifndef __need_getopt - extern int getopt_long (); - extern int getopt_long_only (); - - extern int _getopt_internal (); -# endif -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* getopt.h */ diff --git a/ctrtool/windows/getopt1.c b/ctrtool/windows/getopt1.c deleted file mode 100644 index 00c3071..0000000 --- a/ctrtool/windows/getopt1.c +++ /dev/null @@ -1,188 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "getopt.h" - -#if !defined __STDC__ || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -#include -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char **argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); -} - - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -#include - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */