hmac_sha256.c 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * hmac.c - HMAC
  3. *
  4. * Copyright (C) 2017 Sergei Glushchenko
  5. * Author: Sergei Glushchenko <gl.sergei@gmail.com>
  6. *
  7. * This file is a part of U2F firmware for STM32
  8. *
  9. * This program is free software: you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * As additional permission under GNU GPL version 3 section 7, you may
  23. * distribute non-source form of the Program without the copy of the
  24. * GNU GPL normally required by section 4, provided you inform the
  25. * recipients of GNU GPL by a written offer.
  26. *
  27. */
  28. #include <stdint.h>
  29. #include "sha256.h"
  30. #include "hmac_sha256.h"
  31. static void _hmac_sha256_init(const hmac_context* ctx) {
  32. hmac_sha256_context* context = (hmac_sha256_context*)ctx;
  33. sha256_start(&context->sha_ctx);
  34. }
  35. static void
  36. _hmac_sha256_update(const hmac_context* ctx, const uint8_t* message, unsigned message_size) {
  37. hmac_sha256_context* context = (hmac_sha256_context*)ctx;
  38. sha256_update(&context->sha_ctx, message, message_size);
  39. }
  40. static void _hmac_sha256_finish(const hmac_context* ctx, uint8_t* hash_result) {
  41. hmac_sha256_context* context = (hmac_sha256_context*)ctx;
  42. sha256_finish(&context->sha_ctx, hash_result);
  43. }
  44. /* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
  45. the same size as the hash result size. */
  46. static void hmac_init(const hmac_context* ctx, const uint8_t* K) {
  47. uint8_t* pad = ctx->tmp + 2 * ctx->result_size;
  48. unsigned i;
  49. for(i = 0; i < ctx->result_size; ++i) pad[i] = K[i] ^ 0x36;
  50. for(; i < ctx->block_size; ++i) pad[i] = 0x36;
  51. ctx->init_hash(ctx);
  52. ctx->update_hash(ctx, pad, ctx->block_size);
  53. }
  54. static void hmac_update(const hmac_context* ctx, const uint8_t* message, unsigned message_size) {
  55. ctx->update_hash(ctx, message, message_size);
  56. }
  57. static void hmac_finish(const hmac_context* ctx, const uint8_t* K, uint8_t* result) {
  58. uint8_t* pad = ctx->tmp + 2 * ctx->result_size;
  59. unsigned i;
  60. for(i = 0; i < ctx->result_size; ++i) pad[i] = K[i] ^ 0x5c;
  61. for(; i < ctx->block_size; ++i) pad[i] = 0x5c;
  62. ctx->finish_hash(ctx, result);
  63. ctx->init_hash(ctx);
  64. ctx->update_hash(ctx, pad, ctx->block_size);
  65. ctx->update_hash(ctx, result, ctx->result_size);
  66. ctx->finish_hash(ctx, result);
  67. }
  68. void hmac_sha256_init(hmac_sha256_context* ctx, const uint8_t* K) {
  69. ctx->hmac_ctx.init_hash = _hmac_sha256_init;
  70. ctx->hmac_ctx.update_hash = _hmac_sha256_update;
  71. ctx->hmac_ctx.finish_hash = _hmac_sha256_finish;
  72. ctx->hmac_ctx.block_size = 64;
  73. ctx->hmac_ctx.result_size = 32;
  74. ctx->hmac_ctx.tmp = ctx->tmp;
  75. hmac_init(&ctx->hmac_ctx, K);
  76. }
  77. void hmac_sha256_update(
  78. const hmac_sha256_context* ctx,
  79. const uint8_t* message,
  80. unsigned message_size) {
  81. hmac_update(&ctx->hmac_ctx, message, message_size);
  82. }
  83. void hmac_sha256_finish(const hmac_sha256_context* ctx, const uint8_t* K, uint8_t* hash_result) {
  84. hmac_finish(&ctx->hmac_ctx, K, hash_result);
  85. }