chiark / gitweb /
secnet: Provide `make-public' verb
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 3 Dec 2019 22:57:25 +0000 (22:57 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 Feb 2020 21:56:51 +0000 (21:56 +0000)
This allows the config file to specify the use of the scheme loadpub
call without having to put public keys in separate files.  That will
be useful for testing and perhaps in installations that just want
fixed keys.

There is a bug here: we use system_log for reporting errors, but that
is not set up until after the configuration is read.  So errors turn
into segfaults.  We will fix that in a moment.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
README
modules.c
pubkeys.c
secnet.h

diff --git a/README b/README
index 1d29c55..e23701c 100644 (file)
--- a/README
+++ b/README
@@ -577,6 +577,15 @@ priv-cache: dict argument
   privkey-max (integer): optional, maximum size of private key
     file in bytes. [4095]
 
+** pubkeys
+
+Defines:
+  make-public (closure => sigpubkey closure)
+
+make-public: (
+  arg1: sigscheme name
+  arg2: base91s encoded public key data, according to algorithm
+
 ** rsa
 
 Defines:
index de3e699..38f1d0f 100644 (file)
--- a/modules.c
+++ b/modules.c
@@ -21,6 +21,7 @@
 
 void init_builtin_modules(dict_t *dict)
 {
+    pubkeys_init(dict);
     resolver_module(dict);
     random_module(dict);
     udp_module(dict);
index 7ba9482..903103f 100644 (file)
--- a/pubkeys.c
+++ b/pubkeys.c
@@ -17,6 +17,8 @@
  * https://www.gnu.org/licenses/gpl.html.
  */
 
+#include "util.h"
+#include "base91s/base91.h"
 #include "pubkeys.h"
 #include "pubkeys.yy.h"
 
@@ -43,3 +45,54 @@ const struct sigscheme_info *sigscheme_lookup(const char *name)
            return scheme;
     return 0;
 }
+
+static list_t *makepublic_apply(closure_t *self, struct cloc loc,
+                               dict_t *context, list_t *args)
+{
+#define ARG(ix,vn,what)                                                        \
+    item_t *vn##_i=list_elem(args,ix);                                 \
+    if (!vn##_i) cfgfatal(loc,"make-public","need " what);             \
+    if (vn##_i->type!=t_string) cfgfatal(vn##_i->loc,"make-public",    \
+                                   what "must be string");             \
+    const char *vn=vn##_i->data.string
+
+    ARG(0,algname,"algorithm name");
+    ARG(1,b91d,"base91s-encoded public key");
+
+    const struct sigscheme_info *sch=sigscheme_lookup(algname);
+    if (!sch) cfgfatal(algname_i->loc,"make-public",
+                      "unknown algorithm `%s'",algname);
+
+    size_t b91l=strlen(b91d);
+    if (b91l > INT_MAX/4) cfgfatal(algname_i->loc,"make-public",
+                                     "base91s data unreasonably long");
+
+    struct buffer_if buf;
+    buffer_new(&buf,base91s_decode_maxlen(b91l));
+    BUF_ALLOC(&buf,"make-public data buf");
+    assert(buf.start == buf.base);
+    struct base91s b91;
+    base91s_init(&b91);
+    buf.size= base91s_decode(&b91,b91d,b91l,buf.start);
+    buf.size += base91s_decode_end(&b91,buf.start+buf.size);
+    assert(buf.size <= buf.alloclen);
+
+    struct sigpubkey_if *pubkey;
+    closure_t *cl;
+    bool_t ok=sch->loadpub(sch,&buf,&pubkey,&cl,system_log,loc);
+    if (!ok) cfgfatal(loc,"make-public","public key loading failed");
+
+    if (pubkey->sethash) {
+       struct hash_if *defhash=
+           find_cl_if(context,"hash",CL_HASH,True,"make-public",loc);
+       pubkey->sethash(pubkey->st,defhash);
+    }
+
+    BUF_FREE(&buf);
+    buffer_destroy(&buf);
+    return new_closure(cl);
+}
+
+void pubkeys_init(dict_t *dict) {
+    add_closure(dict,"make-public",makepublic_apply);
+}
index 057d399..dbf3341 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -377,6 +377,7 @@ typedef void init_module(dict_t *dict);
 
 extern void init_builtin_modules(dict_t *dict);
 
+extern init_module pubkeys_init;
 extern init_module resolver_module;
 extern init_module random_module;
 extern init_module udp_module;