eax.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 "prp.h"
  15. #include "modes.h"
  16. #include "tassert.h"
  17. #include "handy.h"
  18. #include <string.h>
  19. static void cmac_compute_n(cf_cmac_stream *ctx,
  20. uint8_t t,
  21. const uint8_t *input, size_t ninput,
  22. uint8_t out[CF_MAXBLOCK])
  23. {
  24. size_t blocksz = ctx->cmac.prp->blocksz;
  25. assert(blocksz > 0);
  26. uint8_t firstblock[CF_MAXBLOCK];
  27. memset(firstblock, 0, blocksz);
  28. firstblock[blocksz - 1] = t;
  29. cf_cmac_stream_reset(ctx);
  30. if (ninput)
  31. {
  32. cf_cmac_stream_update(ctx, firstblock, blocksz, 0);
  33. cf_cmac_stream_update(ctx, input, ninput, 1);
  34. } else {
  35. cf_cmac_stream_update(ctx, firstblock, blocksz, 1);
  36. }
  37. cf_cmac_stream_final(ctx, out);
  38. }
  39. void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
  40. const uint8_t *plain, size_t nplain,
  41. const uint8_t *header, size_t nheader,
  42. const uint8_t *nonce, size_t nnonce,
  43. uint8_t *cipher, /* the same size as nplain */
  44. uint8_t *tag, size_t ntag)
  45. {
  46. uint8_t NN[CF_MAXBLOCK],
  47. HH[CF_MAXBLOCK],
  48. CC[CF_MAXBLOCK];
  49. cf_cmac_stream cmac;
  50. cf_cmac_stream_init(&cmac, prp, prpctx);
  51. /* NN = OMAC_K^0(N) */
  52. cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
  53. /* HH = OMAC_K^1(H) */
  54. cmac_compute_n(&cmac, 1, header, nheader, HH);
  55. /* C = CTR_K^NN(M) */
  56. cf_ctr ctr;
  57. cf_ctr_init(&ctr, prp, prpctx, NN);
  58. cf_ctr_cipher(&ctr, plain, cipher, nplain);
  59. /* CC = OMAC_K^2(C) */
  60. cmac_compute_n(&cmac, 2, cipher, nplain, CC);
  61. /* Tag = NN ^ CC ^ HH
  62. * T = Tag [ first tau bits ] */
  63. assert(ntag <= prp->blocksz);
  64. for (size_t i = 0; i < ntag; i++)
  65. tag[i] = NN[i] ^ CC[i] ^ HH[i];
  66. }
  67. int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
  68. const uint8_t *cipher, size_t ncipher,
  69. const uint8_t *header, size_t nheader,
  70. const uint8_t *nonce, size_t nnonce,
  71. const uint8_t *tag, size_t ntag,
  72. uint8_t *plain) /* the same size as ncipher */
  73. {
  74. uint8_t NN[CF_MAXBLOCK],
  75. HH[CF_MAXBLOCK],
  76. CC[CF_MAXBLOCK];
  77. cf_cmac_stream cmac;
  78. cf_cmac_stream_init(&cmac, prp, prpctx);
  79. /* NN = OMAC_K^0(N) */
  80. cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
  81. /* HH = OMAC_K^1(H) */
  82. cmac_compute_n(&cmac, 1, header, nheader, HH);
  83. /* CC = OMAC_K^2(C) */
  84. cmac_compute_n(&cmac, 2, cipher, ncipher, CC);
  85. uint8_t tt[CF_MAXBLOCK];
  86. assert(ntag && ntag <= prp->blocksz);
  87. for (size_t i = 0; i < ntag; i++)
  88. tt[i] = NN[i] ^ CC[i] ^ HH[i];
  89. if (!mem_eq(tt, tag, ntag))
  90. return 1;
  91. cf_ctr ctr;
  92. cf_ctr_init(&ctr, prp, prpctx, NN);
  93. cf_ctr_cipher(&ctr, cipher, plain, ncipher);
  94. return 0;
  95. }