You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.6KB

  1. /*
  2. * Copyright (C) 2012 Martin Storsjo
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <stddef.h>
  21. #include <stdint.h>
  22. #include <string.h>
  23. #include "attributes.h"
  24. #include "hmac.h"
  25. #include "md5.h"
  26. #include "sha.h"
  27. #include "mem.h"
  28. #include "version.h"
  29. #define MAX_HASHLEN 32
  30. #define MAX_BLOCKLEN 64
  31. typedef void (*hmac_final)(void *ctx, uint8_t *dst);
  32. #if FF_API_CRYPTO_SIZE_T
  33. typedef void (*hmac_update)(void *ctx, const uint8_t *src, int len);
  34. #else
  35. typedef void (*hmac_update)(void *ctx, const uint8_t *src, size_t len);
  36. #endif
  37. typedef void (*hmac_init)(void *ctx);
  38. struct AVHMAC {
  39. void *hash;
  40. int blocklen, hashlen;
  41. hmac_final final;
  42. hmac_update update;
  43. hmac_init init;
  44. uint8_t key[MAX_BLOCKLEN];
  45. int keylen;
  46. };
  47. #define DEFINE_SHA(bits) \
  48. static av_cold void sha ## bits ##_init(void *ctx) \
  49. { \
  50. av_sha_init(ctx, bits); \
  51. }
  52. DEFINE_SHA(160)
  53. DEFINE_SHA(224)
  54. DEFINE_SHA(256)
  55. AVHMAC *av_hmac_alloc(enum AVHMACType type)
  56. {
  57. AVHMAC *c = av_mallocz(sizeof(*c));
  58. if (!c)
  59. return NULL;
  60. switch (type) {
  61. case AV_HMAC_MD5:
  62. c->blocklen = 64;
  63. c->hashlen = 16;
  64. c->init = (hmac_init) av_md5_init;
  65. c->update = (hmac_update) av_md5_update;
  66. c->final = (hmac_final) av_md5_final;
  67. c->hash = av_md5_alloc();
  68. break;
  69. case AV_HMAC_SHA1:
  70. c->blocklen = 64;
  71. c->hashlen = 20;
  72. c->init = sha160_init;
  73. c->update = (hmac_update) av_sha_update;
  74. c->final = (hmac_final) av_sha_final;
  75. c->hash = av_sha_alloc();
  76. break;
  77. case AV_HMAC_SHA224:
  78. c->blocklen = 64;
  79. c->hashlen = 28;
  80. c->init = sha224_init;
  81. c->update = (hmac_update) av_sha_update;
  82. c->final = (hmac_final) av_sha_final;
  83. c->hash = av_sha_alloc();
  84. break;
  85. case AV_HMAC_SHA256:
  86. c->blocklen = 64;
  87. c->hashlen = 32;
  88. c->init = sha256_init;
  89. c->update = (hmac_update) av_sha_update;
  90. c->final = (hmac_final) av_sha_final;
  91. c->hash = av_sha_alloc();
  92. break;
  93. default:
  94. av_free(c);
  95. return NULL;
  96. }
  97. if (!c->hash) {
  98. av_free(c);
  99. return NULL;
  100. }
  101. return c;
  102. }
  103. void av_hmac_free(AVHMAC *c)
  104. {
  105. if (!c)
  106. return;
  107. av_free(c->hash);
  108. av_free(c);
  109. }
  110. void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
  111. {
  112. int i;
  113. uint8_t block[MAX_BLOCKLEN];
  114. if (keylen > c->blocklen) {
  115. c->init(c->hash);
  116. c->update(c->hash, key, keylen);
  117. c->final(c->hash, c->key);
  118. c->keylen = c->hashlen;
  119. } else {
  120. memcpy(c->key, key, keylen);
  121. c->keylen = keylen;
  122. }
  123. c->init(c->hash);
  124. for (i = 0; i < c->keylen; i++)
  125. block[i] = c->key[i] ^ 0x36;
  126. for (i = c->keylen; i < c->blocklen; i++)
  127. block[i] = 0x36;
  128. c->update(c->hash, block, c->blocklen);
  129. }
  130. void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
  131. {
  132. c->update(c->hash, data, len);
  133. }
  134. int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
  135. {
  136. uint8_t block[MAX_BLOCKLEN];
  137. int i;
  138. if (outlen < c->hashlen)
  139. return AVERROR(EINVAL);
  140. c->final(c->hash, out);
  141. c->init(c->hash);
  142. for (i = 0; i < c->keylen; i++)
  143. block[i] = c->key[i] ^ 0x5C;
  144. for (i = c->keylen; i < c->blocklen; i++)
  145. block[i] = 0x5C;
  146. c->update(c->hash, block, c->blocklen);
  147. c->update(c->hash, out, c->hashlen);
  148. c->final(c->hash, out);
  149. return c->hashlen;
  150. }
  151. int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len,
  152. const uint8_t *key, unsigned int keylen,
  153. uint8_t *out, unsigned int outlen)
  154. {
  155. av_hmac_init(c, key, keylen);
  156. av_hmac_update(c, data, len);
  157. return av_hmac_final(c, out, outlen);
  158. }