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