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;
}