--- /dev/null
+/*
+ * PKCS#5 padding
+ *
+ * arguments: block size to pad to, must be power of 2
+ *
+ * encoding: append between 1 and n bytes, all of the same value being
+ * the number of bytes appended
+ */
+
+#include "mech.h"
+
+struct mechdata {
+ unsigned mask;
+};
+
+static unsigned long setup(struct mechdata **md_r) {
+ struct mechdata *md;
+ unsigned long blocksize;
+
+ XMALLOC(md);
+
+ blocksize= getarg_ulong();
+ md->mask= blocksize - 1;
+ arg_assert(!md->mask & blocksize);
+ arg_assert(blocksize <= 255);
+
+ *md_r= md;
+ return blocksize;
+}
+
+static void mes_pkcs5(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
+ unsigned long blocksize;
+
+ blocksize= setup(md_r);
+ *maxsuffix_io += blocksize + 1;
+}
+
+static void mds_pkcs5(struct mechdata **md_r) {
+ setup(md_r);
+}
+
+static void menc_pkcs5(struct mechdata *md, struct buffer *buf) {
+ unsigned char *pad;
+ int padlen;
+
+ /* eg with blocksize=4 mask=3 mask+2=5 */
+ /* msgsize 20 21 22 23 24 */
+ padlen= md->mask - buf->size; /* -17 -18 -19 -16 -17 */
+ padlen &= md->mask; /* 3 2 1 0 3 */
+ padlen++; /* 4 3 2 1 4 */
+
+ pad= buf_append(buf,padlen);
+ memset(pad,padlen,padlen);
+}
+
+static const char *mdec_pkcs5(struct mechdata *md, struct buffer *buf) {
+ unsigned char *padp;
+ unsigned padlen;
+ int i;
+
+ BUF_UNPREPEND(padp,buf,1);
+ padlen= *padp;
+ if (!padlen || (padlen & ~md->mask)) return "invalid length";
+
+ BUF_UNPREPEND(padp,buf,padlen-1);
+ for (i=0; i<padlen-1; i++)
+ if (*++padp != padlen) return "corrupted padding";
+
+ return 0;
+}
+
+STANDARD_MECHANISMLIST("pkcs5",pkcs5)