X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/key/key-data.h diff --git a/key/key-data.h b/key/key-data.h new file mode 100644 index 0000000..9c00908 --- /dev/null +++ b/key/key-data.h @@ -0,0 +1,592 @@ +/* -*-c-*- + * + * Manipulating key data + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * 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, + * MA 02111-1307, USA. + */ + +#ifndef CATACOMB_KEY_DATA_H +#define CATACOMB_KEY_DATA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include +#include + +#ifndef CATACOMB_KEY_ERROR_H +# include "key-error.h" +#endif + +#ifndef CATACOMB_MP_H +# include "mp.h" +#endif + +#ifndef CATACOMB_EC_H +# include "ec.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Key binary data --- */ + +typedef struct key_bin { + octet *k; /* Pointer to key data */ + size_t sz; /* Size of the key data (in bytes) */ +} key_bin; + +/* --- Key data structure --- */ + +typedef struct key_data { + unsigned e; /* Encoding type for key data */ + unsigned ref; /* Reference counter */ + union { + key_bin k; /* Binary key data */ + mp *m; /* Multiprecision integer */ + sym_table s; /* Structured key data */ + char *p; /* String pointer */ + ec e; /* Elliptic curve point */ + } u; +} key_data; + +typedef struct key_struct { + sym_base _b; + key_data *k; +} key_struct; + +typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter; + +/* --- Packing and unpacking --- */ + +typedef struct key_packdef { + unsigned e; /* Key data encoding type */ + void *p; /* Pointer to the destination */ + key_data *kd; /* Key data block */ +} key_packdef; + +typedef struct key_packstruct { + char *name; /* Pointer to name string */ + key_packdef kp; /* Packing structure */ +} key_packstruct; + +/* --- Key binary encoding --- * + * + * The binary encoding consists of a header containing a 16-bit encoding type + * and a 16-bit length, followed immediately by the key data, followed by + * between zero and three zero bytes to make the total length a multiple of + * four. The format of the following data depends on the encoding type: + * + * @KENC_BINARY@ Binary data. + * + * @KENC_MP@ Octet array interpreted in big-endian byte order. + * + * @KENC_STRUCT@ An array of pairs, each containing a string (8-bit + * length followed by data and zero-padding to 4-byte + * boundary) and key binary encodings. + * + * @KENC_ENCRYPT@ Binary data, format + */ + +/* --- Key encoding methods and other flags--- */ + +enum { + + /* --- Bottom two bits are the encoding type --- */ + + KF_ENCMASK = 0x83, /* Encoding mask */ + KENC_BINARY = 0x00, /* Plain binary key (@k@) */ + KENC_MP = 0x01, /* Multiprecision integer (@i@) */ + KENC_STRUCT = 0x02, /* Structured key data (@s@) */ + KENC_ENCRYPT = 0x03, /* Encrypted key type (@k@) */ + KENC_STRING = 0x80, /* ASCII string (@p@) */ + KENC_EC = 0x81, /* Elliptic curve point (@e@) */ + + /* --- Key category bits --- */ + + KF_CATMASK = 0x0c, /* Category mask */ + KCAT_SYMM = 0x00, /* Symmetric encryption key */ + KCAT_PRIV = 0x04, /* Private (asymmetric) key */ + KCAT_PUB = 0x08, /* Public (asymmetric) key */ + KCAT_SHARE = 0x0c, /* Shared (asymmetric) key */ + KF_NONSECRET = 0x08, /* Bit flag for non-secret keys */ + + /* --- Other flags --- */ + + KF_BURN = 0x10, /* Burn key after use */ + KF_OPT = 0x20, /* Optional key (for @key_unpack@) */ + + /* --- Tag end --- */ + + KENC_MAX /* Dummy limit constant */ +}; + +/* --- Key locking return codes --- */ + +#define KL_OK 0 /* All good */ +#define KL_IOERR -1 /* I/O problem (e.g., getting pp) */ +#define KL_KEYERR -2 /* Wrong key supplied */ +#define KL_DATAERR -3 /* Data format error */ + +/* --- Key flag filtering --- */ + +typedef struct key_filter { + unsigned f; + unsigned m; +} key_filter; + +/* --- Matching aginst key selection --- */ + +#define KEY_MATCH(kd, kf) \ + (!(kf) || \ + ((kd)->e & KF_ENCMASK) == KENC_STRUCT || \ + ((kd)->e & (kf)->m) == (kf)->f) + +/*----- Key flags and filtering -------------------------------------------*/ + +/* --- @key_readflags@ --- * + * + * Arguments: @const char *p@ = pointer to string to read + * @char **pp@ = where to store the end pointer + * @unsigned *ff@ = where to store the flags + * @unsigned *mm@ = where to store the mask + * + * Returns: Zero if all went well, nonzero if there was an error. + * + * Use: Reads a flag string. + */ + +extern int key_readflags(const char */*p*/, char **/*pp*/, + unsigned */*ff*/, unsigned */*mm*/); + +/* --- @key_writeflags@ --- * + * + * Arguments: @unsigned f@ = flags to write + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Emits a flags word as a string representation. + */ + +extern void key_writeflags(unsigned /*f*/, dstr */*d*/); + +/* --- @key_match@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Nonzero if the key matches the filter. + * + * Use: Checks whether a key matches a filter. + */ + +extern int key_match(key_data */*k*/, const key_filter */*kf*/); + +/*----- Setting new key data ----------------------------------------------*/ + +/* --- @key_newraw@ --- * + * + * Arguments: @unsigned e@ = encoding type to set + * + * Returns: New key block, not filled in. + */ + +extern key_data *key_newraw(unsigned /*e*/); + +/* --- @key_newbinary@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +extern key_data *key_newbinary(unsigned /*e*/, + const void */*p*/, size_t /*sz*/); + +/* --- @key_newencrypted@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const void *p@ = pointer to key data + * @size_t sz@ = size of the key data + * + * Returns: New key data object. + */ + +extern key_data *key_newencrypted(unsigned /*e*/, + const void */*p*/, size_t /*sz*/); + +/* --- @key_newmp@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @mp *m@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newmp(unsigned /*e*/, mp */*m*/); + +/* --- @key_newstring@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const char *p@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newstring(unsigned /*e*/, const char */*p*/); + +/* --- @key_newec@ --- * + * + * Arguments: @unsigned e@ = other encoding flags + * @const ec *pt@ = pointer to the value to set + * + * Returns: New key data object. + */ + +extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/); + +/* --- @key_newstruct@ --- * + * + * Arguments: --- + * + * Returns: New key data object. + */ + +extern key_data *key_newstruct(void); + +/* --- @key_structfind@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * + * Returns: Pointer to key data block, or null. + * + * Use: Looks up the tag in a structured key. + */ + +extern key_data *key_structfind(key_data */*k*/, const char */*tag*/); + +/* --- @key_mksubkeyiter@ --- * + * + * Arguments: @key_subkeyiter *i@ = pointer to iterator block + * @key_data *k@ = pointer to key data block + * + * Returns: --- + * + * Use: Initializes a subkey iterator. + */ + +extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/); + +/* --- @key_nextsubkey@ --- * + * + * Arguments: @key_structiter *i@ = pointer to iterator block + * @const char **tag@ = where to put the tag pointer, or null + * @key_data **kd@ = where to put the key data pointer, or null + * + * Returns: Nonzero if there was another item, zero if we hit the + * end-stop. + * + * Use: Collects the next subkey of a structured key. + */ + +extern int key_nextsubkey(key_subkeyiter */*i*/, + const char **/*tag*/, key_data **/*kd*/); + +/* --- @key_structset@, @key_structsteal@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const char *tag@ = pointer to tag string + * @key_data *kd@ = new key data to store + * + * Returns: --- + * + * Use: Creates a new subkey. Stealing doesn't affect @kd@'s + * refcount. If @kd@ is null, the subkey is deleted. + */ + +extern void key_structset(key_data */*k*/, + const char */*tag*/, key_data */*kd*/); +extern void key_structsteal(key_data */*k*/, + const char */*tag*/, key_data */*kd*/); + +/* --- @key_split@ --- * + * + * Arguments: @key_data **kk@ = address of pointer to key data block + * + * Returns: --- + * + * Use: Replaces @*kk@ with a pointer to the same key data, but with + * just one reference. + */ + +extern void key_split(key_data **/*kk*/); + +/*----- Miscellaneous operations ------------------------------------------*/ + +/* --- @key_incref@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * + * Returns: --- + * + * Use: Increments the refcount on a key data block. + */ + +#define KEY_INCREF(k) ((k)->ref++) +extern void key_incref(key_data */*k*/); + +/* --- @key_destroy@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Destroys a block of key data, regardless of reference count. + * Don't use this unless you know what you're doing. + */ + +extern void key_destroy(key_data */*k*/); + +/* --- @key_drop@ --- * + * + * Arguments: @key_data *k@ = pointer to key data to destroy + * + * Returns: --- + * + * Use: Drops a reference to key data, destroying it if necessary. + */ + +#define KEY_DROP(k) do { \ + key_data *_k = k; \ + _k->ref--; \ + if (_k->ref == 0) \ + key_destroy(_k); \ +} while (0) + +extern void key_drop(key_data */*k*/); + +/* --- @key_do@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @const key_filter *kf@ = pointer to filter block + * @dstr *d@ = pointer to base string + * @int (*func)(key_data *kd, dstr *d, void *p@ = function + * @void *p@ = argument to function + * + * Returns: Nonzero return code from function, or zero. + * + * Use: Runs a function over all the leaves of a key. + */ + +extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/, + int (*/*func*/)(key_data */*kd*/, + dstr */*d*/, void */*p*/), + void */*p*/); + +/* --- @key_copydata@ --- * + * + * Arguments: @key_data *k@ = key data to copy + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Pointer to a copy of the data, or null if the root subkey + * didn't match the filter. + * + * Use: Copies a chunk of key data. Subkeys, whether they're + * structured or leaves, which don't match the filter aren't + * copied. The copy may or may not have structure in common + * with the original. + */ + +extern key_data *key_copydata(key_data */*k*/, const key_filter */*kf*/); + +/*----- Textual encoding --------------------------------------------------*/ + +/* --- @key_read@ --- * + * + * Arguments: @const char *p@ = pointer to textual key representation + * @char **pp@ = where to store the end pointer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Parses a textual key description. + */ + +extern key_data *key_read(const char */*p*/, char **/*pp*/); + +/* --- @key_write@ --- * + * + * Arguments: @key_data *k@ = pointer to key data + * @dstr *d@ = destination string to write on + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if any items were actually written. + * + * Use: Writes a key in a textual encoding. + */ + +extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/); + +/*----- Key binary encoding -----------------------------------------------*/ + +/* --- @key_decode@ --- * + * + * Arguments: @const void *p@ = pointer to buffer to read + * @size_t sz@ = size of the buffer + * + * Returns: The newly-read key data, or null if it failed. + * + * Use: Decodes a binary representation of a key. + */ + +extern key_data *key_decode(const void */*p*/, size_t /*sz*/); + +/* --- @key_encode@ --- * + * + * Arguments: @key_data *k@ = pointer to key data block + * @dstr *d@ = pointer to destination string + * @const key_filter *kf@ = pointer to key selection block + * + * Returns: Nonzero if any items were actually written. + * + * Use: Encodes a key block as binary data. + */ + +extern int key_encode(key_data */*k*/, dstr */*d*/, + const key_filter */*kf*/); + +/*----- Packing and unpacking keys ----------------------------------------*/ + +/* --- @key_pack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data **kd@ = where to put the key data pointer + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Packs a key from a data structure. + */ + +extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/); + +/* --- @key_unpack@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing structure + * @key_data *kd@ = pointer to source key data + * @dstr *d@ = pointer to tag string for the key data + * + * Returns: Error code, or zero. + * + * Use: Unpacks a key into an appropriate data structure. + */ + +extern int key_unpack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/); + +/* --- @key_unpackdone@ --- * + * + * Arguments: @key_packdef *kp@ = pointer to packing definition + * + * Returns: --- + * + * Use: Frees the key components contained within a packing + * definition, created during key unpacking. + */ + +extern void key_unpackdone(key_packdef */*kp*/); + +/*----- Key encryption ----------------------------------------------------*/ + +/* --- @key_lock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to encrypt key with + * @size_t esz@ = size of the secret + * + * Returns: --- + * + * Use: Encrypts a key data block using a secret. + */ + +extern void key_lock(key_data **/*kt*/, key_data */*k*/, + const void */*e*/, size_t /*esz*/); + +/* --- @key_unlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const void *e@ = secret to decrypt the block with + * @size_t esz@ = size of the secret + * + * Returns: Zero for success, or a @KERR_@ error code. + * + * Use: Unlocks a key using a secret. + */ + +extern int key_unlock(key_data **/*kt*/, key_data */*k*/, + const void */*e*/, size_t /*esz*/); + +/* --- @key_plock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Locks a key by encrypting it with a passphrase. + */ + +extern int key_plock(key_data **/*kt*/, key_data */*k*/, + const char */*tag*/); + +/* --- @key_punlock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Unlocks a passphrase-locked key. + */ + +extern int key_punlock(key_data **/*kt*/, key_data */*k*/, + const char */*tag*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif