summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fankhauser hiddenalpha.ch2023-08-29 20:28:29 +0200
committerAndreas Fankhauser hiddenalpha.ch2023-08-29 20:28:29 +0200
commit1a27bba3a8965a4db06a88e29c0ff2122813f01e (patch)
tree58277e9dccb1dc28ad69dd0ceaadfb23faa80d25
parentf9a0ae3d50fa87ca8cfd7381d785ca4ed9d52569 (diff)
downloadUnspecifiedGarbage-1a27bba3a8965a4db06a88e29c0ff2122813f01e.zip
UnspecifiedGarbage-1a27bba3a8965a4db06a88e29c0ff2122813f01e.tar.gz
Tinker around with ASN.1 stuff.
-rw-r--r--.gitignore1
-rw-r--r--configure45
-rw-r--r--src/main/c/common/commonKludge.h16
-rw-r--r--src/main/c/foo/Asn1Digger.c342
-rw-r--r--src/main/c/foo/PemCodec.c9
5 files changed, 395 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index 5fc607b..826fcc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/Makefile
+/build
diff --git a/configure b/configure
index 9e9ca77..b844b6a 100644
--- a/configure
+++ b/configure
@@ -5,6 +5,7 @@ MF="$(dirname "$0")/Makefile"
printMakefileHdr () {
+ printf '\n'
if [ -n "$WINDOOF" -a "$WINDOOF" != "0" ]; then
printf 'CC=x86_64-w64-mingw32-gcc\n'
printf 'BINEXT=.exe\n'
@@ -13,15 +14,27 @@ printMakefileHdr () {
printf 'BINEXT=\n'
fi
if [ -n "$NDEBUG" -a "$NDEBUG" != "0" ]; then
- printf 'CFLAGS=-Wall -std=c99 -Werror -fmax-errors=3 -Os -DNDEBUG=1\n'
+ printf 'CFLAGS=-Wall -std=c99 -Werror -fmax-errors=3 -DPROJECT_VERSION=$(PROJECT_VERSION) -Os -DNDEBUG=1\n'
else
- printf 'CFLAGS=-Wall -std=c99 -Werror -fmax-errors=3 -O0 -ggdb -g3\n'
+ printf 'CFLAGS=-Wall -std=c99 -Werror -fmax-errors=3 -DPROJECT_VERSION=$(PROJECT_VERSION) -O0 -ggdb -g3\n'
fi
printf 'RIMRAF=rm -rf\n'
printf 'MKDIR_P=mkdir -p\n'
+ printf 'PROJECT_VERSION=$(git describe --tags|sed '\''s,^v,,'\'')\n'
printf '\n'
if [ -z "$VERBOSE" -o "$VERBOSE" == "0" ]; then printf '.SILENT:\n'; fi
printf '\n'
+ printf 'INCDIRS=-Isrc/main/c/common\n'
+ printf '\n'
+ printf 'default: link\n'
+}
+
+
+printTarget_link () {
+ printf '\n'
+ printf 'link:\n'
+ printf 'link: build/bin/pem-codec$(BINEXT)\n'
+ printf 'link: build/bin/asn1-digger$(BINEXT)\n'
}
@@ -30,7 +43,6 @@ printTarget_clean () {
printf '.PHONY: clean\n'
printf 'clean:\n'
printf ' $(RIMRAF) build\n'
- printf '\n'
}
@@ -38,19 +50,30 @@ printTarget_PemCodec () {
printf '\n'
printf 'build/bin/pem-codec$(BINEXT):\n'
printf 'build/bin/pem-codec$(BINEXT): src/main/c/foo/PemCodec.c\n'
- printf ' @echo " LN build/bin/pem-codec$(BINEXT)"\n'
- printf ' $(MKDIR_P) build/bin\n'
- printf ' $(CC) -o build/bin/pem-codec$(BINEXT) $(CFLAGS) $^\n'
+ printf ' @echo " LN $@"\n'
+ printf ' @$(MKDIR_P) build/bin\n'
+ printf ' @$(CC) -o $@ $(CFLAGS) $^ $(INCDIRS)\n'
+}
+
+
+printTarget_Asn1Digger () {
printf '\n'
+ printf 'build/bin/asn1-digger$(BINEXT):\n'
+ printf 'build/bin/asn1-digger$(BINEXT): src/main/c/foo/Asn1Digger.c\n'
+ printf ' @echo " LN $@"\n'
+ printf ' @$(MKDIR_P) build/bin\n'
+ printf ' @$(CC) -o $@ $(CFLAGS) $^ $(INCDIRS)\n'
}
main () {
- printf '\n' > "${MF:?}"
- printMakefileHdr >> "${MF:?}"
- printTarget_clean >> "${MF:?}"
- printTarget_PemCodec >> "${MF:?}"
- printf '\n' >> "${MF:?}"
+ (
+ printMakefileHdr
+ printTarget_clean
+ printTarget_link
+ printTarget_PemCodec
+ printTarget_Asn1Digger
+ ) > "${MF:?}"
}
diff --git a/src/main/c/common/commonKludge.h b/src/main/c/common/commonKludge.h
new file mode 100644
index 0000000..e0f0cba
--- /dev/null
+++ b/src/main/c/common/commonKludge.h
@@ -0,0 +1,16 @@
+
+typedef unsigned char uchar;
+
+#define STRQUOT_ASDFASDF(s) #s
+#define STRQUOT(s) STRQUOT_ASDFASDF(s)
+#ifndef PROJECT_VERSION
+# define PROJECT_VERSION 0.0.0-SNAPSHOT
+#endif
+
+#if __WIN32
+ int _setmode(int,int);
+# define FUCK_BROKEN_SYSTEMS() do{char a=0;for(;!(a&10);){_setmode(a++,32768);}}while(0)
+#else
+# define FUCK_BROKEN_SYSTEMS()
+#endif
+
diff --git a/src/main/c/foo/Asn1Digger.c b/src/main/c/foo/Asn1Digger.c
new file mode 100644
index 0000000..6d4b011
--- /dev/null
+++ b/src/main/c/foo/Asn1Digger.c
@@ -0,0 +1,342 @@
+
+#include "commonKludge.h"
+
+/* System */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FLG_isHelp (1<<0)
+#define FLG_innIsEof (1<<1)
+#define FLG_assumeGpg (1<<2)
+#define FLG_INIT (0)
+
+#define FREAD(buf, sz, cnt, ctx) fread(buf, sz, cnt, ctx)
+#define FPRINTF(...) fprintf(__VA_ARGS__)
+#define PRINTF(...) FPRINTF(stdout, __VA_ARGS__)
+
+#ifndef NDEBUG
+# define IF_DBG(expr) expr;
+#else
+# define IF_DBG(expr)
+#endif
+
+
+typedef enum FuncToCall FuncToCall;
+typedef struct AsnDigger AsnDigger;
+
+
+enum FuncToCall {
+ FUNC_NONE=0,
+ FUNC_asnType,
+ FUNC_asnLength,
+ FUNC_asnValue,
+ FUNC_readChunkForHexDump,
+ FUNC_appendHexDump,
+};
+
+
+struct AsnDigger {
+ unsigned flg;
+ long hexCols;
+ uchar type; /* ASN.1 type */
+ unsigned len; /* ASN.1 length */
+ int hexDumpOffs; /* how many bytes we're offset into current value in context of printing it */
+ int remainValueBytes; /* how many bytes we still need to process from 'value' */
+ FuncToCall funcToCall;
+ int typeNameBuf_cap;
+ char typeNameBuf[sizeof"subType 0xFF, ContextSpecific, constructed"];
+ int asciBuf_cap, asciBuf_len;
+ char asciBuf[48+1];
+ int innBuf_cap;
+ uchar innBuf[1<<15];
+};
+
+
+/* BEG func fwd decls */
+static void constructPrintableTypename( AsnDigger*app );
+/* END func fwd decls */
+
+
+//static size_t myFread( void*restrict buf, size_t sz, size_t cnt, FILE*restrict cls ){
+// size_t ret = fread(buf, sz, cnt, cls);
+// fprintf(stderr, "fread(buf, %llu, %llu, cls) -> %llu\n", sz, cnt, ret);
+// return ret;
+//}
+
+
+static void printHelp(){
+ PRINTF("%s%s%s", " \n"
+ " ", strrchr(__FILE__,'/')+1, " @ " STRQUOT(PROJECT_VERSION) "\n"
+ " \n"
+ " Print ASN.1 from stdin to a textual representation on stdout.\n"
+ " \n"
+ " Options:\n"
+ " \n"
+ " -c <num>\n"
+ " Number of columns to use for hex-dumps. Defaults to 16.\n"
+ " \n"
+ " --gpg\n"
+ " Assume GPG and print additional info for it.\n"
+ " \n");
+}
+
+
+static int parseArgs( int argc, char**argv, AsnDigger*app ){
+ app->flg = FLG_INIT;
+ app->hexCols = 16;
+ for( int iArg=1 ; iArg<argc ; ++iArg ){
+ const char *arg = argv[iArg];
+ if(0){
+ }else if( !strcmp(arg,"--help") ){
+ app->flg |= FLG_isHelp; return 0;
+ }else if( !strcmp(arg,"-c") ){
+ arg = argv[++iArg];
+ if( iArg >= argc ){ FPRINTF(stderr,"EINVAL: -c needs value\n"); return -1; }
+ errno = 0;
+ app->hexCols = strtol(arg, NULL, 0);
+ if( errno != 0 ){ FPRINTF(stderr, "EINVAL: -c: %s\n", strerror(errno)); return -1; }
+ }else if( !strcmp(arg, "--gpg") ){
+ app->flg |= FLG_assumeGpg;
+ }else if( !strcmp(arg, "--no-gpg") ){
+ app->flg &= ~FLG_assumeGpg;
+ }else{
+ FPRINTF(stderr, "EINVAL: '%s'\n", arg); return -1;
+ }
+ }
+ if( app->hexCols <= 0 || app->hexCols > 48 ){
+ FPRINTF(stderr, "ENOTSUP: %ld hex columns not supported.\n", app->hexCols); return -1;
+ }
+ return 0;
+}
+
+
+//static unsigned char* ucharPtrOfcharPtr( char*c ){ return (void*)c; }
+//static char* charPtrOfucharPtr( unsigned char*c ){ return (void*)c; }
+
+
+static int asnType( AsnDigger*app ){
+ size_t sz;
+ int err;
+ uchar type[1];
+ sz = FREAD(type, 1, 1, stdin);
+ if( sz != 1 ){
+ err = errno;
+ if( feof(stdin) ){
+ app->flg |= FLG_innIsEof;
+ IF_DBG(app->funcToCall = FUNC_NONE);
+ return 0;
+ }else{
+ FPRINTF(stderr, "%s STDIN: %s\n", strrchr(__FILE__,'/')+1, strerror(err));
+ return -err;
+ }
+ }
+ app->type = type[0];
+ app->funcToCall = FUNC_asnLength;
+ return 0;
+}
+
+
+static int asnLength( AsnDigger*app ){
+ size_t sz;
+ int err;
+ uchar len[1];
+ sz = FREAD(len, 1, 1, stdin);
+ if( sz != 1 ){
+ if( feof(stdin) ){
+ app->flg |= FLG_innIsEof;
+ IF_DBG(app->funcToCall = FUNC_NONE);
+ return 0;
+ }else{
+ err = errno;
+ FPRINTF(stderr, "%s STDIN: %s\n", strrchr(__FILE__,'/')+1, strerror(err));
+ return -err;
+ }
+ }
+ assert(len[0] < 0x7F && "TODO_20230829164221");
+ app->len = len[0];
+ app->funcToCall = FUNC_asnValue;
+ return 0;
+}
+
+
+static int asnValue( AsnDigger*app ){
+
+ constructPrintableTypename(app);
+ PRINTF("ASN.1 type 0x%02X, len %d (%s), value:", app->type, app->len, app->typeNameBuf);
+
+ if( app->len == 0 ){
+ /* no payload. Ready to go to next tag. */
+ app->funcToCall = FUNC_asnType;
+ return 0;
+ }
+
+ /* go process payload */
+ app->remainValueBytes = app->len;
+ app->funcToCall = FUNC_readChunkForHexDump;
+ return 0;
+}
+
+
+static int readChunkForHexDump( AsnDigger*app ){
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
+ #define IS_PRINTABLE(c) (c >= 0x20 && c <= 0x7E)
+ int err;
+
+ size_t readLen = FREAD(app->innBuf, 1, MIN(app->remainValueBytes, app->innBuf_cap), stdin);
+ if( readLen == 0 ){
+ err = errno;
+ if( feof(stdin) ){
+ app->flg |= FLG_innIsEof;
+ IF_DBG(app->funcToCall = FUNC_NONE);
+ if( app->remainValueBytes > 0 ){
+ FPRINTF(stderr, "%s STDIN: Unexpected EOF\n", strrchr(__FILE__,'/')+1);
+ return -1;
+ }
+ return 0;
+ }else{
+ FPRINTF(stderr, "%s STDIN: %s\n", strrchr(__FILE__,'/')+1, strerror(err));
+ return -1;
+ }
+ }
+ assert(app->remainValueBytes >= readLen);
+ app->remainValueBytes -= readLen;
+ app->funcToCall = FUNC_appendHexDump;
+ return 0;
+}
+
+
+static int appendHexDump( AsnDigger*app ){
+
+ if( app->flg & FLG_assumeGpg ){
+ if( app->type == 0x95 ){
+ PRINTF("\nGPG secret key packet, version %d", app->innBuf[1]);
+ }else if( app->type == 0x99 && app->len == 1 && app->innBuf[0] == 0x0D ){
+ puts("\nGPG certificate");
+ }
+ }
+
+ assert(!"TODO_20230829200858");
+ /* 1st buffer already loaded above. So begin at printing step. */
+// goto printNewline;
+//
+//readNexChunk:
+// if( app->remainValueBytes == 0) goto TODO_20230829193554;
+// readLen = FREAD(app->innBuf, 1, MIN(app->remainValueBytes, app->innBuf_cap), stdin);
+// if( readLen == 0 ){
+// err = errno;
+// if( feof(stdin) ){
+// assert(!ferror(stdin));
+// FPRINTF(stderr, "%s STDIN: Unexpected EndOfFile\n", strrchr(__FILE__,'/')+1);
+// app->flg |= FLG_innIsEof;
+// }else{
+// assert(ferror(stdin));
+// FPRINTF(stderr, "%s STDIN: %s\n", strrchr(__FILE__,'/')+1, strerror(errno));
+// }
+// return -1;
+// }
+// assert(app->remainValueBytes >= readLen);
+// app->remainValueBytes -= readLen;
+//
+//printNewline:
+// assert(app->asciBuf_len % app->hexCols == 0);
+// PRINTF(" %.*s\n %08X:", app->asciBuf_len, app->asciBuf, app->hexDumpOffs);
+// app->asciBuf_len = 0;
+//
+//printHexCol:
+// for(; iInn - innOff < readLen ; ++iInn,++app->hexDumpOffs ){
+// PRINTF(" %02X", app->buf[iInn]);
+// /* cache ASCI part (right column of hex-dump) to write it later at EOL */
+// app->buf[app->asciBuf_len++] = IS_PRINTABLE(app->buf[iInn]) ? app->buf[iInn] : '.';
+// }
+//
+//printAsciCol:
+// if( app->asciBuf_len > 0 && (iInn-innOff>=readLen || app->hexDumpOffs % app->hexCols == 0) ){
+// err = (iInn - innOff) % app->hexCols;
+// for(; err < app->hexCols ; ++err ){ PRINTF(" "); }
+// PRINTF(" %.*s\n", app->asciBuf_len, app->buf);
+// app->asciBuf_len = 0;
+// }
+//
+// app->funcToCall = FUNC_asnType;
+ return 0;
+ #undef MIN
+ #undef IS_PRINTABLE
+}
+
+
+static void constructPrintableTypename( AsnDigger*app ){
+ int err;
+ switch( app->type ){
+ case 0x00: memcpy(app->typeNameBuf, "EndOfContent", 13); break;
+ case 0x02: memcpy(app->typeNameBuf, "integer", 8); break;
+ case 0x04: memcpy(app->typeNameBuf, "octet string", 13); break;
+ case 0x0C: memcpy(app->typeNameBuf, "utf8 string", 12); break;
+ default:
+ /* construct some generified name with help of passed buffer */
+ const char *tagClass;
+ if( (app->type & 0xC0) == 0 ){ tagClass = "Universal"; }
+ else if( (app->type & 0x40) == 0 ){ tagClass = "Application"; }
+ else if( (app->type & 0x80) == 0 ){ tagClass = "ContextSpecific"; }
+ else{ tagClass = "Private"; }
+ const char *primOrConstr = (app->type & 0x20) ? "constructed" : "primitive";
+ int isLongType = (app->type & 0x1F) == 0x1F;
+ if( isLongType ){
+ err = snprintf(app->typeNameBuf, app->typeNameBuf_cap, "LongType, %s, %s",
+ tagClass, primOrConstr);
+ assert(err < app->typeNameBuf_cap);
+ }else{
+ err = snprintf(app->typeNameBuf, app->typeNameBuf_cap, "subType 0x%02X, %s, %s",
+ app->type & 0x1F, tagClass, primOrConstr);
+ assert(err < app->typeNameBuf_cap);
+ }
+ }
+}
+
+
+static int run( AsnDigger*app ){
+ int err;
+ app->funcToCall = FUNC_asnType;
+ while( (app->flg & FLG_innIsEof) == 0 ){
+ switch( app->funcToCall ){
+ case FUNC_asnType: err = asnType(app); break;
+ case FUNC_asnLength: err = asnLength(app); break;
+ case FUNC_asnValue: err = asnValue(app); break;
+ case FUNC_readChunkForHexDump: err = readChunkForHexDump(app); break;
+ case FUNC_appendHexDump: err = appendHexDump(app); break;
+ default:
+ IF_DBG(FPRINTF(stderr,"Whops %d %s:%d\n", app->funcToCall, __FILE__, __LINE__));
+ abort();
+ }
+ if( err != 0 ){ return err; }
+ }
+ return 0;
+}
+
+
+int main( int argc, char**argv ){
+ int err;
+ AsnDigger app;
+ #define app (&app)
+ app->typeNameBuf_cap = sizeof app->typeNameBuf;
+ app->asciBuf_cap = sizeof app->asciBuf;
+ app->asciBuf_len = 0;
+ app->innBuf_cap = sizeof app->innBuf;
+
+ if( (err=parseArgs(argc, argv, app)) != 0 ){ goto endFn; }
+
+ if( app->flg & FLG_isHelp ){ printHelp(app); err = 0; goto endFn; }
+
+ FUCK_BROKEN_SYSTEMS();
+
+ err = run(app);
+
+endFn:
+ return !!err;
+ #undef app
+}
+
+
+
diff --git a/src/main/c/foo/PemCodec.c b/src/main/c/foo/PemCodec.c
index 79f486e..d2531f0 100644
--- a/src/main/c/foo/PemCodec.c
+++ b/src/main/c/foo/PemCodec.c
@@ -1,19 +1,14 @@
+#include "commonKludge.h"
+
/* System */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#define STRQUOT_ASDFASDF(s) #s
-#define STRQUOT(s) STRQUOT_ASDFASDF(s)
-#ifndef PROJECT_VERSION
-# define PROJECT_VERSION 0.0.0-SNAPSHOT
-#endif
#define BUF_CAP (1<<15)
-
typedef struct PemCodec PemCodec;