chiark / gitweb /
@@ -1,6 +1,7 @@
[userv-utils.git] / ipif / mech-pkcs5.c
diff --git a/ipif/mech-pkcs5.c b/ipif/mech-pkcs5.c
new file mode 100644 (file)
index 0000000..3603276
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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)