]> Cypherpunks repositories - keks.git/commitdiff
cyac implemented certificate verifier
authorSergey Matveev <stargrave@stargrave.org>
Tue, 15 Oct 2024 07:31:30 +0000 (10:31 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 15 Oct 2024 12:29:22 +0000 (15:29 +0300)
78 files changed:
cyac/.gitignore
cyac/cmd/.gitignore [deleted file]
cyac/cmd/all.do [deleted file]
cyac/cmd/cer-verify/.gitignore [new file with mode: 0644]
cyac/cmd/cer-verify/all.do [new file with mode: 0644]
cyac/cmd/cer-verify/cer-verify.c [new file with mode: 0644]
cyac/cmd/cer-verify/cer-verify.do [new file with mode: 0644]
cyac/cmd/cer-verify/clean [new file with mode: 0755]
cyac/cmd/cer-verify/compile_flags.txt.do [new file with mode: 0644]
cyac/cmd/cer-verify/conf/.gitignore [new file with mode: 0644]
cyac/cmd/cer-verify/conf/gcl3.rc.do [new file with mode: 0644]
cyac/cmd/cer-verify/curves.c.in [new file with mode: 0644]
cyac/cmd/cer-verify/verifier-gost3410.c [new file with mode: 0644]
cyac/cmd/cer-verify/verifier-gost3410.h [new file with mode: 0644]
cyac/cmd/cer-verify/verifier-gost3410.o.do [new file with mode: 0644]
cyac/cmd/clean
cyac/cmd/default.do [deleted file]
cyac/cmd/lib/clean [new file with mode: 0755]
cyac/cmd/lib/default.o.do [new file with mode: 0644]
cyac/cmd/lib/hex.c [moved from cyac/cmd/hex.c.in with 91% similarity]
cyac/cmd/lib/hex.h [new file with mode: 0644]
cyac/cmd/lib/mmap.c [new file with mode: 0644]
cyac/cmd/lib/mmap.h [new file with mode: 0644]
cyac/cmd/lib/uuid.c [new file with mode: 0644]
cyac/cmd/lib/uuid.h [new file with mode: 0644]
cyac/cmd/print-items/.gitignore [new file with mode: 0644]
cyac/cmd/print-items/all.do [new file with mode: 0644]
cyac/cmd/print-items/clean [new file with mode: 0755]
cyac/cmd/print-items/print-items.c [moved from cyac/cmd/print-items.c with 86% similarity]
cyac/cmd/print-items/print-items.do [new file with mode: 0644]
cyac/cmd/print-itered/.gitignore [new file with mode: 0644]
cyac/cmd/print-itered/all.do [new file with mode: 0644]
cyac/cmd/print-itered/clean [new file with mode: 0755]
cyac/cmd/print-itered/print-itered.c [moved from cyac/cmd/print-itered.c with 82% similarity]
cyac/cmd/print-itered/print-itered.do [new file with mode: 0644]
cyac/cmd/test-vector/.gitignore [new file with mode: 0644]
cyac/cmd/test-vector/all.do [new file with mode: 0644]
cyac/cmd/test-vector/clean [new file with mode: 0755]
cyac/cmd/test-vector/test-vector.c [moved from cyac/cmd/test-vector.c with 93% similarity]
cyac/cmd/test-vector/test-vector.do [new file with mode: 0644]
cyac/default.o.do [deleted file]
cyac/lib/.gitignore [new file with mode: 0644]
cyac/lib/atoms.h [moved from cyac/atoms.h with 100% similarity]
cyac/lib/clean [moved from cyac/clean with 70% similarity]
cyac/lib/dec.c [moved from cyac/dec.c with 100% similarity]
cyac/lib/dec.h [moved from cyac/dec.h with 100% similarity]
cyac/lib/dectai.c [moved from cyac/dectai.c with 100% similarity]
cyac/lib/dectai.h [moved from cyac/dectai.h with 100% similarity]
cyac/lib/default.o.do [new file with mode: 0644]
cyac/lib/enc.c [moved from cyac/enc.c with 100% similarity]
cyac/lib/enc.h [moved from cyac/enc.h with 100% similarity]
cyac/lib/enctai.c [moved from cyac/enctai.c with 100% similarity]
cyac/lib/enctai.h [moved from cyac/enctai.h with 100% similarity]
cyac/lib/err.c [new file with mode: 0644]
cyac/lib/err.h [moved from cyac/err.h with 92% similarity]
cyac/lib/frombe.c [moved from cyac/frombe.c with 100% similarity]
cyac/lib/frombe.h [moved from cyac/frombe.h with 100% similarity]
cyac/lib/h-extract.pl [moved from cyac/h-extract.pl with 64% similarity]
cyac/lib/install.do [moved from cyac/install.do with 68% similarity]
cyac/lib/items.c [moved from cyac/items.c with 58% similarity]
cyac/lib/items.h [moved from cyac/items.h with 62% similarity]
cyac/lib/iter.c [moved from cyac/iter.c with 93% similarity]
cyac/lib/iter.h [moved from cyac/iter.h with 100% similarity]
cyac/lib/leapsecs.c [moved from cyac/leapsecs.c with 100% similarity]
cyac/lib/leapsecs.h [moved from cyac/leapsecs.h with 100% similarity]
cyac/lib/libyac.a.do [moved from cyac/libyac.a.do with 58% similarity]
cyac/lib/o.list [moved from cyac/o.list with 92% similarity]
cyac/lib/pki/.gitignore [new file with mode: 0644]
cyac/lib/pki/cer.c [new file with mode: 0644]
cyac/lib/pki/cer.h [new file with mode: 0644]
cyac/lib/pki/clean [new file with mode: 0755]
cyac/lib/pki/install.do [new file with mode: 0644]
cyac/lib/pki/libyacpki.a.do [new file with mode: 0644]
cyac/lib/pki/o.list [new file with mode: 0644]
cyac/lib/tobe.c [moved from cyac/tobe.c with 100% similarity]
cyac/lib/tobe.h [moved from cyac/tobe.h with 100% similarity]
cyac/lib/utf8.c [moved from cyac/utf8.c with 100% similarity]
cyac/lib/utf8.h [moved from cyac/utf8.h with 100% similarity]

index a0169a40d0b195ae4726b02fb85ca3380c391fd7498cd234c66701a4a091985b..b83cc4558d1a936afb0bfbc66b79aa127fb108339fa65495d385df8447e5edef 100644 (file)
@@ -1,3 +1 @@
-/*.o
 /compile_flags.txt
-/libyac.a
diff --git a/cyac/cmd/.gitignore b/cyac/cmd/.gitignore
deleted file mode 100644 (file)
index 9caf01a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/print-items
-/print-itered
-/test-vector
diff --git a/cyac/cmd/all.do b/cyac/cmd/all.do
deleted file mode 100644 (file)
index 1cf8db8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-redo-ifchange print-items print-itered test-vector
diff --git a/cyac/cmd/cer-verify/.gitignore b/cyac/cmd/cer-verify/.gitignore
new file mode 100644 (file)
index 0000000..81179ab
--- /dev/null
@@ -0,0 +1,2 @@
+/cer-verify
+/compile_flags.txt
diff --git a/cyac/cmd/cer-verify/all.do b/cyac/cmd/cer-verify/all.do
new file mode 100644 (file)
index 0000000..e6c21ce
--- /dev/null
@@ -0,0 +1 @@
+redo-ifchange cer-verify
diff --git a/cyac/cmd/cer-verify/cer-verify.c b/cyac/cmd/cer-verify/cer-verify.c
new file mode 100644 (file)
index 0000000..9643a29
--- /dev/null
@@ -0,0 +1,99 @@
+// cyac -- C YAC encoder implementation
+// Copyright (C) 2024 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <yac/err.h>
+#include <yac/pki/cer.h>
+
+#include "../lib/mmap.h"
+#include "../lib/uuid.h"
+
+#include "verifier-gost3410.h"
+
+int
+main(int argc, char **argv)
+{
+    if (argc < 3) {
+        fprintf(stderr, "Usage: %s EE.cer [CA.cer ...]\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+    const ptrdiff_t cersLen = (ptrdiff_t)argc - 1;
+    struct YACCer *cers = calloc((size_t)cersLen, sizeof(struct YACCer));
+    assert(cers != NULL);
+    char *failReason = NULL;
+    for (int i = 1; i < argc; i++) {
+        unsigned char *buf = NULL;
+        size_t len = 0;
+        if (!Mmap(&buf, &len, argv[i])) {
+            fprintf(stderr, "%s\n", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        fputs(argv[i], stdout);
+        fputs(":\t", stdout);
+        ptrdiff_t off = 0;
+        enum YACErr err = YACCerParse(&(cers[i - 1]), &off, &failReason, buf, len);
+        if (err != YACErrNo) {
+            fprintf(stderr, "%s\n", 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("\n", stdout);
+    }
+
+    struct timeval now;
+    if (gettimeofday(&now, NULL) != 0) {
+        fprintf(stderr, "%s\n", strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    struct YACCerSigVerifier sigVerifiers[] = {
+        {.algo = "gost3410-256A", .func = gost3410SignatureVerifier},
+        {.algo = "gost3410-512C", .func = gost3410SignatureVerifier},
+    };
+    struct YACCerVerifyOpts opts = {
+        .t = now, .sigVerifiers = sigVerifiers, .sigVerifiersLen = 2};
+
+    struct YACCer *toVerify = &(cers[0]);
+    struct YACCer *verifier = NULL;
+    for (;;) {
+        fputs("verifying ", stdout);
+        UUIDPrint(toVerify->cid);
+        fputs(": ", stdout);
+        if (!YACCerVerify(
+                &failReason, &verifier, toVerify, cers, (size_t)cersLen, opts)) {
+            fputs(failReason, stdout);
+            fputs("\n", stdout);
+            return EXIT_FAILURE;
+        }
+        fputs("ok\n", stdout);
+        if (memcmp(toVerify->sid, toVerify->pkid, 16) == 0) {
+            break;
+        }
+        toVerify = verifier;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/cyac/cmd/cer-verify/cer-verify.do b/cyac/cmd/cer-verify/cer-verify.do
new file mode 100644 (file)
index 0000000..ad75159
--- /dev/null
@@ -0,0 +1,13 @@
+deps="../lib/mmap.o ../lib/uuid.o verifier-gost3410.o"
+redo-ifchange $1.c $deps conf/gcl3.rc \
+    ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+LDFLAGS=$(cat ../../conf/ldflags)
+. conf/gcl3.rc
+read PREFIX <../../conf/prefix
+$CC \
+    $CFLAGS -I$PREFIX/include \
+    -o $3 $2.c $deps \
+    $LDFLAGS $GCL3_LDFLAGS -L$PREFIX/lib \
+    -lyac -lyacpki $GCL3_LDLIBS
diff --git a/cyac/cmd/cer-verify/clean b/cyac/cmd/cer-verify/clean
new file mode 100755 (executable)
index 0000000..cdb7ffb
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f cer-verify compile_flags.txt conf/gcl3.rc
diff --git a/cyac/cmd/cer-verify/compile_flags.txt.do b/cyac/cmd/cer-verify/compile_flags.txt.do
new file mode 100644 (file)
index 0000000..e6bf334
--- /dev/null
@@ -0,0 +1,5 @@
+redo-ifchange ../../conf/prefix conf/gcl3.rc
+. conf/gcl3.rc
+read PREFIX <../../conf/prefix
+printf %s "-I$PREFIX/include $GCL3_CFLAGS" |
+tr " " "\n" | grep -v "^$" | sort | uniq
diff --git a/cyac/cmd/cer-verify/conf/.gitignore b/cyac/cmd/cer-verify/conf/.gitignore
new file mode 100644 (file)
index 0000000..0f57c2c
--- /dev/null
@@ -0,0 +1 @@
+/gcl3.rc
diff --git a/cyac/cmd/cer-verify/conf/gcl3.rc.do b/cyac/cmd/cer-verify/conf/gcl3.rc.do
new file mode 100644 (file)
index 0000000..eeb9168
--- /dev/null
@@ -0,0 +1,12 @@
+PKGCONF=${PKGCONF:-`command -v pkgconf || command -v pkg-config`}
+cat <<EOF
+{
+    read GCL3_CFLAGS
+    read GCL3_LDFLAGS
+    read GCL3_LDLIBS
+} <<EOF
+EOF
+$PKGCONF --cflags gcl3
+$PKGCONF --libs-only-L gcl3
+$PKGCONF --libs-only-l gcl3
+echo EOF
diff --git a/cyac/cmd/cer-verify/curves.c.in b/cyac/cmd/cer-verify/curves.c.in
new file mode 100644 (file)
index 0000000..6e5092b
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdint.h>
+
+// clang-format off
+static uint8_t gost3410Curve256Ap[32] = {
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x97,
+};
+static uint8_t gost3410Curve256Aq[32] = {
+    0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x0F,0xD8,0xCD,0xDF,0xC8,0x7B,0x66,0x35, 0xC1,0x15,0xAF,0x55,0x6C,0x36,0x0C,0x67,
+};
+static uint8_t gost3410Curve256Ae[32] = {
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+};
+static uint8_t gost3410Curve256Ad[32] = {
+    0x06,0x05,0xF6,0xB7,0xC1,0x83,0xFA,0x81, 0x57,0x8B,0xC3,0x9C,0xFA,0xD5,0x18,0x13,
+    0x2B,0x9D,0xF6,0x28,0x97,0x00,0x9A,0xF7, 0xE5,0x22,0xC3,0x2D,0x6D,0xC7,0xBF,0xFB,
+};
+static uint8_t gost3410Curve256Au[32] = {
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
+};
+static uint8_t gost3410Curve256Av[32] = {
+    0x60,0xCA,0x1E,0x32,0xAA,0x47,0x5B,0x34, 0x84,0x88,0xC3,0x8F,0xAB,0x07,0x64,0x9C,
+    0xE7,0xEF,0x8D,0xBE,0x87,0xF2,0x2E,0x81, 0xF9,0x2B,0x25,0x92,0xDB,0xA3,0x00,0xE7,
+};
+
+static uint8_t gost3410Curve512Cp[64] = {
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xC7,
+};
+static uint8_t gost3410Curve512Cq[64] = {
+    0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xC9,0x8C,0xDB,0xA4,0x65,0x06,0xAB,0x00, 0x4C,0x33,0xA9,0xFF,0x51,0x47,0x50,0x2C,
+    0xC8,0xED,0xA9,0xE7,0xA7,0x69,0xA1,0x26, 0x94,0x62,0x3C,0xEF,0x47,0xF0,0x23,0xED,
+};
+static uint8_t gost3410Curve512Ce[64] = {
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+};
+static uint8_t gost3410Curve512Cd[64] = {
+    0x9E,0x4F,0x5D,0x8C,0x01,0x7D,0x8D,0x9F, 0x13,0xA5,0xCF,0x3C,0xDF,0x5B,0xFE,0x4D,
+    0xAB,0x40,0x2D,0x54,0x19,0x8E,0x31,0xEB, 0xDE,0x28,0xA0,0x62,0x10,0x50,0x43,0x9C,
+    0xA6,0xB3,0x9E,0x0A,0x51,0x5C,0x06,0xB3, 0x04,0xE2,0xCE,0x43,0xE7,0x9E,0x36,0x9E,
+    0x91,0xA0,0xCF,0xC2,0xBC,0x2A,0x22,0xB4, 0xCA,0x30,0x2D,0xBB,0x33,0xEE,0x75,0x50,
+};
+static uint8_t gost3410Curve512Cu[64] = {
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,
+};
+static uint8_t gost3410Curve512Cv[64] = {
+    0x46,0x9A,0xF7,0x9D,0x1F,0xB1,0xF5,0xE1, 0x6B,0x99,0x59,0x2B,0x77,0xA0,0x1E,0x2A,
+    0x0F,0xDF,0xB0,0xD0,0x17,0x94,0x36,0x8D, 0x9A,0x56,0x11,0x7F,0x7B,0x38,0x66,0x95,
+    0x22,0xDD,0x4B,0x65,0x0C,0xF7,0x89,0xEE, 0xBF,0x06,0x8C,0x5D,0x13,0x97,0x32,0xF0,
+    0x90,0x56,0x22,0xC0,0x4B,0x2B,0xAA,0xE7, 0x60,0x03,0x03,0xEE,0x73,0x00,0x1A,0x3D,
+};
+// clang-format on
diff --git a/cyac/cmd/cer-verify/verifier-gost3410.c b/cyac/cmd/cer-verify/verifier-gost3410.c
new file mode 100644 (file)
index 0000000..9fe1ea6
--- /dev/null
@@ -0,0 +1,142 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#include <gcl.h>
+#pragma clang diagnostic pop
+
+#include "verifier-gost3410.h"
+
+#include "curves.c.in"
+
+static unsigned char *
+align16(unsigned char *p)
+{
+    unsigned int n = (uint64_t)p % 16;
+    if (n == 0) {
+        return p;
+    }
+    return p + (ptrdiff_t)(16 - n);
+}
+
+bool
+gost3410SignatureVerifier(
+    char **failReason,
+    const unsigned char *ai,
+    const size_t aiLen,
+    const unsigned char *sig,
+    const size_t sigLen,
+    const unsigned char *pub,
+    const size_t pubLen,
+    const unsigned char *data,
+    const size_t dataLen)
+{
+    const char *ai256A = "gost3410-256A";
+    const char *ai512C = "gost3410-512C";
+    size_t pointLen = 0;
+    bool is256 = false;
+    if ((aiLen == strlen(ai256A)) && (memcmp(ai, ai256A, aiLen) == 0)) {
+        is256 = true;
+        pointLen = 32;
+    } else if ((aiLen == strlen(ai512C)) && (memcmp(ai, ai512C, aiLen) == 0)) {
+        is256 = false;
+        pointLen = 64;
+    } else {
+        (*failReason) = "unknown ai";
+        return false;
+    }
+    if (pubLen != pointLen * 2) {
+        (*failReason) = "invalid pubkey len";
+        return false;
+    }
+    if (sigLen != pointLen * 2) {
+        (*failReason) = "invalid signature len";
+        return false;
+    }
+    unsigned char hsh[64] = {0};
+    int gcl3rc = GCL_RC_FAILED;
+    {
+        unsigned char ctx[GCL_GOSTR34112012_CTX_SIZE] = {0};
+        GclGostR34112012Ctx *h = NULL;
+        if (is256) {
+            h = gcl_gostr34112012_ctx256_init_mem(
+                (GclGostR34112012Ctx *)align16(ctx), &gcl3rc);
+        } else {
+            h = gcl_gostr34112012_ctx512_init_mem(
+                (GclGostR34112012Ctx *)align16(ctx), &gcl3rc);
+        }
+        if (gcl3rc != GCL_RC_OK) {
+            (*failReason) = "gcl_gostr34112012_ctxX_init_mem failed";
+            return false;
+        }
+        gcl3rc = gcl_gostr34112012_hash_update(h, data, dataLen);
+        if (gcl3rc != GCL_RC_OK) {
+            (*failReason) = "gcl_gostr34112012_hash_update failed";
+            return false;
+        }
+        if (is256) {
+            gcl3rc = gcl_gostr34112012_hash256_finalize(h, hsh);
+        } else {
+            gcl3rc = gcl_gostr34112012_hash512_finalize(h, hsh);
+        }
+        gcl_gostr34112012_ctx_clean(h);
+        if (gcl3rc != GCL_RC_OK) {
+            (*failReason) = "gcl_gostr34112012_hashX_finalize failed";
+            return false;
+        }
+    }
+    {
+        unsigned char ctx[GCL_GOSTR3410_CTX_SIZE] = {0};
+        if (is256) {
+            gcl_edwards_ctx_init_mem_varsize(
+                (GclGostR3410Ctx *)ctx,
+                gost3410Curve256Ap,
+                gost3410Curve256Aq,
+                gost3410Curve256Ae,
+                gost3410Curve256Ad,
+                gost3410Curve256Au,
+                gost3410Curve256Av,
+                256,
+                &gcl3rc);
+        } else {
+            gcl_edwards_ctx_init_mem_varsize(
+                (GclGostR3410Ctx *)ctx,
+                gost3410Curve512Cp,
+                gost3410Curve512Cq,
+                gost3410Curve512Ce,
+                gost3410Curve512Cd,
+                gost3410Curve512Cu,
+                gost3410Curve512Cv,
+                512,
+                &gcl3rc);
+        }
+        if (gcl3rc != GCL_RC_OK) {
+            (*failReason) = "gcl_edwards_ctx_init_mem_varsize failed";
+            return false;
+        }
+        gcl3rc = gcl_gostr3410_ctx_set_public_key_varsize(
+            (GclGostR3410Ctx *)ctx, pub, pub + pointLen, pointLen * 8);
+        if (gcl3rc != GCL_RC_OK) {
+            gcl_gostr3410_ctx_clean((GclGostR3410Ctx *)ctx);
+            (*failReason) = "gcl_gostr3410_ctx_set_public_key_varsize failed";
+            return false;
+        }
+        gcl3rc = gcl_gostr3410_verify_varsize(
+            (GclGostR3410Ctx *)ctx, hsh, pointLen, sig, pointLen * 2);
+        gcl_gostr3410_ctx_clean((GclGostR3410Ctx *)ctx);
+        switch (gcl3rc) {
+        case GCL_RC_OK:
+            return true;
+        case GCL_RC_ECINVALID:
+            (*failReason) = "invalid signature";
+            break;
+        default:
+            (*failReason) = "gcl_gostr3410_ctx_set_public_key_varsize failed";
+        }
+    }
+    return false;
+}
diff --git a/cyac/cmd/cer-verify/verifier-gost3410.h b/cyac/cmd/cer-verify/verifier-gost3410.h
new file mode 100644 (file)
index 0000000..af6ddd6
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef YAC_VERIFIER_GOST3410_H
+#define YAC_VERIFIER_GOST3410_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+gost3410SignatureVerifier(
+    char **failReason,
+    const unsigned char *ai,
+    const size_t aiLen,
+    const unsigned char *sig,
+    const size_t sigLen,
+    const unsigned char *pub,
+    const size_t pubLen,
+    const unsigned char *data,
+    const size_t dataLen);
+
+#endif // YAC_VERIFIER_GOST3410_H
diff --git a/cyac/cmd/cer-verify/verifier-gost3410.o.do b/cyac/cmd/cer-verify/verifier-gost3410.o.do
new file mode 100644 (file)
index 0000000..57c637c
--- /dev/null
@@ -0,0 +1,5 @@
+redo-ifchange ${1%.o}.c conf/gcl3.rc ../../conf/cc ../../conf/cflags
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+. conf/gcl3.rc
+$CC $CFLAGS $GCL3_CFLAGS -c -o $3 ${1%.o}.c
index defcb85251b0380ce9310c92a2a845e7a1d77cb4048e5fd1767ab38eb239d6f4..c0a83028d2afe9291d0086c52d3dcb0438463afc9287557e9599e3de97a393c3 100755 (executable)
@@ -1,3 +1,7 @@
 #!/bin/sh -e
 
-exec rm -f print-items print-itered test-vector
+( cd cer-verify ; ./clean )
+( cd lib ; ./clean )
+( cd print-items ; ./clean )
+( cd print-itered ; ./clean )
+( cd test-vector ; ./clean )
diff --git a/cyac/cmd/default.do b/cyac/cmd/default.do
deleted file mode 100644 (file)
index 2b6e469..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-redo-ifchange $2.c ../conf/cc ../conf/cflags ../conf/ldflags ../conf/prefix
-read CC <../conf/cc
-CFLAGS=$(cat ../conf/cflags)
-LDFLAGS=$(cat ../conf/ldflags)
-read PREFIX <../conf/prefix
-$CC $CFLAGS -I$PREFIX/include -o $3 $2.c $LDFLAGS -L$PREFIX/lib -lyac -lm
diff --git a/cyac/cmd/lib/clean b/cyac/cmd/lib/clean
new file mode 100755 (executable)
index 0000000..f973ebd
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f *.o
diff --git a/cyac/cmd/lib/default.o.do b/cyac/cmd/lib/default.o.do
new file mode 100644 (file)
index 0000000..ac567c2
--- /dev/null
@@ -0,0 +1,4 @@
+redo-ifchange $2.c ../../conf/cc ../../conf/cflags
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+$CC $CFLAGS -c -o $3 $2.c
similarity index 91%
rename from cyac/cmd/hex.c.in
rename to cyac/cmd/lib/hex.c
index b941ccf568e6625c0678415e122a97f98746733d6a793a9b15beb967961da0c0..25c1a3c415cd51d6d6e12f3f28972c3e5299e0fae60bf593afb347cb62430904 100644 (file)
@@ -1,10 +1,10 @@
 #include <stdlib.h>
 
-static const size_t maxStrLen = 40;
+#include "hex.h"
 
 static const char hexdigits[] = "0123456789ABCDEF";
 
-static char *
+char *
 HexEnc(const unsigned char *src, const size_t srcLen)
 {
     // it was based on libressl/crypto/x509v3/v3_utl.c:hex_to_string
diff --git a/cyac/cmd/lib/hex.h b/cyac/cmd/lib/hex.h
new file mode 100644 (file)
index 0000000..a5f956a
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef YAC_HEX_H
+#define YAC_HEX_H
+
+#include <stdlib.h>
+
+char *
+HexEnc(const unsigned char *src, const size_t srcLen);
+
+#endif // YAC_HEX_H
diff --git a/cyac/cmd/lib/mmap.c b/cyac/cmd/lib/mmap.c
new file mode 100644 (file)
index 0000000..9a0c8ce
--- /dev/null
@@ -0,0 +1,26 @@
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "mmap.h"
+
+bool
+Mmap(unsigned char **buf, size_t *len, const char *path)
+{
+    int fd = open(path, O_RDONLY | O_CLOEXEC);
+    if (fd == -1) {
+        return false;
+    }
+    struct stat sb;
+    memset(&sb, 0, sizeof(struct stat));
+    if (fstat(fd, &sb) != 0) {
+        return false;
+    }
+    (*len) = (size_t)sb.st_size;
+    (*buf) = mmap(NULL, *len, PROT_READ, MAP_SHARED, fd, 0);
+    return true;
+}
diff --git a/cyac/cmd/lib/mmap.h b/cyac/cmd/lib/mmap.h
new file mode 100644 (file)
index 0000000..e5416b8
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef YAC_MMAP_H
+#define YAC_MMAP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+Mmap(unsigned char **buf, size_t *len, const char *path);
+
+#endif // YAC_MMAP_H
diff --git a/cyac/cmd/lib/uuid.c b/cyac/cmd/lib/uuid.c
new file mode 100644 (file)
index 0000000..421c9dd
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+#include "uuid.h"
+
+void
+UUIDPrint(const unsigned char *buf)
+{
+    fprintf(
+        stdout,
+        "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+        buf[0],
+        buf[1],
+        buf[2],
+        buf[3],
+        buf[4],
+        buf[5],
+        buf[6],
+        buf[7],
+        buf[8],
+        buf[9],
+        buf[10],
+        buf[11],
+        buf[12],
+        buf[13],
+        buf[14],
+        buf[15]);
+}
diff --git a/cyac/cmd/lib/uuid.h b/cyac/cmd/lib/uuid.h
new file mode 100644 (file)
index 0000000..fbe31c3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef YAC_UUID_H
+#define YAC_UUID_H
+
+void
+UUIDPrint(const unsigned char *buf);
+
+#endif // YAC_UUID_H
diff --git a/cyac/cmd/print-items/.gitignore b/cyac/cmd/print-items/.gitignore
new file mode 100644 (file)
index 0000000..043dac5
--- /dev/null
@@ -0,0 +1 @@
+/print-items
diff --git a/cyac/cmd/print-items/all.do b/cyac/cmd/print-items/all.do
new file mode 100644 (file)
index 0000000..a28095f
--- /dev/null
@@ -0,0 +1 @@
+redo-ifchange print-items
diff --git a/cyac/cmd/print-items/clean b/cyac/cmd/print-items/clean
new file mode 100755 (executable)
index 0000000..c8ef676
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f print-items
similarity index 86%
rename from cyac/cmd/print-items.c
rename to cyac/cmd/print-items/print-items.c
index 38b415027f2b02eaea116272a68a29df7523eadecc0a23cec13386cffee2ac99..c0cf449cc45e0953705b6f5f82056163dd58ac8793e7f3f46635ca96b0ba3f1d 100644 (file)
 
 #include <assert.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <math.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 #include <sys/time.h>
 #include <time.h>
 
 #include <yac/err.h>
 #include <yac/items.h>
 
-#include "hex.c.in"
+#include "../lib/hex.h"
+#include "../lib/mmap.h"
+#include "../lib/uuid.h"
+
+static const size_t maxStrLen = 40;
 
 static const char *ColourRed = "\x1b[31m";
 static const char *ColourGreen = "\x1b[32m";
@@ -100,24 +101,8 @@ printer(
         fputs("TRUE\n", stdout);
         break;
     case YACItemUUID:
-        printf(
-            "UUID(%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
-            item->atom.val.buf[0],
-            item->atom.val.buf[1],
-            item->atom.val.buf[2],
-            item->atom.val.buf[3],
-            item->atom.val.buf[4],
-            item->atom.val.buf[5],
-            item->atom.val.buf[6],
-            item->atom.val.buf[7],
-            item->atom.val.buf[8],
-            item->atom.val.buf[9],
-            item->atom.val.buf[10],
-            item->atom.val.buf[11],
-            item->atom.val.buf[12],
-            item->atom.val.buf[13],
-            item->atom.val.buf[14],
-            item->atom.val.buf[15]);
+        UUIDPrint(item->atom.val.buf);
+        fputs("\n", stdout);
         break;
     case YACItemUint:
         fprintf(stdout, "%zu\n", item->atom.val.uint);
@@ -288,20 +273,9 @@ main(int argc, char **argv)
 {
     size_t len = 0;
     unsigned char *buf = NULL;
-    {
-        int fd = open(argv[1], O_RDONLY | O_CLOEXEC);
-        if (fd == -1) {
-            fprintf(stderr, "%s\n", strerror(errno));
-            return EXIT_FAILURE;
-        }
-        struct stat sb;
-        memset(&sb, 0, sizeof(struct stat));
-        if (fstat(fd, &sb) != 0) {
-            fprintf(stderr, "%s\n", strerror(errno));
-            return EXIT_FAILURE;
-        }
-        len = (size_t)sb.st_size;
-        buf = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    if (!Mmap(&buf, &len, argv[1])) {
+        fprintf(stderr, "%s\n", strerror(errno));
+        exit(EXIT_FAILURE);
     }
 
     NoColour = getenv("NO_COLOR") != NULL;
@@ -314,14 +288,13 @@ main(int argc, char **argv)
     ptrdiff_t off = 0;
     enum YACErr err = YACItemsParse(&items, &off, buf, len);
     if (err != YACErrNo) {
-        fprintf(stderr, "err: %d\n", err);
+        fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
     err = printer(&items, 0, 0, -1, NULL);
     if (err != YACErrNo) {
-        fprintf(stderr, "err: %d\n", err);
+        fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
-
     return EXIT_SUCCESS;
 }
diff --git a/cyac/cmd/print-items/print-items.do b/cyac/cmd/print-items/print-items.do
new file mode 100644 (file)
index 0000000..c735e34
--- /dev/null
@@ -0,0 +1,8 @@
+deps="../lib/hex.o ../lib/mmap.o ../lib/uuid.o"
+redo-ifchange $1.c $deps \
+    ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+LDFLAGS=$(cat ../../conf/ldflags)
+read PREFIX <../../conf/prefix
+$CC $CFLAGS -I$PREFIX/include -o $3 $2.c $deps $LDFLAGS -L$PREFIX/lib -lyac -lm
diff --git a/cyac/cmd/print-itered/.gitignore b/cyac/cmd/print-itered/.gitignore
new file mode 100644 (file)
index 0000000..e918769
--- /dev/null
@@ -0,0 +1 @@
+/print-itered
diff --git a/cyac/cmd/print-itered/all.do b/cyac/cmd/print-itered/all.do
new file mode 100644 (file)
index 0000000..ec62894
--- /dev/null
@@ -0,0 +1 @@
+redo-ifchange print-itered
diff --git a/cyac/cmd/print-itered/clean b/cyac/cmd/print-itered/clean
new file mode 100755 (executable)
index 0000000..1556146
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f print-itered
similarity index 82%
rename from cyac/cmd/print-itered.c
rename to cyac/cmd/print-itered/print-itered.c
index f8a52d7a37525cb06b7ce5ee8ffd68c00801e575194db016fe987d98d2a494d7..1a933d8863d858bda9942eb934c0b83056cfe51fd037ff588cb7f93a3931e594 100644 (file)
 
 #include <assert.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 #include <sys/time.h>
 #include <time.h>
 
 #include <yac/err.h>
 #include <yac/iter.h>
 
-#include "hex.c.in"
+#include "../lib/hex.h"
+#include "../lib/mmap.h"
+#include "../lib/uuid.h"
+
+static const size_t maxStrLen = 40;
 
 struct CbState {
     ptrdiff_t indent;
@@ -78,24 +79,8 @@ myCb(
         fputs("TRUE\n", stdout);
         break;
     case YACItemUUID:
-        printf(
-            "UUID(%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
-            atom->val.buf[0],
-            atom->val.buf[1],
-            atom->val.buf[2],
-            atom->val.buf[3],
-            atom->val.buf[4],
-            atom->val.buf[5],
-            atom->val.buf[6],
-            atom->val.buf[7],
-            atom->val.buf[8],
-            atom->val.buf[9],
-            atom->val.buf[10],
-            atom->val.buf[11],
-            atom->val.buf[12],
-            atom->val.buf[13],
-            atom->val.buf[14],
-            atom->val.buf[15]);
+        UUIDPrint(atom->val.buf);
+        fputs("\n", stdout);
         break;
     case YACItemUint:
         fprintf(stdout, "%zu\n", atom->val.uint);
@@ -207,34 +192,23 @@ main(int argc, char **argv)
 {
     size_t len = 0;
     unsigned char *buf = NULL;
-    {
-        int fd = open(argv[1], O_RDONLY | O_CLOEXEC);
-        if (fd == -1) {
-            fprintf(stderr, "%s\n", strerror(errno));
-            return EXIT_FAILURE;
-        }
-        struct stat sb;
-        memset(&sb, 0, sizeof(struct stat));
-        if (fstat(fd, &sb) != 0) {
-            fprintf(stderr, "%s\n", strerror(errno));
-            return EXIT_FAILURE;
-        }
-        len = (size_t)sb.st_size;
-        buf = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    if (!Mmap(&buf, &len, argv[1])) {
+        fprintf(stderr, "%s\n", strerror(errno));
+        exit(EXIT_FAILURE);
     }
     struct YACAtom atom;
     memset(&atom, 0, sizeof(struct YACAtom));
     ptrdiff_t off = 0;
     enum YACErr err = YACAtomDecode(&atom, buf, len);
     if (err != YACErrNo) {
-        fprintf(stderr, "err: %d\n", err);
+        fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
     off += atom.off;
     struct CbState cbState = {.indent = 0};
     err = myCb(NULL, 0, -1, &cbState, &atom, &off, buf, len);
     if (err != YACErrNo) {
-        fprintf(stderr, "err: %d\n", err);
+        fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
     assert(cbState.indent == 0);
diff --git a/cyac/cmd/print-itered/print-itered.do b/cyac/cmd/print-itered/print-itered.do
new file mode 100644 (file)
index 0000000..3fdc613
--- /dev/null
@@ -0,0 +1,8 @@
+deps="../lib/hex.o ../lib/mmap.o ../lib/uuid.o"
+redo-ifchange $1.c $deps \
+    ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+LDFLAGS=$(cat ../../conf/ldflags)
+read PREFIX <../../conf/prefix
+$CC $CFLAGS -I$PREFIX/include -o $3 $2.c $deps $LDFLAGS -L$PREFIX/lib -lyac
diff --git a/cyac/cmd/test-vector/.gitignore b/cyac/cmd/test-vector/.gitignore
new file mode 100644 (file)
index 0000000..349f06b
--- /dev/null
@@ -0,0 +1 @@
+/test-vector
diff --git a/cyac/cmd/test-vector/all.do b/cyac/cmd/test-vector/all.do
new file mode 100644 (file)
index 0000000..7d70447
--- /dev/null
@@ -0,0 +1 @@
+redo-ifchange test-vector
diff --git a/cyac/cmd/test-vector/clean b/cyac/cmd/test-vector/clean
new file mode 100755 (executable)
index 0000000..a309a96
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f test-vector
similarity index 93%
rename from cyac/cmd/test-vector.c
rename to cyac/cmd/test-vector/test-vector.c
index c341b84d3b36e647a7a40b0a17ac6eb8a1a9094f9245fec588ed6a99d88e9fc7..c30329eb0d8da0670298cb1fd136de4f3eda4fe109a4109aedaf23067e087597 100644 (file)
@@ -168,6 +168,16 @@ main(int argc, char **argv)
         YACTimevalToTAI64(tai, &tv);
         adder(&off, YACAtomTAI64Encode(buf + off, len - off, tai, 12));
 
+        adder(
+            &off,
+            YACAtomRawEncode(
+                buf + off,
+                len - off,
+                YACAtomTAI64N,
+                (const unsigned char
+                     *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55",
+                12));
+
         adder(
             &off,
             YACAtomRawEncode(
@@ -175,7 +185,7 @@ main(int argc, char **argv)
                 len - off,
                 YACAtomTAI64NA,
                 (const unsigned char
-                     *)"\x40\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99",
+                     *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55\x07\x5B\xCD\x15",
                 16));
     }
     adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .dates
@@ -206,6 +216,14 @@ main(int argc, char **argv)
     adder(&off, YACAtomBinEncode(buf + off, len - off, NULL, 0));
     memset(bin, '\x00', 16);
     adder(&off, YACAtomUUIDEncode(buf + off, len - off, bin));
+    adder(
+        &off,
+        YACAtomRawEncode(
+            buf + off,
+            len - off,
+            YACAtomTAI64,
+            (const unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00",
+            8));
     adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .empties
 
     adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .
diff --git a/cyac/cmd/test-vector/test-vector.do b/cyac/cmd/test-vector/test-vector.do
new file mode 100644 (file)
index 0000000..28cdd53
--- /dev/null
@@ -0,0 +1,6 @@
+redo-ifchange $1.c ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+LDFLAGS=$(cat ../../conf/ldflags)
+read PREFIX <../../conf/prefix
+$CC $CFLAGS -I$PREFIX/include -o $3 $2.c $LDFLAGS -L$PREFIX/lib -lyac
diff --git a/cyac/default.o.do b/cyac/default.o.do
deleted file mode 100644 (file)
index fe9918a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-redo-ifchange $2.c $(./h-extract.pl $2.[ch]) conf/cc conf/cflags
-read CC <conf/cc
-CFLAGS=$(cat conf/cflags)
-$CC $CFLAGS -c -o $3 $2.c
diff --git a/cyac/lib/.gitignore b/cyac/lib/.gitignore
new file mode 100644 (file)
index 0000000..a0169a4
--- /dev/null
@@ -0,0 +1,3 @@
+/*.o
+/compile_flags.txt
+/libyac.a
similarity index 100%
rename from cyac/atoms.h
rename to cyac/lib/atoms.h
similarity index 70%
rename from cyac/clean
rename to cyac/lib/clean
index 593bb0ee48522fc63c5a7151e5748e31f65a585fb9c17b4e8d748cb3a5a9f45e..99988a48ca8bf2400b5b1aadfd7fc55e3839ea71ed46edd954c9d99ea56fc03d 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/sh -e
 
-( cd cmd ; ./clean )
+( cd pki ; ./clean )
 exec rm -f *.o *.a compile_flags.txt
similarity index 100%
rename from cyac/dec.c
rename to cyac/lib/dec.c
similarity index 100%
rename from cyac/dec.h
rename to cyac/lib/dec.h
similarity index 100%
rename from cyac/dectai.c
rename to cyac/lib/dectai.c
similarity index 100%
rename from cyac/dectai.h
rename to cyac/lib/dectai.h
diff --git a/cyac/lib/default.o.do b/cyac/lib/default.o.do
new file mode 100644 (file)
index 0000000..071b004
--- /dev/null
@@ -0,0 +1,7 @@
+deps="../conf/cc ../conf/cflags"
+dir=$(dirname $1)
+for dep in $(./h-extract.pl $2.[ch]) ; do deps="$deps $dir/$dep"; done
+redo-ifchange $deps
+read CC <../conf/cc
+CFLAGS=$(cat ../conf/cflags)
+$CC $CFLAGS -c -o $3 $2.c
similarity index 100%
rename from cyac/enc.c
rename to cyac/lib/enc.c
similarity index 100%
rename from cyac/enc.h
rename to cyac/lib/enc.h
similarity index 100%
rename from cyac/enctai.c
rename to cyac/lib/enctai.c
similarity index 100%
rename from cyac/enctai.h
rename to cyac/lib/enctai.h
diff --git a/cyac/lib/err.c b/cyac/lib/err.c
new file mode 100644 (file)
index 0000000..0967b34
--- /dev/null
@@ -0,0 +1,50 @@
+#include "err.h"
+
+const char *
+YACErr2Str(const enum YACErr err)
+{
+    switch (err) {
+    case YACErrInvalid:
+        return "Invalid";
+    case YACErrNo:
+        return "No";
+    case YACErrNotEnough:
+        return "NotEnough";
+    case YACErrUnknownType:
+        return "UnknownType";
+    case YACErrLenNonMinimal:
+        return "LenNonMinimal";
+    case YACErrLenTooBig:
+        return "LenTooBig";
+    case YACErrBadUTF8:
+        return "BadUTF8";
+    case YACErrIntZeroByte:
+        return "IntZeroByte";
+    case YACErrIntNonMinimal:
+        return "IntNonMinimal";
+    case YACErrBlobBadLen:
+        return "BlobBadLen";
+    case YACErrBlobBadAtom:
+        return "BlobBadAtom";
+    case YACErrBlobBadTerm:
+        return "BlobBadTerm";
+    case YACErrTAI64TooBig:
+        return "TAI64TooBig";
+    case YACErrTAI64BadNsec:
+        return "TAI64BadNsec";
+    case YACErrTAI64BadAsec:
+        return "TAI64BadAsec";
+    case YACErrMapBadKey:
+        return "MapBadKey";
+    case YACErrMapNoVal:
+        return "MapNoVal";
+    case YACErrMapUnordered:
+        return "MapUnordered";
+    case YACErrNoMem:
+        return "NoMem";
+    case YACErrUnsatisfiedSchema:
+        return "UnsatisfiedSchema";
+    default:
+        return "unknown";
+    }
+}
similarity index 92%
rename from cyac/err.h
rename to cyac/lib/err.h
index edeb2765f2a4c0f5724e7f225a178fa7e77195602841f315c650770d888421d7..e940f11b22b200cc02d84196d844d3206a87a4a754bd2d126e7464382de04a3d 100644 (file)
@@ -39,6 +39,8 @@
 //     Unordered map keys.
 // @item YACErrNoMem
 //     Not enough memory for allocation.
+// @item YACErrUnsatisfiedSchema
+//     Unsatisfied structure's schema.
 // @end table
 // @end deftypevar
 enum YACErr {
@@ -61,6 +63,10 @@ enum YACErr {
     YACErrMapNoVal,
     YACErrMapUnordered,
     YACErrNoMem,
+    YACErrUnsatisfiedSchema,
 };
 
+const char *
+YACErr2Str(const enum YACErr);
+
 #endif // YAC_ERR_H
similarity index 100%
rename from cyac/frombe.c
rename to cyac/lib/frombe.c
similarity index 100%
rename from cyac/frombe.h
rename to cyac/lib/frombe.h
similarity index 64%
rename from cyac/h-extract.pl
rename to cyac/lib/h-extract.pl
index 52c770cd79b9f01e3115b23672e9c76ed7bab39fc2b12b723bedcb7e876c978b..7cb1d44b5f31d98d56229e79dd06e81be017fa966189f5be7ce37470112f4515 100755 (executable)
@@ -4,8 +4,10 @@
 # hack, to badly exit if there is unexistent file
 $SIG{__WARN__} = sub { die @_ };
 
-map { $inc{$_} = 1 } @ARGV;
+use File::Basename;
+
+map { $inc{basename($_)} = 1 } @ARGV;
 while (<>) {
-    /^#include "([^\/]+)"$/ and ($1 !~ /\.in$/) and $inc{$1} = 1;
+    /^#include "(.+)"$/ and ($1 !~ /\.in$/) and $inc{$1} = 1;
 };
 print join " ", sort keys %inc;
similarity index 68%
rename from cyac/install.do
rename to cyac/lib/install.do
index b5dc6fae5844ca99eecaaab199c3c06f4ed89d117f26a4dfc332cf047fecea54..c2d5470af05e9dbe70c7375372d2220311592ed78854be0c3a535bde35af8893 100644 (file)
@@ -1,5 +1,5 @@
-redo-ifchange *.h libyac.a conf/prefix
-read PREFIX <conf/prefix
+redo-ifchange *.h libyac.a ../conf/prefix
+read PREFIX <../conf/prefix
 mkdir -p $PREFIX/include/yac $PREFIX/lib
 cp -f *.h $PREFIX/include/yac
 cp -f libyac.a $PREFIX/lib
similarity index 58%
rename from cyac/items.c
rename to cyac/lib/items.c
index b2ddfd997871cabe155ca004c377e0cc1a710cfd4df86879f6b0306c467cc49a..67a811173d55db535796b0744b2acc5d6def267a6ba43715049c6ba0707d975b 100644 (file)
@@ -19,6 +19,7 @@
 #include <string.h>
 
 #include "dec.h"
+#include "enc.h"
 #include "err.h"
 #include "items.h"
 
@@ -263,3 +264,202 @@ YACItemsParse(
     }
     return YACErrNo;
 }
+
+ptrdiff_t
+YACItemsEncode(
+    struct YACItems *items,
+    ptrdiff_t idx,
+    ptrdiff_t *off,
+    unsigned char *buf,
+    const size_t cap)
+{
+    struct YACItem *item = &(items->list[idx]);
+    ptrdiff_t diff = 0;
+    switch (item->atom.typ) {
+    case YACItemEOC:
+        return -1;
+    case YACItemNIL:
+        diff = YACAtomNILEncode(buf + *off, cap - (size_t)(*off));
+        break;
+    case YACItemFalse:
+        diff = YACAtomBoolEncode(buf + *off, cap - (size_t)(*off), false);
+        break;
+    case YACItemTrue:
+        diff = YACAtomBoolEncode(buf + *off, cap - (size_t)(*off), true);
+        break;
+    case YACItemUUID:
+        diff = YACAtomUUIDEncode(buf + *off, cap - (size_t)(*off), item->atom.val.buf);
+        break;
+    case YACItemUint:
+        diff = YACAtomUintEncode(buf + *off, cap - (size_t)(*off), item->atom.val.uint);
+        break;
+    case YACItemSint:
+        diff = YACAtomSintEncode(buf + *off, cap - (size_t)(*off), item->atom.val.sint);
+        break;
+    case YACItemList:
+        diff = YACAtomListEncode(buf + *off, cap - (size_t)(*off));
+        if (diff < 0) {
+            return diff;
+        }
+        (*off) += diff;
+        idx = item->atom.val.first;
+        while (idx != -1) {
+            diff = YACItemsEncode(items, idx, off, buf, cap);
+            if (diff < 0) {
+                return diff;
+            }
+            idx = items->list[idx].next;
+        }
+        diff = YACAtomEOCEncode(buf + *off, cap - (size_t)(*off));
+        break;
+    case YACItemMap:
+        diff = YACAtomMapEncode(buf + *off, cap - (size_t)(*off));
+        if (diff < 0) {
+            return diff;
+        }
+        (*off) += diff;
+        idx = item->atom.val.first;
+        while (idx != -1) {
+            diff = YACItemsEncode(items, idx, off, buf, cap);
+            if (diff < 0) {
+                return diff;
+            }
+            idx = items->list[idx].next;
+        }
+        diff = YACAtomEOCEncode(buf + *off, cap - (size_t)(*off));
+        break;
+    case YACItemBlob: {
+        size_t chunkLen = item->atom.val.uint;
+        diff = YACAtomBlobEncode(buf + *off, cap - (size_t)(*off), item->atom.val.uint);
+        if (diff < 0) {
+            return diff;
+        }
+        (*off) += diff;
+        for (;;) {
+            idx++;
+            item = &(items->list[idx]);
+            if (item->atom.len != chunkLen) {
+                break;
+            }
+            diff = YACAtomChunkEncode(
+                buf + *off, cap - (size_t)(*off), item->atom.val.buf, item->atom.len);
+            if (diff < 0) {
+                return diff;
+            }
+            (*off) += diff;
+            continue;
+        }
+        diff = YACAtomBinEncode(
+            buf + *off, cap - (size_t)(*off), item->atom.val.buf, item->atom.len);
+        break;
+    }
+    case YACItemFloat:
+        return -1;
+    case YACItemTAI64:
+        diff = YACAtomTAI64Encode(
+            buf + *off, cap - (size_t)(*off), item->atom.val.buf, item->atom.len);
+        break;
+    case YACItemBin:
+        diff = YACAtomBinEncode(
+            buf + *off, cap - (size_t)(*off), item->atom.val.buf, item->atom.len);
+        break;
+    case YACItemStr:
+        diff = YACAtomStrEncode(
+            buf + *off, cap - (size_t)(*off), item->atom.val.buf, item->atom.len);
+        break;
+    case YACItemRaw:
+        diff = YACAtomRawEncode(
+            buf + *off,
+            cap - (size_t)(*off),
+            item->atom.tag,
+            item->atom.val.buf,
+            item->atom.len);
+        break;
+    default:
+        return -1;
+    }
+    if (diff < 0) {
+        return diff;
+    }
+    (*off) += diff;
+    return 0;
+}
+
+ptrdiff_t
+YACItemsGetByKeyLen(
+    struct YACItems *items,
+    const ptrdiff_t itemIdx,
+    const char *key,
+    const size_t keyLen)
+{
+    struct YACItem *item = &(items->list[itemIdx]);
+    if (item->atom.typ != YACItemMap) {
+        return -1;
+    }
+    ptrdiff_t idx = item->atom.val.first;
+    while (idx != -1) {
+        if ((items->list[idx].atom.len == keyLen) &&
+            (memcmp(items->list[idx].atom.val.buf, key, keyLen) == 0)) {
+            return idx + 1;
+        }
+        idx = items->list[idx].next;
+        idx = items->list[idx].next;
+    }
+    return -1;
+}
+
+ptrdiff_t
+YACItemsGetByKey(struct YACItems *items, const ptrdiff_t itemIdx, const char *key)
+{
+    return YACItemsGetByKeyLen(items, itemIdx, key, strlen(key));
+}
+
+ptrdiff_t
+YACItemsGetByKeyAndType(
+    struct YACItems *items,
+    const ptrdiff_t itemIdx,
+    const char *key,
+    const enum YACItemType typ)
+{
+    ptrdiff_t idx = YACItemsGetByKey(items, itemIdx, key);
+    if (idx == -1) {
+        return -1;
+    }
+    if (items->list[idx].atom.typ != typ) {
+        return -1;
+    }
+    return idx;
+}
+
+bool
+YACStrEqual(struct YACAtom *atom, const char *s)
+{
+    return (atom->len == strlen(s)) && (memcmp(atom->val.buf, s, atom->len) == 0);
+}
+
+bool
+YACListHasOnlyType(struct YACItems *items, ptrdiff_t idx, const enum YACItemType typ)
+{
+    idx = items->list[idx].atom.val.first;
+    while (idx != -1) {
+        if (items->list[idx].atom.typ != typ) {
+            return false;
+        }
+        idx = items->list[idx].next;
+    }
+    return true;
+}
+
+bool
+YACMapHasOnlyType(struct YACItems *items, ptrdiff_t idx, const enum YACItemType typ)
+{
+    idx = items->list[idx].atom.val.first;
+    while (idx != -1) {
+        idx = items->list[idx].next;
+        if (items->list[idx].atom.typ != typ) {
+            return false;
+        }
+        idx = items->list[idx].next;
+    }
+    return true;
+}
similarity index 62%
rename from cyac/items.h
rename to cyac/lib/items.h
index 18c26d8c6e21ae08a087412a5a99963afbf3017718b1933e96e78daedbcd9d2b..ae5de440901920b2abeabefaa06914d7f8a7597dec5f6bc1463dd28db310804c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef YAC_POOL_H
 #define YAC_POOL_H
 
+#include <stdbool.h>
 #include <stddef.h>
 
 #include "dec.h"
 //
 // Remember that @code{.next} of the list/map/blob is the (possible)
 // element after the whole list/map/blob. @code{.atom.val.first} is the
-// (possible) first element inside those containers.
+// (possible) first element inside map/list.
+//
+// Blob's first element always present and it is the next binary string
+// item, until its length is less than chunk len.
 // @end deftypevar
 struct YACItem {
     ptrdiff_t next;
@@ -51,4 +55,38 @@ YACItemsParse(
     const unsigned char *buf,
     const size_t len);
 
+ptrdiff_t
+YACItemsEncode(
+    struct YACItems *,
+    ptrdiff_t idx,
+    ptrdiff_t *off,
+    unsigned char *buf,
+    const size_t cap);
+
+ptrdiff_t
+YACItemsGetByKeyLen(
+    struct YACItems *,
+    const ptrdiff_t itemIdx,
+    const char *key,
+    const size_t keyLen);
+
+ptrdiff_t
+YACItemsGetByKey(struct YACItems *, const ptrdiff_t itemIdx, const char *key);
+
+ptrdiff_t
+YACItemsGetByKeyAndType(
+    struct YACItems *,
+    const ptrdiff_t itemIdx,
+    const char *key,
+    const enum YACItemType typ);
+
+bool
+YACStrEqual(struct YACAtom *, const char *s);
+
+bool
+YACListHasOnlyType(struct YACItems *, ptrdiff_t idx, const enum YACItemType typ);
+
+bool
+YACMapHasOnlyType(struct YACItems *, ptrdiff_t idx, const enum YACItemType typ);
+
 #endif // YAC_POOL_H
similarity index 93%
rename from cyac/iter.c
rename to cyac/lib/iter.c
index 17ce6a614bfc799ebcc1a4ea5f4fcb1464ae4dbe35d651c5e2d368fbdca278df..c7c2b5e873f55163d3965558256ff756aad9a365e0792a97a6a46d6fba8aafa8 100644 (file)
@@ -33,7 +33,7 @@ YACIterList(
     enum YACErr err = YACErrInvalid;
     bool eoc = false;
     for (size_t n = 0;; n++) {
-        err = YACAtomDecode(atom, buf + *off, (size_t)((ptrdiff_t)len - *off));
+        err = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
         if (err != YACErrNo) {
             return err;
         }
@@ -63,7 +63,7 @@ YACIterMap(
     size_t keyLen = 0;
     enum YACErr err = YACErrInvalid;
     for (;;) {
-        err = YACAtomDecode(atom, buf + *off, (size_t)((ptrdiff_t)len - *off));
+        err = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
         if (err != YACErrNo) {
             return err;
         }
@@ -89,7 +89,7 @@ YACIterMap(
         }
         keyLen = atom->len;
         key = atom->val.buf;
-        err = YACAtomDecode(atom, buf + *off, (size_t)((ptrdiff_t)len - *off));
+        err = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
         if (err != YACErrNo) {
             return err;
         }
@@ -118,7 +118,7 @@ YACIterBlob(
     enum YACErr err = YACErrInvalid;
     bool eoc = false;
     for (size_t n = 0; !eoc; n++) {
-        err = YACAtomDecode(atom, buf + *off, (size_t)((ptrdiff_t)len - *off));
+        err = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
         if (err != YACErrNo) {
             return err;
         }
similarity index 100%
rename from cyac/iter.h
rename to cyac/lib/iter.h
similarity index 100%
rename from cyac/leapsecs.c
rename to cyac/lib/leapsecs.c
similarity index 100%
rename from cyac/leapsecs.h
rename to cyac/lib/leapsecs.h
similarity index 58%
rename from cyac/libyac.a.do
rename to cyac/lib/libyac.a.do
index 8068afab7f7960ecc99b738281aaa7ca90b193cbc6aa1e4f8f2f680d95119d2e..0d627bd4a1f5732f036a07222046f71be6c54bd5045cdbaa6b2323a1a2769851 100644 (file)
@@ -1,6 +1,6 @@
 redo-ifchange o.list
 objs=$(cat o.list)
-redo-ifchange $objs conf/ar
-read AR <conf/ar
+redo-ifchange $objs ../conf/ar
+read AR <../conf/ar
 $AR -rcs $3.a $objs
 mv $3.a $3
similarity index 92%
rename from cyac/o.list
rename to cyac/lib/o.list
index d732c982d2a068691ef5a6c36f03445828caf6ce77e28e1e0f3a2003ddd1e3b7..3aaa683b60728dcbb0a97fee91eb83952f6480bb7097049d1bae540b3e979c2f 100644 (file)
@@ -2,6 +2,7 @@ dec.o
 dectai.o
 enc.o
 enctai.o
+err.o
 frombe.o
 items.o
 iter.o
diff --git a/cyac/lib/pki/.gitignore b/cyac/lib/pki/.gitignore
new file mode 100644 (file)
index 0000000..60f79ef
--- /dev/null
@@ -0,0 +1 @@
+/libyacpki.a
diff --git a/cyac/lib/pki/cer.c b/cyac/lib/pki/cer.c
new file mode 100644 (file)
index 0000000..7bc1303
--- /dev/null
@@ -0,0 +1,341 @@
+#include <stddef.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "../dec.h"
+#include "../dectai.h"
+#include "../enc.h"
+#include "../err.h"
+#include "../items.h"
+#include "cer.h"
+
+enum YACErr
+YACCerParse(
+    struct YACCer *cer,
+    ptrdiff_t *off,
+    char **failReason,
+    const unsigned char *buf,
+    const size_t len)
+{
+    struct YACItems *items = &(cer->items);
+    YACItemsInit(items);
+    enum YACErr err = YACItemsParse(items, off, buf, len);
+    if (err != YACErrNo) {
+        return err;
+    }
+    ptrdiff_t idx = 0;
+    struct YACItem *item = NULL;
+    if (YACItemsGetByKey(items, 0, "hash") != -1) {
+        (*failReason) = "unexpected /hash";
+        return YACErrUnsatisfiedSchema;
+    }
+    ptrdiff_t loadIdx = YACItemsGetByKey(items, 0, "load");
+    {
+        if (loadIdx == -1) {
+            (*failReason) = "no /load";
+            return YACErrUnsatisfiedSchema;
+        }
+        idx = YACItemsGetByKeyAndType(items, loadIdx, "t", YACItemStr);
+        if (loadIdx == -1) {
+            (*failReason) = "no /load/t";
+            return YACErrUnsatisfiedSchema;
+        }
+        if (!YACStrEqual(&(items->list[idx].atom), "cer")) {
+            (*failReason) = "/load/t != cer";
+            return YACErrUnsatisfiedSchema;
+        }
+    }
+    cer->load = YACItemsGetByKey(items, loadIdx, "v");
+    {
+        if (cer->load == -1) {
+            (*failReason) = "no /load/v";
+            return YACErrUnsatisfiedSchema;
+        }
+        idx = YACItemsGetByKey(items, cer->load, "ku");
+        if (idx != -1) {
+            item = &(items->list[idx]);
+            if (item->atom.len == 0) {
+                (*failReason) = "empty /load/v/ku";
+                return YACErrUnsatisfiedSchema;
+            }
+            if (!YACMapHasOnlyType(items, idx, YACItemNIL)) {
+                (*failReason) = "bad /load/v/ku value";
+                return YACErrUnsatisfiedSchema;
+            }
+        }
+    }
+    idx = YACItemsGetByKey(items, cer->load, "pub");
+    {
+        if (idx == -1) {
+            (*failReason) = "no /load/v/pub";
+            return YACErrUnsatisfiedSchema;
+        }
+        item = &(items->list[idx]);
+        if (item->atom.len != 1) {
+            (*failReason) = "len(/load/v/pub) != 1";
+            return YACErrUnsatisfiedSchema;
+        }
+        idx = items->list[idx].atom.val.first;
+        cer->pub = idx;
+        while (idx != -1) {
+            if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == -1) {
+                (*failReason) = "no /load/v/pub/a";
+                return YACErrUnsatisfiedSchema;
+            }
+            if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == -1) {
+                (*failReason) = "no /load/v/pub/v";
+                return YACErrUnsatisfiedSchema;
+            }
+            {
+                ptrdiff_t pkidIdx =
+                    YACItemsGetByKeyAndType(items, idx, "id", YACItemUUID);
+                if (pkidIdx == -1) {
+                    (*failReason) = "no /load/v/pub/id";
+                    return YACErrUnsatisfiedSchema;
+                }
+                cer->pkid = items->list[pkidIdx].atom.val.buf;
+            }
+            idx = items->list[idx].next;
+        }
+    }
+    cer->sub = YACItemsGetByKey(items, cer->load, "sub");
+    {
+        if (cer->sub == -1) {
+            (*failReason) = "no /load/v/sub";
+            return YACErrUnsatisfiedSchema;
+        }
+        item = &(items->list[cer->sub]);
+        if (item->atom.len == 0) {
+            (*failReason) = "empty /load/v/sub";
+            return YACErrUnsatisfiedSchema;
+        }
+        if (!YACMapHasOnlyType(items, cer->sub, YACItemStr)) {
+            (*failReason) = "bad /load/v/sub value";
+            return YACErrUnsatisfiedSchema;
+        }
+    }
+    if (YACItemsGetByKey(items, cer->load, "crit") != -1) {
+        (*failReason) = "/load/v/crit is unsupported";
+        return YACErrUnsatisfiedSchema;
+    }
+    ptrdiff_t sigsIdx = YACItemsGetByKey(items, 0, "sigs");
+    {
+        if (sigsIdx == -1) {
+            (*failReason) = "no /sigs";
+            return YACErrUnsatisfiedSchema;
+        }
+        item = &(items->list[sigsIdx]);
+        if (item->atom.len != 1) {
+            (*failReason) = "len(/load/sigs) != 1";
+            return YACErrUnsatisfiedSchema;
+        }
+        ptrdiff_t sigIdx = items->list[sigsIdx].atom.val.first;
+        cer->sig = sigIdx;
+        while (sigIdx != -1) {
+            if (YACItemsGetByKey(items, sigIdx, "hash") != -1) {
+                (*failReason) = "unexpected /sigs/./hash met";
+                return YACErrUnsatisfiedSchema;
+            }
+            {
+                idx = YACItemsGetByKey(items, sigIdx, "sign");
+                if (idx == -1) {
+                    (*failReason) = "no /sigs/./sign";
+                    return YACErrUnsatisfiedSchema;
+                }
+                if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == -1) {
+                    (*failReason) = "no /sigs/./sign/a";
+                    return YACErrUnsatisfiedSchema;
+                }
+                if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == -1) {
+                    (*failReason) = "no /sigs/./sign/v";
+                    return YACErrUnsatisfiedSchema;
+                }
+            }
+            {
+                idx = YACItemsGetByKey(items, sigIdx, "tbs");
+                if (idx == -1) {
+                    (*failReason) = "no /sigs/./tbs";
+                    return YACErrUnsatisfiedSchema;
+                }
+                {
+                    ptrdiff_t cidIdx =
+                        YACItemsGetByKeyAndType(items, idx, "cid", YACItemUUID);
+                    if (cidIdx == -1) {
+                        (*failReason) = "no /sigs/./tbs/cid";
+                        return YACErrUnsatisfiedSchema;
+                    }
+                    cer->cid = items->list[cidIdx].atom.val.buf;
+                }
+                {
+                    ptrdiff_t sidIdx =
+                        YACItemsGetByKeyAndType(items, idx, "sid", YACItemUUID);
+                    if (sidIdx == -1) {
+                        (*failReason) = "no /sigs/./tbs/sid";
+                        return YACErrUnsatisfiedSchema;
+                    }
+                    cer->sid = items->list[sidIdx].atom.val.buf;
+                }
+                idx = YACItemsGetByKeyAndType(items, idx, "exp", YACItemList);
+                if (idx == -1) {
+                    (*failReason) = "no /sigs/./tbs/exp";
+                    return YACErrUnsatisfiedSchema;
+                }
+                if (!YACListHasOnlyType(items, idx, YACItemTAI64)) {
+                    (*failReason) = "bad /sigs/./tbs/exp value";
+                    return YACErrUnsatisfiedSchema;
+                }
+                item = &(items->list[idx]);
+                if (item->atom.len != 2) {
+                    (*failReason) = "len(/sigs/./tbs/exp) != 2";
+                    return YACErrUnsatisfiedSchema;
+                }
+                err = YACTAI64ToTimeval(
+                    &(cer->since),
+                    items->list[idx + 1].atom.val.buf,
+                    items->list[idx + 1].atom.len);
+                if ((err != YACErrNo) || (cer->since.tv_usec != 0)) {
+                    (*failReason) = "bad /sigs/./tbs/exp/since value";
+                    return YACErrUnsatisfiedSchema;
+                }
+                err = YACTAI64ToTimeval(
+                    &(cer->till),
+                    items->list[idx + 2].atom.val.buf,
+                    items->list[idx + 2].atom.len);
+                if ((err != YACErrNo) || (cer->till.tv_usec != 0)) {
+                    (*failReason) = "bad /sigs/./tbs/exp/till value";
+                    return YACErrUnsatisfiedSchema;
+                }
+            }
+            sigIdx = items->list[sigIdx].next;
+        }
+    }
+    return YACErrNo;
+}
+
+bool
+YACCerVerify(
+    char **failReason,
+    struct YACCer **verifier,
+    struct YACCer *cer,
+    struct YACCer *pool,
+    const size_t poolLen,
+    struct YACCerVerifyOpts 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 YACItem *pubA = &((*verifier)->items.list[YACItemsGetByKey(
+        &((*verifier)->items), (*verifier)->pub, "a")]);
+    struct YACItem *pubV = &((*verifier)->items.list[YACItemsGetByKey(
+        &((*verifier)->items), (*verifier)->pub, "v")]);
+    ptrdiff_t signIdx = YACItemsGetByKey(&(cer->items), cer->sig, "sign");
+    struct YACItem *sigV =
+        &(cer->items.list[YACItemsGetByKey(&(cer->items), signIdx, "v")]);
+    {
+        struct YACItem *sigA =
+            &(cer->items.list[YACItemsGetByKey(&(cer->items), signIdx, "a")]);
+        if ((sigA->atom.len != pubA->atom.len) ||
+            (memcmp(sigA->atom.val.buf, pubA->atom.val.buf, sigA->atom.len) != 0)) {
+            (*failReason) = "sign.a != pub.a";
+            return false;
+        }
+    }
+    const size_t cap = 1 << 10;
+    unsigned char buf[1 << 10] = {0};
+    ptrdiff_t off = 0;
+    {
+        const size_t items = 5;
+        struct YACItem tbsItems[5];
+        memset(&tbsItems, 0, sizeof tbsItems);
+        struct YACItems tbs = {.list = tbsItems, items, items};
+        tbsItems[0].atom.typ = YACItemMap;
+        tbsItems[0].atom.val.first = 1;
+
+        tbsItems[1].atom.typ = YACItemStr;
+        tbsItems[1].atom.len = 1;
+        tbsItems[1].atom.val.buf = (const unsigned char *)"t";
+        tbsItems[1].next = 2;
+
+        tbsItems[2].atom.typ = YACItemStr;
+        tbsItems[2].atom.len = 3;
+        tbsItems[2].atom.val.buf = (const unsigned char *)"cer";
+        tbsItems[2].next = 3;
+
+        tbsItems[3].atom.typ = YACItemStr;
+        tbsItems[3].atom.len = 1;
+        tbsItems[3].atom.val.buf = (const unsigned char *)"v";
+        tbsItems[3].next = 4;
+
+        tbsItems[4].atom.typ = YACItemNIL;
+        tbsItems[4].next = -1;
+
+        if (YACItemsEncode(&tbs, 0, &off, buf, cap) != 0) {
+            (*failReason) = "can not prepare tbs";
+            return false;
+        }
+    }
+    off -= 2; // strip off NIL and EOC, continue map generation
+    if (YACItemsEncode(&(cer->items), cer->load, &off, buf, cap) != 0) {
+        (*failReason) = "can not prepare tbs";
+        return false;
+    }
+    {
+        ptrdiff_t diff = YACAtomStrEncode(
+            buf + off, cap - (size_t)off, (const unsigned char *)"tbs", 3);
+        if (diff < 1) {
+            (*failReason) = "can not prepare tbs";
+            return false;
+        }
+        off += diff;
+    }
+    if (YACItemsEncode(
+            &(cer->items),
+            YACItemsGetByKey(&(cer->items), cer->sig, "tbs"),
+            &off,
+            buf,
+            cap) != 0) {
+        (*failReason) = "can not prepare tbs";
+        return false;
+    }
+    {
+        ptrdiff_t diff = YACAtomEOCEncode(buf + off, cap - (size_t)off);
+        if (diff < 1) {
+            (*failReason) = "can not prepare tbs";
+            return false;
+        }
+        off += diff;
+    }
+    for (size_t i = 0; i < opts.sigVerifiersLen; i++) {
+        if (!YACStrEqual(&(pubA->atom), opts.sigVerifiers[i].algo)) {
+            continue;
+        }
+        return opts.sigVerifiers[i].func(
+            failReason,
+            pubA->atom.val.buf,
+            pubA->atom.len,
+            sigV->atom.val.buf,
+            sigV->atom.len,
+            pubV->atom.val.buf,
+            pubV->atom.len,
+            buf,
+            (size_t)off);
+    }
+    (*failReason) = "no signature verifier found";
+    return false;
+}
diff --git a/cyac/lib/pki/cer.h b/cyac/lib/pki/cer.h
new file mode 100644 (file)
index 0000000..052a0ab
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef YAC_CER_H
+#define YAC_CER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/time.h>
+
+#include "../err.h"
+#include "../items.h"
+
+struct YACCer {
+    struct YACItems items;
+    ptrdiff_t load;
+    ptrdiff_t pub;
+    ptrdiff_t sub;
+    ptrdiff_t sig;
+    const unsigned char *cid;
+    const unsigned char *pkid;
+    const unsigned char *sid;
+    struct timeval since;
+    struct timeval till;
+};
+
+enum YACErr
+YACCerParse(
+    struct YACCer *,
+    ptrdiff_t *off,
+    char **failReason,
+    const unsigned char *buf,
+    const size_t len);
+
+typedef bool (*yacSigVerifier)(
+    char **failReason,
+    const unsigned char *ai,
+    const size_t aiLen,
+    const unsigned char *sig,
+    const size_t sigLen,
+    const unsigned char *pub,
+    const size_t pubLen,
+    const unsigned char *data,
+    const size_t dataLen);
+
+struct YACCerSigVerifier {
+    char *algo;
+    yacSigVerifier func;
+};
+
+struct YACCerVerifyOpts {
+    struct timeval t;
+    struct YACCerSigVerifier *sigVerifiers;
+    size_t sigVerifiersLen;
+};
+
+bool
+YACCerVerify(
+    char **failReason,
+    struct YACCer **verifier,
+    struct YACCer *cer,
+    struct YACCer *pool,
+    const size_t poolLen,
+    struct YACCerVerifyOpts opts);
+
+#endif // YAC_CER_H
diff --git a/cyac/lib/pki/clean b/cyac/lib/pki/clean
new file mode 100755 (executable)
index 0000000..318e647
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+exec rm -f *.o *.a
diff --git a/cyac/lib/pki/install.do b/cyac/lib/pki/install.do
new file mode 100644 (file)
index 0000000..219b91b
--- /dev/null
@@ -0,0 +1,6 @@
+redo-ifchange *.h libyacpki.a ../../conf/prefix
+read PREFIX <../../conf/prefix
+mkdir -p $PREFIX/include/yac/pki $PREFIX/lib
+cp -f *.h $PREFIX/include/yac/pki
+cp -f libyacpki.a $PREFIX/lib
+chmod 644 $PREFIX/include/yac/pki/*.h $PREFIX/lib/libyacpki.a
diff --git a/cyac/lib/pki/libyacpki.a.do b/cyac/lib/pki/libyacpki.a.do
new file mode 100644 (file)
index 0000000..437e92a
--- /dev/null
@@ -0,0 +1,6 @@
+redo-ifchange o.list
+objs=$(cat o.list)
+redo-ifchange $objs ../../conf/ar
+read AR <../../conf/ar
+$AR -rcs $3.a $objs
+mv $3.a $3
diff --git a/cyac/lib/pki/o.list b/cyac/lib/pki/o.list
new file mode 100644 (file)
index 0000000..c7f1e63
--- /dev/null
@@ -0,0 +1 @@
+cer.o
similarity index 100%
rename from cyac/tobe.c
rename to cyac/lib/tobe.c
similarity index 100%
rename from cyac/tobe.h
rename to cyac/lib/tobe.h
similarity index 100%
rename from cyac/utf8.c
rename to cyac/lib/utf8.c
similarity index 100%
rename from cyac/utf8.h
rename to cyac/lib/utf8.h