343 lines
10 KiB
C
343 lines
10 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __RABBITSIGN_H__
|
|
#define __RABBITSIGN_H__
|
|
|
|
#ifdef HAVE_GMP_H
|
|
# include <gmp.h>
|
|
# 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__ */
|