X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=hbytes%2Fhbytes.h;h=3b4dd157c022b71eb2633cb3caabb54408058580;hp=ac19c8f9cd941f2ac1aa95fcd2a7daee442e601a;hb=5dca360f2da544c9b6baf9d18ad8cd0b0e073e60;hpb=ac8c0b3b18075ae4273779544eda01c09cfb5145 diff --git a/hbytes/hbytes.h b/hbytes/hbytes.h index ac19c8f..3b4dd15 100644 --- a/hbytes/hbytes.h +++ b/hbytes/hbytes.h @@ -1,5 +1,3 @@ -/* - */ /* * hbytes raw2h BINARY => hex * hbytes h2raw HEX => binary @@ -15,16 +13,44 @@ * * hbytes range VALUE START SIZE => substring (or error) * hbytes overwrite VAR START VALUE - * hbytes trimleft VALUE removes any leading 0 octets + * 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 + * + * 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 carry (-255 to 255, - * and -1,0,1 if VAR not empty) + * hbytes pad pa|ua VAR ALG METH [METHARGS] => 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 h2ulong HEX => ulong (HEX len must be 4) - * hbytes ulong2h UL => hex + * 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 @@ -37,29 +63,86 @@ * uint VARNAME/VALUE (VARNAME if ul2bitfields; * ulong VARNAME/VALUE VALUE if bitfields2ul) * - * ulong ul2int ULONG => INT can fail if >INT_MAX - * ulong int2ul INT => ULONG can fail if <0 + * Address ranges (addrmap.c): * - * hbytes shift l|r ULONG BITS fails if BITS >32 - * hbytes mask A B => A & B + * 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 compare A B - * => -2 A is lexically earlier than B and not a prefix of B (A DATA + * Error on missing default or if any prefix longer than ADDRESS. * - * hbytes pkcs5 pa|ua VAR ALG => worked? (always 1 for p) - * hbytes pkcs5 pn|un VAR BLOCKSIZE => worked? (always 1 for p) - * hbytes blockcipher d|e VAR ALG KEY MODE [IV] => IV - * hbytes blockcipher mac MSG ALG KEY MODE IV => final block + * 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. * - * hbytes hash ALG MESSAGE => hash - * hbytes hmac ALG MESSAGE KEY [MACLENGTH] => mac + * 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 */ +/* ---8<--- end of documentation comment --8<-- */ + +/* + * hbytes - hex-stringrep efficient byteblocks for Tcl + * Copyright 2006 Ian Jackson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + #ifndef HBYTES_H #define HBYTES_H @@ -73,10 +156,9 @@ #include #include #include +#include -#include - -typedef unsigned char Byte; +#include "chiark-tcl.h" /* from hbytes.c */ @@ -103,195 +185,76 @@ typedef struct { */ } HBytes_ComplexValue; /* pointed to from internalRep.otherValuePtr */ +void memxor(Byte *dest, const Byte *src, int l); +extern int Chiark_tcl_hbytes_Init(Tcl_Interp *ip); + /* called by load(3tcl) and also by extensions which depend on this one */ + /* Public interfaces: */ -extern Tcl_ObjType hbytes_type; +extern Tcl_ObjType cht_hbytes_type; -int hbytes_len(const HBytes_Value *v); -Byte *hbytes_data(const HBytes_Value *v); /* caller may then modify data! */ -int hbytes_issentinel(const HBytes_Value *v); +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); -Byte *hbytes_prepend(HBytes_Value *upd, int el); -Byte *hbytes_append(HBytes_Value *upd, int el); +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 */ -const Byte *hbytes_unprepend(HBytes_Value *upd, int rl); -const Byte *hbytes_unappend(HBytes_Value *upd, int rl); +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 hbytes_empty(HBytes_Value *returns); -void hbytes_sentinel(HBytes_Value *returns); -void hbytes_array(HBytes_Value *returns, const Byte *array, int l); -Byte *hbytes_arrayspace(HBytes_Value *returns, int l); -void hbytes_free(const HBytes_Value *frees); +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 hbytes_sentinel should not be passed to - * anything except HBYTES_IS..., and hbytes_free. */ - -/* from sockaddr.c */ - -typedef struct { - Byte *begin, *end; -} SockAddr_Value; - -extern Tcl_ObjType sockaddr_type; - -void sockaddr_clear(SockAddr_Value*); -void sockaddr_create(SockAddr_Value*, const struct sockaddr *addr, int len); -int sockaddr_len(const SockAddr_Value*); -const struct sockaddr *sockaddr_addr(const SockAddr_Value*); -void sockaddr_free(const SockAddr_Value*); - -/* from dgram.c */ - -extern Tcl_ObjType dgramsockid_type; -typedef struct DgramSocket *DgramSockID; +/* The value made by cht_hb_sentinel should not be passed to + * anything except HBYTES_IS..., and cht_hb_free. */ /* from hook.c */ -int staticerr(Tcl_Interp *ip, const char *m); -int posixerr(Tcl_Interp *ip, int errnoval, const char *m); -void objfreeir(Tcl_Obj *o); -int get_urandom(Tcl_Interp *ip, Byte *buffer, int l); - 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); -void obj_updatestr_vstringls(Tcl_Obj *o, ...); - /* const char*, int, const char*, int, ..., (const char*)0 */ -void obj_updatestr_string_len(Tcl_Obj *o, const char *str, int l); -void obj_updatestr_string(Tcl_Obj *o, const char *str); - /* from parse.c */ typedef struct { HBytes_Value *hb; - Tcl_Obj *obj, *var; + Something_Var sth; } HBytes_Var; -void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg); - -/* from chop.c */ - /* only do_... functions declared in tables.h */ - -/* from ulong.c */ - -Tcl_ObjType ulong_type; - -/* from enum.c */ - -extern Tcl_ObjType enum_nearlytype; -extern Tcl_ObjType enum1_nearlytype; - -const void *enum_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o, - const void *firstentry, size_t entrysize, - const char *what); -#define enum_lookup_cached(ip,o,table,what) \ - (enum_lookup_cached_func((ip),(o), \ - &(table)[0],sizeof((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. - */ +/* from addrmap.c */ -int enum1_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o, - const char *opts, const char *what); - /* -1 => error */ - -/* from crypto.c */ - -void memxor(Byte *dest, const Byte *src, int l); +typedef struct AddrMap_Value AddrMap_Value; typedef struct { - const char *name; - int pad, use_algname; -} PadMethod; - -extern Tcl_ObjType blockcipherkey_type; - -/* from algtables.c */ + AddrMap_Value *am; + Something_Var sth; +} AddrMap_Var; -typedef struct { - const char *name; - int hashsize, blocksize, statesize; - void (*init)(void *state); - void (*update)(void *state, const void *data, int len); - void (*final)(void *state, void *digest); - void (*oneshot)(void *digest, const void *data, int len); -} HashAlgInfo; - -extern const HashAlgInfo hashalginfos[]; - -typedef struct { - void (*make_schedule)(void *schedule, const void *key, int keylen); - void (*crypt)(const void *schedule, const void *in, void *out); - /* in and out may be the same, but if they aren't they may not overlap */ - /* in and out for crypt will have been through block_byteswap */ -} BlockCipherPerDirectionInfo; +extern Tcl_ObjType cht_addrmap_type; -typedef struct { - const char *name; - int blocksize, schedule_size, key_min, key_max; - void (*byteswap)(void *block); - BlockCipherPerDirectionInfo encrypt, decrypt; -} BlockCipherAlgInfo; - -extern const BlockCipherAlgInfo blockcipheralginfos[]; +/* from chop.c */ + /* only do_... functions declared in tables.h */ -/* from bcmode.c */ +/* from ulong.c */ -typedef struct { - const char *name; - int iv_blocks, buf_blocks, mac_blocks; - - /* Each function is allowed to use up to buf_blocks * blocksize - * bytes of space in buf. data is blocks * blocksize bytes - * long. data should be modified in place by encrypt and decrypt; - * modes may not change the size of data. iv is always provided and - * is always of length iv_blocks * blocksize; encrypt and - * decrypt may modify the iv value (in which case the Tcl caller - * will get the modified IV) but this is not recommended. mac - * should leave the mac, which must be mac_blocks * blocksize - * bytes, in buf. (Therefore mac_blocks must be at least - * buf_blocks.) - */ - const char *(*encrypt)(Byte *data, int nblocks, - const Byte *iv, Byte *buf, - const BlockCipherAlgInfo *alg, int encr, - const void *sch); - const char *(*decrypt)(Byte *data, int nblocks, - const Byte *iv, Byte *buf, - const BlockCipherAlgInfo *alg, int encr, - const void *sch); - const char *(*mac)(const Byte *data, int nblocks, - const Byte *iv, Byte *buf, - const BlockCipherAlgInfo *alg, - const void *sch); -} BlockCipherModeInfo; - -extern const BlockCipherModeInfo blockciphermodeinfos[]; - -/* from misc.c */ - -int setnonblock(int fd, int isnonblock); +Tcl_ObjType cht_ulong_type; /* useful macros */ #define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue) #define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue) -#define TALLOC(s) ((void*)Tcl_Alloc((s))) -#define TFREE(f) (Tcl_Free((void*)(f))) - #endif /*HBYTES_H*/