cbc_mode.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
  2. /*
  3. * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * - Neither the name of Intel Corporation nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <tinycrypt/cbc_mode.h>
  32. #include <tinycrypt/constants.h>
  33. #include <tinycrypt/utils.h>
  34. int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
  35. unsigned int inlen, const uint8_t *iv,
  36. const TCAesKeySched_t sched)
  37. {
  38. uint8_t buffer[TC_AES_BLOCK_SIZE];
  39. unsigned int n, m;
  40. /* input sanity check: */
  41. if (out == (uint8_t *) 0 ||
  42. in == (const uint8_t *) 0 ||
  43. sched == (TCAesKeySched_t) 0 ||
  44. inlen == 0 ||
  45. outlen == 0 ||
  46. (inlen % TC_AES_BLOCK_SIZE) != 0 ||
  47. (outlen % TC_AES_BLOCK_SIZE) != 0 ||
  48. outlen != inlen + TC_AES_BLOCK_SIZE) {
  49. return TC_CRYPTO_FAIL;
  50. }
  51. /* copy iv to the buffer */
  52. (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
  53. /* copy iv to the output buffer */
  54. (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
  55. out += TC_AES_BLOCK_SIZE;
  56. for (n = m = 0; n < inlen; ++n) {
  57. buffer[m++] ^= *in++;
  58. if (m == TC_AES_BLOCK_SIZE) {
  59. (void)tc_aes_encrypt(buffer, buffer, sched);
  60. (void)_copy(out, TC_AES_BLOCK_SIZE,
  61. buffer, TC_AES_BLOCK_SIZE);
  62. out += TC_AES_BLOCK_SIZE;
  63. m = 0;
  64. }
  65. }
  66. return TC_CRYPTO_SUCCESS;
  67. }
  68. int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
  69. unsigned int inlen, const uint8_t *iv,
  70. const TCAesKeySched_t sched)
  71. {
  72. uint8_t buffer[TC_AES_BLOCK_SIZE];
  73. const uint8_t *p;
  74. unsigned int n, m;
  75. /* sanity check the inputs */
  76. if (out == (uint8_t *) 0 ||
  77. in == (const uint8_t *) 0 ||
  78. sched == (TCAesKeySched_t) 0 ||
  79. inlen == 0 ||
  80. outlen == 0 ||
  81. (inlen % TC_AES_BLOCK_SIZE) != 0 ||
  82. (outlen % TC_AES_BLOCK_SIZE) != 0 ||
  83. outlen != inlen - TC_AES_BLOCK_SIZE) {
  84. return TC_CRYPTO_FAIL;
  85. }
  86. /*
  87. * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
  88. * contiguous. This allows for a very efficient decryption algorithm
  89. * that would not otherwise be possible.
  90. */
  91. p = iv;
  92. for (n = m = 0; n < inlen; ++n) {
  93. if ((n % TC_AES_BLOCK_SIZE) == 0) {
  94. (void)tc_aes_decrypt(buffer, in, sched);
  95. in += TC_AES_BLOCK_SIZE;
  96. m = 0;
  97. }
  98. *out++ = buffer[m++] ^ *p++;
  99. }
  100. return TC_CRYPTO_SUCCESS;
  101. }