code wiki / (root) / nx_chacha20_poly1305_test.nx

nx_chacha20_poly1305_test.nx source

↩ module page · 185 lines · 7346 B

1// nx_chacha20_poly1305_test.nx -- RFC 8439 ยง2.8.2 AEAD KAT. 2// 3// Sunscreen vector (the canonical AEAD test vector): 4// Plaintext (114 bytes ASCII): 5// "Ladies and Gentlemen of the class of '99: If I could offer 6// you only one tip for the future, sunscreen would be it." 7// AAD (12 bytes): 50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7 8// Key (32 bytes): 80..9f sequential 9// Nonce (12 bytes): 07 00 00 00 40 41 42 43 44 45 46 47 10// Expected ciphertext first 32: 11// d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2 12// a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6 13// Expected tag: 1a e1 0b 59 4f 09 e2 6a 7e 90 2e cb d0 60 06 91 14// 15// Also exercises tamper detection (single-bit flip in tag and in 16// ciphertext both reject) and round-trip (decrypt restores PT). 17// 18// expect_exit: 0 19// 20// license_tier: ORIGINAL 21 22import "nx_syscalls.nx" 23import "nx_chacha20_poly1305.nx" 24 25func main() -> i64 { 26 // ---- Key: 0x80..0x9f sequential ---- 27 let key: *u8 = sys_mmap(64) 28 var ki: i64 = 0 29 while ki < 32 { 30 key[ki] = 0x80 + ki 31 ki = ki + 1 32 } 33 34 // ---- Nonce (12 bytes) ---- 35 let nonce: *u8 = sys_mmap(16) 36 nonce[0]=0x07; nonce[1]=0; nonce[2]=0; nonce[3]=0 37 nonce[4]=0x40; nonce[5]=0x41; nonce[6]=0x42; nonce[7]=0x43 38 nonce[8]=0x44; nonce[9]=0x45; nonce[10]=0x46; nonce[11]=0x47 39 40 // ---- AAD (12 bytes) ---- 41 let aad: *u8 = sys_mmap(16) 42 aad[0]=0x50; aad[1]=0x51; aad[2]=0x52; aad[3]=0x53 43 aad[4]=0xc0; aad[5]=0xc1; aad[6]=0xc2; aad[7]=0xc3 44 aad[8]=0xc4; aad[9]=0xc5; aad[10]=0xc6; aad[11]=0xc7 45 46 // ---- Plaintext: 114-byte Sunscreen quote ---- 47 let pt: *u8 = sys_mmap(256) 48 pt[0]=0x4c; pt[1]=0x61; pt[2]=0x64; pt[3]=0x69 49 pt[4]=0x65; pt[5]=0x73; pt[6]=0x20; pt[7]=0x61 50 pt[8]=0x6e; pt[9]=0x64; pt[10]=0x20; pt[11]=0x47 51 pt[12]=0x65; pt[13]=0x6e; pt[14]=0x74; pt[15]=0x6c 52 pt[16]=0x65; pt[17]=0x6d; pt[18]=0x65; pt[19]=0x6e 53 pt[20]=0x20; pt[21]=0x6f; pt[22]=0x66; pt[23]=0x20 54 pt[24]=0x74; pt[25]=0x68; pt[26]=0x65; pt[27]=0x20 55 pt[28]=0x63; pt[29]=0x6c; pt[30]=0x61; pt[31]=0x73 56 pt[32]=0x73; pt[33]=0x20; pt[34]=0x6f; pt[35]=0x66 57 pt[36]=0x20; pt[37]=0x27; pt[38]=0x39; pt[39]=0x39 58 pt[40]=0x3a; pt[41]=0x20; pt[42]=0x49; pt[43]=0x66 59 pt[44]=0x20; pt[45]=0x49; pt[46]=0x20; pt[47]=0x63 60 pt[48]=0x6f; pt[49]=0x75; pt[50]=0x6c; pt[51]=0x64 61 pt[52]=0x20; pt[53]=0x6f; pt[54]=0x66; pt[55]=0x66 62 pt[56]=0x65; pt[57]=0x72; pt[58]=0x20; pt[59]=0x79 63 pt[60]=0x6f; pt[61]=0x75; pt[62]=0x20; pt[63]=0x6f 64 pt[64]=0x6e; pt[65]=0x6c; pt[66]=0x79; pt[67]=0x20 65 pt[68]=0x6f; pt[69]=0x6e; pt[70]=0x65; pt[71]=0x20 66 pt[72]=0x74; pt[73]=0x69; pt[74]=0x70; pt[75]=0x20 67 pt[76]=0x66; pt[77]=0x6f; pt[78]=0x72; pt[79]=0x20 68 pt[80]=0x74; pt[81]=0x68; pt[82]=0x65; pt[83]=0x20 69 pt[84]=0x66; pt[85]=0x75; pt[86]=0x74; pt[87]=0x75 70 pt[88]=0x72; pt[89]=0x65; pt[90]=0x2c; pt[91]=0x20 71 pt[92]=0x73; pt[93]=0x75; pt[94]=0x6e; pt[95]=0x73 72 pt[96]=0x63; pt[97]=0x72; pt[98]=0x65; pt[99]=0x65 73 pt[100]=0x6e; pt[101]=0x20; pt[102]=0x77; pt[103]=0x6f 74 pt[104]=0x75; pt[105]=0x6c; pt[106]=0x64; pt[107]=0x20 75 pt[108]=0x62; pt[109]=0x65; pt[110]=0x20; pt[111]=0x69 76 pt[112]=0x74; pt[113]=0x2e 77 78 let ct: *u8 = sys_mmap(256) 79 let tag: *u8 = sys_mmap(32) 80 let v: i64 = nx_chacha20_poly1305_encrypt( 81 key, nonce, aad, 12, pt, 114, ct, tag 82 ) 83 if v != NX_AEAD_VERDICT_OK { return 1 } 84 85 // ---- Ciphertext first 32 bytes ---- 86 if (ct[0] & 0xff) != 0xd3 { return 2 } 87 if (ct[1] & 0xff) != 0x1a { return 3 } 88 if (ct[2] & 0xff) != 0x8d { return 4 } 89 if (ct[3] & 0xff) != 0x34 { return 5 } 90 if (ct[4] & 0xff) != 0x64 { return 6 } 91 if (ct[5] & 0xff) != 0x8e { return 7 } 92 if (ct[6] & 0xff) != 0x60 { return 8 } 93 if (ct[7] & 0xff) != 0xdb { return 9 } 94 if (ct[8] & 0xff) != 0x7b { return 10 } 95 if (ct[9] & 0xff) != 0x86 { return 11 } 96 if (ct[10] & 0xff) != 0xaf { return 12 } 97 if (ct[11] & 0xff) != 0xbc { return 13 } 98 if (ct[12] & 0xff) != 0x53 { return 14 } 99 if (ct[13] & 0xff) != 0xef { return 15 } 100 if (ct[14] & 0xff) != 0x7e { return 16 } 101 if (ct[15] & 0xff) != 0xc2 { return 17 } 102 if (ct[16] & 0xff) != 0xa4 { return 18 } 103 if (ct[17] & 0xff) != 0xad { return 19 } 104 if (ct[18] & 0xff) != 0xed { return 20 } 105 if (ct[19] & 0xff) != 0x51 { return 21 } 106 if (ct[20] & 0xff) != 0x29 { return 22 } 107 if (ct[21] & 0xff) != 0x6e { return 23 } 108 if (ct[22] & 0xff) != 0x08 { return 24 } 109 if (ct[23] & 0xff) != 0xfe { return 25 } 110 if (ct[24] & 0xff) != 0xa9 { return 26 } 111 if (ct[25] & 0xff) != 0xe2 { return 27 } 112 if (ct[26] & 0xff) != 0xb5 { return 28 } 113 if (ct[27] & 0xff) != 0xa7 { return 29 } 114 if (ct[28] & 0xff) != 0x36 { return 30 } 115 if (ct[29] & 0xff) != 0xee { return 31 } 116 if (ct[30] & 0xff) != 0x62 { return 32 } 117 if (ct[31] & 0xff) != 0xd6 { return 33 } 118 119 // ---- Last two ciphertext bytes (partial-final-block sanity) ---- 120 if (ct[112] & 0xff) != 0x61 { return 40 } 121 if (ct[113] & 0xff) != 0x16 { return 41 } 122 123 // ---- Tag: all 16 bytes ---- 124 if (tag[0] & 0xff) != 0x1a { return 50 } 125 if (tag[1] & 0xff) != 0xe1 { return 51 } 126 if (tag[2] & 0xff) != 0x0b { return 52 } 127 if (tag[3] & 0xff) != 0x59 { return 53 } 128 if (tag[4] & 0xff) != 0x4f { return 54 } 129 if (tag[5] & 0xff) != 0x09 { return 55 } 130 if (tag[6] & 0xff) != 0xe2 { return 56 } 131 if (tag[7] & 0xff) != 0x6a { return 57 } 132 if (tag[8] & 0xff) != 0x7e { return 58 } 133 if (tag[9] & 0xff) != 0x90 { return 59 } 134 if (tag[10] & 0xff) != 0x2e { return 60 } 135 if (tag[11] & 0xff) != 0xcb { return 61 } 136 if (tag[12] & 0xff) != 0xd0 { return 62 } 137 if (tag[13] & 0xff) != 0x60 { return 63 } 138 if (tag[14] & 0xff) != 0x06 { return 64 } 139 if (tag[15] & 0xff) != 0x91 { return 65 } 140 141 // ---- Round-trip: decrypt(encrypt(pt)) == pt ---- 142 let pt2: *u8 = sys_mmap(256) 143 let v2: i64 = nx_chacha20_poly1305_decrypt( 144 key, nonce, aad, 12, ct, 114, tag, pt2 145 ) 146 if v2 != NX_AEAD_VERDICT_OK { return 70 } 147 var r: i64 = 0 148 while r < 114 { 149 if (pt[r] & 0xff) != (pt2[r] & 0xff) { return 80 + r } 150 r = r + 1 151 } 152 153 // ---- Tampered tag (flip 1 bit) -> TAG_MISMATCH, no decrypt ---- 154 let bad_tag: *u8 = sys_mmap(32) 155 var bt: i64 = 0 156 while bt < 16 { 157 bad_tag[bt] = tag[bt] 158 bt = bt + 1 159 } 160 bad_tag[5] = bad_tag[5] ^ 1 161 let v3: i64 = nx_chacha20_poly1305_decrypt( 162 key, nonce, aad, 12, ct, 114, bad_tag, pt2 163 ) 164 if v3 != NX_AEAD_VERDICT_TAG_MISMATCH { return 220 } 165 166 // ---- Tampered ciphertext (flip 1 bit) -> TAG_MISMATCH ---- 167 let bad_ct: *u8 = sys_mmap(256) 168 var bc: i64 = 0 169 while bc < 114 { 170 bad_ct[bc] = ct[bc] 171 bc = bc + 1 172 } 173 bad_ct[33] = bad_ct[33] ^ 0x80 174 let v4: i64 = nx_chacha20_poly1305_decrypt( 175 key, nonce, aad, 12, bad_ct, 114, tag, pt2 176 ) 177 if v4 != NX_AEAD_VERDICT_TAG_MISMATCH { return 221 } 178 179 // ---- Verdict gate ---- 180 if nx_aead_verdict_is_valid(NX_AEAD_VERDICT_OK) != 1 { return 230 } 181 if nx_aead_verdict_is_valid(NX_AEAD_VERDICT_N) != 0 { return 231 } 182 if nx_aead_verdict_is_valid(0 - 1) != 0 { return 232 } 183 184 return 0 185}