Botan  1.11.15
src/lib/hash/keccak/keccak.cpp
Go to the documentation of this file.
00001 /*
00002 * Keccak
00003 * (C) 2010 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/hash_utils.h>
00009 #include <botan/keccak.h>
00010 #include <botan/parsing.h>
00011 #include <botan/exceptn.h>
00012 #include <botan/internal/xor_buf.h>
00013 
00014 namespace Botan {
00015 
00016 BOTAN_REGISTER_HASH_NAMED_1LEN(Keccak_1600, "Keccak-1600", 512);
00017 
00018 namespace {
00019 
00020 void keccak_f_1600(u64bit A[25])
00021    {
00022    static const u64bit RC[24] = {
00023       0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
00024       0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
00025       0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
00026       0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
00027       0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
00028       0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
00029       0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
00030       0x8000000000008080, 0x0000000080000001, 0x8000000080008008
00031    };
00032 
00033    for(size_t i = 0; i != 24; ++i)
00034       {
00035       const u64bit C0 = A[0] ^ A[5] ^ A[10] ^ A[15] ^ A[20];
00036       const u64bit C1 = A[1] ^ A[6] ^ A[11] ^ A[16] ^ A[21];
00037       const u64bit C2 = A[2] ^ A[7] ^ A[12] ^ A[17] ^ A[22];
00038       const u64bit C3 = A[3] ^ A[8] ^ A[13] ^ A[18] ^ A[23];
00039       const u64bit C4 = A[4] ^ A[9] ^ A[14] ^ A[19] ^ A[24];
00040 
00041       const u64bit D0 = rotate_left(C0, 1) ^ C3;
00042       const u64bit D1 = rotate_left(C1, 1) ^ C4;
00043       const u64bit D2 = rotate_left(C2, 1) ^ C0;
00044       const u64bit D3 = rotate_left(C3, 1) ^ C1;
00045       const u64bit D4 = rotate_left(C4, 1) ^ C2;
00046 
00047       const u64bit B00 = A[ 0] ^ D1;
00048       const u64bit B01 = rotate_left(A[ 6] ^ D2, 44);
00049       const u64bit B02 = rotate_left(A[12] ^ D3, 43);
00050       const u64bit B03 = rotate_left(A[18] ^ D4, 21);
00051       const u64bit B04 = rotate_left(A[24] ^ D0, 14);
00052       const u64bit B05 = rotate_left(A[ 3] ^ D4, 28);
00053       const u64bit B06 = rotate_left(A[ 9] ^ D0, 20);
00054       const u64bit B07 = rotate_left(A[10] ^ D1, 3);
00055       const u64bit B08 = rotate_left(A[16] ^ D2, 45);
00056       const u64bit B09 = rotate_left(A[22] ^ D3, 61);
00057       const u64bit B10 = rotate_left(A[ 1] ^ D2, 1);
00058       const u64bit B11 = rotate_left(A[ 7] ^ D3, 6);
00059       const u64bit B12 = rotate_left(A[13] ^ D4, 25);
00060       const u64bit B13 = rotate_left(A[19] ^ D0, 8);
00061       const u64bit B14 = rotate_left(A[20] ^ D1, 18);
00062       const u64bit B15 = rotate_left(A[ 4] ^ D0, 27);
00063       const u64bit B16 = rotate_left(A[ 5] ^ D1, 36);
00064       const u64bit B17 = rotate_left(A[11] ^ D2, 10);
00065       const u64bit B18 = rotate_left(A[17] ^ D3, 15);
00066       const u64bit B19 = rotate_left(A[23] ^ D4, 56);
00067       const u64bit B20 = rotate_left(A[ 2] ^ D3, 62);
00068       const u64bit B21 = rotate_left(A[ 8] ^ D4, 55);
00069       const u64bit B22 = rotate_left(A[14] ^ D0, 39);
00070       const u64bit B23 = rotate_left(A[15] ^ D1, 41);
00071       const u64bit B24 = rotate_left(A[21] ^ D2, 2);
00072 
00073       A[ 0] = B00 ^ (~B01 & B02);
00074       A[ 1] = B01 ^ (~B02 & B03);
00075       A[ 2] = B02 ^ (~B03 & B04);
00076       A[ 3] = B03 ^ (~B04 & B00);
00077       A[ 4] = B04 ^ (~B00 & B01);
00078       A[ 5] = B05 ^ (~B06 & B07);
00079       A[ 6] = B06 ^ (~B07 & B08);
00080       A[ 7] = B07 ^ (~B08 & B09);
00081       A[ 8] = B08 ^ (~B09 & B05);
00082       A[ 9] = B09 ^ (~B05 & B06);
00083       A[10] = B10 ^ (~B11 & B12);
00084       A[11] = B11 ^ (~B12 & B13);
00085       A[12] = B12 ^ (~B13 & B14);
00086       A[13] = B13 ^ (~B14 & B10);
00087       A[14] = B14 ^ (~B10 & B11);
00088       A[15] = B15 ^ (~B16 & B17);
00089       A[16] = B16 ^ (~B17 & B18);
00090       A[17] = B17 ^ (~B18 & B19);
00091       A[18] = B18 ^ (~B19 & B15);
00092       A[19] = B19 ^ (~B15 & B16);
00093       A[20] = B20 ^ (~B21 & B22);
00094       A[21] = B21 ^ (~B22 & B23);
00095       A[22] = B22 ^ (~B23 & B24);
00096       A[23] = B23 ^ (~B24 & B20);
00097       A[24] = B24 ^ (~B20 & B21);
00098 
00099       A[0] ^= RC[i];
00100       }
00101    }
00102 
00103 }
00104 
00105 Keccak_1600::Keccak_1600(size_t output_bits) :
00106    output_bits(output_bits),
00107    bitrate(1600 - 2*output_bits),
00108    S(25),
00109    S_pos(0)
00110    {
00111    // We only support the parameters for the SHA-3 proposal
00112 
00113    if(output_bits != 224 && output_bits != 256 &&
00114       output_bits != 384 && output_bits != 512)
00115       throw Invalid_Argument("Keccak_1600: Invalid output length " +
00116                              std::to_string(output_bits));
00117    }
00118 
00119 std::string Keccak_1600::name() const
00120    {
00121    return "Keccak-1600(" + std::to_string(output_bits) + ")";
00122    }
00123 
00124 HashFunction* Keccak_1600::clone() const
00125    {
00126    return new Keccak_1600(output_bits);
00127    }
00128 
00129 void Keccak_1600::clear()
00130    {
00131    zeroise(S);
00132    S_pos = 0;
00133    }
00134 
00135 void Keccak_1600::add_data(const byte input[], size_t length)
00136    {
00137    if(length == 0)
00138       return;
00139 
00140    while(length)
00141       {
00142       size_t to_take = std::min(length, bitrate / 8 - S_pos);
00143 
00144       length -= to_take;
00145 
00146       while(to_take && S_pos % 8)
00147          {
00148          S[S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (S_pos % 8));
00149 
00150          ++S_pos;
00151          ++input;
00152          --to_take;
00153          }
00154 
00155       while(to_take && to_take % 8 == 0)
00156          {
00157          S[S_pos / 8] ^= load_le<u64bit>(input, 0);
00158          S_pos += 8;
00159          input += 8;
00160          to_take -= 8;
00161          }
00162 
00163       while(to_take)
00164          {
00165          S[S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (S_pos % 8));
00166 
00167          ++S_pos;
00168          ++input;
00169          --to_take;
00170          }
00171 
00172       if(S_pos == bitrate / 8)
00173          {
00174          keccak_f_1600(&S[0]);
00175          S_pos = 0;
00176          }
00177       }
00178    }
00179 
00180 void Keccak_1600::final_result(byte output[])
00181    {
00182    std::vector<byte> padding(bitrate / 8 - S_pos);
00183 
00184    padding[0] = 0x01;
00185    padding[padding.size()-1] |= 0x80;
00186 
00187    add_data(&padding[0], padding.size());
00188 
00189    /*
00190    * We never have to run the permutation again because we only support
00191    * limited output lengths
00192    */
00193    for(size_t i = 0; i != output_bits/8; ++i)
00194       output[i] = get_byte(7 - (i % 8), S[i/8]);
00195 
00196    clear();
00197    }
00198 
00199 }