X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=crypto%2Fcrypto.c;h=f6f12e1e70c568adeec252ee9379964834f89679;hp=1866a6578504be8232074ecdd19d6f47322b6953;hb=bc4e7d2673e44826dd768ad7f91c393349da24de;hpb=9b7d11070d3e9dc1eb61cbccd5155f47a27047c3;ds=sidebyside diff --git a/crypto/crypto.c b/crypto/crypto.c index 1866a65..f6f12e1 100644 --- a/crypto/crypto.c +++ b/crypto/crypto.c @@ -11,7 +11,49 @@ void memxor(Byte *dest, const Byte *src, int l) { 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