123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /**
- This code is licensed under the MCGSI Public License
- Copyright 2018 Jeff Becker
- Kovri go write your own code
- */
- #ifndef LIBI2PD_POLY1305_H
- #define LIBI2PD_POLY1305_H
- #include <cstdint>
- #include <cstring>
- #include "Crypto.h"
- #if !OPENSSL_AEAD_CHACHA20_POLY1305
- namespace i2p
- {
- namespace crypto
- {
- const std::size_t POLY1305_DIGEST_BYTES = 16;
- const std::size_t POLY1305_DIGEST_DWORDS = 4;
- const std::size_t POLY1305_KEY_BYTES = 32;
- const std::size_t POLY1305_KEY_DWORDS = 8;
- const std::size_t POLY1305_BLOCK_BYTES = 16;
- namespace poly1305
- {
- struct LongBlock
- {
- unsigned long data[17];
- operator unsigned long * ()
- {
- return data;
- }
- };
- struct Block
- {
- unsigned char data[17];
- void Zero()
- {
- memset(data, 0, sizeof(data));
- }
- operator uint8_t * ()
- {
- return data;
- }
- Block & operator += (const Block & other)
- {
- unsigned short u;
- unsigned int i;
- for(u = 0, i = 0; i < 17; i++)
- {
- u += (unsigned short) data[i] + (unsigned short) other.data[i];
- data[i] = (unsigned char) u & 0xff;
- u >>= 8;
- }
- return *this;
- }
- Block & operator %=(const LongBlock & other)
- {
- unsigned long u;
- unsigned int i;
- u = 0;
- for (i = 0; i < 16; i++) {
- u += other.data[i];
- data[i] = (unsigned char)u & 0xff;
- u >>= 8;
- }
- u += other.data[16];
- data[16] = (unsigned char)u & 0x03;
- u >>= 2;
- u += (u << 2);
- for (i = 0; i < 16; i++) {
- u += data[i];
- data[i] = (unsigned char)u & 0xff;
- u >>= 8;
- }
- data[16] += (unsigned char)u;
- return *this;
- }
- Block & operator = (const Block & other)
- {
- memcpy(data, other.data, sizeof(data));
- return *this;
- }
- Block & operator ~ ()
- {
- static const Block minusp = {
- 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xfc
- };
- Block orig;
- unsigned char neg;
- unsigned int i;
- orig = *this;
- *this += minusp;
- neg = -(data[16] >> 7);
- for(i = 0; i < 17; i++)
- data[i] ^= neg & (orig.data[i] ^ data[i]);
- return *this;
- }
- void PutKey(const uint64_t * key_l)
- {
- const uint8_t * key = (const uint8_t*) key_l;
- data[0] = key[0] & 0xff;
- data[1] = key[1] & 0xff;
- data[2] = key[2] & 0xff;
- data[3] = key[3] & 0x0f;
- data[4] = key[4] & 0xfc;
- data[5] = key[5] & 0xff;
- data[6] = key[6] & 0xff;
- data[7] = key[7] & 0x0f;
- data[8] = key[8] & 0xfc;
- data[9] = key[9] & 0xff;
- data[10] = key[10] & 0xff;
- data[11] = key[11] & 0x0f;
- data[12] = key[12] & 0xfc;
- data[13] = key[13] & 0xff;
- data[14] = key[14] & 0xff;
- data[15] = key[15] & 0x0f;
- data[16] = 0;
- }
- template<typename Int_t>
- void Put(const Int_t * d, uint8_t last=0)
- {
- memcpy(data, d, 16);
- data[16] = last;
- }
- };
- struct Buffer
- {
- uint8_t data[POLY1305_BLOCK_BYTES];
- operator uint8_t * ()
- {
- return data;
- }
- };
- }
- struct Poly1305
- {
- Poly1305(const uint64_t * key)
- {
- m_Leftover = 0;
- m_H.Zero();
- m_Final = 0;
- m_R.PutKey(key);
- m_Pad.Put(key + 2);
- }
- void Update(const uint8_t * buf, size_t sz)
- {
- // process leftover
- if(m_Leftover)
- {
- size_t want = POLY1305_BLOCK_BYTES - m_Leftover;
- if(want > sz) want = sz;
- memcpy(m_Buffer + m_Leftover, buf, want);
- sz -= want;
- buf += want;
- m_Leftover += want;
- if(m_Leftover < POLY1305_BLOCK_BYTES) return;
- Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
- m_Leftover = 0;
- }
- // process blocks
- if(sz >= POLY1305_BLOCK_BYTES)
- {
- size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1));
- Blocks(buf, want);
- buf += want;
- sz -= want;
- }
- // leftover
- if(sz)
- {
- memcpy(m_Buffer+m_Leftover, buf, sz);
- m_Leftover += sz;
- }
- }
- void Blocks(const uint8_t * buf, size_t sz)
- {
- const unsigned char hi = m_Final ^ 1;
- while (sz >= POLY1305_BLOCK_BYTES) {
- unsigned long u;
- unsigned int i, j;
- m_Msg.Put(buf, hi);
- /* h += m */
- m_H += m_Msg;
- /* h *= r */
- for (i = 0; i < 17; i++) {
- u = 0;
- for (j = 0; j <= i ; j++) {
- u += (unsigned short)m_H.data[j] * m_R.data[i - j];
- }
- for (j = i + 1; j < 17; j++) {
- unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j];
- v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */
- u += v;
- }
- m_HR[i] = u;
- }
- /* (partial) h %= p */
- m_H %= m_HR;
- buf += POLY1305_BLOCK_BYTES;
- sz -= POLY1305_BLOCK_BYTES;
- }
- }
- void Finish(uint64_t * out)
- {
- // process leftovers
- if(m_Leftover)
- {
- size_t idx = m_Leftover;
- m_Buffer[idx++] = 1;
- for(; idx < POLY1305_BLOCK_BYTES; idx++)
- m_Buffer[idx] = 0;
- m_Final = 1;
- Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
- }
- // freeze H
- ~m_H;
- // add pad
- m_H += m_Pad;
- // copy digest
- memcpy(out, m_H, 16);
- }
- size_t m_Leftover;
- poly1305::Buffer m_Buffer;
- poly1305::Block m_H;
- poly1305::Block m_R;
- poly1305::Block m_Pad;
- poly1305::Block m_Msg;
- poly1305::LongBlock m_HR;
- uint8_t m_Final;
- };
- void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
- }
- }
- #endif
- #endif
|