* hbytes raw2h BINARY => hex
* hbytes h2raw HEX => binary
*
+ * 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 ...]
const char *what);
#define enum_lookup_cached(ip,o,table,what) \
(enum_lookup_cached_func((ip),(o), \
- sizeof((table)[0]),&(table)[0], \
+ &(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*.
void memxor(Byte *dest, const Byte *src, int l);
+typedef struct {
+ const char *name;
+ int pad, use_algname;
+} PadMethod;
+
/* from hash.c */
typedef struct {
return TCL_OK;
}
-#if 0
-HC_DEFINE(pkcs5) {
- static const PadKindInfo padkindinfos[0]= {
- { "pa", 1, 1 },
- { "pn", 1, 0 },
- { "ua", 0, 1 },
- { "un", 0, 0 },
- { 0 }
- };
-
- HC_DECLS_HBV;
- Tcl_Obj *v;
- int blocksize;
- const PadKindInfo *pk;
- const BlockCipherInfo *bc;
-
- HC_ARG_ENUM(pk, padkindinfos);
- HC_ARG_HBV;
- if (!pk->algname) HC_ARG_INTRANGE(blocksize, 1,255);
- else { HC_ARG_ENUM(bc, blockciphers); blocksize= bc->blocksize; }
- HC_ARGS_E;
-
- /* do nothing :-) */
-
- HC_FINI_HBV;
+int do_hbytes_length(ClientData cd, Tcl_Interp *ip,
+ HBytes_Value v, int *result) {
+ *result= hbytes_len(&v);
+ return TCL_OK;
}
-#endif
int do__hbytes(ClientData cd, Tcl_Interp *ip,
const HBytes_SubCommand *subcmd,
void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
Tcl_Obj *ro;
- Tcl_InvalidateStringRep(agg->obj);
+ if (agg->obj) Tcl_InvalidateStringRep(agg->obj);
if (!rc) {
assert(agg->obj);
ro= Tcl_ObjSetVar2(ip,agg->var,0,agg->obj,TCL_LEAVE_ERR_MSG);
return obj;
}
+Tcl_Obj *ret_int(Tcl_Interp *ip, int val) {
+ return Tcl_NewIntObj(val);
+}
+
Tcl_Obj *ret_obj(Tcl_Interp *ip, Tcl_Obj *val) {
return val;
}
h2raw
hex hb
=> obj
+ length
+ v hb
+ => int
prepend
v hbv
str ...
=> hb
pkcs5
meth enum(PadMethod, "hbytes pad subcommand")
- obj ...
+ v hbv
+ block obj
+ => int
# blockcipher
# encrypt charfrom("de","encrypt/decrypt")
# v hbv
# key hb
# maclen int
# => hb
-
-Table padmethod PadMethod
- pa 1
- v hbv
- alg enum(BlockCipherAlgInfo, "pad alg")
- ua 0
- v hbv
- alg enum(BlockCipherAlgInfo, "pad alg")
- pn 1
- v hbv
- block int
- un 0
- v hbv
- block int
-
-EntryExtra PadMethod
- int pad;
while (l--) *dest++ ^= *src++;
}
+const PadMethod padmethods[]= {
+ { "un", 0, 0 },
+ { "ua", 0, 1 },
+ { "pn", 1, 0 },
+ { "pa", 1, 1 },
+ { 0 }
+};
+
int do_hbytes_pkcs5(ClientData cd, Tcl_Interp *ip,
- const PadMethod *meth, int objc, Tcl_Obj *const *objv) {
- return meth->func((void*)meth, ip, objc, objv);
+ const PadMethod *meth, HBytes_Var v, Tcl_Obj *block,
+ int *ok) {
+ int rc, blocksize, padlen, old_len, i;
+ Byte *padding;
+ const Byte *unpad;
+
+ if (meth->use_algname) {
+ const BlockCipherAlgInfo *alg;
+ alg= enum_lookup_cached(ip,block,blockcipheralginfos,"cipher alg for pad");
+ if (!alg) return TCL_ERROR;
+ blocksize= alg->blocksize;
+ } else {
+ rc= Tcl_GetIntFromObj(ip, block, &blocksize); if (rc) return rc;
+ if (blocksize < 1 || blocksize > 255)
+ return staticerr(ip, "block size out of pkcs#5 range 1..255");
+ }
+
+ if (meth->pad) {
+ padlen= blocksize - (hbytes_len(v.hb) % blocksize);
+ padding= hbytes_append(v.hb, padlen);
+ memset(padding, padlen, padlen);
+ } else {
+ old_len= hbytes_len(v.hb); if (old_len % blocksize) goto bad;
+ unpad= hbytes_unappend(v.hb, 1); if (!unpad) goto bad;
+ padlen= *unpad;
+ if (padlen < 1 || padlen > blocksize) goto bad;
+ unpad= hbytes_unappend(v.hb, padlen-1); if (!unpad) goto bad;
+ for (i=0; i<padlen-1; i++, unpad++) if (*unpad != padlen) goto bad;
+ }
+
+ *ok= 1;
+ return TCL_OK;
+
+ bad:
+ *ok= 0;
+ return TCL_OK;
}
* hbytes raw2h BINARY => hex
* hbytes h2raw HEX => binary
*
+ * 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 ...]
const char *what);
#define enum_lookup_cached(ip,o,table,what) \
(enum_lookup_cached_func((ip),(o), \
- sizeof((table)[0]),&(table)[0], \
+ &(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*.
void memxor(Byte *dest, const Byte *src, int l);
+typedef struct {
+ const char *name;
+ int pad, use_algname;
+} PadMethod;
+
/* from hash.c */
typedef struct {
return TCL_OK;
}
-#if 0
-HC_DEFINE(pkcs5) {
- static const PadKindInfo padkindinfos[0]= {
- { "pa", 1, 1 },
- { "pn", 1, 0 },
- { "ua", 0, 1 },
- { "un", 0, 0 },
- { 0 }
- };
-
- HC_DECLS_HBV;
- Tcl_Obj *v;
- int blocksize;
- const PadKindInfo *pk;
- const BlockCipherInfo *bc;
-
- HC_ARG_ENUM(pk, padkindinfos);
- HC_ARG_HBV;
- if (!pk->algname) HC_ARG_INTRANGE(blocksize, 1,255);
- else { HC_ARG_ENUM(bc, blockciphers); blocksize= bc->blocksize; }
- HC_ARGS_E;
-
- /* do nothing :-) */
-
- HC_FINI_HBV;
+int do_hbytes_length(ClientData cd, Tcl_Interp *ip,
+ HBytes_Value v, int *result) {
+ *result= hbytes_len(&v);
+ return TCL_OK;
}
-#endif
int do__hbytes(ClientData cd, Tcl_Interp *ip,
const HBytes_SubCommand *subcmd,
void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
Tcl_Obj *ro;
- Tcl_InvalidateStringRep(agg->obj);
+ if (agg->obj) Tcl_InvalidateStringRep(agg->obj);
if (!rc) {
assert(agg->obj);
ro= Tcl_ObjSetVar2(ip,agg->var,0,agg->obj,TCL_LEAVE_ERR_MSG);
return obj;
}
+Tcl_Obj *ret_int(Tcl_Interp *ip, int val) {
+ return Tcl_NewIntObj(val);
+}
+
Tcl_Obj *ret_obj(Tcl_Interp *ip, Tcl_Obj *val) {
return val;
}