diff --git a/lib/modules/SSL.pmod/https.pike b/lib/modules/SSL.pmod/https.pike
index 6aa4c5ca7fea135f9c9312f4d09a6b05e4553d97..7f1e2ed57a747d5cd9a107797275f445668afc06 100644
--- a/lib/modules/SSL.pmod/https.pike
+++ b/lib/modules/SSL.pmod/https.pike
@@ -1,6 +1,6 @@
-/* test_server.pike
+/* https.pike
  *
- * echoes packets over the SSL-packet layer
+ * dummy https server
  */
 
 #define PORT 25678
diff --git a/lib/modules/SSL.pmod/pem.pmod b/lib/modules/SSL.pmod/pem.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..a7c79e69994a2337e299dcb7f0effc93b3e3630f
--- /dev/null
+++ b/lib/modules/SSL.pmod/pem.pmod
@@ -0,0 +1,56 @@
+/* pem.pmod
+ *
+ * Primitive PEM decoder. (Extracted from roxen/server/protocols/ssl3.pike).
+ */
+
+object begin_pem = Regexp("-----BEGIN (.*)----- *$");
+object end_pem = Regexp("-----END (.*)----- *$");
+
+mapping(string:string) parse_pem(string f)
+{
+#ifdef PEM_DEBUG
+  werror(sprintf("parse_pem: '%s'\n", f));
+#endif
+#if 0
+if(!f)
+  {
+    werror("PEM: No certificate found.\n");
+    return 0;
+  }
+#endif
+  array(string) lines = f / "\n";
+  string name = 0;
+  int start_line;
+  mapping(string:string) parts = ([ ]);
+
+  for(int i = 0; i < sizeof(lines); i++)
+  {
+    array(string) res;
+    if (res = begin_pem->split(lines[i]))
+    {
+#ifdef PEM_DEBUG
+      werror(sprintf("Matched start of '%s'\n", res[0]));
+#endif
+      if (name) /* Bad syntax */
+	return 0;
+      name = res[0];
+      start_line = i + 1;
+    }
+    else if (res = end_pem->split(lines[i]))
+    {
+#ifdef PEM_DEBUG
+      werror(sprintf("Matched end of '%s'\n", res[0]));      
+#endif
+      if (name != res[0]) /* Bad syntax */
+	return 0;
+      parts[name] = MIME.decode_base64(lines[start_line .. i - 1] * "");
+      name = 0;
+    }
+  }
+  if (name) /* Bad syntax */
+    return 0;
+#ifdef PEM_DEBUG
+  werror(sprintf("pem contents: %O\n", parts));
+#endif
+  return parts;
+}