/* * RabbitSign - Tools for signing TI graphing calculator software * Copyright (C) 2009 Benjamin Moody * * 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 3 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, see . */ #ifndef __RABBITSIGN_H__ #define __RABBITSIGN_H__ #ifdef HAVE_GMP_H # include # define rs_snprintf gmp_snprintf # define rs_vsnprintf gmp_vsnprintf #else # include "mpz.h" #endif #if __GNUC__ >= 3 # define RS_ATTR_PURE __attribute__((pure)) # define RS_ATTR_MALLOC __attribute__((malloc)) # define RS_ATTR_UNUSED __attribute__((unused)) # define RS_ATTR_PRINTF(f,i) __attribute__((format(printf,f,i))) #else # define RS_ATTR_PURE # define RS_ATTR_MALLOC # define RS_ATTR_UNUSED # define RS_ATTR_PRINTF(f,i) #endif #ifdef __cplusplus extern "C" { #endif /* Calculator types */ typedef enum _RSCalcType { RS_CALC_UNKNOWN = 0, RS_CALC_TI73 = 0x74, RS_CALC_TI83P = 0x73, RS_CALC_TI89 = 0x98, RS_CALC_TI92P = 0x88 } RSCalcType; #define rs_calc_is_ti8x(ttt) ((ttt) == RS_CALC_TI73 || (ttt) == RS_CALC_TI83P) #define rs_calc_is_ti9x(ttt) ((ttt) == RS_CALC_TI89 || (ttt) == RS_CALC_TI92P) /* Data types */ typedef enum _RSDataType { RS_DATA_UNKNOWN = 0, RS_DATA_OS = 0x23, RS_DATA_APP = 0x24, RS_DATA_CERT = 0x25 } RSDataType; /* Flags for app signing */ typedef enum _RSRepairFlags { RS_IGNORE_ALL_WARNINGS = 1, RS_REMOVE_OLD_SIGNATURE = 2, /* Remove existing signature */ RS_FIX_PAGE_COUNT = 4, /* Fix page count header field */ RS_FIX_OS_SIZE = 8, /* Fix size in OS header */ RS_ZEALOUSLY_PAD_APP = 16 /* Pad application with an extra page if necessary */ } RSRepairFlags; /* Flags for file input */ typedef enum _RSInputFlags { RS_INPUT_BINARY = 32, /* Assume input is raw binary data */ RS_INPUT_SORTED = 64 /* Assume plain hex input is sorted (implicit page switch) */ } RSInputFlags; /* Flags for file output */ typedef enum _RSOutputFlags { RS_OUTPUT_HEX_ONLY = 128, /* Write plain hex (.app) format */ RS_OUTPUT_APPSIGN = 256 /* Write hex data in appsign-compatible format */ } RSOutputFlags; /* Encryption key structure */ typedef struct _RSKey { char* filename; /* Filename */ unsigned long id; /* Key ID */ mpz_t n; /* Modulus (public key) */ mpz_t p; /* First factor */ mpz_t q; /* Second factor */ mpz_t qinv; /* q^-1 mod p (for Rabin) (rs_sign_rabin() will calculate this based on p and q, if needed) */ mpz_t d; /* Signing exponent (for RSA) (rs_sign_rsa() will calculate this based on p and q, if needed) */ } RSKey; /* Program data structure */ typedef struct _RSProgram { char* filename; /* Filename */ RSCalcType calctype; /* Calculator type */ RSDataType datatype; /* Program data type */ unsigned char* data; /* Program data */ unsigned long length; /* Length of program data */ unsigned long length_a; /* Size of buffer allocated */ /* Additional metadata (only used by TI-8x OS) */ unsigned char* header; /* OS header */ unsigned int header_length; /* Length of OS header */ unsigned char* signature; /* OS signature */ unsigned int signature_length; /* Length of OS signature */ unsigned int* pagenums; /* List of page numbers */ int npagenums; /* Number of page numbers */ } RSProgram; /* Status codes */ typedef enum _RSStatus { RS_SUCCESS = 0, RS_ERR_MISSING_PAGE_COUNT, RS_ERR_MISSING_KEY_ID, RS_ERR_MISSING_DATE_STAMP, RS_ERR_MISSING_PROGRAM_IMAGE, RS_ERR_MISALIGNED_PROGRAM_IMAGE, RS_ERR_INVALID_PROGRAM_DATA, RS_ERR_INVALID_PROGRAM_SIZE, RS_ERR_INCORRECT_PAGE_COUNT, RS_ERR_FINAL_PAGE_TOO_LONG, RS_ERR_FIELD_TOO_SMALL, RS_ERR_CRITICAL = 1000, RS_ERR_OUT_OF_MEMORY, RS_ERR_FILE_IO, RS_ERR_HEX_SYNTAX, RS_ERR_UNKNOWN_FILE_FORMAT, RS_ERR_UNKNOWN_PROGRAM_TYPE, RS_ERR_MISSING_HEADER, RS_ERR_MISSING_RABIN_SIGNATURE, RS_ERR_MISSING_RSA_SIGNATURE, RS_ERR_INCORRECT_PROGRAM_SIZE, RS_ERR_KEY_NOT_FOUND, RS_ERR_KEY_SYNTAX, RS_ERR_INVALID_KEY, RS_ERR_MISSING_PUBLIC_KEY, RS_ERR_MISSING_PRIVATE_KEY, RS_ERR_UNSUITABLE_RABIN_KEY, RS_ERR_UNSUITABLE_RSA_KEY, RS_SIGNATURE_INCORRECT = -1 } RSStatus; /**** Key handling (keys.c) ****/ /* Create a new key. */ RSKey* rs_key_new (void) RS_ATTR_MALLOC; /* Free a key. */ void rs_key_free (RSKey* key); /* Read key from a file. */ RSStatus rs_read_key_file (RSKey* key, FILE* f, const char* fname, int verify); /* Parse a number written in TI's hexadecimal key format. */ RSStatus rs_parse_key_value (mpz_t dest, const char* str); /**** Program data manipulation (program.c) ****/ /* Create a new program. */ RSProgram* rs_program_new (void) RS_ATTR_MALLOC; /* Create a new program from an existing data buffer. */ RSProgram* rs_program_new_with_data (RSCalcType ctype, RSDataType dtype, void* data, unsigned long length, unsigned long buffer_size) RS_ATTR_MALLOC; /* Free program data. */ void rs_program_free (RSProgram* prgm); /* Truncate or extend program. */ RSStatus rs_program_set_length (RSProgram* prgm, unsigned long length); /* Add data to the end of the program. */ RSStatus rs_program_append_data (RSProgram* prgm, const unsigned char* data, unsigned long length); /**** Search for key file (autokey.c) ****/ /* Get key ID for the given program. */ unsigned long rs_program_get_key_id (const RSProgram* prgm) RS_ATTR_PURE; /* Find key file for the given ID. */ RSStatus rs_key_find_for_id (RSKey* key, unsigned long keyid, int publiconly); /**** Program signing and validation (apps.c) ****/ /* Check/fix program header and data. */ RSStatus rs_repair_program (RSProgram* prgm, RSRepairFlags flags); /* Add a signature to the program. */ RSStatus rs_sign_program (RSProgram* prgm, RSKey* key, int rootnum); /* Validate program signature. */ RSStatus rs_validate_program (const RSProgram* prgm, const RSKey* key); /**** TI-73/83+/84+ app signing (app8x.c) ****/ /* Check/fix Flash app header and data. */ RSStatus rs_repair_ti8x_app (RSProgram* app, RSRepairFlags flags); /* Add a signature to a Flash app. */ RSStatus rs_sign_ti8x_app (RSProgram* app, RSKey* key, int rootnum); /* Validate Flash app signature. */ RSStatus rs_validate_ti8x_app (const RSProgram* app, const RSKey* key); /**** TI-73/83+/84+ OS signing (os8x.c) ****/ /* Check/fix OS header and data. */ RSStatus rs_repair_ti8x_os (RSProgram* os, RSRepairFlags flags); /* Add a signature to an OS. */ RSStatus rs_sign_ti8x_os (RSProgram* os, RSKey* key); /* Validate OS signature. */ RSStatus rs_validate_ti8x_os (const RSProgram* os, const RSKey* key); /**** TI-89/92+ app/OS signing (app9x.c) ****/ /* Check/fix Flash app header and data. */ RSStatus rs_repair_ti9x_app (RSProgram* app, RSRepairFlags flags); /* Check/fix OS header and data. */ RSStatus rs_repair_ti9x_os (RSProgram* app, RSRepairFlags flags); /* Add a signature to a 68k app/OS. */ RSStatus rs_sign_ti9x_app (RSProgram* app, RSKey* key); /* Validate app/OS signature. */ RSStatus rs_validate_ti9x_app (const RSProgram* app, const RSKey* key); #define rs_sign_ti9x_os rs_sign_ti9x_app #define rs_validate_ti9x_os rs_validate_ti9x_app /**** File input (input.c) ****/ /* Read program contents from a file. */ RSStatus rs_read_program_file (RSProgram* prgm, FILE* f, const char* fname, RSInputFlags flags); /**** File output (output.c) ****/ /* Write program contents to a file. */ RSStatus rs_write_program_file(const RSProgram* prgm, FILE* f, int month, int day, int year, RSOutputFlags flags); /**** Hex file output (output8x.c) ****/ /* Write program to a .73k/.73u/.8xk/.8xu or .app file. */ RSStatus rs_write_ti8x_file (const RSProgram* prgm, FILE* f, int month, int day, int year, RSOutputFlags flags); /**** Binary file output (output9x.c) ****/ /* Write program to a .89k/.89u/.9xk/.9xu file. */ RSStatus rs_write_ti9x_file (const RSProgram* prgm, FILE* f, int month, int day, int year, RSOutputFlags flags); /**** App header/certificate utility functions (header.c) ****/ /* Get length of a header field. */ void rs_get_field_size (const unsigned char* data, unsigned long* fieldstart, unsigned long* fieldsize); /* Set length of a header field. */ int rs_set_field_size (unsigned char* data, unsigned long fieldsize); /* Find a given header field in the data. */ int rs_find_app_field (unsigned int type, const unsigned char* data, unsigned long length, unsigned long* fieldhead, unsigned long* fieldstart, unsigned long* fieldsize); /* Get value of a numeric header field. */ unsigned long rs_get_numeric_field (unsigned int type, const unsigned char* data, unsigned long length) RS_ATTR_PURE; /**** Error/message logging (error.c) ****/ typedef void (*RSMessageFunc) (const RSKey*, const RSProgram*, const char*, void*); /* Set program name */ void rs_set_progname (const char* s); /* Set verbosity level */ void rs_set_verbose (int v); /* Set error logging function */ void rs_set_error_func (RSMessageFunc func, void* data); /* Set message logging function */ void rs_set_message_func (RSMessageFunc func, void* data); #ifdef __cplusplus } #endif #endif /* __RABBITSIGN_H__ */