]> Cypherpunks repositories - keks.git/commitdiff
Restore c/cmd/pub-verify workability
authorSergey Matveev <stargrave@stargrave.org>
Sun, 6 Apr 2025 16:06:50 +0000 (19:06 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 6 Apr 2025 16:06:50 +0000 (19:06 +0300)
32 files changed:
c/cmd/cer-verify/all.do [deleted file]
c/cmd/pub-verify/.gitignore [moved from c/cmd/cer-verify/.gitignore with 61% similarity]
c/cmd/pub-verify/all.do [new file with mode: 0644]
c/cmd/pub-verify/clean [moved from c/cmd/cer-verify/clean with 50% similarity]
c/cmd/pub-verify/compile_flags.txt.do [moved from c/cmd/cer-verify/compile_flags.txt.do with 100% similarity]
c/cmd/pub-verify/conf/.gitignore [moved from c/cmd/cer-verify/conf/.gitignore with 100% similarity]
c/cmd/pub-verify/conf/gcl3.rc.do [moved from c/cmd/cer-verify/conf/gcl3.rc.do with 100% similarity]
c/cmd/pub-verify/conf/monocypher.rc.do [moved from c/cmd/cer-verify/conf/monocypher.rc.do with 100% similarity]
c/cmd/pub-verify/curves.c.in [moved from c/cmd/cer-verify/curves.c.in with 100% similarity]
c/cmd/pub-verify/pub-verify.c [moved from c/cmd/cer-verify/cer-verify.c with 72% similarity]
c/cmd/pub-verify/pub-verify.do [moved from c/cmd/cer-verify/cer-verify.do with 72% similarity]
c/cmd/pub-verify/verifier-ed25519-blake2b.c [moved from c/cmd/cer-verify/verifier-ed25519-blake2b.c with 81% similarity]
c/cmd/pub-verify/verifier-ed25519-blake2b.h [moved from c/cmd/cer-verify/verifier-ed25519-blake2b.h with 100% similarity]
c/cmd/pub-verify/verifier-ed25519-blake2b.o.do [moved from c/cmd/cer-verify/verifier-ed25519-blake2b.o.do with 100% similarity]
c/cmd/pub-verify/verifier-gost3410.c [moved from c/cmd/cer-verify/verifier-gost3410.c with 100% similarity]
c/cmd/pub-verify/verifier-gost3410.h [moved from c/cmd/cer-verify/verifier-gost3410.h with 100% similarity]
c/cmd/pub-verify/verifier-gost3410.o.do [moved from c/cmd/cer-verify/verifier-gost3410.o.do with 100% similarity]
c/lib/clean
c/lib/cm/.gitignore [new file with mode: 0644]
c/lib/cm/clean [moved from c/lib/pki/clean with 100% similarity]
c/lib/cm/default.schema.keks.c.in.do [new file with mode: 0644]
c/lib/cm/default.schema.keks.do [new file with mode: 0644]
c/lib/cm/install.do [new file with mode: 0644]
c/lib/cm/libkekscm.a.do [moved from c/lib/pki/libkekspki.a.do with 100% similarity]
c/lib/cm/o.list [new file with mode: 0644]
c/lib/cm/pub.c [new file with mode: 0644]
c/lib/cm/pub.h [moved from c/lib/pki/cer.h with 64% similarity]
c/lib/pki/.gitignore [deleted file]
c/lib/pki/cer.c [deleted file]
c/lib/pki/install.do [deleted file]
c/lib/pki/o.list [deleted file]
c/lib/schema.c

diff --git a/c/cmd/cer-verify/all.do b/c/cmd/cer-verify/all.do
deleted file mode 100644 (file)
index e6c21ce..0000000
+++ /dev/null
@@ -1 +0,0 @@
-redo-ifchange cer-verify
similarity index 61%
rename from c/cmd/cer-verify/.gitignore
rename to c/cmd/pub-verify/.gitignore
index 81179ab6ef776c4e7485892282a9c5ae58634e801a63038d9d33c89128e5b82d..c000eadcb693f4c840351a5415521a0475948c0a18f563d6b73d9869ece2debe 100644 (file)
@@ -1,2 +1,2 @@
-/cer-verify
 /compile_flags.txt
+/pub-verify
diff --git a/c/cmd/pub-verify/all.do b/c/cmd/pub-verify/all.do
new file mode 100644 (file)
index 0000000..84a3ca4
--- /dev/null
@@ -0,0 +1 @@
+redo-ifchange pub-verify
similarity index 50%
rename from c/cmd/cer-verify/clean
rename to c/cmd/pub-verify/clean
index f5e1b4a89236cb8ba06953118a454b7829c32e9a3223c6aba48aef08682792c0..48f4a9b705040ee603445db497c2cf8659c861fd9bb1a7d348e5dd84327ad54e 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/sh -e
 
 cd "$(dirname "$(realpath -- "$0")")"
-exec rm -f cer-verify compile_flags.txt conf/gcl3.rc conf/monocypher.rc *.o
+exec rm -f pub-verify compile_flags.txt conf/gcl3.rc conf/monocypher.rc *.o
similarity index 72%
rename from c/cmd/cer-verify/cer-verify.c
rename to c/cmd/pub-verify/pub-verify.c
index f303c0d49e4f512b14c6d0f9c29dfad4b89a61332912784e0d5b47d65b8e217c..ba459b7d9167dd9e5e6040cf293c05b6403b71736c60788aa2e0cb6bf794a983 100644 (file)
 #include <string.h>
 #include <time.h>
 
+#include <keks/cm/pub.h>
 #include <keks/err.h>
-#include <keks/items.h>
-#include <keks/pki/cer.h>
 
+#include "../lib/hex.h"
 #include "../lib/mmap.h"
 #include "../lib/uuid.h"
 
@@ -34,11 +34,11 @@ int
 main(int argc, char **argv)
 {
     if (argc < 3) {
-        fprintf(stderr, "Usage: %s EE.cer [CA.cer ...]\n", argv[0]);
+        fprintf(stderr, "Usage: %s EE.pub [CA.pub ...]\n", argv[0]);
         return EXIT_FAILURE;
     }
     const size_t cersLen = (size_t)argc - 1;
-    struct KEKSCer *cers = calloc(cersLen, sizeof(struct KEKSCer));
+    struct KEKSCMPub *cers = calloc(cersLen, sizeof(struct KEKSCMPub));
     assert(cers != NULL);
     char *failReason = NULL;
     for (int i = 1; i < argc; i++) {
@@ -51,17 +51,25 @@ main(int argc, char **argv)
         fputs(argv[i], stdout);
         fputs(":\t", stdout);
         size_t off = 0;
-        enum KEKSErr err = KEKSCerParse(&(cers[i - 1]), &off, &failReason, buf, len);
+        enum KEKSErr err = KEKSCMPubParse(&(cers[i - 1]), &off, &failReason, buf, len);
         if (err != KEKSErrNo) {
             fprintf(stderr, "%s: %s\n", argv[i], failReason);
             return EXIT_FAILURE;
         }
         fputs("cid:", stdout);
         UUIDPrint(cers[i - 1].cid);
-        fputs(" pkid:", stdout);
-        UUIDPrint(cers[i - 1].pkid);
-        fputs(" sid:", stdout);
-        UUIDPrint(cers[i - 1].sid);
+        {
+            fputs(" pubId:", stdout);
+            char *hex = HexEnc(cers[i - 1].pubId, 32);
+            fputs(hex, stdout);
+            free(hex);
+        }
+        {
+            fputs(" sid:", stdout);
+            char *hex = HexEnc(cers[i - 1].sid, 32);
+            fputs(hex, stdout);
+            free(hex);
+        }
         fputs("\n", stdout);
     }
 
@@ -72,26 +80,26 @@ main(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
-    struct KEKSCerSigVerifier sigVerifiers[] = {
+    struct KEKSCMPubSigVerifier sigVerifiers[] = {
         {.algo = "ed25519-blake2b", .func = ed25519blake2bSignatureVerifier},
         {.algo = "gost3410-256A", .func = gost3410SignatureVerifier},
         {.algo = "gost3410-512C", .func = gost3410SignatureVerifier},
         {.algo = NULL},
     };
-    struct KEKSCerVerifyOpts opts = {.t = now, .sigVerifiers = sigVerifiers};
+    struct KEKSCMPubVerifyOpts opts = {.t = now, .sigVerifiers = sigVerifiers};
 
-    struct KEKSCer *toVerify = &(cers[0]);
-    struct KEKSCer *verifier = NULL;
+    struct KEKSCMPub *toVerify = &(cers[0]);
+    struct KEKSCMPub *verifier = NULL;
     for (;;) {
         fputs("verifying ", stdout);
         UUIDPrint(toVerify->cid);
         fputs(": ", stdout);
-        if (!KEKSCerVerify(&failReason, &verifier, toVerify, cers, cersLen, opts)) {
+        if (!KEKSCMPubVerify(&failReason, &verifier, toVerify, cers, cersLen, opts)) {
             fputs(failReason, stdout);
             fputs("\n", stdout);
             return EXIT_FAILURE;
         }
-        if (memcmp(toVerify->sid, toVerify->pkid, 16) == 0) {
+        if (memcmp(toVerify->sid, toVerify->pubId, 32) == 0) {
             fputs("ok\n", stdout);
             break;
         }
similarity index 72%
rename from c/cmd/cer-verify/cer-verify.do
rename to c/cmd/pub-verify/pub-verify.do
index e42594d0222b2994f95a9f497ba8639ac192829960319cb6982a316ee13026d3..7f29ae5d5d53beb91c962ff6e870052cc48f93ec9914be3bbe324e08aa135110 100644 (file)
@@ -1,4 +1,10 @@
-deps="../lib/mmap.o ../lib/uuid.o verifier-ed25519-blake2b.o verifier-gost3410.o"
+deps="
+../lib/hex.o
+../lib/mmap.o
+../lib/uuid.o
+verifier-ed25519-blake2b.o
+verifier-gost3410.o
+"
 redo-ifchange $1.c $deps conf/gcl3.rc conf/monocypher.rc \
     ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
 read CC <../../conf/cc
@@ -11,4 +17,4 @@ $CC \
     $CFLAGS -I$PREFIX/include \
     -o $3 $2.c $deps \
     $LDFLAGS $GCL3_LDFLAGS $MONOCYPHER_LDFLAGS -L$PREFIX/lib \
-    -lkeks -lkekspki $GCL3_LDLIBS $MONOCYPHER_LDLIBS -static
+    -lkeks -lkekscm $GCL3_LDLIBS $MONOCYPHER_LDLIBS -static
similarity index 81%
rename from c/cmd/cer-verify/verifier-ed25519-blake2b.c
rename to c/cmd/pub-verify/verifier-ed25519-blake2b.c
index 0ecadd9135e5f8ec16b53a94debded48935f2f09f8db31375044e6a62053bd37..fe5550cfcff987c297fbc85374b1d62758939059e38f5b6f51c6c1ba0f4e1c8b 100644 (file)
@@ -27,5 +27,9 @@ ed25519blake2bSignatureVerifier(
         (*failReason) = "invalid signature len";
         return false;
     }
-    return crypto_eddsa_check(sig, pub, data, dataLen) == 0;
+    if (crypto_eddsa_check(sig, pub, data, dataLen) != 0) {
+        (*failReason) = "bad signature";
+        return false;
+    }
+    return true;
 }
index f6a08cac1d60e2063f57516d2b6d1d0938a3707b4693fb57fd4fe292e62f3f14..e633c5a199d24a9f603ef2be85e1e9c5e8bbdc7dfbdd7f5dad3c985812d242a8 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh -e
 
 cd "$(dirname "$(realpath -- "$0")")"
-pki/clean
+cm/clean
 exec rm -f *.o *.a compile_flags.txt
diff --git a/c/lib/cm/.gitignore b/c/lib/cm/.gitignore
new file mode 100644 (file)
index 0000000..30015a3
--- /dev/null
@@ -0,0 +1,3 @@
+/libkekscm.a
+/pub.schema.keks
+/pub.schema.keks.c.in
similarity index 100%
rename from c/lib/pki/clean
rename to c/lib/cm/clean
diff --git a/c/lib/cm/default.schema.keks.c.in.do b/c/lib/cm/default.schema.keks.c.in.do
new file mode 100644 (file)
index 0000000..6fa1180
--- /dev/null
@@ -0,0 +1,7 @@
+redo-ifchange $2.schema.keks
+echo "const unsigned char KEKSCMPubSchemaRaw[] = {"
+xxd -i -s +16 <$2.schema.keks
+echo "};"
+s=$(perl -e "print -s \"$2.schema.keks\"")
+s=$(( $s - 16 )) # skip MAGIC
+echo "const size_t KEKSCMPubSchemaRawLen = $s;"
diff --git a/c/lib/cm/default.schema.keks.do b/c/lib/cm/default.schema.keks.do
new file mode 100644 (file)
index 0000000..4d4033b
--- /dev/null
@@ -0,0 +1,3 @@
+n=${2##*/}.tcl
+redo-ifchange ../../../tcl/schema2bin ../../../tcl/schemas/$n
+../../../tcl/schema2bin ../../../tcl/schemas/$n | xxd -r -p
diff --git a/c/lib/cm/install.do b/c/lib/cm/install.do
new file mode 100644 (file)
index 0000000..bc6bcf1
--- /dev/null
@@ -0,0 +1,6 @@
+redo-ifchange *.h libkekscm.a ../../conf/prefix
+read PREFIX <../../conf/prefix
+mkdir -p $PREFIX/include/keks/cm $PREFIX/lib
+cp -f *.h $PREFIX/include/keks/cm
+cp -f libkekscm.a $PREFIX/lib
+chmod 644 $PREFIX/include/keks/cm/*.h $PREFIX/lib/libkekscm.a
diff --git a/c/lib/cm/o.list b/c/lib/cm/o.list
new file mode 100644 (file)
index 0000000..8f31940
--- /dev/null
@@ -0,0 +1 @@
+pub.o
diff --git a/c/lib/cm/pub.c b/c/lib/cm/pub.c
new file mode 100644 (file)
index 0000000..f059f9f
--- /dev/null
@@ -0,0 +1,197 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "../atom.h"
+#include "../dectai.h"
+#include "../err.h"
+#include "../items.h"
+#include "../schema.h"
+#include "pub.h"
+
+#include "pub.schema.keks.c.in"
+
+enum KEKSErr
+KEKSCMPubParse(
+    struct KEKSCMPub *cer,
+    size_t *off,
+    char **failReason,
+    const unsigned char *buf,
+    const size_t len)
+{
+    (*failReason) = "unspecified";
+    struct KEKSItems schema;
+    enum KEKSErr err = KEKSItemsInit(&schema, 512);
+    if (err != KEKSErrNo) {
+        (*failReason) = "init schema";
+        return err;
+    }
+    err = KEKSItemsParse(&schema, off, KEKSCMPubSchemaRaw, KEKSCMPubSchemaRawLen);
+    if (err != KEKSErrNo) {
+        (*failReason) = "parse schema";
+        return err;
+    }
+    size_t idxSchema = KEKSItemsGetByKey(&schema, 0, "pub");
+    if (idxSchema == 0) {
+        KEKSItemsFree(&schema);
+        (*failReason) = "schema: no pub";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    struct KEKSItems *items = &(cer->items);
+    err = KEKSItemsInit(items, 512);
+    if (err != KEKSErrNo) {
+        KEKSItemsFree(&schema);
+        (*failReason) = "init items";
+        return err;
+    }
+    (*off) = 0;
+    err = KEKSItemsParse(items, off, buf, len);
+    if (err != KEKSErrNo) {
+        KEKSItemsFree(&schema);
+        (*failReason) = "parse items";
+        return err;
+    }
+    struct KEKSSchemaErr errSchema = KEKSSchemaValidate(&schema, items, idxSchema, 0);
+    KEKSItemsFree(&schema);
+    if (errSchema.code != KEKSSchemaErrNo) {
+        (*failReason) = "schema failed";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    size_t idx = KEKSItemsGetByKey(items, KEKSItemsGetByKey(items, 0, "load"), "v");
+    cer->pub = KEKSItemsGetByKey(items, idx, "pub");
+    cer->pub = items->list[cer->pub].atom.v.list.head;
+    cer->sub = KEKSItemsGetByKey(items, idx, "sub");
+    cer->pubId = items->list[KEKSItemsGetByKey(items, idx, "id")].atom.v.str.ptr;
+    cer->sig = 0;
+    cer->cid = NULL;
+    cer->sid = NULL;
+    idx = KEKSItemsGetByKey(items, 0, "sigs");
+    if (idx == 0) {
+        return KEKSErrNo;
+    }
+    if (items->list[idx].atom.v.list.len != 1) {
+        (*failReason) = "len(/load/sigs) != 1";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    cer->sig = items->list[idx].atom.v.list.head;
+    idx = KEKSItemsGetByKey(items, cer->sig, "tbs");
+    cer->cid = items->list[KEKSItemsGetByKey(items, idx, "cid")].atom.v.hexlet;
+    cer->sid = items->list[KEKSItemsGetByKey(items, idx, "sid")].atom.v.str.ptr;
+    idx = KEKSItemsGetByKey(items, idx, "exp");
+    err = KEKSTAI64ToTimespec(
+        &(cer->since),
+        items->list[idx + 1].atom.v.str.ptr,
+        items->list[idx + 1].atom.v.str.len);
+    if ((err != KEKSErrNo) || (cer->since.tv_nsec != 0)) {
+        (*failReason) = "bad /sigs/./tbs/exp/since value";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    err = KEKSTimespecToUTC(&(cer->since));
+    if (err != KEKSErrNo) {
+        (*failReason) = "bad /sigs/./tbs/exp/since UTC value";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    err = KEKSTAI64ToTimespec(
+        &(cer->till),
+        items->list[idx + 2].atom.v.str.ptr,
+        items->list[idx + 2].atom.v.str.len);
+    if ((err != KEKSErrNo) || (cer->till.tv_nsec != 0)) {
+        (*failReason) = "bad /sigs/./tbs/exp/till value";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    err = KEKSTimespecToUTC(&(cer->till));
+    if (err != KEKSErrNo) {
+        (*failReason) = "bad /sigs/./tbs/exp/till UTC value";
+        return KEKSErrUnsatisfiedSchema;
+    }
+    return KEKSErrNo;
+}
+
+bool
+KEKSCMPubVerify(
+    char **failReason,
+    struct KEKSCMPub **verifier,
+    struct KEKSCMPub *cer,
+    struct KEKSCMPub *pool,
+    const size_t poolLen,
+    const struct KEKSCMPubVerifyOpts opts)
+{
+    (*failReason) = "unspecified";
+    if (opts.t.tv_sec <= cer->since.tv_sec) {
+        (*failReason) = "unsatisfied since";
+        return false;
+    }
+    if (opts.t.tv_sec >= cer->till.tv_sec) {
+        (*failReason) = "unsatisfied till";
+        return false;
+    }
+    (*verifier) = NULL;
+    for (size_t i = 0; i < poolLen; i++) {
+        if (memcmp(cer->sid, pool[i].pubId, 32) == 0) {
+            (*verifier) = &(pool[i]);
+            break;
+        }
+    }
+    if ((*verifier) == NULL) {
+        (*failReason) = "no verifier found";
+        return false;
+    }
+    struct KEKSItem *pubA = &((*verifier)->items.list[KEKSItemsGetByKey(
+        &((*verifier)->items), (*verifier)->pub, "a")]);
+    struct KEKSItem *pubV = &((*verifier)->items.list[KEKSItemsGetByKey(
+        &((*verifier)->items), (*verifier)->pub, "v")]);
+    size_t signIdx = KEKSItemsGetByKey(&(cer->items), cer->sig, "sign");
+    struct KEKSItem *sigV =
+        &(cer->items.list[KEKSItemsGetByKey(&(cer->items), signIdx, "v")]);
+    {
+        struct KEKSItem *sigA =
+            &(cer->items.list[KEKSItemsGetByKey(&(cer->items), signIdx, "a")]);
+        if ((sigA->atom.v.str.len != pubA->atom.v.str.len) ||
+            (memcmp(sigA->atom.v.str.ptr, pubA->atom.v.str.ptr, sigA->atom.v.str.len) !=
+             0)) {
+            (*failReason) = "sign.a != pub.a";
+            return false;
+        }
+    }
+    const size_t cap = (size_t)1 << (uint8_t)10;
+    unsigned char buf[(uint16_t)1 << (uint8_t)10] = {0};
+    size_t off = 0;
+    if (!KEKSItemsEncode(
+            &(cer->items),
+            KEKSItemsGetByKey(&(cer->items), 0, "load"),
+            &off,
+            buf,
+            cap)) {
+        (*failReason) = "can not prepare tbs: load";
+        return false;
+    }
+    size_t off2 = 0;
+    if (!KEKSItemsEncode(
+            &(cer->items),
+            KEKSItemsGetByKey(&(cer->items), cer->sig, "tbs"),
+            &off2,
+            buf + off,
+            cap - off)) {
+        (*failReason) = "can not prepare tbs: tbs";
+        return false;
+    }
+    off += off2;
+
+    for (size_t i = 0; opts.sigVerifiers[i].algo != NULL; i++) {
+        if (!KEKSStrEqual(&(pubA->atom), opts.sigVerifiers[i].algo)) {
+            continue;
+        }
+        return opts.sigVerifiers[i].func(
+            failReason,
+            pubA->atom.v.str.ptr,
+            pubA->atom.v.str.len,
+            sigV->atom.v.str.ptr,
+            sigV->atom.v.str.len,
+            pubV->atom.v.str.ptr,
+            pubV->atom.v.str.len,
+            buf,
+            off);
+    }
+    (*failReason) = "no signature verifier found";
+    return false;
+}
similarity index 64%
rename from c/lib/pki/cer.h
rename to c/lib/cm/pub.h
index 08eb4e810f8c7941f602bc4a6704995edb9c28c13423e39744452c3f5e74e34f..ac831d010586e32f3cd228a82c9ab064c8781290f7c3dfcbb9b962f12bba7242 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef KEKS_CER_H
-#define KEKS_CER_H
+#ifndef KEKS_CM_PUB_H
+#define KEKS_CM_PUB_H
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -8,14 +8,12 @@
 #include "../err.h"
 #include "../items.h"
 
-// TEXINFO: KEKSCer
-// @deftp {Data type} {struct KEKSCer}
+// TEXINFO: KEKSCMPub
+// @deftp {Data type} {struct KEKSCMPub}
 // Parsed certificate structure.
 // @table @code
 // @item .items
 //     Holds parsed @ref{KEKSItems} items.
-// @item .load
-//     Items index of the @code{/load/v}, certificate body.
 // @item .pub
 //     Items index of the first @code{/load/v/pub}, certificate's public key.
 // @item .sub
 // @item .sig
 //     Items index of the first @code{/sigs}, certificate's signature.
 // @item .cid
-//     Pointer to the start of if @code{cid} UUID, certificate's id.
-// @item .pkid
-//     Pointer to the start of if @code{pkid} UUID, certificate's
-//     first public key id.
+//     Pointer to the start of if @code{cid} hexlet, certificate's id.
+// @item .pubId
+//     Pointer to the start of if @code{id}, certificate's public key id.
 // @item .sid
-//     Pointer to the start of if @code{sid} UUID, certificate's signature id.
+//     Pointer to the start of if @code{sid}, certificate's signature id.
 // @item .since
 //     Parsed "since" datetime.
 // @item .till
 //     Parsed un"till" datetime.
 // @end table
 // @end deftp
-struct KEKSCer {
+struct KEKSCMPub {
     struct KEKSItems items;
-    size_t load;
     size_t pub;
     size_t sub;
     size_t sig;
     const unsigned char *cid;
-    const unsigned char *pkid;
+    const unsigned char *pubId;
     const unsigned char *sid;
     struct timespec since;
     struct timespec till;
 };
 
-// TEXINFO: KEKSCerParse
-// @deftypefun {enum KEKSErr} KEKSCerParse ( @
-//     struct KEKSCer *cer, @
+// TEXINFO: KEKSCMPubParse
+// @deftypefun {enum KEKSErr} KEKSCMPubParse ( @
+//     struct KEKSCMPub *cer, @
 //     size_t *off, @
 //     char **failReason, @
 //     const unsigned char *buf, @
@@ -63,8 +59,8 @@ struct KEKSCer {
 // the @var{failReason} to the string describing the error.
 // @end deftypefun
 enum KEKSErr
-KEKSCerParse(
-    struct KEKSCer *,
+KEKSCMPubParse(
+    struct KEKSCMPub *,
     size_t *off,
     char **failReason,
     const unsigned char *buf,
@@ -81,56 +77,59 @@ typedef bool (*keksSigVerifier)(
     const unsigned char *data,
     const size_t dataLen);
 
-// TEXINFO: KEKSCerSigVerifier
-// @deftp {Data type} {struct KEKSCerSigVerifier}
+// TEXINFO: KEKSCMPubSigVerifier
+// @deftp {Data type} {struct KEKSCMPubSigVerifier}
 // Cryptographic signature verifier. That structure's @code{.algo} holds
 // the string identifier of the algorithm met in the KEKS structures.
 // @code{.func} holds the pointer to the verifier function itself, that
 // accepts the algorithm identifier, signature, raw public key, the data
 // to be verified.
 // @end deftp
-struct KEKSCerSigVerifier {
+struct KEKSCMPubSigVerifier {
     char *algo;
     keksSigVerifier func;
 };
 
-// TEXINFO: KEKSCerVerifyOpts
-// @deftp {Data type} {struct KEKSCerVerifyOpts}
-// Certificate verification options:
+// TEXINFO: KEKSCMPubVerifyOpts
+// @deftp {Data type} {struct KEKSCMPubVerifyOpts}
+// Pubtificate verification options:
 // @table @code
 // @item .t
 //     Validity time to check against.
 // @item .sigVerifiers
-//     List of @ref{KEKSCerSigVerifier}.
+//     List of @ref{KEKSCMPubSigVerifier}.
 //     Its last dummy element must have NULL @code{.algo}.
 // @end table
 // @end deftp
-struct KEKSCerVerifyOpts {
+struct KEKSCMPubVerifyOpts {
     struct timespec t;
-    struct KEKSCerSigVerifier *sigVerifiers;
+    struct KEKSCMPubSigVerifier *sigVerifiers;
 };
 
-// TEXINFO: KEKSCerVerify
-// @deftypefun bool KEKSCerVerify ( @
+// TEXINFO: KEKSCMPubVerify
+// @deftypefun bool KEKSCMPubVerify ( @
 //     char **failReason, @
-//     struct KEKSCer **verifier, @
-//     struct KEKSCer *cer, @
-//     struct KEKSCer *pool, @
+//     struct KEKSCMPub **verifier, @
+//     struct KEKSCMPub *cer, @
+//     struct KEKSCMPub *pool, @
 //     const size_t poolLen, @
-//     const struct KEKSCerVerifyOpts opts)
+//     const struct KEKSCMPubVerifyOpts opts)
 // Verify @var{cer} certificate. @var{pool} is a list of certificates of
 // @var{poolLen} length, which is searched for verifier certificates. If
-// verifier is found (certificate with @code{pkid} equals to @code{sid}),
+// verifier is found (certificate with @code{pubId} equals to @code{sid}),
 // then @var{verifier} points to it. @var{opts} options affect
 // verification process.
 // @end deftypefun
 bool
-KEKSCerVerify(
+KEKSCMPubVerify(
     char **failReason,
-    struct KEKSCer **verifier,
-    struct KEKSCer *cer,
-    struct KEKSCer *pool,
+    struct KEKSCMPub **verifier,
+    struct KEKSCMPub *cer,
+    struct KEKSCMPub *pool,
     const size_t poolLen,
-    const struct KEKSCerVerifyOpts opts);
+    const struct KEKSCMPubVerifyOpts opts);
 
-#endif // KEKS_CER_H
+extern const unsigned char KEKSCMPubSchemaRaw[];
+extern const size_t KEKSCMPubSchemaRawLen;
+
+#endif // KEKS_CM_PUB_H
diff --git a/c/lib/pki/.gitignore b/c/lib/pki/.gitignore
deleted file mode 100644 (file)
index 3016f89..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/libkekspki.a
diff --git a/c/lib/pki/cer.c b/c/lib/pki/cer.c
deleted file mode 100644 (file)
index 81ce256..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "../atom.h"
-#include "../dectai.h"
-#include "../enc.h"
-#include "../err.h"
-#include "../items.h"
-#include "cer.h"
-
-enum KEKSErr
-KEKSCerParse(
-    struct KEKSCer *cer,
-    size_t *off,
-    char **failReason,
-    const unsigned char *buf,
-    const size_t len)
-{
-    struct KEKSItems *items = &(cer->items);
-    enum KEKSErr err = KEKSItemsInit(items, 64);
-    if (err != KEKSErrNo) {
-        return err;
-    }
-    err = KEKSItemsParse(items, off, buf, len);
-    if (err != KEKSErrNo) {
-        return err;
-    }
-    size_t idx = 0;
-    struct KEKSItem *item = NULL;
-    if (KEKSItemsGetByKey(items, 0, "hash") != 0) {
-        (*failReason) = "unexpected /hash";
-        return KEKSErrUnsatisfiedSchema;
-    }
-    size_t loadIdx = KEKSItemsGetByKey(items, 0, "load");
-    {
-        if (loadIdx == 0) {
-            (*failReason) = "no /load";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        idx = KEKSItemsGetByKeyAndType(items, loadIdx, "t", KEKSItemStr);
-        if (loadIdx == 0) {
-            (*failReason) = "no /load/t";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        if (!KEKSStrEqual(&(items->list[idx].atom), "cer")) {
-            (*failReason) = "/load/t != cer";
-            return KEKSErrUnsatisfiedSchema;
-        }
-    }
-    cer->load = KEKSItemsGetByKey(items, loadIdx, "v");
-    {
-        if (cer->load == 0) {
-            (*failReason) = "no /load/v";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        idx = KEKSItemsGetByKey(items, cer->load, "ku");
-        if (idx != 0) {
-            item = &(items->list[idx]);
-            if (item->atom.v.list.len == 0) {
-                (*failReason) = "empty /load/v/ku";
-                return KEKSErrUnsatisfiedSchema;
-            }
-            if (!KEKSMapHasOnlyType(items, idx, KEKSItemNIL)) {
-                (*failReason) = "bad /load/v/ku value";
-                return KEKSErrUnsatisfiedSchema;
-            }
-        }
-    }
-    idx = KEKSItemsGetByKey(items, cer->load, "pub");
-    {
-        if (idx == 0) {
-            (*failReason) = "no /load/v/pub";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        item = &(items->list[idx]);
-        if (item->atom.v.list.len != 1) {
-            (*failReason) = "len(/load/v/pub) != 1";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        idx = items->list[idx].atom.v.list.head;
-        cer->pub = idx;
-        while (idx != 0) {
-            if (KEKSItemsGetByKeyAndType(items, idx, "a", KEKSItemStr) == 0) {
-                (*failReason) = "no /load/v/pub/a";
-                return KEKSErrUnsatisfiedSchema;
-            }
-            if (KEKSItemsGetByKeyAndType(items, idx, "v", KEKSItemBin) == 0) {
-                (*failReason) = "no /load/v/pub/v";
-                return KEKSErrUnsatisfiedSchema;
-            }
-            {
-                size_t pkidIdx =
-                    KEKSItemsGetByKeyAndType(items, idx, "id", KEKSItemUUID);
-                if (pkidIdx == 0) {
-                    (*failReason) = "no /load/v/pub/id";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                cer->pkid = items->list[pkidIdx].atom.v.uuid;
-            }
-            idx = items->list[idx].next;
-        }
-    }
-    cer->sub = KEKSItemsGetByKey(items, cer->load, "sub");
-    {
-        if (cer->sub == 0) {
-            (*failReason) = "no /load/v/sub";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        item = &(items->list[cer->sub]);
-        if (item->atom.v.list.len == 0) {
-            (*failReason) = "empty /load/v/sub";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        if (!KEKSMapHasOnlyType(items, cer->sub, KEKSItemStr)) {
-            (*failReason) = "bad /load/v/sub value";
-            return KEKSErrUnsatisfiedSchema;
-        }
-    }
-    if (KEKSItemsGetByKey(items, cer->load, "crit") != 0) {
-        (*failReason) = "/load/v/crit is unsupported";
-        return KEKSErrUnsatisfiedSchema;
-    }
-    size_t sigsIdx = KEKSItemsGetByKey(items, 0, "sigs");
-    {
-        if (sigsIdx == 0) {
-            (*failReason) = "no /sigs";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        item = &(items->list[sigsIdx]);
-        if (item->atom.v.list.len != 1) {
-            (*failReason) = "len(/load/sigs) != 1";
-            return KEKSErrUnsatisfiedSchema;
-        }
-        size_t sigIdx = items->list[sigsIdx].atom.v.list.head;
-        cer->sig = sigIdx;
-        while (sigIdx != 0) {
-            if (KEKSItemsGetByKey(items, sigIdx, "hash") != 0) {
-                (*failReason) = "unexpected /sigs/./hash met";
-                return KEKSErrUnsatisfiedSchema;
-            }
-            {
-                idx = KEKSItemsGetByKey(items, sigIdx, "sign");
-                if (idx == 0) {
-                    (*failReason) = "no /sigs/./sign";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                if (KEKSItemsGetByKeyAndType(items, idx, "a", KEKSItemStr) == 0) {
-                    (*failReason) = "no /sigs/./sign/a";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                if (KEKSItemsGetByKeyAndType(items, idx, "v", KEKSItemBin) == 0) {
-                    (*failReason) = "no /sigs/./sign/v";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-            }
-            {
-                idx = KEKSItemsGetByKey(items, sigIdx, "tbs");
-                if (idx == 0) {
-                    (*failReason) = "no /sigs/./tbs";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                {
-                    size_t cidIdx =
-                        KEKSItemsGetByKeyAndType(items, idx, "cid", KEKSItemUUID);
-                    if (cidIdx == 0) {
-                        (*failReason) = "no /sigs/./tbs/cid";
-                        return KEKSErrUnsatisfiedSchema;
-                    }
-                    cer->cid = items->list[cidIdx].atom.v.uuid;
-                }
-                {
-                    size_t sidIdx =
-                        KEKSItemsGetByKeyAndType(items, idx, "sid", KEKSItemUUID);
-                    if (sidIdx == 0) {
-                        (*failReason) = "no /sigs/./tbs/sid";
-                        return KEKSErrUnsatisfiedSchema;
-                    }
-                    cer->sid = items->list[sidIdx].atom.v.uuid;
-                }
-                idx = KEKSItemsGetByKeyAndType(items, idx, "exp", KEKSItemList);
-                if (idx == 0) {
-                    (*failReason) = "no /sigs/./tbs/exp";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                if (!KEKSListHasOnlyType(items, idx, KEKSItemTAI64)) {
-                    (*failReason) = "bad /sigs/./tbs/exp value";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                item = &(items->list[idx]);
-                if (item->atom.v.list.len != 2) {
-                    (*failReason) = "len(/sigs/./tbs/exp) != 2";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                err = KEKSTAI64ToTimespec(
-                    &(cer->since),
-                    items->list[idx + 1].atom.v.str.ptr,
-                    items->list[idx + 1].atom.v.str.len);
-                if ((err != KEKSErrNo) || (cer->since.tv_nsec != 0)) {
-                    (*failReason) = "bad /sigs/./tbs/exp/since value";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                err = KEKSTimespecToUTC(&(cer->since));
-                if (err != KEKSErrNo) {
-                    (*failReason) = "bad /sigs/./tbs/exp/since UTC value";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                err = KEKSTAI64ToTimespec(
-                    &(cer->till),
-                    items->list[idx + 2].atom.v.str.ptr,
-                    items->list[idx + 2].atom.v.str.len);
-                if ((err != KEKSErrNo) || (cer->till.tv_nsec != 0)) {
-                    (*failReason) = "bad /sigs/./tbs/exp/till value";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-                err = KEKSTimespecToUTC(&(cer->till));
-                if (err != KEKSErrNo) {
-                    (*failReason) = "bad /sigs/./tbs/exp/till UTC value";
-                    return KEKSErrUnsatisfiedSchema;
-                }
-            }
-            sigIdx = items->list[sigIdx].next;
-        }
-    }
-    return KEKSErrNo;
-}
-
-bool
-KEKSCerVerify(
-    char **failReason,
-    struct KEKSCer **verifier,
-    struct KEKSCer *cer,
-    struct KEKSCer *pool,
-    const size_t poolLen,
-    const struct KEKSCerVerifyOpts opts)
-{
-    if (opts.t.tv_sec <= cer->since.tv_sec) {
-        (*failReason) = "unsatisfied since";
-        return false;
-    }
-    if (opts.t.tv_sec >= cer->till.tv_sec) {
-        (*failReason) = "unsatisfied till";
-        return false;
-    }
-    (*verifier) = NULL;
-    for (size_t i = 0; i < poolLen; i++) {
-        if (memcmp(cer->sid, pool[i].pkid, 16) == 0) {
-            (*verifier) = &(pool[i]);
-            break;
-        }
-    }
-    if ((*verifier) == NULL) {
-        (*failReason) = "no verifier found";
-        return false;
-    }
-    struct KEKSItem *pubA = &((*verifier)->items.list[KEKSItemsGetByKey(
-        &((*verifier)->items), (*verifier)->pub, "a")]);
-    struct KEKSItem *pubV = &((*verifier)->items.list[KEKSItemsGetByKey(
-        &((*verifier)->items), (*verifier)->pub, "v")]);
-    size_t signIdx = KEKSItemsGetByKey(&(cer->items), cer->sig, "sign");
-    struct KEKSItem *sigV =
-        &(cer->items.list[KEKSItemsGetByKey(&(cer->items), signIdx, "v")]);
-    {
-        struct KEKSItem *sigA =
-            &(cer->items.list[KEKSItemsGetByKey(&(cer->items), signIdx, "a")]);
-        if ((sigA->atom.v.str.len != pubA->atom.v.str.len) ||
-            (memcmp(sigA->atom.v.str.ptr, pubA->atom.v.str.ptr, sigA->atom.v.str.len) !=
-             0)) {
-            (*failReason) = "sign.a != pub.a";
-            return false;
-        }
-    }
-    const size_t cap = (size_t)1 << (uint8_t)10;
-    unsigned char buf[(uint16_t)1 << (uint8_t)10] = {0};
-    size_t off = 0;
-    {
-        const size_t items = 5;
-        struct KEKSItem tbsItems[5];
-        memset(&tbsItems, 0, sizeof tbsItems);
-        struct KEKSItems tbs = {
-            .list = tbsItems, .offsets = NULL, .len = items, .cap = -1};
-        tbsItems[0].atom.typ = KEKSItemMap;
-        tbsItems[0].atom.v.list.head = 1;
-
-        tbsItems[1].atom.typ = KEKSItemStr;
-        tbsItems[1].atom.v.str.len = 1;
-        tbsItems[1].atom.v.str.ptr = (const unsigned char *)"t";
-        tbsItems[1].next = 2;
-
-        tbsItems[2].atom.typ = KEKSItemStr;
-        tbsItems[2].atom.v.str.len = 3;
-        tbsItems[2].atom.v.str.ptr = (const unsigned char *)"cer";
-        tbsItems[2].next = 3;
-
-        tbsItems[3].atom.typ = KEKSItemStr;
-        tbsItems[3].atom.v.str.len = 1;
-        tbsItems[3].atom.v.str.ptr = (const unsigned char *)"v";
-        tbsItems[3].next = 4;
-
-        tbsItems[4].atom.typ = KEKSItemNIL;
-        tbsItems[4].next = 0;
-
-        if (!KEKSItemsEncode(&tbs, 0, &off, buf, cap)) {
-            (*failReason) = "can not prepare tbs: start";
-            return false;
-        }
-    }
-    off -= 2; // strip off NIL and EOC, continue map generation
-    if (!KEKSItemsEncode(&(cer->items), cer->load, &off, buf, cap)) {
-        (*failReason) = "can not prepare tbs: load";
-        return false;
-    }
-    {
-        size_t got = 0;
-        if (!KEKSAtomStrEncode(
-                &got, buf + off, cap - off, (const unsigned char *)"tbs", 3)) {
-            (*failReason) = "can not prepare tbs: tbs key";
-            return false;
-        }
-        off += got;
-    }
-    if (!KEKSItemsEncode(
-            &(cer->items),
-            KEKSItemsGetByKey(&(cer->items), cer->sig, "tbs"),
-            &off,
-            buf,
-            cap)) {
-        (*failReason) = "can not prepare tbs: tbs";
-        return false;
-    }
-    {
-        size_t got = 0;
-        if (!KEKSAtomEOCEncode(&got, buf + off, cap - off)) {
-            (*failReason) = "can not prepare tbs: eoc";
-            return false;
-        }
-        off += got;
-    }
-    for (size_t i = 0; opts.sigVerifiers[i].algo != NULL; i++) {
-        if (!KEKSStrEqual(&(pubA->atom), opts.sigVerifiers[i].algo)) {
-            continue;
-        }
-        return opts.sigVerifiers[i].func(
-            failReason,
-            pubA->atom.v.str.ptr,
-            pubA->atom.v.str.len,
-            sigV->atom.v.str.ptr,
-            sigV->atom.v.str.len,
-            pubV->atom.v.str.ptr,
-            pubV->atom.v.str.len,
-            buf,
-            off);
-    }
-    (*failReason) = "no signature verifier found";
-    return false;
-}
diff --git a/c/lib/pki/install.do b/c/lib/pki/install.do
deleted file mode 100644 (file)
index 686011b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-redo-ifchange *.h libkekspki.a ../../conf/prefix
-read PREFIX <../../conf/prefix
-mkdir -p $PREFIX/include/keks/pki $PREFIX/lib
-cp -f *.h $PREFIX/include/keks/pki
-cp -f libkekspki.a $PREFIX/lib
-chmod 644 $PREFIX/include/keks/pki/*.h $PREFIX/lib/libkekspki.a
diff --git a/c/lib/pki/o.list b/c/lib/pki/o.list
deleted file mode 100644 (file)
index c7f1e63..0000000
+++ /dev/null
@@ -1 +0,0 @@
-cer.o
index 988d359833ddf2fac15ccab078557d77db616895ce5a7e449e1dd8c790ac7ee0..1338d9f0f0388a97dd126176748341945a485677d3b919ceac5695c8ffdade85 100644 (file)
@@ -310,6 +310,9 @@ Eached:
             (*taken) = SIZE_MAX;
         } else {
             (*taken) = data->list[*taken].atom.v.list.head;
+            if (*eachInMap) {
+                (*taken) = data->list[*taken].next;
+            }
         }
         err.code = KEKSSchemaErrNo;
         return err;