cifra_cmac.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * cifra - embedded cryptography library
  3. * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
  4. *
  5. * To the extent possible under law, the author(s) have dedicated all
  6. * copyright and related and neighboring rights to this software to the
  7. * public domain worldwide. This software is distributed without any
  8. * warranty.
  9. *
  10. * You should have received a copy of the CC0 Public Domain Dedication
  11. * along with this software. If not, see
  12. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  13. */
  14. #include "handy.h"
  15. #include "prp.h"
  16. #include "modes.h"
  17. #include "bitops.h"
  18. #include "blockwise.h"
  19. #include "gf128.h"
  20. #include "tassert.h"
  21. #include <string.h>
  22. void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx)
  23. {
  24. uint8_t L[CF_MAXBLOCK];
  25. assert(prp->blocksz == 16);
  26. mem_clean(ctx, sizeof *ctx);
  27. /* L = E_K(0^n) */
  28. mem_clean(L, prp->blocksz);
  29. prp->encrypt(prpctx, L, L);
  30. /* B = 2L */
  31. cf_gf128 gf;
  32. cf_gf128_frombytes_be(L, gf);
  33. cf_gf128_double(gf, gf);
  34. cf_gf128_tobytes_be(gf, ctx->B);
  35. /* P = 4L */
  36. cf_gf128_double(gf, gf);
  37. cf_gf128_tobytes_be(gf, ctx->P);
  38. ctx->prp = prp;
  39. ctx->prpctx = prpctx;
  40. }
  41. void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK])
  42. {
  43. cf_cmac_stream stream;
  44. stream.cmac = *ctx;
  45. cf_cmac_stream_reset(&stream);
  46. cf_cmac_stream_update(&stream, data, len, 1);
  47. cf_cmac_stream_final(&stream, out);
  48. }
  49. void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx)
  50. {
  51. cf_cmac_init(&ctx->cmac, prp, prpctx);
  52. cf_cmac_stream_reset(ctx);
  53. }
  54. void cf_cmac_stream_reset(cf_cmac_stream *ctx)
  55. {
  56. uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
  57. cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero);
  58. mem_clean(ctx->buffer, sizeof ctx->buffer);
  59. ctx->used = 0;
  60. ctx->processed = 0;
  61. ctx->finalised = 0;
  62. }
  63. static void cmac_process(void *vctx, const uint8_t *block)
  64. {
  65. cf_cmac_stream *ctx = vctx;
  66. uint8_t output[CF_MAXBLOCK];
  67. cf_cbc_encrypt(&ctx->cbc, block, output, 1);
  68. ctx->processed += ctx->cmac.prp->blocksz;
  69. }
  70. static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block,
  71. const uint8_t *xor)
  72. {
  73. uint8_t input[CF_MAXBLOCK];
  74. uint8_t output[CF_MAXBLOCK];
  75. xor_bb(input, block, xor, ctx->cmac.prp->blocksz);
  76. cf_cbc_encrypt(&ctx->cbc, input, output, 1);
  77. ctx->processed += ctx->cmac.prp->blocksz;
  78. /* signature is in ctx->cbc.block. */
  79. }
  80. static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
  81. {
  82. cf_cmac_stream *ctx = vctx;
  83. cmac_process_final(ctx, block, ctx->cmac.B);
  84. ctx->finalised = 1;
  85. }
  86. static void cmac_process_final_pad(void *vctx, const uint8_t *block)
  87. {
  88. cf_cmac_stream *ctx = vctx;
  89. cmac_process_final(ctx, block, ctx->cmac.P);
  90. ctx->finalised = 1;
  91. }
  92. void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
  93. {
  94. size_t blocksz = ctx->cmac.prp->blocksz;
  95. cf_blockwise_in_fn final_fn = cmac_process;
  96. int needpad = 0;
  97. if (isfinal)
  98. {
  99. int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
  100. int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;
  101. assert(!ctx->finalised); /* finalised before? */
  102. assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */
  103. /* If we have a whole number of blocks, and at least 1 block, we XOR in B.
  104. * Otherwise, we need to pad and XOR in P. */
  105. if (whole_number_of_blocks && !empty_message)
  106. final_fn = cmac_process_final_nopad;
  107. else
  108. needpad = 1;
  109. }
  110. /* Input data */
  111. cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz,
  112. data, len,
  113. cmac_process,
  114. final_fn, ctx);
  115. /* Input padding */
  116. if (needpad)
  117. {
  118. cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz,
  119. 0x80, 0x00, 0x00, blocksz - ctx->used,
  120. cmac_process_final_pad, ctx);
  121. }
  122. }
  123. void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
  124. {
  125. assert(ctx->finalised);
  126. memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz);
  127. }