Skip to content

Instantly share code, notes, and snippets.

@resilar
Last active May 6, 2023 04:34
Show Gist options
  • Save resilar/6eaeb71fcf0bb3c3e4b55c8fb9bcc1b2 to your computer and use it in GitHub Desktop.
Save resilar/6eaeb71fcf0bb3c3e4b55c8fb9bcc1b2 to your computer and use it in GitHub Desktop.
poly1305 implementation in C
#include <stddef.h>
#include <stdint.h>
#define LOAD32_LE(p) \
( ((uint32_t)((p)[0]) << 0) \
| ((uint32_t)((p)[1]) << 8) \
| ((uint32_t)((p)[2]) << 16) \
| ((uint32_t)((p)[3]) << 24) \
)
#define STORE32_LE(p, v) \
(p)[0] = ((v) >> 0) & 0xFF; \
(p)[1] = ((v) >> 8) & 0xFF; \
(p)[2] = ((v) >> 16) & 0xFF; \
(p)[3] = ((v) >> 24) & 0xFF;
void poly1305(const uint8_t *msg, size_t n,
const uint8_t key[32], uint8_t tag[16])
{
uint64_t d0, d1, d2, d3, d4;
uint32_t h0, h1, h2, h3, h4;
uint32_t r0, r1, r2, r3, r4;
uint32_t s1, s2, s3, s4;
h0 = h1 = h2 = h3 = h4 = 0;
r0 = (LOAD32_LE(key + 0) >> 0) & 0x03FFFFFF;
r1 = (LOAD32_LE(key + 3) >> 2) & 0x03FFFF03; s1 = r1 * 5;
r2 = (LOAD32_LE(key + 6) >> 4) & 0x03FFC0FF; s2 = r2 * 5;
r3 = (LOAD32_LE(key + 9) >> 6) & 0x03F03FFF; s3 = r3 * 5;
r4 = (LOAD32_LE(key + 12) >> 8) & 0x000FFFFF; s4 = r4 * 5;
while (n >= 16) {
h4 += 0x01000000;
process_block:
h0 += (LOAD32_LE(msg + 0) >> 0) & 0x03FFFFFF;
h1 += (LOAD32_LE(msg + 3) >> 2) & 0x03FFFFFF;
h2 += (LOAD32_LE(msg + 6) >> 4) & 0x03FFFFFF;
h3 += (LOAD32_LE(msg + 9) >> 6) & 0x03FFFFFF;
h4 += (LOAD32_LE(msg + 12) >> 8);
#define MUL(a,b) ((uint64_t)(a) * (b))
d0 = MUL(h0,r0) + MUL(h1,s4) + MUL(h2,s3) + MUL(h3,s2) + MUL(h4,s1);
d1 = MUL(h0,r1) + MUL(h1,r0) + MUL(h2,s4) + MUL(h3,s3) + MUL(h4,s2);
d2 = MUL(h0,r2) + MUL(h1,r1) + MUL(h2,r0) + MUL(h3,s4) + MUL(h4,s3);
d3 = MUL(h0,r3) + MUL(h1,r2) + MUL(h2,r1) + MUL(h3,r0) + MUL(h4,s4);
d4 = MUL(h0,r4) + MUL(h1,r3) + MUL(h2,r2) + MUL(h3,r1) + MUL(h4,r0);
#undef MUL
h0 = d0 & 0x03FFFFFF; d1 += (d0 >> 26);
h1 = d1 & 0x03FFFFFF; d2 += (d1 >> 26);
h2 = d2 & 0x03FFFFFF; d3 += (d2 >> 26);
h3 = d3 & 0x03FFFFFF; d4 += (d3 >> 26);
h4 = d4 & 0x03FFFFFF; h0 += (uint32_t)(d4 >> 26) * 5;
msg += 16;
n -= 16;
}
if (n) {
size_t i;
for (i = 0; i < n; tag[i] = msg[i], i++);
for (tag[i++] = 1; i < 16; tag[i++] = 0);
msg = tag;
n = 16;
goto process_block;
}
r0 = (h0 + 5) >> 26;
r1 = (h1 + r0) >> 26;
r2 = (h2 + r1) >> 26;
r3 = (h3 + r2) >> 26;
r4 = (h4 + r3) >> 26;
h0 += r4 * 5;
d1 = (uint64_t)LOAD32_LE(key + 16) + (h0 >> 0) + (h1 << 26);
d2 = (uint64_t)LOAD32_LE(key + 20) + (h1 >> 6) + (h2 << 20) + (d1 >> 32);
d3 = (uint64_t)LOAD32_LE(key + 24) + (h2 >> 12) + (h3 << 14) + (d2 >> 32);
d4 = (uint64_t)LOAD32_LE(key + 28) + (h3 >> 18) + (h4 << 8) + (d3 >> 32);
s1 = d1; STORE32_LE(tag + 0, s1);
s2 = d2; STORE32_LE(tag + 4, s2);
s3 = d3; STORE32_LE(tag + 8, s3);
s4 = d4; STORE32_LE(tag + 12, s4);
}
int poly1305_tagcmp(const uint8_t tag1[16], const uint8_t tag2[16])
{
uint8_t d = 0;
d |= tag1[ 0] ^ tag2[ 0];
d |= tag1[ 1] ^ tag2[ 1];
d |= tag1[ 2] ^ tag2[ 2];
d |= tag1[ 3] ^ tag2[ 3];
d |= tag1[ 4] ^ tag2[ 4];
d |= tag1[ 5] ^ tag2[ 5];
d |= tag1[ 6] ^ tag2[ 6];
d |= tag1[ 7] ^ tag2[ 7];
d |= tag1[ 8] ^ tag2[ 8];
d |= tag1[ 9] ^ tag2[ 9];
d |= tag1[10] ^ tag2[10];
d |= tag1[11] ^ tag2[11];
d |= tag1[12] ^ tag2[12];
d |= tag1[13] ^ tag2[13];
d |= tag1[14] ^ tag2[14];
d |= tag1[15] ^ tag2[15];
return (int)d;
}
/* poly1305 unit test harness */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern void poly1305(const uint8_t *msg, size_t n,
const uint8_t key[32], uint8_t tag[16]);
struct { const char *key; const char *msg; const char *tag; } tests[] = {
{
"0000000000000000000000000000000000000000000000000000000000000000",
"",
"00000000000000000000000000000000"
},
{
"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
"",
"00000000000000000000000000000000"
},
{
"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
"",
"36e5f6b5c5e06070f0efca96227a863e"
},
{
"79207375626d697373696f6e20746f2036e5f6b5c5e06070f0efca96227a863e",
"",
"36e5f6b5c5e06070f0efca96227a863e"
},
{
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000"
},
{
"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
"416e79207375626d697373696f6e20746f20746865204945544620696e74656e"
"6465642062792074686520436f6e7472696275746f7220666f72207075626c69"
"636174696f6e20617320616c6c206f722070617274206f6620616e2049455446"
"20496e7465726e65742d4472616674206f722052464320616e6420616e792073"
"746174656d656e74206d6164652077697468696e2074686520636f6e74657874"
"206f6620616e204945544620616374697669747920697320636f6e7369646572"
"656420616e20224945544620436f6e747269627574696f6e222e205375636820"
"73746174656d656e747320696e636c756465206f72616c2073746174656d656e"
"747320696e20494554462073657373696f6e732c2061732077656c6c20617320"
"7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361"
"74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c"
"207768696368206172652061646472657373656420746f",
"36e5f6b5c5e06070f0efca96227a863e"
},
{
"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
"416e79207375626d697373696f6e20746f20746865204945544620696e74656e"
"6465642062792074686520436f6e7472696275746f7220666f72207075626c69"
"636174696f6e20617320616c6c206f722070617274206f6620616e2049455446"
"20496e7465726e65742d4472616674206f722052464320616e6420616e792073"
"746174656d656e74206d6164652077697468696e2074686520636f6e74657874"
"206f6620616e204945544620616374697669747920697320636f6e7369646572"
"656420616e20224945544620436f6e747269627574696f6e222e205375636820"
"73746174656d656e747320696e636c756465206f72616c2073746174656d656e"
"747320696e20494554462073657373696f6e732c2061732077656c6c20617320"
"7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361"
"74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c"
"207768696368206172652061646472657373656420746f",
"f3477e7cd95417af89a6b8794c310cf0"
},
{
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"2754776173206272696c6c69672c20616e642074686520736c6974687920746f"
"7665730a446964206779726520616e642067696d626c6520696e207468652077"
"6162653a0a416c6c206d696d737920776572652074686520626f726f676f7665"
"732c0a416e6420746865206d6f6d65207261746873206f757467726162652e",
"4541669a7eaaee61e708dc7cbcc5eb62"
},
{
"0200000000000000000000000000000000000000000000000000000000000000",
"ffffffffffffffffffffffffffffffff",
"03000000000000000000000000000000"
},
{
"0100000000000000000000000000000000000000000000000000000000000000",
"fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff"
"11000000000000000000000000000000",
"05000000000000000000000000000000"
},
{
"0100000000000000000000000000000000000000000000000000000000000000",
"fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe"
"01010101010101010101010101010101",
"00000000000000000000000000000000"
},
{
"0200000000000000000000000000000000000000000000000000000000000000",
"fdffffffffffffffffffffffffffffff",
"faffffffffffffffffffffffffffffff"
},
{
"0100000000000000040000000000000000000000000000000000000000000000",
"e33594d7505e43b900000000000000003394d7505e4379cd0100000000000000"
"0000000000000000000000000000000001000000000000000000000000000000",
"14000000000000005500000000000000"
},
{
"0100000000000000040000000000000000000000000000000000000000000000",
"e33594d7505e43b900000000000000003394d7505e4379cd0100000000000000"
"00000000000000000000000000000000",
"13000000000000000000000000000000"
},
{
"85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
"43727970746f6772617068696320466f72756d2052657365617263682047726f"
"7570",
"a8061dc1305136c6c22b8baf0c0127a9"
},
{
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef",
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
"0ee1c16bb73f0f4fd19881753c01cdbe"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9",
"5154ad0d2cb26e01274fc51148491f1b"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af",
"812059a5da198637cac7c4a631bee466"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67",
"5b88d7f6228b11e2e28579a5c0c1f761"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
"bbb613b2b6d753ba07395b916aaece15"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24",
"c794d7057d1778c4bbee0a39b3d97342"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
"ffbcb9b371423152d7fca5ad042fbaa9"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
"812059a5da198637cac7c4a631bee466",
"069ed6b8ef0f207b3e243bb1019fe632"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
"812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761",
"cca339d9a45fa2368c2c68b3a4179133"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
"812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761"
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
"53f6e828a2f0fe0ee815bf0bd5841a34"
},
{
"12976a08c4426d0ce8a82407c4f4820780f8c20aa71202d1e29179cbcb555a57",
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
"812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761"
"ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
"990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
"48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
"663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
"812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761",
"b846d44e9bbd53cedffbfbb6b7fa4933"
},
{
"ad628107e8351d0f2c231a05dc4a410600000000000000000000000000000000",
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"07145a4c02fe5fa32036de68fabe9066"
},
{
"95d5c005503e510d8cd0aa072c4a4d066eabc52d11653df47fbf63ab198bcc26",
"842364e156336c0998b933a6237726180d9e3fdcbde4cd5d17080fc3beb49614"
"d7122c037463ff104d73f19c12704628d417c4c54a3fe30d3c3d7714382d43b0"
"382a50a5dee54be844b076e8df88201a1cd43b90eb21643fa96f39b518aa8340"
"c942ff3c31baf7c9bdbf0f31ae3fa096bf8c63030609829fe72e179824890bc8"
"e08c315c1cce2a83144dbbff09f74e3efc770b54d0984a8f19b14719e6363564"
"1d6b1eedf63efbf080e1783d32445412114c20de0b837a0dfa33d6b82825fff4"
"4c9a70ea54ce47f07df698e6b03323b53079364a5fc3e9dd034392bdde86dccd"
"da94321c5e44060489336cb65bf3989c36f7282c2f5d2b882c171e74",
"f248312e578d9d58f8b7bb4d19105431"
},
{
"000102030405060708090a0b0c0d0e0f00000000000000000000000000000000",
"248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd"
"2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e8"
"74cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c"
"8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936a"
"ff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a37"
"09894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901f"
"de7db79fa1818c11336dbc07244a40eb",
"bc939bc5281480fa99c6d68c258ec42f"
},
{
"746869732069732033322d62797465206b657920666f7220506f6c7931333035",
"48656c6c6f20776f726c6421",
"a6f745008f81c916a20dcc74eef2b2f0"
},
{
"746869732069732033322d62797465206b657920666f7220506f6c7931333035",
"0000000000000000000000000000000000000000000000000000000000000000",
"49ec78090e481ec6c26b33b91ccc0307"
},
{
"2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea",
"89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a9"
"1c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a62033427"
"0372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f1"
"41300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595",
"c85d15ed44c378d6b00e23064c7bcd51"
},
{
"99e5822dd4173c995e3dae0ddefb97743fde3b080134b39f76e9bf8d0e88d546",
"000000000000000b170303020000000006db1f1f368d696a810a349c0c714c9a"
"5e7850c2407d721acded95e018d7a85266a6e1289cdb4aeb18da5ac8a2b0026d"
"24a59ad485227f3eaedbb2e7e35e1c66cd60f9abf716dcc9ac42682dd7dab287"
"a7024c4eefc321cc0574e16793e37cec03c5bda42b54c114a80b57af26416c7b"
"e742005e20855c73e21dc8e2edc9d435cb6f6059280011c270b71570051c1c9b"
"3052126620bc1e2730fa066c7a509d53c60e5ae1b40aa6e39e49669228c90eec"
"b4a50db32a50bc49e90b4f4b359a1dfd11749cd3867fcf2fb7bb6cd4738f6a4a"
"d6f7ca5058f7618845af9f020f6c3b967b8f4cd4a91e2813b507ae66f2d35c18"
"284f7292186062e10fd5510d18775351ef334e7634ab4743f5b68f49adcab384"
"d3fd75f7390f4006ef2a295c8c7a076ad54546cd25d2107fbe1436c840924aae"
"be5b370893cd63d1325b8616fc4810886bc152c53221b6df373119393255ee72"
"bcaa880174f1717f9184fa91646f17a24ac55d16bfddca9581a92eda479201f0"
"edbf633600d6066d1ab36d5d2415d71351bbcd608a25108d25641992c1f26c53"
"1cf9f90203bc4cc19f5927d834b0a47116d3884bbb164b8ec883d1ac832e56b3"
"918a98601a08d171881541d594db399c6ae6151221745aec814c45b0b05b5654"
"36fd6f137aa10a0c0b643761dbd6f9a9dcb99b1a6e690854ce0769cde39761d8"
"2fcdec15f0d92d7d8e94ade8eb83fbe0",
"2637408fe13086ea73f971e3425e2820"
},
{
"7f1b02640000000000000000000000000000000000000000cccccccccccccccc",
"cccccccccccccccccccccccccccccccccccccccccccccccccc80cccccccccccc"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccecccccc"
"ccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccc"
"cccccccccce3cccccccccccccccccccccccccccccccccccccccccccccccccccc"
"ccccccccaccccccccccccccccccccce6cccccccccc000000afcccccccccccccc"
"ccccfffffff50000000000000000000000000000000000000000000000000000"
"00ffffffe7000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000719205a8521d"
"fc",
"8559b876eceed66eb37798c0457baff9"
},
{
"e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0000000000"
"00000000800264",
"00bd1258978e205444c9aaaa82006fed"
},
{
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
"02fc",
"06120c0c0c0c0c0c0c0c0c0c0c0c0c0c"
},
{
"00ff000000000000000000000000000000000000001e00000000000000007b7b",
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"
"7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"
"7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b"
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b"
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"
"7b6e7b001300000000b300000000000000000000000000000000000000000000"
"f20000000000000000000000000000000000002000efff000900000000000000"
"0000000000100000000009000000640000000000000000000000001300000000"
"b300000000000000000000000000000000000000000000f20000000000000000"
"000000000000000000002000efff00090000000000000000007a000010000000"
"000900000064000000000000000000000000000000000000000000000000fc",
"33205bbf9e9f8f7212ab9e2ab9b7e4a5"
},
{
"0000007f0000007f01000020000000000000cf77777777777777777777777777",
"7777777777777777777777777777777777777777777777777777777777777777"
"7777777777777777777777777777777777777777777777777777777777777777"
"777777777777777777777777ffffffe9e9acacacacacacacacacacac0000acac"
"ec0100acacac2caca2acacacacacacacacacacac64f2",
"02ee7c8c546ddeb1a467e4c3981158b9"
},
{
"eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880",
"8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
"c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
"b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
"99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74"
"e355a5",
"f3ffc7703f9400e52a7dfb4b3d3305d9"
},
/* custom tests for interesting edge cases */
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ffffffffffffffffffffffffffffffff",
"fbffff17faffff17faffff17faffff17"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"900fe32bc15fa8d7bca8efe4c7e37eb1"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"f8aaa2240c6c4b3a9de57476ea806eb4"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"c30c8c6a3af35fc6645a7e3a51df3f04"
},
{
"1111111111111111111111111111111122222222222222222222222222222222",
"00000000000000000000000000000000",
"76777723767777237677772376777723"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"811000fcffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"9438472b0afb6a59fff6685d07b47057"
}
};
int decode_xdigit(char xdigit)
{
if ('0' <= xdigit && xdigit <= '9') {
xdigit -= '0';
} else if ('A' <= xdigit && xdigit <= 'F') {
xdigit -= 'A';
xdigit += 10;
} else if ('a' <= xdigit && xdigit <= 'f') {
xdigit -= 'a';
xdigit += 10;
} else {
fprintf(stderr, "bad xdigit: %c\n", xdigit);
abort();
}
return xdigit;
}
size_t decode_hex(const unsigned char *in, void *out)
{
size_t len = 0;
for (len = 0; in[2*len] && in[2*len+1]; len++) {
int hi = decode_xdigit(in[2*len]);
int lo = decode_xdigit(in[2*len + 1]);
if (out) ((unsigned char *)out)[len] = (hi << 4) + lo;
}
if (in[2*len]) {
fprintf(stderr, "odd length hex input string: %s\n", in);
abort();
}
return len;
}
size_t encode_hex(const void *in, size_t len, unsigned char *out)
{
static const char pool[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
size_t i;
if (!len) len = strlen((char *)in);
for (i = 0; i < len; i++) {
*out++ = pool[(((unsigned char *)in)[i] >> 4) & 0x0F];
*out++ = pool[((unsigned char *)in)[i] & 0x0F];
}
return i;
}
void self_tests()
{
size_t i;
unsigned char key[32], msg[4096 * 10], tag[16];
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
size_t len;
unsigned char out[16];
unsigned char hex[32];
fprintf(stdout, "TEST %02u: ", (unsigned int)i);
fflush(stdout);
len = decode_hex((unsigned char *)tests[i].msg, msg);
if (len > sizeof(msg)) {
fprintf(stderr, "message length %lu exceeds limit %lu\n",
(unsigned long)len, (unsigned long)sizeof(msg));
abort();
}
decode_hex((unsigned char *)tests[i].key, key);
decode_hex((unsigned char *)tests[i].tag, tag);
poly1305((uint8_t *)msg, len, (uint8_t *)key, (uint8_t *)out);
encode_hex(out, 16, hex);
fprintf(stdout, "%.32s", hex);
fprintf(stdout, " %s\n", !memcmp(tag, out, 16) ? "OK" : "FAIL");
fflush(stdout);
}
}
static unsigned char *read_input_message(FILE *in, size_t *length)
{
void *buf;
unsigned char *msg;
size_t capacity, *size, tmp;
/* Read using a dynamic buffer (to support non-seekable streams) */
if (!(buf = malloc((capacity = 1024))))
return NULL;
msg = (unsigned char *)buf;
*(size = length ? length : &tmp) = 0;
while (!feof(in)) {
if (*size == capacity) {
buf = realloc(buf, (capacity = capacity*2));
if (!buf) goto fail;
msg = (unsigned char *)buf;
}
*size += fread(&msg[*size], sizeof(unsigned char), capacity-*size, in);
if (ferror(in))
goto fail;
}
/* Truncate */
if (0 < *size && *size < capacity && (buf = realloc(buf, *size)))
msg = (unsigned char *)buf;
return msg;
fail:
free((void *)msg);
return NULL;
}
int main(int argc, char *argv[])
{
char *end;
long reps = 1;
if (argc != 2 && argc != 3) {
self_tests();
} else if (argc == 2 || ((reps = strtol(argv[2], &end, 0)) > 0 && !*end)) {
size_t len;
unsigned char *key;
unsigned char *msg;
unsigned char *input;
unsigned char tag[16];
unsigned char hex[64];
if (!strcmp(argv[1], "-")) {
input = read_input_message(stdin, &len);
} else {
FILE *in;
if (!(in = fopen(argv[1], "rb"))) {
fprintf(stderr, "opening '%s' for read failed\n", argv[1]);
return 1;
}
input = read_input_message(in, &len);
fclose(in);
}
if (input == NULL) {
fprintf(stderr, "reading file '%s' failed\n", argv[1]);
return 2;
}
if (len < 32) {
free(input);
fprintf(stderr, "file '%s' shorter than 32 key bytes\n", argv[1]);
return 2;
}
key = input;
msg = input + 32;
encode_hex(key, 32, hex);
fprintf(stderr, "Poly1305(%s, len=%lu, key=%.64s, reps=%ld)\n",
argv[1], (unsigned long)(len - 32), hex, reps);
fflush(stderr);
do {
poly1305((uint8_t *)msg, len - 32, (uint8_t *)key, (uint8_t *)tag);
} while (--reps > 0);
encode_hex(tag, 16, hex);
printf("%.32s\n", hex);
fflush(stdout);
free(input);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment