4 * The One-key CBC MAC (OMAC) message authentication code,
\r
5 * designed by T. Iwata and K. Kurosawa.
\r
7 * @author Paulo S. L. M. Barreto
\r
11 * This software is hereby placed in the public domain.
\r
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
\r
14 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
\r
17 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
\r
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
\r
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
\r
20 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
\r
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
23 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
37 memset(L, (byte)0, sizeof(L));
\r
38 memset(T, (byte)0, sizeof(L));
\r
47 memset(L, (byte)0, sizeof(L));
\r
48 memset(T, (byte)0, sizeof(L));
\r
51 void OMAC::init(BlockCipher* E) {
\r
53 throw "Invalid block cipher";
\r
56 t = block_size = _E->blockSize();
\r
57 if (block_size != 16 && block_size != 8) {
\r
58 throw "Block size not supported";
\r
60 mask = (block_size == 16) ? 0x87 : 0x1B;
\r
61 // compute padding mask:
\r
62 memset(L, (byte)0, block_size);
\r
63 _E->encrypt(L, L); // L = E_K(0^n)
\r
64 uint c = L[0] & 0x80; // carry
\r
65 for (uint b = 0; b < block_size - 1; b++) {
\r
66 L[b] = (byte)((L[b] << 1) | ((L[b + 1] & 0xff) >> 7));
\r
68 L[block_size - 1] = (byte)((L[block_size - 1] << 1) ^ (c != 0 ? mask : 0)); // B = 2L
\r
69 // initialize tag accumulator
\r
70 memset(T, (byte)0, block_size);
\r
74 void OMAC::update(const byte* M, uint m) {
\r
76 throw "OMAC computation not initialized";
\r
78 uint i = block_size - t;
\r
80 while (m > t) { // N.B. m is strictly larger than t!
\r
81 // complete tag block:
\r
82 for (uint b = 0; b < t; b++) {
\r
83 T[i + b] ^= M[j + b];
\r
85 _E->encrypt(T, T); // since there is more data, no padding applies
\r
86 // proceed to the next block:
\r
93 // process remaining chunk (m bytes):
\r
94 for (uint b = 0; b < m; b++) {
\r
95 T[i + b] ^= M[j + b];
\r
98 //assert(m == 0 || t < block_size); // m == 0 here only occurs if m == 0 from the very beginning
\r
101 void OMAC::final(byte* tag) {
\r
103 // compute padding:
\r
105 // compute special padding mask:
\r
106 uint c = L[0] & 0x80; // carry
\r
107 for (uint b = 0; b < block_size - 1; b++) {
\r
108 L[b] = (byte)((L[b] << 1) | ((L[b + 1] & 0xff) >> 7));
\r
110 L[block_size - 1] = (byte)((L[block_size - 1] << 1) ^ (c != 0 ? mask : 0)); // P = 4L
\r
111 // pad incomplete block:
\r
112 T[block_size - t] ^= 0x80; // padding toggle
\r
115 for (uint b = 0; b < block_size; b++) {
\r
118 _E->encrypt(T, T); // T contains the complete tag
\r
119 ready = 1; // OMAC tag available
\r
120 _E = 0; // OMAC computation is complete; context no longer initialized
\r
121 } else if (!ready) {
\r
122 throw "OMAC computation not initialized";
\r
124 memcpy(tag, T, block_size);
\r