X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/5c3f75ec49019d160806489824fc76652a2ef444..813390c45f438f411662b1a55678e63f11681eb4:/cc.h diff --git a/cc.h b/cc.h index 7c2c092..f3a03f3 100644 --- a/cc.h +++ b/cc.h @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: cc.h,v 1.1 2004/04/17 09:58:37 mdw Exp $ + * $Id$ * * Catcrypt common stuff * * (c) 2004 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,12 +15,12 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, @@ -36,7 +36,16 @@ /*----- Header files ------------------------------------------------------*/ +#if _FILE_OFFSET_BITS != 64 +# error "Must set _FILE_OFFSET_BITS to 64." +#endif + #include +#include +#include + +#include +#include #include @@ -45,7 +54,7 @@ #include "ghash.h" #include "gmac.h" -/*----- Data structures ---------------------------------------------------*/ +/*----- Cryptographic object tables ---------------------------------------*/ /* --- Key encapsulation --- */ @@ -67,44 +76,13 @@ typedef struct kemops { void (*destroy)(kem */*k*/); } kemops; -/* --- Signing --- */ - -typedef struct sig { - const struct sigops *ops; - key_packdef *kp; - void *kd; - ghash *h; -} sig; - -typedef struct sigops { - const key_fetchdef *kf; /* Key fetching structure */ - size_t kdsz; /* Size of the key-data structure */ - sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/); - int (*doit)(sig */*s*/, dstr */*d*/); - const char *(*check)(sig */*s*/); - void (*destroy)(sig */*s*/); -} sigops; - -/* --- Data encoding --- */ - -typedef struct enc { - const struct encops *ops; - FILE *fp; -} enc; - -typedef struct encops { +struct kemtab { const char *name; - const char *rmode, *wmode; - enc *(*initenc)(FILE */*fp*/, const char */*msg*/); - enc *(*initdec)(FILE */*fp*/, const char */*msg*/); - int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/); - int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/); - int (*encdone)(enc */*e*/); - int (*decdone)(enc */*e*/); - void (*destroy)(enc */*e*/); -} encops; + const kemops *encops; + const kemops *decops; +}; -/*----- Functions provided ------------------------------------------------*/ +extern const struct kemtab kemtab[]; /* --- @getkem@ --- * * @@ -146,6 +124,34 @@ extern int setupkem(kem */*k*/, dstr */*d*/, extern void freekem(kem */*k*/); +/* --- Signing --- */ + +typedef struct sig { + const struct sigops *ops; + key_packdef *kp; + void *kd; + const gchash *ch; + ghash *h; +} sig; + +typedef struct sigops { + const key_fetchdef *kf; /* Key fetching structure */ + size_t kdsz; /* Size of the key-data structure */ + sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/); + int (*doit)(sig */*s*/, dstr */*d*/); + const char *(*check)(sig */*s*/); + void (*destroy)(sig */*s*/); +} sigops; + +struct sigtab { + const char *name; + const sigops *signops; + const sigops *verifyops; + const gchash *ch; +}; + +extern const struct sigtab sigtab[]; + /* --- @getsig@ --- * * * Arguments: @key *k@ = the key to load @@ -170,6 +176,31 @@ extern sig *getsig(key */*k*/, const char */*app*/, int /*wantpriv*/); extern void freesig(sig */*s*/); +/*----- File encodings ----------------------------------------------------*/ + +/* --- Data encoding --- */ + +typedef struct enc { + const struct encops *ops; + FILE *fp; +} enc; + +typedef struct encops { + const char *name; + const char *rmode, *wmode; + int nraw, ncook; + enc *(*initenc)(FILE */*fp*/, const char */*msg*/); + enc *(*initdec)(FILE */*fp*/, + int (*/*func*/)(const char *, void *), void */*p*/); + int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/); + int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/); + int (*encdone)(enc */*e*/); + int (*decdone)(enc */*e*/); + void (*destroy)(enc */*e*/); +} encops; + +extern const encops enctab[]; + /* --- @getenc@ --- * * * Arguments: @const char *enc@ = name of wanted encoding @@ -181,20 +212,45 @@ extern void freesig(sig */*s*/); extern const encops *getenc(const char */*enc*/); +/* --- @checkbdry@ --- * + * + * Arguments: @const char *b@ = boundary string found + * @void *p@ = boundary string wanted + * + * Returns: Nonzero if the boundary string is the one we wanted. + * + * Use: Pass as @func@ to @initdec@ if you just want a simple life. + */ + +extern int checkbdry(const char */*b*/, void */*p*/); + /* --- @initenc@ --- * * * Arguments: @const encops *eo@ = operations (from @getenc@) * @FILE *fp@ = file handle to attach * @const char *msg@ = banner message - * @int wantenc@ = nonzero if we want to encode * * Returns: The encoder object. * * Use: Initializes an encoder. */ -extern enc *initenc(const encops */*eo*/, FILE */*fp*/, - const char */*msg*/, int /*wantenc*/); +extern enc *initenc(const encops */*eo*/, FILE */*fp*/, const char */*msg*/); + +/* --- @initdec@ --- * + * + * Arguments: @const encops *eo@ = operations (from @getenc@) + * @FILE *fp@ = file handle to attach + * @int (*func)(const char *, void *)@ = banner check function + * @void *p@ = argument for @func@ + * + * Returns: The encoder object. + * + * Use: Initializes an encoder. + */ + +extern enc *initdec(const encops */*eo*/, FILE */*fp*/, + int (*/*func*/)(const char *, void *), void */*p*/); /* --- @freeenc@ --- * * @@ -207,6 +263,393 @@ extern enc *initenc(const encops */*eo*/, FILE */*fp*/, extern void freeenc(enc */*e*/); +/* --- @cmd_encode@, @cmd_decode@ --- */ + +#define CMD_ENCODE { \ + "encode", cmd_encode, \ + "encode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ + "\ +Options:\n\ +\n\ +-f, --format=FORMAT Encode to FORMAT.\n\ +-b, --boundary=LABEL PEM boundary is LABEL.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +" } + +#define CMD_DECODE { \ + "decode", cmd_decode, \ + "decode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", \ + "\ +Options:\n\ +\n\ +-f, --format=FORMAT Decode from FORMAT.\n\ +-b, --boundary=LABEL PEM boundary is LABEL.\n\ +-o, --output=FILE Write output to FILE.\n\ +-p, --progress Show progress on large files.\n\ +" } + +extern int cmd_encode(int /*argc*/, char */*argv*/[]); +extern int cmd_decode(int /*argc*/, char */*argv*/[]); + +/*----- Hash encoding functions -------------------------------------------*/ + +/* --- Table --- */ + +#define ENCODINGS(_) \ + _(HEX, hex) \ + _(BASE64, base64) \ + _(BASE32, base32) + +enum { +#define ENUM(tag, name) ENC_##tag, + ENCODINGS(ENUM) +#undef ENUM + ENC_LIMIT +}; + +typedef struct encodeops { + const char *name; + void (*put)(const octet *, size_t, FILE *); + size_t (*get)(const char *, octet *, size_t, char **); +} encodeops; + +extern const encodeops encodingtab[]; + +/* --- @getencoding@ --- * + * + * Arguments: @const char *ename@ = encoding name + * + * Returns: Pointer to encoding table entry, or null. + * + * Use: Finds an encoding entry given its name. + */ + +extern const encodeops *getencoding(const char */*ename*/); + +/*----- File hashing ------------------------------------------------------*/ + +typedef struct fhashstate { + const gchash *gch; + unsigned f; + struct fhent *ents; +} fhashstate; + +#define FHF_BINARY 0x100u +#define FHF_PROGRESS 0x200u +#define FHF_JUNK 0x400u + +#define FHF_MASK 0xff00u + +/* --- @gethash@ --- * + * + * Arguments: @const char *name@ = pointer to name string + * + * Returns: Pointer to appropriate hash class. + * + * Use: Chooses a hash function by name. + */ + +extern const gchash *gethash(const char */*name*/); + +/* --- @describefile@ --- * + * + * Arguments: @const struct stat *st@ = pointer to file state + * + * Returns: A snappy one-word description of the file. + */ + +extern const char *describefile(const struct stat */*st*/); + +/* --- @fhash_init@ ---* + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to initialize + * @const gchash *gch@ = hash class to set + * @unsigned f@ initial flags to set + * + * Returns: --- + * + * Use: Initializes an @fhashstate@ structure. + */ + +extern void fhash_init(fhashstate */*fh*/, + const gchash */*gch*/, unsigned /*f*/); + +/* --- @fhash_free@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state to free + * + * Returns: --- + * + * Use: Frees an fhash state. + */ + +extern void fhash_free(fhashstate */*fh*/); + +/* --- @fhash@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state + * @const char *file@ = file name to be hashed (null for stdin) + * @void *buf@ = pointer to hash output buffer + * + * Returns: Zero if it worked, nonzero on error. + * + * Use: Hashes a file. + */ + +extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/); + +/* --- @fhash_junk@ --- * + * + * Arguments: @fhashstate *fh@ = pointer to fhash state + * @void (*func)(const char *, const struct stat *, void *)@ + * @void *p@ = pointer to pass to function + * + * Returns: Positive if any junk was found, negative on error, zero if + * everything was fine. + * + * Use: Reports junk files in any directories covered by the hash + * state. + */ + +extern int fhash_junk(fhashstate */*fh*/, + int (*/*func*/)(const char *, + const struct stat *, + void *), + void */*p*/); + +/* --- @hfparse@ --- * + * + * Arguments: @hfpctx *hfp@ = pointer to the context structure + * + * Returns: A code indicating what happened. + * + * Use: Parses a line from the input file. + */ + +enum { /* Meaning and members set */ + HF_FILE, /* File hash: @dline@ and @hbuf@ */ + HF_ENC, /* Encoding: @ee@ */ + HF_HASH, /* Hash function: @gch@ */ + HF_ESC, /* Name escape: @f@ */ + HF_EOF, /* End of file */ + HF_BAD /* Unrecognized line */ +}; + +typedef struct hfpctx { + unsigned f; /* Flags to read */ +#define HFF_ESCAPE 1u /* File names are escaped */ + FILE *fp; /* Input file to read */ + dstr *dline; /* Line contents, corrupted */ + const gchash *gch; /* Hash function to use */ + const encodeops *ee; /* Encoding to apply to hashes */ + dstr *dfile; /* File name for @HF_FILE@ lines */ + octet *hbuf; /* Output buffer for hash data */ +} hfpctx; + +extern int hfparse(hfpctx */*hfp*/); + +/*----- String I/O --------------------------------------------------------*/ + +#define GSF_RAW 4096u +#define GSF_FILE 0u +#define GSF_STRING 8192u + +#define GSF_MASK 61440u + +/* --- @getstring@ --- * + * + * Arguments: @void *in@ = input source + * @dstr *d@ = destination string + * @unsigned f@ = input flags + * + * Returns: Zero if OK, nonzero on end-of-file. + * + * Use: Reads a filename (or something similar) from a stream. + */ + +extern int getstring(void */*in*/, dstr */*d*/, unsigned /*f*/); + +/* --- @putstring@ --- * + * + * Arguments: @FILE *fp@ = stream to write on + * @const char *p@ = pointer to text + * @unsigned f@ = output flags + * + * Returns: --- + * + * Use: Emits a string to a stream. + */ + +extern void putstring(FILE */*fp*/, const char */*p*/, unsigned /*f*/); + +/*----- Lists of things ---------------------------------------------------*/ + +/* --- @LIST(STRING, FP, END-TEST, NAME-EXPR)@ --- * + * + * Produce list of things. Requires @i@ and @w@ variables in scope. + * END-TEST and NAME-EXPR are in terms of @i@. + */ + +#define LIST(what, fp, end, name) do { \ + fputs(what ":\n ", fp); \ + w = 2; \ + for (i = 0; end; i++) { \ + if (w == 2) \ + w += strlen(name); \ + else { \ + if (strlen(name) + w > 76) { \ + fputs("\n ", fp); \ + w = 2 + strlen(name); \ + } else { \ + fputc(' ', fp); \ + w += strlen(name) + 1; \ + } \ + } \ + fputs(name, fp); \ + } \ + fputc('\n', fp); \ +} while (0) + +#define STDLISTS(LI) \ + LI("Hash functions", hash, \ + ghashtab[i], ghashtab[i]->name) \ + LI("Encryption schemes", enc, \ + gciphertab[i], gciphertab[i]->name) \ + LI("Message authentication schemes", mac, \ + gmactab[i], gmactab[i]->name) \ + LI("Elliptic curves", ec, \ + ectab[i].name, ectab[i].name) \ + LI("Diffie-Hellman groups", dh, \ + ptab[i].name, ptab[i].name) + +#define LIDECL(text, tag, test, name) \ + static void show_##tag(void); + +#define LIDEF(text, tag, test, name) \ + static void show_##tag(void) \ + { \ + unsigned i, w; \ + LIST(text, stdout, test, name); \ + } + +#define LIENT(text, tag, test, name) \ + { #tag, show_##tag }, + +struct listent { + const char *name; + void (*list)(void); +}; + +#define MAKELISTTAB(listtab, LISTS) \ + LISTS(LIDECL) \ + static const struct listent listtab[] = { \ + LISTS(LIENT) \ + { 0, 0 } \ + }; \ + LISTS(LIDEF) + +extern int displaylists(const struct listent */*listtab*/, + char *const /*argv*/[]); + +/*----- Progress indicators -----------------------------------------------*/ + +typedef struct fprogress { + const char *bp; + off_t o, sz, olast; + time_t start, last; + char name[24]; +} fprogress; + +/* --- @fprogress_init@ --- * + * + * Arguments: @fprogress *f@ = progress context to be initialized + * @const char *name@ = file name string to show + * @FILE *fp@ = file we're reading from + * + * Returns: Zero on success, nonzero if the file's state is now broken. + * + * Use: Initializes a progress context. Nothing is actually + * displayed yet. + */ + +extern int fprogress_init(fprogress */*f*/, + const char */*name*/, FILE */*fp*/); + +/* --- @fprogress_update@ --- * + * + * Arguments: @fprogress *f@ = progress context + * @size_t n@ = how much progress has been made + * + * Returns: --- + * + * Use: Maybe updates the display to show that some progress has been + * made. + */ + +extern void fprogress_update(fprogress */*f*/, size_t /*n*/); + +/* --- @fprogress_clear@ --- * + * + * Arguments: @fprogress *f@ = progress context + * + * Returns: --- + * + * Use: Clears the progress display from the screen. + */ + +extern void fprogress_clear(fprogress */*f*/); + +/* --- @fprogress_done@ --- * + * + * Arguments: @fprogress *f@ = progress context + * + * Returns: --- + * + * Use: Clear up the progress context and removes any display. + */ + +extern void fprogress_done(fprogress */*f*/); + +/*----- Subcommand dispatch -----------------------------------------------*/ + +typedef struct cmd { + const char *name; + int (*cmd)(int /*argc*/, char */*argv*/[]); + const char *usage; + const char *help; +} cmd; + +extern void version(FILE */*fp*/); +extern void help_global(FILE */*fp*/); + +/* --- @findcmd@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @const char *name@ = a command name + * + * Returns: Pointer to the command structure. + * + * Use: Looks up a command by name. If the command isn't found, an + * error is reported and the program is terminated. + */ + +const cmd *findcmd(const cmd */*cmds*/, const char */*name*/); + +/* --- @sc_help@ --- * + * + * Arguments: @const cmd *cmds@ = pointer to command table + * @FILE *fp@ = output file handle + * @char *const *argv@ = remaining arguments + * + * Returns: --- + * + * Use: Prints a help message, maybe with help about subcommands. + */ + +extern void sc_help(const cmd */*cmds*/, FILE */*fp*/, + char *const */*argv*/); + /*----- That's all, folks -------------------------------------------------*/ #ifdef __cplusplus