1% Tests for RFC5925 TCP Authentication Option (TCP-AO) 2~ tcp tcpao 3# Some data from https://datatracker.ietf.org/doc/html/draft-touch-tcpm-ao-test-vectors-02 4 5+ Test Utilities 6= Test Utilities 7 8# Tolerate all whitespace like py37+ bytes.fromhex 9def fromhex(hex): 10 return bytes(bytearray.fromhex(hex.replace(" ", "").replace("\n", ""))) 11 12+ TCP-AO Test Vectors 13= TCP-AO Test Vectors Utilities 14from scapy.contrib import tcpao 15master_key = b"testvector" 16client_keyid = 61 17server_keyid = 84 18 19def check( 20 packet_hex, 21 traffic_key_hex, 22 mac_hex, 23 src_isn, 24 dst_isn, 25 include_options=True, 26 alg_name="HMAC-SHA-1-96", 27 sne=0, 28 ): 29 packet_bytes = fromhex(packet_hex) 30 # sanity check for ip version 31 ipv = orb(packet_bytes[0]) >> 4 32 if ipv == 4: 33 p = IP(fromhex(packet_hex)) 34 assert p[IP].proto == socket.IPPROTO_TCP 35 elif ipv == 6: 36 p = IPv6(fromhex(packet_hex)) 37 assert p[IPv6].nh == socket.IPPROTO_TCP 38 else: 39 raise ValueError("bad ipv={}".format(ipv)) 40 # sanity check for seq/ack in SYN/ACK packets 41 if p[TCP].flags.S and p[TCP].flags.A is False: 42 assert p[TCP].seq == src_isn 43 assert p[TCP].ack == 0 44 if p[TCP].flags.S and p[TCP].flags.A: 45 assert p[TCP].seq == src_isn 46 assert p[TCP].ack == dst_isn + 1 47 # check option bytes in header 48 opt = get_tcpao(p[TCP]) 49 assert opt is not None 50 assert opt.keyid in [client_keyid, server_keyid] 51 assert opt.rnextkeyid in [client_keyid, server_keyid] 52 assert opt.mac == fromhex(mac_hex), "match parsed mac" 53 # check traffic key 54 alg = get_alg(alg_name) 55 context_bytes = tcpao.build_context_from_packet(p, src_isn, dst_isn) 56 traffic_key = alg.kdf(master_key, context_bytes) 57 assert traffic_key == fromhex(traffic_key_hex), "match traffic key" 58 # check mac 59 message_bytes = tcpao.build_message_from_packet( 60 p, include_options=include_options, sne=sne 61 ) 62 mac = alg.mac(traffic_key, message_bytes) 63 assert mac == fromhex(mac_hex), "match computed mac" 64 65= TCP-AO Test Vector 4.1.1: SHA-1 Send Syn 66client_isn_41x = 0xFBFBAB5A 67server_isn_41x = 0x11C14261 68 69check( 70 """ 71 45 e0 00 4c dd 0f 40 00 ff 06 bf 6b 0a 0b 0c 0d 72 ac 1b 1c 1d e9 d7 00 b3 fb fb ab 5a 00 00 00 00 73 e0 02 ff ff ca c4 00 00 02 04 05 b4 01 03 03 08 74 04 02 08 0a 00 15 5a b7 00 00 00 00 1d 10 3d 54 75 2e e4 37 c6 f8 ed e6 d7 c4 d6 02 e7 76 """, 77 "6d 63 ef 1b 02 fe 15 09 d4 b1 40 27 07 fd 7b 04 16 ab b7 4f", 78 "2e e4 37 c6 f8 ed e6 d7 c4 d6 02 e7", 79 client_isn_41x, 80 0, 81) 82 83= TCP-AO Test Vector 4.1.2 SHA-1 Recv Syn-Ack 84check( 85 """ 86 45 e0 00 4c 65 06 40 00 ff 06 37 75 ac 1b 1c 1d 87 0a 0b 0c 0d 00 b3 e9 d7 11 c1 42 61 fb fb ab 5b 88 e0 12 ff ff 37 76 00 00 02 04 05 b4 01 03 03 08 89 04 02 08 0a 84 a5 0b eb 00 15 5a b7 1d 10 54 3d 90 ee ab 0f e2 4c 30 10 81 51 16 b3 be 91 """, 92 "d9 e2 17 e4 83 4a 80 ca 2f 3f d8 de 2e 41 b8 e6 79 7f ea 96", 93 "ee ab 0f e2 4c 30 10 81 51 16 b3 be", 94 server_isn_41x, 95 client_isn_41x, 96) 97 98= TCP-AO Test Vector 4.1.3 SHA-1 Send Other 99check( 100 """ 101 45 e0 00 87 36 a1 40 00 ff 06 65 9f 0a 0b 0c 0d 102 ac 1b 1c 1d e9 d7 00 b3 fb fb ab 5b 11 c1 42 62 103 c0 18 01 04 a1 62 00 00 01 01 08 0a 00 15 5a c1 104 84 a5 0b eb 1d 10 3d 54 70 64 cf 99 8c c6 c3 15 105 c2 c2 e2 bf ff ff ff ff ff ff ff ff ff ff ff ff 106 ff ff ff ff 00 43 01 04 da bf 00 b4 0a 0b 0c 0d 107 26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02 108 00 02 02 42 00 02 06 41 04 00 00 da bf 02 08 40 109 06 00 64 00 01 01 00 110 """, 111 "d2 e5 9c 65 ff c7 b1 a3 93 47 65 64 63 b7 0e dc 24 a1 3d 71", 112 "70 64 cf 99 8c c6 c3 15 c2 c2 e2 bf", 113 client_isn_41x, 114 server_isn_41x, 115) 116 117= TCP-AO Test Vector 4.1.4 SHA-1 Recv Other 118check( 119 """ 120 45 e0 00 87 1f a9 40 00 ff 06 7c 97 ac 1b 1c 1d 121 0a 0b 0c 0d 00 b3 e9 d7 11 c1 42 62 fb fb ab 9e 122 c0 18 01 00 40 0c 00 00 01 01 08 0a 84 a5 0b f5 123 00 15 5a c1 1d 10 54 3d a6 3f 0e cb bb 2e 63 5c 124 95 4d ea c7 ff ff ff ff ff ff ff ff ff ff ff ff 125 ff ff ff ff 00 43 01 04 da c0 00 b4 ac 1b 1c 1d 126 26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02 127 00 02 02 42 00 02 06 41 04 00 00 da c0 02 08 40 128 06 00 64 00 01 01 00 129 """, 130 "d9 e2 17 e4 83 4a 80 ca 2f 3f d8 de 2e 41 b8 e6 79 7f ea 96", 131 "a6 3f 0e cb bb 2e 63 5c 95 4d ea c7", 132 server_isn_41x, 133 client_isn_41x, 134) 135 136= TCP-AO Test Vector 4.2.1 137client_isn_42x = 0xCB0EFBEE 138server_isn_42x = 0xACD5B5E1 139check( 140 """ 141 45 e0 00 4c 53 99 40 00 ff 06 48 e2 0a 0b 0c 0d 142 ac 1b 1c 1d ff 12 00 b3 cb 0e fb ee 00 00 00 00 143 e0 02 ff ff 54 1f 00 00 02 04 05 b4 01 03 03 08 144 04 02 08 0a 00 02 4c ce 00 00 00 00 1d 10 3d 54 145 80 af 3c fe b8 53 68 93 7b 8f 9e c2 146 """, 147 "30 ea a1 56 0c f0 be 57 da b5 c0 45 22 9f b1 0a 42 3c d7 ea", 148 "80 af 3c fe b8 53 68 93 7b 8f 9e c2", 149 client_isn_42x, 150 0, 151 include_options=False, 152) 153 154= TCP-AO Test Vector 4.2.2 155check( 156 """ 157 45 e0 00 4c 32 84 40 00 ff 06 69 f7 ac 1b 1c 1d 158 0a 0b 0c 0d 00 b3 ff 12 ac d5 b5 e1 cb 0e fb ef 159 e0 12 ff ff 38 8e 00 00 02 04 05 b4 01 03 03 08 160 04 02 08 0a 57 67 72 f3 00 02 4c ce 1d 10 54 3d 161 09 30 6f 9a ce a6 3a 8c 68 cb 9a 70 162 """, 163 "b5 b2 89 6b b3 66 4e 81 76 b0 ed c6 e7 99 52 41 01 a8 30 7f", 164 "09 30 6f 9a ce a6 3a 8c 68 cb 9a 70", 165 server_isn_42x, 166 client_isn_42x, 167 include_options=False, 168) 169 170= TCP-AO Test Vector 4.2.3 171check( 172 """ 173 45 e0 00 87 a8 f5 40 00 ff 06 f3 4a 0a 0b 0c 0d 174 ac 1b 1c 1d ff 12 00 b3 cb 0e fb ef ac d5 b5 e2 175 c0 18 01 04 6c 45 00 00 01 01 08 0a 00 02 4c ce 176 57 67 72 f3 1d 10 3d 54 71 06 08 cc 69 6c 03 a2 177 71 c9 3a a5 ff ff ff ff ff ff ff ff ff ff ff ff 178 ff ff ff ff 00 43 01 04 da bf 00 b4 0a 0b 0c 0d 179 26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02 180 00 02 02 42 00 02 06 41 04 00 00 da bf 02 08 40 181 06 00 64 00 01 01 00 182 """, 183 "f3 db 17 93 d7 91 0e cd 80 6c 34 f1 55 ea 1f 00 34 59 53 e3", 184 "71 06 08 cc 69 6c 03 a2 71 c9 3a a5", 185 client_isn_42x, 186 server_isn_42x, 187 include_options=False, 188) 189 190= TCP-AO Test Vector 4.2.4 191check( 192 """ 193 45 e0 00 87 54 37 40 00 ff 06 48 09 ac 1b 1c 1d 194 0a 0b 0c 0d 00 b3 ff 12 ac d5 b5 e2 cb 0e fc 32 195 c0 18 01 00 46 b6 00 00 01 01 08 0a 57 67 72 f3 196 00 02 4c ce 1d 10 54 3d 97 76 6e 48 ac 26 2d e9 197 ae 61 b4 f9 ff ff ff ff ff ff ff ff ff ff ff ff 198 ff ff ff ff 00 43 01 04 da c0 00 b4 ac 1b 1c 1d 199 26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02 200 00 02 02 42 00 02 06 41 04 00 00 da c0 02 08 40 201 06 00 64 00 01 01 00 202 """, 203 "b5 b2 89 6b b3 66 4e 81 76 b0 ed c6 e7 99 52 41 01 a8 30 7f", 204 "97 76 6e 48 ac 26 2d e9 ae 61 b4 f9", 205 server_isn_42x, 206 client_isn_42x, 207 include_options=False, 208) 209 210= TCP-AO Test Vector 5.1.1 211check( 212 """ 213 45 e0 00 4c 7b 9f 40 00 ff 06 20 dc 0a 0b 0c 0d 214 ac 1b 1c 1d c4 fa 00 b3 78 7a 1d df 00 00 00 00 215 e0 02 ff ff 5a 0f 00 00 02 04 05 b4 01 03 03 08 216 04 02 08 0a 00 01 7e d0 00 00 00 00 1d 10 3d 54 217 e4 77 e9 9c 80 40 76 54 98 e5 50 91 218 """, 219 "f5 b8 b3 d5 f3 4f db b6 eb 8d 4a b9 66 0e 60 e3", 220 "e4 77 e9 9c 80 40 76 54 98 e5 50 91", 221 0x787A1DDF, 222 0, 223 include_options=True, 224 alg_name="AES-128-CMAC-96", 225) 226 227= TCP-AO Test Vector 6.1.1 228client_isn_61x = 0x176A833F 229server_isn_61x = 0x3F51994B 230check( 231 """ 232 6e 08 91 dc 00 38 06 40 fd 00 00 00 00 00 00 00 233 00 00 00 00 00 00 00 01 fd 00 00 00 00 00 00 00 234 00 00 00 00 00 00 00 02 f7 e4 00 b3 17 6a 83 3f 235 00 00 00 00 e0 02 ff ff 47 21 00 00 02 04 05 a0 236 01 03 03 08 04 02 08 0a 00 41 d0 87 00 00 00 00 237 1d 10 3d 54 90 33 ec 3d 73 34 b6 4c 5e dd 03 9f 238 """, 239 "62 5e c0 9d 57 58 36 ed c9 b6 42 84 18 bb f0 69 89 a3 61 bb", 240 "90 33 ec 3d 73 34 b6 4c 5e dd 03 9f", 241 client_isn_61x, 242 0, 243 include_options=True, 244) 245 246= TCP-AO Test Vector 6.1.2 247check( 248 """ 249 6e 01 00 9e 00 38 06 40 fd 00 00 00 00 00 00 00 250 00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00 251 00 00 00 00 00 00 00 01 00 b3 f7 e4 3f 51 99 4b 252 17 6a 83 40 e0 12 ff ff bf ec 00 00 02 04 05 a0 253 01 03 03 08 04 02 08 0a bd 33 12 9b 00 41 d0 87 254 1d 10 54 3d f1 cb a3 46 c3 52 61 63 f7 1f 1f 55 255 """, 256 "e4 a3 7a da 2a 0a fc a8 71 14 34 91 3f e1 38 c7 71 eb cb 4a", 257 "f1 cb a3 46 c3 52 61 63 f7 1f 1f 55", 258 server_isn_61x, 259 client_isn_61x, 260 include_options=True, 261) 262 263= TCP-AO Test Vector 6.2.2 264client_isn_62x = 0x020C1E69 265server_isn_62x = 0xEBA3734D 266check( 267 """ 268 6e 0a 7e 1f 00 38 06 40 fd 00 00 00 00 00 00 00 269 00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00 270 00 00 00 00 00 00 00 01 00 b3 c6 cd eb a3 73 4d 271 02 0c 1e 6a e0 12 ff ff 77 4d 00 00 02 04 05 a0 272 01 03 03 08 04 02 08 0a 5e c9 9b 70 00 9d b9 5b 273 1d 10 54 3d 3c 54 6b ad 97 43 f1 2d f8 b8 01 0d 274 """, 275 "40 51 08 94 7f 99 65 75 e7 bd bc 26 d4 02 16 a2 c7 fa 91 bd", 276 "3c 54 6b ad 97 43 f1 2d f8 b8 01 0d", 277 server_isn_62x, 278 client_isn_62x, 279 include_options=False, 280) 281 282= TCP-AO Test Vector 6.2.4 283check( 284 """ 285 6e 0a 7e 1f 00 73 06 40 fd 00 00 00 00 00 00 00 286 00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00 287 00 00 00 00 00 00 00 01 00 b3 c6 cd eb a3 73 4e 288 02 0c 1e ad c0 18 01 00 71 6a 00 00 01 01 08 0a 289 5e c9 9b 7a 00 9d b9 65 1d 10 54 3d 55 9a 81 94 290 45 b4 fd e9 8d 9e 13 17 ff ff ff ff ff ff ff ff 291 ff ff ff ff ff ff ff ff 00 43 01 04 fd e8 00 b4 292 01 01 01 7a 26 02 06 01 04 00 01 00 01 02 02 80 293 00 02 02 02 00 02 02 42 00 02 06 41 04 00 00 fd 294 e8 02 08 40 06 00 64 00 01 01 00 295 """, 296 "40 51 08 94 7f 99 65 75 e7 bd bc 26 d4 02 16 a2 c7 fa 91 bd", 297 "55 9a 81 94 45 b4 fd e9 8d 9e 13 17", 298 server_isn_62x, 299 client_isn_62x, 300 include_options=False, 301) 302 303= TCP-AO Test Vector 7.1.2 304server_isn_71x = 0xA6744ECB 305client_isn_71x = 0x193CCCEC 306check( 307 """ 308 6e 06 15 20 00 38 06 40 fd 00 00 00 00 00 00 00 309 00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00 310 00 00 00 00 00 00 00 01 00 b3 f8 5a a6 74 4e cb 311 19 3c cc ed e0 12 ff ff ea bb 00 00 02 04 05 a0 312 01 03 03 08 04 02 08 0a 71 da ab c8 13 e4 ab 99 313 1d 10 54 3d dc 28 43 a8 4e 78 a6 bc fd c5 ed 80 314 """, 315 "cf 1b 1e 22 5e 06 a6 36 16 76 4a 06 7b 46 f4 b1", 316 "dc 28 43 a8 4e 78 a6 bc fd c5 ed 80", 317 server_isn_71x, 318 client_isn_71x, 319 alg_name="AES-128-CMAC-96", 320 include_options=True, 321) 322 323= TCP-AO Test Vector 7.1.4 324check( 325 """ 326 6e 06 15 20 00 73 06 40 fd 00 00 00 00 00 00 00 327 00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00 328 00 00 00 00 00 00 00 01 00 b3 f8 5a a6 74 4e cc 329 19 3c cd 30 c0 18 01 00 52 f4 00 00 01 01 08 0a 330 71 da ab d3 13 e4 ab a3 1d 10 54 3d c1 06 9b 7d 331 fd 3d 69 3a 6d f3 f2 89 ff ff ff ff ff ff ff ff 332 ff ff ff ff ff ff ff ff 00 43 01 04 fd e8 00 b4 333 01 01 01 7a 26 02 06 01 04 00 01 00 01 02 02 80 334 00 02 02 02 00 02 02 42 00 02 06 41 04 00 00 fd 335 e8 02 08 40 06 00 64 00 01 01 00 336 """, 337 "cf 1b 1e 22 5e 06 a6 36 16 76 4a 06 7b 46 f4 b1", 338 "c1 06 9b 7d fd 3d 69 3a 6d f3 f2 89", 339 server_isn_71x, 340 client_isn_71x, 341 alg_name="AES-128-CMAC-96", 342 include_options=True, 343) 344 345+ TCP-AO Signature API 346= TCP-AO sign SYN packet build from scratch 347master_key = b"hello" 348alg = TCPAOAlg_HMAC_SHA1() 349keyid = 12 350rnextkeyid = 34 351 352p = IP() / TCP() 353p[TCP].flags == "S" 354sisn = p[TCP].seq 355disn = 0 356 357# sign 358traffic_key = calc_tcpao_traffic_key(p, alg, master_key, sisn, disn) 359sign_tcpao(p, alg, traffic_key, keyid, rnextkeyid) 360mac = calc_tcpao_mac(p, alg, traffic_key) 361 362# parse 363p2 = IP(raw(p)) 364ao = get_tcpao(p2[TCP]) 365ao is not None 366ao.keyid == keyid 367ao.rnextkeyid == rnextkeyid 368ao.mac == mac 369 370# calculate signature again on parsed packet 371traffic_key2 = calc_tcpao_traffic_key(p2, alg, master_key, p2[TCP].seq, 0) 372traffic_key == traffic_key2 373mac2 = calc_tcpao_mac(p2, alg, traffic_key2) 374mac == mac2 375