0
|
1 /**
|
|
2 * This file is part of the dcrypt project.
|
|
3 *
|
|
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
|
|
5 * License: MIT
|
|
6 * Authors: Thomas Dixon
|
|
7 */
|
|
8
|
|
9 module dcrypt.crypto.modes.CTR;
|
|
10
|
|
11 import dcrypt.crypto.BlockCipher;
|
|
12 import dcrypt.crypto.params.ParametersWithIV;
|
|
13
|
|
14
|
|
15 /** This class implements the counter (CTR/SIC/ICM) block mode,
|
|
16 treating the counter as a big endian integer. */
|
|
17 class CTR : BlockCipher {
|
|
18 private BlockCipher m_cipher;
|
|
19 private ubyte[] iv,
|
|
20 counter,
|
|
21 counterOutput;
|
|
22 private bool initialized = false;
|
|
23
|
|
24 /**
|
|
25 * Params:
|
|
26 * cipher = Block cipher to wrap.
|
|
27 */
|
|
28 this (BlockCipher cipher) {
|
|
29 m_cipher = cipher;
|
|
30 }
|
|
31
|
|
32 /** Returns: The underlying cipher we are wrapping. */
|
|
33 BlockCipher cipher() {
|
|
34 return m_cipher;
|
|
35 }
|
|
36
|
|
37 char[] name() {
|
|
38 return m_cipher.name~"/CTR";
|
|
39 }
|
|
40
|
|
41 /**
|
|
42 * Throws: dcrypt.crypto.errors.InvalidParameterError if params aren't
|
|
43 * an instance of dcrypt.crypto.params.ParametersWithIV.
|
|
44 */
|
|
45 void init(bool encrypt, CipherParameters params) {
|
|
46 ParametersWithIV ivParams = cast(ParametersWithIV)params;
|
|
47
|
|
48 if (!ivParams)
|
|
49 throw new InvalidParameterError(
|
|
50 name()~": Block mode requires IV (use ParametersWithIV)");
|
|
51 if (ivParams.iv.length != blockSize)
|
|
52 throw new InvalidParameterError(
|
|
53 name()~": IV must be same length as cipher block size");
|
|
54
|
|
55 m_cipher.init(true, ivParams.parameters);
|
|
56
|
|
57 iv = ivParams.iv[0..blockSize];
|
|
58 counter = new ubyte[blockSize];
|
|
59 counter[] = iv;
|
|
60 counterOutput = new ubyte[blockSize];
|
|
61
|
|
62 initialized = true;
|
|
63 }
|
|
64
|
|
65 uint processBlock(void[] input_, uint inOff, void[] output_, uint outOff) {
|
|
66 if (!initialized)
|
|
67 throw new NotInitializedError(
|
|
68 name()~": Block mode not initialized");
|
|
69
|
|
70 ubyte[] input = cast(ubyte[]) input_;
|
|
71 ubyte[] output = cast(ubyte[]) output_;
|
|
72
|
|
73 // Encrypt the counter
|
|
74 m_cipher.processBlock(counter, 0, counterOutput, 0);
|
|
75
|
|
76 // XOR output with plaintext to create ciphertext
|
|
77 for (int i = 0; i < counter.length; i++)
|
|
78 output[outOff++] = (counterOutput[i] ^ input[inOff++]);
|
|
79
|
|
80 // Increment the counter
|
|
81 for (int i = counter.length-1; i >= 0; i--)
|
|
82 if (++counter[i]) break;
|
|
83
|
|
84 return counter.length;
|
|
85 }
|
|
86
|
|
87 uint blockSize() {
|
|
88 return m_cipher.blockSize;
|
|
89 }
|
|
90
|
|
91 void reset() {
|
|
92 counter[] = iv;
|
|
93 m_cipher.reset();
|
|
94 }
|
|
95 }
|