home *** CD-ROM | disk | FTP | other *** search
-
- /* --- C ---
- ************************************************************************
- *
- * Filename : main.c
- * Description : Main-module - command parser
- * Part of : SECMPEG
- *
- * Version : 1.0
- * Language : C
- * For machine : SunOS 4.1.x, INTERACTIVE Unix 2.2.1, Linux, MS-DOS
- * Compile as : see Makefile
- *
- * Authors : Juergen Meyer, Frank Gadegast
- * Contact : jm@cs.tu-berlin.de, phade@cs.tu-berlin.de
- *
- ************************************************************************
- */
- #include "version.h"
- #define NEED_ERRORS
- #include "defs.h"
- #undef NEED_ERRORS
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #ifdef DOSTIME
- #include <time.h>
- #include <dos.h>
- #else
- #include <sys/timeb.h>
- #endif
-
-
- /* ------ PUBLIC ------ */
- int main (int,char **);
- int EncryptMpeg();
- int DecryptSecMpeg();
- int error_exit ();
-
-
- /* ------ PRIVAT ------ */
- static int ProcessFrame(int,unsigned long);
-
- static int GetNumberOfMakroBlocks();
- static int GetAverageMakroBlockSize(int,unsigned long);
- static int CheckIntraFrameSize(int,unsigned long);
- static int parse_commandline(int,char **);
- static void usage();
-
-
- /* ------ IMPORT ------ */
- extern int InitMemory(); /* stream.c */
- extern int FreeMemory();
- extern int OpenInputStream(char *);
- extern int OpenOutputStream(char *);
- extern void CloseStreams();
- extern int WriteStream();
- extern int ReadStream(unsigned long);
- extern void CopyBuffer();
-
- extern int ReadPictureHeader(); /* header.c */
- extern int DecodeFrame(); /* decode.c */
-
- extern int WriteSecureMpegHeader(); /* sec.c */
- extern int WriteSecureMpegInfo();
- extern int ReadSecureMpegHeader();
- extern int ReadSecureMpegInfo();
- extern unsigned long GetPictureHeader(int);
- extern int EncryptFrame(int,unsigned long);
- extern int DecryptFrame(int,unsigned long);
- extern int SetTableEntries(int,unsigned long);
- extern int CryptStream ();
- extern int CrcStream ();
-
- extern int desinit(); /* des.c */
- extern void desdone();
- extern int Encrypt(char *,unsigned long);
- extern int Decrypt(char *,unsigned long);
- extern char *string_to_key(char *);
- extern void setdeskey(char *);
-
- extern int InitHuffman(); /* huff.c */
- extern void FreeHuffTables();
-
- extern BYTE *frame_buffer; /* stream.c */
-
- extern unsigned long crc16buf (); /* crc.c */
- extern unsigned long crc32buf (); /* crc.c */
-
- /* ------ VARS ------ */
- char *progname;
- char deskey[9];
- char input_stream[128];
- char output_stream[128];
- short ENCODE = 0;
- int WRITE = TRUE;
- int VERBOSE = TRUE;
-
- int MBcount;
- int c_level = -1;
- int i_level = -1;
- int c_table_entries;
- SECUREHEADER sec_header;
- SECUREINFO sec_info;
- INTEGRTABLE i_table [1];
- SECURETABLE c_table [MAX_MB];
-
- extern int end_of_file; /* stream.h */
- extern unsigned long total_bytes_read;
- extern unsigned long total_bytes_written;
-
- extern int HorizontalSize; /* header.h */
- extern int VerticalSize;
-
- extern int MBHeight; /* decode.h */
- extern int MBWidth;
-
- extern long mvalue; /* sec.c */
-
- int main(int argc, char **argv)
- {
- int retval;
-
- #ifdef DOSTIME
- time_t t1,t2;
- extern unsigned _stklen;
-
- _stklen = 4 * 1024;
- #else
- struct timeb t1,t2;
- time_t sec;
- unsigned short msec;
- #endif
-
-
- #ifdef DEBUG
- fprintf(stderr," %s \n","secure_mpeg");
- #endif
-
- if (!parse_commandline (argc, argv))
- {
- usage ();
- error_exit (ERROR_USAGE);
- }
-
- retval = desinit();
- if (retval < 0) error_exit (retval);
- retval = InitHuffman();
- if (retval < 0) error_exit (retval);
- retval = InitMemory();
- if (retval < 0) error_exit (retval);
-
- retval = OpenInputStream (input_stream);
- if (retval < 0) error_exit (ERROR_OPEN_INPUT);
- if (WRITE)
- {
- retval = OpenOutputStream (output_stream);
- if (retval < 0) error_exit (ERROR_OPEN_OUTPUT);
- }
-
- setdeskey (deskey);
-
- #ifdef TIME
- #ifdef DOSTIME
- t1 = clock();
- #else
- ftime(&t1);
- #endif
- #endif
-
- retval = ERROR_NOTHING_TODO;
- switch (ENCODE)
- {
- case M_ENCODE :
- retval = EncryptMpeg ();
- break;
- case M_DECODE :
- retval = DecryptSecMpeg();
- break;
- case M_VALUE :
- retval = CrcStream ();
- break;
- case M_CENCRYPT :
- case M_CDECRYPT :
- retval = CryptStream (ENCODE);
- break;
- }
- if (retval != ERROR_NONE) error_exit (retval);
-
- #ifdef TIME
- #ifdef DOSTIME
- t2 = clock();
- if (VERBOSE)
- fprintf (stderr,
- "%s elapsed time %f sec.\n", progname, (t2-t1)/CLK_TCK);
- #else
- ftime(&t2);
- sec = t2.time - t1.time;
- msec = (1000 - t1.millitm)+t2.millitm;
- if (msec > 1000) msec -= 1000;
- else sec--;
-
- if (VERBOSE)
- {
- if ((!WRITE) && (ENCODE != M_VALUE))
- fprintf (stderr, "%s: elapsed time %d.%d sec. CRC-check ok.\n",
- progname, sec, msec);
- else
- if (ENCODE == M_VALUE)
- fprintf (stderr, "%s: elapsed time %d.%d sec. CRC = %ld\n",
- progname, sec, msec, mvalue);
- else
- fprintf (stderr,
- "%s: elapsed time %d.%d sec.\n", progname, sec, msec);
- }
-
- #endif
- #endif
- desdone();
- FreeHuffTables();
- FreeMemory();
-
- return (ERROR_NONE);
- }
-
-
- int EncryptMpeg()
- {
- unsigned long offset;
- unsigned long header_size;
- int picture_type;
- int i;
- int frame = 0;
- int makroblocks;
-
- do
- {
- if (!frame++)
- {
- WriteSecureMpegHeader();
- offset = GetPictureHeader (0); /* PSC in marker.h */
- if (!offset) return (ERROR_MARKER_STRUCTURE );
- CopyBuffer ();
- MBcount = GetNumberOfMakroBlocks();
- if (MBcount > MAX_MB) return (ERROR_NO_MPEGI);
- sec_info.IntegrityDataSize = -1; /* nicht vorhanden */
- sec_info.ConfidentialityDataSize = 0; /* alle Daten bis zum naechsten Header */
- sec_info.NextHeader = offset;
- WriteSecureMpegInfo();
- if (c_level > -1) EncryptFrame (0, offset);
- WriteStream ();
- }
-
- offset = GetPictureHeader(1);
- if(offset) CopyBuffer(); /* copy bits into frame_buffer */
-
- picture_type = ReadPictureHeader();
-
-
- #ifdef DEBUG
-
- switch(picture_type)
- {
- case P_PREDICTED:
- fprintf (stderr,
- "Frame : %.3d PREDICTED FRAME Size : %.5lu\n",
- frame,offset);
- break;
- case P_DCINTRA:
- fprintf (stderr,
- "Frame : %.3d DC-INTRA FRAME Size : %.5lu\n",
- frame,offset);
- break;
- case P_INTRA:
- fprintf (stderr,
- "Frame : %.3d INTRA FRAME Size : %.5lu\n",
- frame,offset);
- break;
- case P_INTERPOLATED:
- printf (stderr,
- "Frame : %.3d INTERPOLATED FRAME Size : %.5lu\n",
- frame,offset);
- break;
- default:
- /*
- picture_type = P_INTRA;
- fprintf (stderr,
- "Frame : %.3d UNKNOWN FRAME Size : %.5lu now INTRA\n",
- frame,offset);
- break;
- */
- return(picture_type);
- }
- #else
- if(picture_type < 0) return(picture_type);
- #endif
-
- ProcessFrame(picture_type,offset);
- WriteStream();
- }
- while(!end_of_file);
-
-
- sec_info.IntegrityDataSize = -1;
- sec_info.ConfidentialityDataSize = -1;
- sec_info.NextHeader = 0; /* end_of_file marker */
- WriteSecureMpegInfo();
- return (ERROR_NONE);
- }
-
- int DecryptSecMpeg()
- {
- unsigned long offset;
- int retval;
- int first_frame = 1;
- int i;
- int crc;
-
- do
- {
- if(first_frame)
- {
- retval = ReadSecureMpegHeader();
- if (retval < 0) error_exit (ERROR_NO_MPEGHEADER);
- retval = ReadSecureMpegInfo();
- if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
- offset = sec_info.NextHeader;
- retval = ReadStream (offset);
- if (retval < 0) error_exit (ERROR_STREAM);
- if (c_level > -1) DecryptFrame(0,offset);
- WriteStream();
-
- retval = ReadSecureMpegInfo();
- if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
- offset = sec_info.NextHeader;
- first_frame--;
- }
- retval = ReadStream (offset);
- if (retval < 0) error_exit (ERROR_STREAM);
-
- if (c_level > -1) DecryptFrame(sec_info.ConfidentialityDataSize,offset);
- if (i_level > -1)
- {
- switch (i_level)
- {
- case I_CRC16 :
- crc = crc16buf ((char *)frame_buffer, (unsigned long) 24);
- break;
- case I_CRC16FULL :
- crc = crc16buf ((char *)frame_buffer, i_table[0].len);
- break;
- case I_CRC32 :
- crc = crc32buf ((char *)frame_buffer, (unsigned long) 24);
- break;
- case I_CRC32FULL :
- crc = crc32buf ((char *)frame_buffer, i_table[0].len);
- break;
- default:
- error_exit (ERROR_INOTSUPPORTED);
- break;
- }
- if (crc != i_table[0].crc)
- error_exit (ERROR_CRCFAILED);
- }
- WriteStream();
-
- retval = ReadSecureMpegInfo();
- if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
- offset = sec_info.NextHeader;
-
- }
- while (!end_of_file);
- return (ERROR_NONE);
- }
-
-
- static int ProcessFrame (int picture_type,unsigned long frame_len)
- {
- int c_size;
- int mb_size = 0;
-
- sec_info.NextHeader = frame_len;
-
- if (i_level > -1)
- {
- switch (i_level)
- {
- case I_CRC16 :
- i_table[0].crc =
- crc16buf ((char *)frame_buffer, (unsigned long) 24);
- i_table[0].len = (unsigned long) 24;
- break;
- case I_CRC16FULL :
- i_table[0].crc = crc16buf ((char *)frame_buffer, frame_len);
- i_table[0].len = frame_len;
- break;
- case I_CRC32 :
- i_table[0].crc =
- crc32buf ((char *)frame_buffer, (unsigned long) 24);
- i_table[0].len = (unsigned long) 24;
- break;
- case I_CRC32FULL :
- i_table[0].crc = crc32buf ((char *)frame_buffer, frame_len);
- i_table[0].len = frame_len;
- break;
- default:
- error_exit (ERROR_INOTSUPPORTED);
- /* no Integrity-checks */
- break;
- }
- }
-
- c_size = 0;
- if (c_level > -1)
- {
- switch (c_level)
- {
- case C_24BYTE :
- c_size = 1;
- c_table[0].Offset = 0;
- c_table[0].Len = 24;
- break;
- case C_HEADER :
- c_size = SetTableEntries(8,frame_len);
- break;
- case C_HEADERMB :
- mb_size = GetAverageMakroBlockSize(MBcount,frame_len);
- c_size = SetTableEntries(mb_size,frame_len);
- break;
- case C_INTRAHEADERMB :
- if ((picture_type == P_INTRA) || (picture_type == P_DCINTRA))
- c_size = 0;
- else
- {
- mb_size = GetAverageMakroBlockSize(MBcount,frame_len);
- c_size = SetTableEntries(mb_size,frame_len);
- }
- break;
- case C_INTRACOMPLETE:
- if ((picture_type == P_INTRA) || (picture_type == P_DCINTRA))
- c_size = 0;
- else
- c_size = DecodeFrame(c_table, c_table_entries);
- break;
- default:
- error_exit (ERROR_CNOTSUPPORTED);
- break;
- }
- EncryptFrame (c_size,frame_len);
- }
-
- sec_info.IntegrityDataSize = c_size;
- sec_info.ConfidentialityDataSize = c_size;
- sec_info.NextHeader = frame_len;
- WriteSecureMpegInfo();
- return(TRUE);
- }
-
-
- /*
- Berechnung der Anzahl der MakroBl÷cke pro Frame,
- wird ben÷tigt zur AbschΣtzung, ob ein Intraframe
- vollstΣndig verschlⁿsselt wird, oder nur Teile
- davon.
- MBWidth und MBHeight mⁿssen berechnet werden, da
- VideoSequence- und GroupOfPicturesHeader nicht
- explizit gelesen werden.
-
- */
- static int GetNumberOfMakroBlocks()
- {
- MBHeight = (VerticalSize + 15) / 16;
- MBWidth = (HorizontalSize + 15) / 16;
-
- return(MBHeight * MBWidth);
-
- }
-
- static int GetAverageMakroBlockSize(int makroblocks,unsigned long frame_len)
- {
- int mb_size;
-
- mb_size = (int)(frame_len / makroblocks);
- mb_size += 7;
- mb_size >>= 3;
- mb_size <<=3;
-
- return(mb_size);
- }
- /*
- AbschΣtzung, ob der Frame vollstΣndig verschlⁿsselt
- werden soll oder nur zum Teil.
-
- avg MB Size Intra 2 Bit
- Predicted 10 Bit
- Interpoleted 16 Bit
- SliceHeader 6 Bit
-
-
- */
- static int CheckIntraFrameSize(int makroblocks,unsigned long framelen)
- {
-
- unsigned long size;
-
- size = framelen - (unsigned long)(makroblocks / 4);
-
- size /= (unsigned long)(makroblocks * 6);
-
- if(size < 16)
- return(TRUE);
- return(FALSE);
- }
-
-
- static int parse_commandline (int argc, char **argv)
- {
- int i;
-
- progname = argv [0];
- if (argc == 2)
- if (!strcmp (argv [1], "-v"))
- {
- fprintf (stderr, "%s: %s\n", progname, version_string);
- exit (0);
- }
- if (argc < 3) return (FALSE);
- for (i=1; i < argc; i++)
- {
- if (argv [i][0] == '-')
- {
- switch (argv[i][1])
- {
- case 'e' :
- ENCODE = M_ENCODE;
- c_level = atoi (argv [++i]);
- if (c_level > -1)
- strcpy (deskey, argv [++i]);
- i_level = atoi (argv [++i]);
- break;
- case 'd' :
- ENCODE = M_DECODE;
- if (argc == i+4)
- strcpy (deskey, argv [++i]);
- break;
- case 'c' :
- ENCODE = M_DECODE;
- WRITE = FALSE;
- if (argc == i+3)
- strcpy (deskey, argv [++i]);
- break;
- case 's' :
- case 'S' :
- VERBOSE = FALSE;
- break;
- case 'E' :
- ENCODE = M_CENCRYPT;
- strcpy (deskey, argv [++i]);
- break;
- case 'D' :
- ENCODE = M_CDECRYPT;
- strcpy (deskey, argv [++i]);
- break;
- case 'C' :
- ENCODE = M_VALUE;
- WRITE = FALSE;
- break;
- default :
- if (strlen (argv[i]) > 1) return (FALSE);
- break;
- }
- }
- }
-
- strcpy (input_stream, argv [argc-2]);
- strcpy (output_stream, argv [argc-1]);
- if (!WRITE) strcpy (input_stream, output_stream);
-
- sec_header.ConfidentialityInfo = (long) c_level;
- sec_header.IntegrityInfo = (long) i_level;
-
- return (TRUE);
- }
-
- static void usage()
- {
- fprintf (stderr, "usage : %s {-scedCED} [clevel key ilevel] infile.mpg [outfile.mpg]\n", progname);
- }
-
-
- int error_exit (exit_code)
- int exit_code;
- {
- FreeMemory ();
- CloseStreams ();
- desdone ();
- FreeHuffTables ();
- if (exit_code < 0)
- {
- if (strlen (error_msg [abs (exit_code)]) > 1)
- fprintf (stderr, "%s : fatal error '%s'\n",
- progname, error_msg [abs (exit_code)]);
- else fprintf (stderr, "%s : fatal error\n", progname );
- exit (exit_code);
- }
- exit (exit_code);
- }
-
-