/* * 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 . */ #ifdef HAVE_CONFIG_H # include #endif #include #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif #include "rabbitsign.h" #include "internal.h" #include "autokeys.h" /* * Get key ID for the given program. */ unsigned long rs_program_get_key_id(const RSProgram* prgm) { const unsigned char* hdr; unsigned long hdrstart, hdrsize; if (prgm->header_length > 0) { hdr = prgm->header; hdrsize = prgm->header_length; } else if (prgm->length > 0) { hdr = prgm->data; hdrsize = prgm->length; if (hdrsize > 128) hdrsize = 128; } else return 0; rs_get_field_size(hdr, &hdrstart, NULL); hdrsize -= hdrstart; if (hdr[0] == 0x81) return rs_get_numeric_field(0x8110, hdr + hdrstart, hdrsize); else return rs_get_numeric_field(0x8010, hdr + hdrstart, hdrsize); } /* * Try to load key from a file. */ static int try_key_file(RSKey* key, /* key structure to store result */ const char* a, /* first path element */ const char* b, /* second path element */ const char* c) /* third path element */ { char* s; FILE* f; int e; s = rs_malloc(strlen(a) + strlen(b) + strlen(c) + 1); if (!s) return RS_ERR_OUT_OF_MEMORY; strcpy(s, a); strcat(s, b); strcat(s, c); f = fopen(s, "rt"); if (!f) { rs_free(s); return RS_ERR_KEY_NOT_FOUND; } if ((e = rs_read_key_file(key, f, s, 1))) { fclose(f); rs_free(s); return e; } fclose(f); rs_free(s); return RS_SUCCESS; } /* * Try to locate a given key file. */ static int find_key_file(RSKey* key, /* key structure to store result */ const char* filename) /* file name to search for */ { const char* p; int e; e = try_key_file(key, "", "", filename); if (e != RS_ERR_KEY_NOT_FOUND) return e; if ((p = getenv("RABBITSIGN_KEY_DIR"))) { #if defined(__MSDOS__) || defined(__WIN32__) e = try_key_file(key, p, "\\", filename); #else e = try_key_file(key, p, "/", filename); #endif if (e != RS_ERR_KEY_NOT_FOUND) return e; } #if defined(__MSDOS__) || defined(__WIN32__) if ((p = getenv("TI83PLUSDIR"))) { e = try_key_file(key, p, "\\Utils\\", filename); if (e != RS_ERR_KEY_NOT_FOUND) return e; } #endif #ifdef SHARE_DIR e = try_key_file(key, SHARE_DIR, "", filename); if (e != RS_ERR_KEY_NOT_FOUND) return e; #endif return RS_ERR_KEY_NOT_FOUND; } /* * Find key file for the given ID. */ int rs_key_find_for_id(RSKey* key, /* key structure to store result */ unsigned long keyid, /* key ID to search for */ int publiconly) /* 1 = search for public key only */ { static const char* fmts[] = { "%02lx.%s", "%02lX.%s", "%04lx.%s", "%04lX.%s", NULL }; char buf[16]; int i, e; mpz_set_ui(key->p, 0); mpz_set_ui(key->q, 0); mpz_set_ui(key->qinv, 0); mpz_set_ui(key->d, 0); if (keyid > 0xFF) sprintf(buf, "%04lX", keyid); else sprintf(buf, "%02lX", keyid); for (i = 0; known_priv_keys[i].n; i++) { if (keyid == known_priv_keys[i].id) { if ((e = rs_parse_key_value(key->n, known_priv_keys[i].n))) return e; if (known_priv_keys[i].p && (e = rs_parse_key_value(key->p, known_priv_keys[i].p))) return e; if (known_priv_keys[i].q && (e = rs_parse_key_value(key->q, known_priv_keys[i].q))) return e; if (known_priv_keys[i].d && (e = rs_parse_key_value(key->d, known_priv_keys[i].d))) return e; rs_message(2, key, NULL, "Loaded builtin private key %s:", buf); rs_message(2, key, NULL, " n = %ZX", key->n); if (mpz_sgn(key->p)) rs_message(2, key, NULL, " p = %ZX", key->p); if (mpz_sgn(key->q)) rs_message(2, key, NULL, " q = %ZX", key->q); if (mpz_sgn(key->d)) rs_message(2, key, NULL, " d = %ZX", key->d); key->id = keyid; return 0; } } if (publiconly) { for (i = 0; known_pub_keys[i].n; i++) { if (keyid == known_pub_keys[i].id) { if ((e = rs_parse_key_value(key->n, known_pub_keys[i].n))) return e; rs_message(2, key, NULL, "Loaded builtin public key %s:", buf); rs_message(2, key, NULL, " n = %ZX", key->n); key->id = keyid; return 0; } } } for (i = 0; fmts[i]; i++) { sprintf(buf, fmts[i], keyid, "key"); e = find_key_file(key, buf); if (e != RS_ERR_KEY_NOT_FOUND) { if (e == 0 && !key->id) key->id = keyid; return e; } } if (publiconly) { for (i = 0; fmts[i]; i++) { sprintf(buf, fmts[i], keyid, "pub"); e = find_key_file(key, buf); if (e != RS_ERR_KEY_NOT_FOUND) { if (e == 0 && !key->id) key->id = keyid; return e; } } } rs_error(NULL, NULL, "cannot find key file %s", buf); return RS_ERR_KEY_NOT_FOUND; }