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.

AESInStream.cxx 2.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /* Copyright (C) 2022 Dinglan Peng
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <assert.h>
  22. #include <rdr/AESInStream.h>
  23. #include <rdr/Exception.h>
  24. #ifdef HAVE_NETTLE
  25. using namespace rdr;
  26. AESInStream::AESInStream(InStream* _in, const U8* key, int _keySize)
  27. : keySize(_keySize), in(_in), counter()
  28. {
  29. if (keySize == 128)
  30. EAX_SET_KEY(&eaxCtx128, aes128_set_encrypt_key, aes128_encrypt, key);
  31. else if (keySize == 256)
  32. EAX_SET_KEY(&eaxCtx256, aes256_set_encrypt_key, aes256_encrypt, key);
  33. else
  34. assert(!"incorrect key size");
  35. }
  36. AESInStream::~AESInStream() {}
  37. bool AESInStream::fillBuffer()
  38. {
  39. if (!in->hasData(2))
  40. return false;
  41. const U8* ptr = in->getptr(2);
  42. size_t length = ((int)ptr[0] << 8) | (int)ptr[1];
  43. if (!in->hasData(2 + length + 16))
  44. return false;
  45. ensureSpace(length);
  46. ptr = in->getptr(2 + length + 16);
  47. const U8* ad = ptr;
  48. const U8* data = ptr + 2;
  49. const U8* mac = ptr + 2 + length;
  50. U8 macComputed[16];
  51. if (keySize == 128) {
  52. EAX_SET_NONCE(&eaxCtx128, aes128_encrypt, 16, counter);
  53. EAX_UPDATE(&eaxCtx128, aes128_encrypt, 2, ad);
  54. EAX_DECRYPT(&eaxCtx128, aes128_encrypt, length, (rdr::U8*)end, data);
  55. EAX_DIGEST(&eaxCtx128, aes128_encrypt, 16, macComputed);
  56. } else {
  57. EAX_SET_NONCE(&eaxCtx256, aes256_encrypt, 16, counter);
  58. EAX_UPDATE(&eaxCtx256, aes256_encrypt, 2, ad);
  59. EAX_DECRYPT(&eaxCtx256, aes256_encrypt, length, (rdr::U8*)end, data);
  60. EAX_DIGEST(&eaxCtx256, aes256_encrypt, 16, macComputed);
  61. }
  62. if (memcmp(mac, macComputed, 16) != 0)
  63. throw Exception("AESInStream: failed to authenticate message");
  64. in->setptr(2 + length + 16);
  65. end += length;
  66. // Update nonce by incrementing the counter as a
  67. // 128bit little endian unsigned integer
  68. for (int i = 0; i < 16; ++i) {
  69. // increment until there is no carry
  70. if (++counter[i] != 0) {
  71. break;
  72. }
  73. }
  74. return true;
  75. }
  76. #endif