X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/fddd7fb7f11a3f4399e90ee52f874f65718eb348..26936c8341691d67655a055956656f2506d53a63:/server/tripe.h diff --git a/server/tripe.h b/server/tripe.h index cb892208..56cd0b40 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -91,21 +91,27 @@ #include #include +#include #include #include #include #include #include +#include +#include #include #include #include +#include #include #include #include +#include #include -#include +#include +#include #include "priv.h" #include "protocol.h" @@ -158,45 +164,234 @@ typedef struct keyset keyset; typedef struct algswitch algswitch; +typedef struct kdata kdata; +typedef struct admin admin; + +typedef struct dhgrp { + const struct dhops *ops; + size_t scsz; +} dhgrp; + +typedef struct dhsc dhsc; +typedef struct dhge dhge; + +enum { + DHFMT_STD, /* Fixed-width format, suitable for encryption */ + DHFMT_HASH, /* Deterministic format, suitable for hashing */ + DHFMT_VAR /* Variable-width-format, mostly a bad idea */ +}; + +typedef struct bulkalgs { + const struct bulkops *ops; +} bulkalgs; + +typedef struct bulkctx { + const struct bulkops *ops; +} bulkctx; + +typedef struct bulkchal { + const struct bulkops *ops; + size_t tagsz; +} bulkchal; + +struct rawkey; + +typedef struct dhops { + const char *name; + + int (*ldpriv)(key_file */*kf*/, key */*k*/, key_data */*d*/, + kdata */*kd*/, dstr */*t*/, dstr */*e*/); + /* Load a private key from @d@, storing the data in @kd@. The key's + * file and key object are in @kf@ and @k, mostly in case its + * attributes are interesting; the key tag is in @t@; errors are + * reported by writing tokens to @e@ and returning nonzero. + */ + + int (*ldpub)(key_file */*kf*/, key */*k*/, key_data */*d*/, + kdata */*kd*/, dstr */*t*/, dstr */*e*/); + /* Load a public key from @d@, storing the data in @kd@. The key's + * file and key object are in @kf@ and @k, mostly in case its + * attributes are interesting; the key tag is in @t@; errors are + * reported by writing tokens to @e@ and returning nonzero. + */ + + const char *(*checkgrp)(const dhgrp */*g*/); + /* Check that the group is valid; return null on success, or an error + * string. + */ + + void (*grpinfo)(const dhgrp */*g*/, admin */*a*/); + /* Report on the group to an admin client. */ + + T( void (*tracegrp)(const dhgrp */*g*/); ) + /* Trace a description of the group. */ + + int (*samegrpp)(const dhgrp */*g*/, const dhgrp */*gg*/); + /* Return nonzero if the two group objects represent the same + * group. + */ + + void (*freegrp)(dhgrp */*g*/); + /* Free a group and the resources it holds. */ + + dhsc *(*ldsc)(const dhgrp */*g*/, const void */*p*/, size_t /*sz*/); + /* Load a scalar from @p@, @sz@ and return it. Return null on + * error. + */ + + int (*stsc)(const dhgrp */*g*/, + void */*p*/, size_t /*sz*/, const dhsc */*x*/); + /* Store a scalar at @p@, @sz@. Return nonzero on error. */ + + dhsc *(*randsc)(const dhgrp */*g*/); + /* Return a random scalar. */ + + T( const char *(*scstr)(const dhgrp */*g*/, const dhsc */*x*/); ) + /* Return a human-readable representation of @x@; @buf_t@ may be used + * to hold it. + */ + + void (*freesc)(const dhgrp */*g*/, dhsc */*x*/); + /* Free a scalar and the resources it holds. */ + + dhge *(*ldge)(const dhgrp */*g*/, buf */*b*/, int /*fmt*/); + /* Load a group element from @b@, encoded using format @fmt@. Return + * null on error. + */ + + int (*stge)(const dhgrp */*g*/, buf */*b*/, + const dhge */*Y*/, int /*fmt*/); + /* Store a group element in @b@, encoded using format @fmt@. Return + * nonzero on error. + */ + + int (*checkge)(const dhgrp */*h*/, const dhge */*Y*/); + /* Check a group element for validity. Return zero if everything + * checks out; nonzero on failure. + */ + + int (*eq)(const dhgrp */*g*/, const dhge */*Y*/, const dhge */*Z*/); + /* Return nonzero if @Y@ and @Z@ are equal. */ + + dhge *(*mul)(const dhgrp */*g*/, const dhsc */*x*/, const dhge */*Y*/); + /* Multiply a group element by a scalar, resulting in a shared-secret + * group element. If @y@ is null, then multiply the well-known + * generator. + */ + + T( const char *(*gestr)(const dhgrp */*g*/, const dhge */*Y*/); ) + /* Return a human-readable representation of @Y@; @buf_t@ may be used + * to hold it. + */ + + void (*freege)(const dhgrp */*g*/, dhge */*Y*/); + /* Free a group element and the resources it holds. */ + +} dhops; typedef struct bulkops { const char *name; - unsigned prim; - int (*check)(const algswitch */*a*/, dstr */*e*/); - size_t (*overhead)(const algswitch */*a*/); - int (*encrypt)(keyset */*ks*/, unsigned /*ty*/, buf */*b*/, buf */*bb*/); - int (*decrypt)(keyset */*ks*/, unsigned /*ty*/, + + bulkalgs *(*getalgs)(const algswitch */*asw*/, dstr */*e*/, + key_file */*kf*/, key */*k*/); + /* Determine algorithms to use and return a @bulkalgs@ object + * representing the decision. On error, write tokens to @e@ and + * return null. + */ + + T( void (*tracealgs)(const bulkalgs */*a*/); ) + /* Write trace information about the algorithm selection. */ + + int (*checkalgs)(bulkalgs */*a*/, const algswitch */*asw*/, dstr */*e*/); + /* Check that the algorithms in @a@ and @asw@ are acceptable. On + * error, write tokens to @e@ and return @-1@; otherwise return zero. + */ + + int (*samealgsp)(const bulkalgs */*a*/, const bulkalgs */*aa*/); + /* If @a@ and @aa@ represent the same algorithm selection, return + * nonzero; if not, return zero. + */ + + void (*alginfo)(const bulkalgs */*a*/, admin */*adm*/); + /* Report on the algorithm selection to an admin client: call + * @a_info@ with appropriate key-value pairs. + */ + + size_t (*overhead)(const bulkalgs */*a*/); + /* Return the per-packet overhead of the bulk transform, in bytes. */ + + size_t (*expsz)(const bulkalgs */*a*/); + /* Return the total size limit for the bulk transform, in bytes, + * after which the keys must no longer be used. + */ + + bulkctx *(*genkeys)(const bulkalgs */*a*/, const struct rawkey */*rk*/); + /* Generate session keys and construct and return an appropriate + * context for using them, by calling @ks_derive@. + */ + + bulkchal *(*genchal)(const bulkalgs */*a*/); + /* Construct and return a challenge issuing and verification + * context with a fresh random key. + */ + + void (*freealgs)(bulkalgs */*a*/); + /* Release an algorithm selection object. (Associated bulk + * encryption contexts and challenge contexts may still exist and + * must remain valid.) + */ + + int (*encrypt)(bulkctx */*bc*/, unsigned /*ty*/, + buf */*b*/, buf */*bb*/, uint32 /*seq*/); + /* Encrypt the packet in @b@, with type @ty@ (which doesn't need + * encoding separately) and sequence number @seq@ (which must be + * recoverable by @decrypt@), and write the result to @bb@. On + * error, return a @KSERR_...@ code and/or break the output buffer. + */ + + int (*decrypt)(bulkctx */*bc*/, unsigned /*ty*/, buf */*b*/, buf */*bb*/, uint32 */*seq*/); -} bulkops; + /* Decrypt the packet in @b@, with type @ty@, writing the result to + * @bb@ and storing the incoming (claimed) sequence number in @seq@. + * On error, return a @KSERR_...@ code. + */ + + void (*freectx)(bulkctx */*a*/); + /* Release a bulk encryption context and the resources it holds. */ + + int (*chaltag)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/, + void */*t*/); + /* Calculate a tag for the challenge in @m@, @msz@, and write it to + * @t@. Return @-1@ on error, zero on success. + */ + + int (*chalvrf)(bulkchal */*bc*/, const void */*m*/, size_t /*msz*/, + const void */*t*/); + /* Check the tag @t@ on @m@, @msz@: return zero if the tag is OK, + * nonzero if it's bad. + */ -#define BCP_CIPHER 1 -#define BCP_MAC 2 -#define BCP_BLKC 4 + void (*freechal)(bulkchal */*bc*/); + /* Release a challenge context and the resources it holds. */ + +} bulkops; struct algswitch { - const gchash *h; /* Hash function */ + const gchash *h; size_t hashsz; /* Hash function */ const gccipher *mgf; /* Mask-generation function */ - const bulkops *bulk; /* Bulk crypto transformation */ - const gccipher *c; /* Symmetric encryption scheme */ - const gcmac *m; /* Message authentication code */ - const gccipher *b; /* Block cipher */ - size_t hashsz; /* Hash output size */ - size_t tagsz; /* Length to truncate MAC tags */ - size_t expsz; /* Size of data to process */ - size_t cksz, mksz, bksz; /* Key lengths for things */ + bulkalgs *bulk; /* Bulk crypto algorithms */ }; -typedef struct kdata { +struct kdata { unsigned ref; /* Reference counter */ struct knode *kn; /* Pointer to cache entry */ char *tag; /* Full tag name of the key */ - group *g; /* The group we work in */ - size_t indexsz; /* Size of exponent for the group */ - mp *kpriv; /* The private key (or null) */ - ge *kpub; /* The public key */ + dhgrp *grp; /* The group we work in */ + dhsc *k; /* The private key (or null) */ + dhge *K; /* The public key */ time_t t_exp; /* Expiry time of the key */ algswitch algs; /* Collection of algorithms */ -} kdata; +}; typedef struct knode { sym_base _b; /* Symbol table intrusion */ @@ -210,6 +405,7 @@ typedef struct knode { #define HASH_STRING(h, s) GH_HASH((h), (s), sizeof(s)) +extern const dhops dhtab[]; extern const bulkops bulktab[]; /*----- Data structures ---------------------------------------------------*/ @@ -258,6 +454,8 @@ typedef struct seqwin { * expiry. */ +enum { DIR_IN, DIR_OUT, NDIR }; + struct keyset { struct keyset *next; /* Next active keyset in the list */ unsigned ref; /* Reference count for keyset */ @@ -266,13 +464,7 @@ struct keyset { unsigned long sz_exp, sz_regen; /* Data limits for the keyset */ T( unsigned seq; ) /* Sequence number for tracing */ unsigned f; /* Various useful flags */ - const bulkops *bulk; /* Bulk crypto transform */ - size_t tagsz; /* Length to truncate MAC tags */ - struct ksdir { - gcipher *c; /* Keyset cipher for encryption */ - gmac *m; /* Keyset MAC for integrity */ - gcipher *b; /* Block cipher, just in case */ - } in, out; + bulkctx *bulk; /* Bulk crypto transform */ uint32 oseq; /* Outbound sequence number */ seqwin iseq; /* Inbound sequence number */ }; @@ -303,8 +495,8 @@ typedef struct retry { typedef struct kxchal { struct keyexch *kx; /* Pointer back to key exchange */ - ge *c; /* Responder's challenge */ - ge *r; /* My reply to the challenge */ + dhge *C; /* Responder's challenge */ + dhge *R; /* My reply to the challenge */ keyset *ks; /* Pointer to temporary keyset */ unsigned f; /* Various useful flags */ sel_timer t; /* Response timer for challenge */ @@ -326,9 +518,9 @@ typedef struct keyexch { unsigned s; /* Current state in exchange */ sel_timer t; /* Timer for next exchange */ retry rs; /* Retry state */ - mp *alpha; /* My temporary secret */ - ge *c; /* My challenge */ - ge *rx; /* The expected response */ + dhsc *a; /* My temporary secret */ + dhge *C; /* My challenge */ + dhge *RX; /* The expected response */ unsigned nr; /* Number of extant responses */ time_t t_valid; /* When this exchange goes bad */ octet hc[MAXHASHSZ]; /* Hash of my challenge */ @@ -529,7 +721,7 @@ typedef struct admin_jobtable { admin_jobentry *v; /* And the big array of entries */ } admin_jobtable; -typedef struct admin { +struct admin { struct admin *next, *prev; /* Links to next and previous */ unsigned f; /* Various useful flags */ unsigned ref; /* Reference counter */ @@ -543,7 +735,7 @@ typedef struct admin { admin_jobtable j; /* Table of outstanding jobs */ selbuf b; /* Line buffer for commands */ sel_file w; /* Selector for write buffering */ -} admin; +}; #define AF_DEAD 1u /* Destroy this admin block */ #define AF_CLOSE 2u /* Client closed connection */ @@ -748,6 +940,27 @@ extern int kx_init(keyexch */*kx*/, peer */*p*/, extern void ks_drop(keyset */*ks*/); +/* --- @ks_derivekey@ --- * + * + * Arguments: @octet *k@ = pointer to an output buffer of at least + * @MAXHASHSZ@ bytes + * @size_t ksz@ = actual size wanted (for tracing) + * @const struct rawkey *rk@ = a raw key, as passed into + * @genkeys@ + * @int dir@ = direction for the key (@DIR_IN@ or @DIR_OUT@) + * @const char *what@ = label for the key (input to derivation) + * + * Returns: --- + * + * Use: Derives a session key, for use on incoming or outgoing data. + * This function is part of a private protocol between @ks_gen@ + * and the bulk crypto transform @genkeys@ operation. + */ + +extern void ks_derivekey(octet */*k*/, size_t /*ksz*/, + const struct rawkey */*rk*/, + int /*dir*/, const char */*what*/); + /* --- @ks_gen@ --- * * * Arguments: @const void *k@ = pointer to key material @@ -980,6 +1193,19 @@ extern void a_vformat(dstr */*d*/, const char */*fmt*/, va_list */*ap*/); extern void EXECL_LIKE(0) a_format(dstr */*d*/, const char */*fmt*/, ...); +/* --- @a_info@ --- * + * + * Arguments: @admin *a@ = connection + * @const char *fmt@ = format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Report information to an admin client. + */ + +extern void EXECL_LIKE(0) a_info(admin */*a*/, const char */*fmt*/, ...); + /* --- @a_warn@ --- * * * Arguments: @const char *fmt@ = pointer to format string @@ -1484,31 +1710,6 @@ extern const tunnel_ops tun_slip; /*----- Other handy utilities ---------------------------------------------*/ -/* --- @mpstr@ --- * - * - * Arguments: @mp *m@ = a multiprecision integer - * - * Returns: A pointer to the integer's textual representation. - * - * Use: Converts a multiprecision integer to a string. Corrupts - * @buf_u@. - */ - -extern const char *mpstr(mp */*m*/); - -/* --- @gestr@ --- * - * - * Arguments: @group *g@ = a group - * @ge *x@ = a group element - * - * Returns: A pointer to the element's textual representation. - * - * Use: Converts a group element to a string. Corrupts - * @buf_u@. - */ - -extern const char *gestr(group */*g*/, ge */*x*/); - /* --- @timestr@ --- * * * Arguments: @time_t t@ = a time to convert