⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dumpasn1.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ASN.1 object dumping code, copyright Peter Gutmann
   <pgut001@cs.auckland.ac.nz>, based on ASN.1 dump program by David Kemp
   <dpkemp@missi.ncsc.mil>, with contributions from various people including
   Matthew Hamrick <hamrick@rsa.com>, Bruno Couillard
   <bcouillard@chrysalis-its.com>, Hallvard Furuseth
   <h.b.furuseth@usit.uio.no>, Geoff Thorpe <geoff@raas.co.nz>, David Boyce
   <d.boyce@isode.com>, John Hughes <john.hughes@entegrity.com>, Life is hard,
   and then you die <ronald@trustpoint.com>, Hans-Olof Hermansson
   <hans-olof.hermansson@postnet.se>, Tor Rustad <Tor.Rustad@bbs.no>, and
   several other people whose names I've misplaced.

   Available from http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c.
   Last updated 27 October 2001.

   This version of dumpasn1 requires a config file dumpasn1.cfg to be present
   in the same location as the program itself or in a standard directory
   where binaries live (it will run without it but will display a warning
   message, you can configure the path either by hardcoding it in or using an
   environment variable as explained further down).  The config file is
   available from http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg.

   This code assumes that the input data is binary, having come from a MIME-
   aware mailer or been piped through a decoding utility if the original
   format used base64 encoding.  Bruno Couillard has created a modified
   version which will read raw base64-encoded data (ie without any MIME
   encapsulation or other headers) directly, at the expense of being somewhat
   non-portable.  Alternatively, you can use utilities like uudeview (which
   will strip virtually any kind of encoding, MIME, PEM, PGP, whatever) to
   recover the binary original.

   You can use this code in whatever way you want, as long as you don't try
   to claim you wrote it.

   Editing notes: Tabs to 4, phasers to stun */

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

/* The update string, printed as part of the help screen */

#define UPDATE_STRING	"27 October 2001"

/* Useful defines */

#ifndef TRUE
  #define FALSE	0
  #define TRUE	( !FALSE )
#endif /* TRUE */

/* Tandem Guardian NonStop Kernel options */

#ifdef __TANDEM
  #pragma nolist		/* Spare us the source listing, no GUI... */
  #pragma nowarn (1506)	/* Implicit type conversion: int to char etc */
#endif /* __TANDEM */

/* SunOS 4.x doesn't define seek codes or exit codes or FILENAME_MAX (it does
   define _POSIX_MAX_PATH, but in funny locations and to different values
   depending on which include file you use).  Strictly speaking this code
   isn't right since we need to use PATH_MAX, however not all systems define
   this, some use _POSIX_PATH_MAX, and then there are all sorts of variations
   and other defines you have to check which require about a page of code to
   cover each OS, so we just use max( FILENAME_MAX, 512 ) which should work
   for everything */

#ifndef SEEK_SET
  #define SEEK_SET	0
  #define SEEK_CUR	2
#endif /* No fseek() codes defined */
#ifndef EXIT_FAILURE
  #define EXIT_FAILURE	1
  #define EXIT_SUCCESS	( !EXIT_FAILURE )
#endif /* No exit() codes defined */
#ifndef FILENAME_MAX
  #define FILENAME_MAX	512
#else
  #if FILENAME_MAX < 128
	#undef FILENAME_MAX
	#define FILENAME_MAX	512
  #endif /* FILENAME_MAX < 128 */
#endif /* FILENAME_MAX */

/* Under Windows we can do special-case handling for things like BMPStrings */

#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \
	  defined( __WIN32__ ) )
  #define __WIN32__
#endif /* Win32 */

/* Under Unix we can do special-case handling for paths.  Detecting this is
   a bit tricky but the following should find most versions */

#if defined( linux ) || defined( __linux__ ) || defined( sun ) || \
	defined( __bsdi__ ) || defined( __FreeBSD__ ) || \
	defined( __OpenBSD__ ) || defined( __hpux ) || defined( _M_XENIX ) || \
	defined( __osf__ ) || defined( _AIX )
  #define __UNIX__
#endif /* Every commonly-used Unix */

/* Tandem NSK: Don't use __TANDEM__, which violates the ISO C reserved name
   space, also don't mangle with Tandem OSS, which is almost UNIX */

#ifdef __TANDEM
  #ifdef _GUARDIAN_TARGET
	#define TANDEM_NSK
  #else
	#define __UNIX__
  #endif /* _GUARDIAN_TARGET */
#endif /* __TANDEM */

/* Some OS's don't define the min() macro */

#ifndef min
  #define min(a,b)		( ( a ) < ( b ) ? ( a ) : ( b ) )
#endif /* !min */

/* The level of recursion can get scary for deeply-nested structures so we
   use a larger-than-normal stack under DOS */

#ifdef  __TURBOC__
  extern unsigned _stklen = 16384;
#endif /* __TURBOC__ */

/* When we dump a nested data object encapsulated within a larger object, the
   length is initially set to a magic value which is adjusted to the actual
   length once we start parsing the object */

#define LENGTH_MAGIC	177545L

/* Tag classes */

#define CLASS_MASK		0xC0	/* Bits 8 and 7 */
#define UNIVERSAL		0x00	/* 0 = Universal (defined by ITU X.680) */
#define APPLICATION		0x40	/* 1 = Application */
#define CONTEXT			0x80	/* 2 = Context-specific */
#define PRIVATE			0xC0	/* 3 = Private */

/* Encoding type */

#define FORM_MASK		0x20	/* Bit 6 */
#define PRIMITIVE		0x00	/* 0 = primitive */
#define CONSTRUCTED		0x20	/* 1 = constructed */

/* Universal tags */

#define TAG_MASK		0x1F	/* Bits 5 - 1 */
#define EOC				0x00	/*  0: End-of-contents octets */
#define BOOLEAN			0x01	/*  1: Boolean */
#define INTEGER			0x02	/*  2: Integer */
#define BITSTRING		0x03	/*  2: Bit string */
#define OCTETSTRING		0x04	/*  4: Byte string */
#define NULLTAG			0x05	/*  5: NULL */
#define OID				0x06	/*  6: Object Identifier */
#define OBJDESCRIPTOR	0x07	/*  7: Object Descriptor */
#define EXTERNAL		0x08	/*  8: External */
#define REAL			0x09	/*  9: Real */
#define ENUMERATED		0x0A	/* 10: Enumerated */
#define EMBEDDED_PDV	0x0B	/* 11: Embedded Presentation Data Value */
#define UTF8STRING		0x0C	/* 12: UTF8 string */
#define SEQUENCE		0x10	/* 16: Sequence/sequence of */
#define SET				0x11	/* 17: Set/set of */
#define NUMERICSTRING	0x12	/* 18: Numeric string */
#define PRINTABLESTRING	0x13	/* 19: Printable string (ASCII subset) */
#define T61STRING		0x14	/* 20: T61/Teletex string */
#define VIDEOTEXSTRING	0x15	/* 21: Videotex string */
#define IA5STRING		0x16	/* 22: IA5/ASCII string */
#define UTCTIME			0x17	/* 23: UTC time */
#define GENERALIZEDTIME	0x18	/* 24: Generalized time */
#define GRAPHICSTRING	0x19	/* 25: Graphic string */
#define VISIBLESTRING	0x1A	/* 26: Visible string (ASCII subset) */
#define GENERALSTRING	0x1B	/* 27: General string */
#define UNIVERSALSTRING	0x1C	/* 28: Universal string */
#define BMPSTRING		0x1E	/* 30: Basic Multilingual Plane/Unicode string */

/* Length encoding */

#define LEN_XTND  0x80		/* Indefinite or long form */
#define LEN_MASK  0x7F		/* Bits 7 - 1 */

/* Various special-case operations to perform on strings */

typedef enum {
	STR_NONE,				/* No special handling */
	STR_UTCTIME,			/* Check it's UTCTime */
	STR_GENERALIZED,		/* Check it's GeneralizedTime */
	STR_PRINTABLE,			/* Check it's a PrintableString */
	STR_IA5,				/* Check it's an IA5String */
	STR_BMP,				/* Read and display string as Unicode */
	STR_BMP_REVERSED		/* STR_BMP with incorrect endianness */
	} STR_OPTION;

/* Structure to hold info on an ASN.1 item */

typedef struct {
	int id;						/* Identifier */
	int tag;					/* Tag */
	long length;				/* Data length */
	int indefinite;				/* Item has indefinite length */
	int headerSize;				/* Size of tag+length */
	unsigned char header[ 8 ];	/* Tag+length data */
	} ASN1_ITEM;

/* Config options */

static int printDots = FALSE;		/* Whether to print dots to align columns */
static int doPure = FALSE;			/* Print data without LHS info column */
static int doDumpHeader = FALSE;	/* Dump tag+len in hex (level = 0, 1, 2) */
static int extraOIDinfo = FALSE;	/* Print extra information about OIDs */
static int doHexValues = FALSE;		/* Display size, offset in hex not dec.*/
static int useStdin = FALSE;		/* Take input from stdin */
static int zeroLengthAllowed = FALSE;/* Zero-length items allowed */
static int dumpText = FALSE;		/* Dump text alongside hex data */
static int printAllData = FALSE;	/* Whether to print all data in long blocks */
static int checkEncaps = TRUE;		/* Print encaps.data in BIT/OCTET STRINGs */
static int reverseBitString = TRUE;	/* Print BIT STRINGs in natural order */

/* Error and warning information */

static int noErrors = 0;			/* Number of errors found */
static int noWarnings = 0;			/* Number of warnings */

/* Position in the input stream */

static int fPos = 0;				/* Absolute position in data */

/* The output stream */

static FILE *output;				/* Output stream */

/* Information on an ASN.1 Object Identifier */

#define MAX_OID_SIZE	32

typedef struct tagOIDINFO {
	struct tagOIDINFO *next;		/* Next item in list */
	char oid[ MAX_OID_SIZE ], *comment, *description;
	int oidLength;					/* Name, rank, serial number */
	int warn;						/* Whether to warn if OID encountered */
	} OIDINFO;

static OIDINFO *oidList = NULL;

/* If the config file isn't present in the current directory, we search the
   following paths (this is needed for Unix with dumpasn1 somewhere in the
   path, since this doesn't set up argv[0] to the full path).  Anything
   beginning with a '$' uses the appropriate environment variable.  In
   addition under Unix we also walk down $PATH looking for it */

#ifdef TANDEM_NSK
  #define CONFIG_NAME		"asn1cfg"
#else
  #define CONFIG_NAME		"dumpasn1.cfg"
#endif /* TANDEM_NSK */

#if defined( TANDEM_NSK )

static const char *configPaths[] = {
	"$system.security", "$system.system",
	NULL
	};

#elif defined( __WIN32__ )

static const char *configPaths[] = {
	/* Windoze absolute paths.  Usually things are on C:, but older NT setups
	   are easier to do on D: if the initial copy is done to C: */
	"c:\\dos\\", "d:\\dos\\", "c:\\windows\\", "d:\\windows\\",
	"c:\\winnt\\", "d:\\winnt\\",

	/* It's my program, I'm allowed to hardcode in strange paths which noone
	   else uses */
	"c:\\program files\\bin\\",

	/* General environment-based paths */
	"$DUMPASN1_PATH/",

	NULL
	};

#else

static const char *configPaths[] = {
	/* Unix absolute paths */
	"/bin/", "/usr/bin/", "/usr/local/bin/",

	/* It's my program, I'm allowed to hardcode in strange paths which noone
	   else uses */
	"$HOME/BIN/",

	/* Unix environment-based paths */
	"$HOME/", "$HOME/bin/",

	/* General environment-based paths */
	"$DUMPASN1_PATH/",

	NULL
	};
#endif /* OS-specific search paths */

#define isEnvTerminator( c )	\
	( ( ( c ) == '/' ) || ( ( c ) == '.' ) || ( ( c ) == '$' ) || \
	  ( ( c ) == '\0' ) || ( ( c ) == '~' ) )

/****************************************************************************
*																			*
*					Object Identification/Description Routines				*
*																			*
****************************************************************************/

/* Return descriptive strings for universal tags */

char *idstr( const int tagID )
	{
	switch( tagID )
		{
		case EOC:
			return( "End-of-contents octets" );
		case BOOLEAN:
			return( "BOOLEAN" );
		case INTEGER:
			return( "INTEGER" );
		case BITSTRING:
			return( "BIT STRING" );
		case OCTETSTRING:
			return( "OCTET STRING" );
		case NULLTAG:
			return( "NULL" );
		case OID:
			return( "OBJECT IDENTIFIER" );
		case OBJDESCRIPTOR:
			return( "ObjectDescriptor" );
		case EXTERNAL:
			return( "EXTERNAL" );
		case REAL:
			return( "REAL" );
		case ENUMERATED:
			return( "ENUMERATED" );
		case EMBEDDED_PDV:
			return( "EMBEDDED PDV" );
		case UTF8STRING:
			return( "UTF8String" );
		case SEQUENCE:
			return( "SEQUENCE" );
		case SET:
			return( "SET" );
		case NUMERICSTRING:
			return( "NumericString" );
		case PRINTABLESTRING:
			return( "PrintableString" );
		case T61STRING:
			return( "TeletexString" );
		case VIDEOTEXSTRING:
			return( "VideotexString" );
		case IA5STRING:
			return( "IA5String" );
		case UTCTIME:
			return( "UTCTime" );
		case GENERALIZEDTIME:
			return( "GeneralizedTime" );
		case GRAPHICSTRING:
			return( "GraphicString" );
		case VISIBLESTRING:
			return( "VisibleString" );
		case GENERALSTRING:
			return( "GeneralString" );
		case UNIVERSALSTRING:
			return( "UniversalString" );
		case BMPSTRING:
			return( "BMPString" );
		default:
			return( "Unknown (Reserved)" );
		}
	}

/* Return information on an object identifier */

static OIDINFO *getOIDinfo( char *oid, const int oidLength )
	{
	OIDINFO *oidPtr;

	memset( oid + oidLength, 0, 2 );
	for( oidPtr = oidList; oidPtr != NULL; oidPtr = oidPtr->next )
		if( oidLength == oidPtr->oidLength - 2 && \
			!memcmp( oidPtr->oid + 2, oid, oidLength ) )
			return( oidPtr );

	return( NULL );
	}

/* Add an OID attribute */

static int addAttribute( char **buffer, char *attribute )
	{
	if( ( *buffer = ( char * ) malloc( strlen( attribute ) + 1 ) ) == NULL )
		{
		puts( "Out of memory." );
		return( FALSE );
		}
	strcpy( *buffer, attribute );
	return( TRUE );
	}

/* Table to identify valid string chars (taken from cryptlib) */

#define P	1						/* PrintableString */
#define I	2						/* IA5String */
#define PI	3						/* IA5String and PrintableString */

static int charFlags[] = {
	/* 00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F */
		0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
	/* 10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F */
		0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
	/*		!	"	#	$	%	&	'	(	)	*	+	,	-	.	/ */
	   PI,	I,	I,	I,	I,	I,	I, PI, PI, PI,	I, PI, PI, PI, PI, PI,
	/*	0	1	2	3	4	5	6	7	8	9	:	;	<	=	>	? */
	   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,	I,	I, PI,	I, PI,
	/*	@	A	B	C	D	E	F	G	H	I	J	K	L	M	N	O */
		I, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,
	/*	P	Q	R	S	T	U	V	W	X	Y	Z	[	\	]	^ _ */
	   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,	I,	I,	I,	I,	I,
	/*	`	a	b	c	d	e	f	g	h	i	j	k	l	m	n	o */
		I, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,
	/*	p	q	r	s	t	u	v	w	x	y	z	{	|	}	~  DL */
	   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,	I,	I,	I,	I,	0
	};

static int isPrintable( int ch )
	{
	if( ch >= 128 || !( charFlags[ ch ] & P ) )
		return( FALSE );
	return( TRUE );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -