summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c
new file mode 100644
index 00000000..51f5843f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c
@@ -0,0 +1,150 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "bitops.h"
+#include "blockwise.h"
+#include "gf128.h"
+#include "tassert.h"
+
+#include <string.h>
+
+void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx)
+{
+ uint8_t L[CF_MAXBLOCK];
+ assert(prp->blocksz == 16);
+
+ mem_clean(ctx, sizeof *ctx);
+
+ /* L = E_K(0^n) */
+ mem_clean(L, prp->blocksz);
+ prp->encrypt(prpctx, L, L);
+
+ /* B = 2L */
+ cf_gf128 gf;
+ cf_gf128_frombytes_be(L, gf);
+ cf_gf128_double(gf, gf);
+ cf_gf128_tobytes_be(gf, ctx->B);
+
+ /* P = 4L */
+ cf_gf128_double(gf, gf);
+ cf_gf128_tobytes_be(gf, ctx->P);
+
+ ctx->prp = prp;
+ ctx->prpctx = prpctx;
+}
+
+void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK])
+{
+ cf_cmac_stream stream;
+ stream.cmac = *ctx;
+ cf_cmac_stream_reset(&stream);
+ cf_cmac_stream_update(&stream, data, len, 1);
+ cf_cmac_stream_final(&stream, out);
+}
+
+void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx)
+{
+ cf_cmac_init(&ctx->cmac, prp, prpctx);
+ cf_cmac_stream_reset(ctx);
+}
+
+void cf_cmac_stream_reset(cf_cmac_stream *ctx)
+{
+ uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
+ cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero);
+ mem_clean(ctx->buffer, sizeof ctx->buffer);
+ ctx->used = 0;
+ ctx->processed = 0;
+ ctx->finalised = 0;
+}
+
+static void cmac_process(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ uint8_t output[CF_MAXBLOCK];
+ cf_cbc_encrypt(&ctx->cbc, block, output, 1);
+ ctx->processed += ctx->cmac.prp->blocksz;
+}
+
+static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block,
+ const uint8_t *xor)
+{
+ uint8_t input[CF_MAXBLOCK];
+ uint8_t output[CF_MAXBLOCK];
+ xor_bb(input, block, xor, ctx->cmac.prp->blocksz);
+ cf_cbc_encrypt(&ctx->cbc, input, output, 1);
+ ctx->processed += ctx->cmac.prp->blocksz;
+ /* signature is in ctx->cbc.block. */
+}
+
+static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ cmac_process_final(ctx, block, ctx->cmac.B);
+ ctx->finalised = 1;
+}
+
+static void cmac_process_final_pad(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ cmac_process_final(ctx, block, ctx->cmac.P);
+ ctx->finalised = 1;
+}
+
+void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
+{
+ size_t blocksz = ctx->cmac.prp->blocksz;
+ cf_blockwise_in_fn final_fn = cmac_process;
+ int needpad = 0;
+
+ if (isfinal)
+ {
+ int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
+ int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;
+
+ assert(!ctx->finalised); /* finalised before? */
+ assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */
+
+ /* If we have a whole number of blocks, and at least 1 block, we XOR in B.
+ * Otherwise, we need to pad and XOR in P. */
+ if (whole_number_of_blocks && !empty_message)
+ final_fn = cmac_process_final_nopad;
+ else
+ needpad = 1;
+ }
+
+ /* Input data */
+ cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz,
+ data, len,
+ cmac_process,
+ final_fn, ctx);
+
+ /* Input padding */
+ if (needpad)
+ {
+ cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz,
+ 0x80, 0x00, 0x00, blocksz - ctx->used,
+ cmac_process_final_pad, ctx);
+ }
+}
+
+void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
+{
+ assert(ctx->finalised);
+ memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz);
+}
+