/*
* 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__ */