1 /** 2 * ECB/CBC Padding Methods 3 * 4 * Copyright: 5 * (C) 1999-2008,2013 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.modes.mode_pad; 12 13 import memutils.vector; 14 import botan.utils.exceptn; 15 import botan.constants; 16 17 /** 18 * Block Cipher Mode Padding Method 19 * This class is pretty limited, it cannot deal well with 20 * randomized padding methods, or any padding method that 21 * wants to add more than one block. For instance, it should 22 * be possible to define cipher text stealing mode as simply 23 * a padding mode for CBC, which happens to consume the last 24 * two block (and requires use of the block cipher). 25 */ 26 interface BlockCipherModePaddingMethod 27 { 28 public: 29 abstract void addPadding(ref SecureVector!ubyte buffer, size_t final_block_bytes, size_t block_size) const; 30 31 /** 32 * Params: 33 * block = the last block 34 * size = the of the block 35 */ 36 abstract size_t unpad(const(ubyte)* block, 37 size_t size) const; 38 39 /** 40 * Params: 41 * block_size = of the cipher 42 * Returns: valid block size for this padding mode 43 */ 44 abstract bool validBlocksize(size_t block_size) const; 45 46 /** 47 * Returns: name of the mode 48 */ 49 abstract @property string name() const; 50 51 } 52 53 /** 54 * PKCS#7 Padding 55 */ 56 final class PKCS7Padding : BlockCipherModePaddingMethod 57 { 58 public: 59 /* 60 * Pad with PKCS #7 Method 61 */ 62 override void addPadding(ref SecureVector!ubyte buffer, size_t last_byte_pos, size_t block_size) const 63 { 64 const ubyte pad_value = cast(ubyte)( block_size - last_byte_pos ); 65 66 foreach (size_t i; 0 .. pad_value) 67 buffer.pushBack(cast(ubyte)pad_value); 68 } 69 70 /* 71 * Unpad with PKCS #7 Method 72 */ 73 override size_t unpad(const(ubyte)* block, size_t size) const 74 { 75 size_t position = block[size-1]; 76 77 if (position > size) 78 throw new DecodingError("Bad padding in " ~ name); 79 80 foreach (size_t j; (size-position) .. (size-1)) 81 if (block[j] != position) 82 throw new DecodingError("Bad padding in " ~ name); 83 84 return (size-position); 85 } 86 87 override bool validBlocksize(size_t bs) const { return (bs > 0 && bs < 256); } 88 89 override @property string name() const { return "PKCS7"; } 90 } 91 92 /** 93 * ANSI X9.23 Padding 94 */ 95 final class ANSIX923Padding : BlockCipherModePaddingMethod 96 { 97 public: 98 /* 99 * Pad with ANSI X9.23 Method 100 */ 101 override void addPadding(ref SecureVector!ubyte buffer, 102 size_t last_byte_pos, 103 size_t block_size) const 104 { 105 const ubyte pad_value = cast(ubyte) (block_size - last_byte_pos); 106 107 for (size_t i = last_byte_pos; i < block_size; ++i) 108 buffer.pushBack(0); 109 buffer.pushBack(pad_value); 110 } 111 112 /* 113 * Unpad with ANSI X9.23 Method 114 */ 115 override size_t unpad(const(ubyte)* block, size_t size) const 116 { 117 size_t position = block[size-1]; 118 if (position > size) 119 throw new DecodingError(name); 120 foreach (size_t j; (size-position) .. (size-1)) 121 if (block[j] != 0) 122 throw new DecodingError(name); 123 return (size-position); 124 } 125 126 override bool validBlocksize(size_t bs) const { return (bs > 0 && bs < 256); } 127 128 override @property string name() const { return "X9.23"; } 129 } 130 131 /** 132 * One And Zeros Padding 133 */ 134 final class OneAndZerosPadding : BlockCipherModePaddingMethod 135 { 136 public: 137 /* 138 * Pad with One and Zeros Method 139 */ 140 override void addPadding(ref SecureVector!ubyte buffer, size_t last_byte_pos, size_t block_size) const 141 { 142 buffer.pushBack(0x80); 143 144 for (size_t i = last_byte_pos + 1; i % block_size; ++i) 145 buffer.pushBack(0x00); 146 } 147 148 /* 149 * Unpad with One and Zeros Method 150 */ 151 override size_t unpad(const(ubyte)* block, size_t size) const 152 { 153 while (size) 154 { 155 if (block[size-1] == 0x80) 156 break; 157 if (block[size-1] != 0x00) 158 throw new DecodingError(name); 159 size--; 160 } 161 if (!size) 162 throw new DecodingError(name); 163 return (size-1); 164 } 165 166 override bool validBlocksize(size_t bs) const { return (bs > 0); } 167 168 override @property string name() const { return "OneAndZeros"; } 169 } 170 171 /** 172 * Null Padding 173 */ 174 final class NullPadding : BlockCipherModePaddingMethod 175 { 176 public: 177 override void addPadding(ref SecureVector!ubyte, size_t, size_t) const {} 178 179 override size_t unpad(const(ubyte)*, size_t size) const { return size; } 180 181 override bool validBlocksize(size_t) const { return true; } 182 183 override @property string name() const { return "NoPadding"; } 184 }