Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
25
Добавлен:
16.04.2013
Размер:
25.62 Кб
Скачать
/*****************************************************************************
 * search.c                                                                  *
 *                     Search Engine Controller Program                      *
 *                                                                           *
 *    Written 1998 by Cryptography Research (http://www.cryptography.com)    *
 *       and Paul Kocher for the Electronic Frontier Foundation (EFF).       *
 *       Placed in the public domain by Cryptography Research and EFF.       *
 *  THIS IS UNSUPPORTED FREE SOFTWARE. USE AND DISTRIBUTE AT YOUR OWN RISK.  *
 *                                                                           *
 *  IMPORTANT: U.S. LAW MAY REGULATE THE USE AND/OR EXPORT OF THIS PROGRAM.  *
 *                                                                           *
 *****************************************************************************
 *                                                                           *
 *   REVISION HISTORY:                                                       *
 *                                                                           *
 *   Version 1.0:  Initial release by Cryptography Research to EFF.          *
 *                                                                           *
 *****************************************************************************/

#define SOFTWARE_VERSION "1.0"
#define SOFTWARE_DATE    "04-21-1998"


#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <memory.h>
#include <time.h>
#include <string.h>
#include <conio.h>
#include "search.h"
#include "chipio.h"
#include "keyblock.h"
#include "des.h"



/*
 *  SEARCH_CHIP STRUCTURE: Contains status information about each chip.
 *
 *    board:  The board this chip is on (1 byte).
 *    chip:  The ID of this chip on the board (1 byte).
 *    initialized:  0=uninitialized, 1=initialized, -1=defective.
 *    region[]: Specifies the top 24 bits of the key being searched by each
 *        search unit. A value of -1 means the search unit is idle
 *        (idle), and a value of -2 means the search unit is not used.
 *    overFlow[]: Specifies the value at which the low 32 bits of the
 *        key (the key counter) will have gone through all 2^32
 *        possibilities.  Note: this only has the top 24 bits of the
 *        counter, which corresponds to key bytes: .. .. .. XX XX XX.. (LSB)
 *    lastSeen[]:  The value last seen in the low 32 bits of the key.
 *        This has the same encoding as overFlow.
 */
typedef struct CHIP_CTX {
  unsigned char board, chip;
  int initialized;
  long region[SEARCH_UNITS_PER_CHIP];
  long overFlow[SEARCH_UNITS_PER_CHIP];
  long lastDone[SEARCH_UNITS_PER_CHIP];
  struct CHIP_CTX *nextChip;
} CHIP_CTX;


/*
 *  GLOBAL VARIABLES
 */
CHIP_CTX *CHIP_ARRAY = NULL;
SEARCH_CTX CTX;
static int QUIET = 0;
static int VERBOSE = 0;
static FILE *FP_LOG = NULL;


/*
 *  FUNCTION PROTOTYPES & MINI FUNCTIONS & MACROS
 */
static void EXIT_ERR(char *s) { fprintf(stderr, s); exit(1); }
long ReadConfig(char *configFilespec);
void RunSearch(FILE *ctxFile);
void InitializeChip(CHIP_CTX *cp, SEARCH_CTX *ctx);
void ServiceChip(CHIP_CTX *cp, SEARCH_CTX *ctx, FILE *ctxFile);
long GetUnitKeyCounter(int board, int chip, int unit);
void CheckAndPrintKey(CHIP_CTX *cp, SEARCH_CTX *ctx, int unit);
int ServiceKeyboard(SEARCH_CTX *ctx);
int CheckKey(unsigned char key[56], SEARCH_CTX *ctx);


/*
 *  ReadConfig():  Read the search array configuration file.  This file
 *      specifies the I/O base port for SetBaseAddress and also the
 *      search units.  It can contain 3 kinds of lines: comments that
 *      that with '%', base port with "PORT=210" for port 210 hex, and
 *      "UNIT= 12 32 8" to add a search unit on board 0x12, chip 0x32,
 *      and unit 0x08 (all hex).  The function constructs CHIP_ARRAY
 *      as a linked list of chips.
 *   Returns: Total number of search units.
 */
long ReadConfig(char *configFilespec) {
  char buffer[200];
  int basePort = -1;
  int board, chip, unit, i;
  int lastBoard = -1, lastChip = -1;
  long totalUnits = 0;
  CHIP_CTX *cp;
  FILE *fp;

  cp = CHIP_ARRAY;
  if (cp != NULL)
    EXIT_ERR("Chip array base isn't NULL. (Internal error.)\n");

  fp = fopen(configFilespec, "rb");
  if (fp == NULL)
    EXIT_ERR("Error opening configuration filespec.\n");

  if (!QUIET) printf("Reading configuration file \"%s\".\n", configFilespec);
  while (fgets (buffer, 190, fp) != NULL) {
    if (buffer[0] == '\0' || buffer[0] == '%')
      continue;
    if (memcmp(buffer, "PORT=", 5) == 0) {
      basePort = 0;
      sscanf(buffer+5, "%x", &basePort);
      if (basePort <= 0)
        EXIT_ERR("Defective PORT= in configuration file.\n");
      SetBaseAddress(basePort);
      if (!QUIET) printf("Set base port to %x\n", basePort);
      if (FP_LOG && VERBOSE) fprintf(FP_LOG, "Set base port=0x%x\n", basePort);
    }
    else if (memcmp(buffer, "UNIT=", 5) == 0 ||
            memcmp(buffer, "FAIL=", 5) == 0) {
      board = chip = unit = -1;
      sscanf(buffer+5, "%x %x %x", &board, &chip, &unit);
      if (board < 0 || chip < 0 || unit < 0)
        EXIT_ERR("Defective UNIT= or FAIL= in configuration file.\n");
      if (board < lastBoard || (board == lastBoard && chip < lastChip))
        EXIT_ERR("Bad UNIT= or FAIL= in config: board & chip must decrease\n");
      if (board != lastBoard || chip != lastChip) {
        lastBoard = board;
        lastChip = chip;
        if (cp == NULL)
          cp = CHIP_ARRAY = malloc(sizeof(CHIP_CTX));
        else {
          cp->nextChip = malloc(sizeof(CHIP_CTX));
          cp = cp->nextChip;
        }
        cp->board = (unsigned char)board;
        cp->chip = (unsigned char)chip;
        cp->initialized = 0;
        for (i = 0; i < SEARCH_UNITS_PER_CHIP; i++)
          cp->region[i] = -2;
        cp->nextChip = NULL;
      }
      if (cp->region[unit] == -2 && memcmp(buffer, "UNIT=", 5) == 0) {
        totalUnits++;
        cp->region[unit] = -1;                    /* mark the unit as extant */
      }
    } else {
      fprintf(stderr, "IGNORING UNKNOWN CONFIG FILE LINE: \"%s\"\n", buffer);
    }
  }
  fclose(fp);
  if (CHIP_ARRAY == NULL)
    EXIT_ERR("Error: Configuration file does not have any valid units.\n");

  if (FP_LOG && VERBOSE) {
    fprintf(FP_LOG, "Configuration summary:\n");
    for (cp = CHIP_ARRAY; cp != NULL; cp = cp->nextChip) {
      for (i = 0; i < SEARCH_UNITS_PER_CHIP; i++)
        if (cp->region[i] != -2)
          fprintf(FP_LOG, "%s=0x%02X 0x%02X 0x%02X\n",
                  (cp->initialized >= 0) ? "UNIT" : "FAIL",
                   cp->board, cp->chip, i);
    }
  }
  if (!QUIET) printf("Config done: Found %ld search units.\n", totalUnits);
  if (FP_LOG) fprintf(FP_LOG, "Config found %ld search units.\n", totalUnits);
  return (totalUnits);
}



void main(int argc, char **argv) {
  FILE *ctxFile;
  int i;
  time_t t;
  CHIP_CTX *cp;

  printf("\nDES Search Engine Controller (Ver %s, %s). May be export "
         "controlled.\nWritten 1998 by Cryptography Research "
         "(http://www.cryptography.com) for EFF.\n"
         "This is unsupported "
         "free software: Use and distribute at your own risk.\n"
         "-------------------------------------------"
         "---------------------------------\n\n\n",
         SOFTWARE_VERSION, SOFTWARE_DATE);
  if (argc < 3) {
    fprintf(stderr,
         "Usage:  search configFile contextFile [logfile] [-v] [-q]\n"
         "     configFile: Search array configuration from autoconf\n"
         "    contextFile: Search context (from init)\n"
         "        logfile: Output file with detailed reporting info\n"
         "             -v: verbose output to logfile\n"
         "             -q: quiet mode (less output to the screen)\n"
         "  (Note: paramaters must be in the order above.)\n");
    exit(1);
  }
  for (i = 3; i < argc; i++) {
    if (i == 3 && argv[i][0] != '-') {
      FP_LOG = fopen(argv[3], "w");
      if (FP_LOG == NULL)
        EXIT_ERR("Error opening log file.");
    } else if (stricmp(argv[i], "-v") == 0)
      VERBOSE = 1;
    else if (stricmp(argv[i], "-q") == 0)
      QUIET = 1;
    else {
      fprintf(stderr, "Unknown parameter \"%s\"\n", argv[i]);
      exit(1);
    }
  }

  /* READ CONFIGURATION FILE SPECIFYING BASE PORT AND SEARCH UNITS */
  CTX.totalUnits = ReadConfig(argv[1]);

  /* RESET THE SEARCH ARRAY */
  if (!QUIET) printf("Resetting the search array.\n");
  i = -1;
  for (cp = CHIP_ARRAY; cp != NULL; cp = cp->nextChip) {
    if (i != cp->board) {
      i = cp->board;
      ResetBoard(i);
    }
  }
  t = time(NULL);

  /* READ SEARCH FILE SPECIFYING SEARCH INFO & REMAINING KEY BLOCKS */
  ctxFile = fopen(argv[2], "r+b");
  if (ctxFile == NULL) {
    fprintf(stderr, "Error opening search context file \"%s\"\n", argv[2]);
    exit(1);
  }

  /* MAKE SURE RESET HAD AT LEAST 1 SECOND TO SETTLE. */
  if (!QUIET) printf("Waiting for reset to settle.\n");
  while(t + 1 >= time(NULL)) {}

  /* RUN THE SEARCH! */
  RunSearch(ctxFile);
  fclose(ctxFile);
  if (!QUIET) printf("Exiting.\n");
}


/*
 *  Run the search. Uses the search parameters in the
 *       global linked list CHIP_ARRAY and keeps its context info
 *       in the global CTX.
 */
void RunSearch(FILE *ctxFile) {
  CHIP_CTX *cp;
  SEARCH_CTX *ctx = &CTX;
  int halt = 0;
  time_t startTime, lastReportTime, t;
  long loopCount = 0;
  char buffer[128];

  if (!QUIET) printf("Loading search context file...\n");
  OpenSearchContext(ctxFile, ctx);

  printf("Initialization Successful - Beginning search.\n");
  if (QUIET) printf("Quiet mode: Press ? for help during search.\n");
  if (FP_LOG && VERBOSE) fprintf(FP_LOG, "--- Beginning search ---\n");
  for (cp = CHIP_ARRAY; cp != NULL; cp = cp->nextChip)
    InitializeChip(cp, ctx);
  startTime = time(NULL);
  lastReportTime = 0;

  while (halt == 0) {
    t = time(NULL);                                /* report every 5 seconds */
    if (t/5 != lastReportTime/5) {
      sprintf(buffer, "%7ld blocks done, %7ld left, %4ld running (time=%7ld).",
              ctx->totalFinishedKeyBlocks, ctx->totalUnstartedKeyBlocks +
              ctx->totalPendingKeyBlocks, ctx->totalPendingKeyBlocks,
              (long)(t - startTime));
      if (!QUIET) printf(">%s ('?'=help)\n", buffer);
      if (FP_LOG && VERBOSE) fprintf(FP_LOG, "Report: %s\n", buffer);
      lastReportTime = t;
    }
    for (cp = CHIP_ARRAY; cp != NULL && halt == 0; cp = cp->nextChip) {
      ServiceChip(cp, ctx, ctxFile);
      if (ServiceKeyboard(ctx) < 0)
        halt = 1;
    }
    if (ctx->totalFinishedKeyBlocks == (1L<<24))
      halt = 1;
    GetRegister(255, 255, 255);
    loopCount++;
  }
}


/*
 *  InitializeChip(cp, ctx):  Initialize a chip whose chip context is
 *      at cp, using the search parameters at ctx.
 */
void InitializeChip(CHIP_CTX *cp, SEARCH_CTX *ctx) {
  int i,j;

  if (!QUIET) printf("Initializing board 0x%02X, chip 0x%02X\n",
          cp->board, cp->chip);
  if (FP_LOG && VERBOSE) fprintf(FP_LOG,
          "Initializing board 0x%02X, chip 0x%02X\n", cp->board, cp->chip);
  SetRegister(cp->board, cp->chip, REG_PTXT_BYTE_MASK, 0xFF);   /* halt chip */
  for (i = 0; i < 32; i++)
    SetRegister(cp->board, cp->chip, REG_PTXT_VECTOR+i,
            ctx->plaintextVector[i]);
  for (i = 0; i < 8; i++)
    SetRegister(cp->board, cp->chip,REG_PTXT_XOR_MASK+i,
            ctx->plaintextXorMask[i]);
  for (i = 0; i < 8; i++)
    SetRegister(cp->board, cp->chip, REG_CIPHERTEXT0+i, ctx->ciphertext0[i]);
  for (i = 0; i < 8; i++)
    SetRegister(cp->board, cp->chip, REG_CIPHERTEXT1+i, ctx->ciphertext1[i]);
  SetRegister(cp->board, cp->chip, REG_PTXT_BYTE_MASK, ctx->plaintextByteMask);
  SetRegister(cp->board, cp->chip, REG_SEARCHINFO, ctx->searchInfo);

  /* TO BE SAFE, VERIFY THAT ALL REGISTERS WERE WRITTEN PROPERLY */
  /* (Each chip only gets initialized once, so this is quick.) */
  j = 0;
  for (i = 0; i < 32; i++)
    j += CheckRegister(cp->board, cp->chip, REG_PTXT_VECTOR+i,
            ctx->plaintextVector[i]);
  for (i = 0; i < 8; i++) {
    j += CheckRegister(cp->board, cp->chip, REG_PTXT_XOR_MASK+i,
            ctx->plaintextXorMask[i]);
    j += CheckRegister(cp->board, cp->chip, REG_CIPHERTEXT0+i,
            ctx->ciphertext0[i]);
    j += CheckRegister(cp->board, cp->chip, REG_CIPHERTEXT1+i,
            ctx->ciphertext1[i]);
  }
  j += CheckRegister(cp->board, cp->chip, REG_PTXT_BYTE_MASK,
          ctx->plaintextByteMask);
  j += CheckRegister(cp->board, cp->chip, REG_SEARCHINFO, ctx->searchInfo);
  if (j != 0) {
    printf("Bad register on board 0x%02X, chip 0x%02X. Chip disabled.\n",
            cp->board, cp->chip);
    if (FP_LOG) fprintf(FP_LOG, "Bad register on board 0x%02X, chip 0x%02X.%s",
            cp->board, cp->chip, " Chip disabled.\n");
  }

  /* UPDATE THE CHIP CONTEXT */
  cp->initialized = (j == 0) ? 1 : -1;           /* initialized or defective */
}


/*
 *  Service a chip by doing the following:
 *    - Check if it has halted
 *    - Check to see if it has finished its region
 *    - Restart if it is idle
 */
void ServiceChip(CHIP_CTX *cp, SEARCH_CTX *ctx, FILE *ctxFile) {
  int unit;
  long k;

  if (cp->initialized < 0)
    return;

  /*
   *  READ KEYS & RESTART ANY HALTED UNITS
   */
  for (unit = 0; unit < SEARCH_UNITS_PER_CHIP; unit++) {
    if (cp->region[unit] >= 0) {                     /* if currently running */
      if (!(GetRegister(cp->board, cp->chip, REG_SEARCH_STATUS(unit)) & 1)) {
        CheckAndPrintKey(cp, ctx, unit);
        SetRegister(cp->board, cp->chip, REG_SEARCH_STATUS(unit), 1);
      }
    }
  }

  /*
   *  See if any units have completed their search regions
   *    Note: If I/O bandwidth was a problem and the clock rate of the
   *       search system was fixed, we could predict when the keycounter
   *       would flip and avoid this check.
   */
  for (unit = 0; unit < SEARCH_UNITS_PER_CHIP; unit++) {
    if (cp->region[unit] < 0)
      continue;
    k = GetUnitKeyCounter(cp->board, cp->chip, unit);
    k -= cp->overFlow[unit];
    if (k < 0)
      k += (1L << 24);
    if (VERBOSE && FP_LOG) fprintf(FP_LOG,
              "Board 0x%02X chip 0x%02X unit 0x%02X is at 0x%06lX "
              "(lastDone=0x%06lX, overFlow=%06lX)\n",
              cp->board, cp->chip, unit, k,
              cp->lastDone[unit], cp->overFlow[unit]);
    if (k < cp->lastDone[unit]) {
      if (!QUIET) printf("Board 0x%02X chip 0x%02X unit 0x%02X finished block "
              "0x%06lX (lastDone=0x%06lX, got 0x%06lX, overFlow=%06lX)\n",
              cp->board, cp->chip, unit, cp->region[unit],
              cp->lastDone[unit], k, cp->overFlow[unit]);
      if (FP_LOG) fprintf(FP_LOG, "Unit 0x%02X 0x%02X 0x%02X finished "
              "0x%06lX (last=%06lX, got %06lX, oFlow=%06lX)\n",
              cp->board, cp->chip, unit, cp->region[unit],
              cp->lastDone[unit], k, cp->overFlow[unit]);
      FinishKeyRegion(ctxFile, ctx, cp->region[unit]);     /* region is done */
      cp->region[unit] = -1;                             /* unit is now idle */
    } else {
      cp->lastDone[unit] = k;
    }
  }

  /*
   *  Start any units that are currently stalled
   */
  for (unit = 0; unit < SEARCH_UNITS_PER_CHIP; unit++) {
    if (cp->region[unit] == -1) {
      k = ReserveKeyRegion(ctxFile, ctx);
      if (k < 0)
        break;                                         /* no more regions... */
      if (!QUIET) printf("Starting board 0x%02X, chip 0x%02X, unit 0x%02X... ",
           cp->board, cp->chip, unit);
      if (FP_LOG) fprintf(FP_LOG, "Starting unit 0x%02X 0x%02X 0x%02X... ",
           cp->board, cp->chip, unit);
      cp->region[unit] = k;

      /* LOAD UP THE KEY REGION AND LET 'ER RIP... */
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+6,
              (unsigned char)((k >> 16) & 0xFF));
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+5,
              (unsigned char)((k >> 8) & 0xFF));
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+4,
              (unsigned char)(k & 0xFF));
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+3, 0);
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+2, 0);
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+1, 0);
      SetRegister(cp->board, cp->chip, REG_SEARCH_KEY(unit)+0, 0);

      SetRegister(cp->board, cp->chip, REG_SEARCH_STATUS(unit), 1);   /* GO! */

      /* READ OUT THE KEY COUNTER (3 BYTES) FOR OVERFLOW SENSING */
      k = GetUnitKeyCounter(cp->board, cp->chip, unit);
      cp->overFlow[unit] = k;
      cp->lastDone[unit] = k;
      if (!QUIET) printf("Region=0x%06lX, overFlow=0x%06lX\n",
            cp->region[unit], k);
      if (FP_LOG) fprintf(FP_LOG, "Region=0x%06lX, overFlow=0x%06lX\n",
            cp->region[unit], k);
    }
  }
}


/*
 *  Read the value of a rapidly-incrementing key counter register.
 *     The function reads the register twice, finds the most-significant
 *     bit that changed during the operation, and returns the later
 *     (higher) value with all bits to the right of the one that changed
 *     set to zero.
 *  The return value is the top 24 bits of the low 32 bits of the
 *     key counter -- i.e., key bytes (MSB).. .. .. XX XX XX ..(LSB)
 */
long GetUnitKeyCounter(int board, int chip, int unit) {
  long v1, v2, m;
  do {
    v1 = ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+3)) << 16;
    v1 |= ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+2)) << 8;
    v1 |= ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+1));
    v2 = ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+3)) << 16;
    v2 |= ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+2)) << 8;
    v2 |= ((long)GetRegister(board, chip, REG_SEARCH_KEY(unit)+1));
  } while (v1 > v2);
  for (m = 0x800000L; m != 0; m >>= 1) {
    if ((v1 & m) != (v2 & m)) {
      v2 = (v2 & (0xFFFFFFL - m + 1));
      break;
    }
  }
  return (v2);
}


/*
 *  Get the key out of a halted unit and print it to the screen/logs
 */
void CheckAndPrintKey(CHIP_CTX *cp, SEARCH_CTX *ctx, int unit) {
  unsigned char key[7];
  unsigned char binKey[56];
  char buf[128];
  int i,j, goodKey;

  for (i = 0; i < 7; i++)
    key[i] = (unsigned char)GetRegister(cp->board, cp->chip,
            REG_SEARCH_KEY(unit)+i);
  if (--(key[0]) == 0xFF)                                   /* Decrement key */
    if (--(key[1]) == 0xFF)
      if (--(key[2]) == 0xFF)
        --key[3];
  for (i = 0; i < 56; i++)
    binKey[i] = (key[i/8] >> (i&7)) & 1;
  for (i = 7; i >= 0; i--) {
    j = binKey[i*7]*2 + binKey[i*7+1]*4 + binKey[i*7+2]*8 + binKey[i*7+3]*16 +
        binKey[i*7+4]*32 + binKey[i*7+5]*64 + binKey[i*7+6]*128;
    sprintf(buf+14-2*i, "%02X", j);
  }

  if (QUIET)
    printf("Halt in %02X.%02X.%02X, K=%s P=", cp->board, cp->chip, unit, buf);
  else {
    printf("BOARD 0x%02X, CHIP 0x%02X, UNIT 0x%02X HALTED!\n    K56 = ",
            cp->board, cp->chip, unit);
    for (i = 6; i >= 0; i--) printf("%02X", key[i]);
    printf("\n    K64 = %s\n", buf);
  }
  if (FP_LOG) {
    fprintf(FP_LOG, "Halt@ %02X.%02X.%02X, K=",
            cp->board, cp->chip, unit);
    for (i = 6; i >= 0; i--) fprintf(FP_LOG, "%02X", key[i]);
    if (VERBOSE) fprintf(FP_LOG, ", K64=%s", buf);
  }

  goodKey = CheckKey(binKey, ctx);                      /* prints plaintexts */

  if (QUIET) printf(goodKey ? " (OK!)\n" : " (BAD)\n");
  else printf("    ***** KEY IS %s *****\n", goodKey ? " OKAY " : "BAD");
  if (FP_LOG) fprintf(FP_LOG, goodKey ? " (=OK!)\n" : " (=BAD)\n");
  fflush(stdout);
  if (FP_LOG) fflush(FP_LOG);
}


/*
 *  Let the user see what's going on.
 */
int ServiceKeyboard(SEARCH_CTX *ctx) {
  int k, i, board, chip, reg, val;
  char buffer[128];

  while (kbhit()) {
    k = toupper(getch());
    if (k == '?') {
      printf("Keystroke options:\n    ESC=quit search\n");
      printf("    R=read a chip\n    SPACE=status\n    P=pause\n");
      printf("    S=set register\n");
      printf("Press a command letter, ENTER to continue\n");
      while (!kbhit()) {}
      continue;
    }
    if (k == 'P') {
      fprintf(stderr, "  --- PAUSED ---\n(Press a command letter, ");
      fprintf(stderr, "ENTER to continue, or ? for help.)\n");
      while (!kbhit()) {}
      continue;
    }
    if (k == 27) {
      fprintf(stderr, "  -- ESC PRESSED! HIT 'Y' TO CONFIRM HALT --\n");
      if (toupper(getch()) == 'Y') {
        fprintf(stderr, "Halting...\n");
        return (-1);
      }
      fprintf(stderr, "   (Not halting.)\n");
      continue;
    }
    if (k == ' ') {
      fprintf(stderr, "There are %ld search units running\n", ctx->totalUnits);
      fprintf(stderr, "Of %ld blocks: %ld done, %ld unstarted, %ld pending\n",
            1L<<24, ctx->totalFinishedKeyBlocks, ctx->totalUnstartedKeyBlocks,
            ctx->totalPendingKeyBlocks);
      fprintf(stderr, "The next key block to start is 0x%06lX.\n",
              ctx->nextUnstartedKeyBlock);
      fprintf(stderr, "Press a command letter or ENTER to continue\n");
      while (!kbhit()) {}
    }
    if (k == 'R') {
      fprintf(stderr, "Enter board and chip (in hex): ");
      fgets(buffer, 127, stdin);
      board = chip = -1;
      sscanf(buffer, "%x %x", &board, &chip);
      if (board < 0 || board > 255 || chip < 0 || chip > 255) {
        fprintf(stderr, "Bad board (0x%02X) or chip (0x%02X)\n", board, chip);
        continue;
      }
      for (i = 0; i < 256; i++) {
        if ((i & 15) == 0)
          printf("\n0x%02X 0x%02X 0x%02X:", board, chip, i);
        printf(" %02X", GetRegister(board, chip, i));
      }
      printf("\n");
      fprintf(stderr, "Press a command letter or ENTER to continue\n");
      while (!kbhit()) {}
      continue;
    }
    if (k == 'S') {
      fprintf(stderr, "Enter board chip reg value (all hex): ");
      fgets(buffer, 127, stdin);
      board = chip = reg = val = -1;
      sscanf(buffer, "%x %x %x %x", &board, &chip, &reg, &val);
      if (board >= 0 && chip >= 0 && reg >= 0 && val >= 0) {
        fprintf(stderr, "Writing 0x%02X to 0x%02X.0x%02X reg 0x%02X\n",
            val, board, chip, reg);
        SetRegister(board, chip, reg, val);
      }
      fprintf(stderr, "Press a command letter or ENTER to continue.\n");
      while (!kbhit()) {}
      continue;
    }
  }
  return (0);
}


/*
 *  If needed, this function can be used to decide whether keys are
 *      actually good or not to reject false positives.
 *  Returns 1 if the key is not bad, zero if it is wrong.
 */
int CheckKey(unsigned char key[56], SEARCH_CTX *ctx) {
  bool ctxt[64],ptxt0[64],ptxt1[64];
  unsigned char p0[8],p1[8];
  int i,c;

  /* Compute the plaintext and try to print it to the screen */
  for (i = 0; i < 64; i++)
    ctxt[i] = (ctx->ciphertext0[i/8] >> (i&7)) & 1;
  DecryptDES((bool*)key, ptxt0, ctxt, 0);
  for (i = 0; i < 8; i++) {
    p0[i] = (unsigned char)(ptxt0[i*8+0]+ptxt0[i*8+1]*2+ptxt0[i*8+2]*4+
           ptxt0[i*8+3]*8+ptxt0[i*8+4]*16+ptxt0[i*8+5]*32+ptxt0[i*8+6]*64+
           ptxt0[i*8+7]*128);
  }
  for (i = 0; i < 8; i++)
    p0[i] ^= ctx->plaintextXorMask[i];
  if (!QUIET) {
    printf("    Plaintext0 =");
    for (i = 7; i>=0; i--) printf(" %02X", p0[i]);
    printf("   (\"");
    for (i = 7; i>=0; i--)
      printf("%c", (p0[i] < 32) ? '?' : p0[i]);
    printf("\")\n");
  }
  if (QUIET) for (i = 7; i>=0; i--) printf("%02X", p0[i]);
  if (FP_LOG) fprintf(FP_LOG, ", ptxt=");
  if (FP_LOG) for (i = 7; i>=0; i--) fprintf(FP_LOG, "%02X", p0[i]);

  for (i = 0; i < 64; i++)
    ctxt[i] = (ctx->ciphertext1[i/8] >> (i&7)) & 1;
  DecryptDES((bool*)key, ptxt1, ctxt, 0);
  for (i = 0; i < 8; i++) {
    p1[i] = (unsigned char)(ptxt1[i*8+0]+ptxt1[i*8+1]*2+ptxt1[i*8+2]*4+
           ptxt1[i*8+3]*8+ptxt1[i*8+4]*16+ptxt1[i*8+5]*32+ptxt1[i*8+6]*64+
           ptxt1[i*8+7]*128);
  }
  if (ctx->searchInfo & 1) {                 /* if CBC mode, XOR w/ 1st ctxt */
    for (i = 0; i < 8; i++)
      p1[i] ^= ctx->ciphertext0[i];
  }
  if (!QUIET) printf("    Plaintext1 =");
  if (QUIET) printf("/");
  if (FP_LOG) fprintf(FP_LOG, "/");
  if (!QUIET) for (i = 7; i>=0; i--) printf(" %02X", p1[i]);
  if (QUIET) for (i = 7; i>=0; i--) printf("%02X", p1[i]);
  if (FP_LOG) for (i = 7; i>=0; i--) fprintf(FP_LOG, "%02X", p1[i]);
  if (!QUIET) {
    printf("   (\"");
    for (i = 7; i>=0; i--)
      printf("%c", (p1[i] < 32) ? '?' : p1[i]);
    printf("\")\n");
  }

  /* Reject key if doesn't contain good characters */
  for(i = 0; i < 8;i++) {
    if (((ctx->plaintextByteMask) >> i) & 1)
      continue;
    c = p0[i];
    if (((ctx->plaintextVector[c/8] >> (c & 7)) & 1) == 0)
      return (0);
    c = p1[i];
    if (((ctx->plaintextVector[c/8] >> (c & 7)) & 1) == 0)
      return (0);
  }

  /*
   *  INSERT ADDITIONAL CODE HERE TO REJECT FALSE POSITIVES
   */
  return (1);
}

Соседние файлы в папке CH5