/ src / crypto / aes.cpp
aes.cpp
  1  // Copyright (c) 2016-present The Bitcoin Core developers
  2  // Distributed under the MIT software license, see the accompanying
  3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4  
  5  #include <crypto/aes.h>
  6  
  7  #include <cstring>
  8  
  9  extern "C" {
 10  #include <crypto/ctaes/ctaes.c>
 11  }
 12  
 13  AES256Encrypt::AES256Encrypt(const unsigned char key[32])
 14  {
 15      AES256_init(&ctx, key);
 16  }
 17  
 18  AES256Encrypt::~AES256Encrypt()
 19  {
 20      memset(&ctx, 0, sizeof(ctx));
 21  }
 22  
 23  void AES256Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
 24  {
 25      AES256_encrypt(&ctx, 1, ciphertext, plaintext);
 26  }
 27  
 28  AES256Decrypt::AES256Decrypt(const unsigned char key[32])
 29  {
 30      AES256_init(&ctx, key);
 31  }
 32  
 33  AES256Decrypt::~AES256Decrypt()
 34  {
 35      memset(&ctx, 0, sizeof(ctx));
 36  }
 37  
 38  void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
 39  {
 40      AES256_decrypt(&ctx, 1, plaintext, ciphertext);
 41  }
 42  
 43  
 44  template <typename T>
 45  static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
 46  {
 47      int written = 0;
 48      int padsize = size % AES_BLOCKSIZE;
 49      unsigned char mixed[AES_BLOCKSIZE];
 50  
 51      if (!data || !size || !out)
 52          return 0;
 53  
 54      if (!pad && padsize != 0)
 55          return 0;
 56  
 57      memcpy(mixed, iv, AES_BLOCKSIZE);
 58  
 59      // Write all but the last block
 60      while (written + AES_BLOCKSIZE <= size) {
 61          for (int i = 0; i != AES_BLOCKSIZE; i++)
 62              mixed[i] ^= *data++;
 63          enc.Encrypt(out + written, mixed);
 64          memcpy(mixed, out + written, AES_BLOCKSIZE);
 65          written += AES_BLOCKSIZE;
 66      }
 67      if (pad) {
 68          // For all that remains, pad each byte with the value of the remaining
 69          // space. If there is none, pad by a full block.
 70          for (int i = 0; i != padsize; i++)
 71              mixed[i] ^= *data++;
 72          for (int i = padsize; i != AES_BLOCKSIZE; i++)
 73              mixed[i] ^= AES_BLOCKSIZE - padsize;
 74          enc.Encrypt(out + written, mixed);
 75          written += AES_BLOCKSIZE;
 76      }
 77      return written;
 78  }
 79  
 80  template <typename T>
 81  static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
 82  {
 83      int written = 0;
 84      bool fail = false;
 85      const unsigned char* prev = iv;
 86  
 87      if (!data || !size || !out)
 88          return 0;
 89  
 90      if (size % AES_BLOCKSIZE != 0)
 91          return 0;
 92  
 93      // Decrypt all data. Padding will be checked in the output.
 94      while (written != size) {
 95          dec.Decrypt(out, data + written);
 96          for (int i = 0; i != AES_BLOCKSIZE; i++)
 97              *out++ ^= prev[i];
 98          prev = data + written;
 99          written += AES_BLOCKSIZE;
100      }
101  
102      // When decrypting padding, attempt to run in constant-time
103      if (pad) {
104          // If used, padding size is the value of the last decrypted byte. For
105          // it to be valid, It must be between 1 and AES_BLOCKSIZE.
106          unsigned char padsize = *--out;
107          fail = !padsize | (padsize > AES_BLOCKSIZE);
108  
109          // If not well-formed, treat it as though there's no padding.
110          padsize *= !fail;
111  
112          // All padding must equal the last byte otherwise it's not well-formed
113          for (int i = AES_BLOCKSIZE; i != 0; i--)
114              fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize));
115  
116          written -= padsize;
117      }
118      return written * !fail;
119  }
120  
121  AES256CBCEncrypt::AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
122      : enc(key), pad(padIn)
123  {
124      memcpy(iv, ivIn, AES_BLOCKSIZE);
125  }
126  
127  int AES256CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const
128  {
129      return CBCEncrypt(enc, iv, data, size, pad, out);
130  }
131  
132  AES256CBCEncrypt::~AES256CBCEncrypt()
133  {
134      memset(iv, 0, sizeof(iv));
135  }
136  
137  AES256CBCDecrypt::AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
138      : dec(key), pad(padIn)
139  {
140      memcpy(iv, ivIn, AES_BLOCKSIZE);
141  }
142  
143  
144  int AES256CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const
145  {
146      return CBCDecrypt(dec, iv, data, size, pad, out);
147  }
148  
149  AES256CBCDecrypt::~AES256CBCDecrypt()
150  {
151      memset(iv, 0, sizeof(iv));
152  }