rustc_middle/ptrauth/llvm_siphash/
mod.rs1pub fn llvm_pointer_auth_stable_siphash(data: &[u8]) -> u16 {
3 let raw = llvm_siphash_2_4_64(data);
4
5 ((raw % 0xFFFF) + 1) as u16
6}
7
8const SIPHASH_KEY: [u8; 16] = [
9 0xb5, 0xd4, 0xc9, 0xeb, 0x79, 0x10, 0x4a, 0x79, 0x6f, 0xec, 0x8b, 0x1b, 0x42, 0x87, 0x81, 0xd4,
10];
11
12#[inline(always)]
13fn rotl(x: u64, b: u32) -> u64 {
14 (x << b) | (x >> (64 - b))
15}
16
17#[inline(always)]
18fn sipround(v0: &mut u64, v1: &mut u64, v2: &mut u64, v3: &mut u64) {
19 *v0 = v0.wrapping_add(*v1);
20 *v1 = rotl(*v1, 13);
21 *v1 ^= *v0;
22 *v0 = rotl(*v0, 32);
23
24 *v2 = v2.wrapping_add(*v3);
25 *v3 = rotl(*v3, 16);
26 *v3 ^= *v2;
27
28 *v0 = v0.wrapping_add(*v3);
29 *v3 = rotl(*v3, 21);
30 *v3 ^= *v0;
31
32 *v2 = v2.wrapping_add(*v1);
33 *v1 = rotl(*v1, 17);
34 *v1 ^= *v2;
35 *v2 = rotl(*v2, 32);
36}
37
38fn u64_from_le(bytes: &[u8]) -> u64 {
39 u64::from_le_bytes(bytes.try_into().unwrap())
40}
41
42fn load_u64_partial(bytes: &[u8]) -> u64 {
43 let mut b = 0u64;
44
45 match bytes.len() {
46 7 => {
47 b |= (bytes[6] as u64) << 48;
48 b |= (bytes[5] as u64) << 40;
49 b |= (bytes[4] as u64) << 32;
50 b |= (bytes[3] as u64) << 24;
51 b |= (bytes[2] as u64) << 16;
52 b |= (bytes[1] as u64) << 8;
53 b |= bytes[0] as u64;
54 }
55 6 => {
56 b |= (bytes[5] as u64) << 40;
57 b |= (bytes[4] as u64) << 32;
58 b |= (bytes[3] as u64) << 24;
59 b |= (bytes[2] as u64) << 16;
60 b |= (bytes[1] as u64) << 8;
61 b |= bytes[0] as u64;
62 }
63 5 => {
64 b |= (bytes[4] as u64) << 32;
65 b |= (bytes[3] as u64) << 24;
66 b |= (bytes[2] as u64) << 16;
67 b |= (bytes[1] as u64) << 8;
68 b |= bytes[0] as u64;
69 }
70 4 => {
71 b |= (bytes[3] as u64) << 24;
72 b |= (bytes[2] as u64) << 16;
73 b |= (bytes[1] as u64) << 8;
74 b |= bytes[0] as u64;
75 }
76 3 => {
77 b |= (bytes[2] as u64) << 16;
78 b |= (bytes[1] as u64) << 8;
79 b |= bytes[0] as u64;
80 }
81 2 => {
82 b |= (bytes[1] as u64) << 8;
83 b |= bytes[0] as u64;
84 }
85 1 => {
86 b |= bytes[0] as u64;
87 }
88 _ => {}
89 }
90
91 b
92}
93
94fn siphash_2_4_64_with_key(data: &[u8], key: &[u8; 16]) -> u64 {
95 let k0 = u64_from_le(&key[0..8]);
96 let k1 = u64_from_le(&key[8..16]);
97
98 let mut v0: u64 = 0x736f6d6570736575 ^ k0;
99 let mut v1: u64 = 0x646f72616e646f6d ^ k1;
100 let mut v2: u64 = 0x6c7967656e657261 ^ k0;
101 let mut v3: u64 = 0x7465646279746573 ^ k1;
102
103 let mut b: u64 = (data.len() as u64) << 56;
104 let mut i = 0;
105
106 while i + 8 <= data.len() {
108 let m = u64_from_le(&data[i..i + 8]);
109 i += 8;
110
111 v3 ^= m;
112
113 for _ in 0..2 {
114 sipround(&mut v0, &mut v1, &mut v2, &mut v3);
115 }
116
117 v0 ^= m;
118 }
119
120 let tail = &data[i..];
122
123 b |= load_u64_partial(tail);
124
125 v3 ^= b;
126
127 for _ in 0..2 {
128 sipround(&mut v0, &mut v1, &mut v2, &mut v3);
129 }
130
131 v0 ^= b;
132
133 v2 ^= 0xff;
135
136 for _ in 0..4 {
137 sipround(&mut v0, &mut v1, &mut v2, &mut v3);
138 }
139
140 v0 ^ v1 ^ v2 ^ v3
141}
142fn llvm_siphash_2_4_64(data: &[u8]) -> u64 {
144 siphash_2_4_64_with_key(data, &SIPHASH_KEY)
145}
146
147#[cfg(test)]
148mod llvm_siphash_vectors;
149
150#[cfg(test)]
151mod tests;