X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=hbytes%2Fhbytes.h;h=4a2f394862eb5eb31e5f618738e96d811f84e092;hp=5aca1625a0c9a2dc38c4b38497e7e2bc935166a8;hb=82f88c53ddb84e42c770c23feb9bb0ee18341188;hpb=b30fd7b756a0664c4e1fef3e936d9aab13c0d6fe diff --git a/hbytes/hbytes.h b/hbytes/hbytes.h index 5aca162..4a2f394 100644 --- a/hbytes/hbytes.h +++ b/hbytes/hbytes.h @@ -1,74 +1,237 @@ /* */ /* + * hbytes raw2h BINARY => hex + * hbytes h2raw HEX => binary * - * hbytes bin VAR => binary string - * hbytes bin VAR VALUE => set - * - * hbytes prefix VAR [VALUE ...] = set VAR [concat VALUE ... $VAR] - * hbytes append VAR [VALUE ...] = set VAR [concat $VAR VALUE ...] - * hbytes concat VAR [VALUE ...] = set VAR [concat VALUE ...] + * hbytes length VALUE => count + * hbytes prepend VAR [VALUE ...] = set VAR [concat VALUE ... $VAR] + * hbytes append VAR [VALUE ...] = set VAR [concat $VAR VALUE ...] + * hbytes concat VAR [VALUE ...] = set VAR [concat VALUE ...] * hbytes unprepend VAR PREFIXLENGTH => prefix (removed from VAR) * hbytes unappend VAR SUFFIXLENGTH => suffix (removed from VAR) * hbytes chopto VAR NEWVARLENGTH => suffix (removed from VAR) * (too short? error) * - * hbytes pkcs5 pv|uv VAR ALG => worked? (always 1 for p) - * hbytes pkcs5 pn|un VAR BLOCKSIZE => worked? (always 1 for p) - * hbytes blockcipher e|d VAR ALG MODE [IV] => IV - * hbytes hash ALG VALUE => hash - * hbytes hmac ALG VALUE KEY [MACLENGTH] => mac + * hbytes range VALUE START SIZE => substring (or error) + * hbytes overwrite VAR START VALUE + * hbytes trimleft VAR removes any leading 0 octets + * hbytes repeat VALUE COUNT => COUNT copies of VALUE + * hbytes zeroes COUNT => COUNT zero bytes + * hbytes random COUNT => COUNT random bytes + * hbytes xor VAR VALUE $VAR (+)= VALUE * - * Refs: HMAC: RFC2104 - */ + * hbytes ushort2h LONG => LONG must be <2^16, returns as hex + * hbytes h2ushort HEX => |HEX| must be 2 bytes, returns as ulong + * + * hbytes compare A B + * => -2 A is lexically earlier than B and not a prefix of B (A worked? (always 1 for p) + * hbytes pad pn|un VAR BS METH [METHARGS] => worked? (always 1 for p) + * hbytes pad pa|pn VAR ALG|BS pkcs5 => 1 + * hbytes pad ua|un VAR ALG|BS pkcs5 => worked? + * hbytes pad pa|pn VAR ALG|BS rfc2406 NXTHDR => 1 + * hbytes pad ua|un VAR ALG|BS rfc2406 NXTHDRVAR => worked? + * + * hbytes blockcipher d|e VAR ALG KEY MODE [IV] => IV + * hbytes blockcipher mac MSG ALG KEY MODE IV => final block + * hbytes blockcipher prop PROPERTY ALG => property value + * + * hbytes hash ALG MESSAGE => hash + * hbytes hmac ALG MESSAGE KEY [MACLENGTH] => mac + * hbytes hash-prop PROPERTY ALG => property value + * + * ulong ul2int ULONG => INT can fail if >INT_MAX + * ulong int2ul INT => ULONG can fail if <0 + * ulong mask A B => A & B + * ulong add A B => A + B (mod 2^32) + * ulong subtract A B => A - B (mod 2^32) + * ulong compare A B => 0 -1 (AB) + * ulong shift l|r ULONG BITS fails if BITS >32 + * + * ulong ul2bitfields VALUE [SIZE TYPE [TYPE-ARG...] ...] => 0/1 + * ulong bitfields2ul BASE [SIZE TYPE [TYPE-ARG...] ...] => ULONG + * goes from left (MSbit) to right (LSbit) where + * SIZE is size in bits + * TYPE [TYPE-ARGS...] is as below + * zero + * ignore + * fixed ULONG-VALUE + * uint VARNAME/VALUE (VARNAME if ul2bitfields; + * ulong VARNAME/VALUE VALUE if bitfields2ul) + * + * Address ranges (addrmap.c): + * + * An address range is a slightly efficient partial mapping from + * addresses to arbitrary data values. An address is a number of + * octets expressed as an hbytes. All the addresses covered by the + * same addrmap should have the same length. + * + * hbytes addr-map lookup MAP-VAR ADDRESS [DEFAULT] => DATA + * Error on missing default or if any prefix longer than ADDRESS. + * + * hbytes addr-map amend-range MAP-VAR START END DATA + * hbytes addr-map amend-mask MAP-VAR PREFIX PREFIX-LENGTH DATA + * Sets all of the addresses in PREFIX/PREFIX-LENGTH to the + * relevant value. + * + * Representation: + * An address map MAP is + * [list BIT-LENGTH \ + * [list START END DATA-VALUE] \ + * [list START' END' DATA-VALUE'] \ + * ... + * ] + * The list is sorted by ascending START and entries do not overlap. + * START and END are both inclusive. BIT-LENGTH is in usual Tcl + * integer notation and must be a multiple of 8. + * + * Error codes + * + * HBYTES BLOCKCIPHER CRYPTFAIL CRYPT block cipher mode failed somehow (!) + * HBYTES BLOCKCIPHER CRYPTFAIL MAC HMAC failed somehow (!) + * HBYTES BLOCKCIPHER LENGTH block cipher input has unsuitable length + * HBYTES BLOCKCIPHER PARAMS key or iv not suitable + * HBYTES HMAC PARAMS key, input or output size not suitable + * HBYTES LENGTH OVERRUN block too long + * HBYTES LENGTH RANGE input length or offset is -ve or silly + * HBYTES LENGTH UNDERRUN block too short (or offset too big) + * HBYTES LENGTH MISMATCH when blocks must be exactly same length + * HBYTES SYNTAX supposed hex block had wrong syntax + * HBYTES VALUE OVERFLOW value to be conv'd to hex too big/long + * HBYTES ADDRMAP NOMATCH no addr/mask matches address for lookup + * HBYTES ADDRMAP UNDERRUN addr for lookup or amend is too short + * HBYTES ADDRMAP OVERRUN addr for lookup or amend is too long + * HBYTES ADDRMAP EXCLBITS amend-mask 1-bits outside prefix len + * HBYTES ADDRMAP BADRANGE amend-range start > end + * HBYTES ADDRMAP VALUE addr-map string value is erroneous + * SOCKADDR AFUNIX LENGTH path for AF_UNIX socket too long + * SOCKADDR SYNTAX IPV4 bad IPv4 socket address &/or port + * SOCKADDR SYNTAX OTHER bad socket addr, couldn't tell what kind + * ULONG BITCOUNT NEGATIVE -ve bitcount specified where not allowed + * ULONG BITCOUNT OVERRUN attempt to use more than 32 bits + * ULONG BITCOUNT UNDERRUN bitfields add up to less than 32 + * ULONG VALUE NEGATIVE attempt convert -ve integers to ulong + * ULONG VALUE OVERFLOW converted value does not fit in result + * TUNTAP IFNAME LENGTH tun/tap interface name too long + * TUNTAP MTU OVERRUN tun/tap mtu limited to 2^16 bytes + * + * Refs: HMAC: RFC2104 */ #ifndef HBYTES_H #define HBYTES_H #include #include +#include +#include +#include +#include +#include +#include +#include +#include -#include - -typedef unsigned char Byte; +#include "chiark-tcl.h" /* from hbytes.c */ +int Hbytes_Init(Tcl_Interp *ip); /* called by Tcl's "load" */ + +/* Internal representation details: */ +#define HBYTES_ISEMPTY(hb) (!(hb)->begin_complex && !(hb)->end_0) +#define HBYTES_ISSENTINEL(hb) (!(hb)->begin_complex && (hb)->end_0) +#define HBYTES_ISSIMPLE(hb) ((hb)->begin_complex && (hb)->end_0) +#define HBYTES_ISCOMPLEX(hb) ((hb)->begin_complex && !(hb)->end_0) + typedef struct { - Byte *start, *end; /* always allocated dynamically */ + void *begin_complex, *end_0; } HBytes_Value; /* overlays internalRep */ -extern Tcl_ObjType hbytes_type; +typedef struct { + Byte *dstart; /* always allocated dynamically */ + int prespace, len, avail; + /* + * | SPARE | USED | SPARE | + * |<-prespace->|<-len->| | + * | |<----avail---->| + * ^start + */ +} HBytes_ComplexValue; /* pointed to from internalRep.otherValuePtr */ -int staticerr(Tcl_Interp *ip, const char *m); -void objfreeir(Tcl_Obj *o); +void memxor(Byte *dest, const Byte *src, int l); -Tcl_Obj *hbytes_set(Tcl_Obj *overwrite, const Byte *array, int l); +/* Public interfaces: */ -/* from enum.c */ +extern Tcl_ObjType cht_hbytes_type; -extern Tcl_ObjType enum_nearlytype; +int cht_hb_len(const HBytes_Value *v); +Byte *cht_hb_data(const HBytes_Value *v); /* caller may then modify data! */ +int cht_hb_issentinel(const HBytes_Value *v); -const void *enum_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o, - size_t entrysize, const void *firstentry, - const char *what); -#define enum_lookup_cached(ip,o,table,what) \ - (enum_lookup_cached_func((ip),(o), \ - sizeof((table)[0]),&(table)[0], \ - (what))) - /* table should be a pointer to an array of structs of size - * entrysize, the first member of which should be a const char*. - * The table should finish with a null const char *. - * On error, 0 is returned and the ip->result will have been - * set to the error message. - */ +Byte *cht_hb_prepend(HBytes_Value *upd, int el); +Byte *cht_hb_append(HBytes_Value *upd, int el); + /* return value is where to put the data */ -/* useful macros */ +const Byte *cht_hb_unprepend(HBytes_Value *upd, int rl); +const Byte *cht_hb_unappend(HBytes_Value *upd, int rl); + /* return value points to the removed data, which remains valid + * until next op on the HBytes_Value. If original value is + * shorter than rl or negative, returns 0 and does nothing. */ + +void cht_hb_empty(HBytes_Value *returns); +void cht_hb_sentinel(HBytes_Value *returns); +void cht_hb_array(HBytes_Value *returns, const Byte *array, int l); +Byte *cht_hb_arrayspace(HBytes_Value *returns, int l); +void cht_hb_free(const HBytes_Value *frees); + /* _empty, _sentinel and _array do not free or read the old value; + * _free it first if needed. _free leaves it garbage, so you + * have to call _empty to reuse it. _arrayspace doesn't fill + * the array; you get a pointer and must fill it with data + * yourself. */ + +/* The value made by cht_hb_sentinel should not be passed to + * anything except HBYTES_IS..., and cht_hb_free. */ + +/* from hook.c */ + +void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l); +void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte, + int l, const char *prefix); + +/* from parse.c */ + +typedef struct { + HBytes_Value *hb; + Something_Var sth; +} HBytes_Var; -#define HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue) -#define HBYTES_LEN(o) (HBYTES((o))->end - HBYTES((o))->start) +/* from addrmap.c */ + +typedef struct AddrMap_Value AddrMap_Value; + +typedef struct { + AddrMap_Value *am; + Something_Var sth; +} AddrMap_Var; + +extern Tcl_ObjType cht_addrmap_type; + +/* from chop.c */ + /* only do_... functions declared in tables.h */ + +/* from ulong.c */ + +Tcl_ObjType cht_ulong_type; + +/* useful macros */ -#define TALLOC(s) ((void*)Tcl_Alloc((s))) -#define TFREE(f) (Tcl_Free((void*)(f))) +#define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue) +#define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue) #endif /*HBYTES_H*/