crypto_aesctr_shared.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * This code is shared between crypto_aesctr*.c files, and should not be
  3. * compiled as a separate translation unit. For details, see the comments in
  4. * those files.
  5. */
  6. /* AES-CTR state. */
  7. struct crypto_aesctr {
  8. const struct crypto_aes_key * key;
  9. uint64_t bytectr;
  10. uint8_t buf[16];
  11. uint8_t pblk[16];
  12. };
  13. /* Generate a block of cipherstream. */
  14. static inline void
  15. crypto_aesctr_stream_cipherblock_generate(struct crypto_aesctr * stream)
  16. {
  17. /* Sanity check. */
  18. assert(stream->bytectr % 16 == 0);
  19. /* Prepare counter. */
  20. stream->pblk[15]++;
  21. if (stream->pblk[15] == 0) {
  22. /*
  23. * If incrementing the least significant byte resulted in it
  24. * wrapping, re-encode the complete 64-bit value.
  25. */
  26. be64enc(stream->pblk + 8, stream->bytectr / 16);
  27. }
  28. /* Encrypt the cipherblock. */
  29. crypto_aes_encrypt_block(stream->pblk, stream->buf, stream->key);
  30. }
  31. /* Encrypt ${nbytes} bytes, then update ${inbuf}, ${outbuf}, and ${buflen}. */
  32. static inline void
  33. crypto_aesctr_stream_cipherblock_use(struct crypto_aesctr * stream,
  34. const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen, size_t nbytes,
  35. size_t bytemod)
  36. {
  37. size_t i;
  38. /* Encrypt the byte(s). */
  39. for (i = 0; i < nbytes; i++)
  40. (*outbuf)[i] = (*inbuf)[i] ^ stream->buf[bytemod + i];
  41. /* Move to the next byte(s) of cipherstream. */
  42. stream->bytectr += nbytes;
  43. /* Update the positions. */
  44. *inbuf += nbytes;
  45. *outbuf += nbytes;
  46. *buflen -= nbytes;
  47. }
  48. /*
  49. * Process any bytes before we can process a whole block. Return 1 if there
  50. * are no bytes left to process after calling this function.
  51. */
  52. static inline int
  53. crypto_aesctr_stream_pre_wholeblock(struct crypto_aesctr * stream,
  54. const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p)
  55. {
  56. size_t bytemod;
  57. /* Do we have any bytes left in the current cipherblock? */
  58. bytemod = stream->bytectr % 16;
  59. if (bytemod != 0) {
  60. /* Do we have enough to complete the request? */
  61. if (bytemod + *buflen_p <= 16) {
  62. /* Process only buflen bytes, then return. */
  63. crypto_aesctr_stream_cipherblock_use(stream, inbuf,
  64. outbuf, buflen_p, *buflen_p, bytemod);
  65. return (1);
  66. }
  67. /* Encrypt the byte(s) and update the positions. */
  68. crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf,
  69. buflen_p, 16 - bytemod, bytemod);
  70. }
  71. /* Success! */
  72. return (0);
  73. }
  74. /* Process any final bytes after finishing all whole blocks. */
  75. static inline void
  76. crypto_aesctr_stream_post_wholeblock(struct crypto_aesctr * stream,
  77. const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p)
  78. {
  79. /* Process any final bytes; we need a new cipherblock. */
  80. if (*buflen_p > 0) {
  81. /* Generate a block of cipherstream. */
  82. crypto_aesctr_stream_cipherblock_generate(stream);
  83. /* Encrypt the byte(s) and update the positions. */
  84. crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf,
  85. buflen_p, *buflen_p, 0);
  86. }
  87. }