Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 *
 * Adobe's encryption/decryption algorithm for eexec and show. Runs in
 * eexec mode unless told otherwise. Use,
 *
 *              pscrypt file.cypher > file.clear
 *
 * to decrypt eexec input. Assumes file.cypher is hex with the key as the
 * first four bytes, and writes file.clear as binary (omitting the key).
 * Use
 *
 *              pscrypt -e12ab34ef file.clear >file.cypher
 *
 * to encrypt file.clear (for eexec) using 12ab34ef as the key. Input is
 * binary and output is hex. The key must be given as a hex number. Use
 * -sshow to encrypt or decrypt a CharString or Subr,
 *
 *              pscrypt -sshow file.cypher > file.clear
 *
 * Use -b or -x to read binary or hex input, and -B or -X to output binary
 * or hex.
 *
 */

#include <stdio.h>
#include <ctype.h>

#define ENCRYPT         0
#define DECRYPT         1

#define NOTSET          -1
#define BINARY          0
#define HEX             1
#define LINELENGTH      40

#define CHARSTRING      4330
#define EEXEC           55665
#define MAGIC1          52845
#define MAGIC2          22719

int     argc;
char    **argv;

int     mode = DECRYPT;
int     input = NOTSET;
int     output = NOTSET;
int     outoffset = NOTSET;
int     inoffset = NOTSET;

int     cryptkey = 0;                   /* encryption key set with -e */
int     linelength = LINELENGTH;        /* only for hex output */
int     lastchar = 0;

unsigned long   seed = EEXEC;
unsigned long   key;

FILE    *fp_in = stdin;

/*****************************************************************************/

main(agc, agv)

    int         agc;
    char        *agv[];

{

/*
 *
 * Implementation of the encryption/decryption used by eexec and show.
 *
 */

    argc = agc;
    argv = agv;

    options();
    initialize();
    arguments();

    exit(0);

}   /* End of main */

/*****************************************************************************/

options()

{

    int         ch;
    char        *names = "bde:l:os:xBSX";

    extern char *optarg;
    extern int  optind;

/*
 *
 * Command line options.
 *
 */

    while ( (ch = getopt(argc, argv, names)) != EOF )
        switch ( ch ) {
            case 'b':                   /* binary input */
                    input = BINARY;
                    break;

            case 'd':                   /* decrypt */
                    mode = DECRYPT;
                    break;

            case 'e':                   /* encrypt */
                    mode = ENCRYPT;
                    if ( *optarg == '0' && *optarg == 'x' )
                        optarg += 2;
                    sscanf(optarg, "%8x", &cryptkey);
                    break;

            case 'l':                   /* line length hex output */
                    linelength = atoi(optarg);
                    break;

            case 'o':                   /* output all bytes - debugging */
                    outoffset = 0;
                    break;

            case 's':                   /* seed */
                    if ( *optarg == 'e' )
                        seed = EEXEC;
                    else if ( *optarg == 's' )
                        seed = CHARSTRING;
                    else if ( *optarg == '0' && *(optarg+1) == 'x' )
                        sscanf(optarg+2, "%x", &seed);
                    else if ( *optarg == '0' )
                        sscanf(optarg, "%o", &seed);
                    else sscanf(optarg, "%d", &seed);
                    break;

            case 'x':                   /* hex input */
                    input = HEX;
                    break;

            case 'B':                   /* binary output */
                    output = BINARY;
                    break;

            case 'X':                   /* hex output */
                    output = HEX;
                    break;

            case '?':                   /* don't understand the option */
                    fprintf(stderr, "bad option -%c\n", ch);
                    exit(1);
                    break;

            default:                    /* don't know what to do for ch */
                    fprintf(stderr, "missing case for option -%c\n", ch);
                    exit(1);
                    break;
        }   /* End switch */

    argc -= optind;                     /* get ready for non-option args */
    argv += optind;

}   /* End of options */

/*****************************************************************************/

initialize()

{

/*
 *
 * Initialization that has to be done after the options.
 *
 */

    key = seed;

    if ( mode == DECRYPT ) {
        input = (input == NOTSET) ? HEX : input;
        output = (output == NOTSET) ? BINARY : output;
        inoffset = (inoffset == NOTSET) ? 0 : inoffset;
        outoffset = (outoffset == NOTSET) ? -4 : outoffset;
    } else {
        input = (input == NOTSET) ? BINARY : input;
        output = (output == NOTSET) ? HEX : output;
        inoffset = (inoffset == NOTSET) ? 4 : inoffset;
        outoffset = (outoffset == NOTSET) ? 0 : outoffset;
    }   /* End else */

    if ( linelength <= 0 )
        linelength = LINELENGTH;

}   /* End of initialize */

/*****************************************************************************/

arguments()

{

/*
 *
 * Everything left is an input file. No arguments or '-' means stdin.
 *
 */

    if ( argc < 1 )
        crypt();
    else
        while ( argc > 0 ) {
            if ( strcmp(*argv, "-") == 0 )
                fp_in = stdin;
            else if ( (fp_in = fopen(*argv, "r")) == NULL ) {
                fprintf(stderr, "can't open %s\n", *argv);
                exit(1);
            }   /* End if */
            crypt();
            if ( fp_in != stdin )
                fclose(fp_in);
            argc--;
            argv++;
        }   /* End while */

}   /* End of arguments */

/*****************************************************************************/

crypt()

{

    unsigned int        cypher;
    unsigned int        clear;

/*
 *
 * Runs the encryption/decryption algorithm.
 *
 */

    while ( lastchar != EOF ) {
        cypher = nextbyte();
        clear = ((key >> 8) ^ cypher) & 0xFF;
        key = (key + (mode == DECRYPT ? cypher : clear)) * MAGIC1 + MAGIC2;
        if ( ++outoffset > 0 && lastchar != EOF ) {
            if ( output == HEX ) {
                printf("%.2X", clear);
                if ( linelength > 0 && (outoffset % linelength) == 0 )
                    putchar('\n');
            } else putchar(clear);
        }   /* End if */
    }   /* End while */

}   /* End of crypt */

/*****************************************************************************/

nextbyte()

{

    int         val = EOF;

/*
 *
 * Returns the next byte. Uses cryptkey (i.e. what followed -e) while inoffset is
 * positive, otherwise reads (hex or binary) from fp_in.
 *
 */

    if ( inoffset-- > 0 )
        val = (cryptkey >> (inoffset*8)) & 0xFF;
    else if ( input == HEX ) {
        if ( (val = nexthexchar()) != EOF )
            val = (val << 4) | nexthexchar();
    } else if ( input == BINARY )
        val = Getc(fp_in);

    return(val);

}   /* End of nextbyte */

/*****************************************************************************/

nexthexchar()

{

    int         ch;

/*
 *
 * Reads the next hex character.
 *
 */

    while ( (ch = Getc(fp_in)) != EOF && ! isxdigit(ch) ) ;

    if ( isdigit(ch) )
        ch -= '0';
    else if ( isupper(ch) )
        ch -= 'A' - 10;
    else if ( islower(ch) )
        ch -= 'a' - 10;

    return(ch);

}   /* End of nexthexchar */

/*****************************************************************************/

Getc(fp)

    FILE        *fp;

{

/*
 *
 * Reads the next byte from *fp, sets lastchar, and returns the character.
 *
 */

    return(lastchar = getc(fp));

}   /* End of Getc */

/*****************************************************************************/