nx_poly1305_test.nx source
↩ module page · 89 lines · 3835 B
1// nx_poly1305_test.nx -- RFC 8439 §2.5.2 KAT for Poly1305.
2//
3// Worked example from the spec:
4// Key (hex): 85d6be7857556d337f4452fe42d506a8
5// 0103808afb0db2fd4abff6af4149f51b
6// Message (ASCII): "Cryptographic Forum Research Group" (34 bytes)
7// Expected tag: a8061dc1305136c6c22b8baf0c0127a9
8//
9// Also exercises poly1305_tag_equal for constant-time tag compare
10// (the function TLS Finished verification must use to avoid a
11// timing side-channel that byte-bisects the tag).
12//
13// expect_exit: 0
14//
15// license_tier: ORIGINAL
16
17import "nx_syscalls.nx"
18import "nx_poly1305.nx"
19
20func main() -> i64 {
21 // ---- 32-byte key = r || s per RFC 8439 §2.5.1 ----
22 let key: *u8 = sys_mmap(64)
23 key[0]=0x85; key[1]=0xd6; key[2]=0xbe; key[3]=0x78
24 key[4]=0x57; key[5]=0x55; key[6]=0x6d; key[7]=0x33
25 key[8]=0x7f; key[9]=0x44; key[10]=0x52; key[11]=0xfe
26 key[12]=0x42; key[13]=0xd5; key[14]=0x06; key[15]=0xa8
27 key[16]=0x01; key[17]=0x03; key[18]=0x80; key[19]=0x8a
28 key[20]=0xfb; key[21]=0x0d; key[22]=0xb2; key[23]=0xfd
29 key[24]=0x4a; key[25]=0xbf; key[26]=0xf6; key[27]=0xaf
30 key[28]=0x41; key[29]=0x49; key[30]=0xf5; key[31]=0x1b
31
32 // ---- 34-byte message "Cryptographic Forum Research Group" ----
33 let msg: *u8 = sys_mmap(64)
34 msg[0]=0x43; msg[1]=0x72; msg[2]=0x79; msg[3]=0x70
35 msg[4]=0x74; msg[5]=0x6f; msg[6]=0x67; msg[7]=0x72
36 msg[8]=0x61; msg[9]=0x70; msg[10]=0x68; msg[11]=0x69
37 msg[12]=0x63; msg[13]=0x20; msg[14]=0x46; msg[15]=0x6f
38 msg[16]=0x72; msg[17]=0x75; msg[18]=0x6d; msg[19]=0x20
39 msg[20]=0x52; msg[21]=0x65; msg[22]=0x73; msg[23]=0x65
40 msg[24]=0x61; msg[25]=0x72; msg[26]=0x63; msg[27]=0x68
41 msg[28]=0x20; msg[29]=0x47; msg[30]=0x72; msg[31]=0x6f
42 msg[32]=0x75; msg[33]=0x70
43
44 let tag: *u8 = sys_mmap(32)
45 poly1305_mac(key, msg, 34, tag)
46
47 // ---- Verify tag byte-for-byte against RFC 8439 §2.5.2 ----
48 if (tag[0] & 0xff) != 0xa8 { return 1 }
49 if (tag[1] & 0xff) != 0x06 { return 2 }
50 if (tag[2] & 0xff) != 0x1d { return 3 }
51 if (tag[3] & 0xff) != 0xc1 { return 4 }
52 if (tag[4] & 0xff) != 0x30 { return 5 }
53 if (tag[5] & 0xff) != 0x51 { return 6 }
54 if (tag[6] & 0xff) != 0x36 { return 7 }
55 if (tag[7] & 0xff) != 0xc6 { return 8 }
56 if (tag[8] & 0xff) != 0xc2 { return 9 }
57 if (tag[9] & 0xff) != 0x2b { return 10 }
58 if (tag[10] & 0xff) != 0x8b { return 11 }
59 if (tag[11] & 0xff) != 0xaf { return 12 }
60 if (tag[12] & 0xff) != 0x0c { return 13 }
61 if (tag[13] & 0xff) != 0x01 { return 14 }
62 if (tag[14] & 0xff) != 0x27 { return 15 }
63 if (tag[15] & 0xff) != 0xa9 { return 16 }
64
65 // ---- Constant-time tag compare: equal to expected = 1 ----
66 let expected: *u8 = sys_mmap(16)
67 expected[0]=0xa8; expected[1]=0x06; expected[2]=0x1d; expected[3]=0xc1
68 expected[4]=0x30; expected[5]=0x51; expected[6]=0x36; expected[7]=0xc6
69 expected[8]=0xc2; expected[9]=0x2b; expected[10]=0x8b; expected[11]=0xaf
70 expected[12]=0x0c; expected[13]=0x01; expected[14]=0x27; expected[15]=0xa9
71 if poly1305_tag_equal(tag, expected) != 1 { return 20 }
72
73 // Flip one bit -> compare returns 0. Defends TLS Finished from
74 // timing-bisect attacks (the lesson from BEAST/Lucky13).
75 expected[7] = expected[7] ^ 1
76 if poly1305_tag_equal(tag, expected) != 0 { return 21 }
77
78 // ---- Empty-message edge case: tag = s mod 2^128 ----
79 let empty: *u8 = sys_mmap(16)
80 let tag_e: *u8 = sys_mmap(16)
81 poly1305_mac(key, empty, 0, tag_e)
82 // Empty message: h = 0, tag = (h + s) mod 2^128 = s.
83 // s bytes 16..31 of key = 01 03 80 8a fb 0d b2 fd 4a bf f6 af 41 49 f5 1b
84 if (tag_e[0] & 0xff) != 0x01 { return 30 }
85 if (tag_e[7] & 0xff) != 0xfd { return 31 }
86 if (tag_e[15] & 0xff) != 0x1b { return 32 }
87
88 return 0
89}