Skip to content

Commit 0110c6b

Browse files
committed
document new unsafe blocks in unsafe functions
1 parent 97ee2bb commit 0110c6b

18 files changed

+107
-37
lines changed

graviola/src/low/aarch64/aes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl AesKey {
4747

4848
#[target_feature(enable = "aes,neon")]
4949
unsafe fn _ctr(&self, initial_counter: &[u8; 16], cipher_inout: &mut [u8]) {
50+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
5051
unsafe {
5152
// counter and inc are big endian, so must be vrev32q_u8'd before use
5253
let counter = vld1q_u8(initial_counter.as_ptr().cast());
@@ -248,6 +249,7 @@ fn sub_word(w: u32) -> u32 {
248249

249250
#[target_feature(enable = "aes")]
250251
unsafe fn _sub_word(w: u32) -> u32 {
252+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
251253
unsafe {
252254
// we have the `aese` instruction, which is
253255
// `sub_word(shift_rows(w), S)`. however, fortunately
@@ -268,6 +270,7 @@ const RCON: [u32; 10] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0
268270

269271
#[target_feature(enable = "aes")]
270272
unsafe fn aes128_block(round_keys: &[uint8x16_t; 11], block_inout: &mut [u8]) {
273+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
271274
unsafe {
272275
let block = vld1q_u8(block_inout.as_ptr() as *const _);
273276
let block = _aes128_block(round_keys, block);
@@ -278,6 +281,7 @@ unsafe fn aes128_block(round_keys: &[uint8x16_t; 11], block_inout: &mut [u8]) {
278281
#[target_feature(enable = "aes")]
279282
#[inline]
280283
unsafe fn _aes128_block(round_keys: &[uint8x16_t; 11], block: uint8x16_t) -> uint8x16_t {
284+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
281285
unsafe {
282286
let block = vaeseq_u8(block, round_keys[0]);
283287
let block = vaesmcq_u8(block);
@@ -346,6 +350,7 @@ unsafe fn _aes128_8_blocks(
346350
uint8x16_t,
347351
uint8x16_t,
348352
) {
353+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
349354
unsafe {
350355
round_8!(b0, b1, b2, b3, b4, b5, b6, b7, round_keys[0]);
351356
round_8!(b0, b1, b2, b3, b4, b5, b6, b7, round_keys[1]);
@@ -380,6 +385,7 @@ unsafe fn _aes128_8_blocks(
380385

381386
#[target_feature(enable = "aes")]
382387
unsafe fn aes256_block(round_keys: &[uint8x16_t; 15], block_inout: &mut [u8]) {
388+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
383389
unsafe {
384390
let block = vld1q_u8(block_inout.as_ptr() as *const _);
385391
let block = _aes256_block(round_keys, block);
@@ -390,6 +396,7 @@ unsafe fn aes256_block(round_keys: &[uint8x16_t; 15], block_inout: &mut [u8]) {
390396
#[target_feature(enable = "aes")]
391397
#[inline]
392398
unsafe fn _aes256_block(round_keys: &[uint8x16_t; 15], block: uint8x16_t) -> uint8x16_t {
399+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
393400
unsafe {
394401
let block = vaeseq_u8(block, round_keys[0]);
395402
let block = vaesmcq_u8(block);
@@ -444,6 +451,7 @@ unsafe fn _aes256_8_blocks(
444451
uint8x16_t,
445452
uint8x16_t,
446453
) {
454+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
447455
unsafe {
448456
round_8!(b0, b1, b2, b3, b4, b5, b6, b7, round_keys[0]);
449457
round_8!(b0, b1, b2, b3, b4, b5, b6, b7, round_keys[1]);

graviola/src/low/aarch64/bignum_point_select_p256.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub(crate) fn bignum_jac_point_select_p256(z: &mut [u64; 12], table: &[u64], ind
2525

2626
#[target_feature(enable = "neon")]
2727
unsafe fn _select_aff_p256(z: &mut [u64; 8], table: &[u64], index: u8) {
28+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
2829
unsafe {
2930
// SAFETY: u128 and uint32x4_t have same size and meaning
3031
let mut acc0: uint32x4_t = mem::transmute(0u128);
@@ -65,6 +66,7 @@ unsafe fn _select_aff_p256(z: &mut [u64; 8], table: &[u64], index: u8) {
6566

6667
#[target_feature(enable = "neon")]
6768
unsafe fn _select_jac_p256(z: &mut [u64; 12], table: &[u64], index: u8) {
69+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
6870
unsafe {
6971
let mut acc0: uint32x4_t = mem::transmute(0u128);
7072
let mut acc1 = acc0;

graviola/src/low/aarch64/bignum_point_select_p384.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub(crate) fn bignum_jac_point_select_p384(z: &mut [u64; 18], table: &[u64], ind
1414

1515
#[target_feature(enable = "neon")]
1616
unsafe fn _select_jac_p384(z: &mut [u64; 18], table: &[u64], index: u8) {
17+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
1718
unsafe {
1819
let mut acc0: uint32x4_t = mem::transmute(0u128);
1920
let mut acc1 = acc0;

graviola/src/low/aarch64/cpu.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub(crate) fn leave_cpu_state(old: u32) {
1616

1717
#[target_feature(enable = "neon")]
1818
unsafe fn zero_neon_registers() {
19+
// SAFETY: inline assembly. all written registers are listed as clobbers.
1920
unsafe {
20-
// SAFETY: inline assembly. all written registers are listed as clobbers.
2121
core::arch::asm!(
2222
" eor v0.16b, v0.16b, v0.16b",
2323
" eor v1.16b, v1.16b, v1.16b",
@@ -131,6 +131,7 @@ pub(in crate::low) fn zero_bytes(ptr: *mut u8, len: usize) {
131131
/// # Safety
132132
/// The caller must ensure that there are `len` bytes readable at `a` and `b`,
133133
pub(in crate::low) unsafe fn ct_compare_bytes(a: *const u8, b: *const u8, len: usize) -> u8 {
134+
// SAFETY: inline assembly.
134135
unsafe {
135136
let mut acc = 0u8;
136137
core::arch::asm!(

graviola/src/low/aarch64/ghash.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ macro_rules! reduce {
197197

198198
#[target_feature(enable = "neon,aes")]
199199
unsafe fn _mul(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
200+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
200201
unsafe {
201202
let (mut lo, mut mi, mut hi) = (zero(), zero(), zero());
202203
let bx = xor_halves(b);
@@ -217,6 +218,7 @@ unsafe fn _mul8(
217218
g: uint64x2_t,
218219
h: uint64x2_t,
219220
) -> uint64x2_t {
221+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
220222
unsafe {
221223
let (mut lo, mut mi, mut hi) = (zero(), zero(), zero());
222224
mul!(lo, mi, hi, a, table.powers[7], table.powers_xor[7]);
@@ -233,6 +235,7 @@ unsafe fn _mul8(
233235

234236
#[target_feature(enable = "neon")]
235237
unsafe fn xor_halves(h: uint64x2_t) -> uint64x2_t {
238+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
236239
unsafe {
237240
let hx = vextq_u64(h, h, 1);
238241
veorq_u64(hx, h)
@@ -241,6 +244,7 @@ unsafe fn xor_halves(h: uint64x2_t) -> uint64x2_t {
241244

242245
#[target_feature(enable = "neon")]
243246
unsafe fn gf128_big_endian(h: uint64x2_t) -> uint64x2_t {
247+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
244248
unsafe {
245249
// takes a raw hash subkey, and arranges that it can
246250
// be used in big endian ordering.
@@ -267,6 +271,7 @@ unsafe fn gf128_big_endian(h: uint64x2_t) -> uint64x2_t {
267271
#[inline]
268272
#[target_feature(enable = "neon,aes")]
269273
unsafe fn vmull_p64_fix(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
274+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
270275
unsafe {
271276
let a = vgetq_lane_u64::<0>(a);
272277
let b = vgetq_lane_u64::<0>(b);
@@ -277,6 +282,7 @@ unsafe fn vmull_p64_fix(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
277282
#[inline]
278283
#[target_feature(enable = "neon,aes")]
279284
unsafe fn vmull_high_p64_fix(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
285+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
280286
unsafe {
281287
let a = vgetq_lane_u64::<1>(a);
282288
let b = vgetq_lane_u64::<1>(b);

graviola/src/low/aarch64/sha256.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ macro_rules! round {
3737

3838
#[target_feature(enable = "neon,sha2")]
3939
unsafe fn sha256(state: &mut [u32; 8], blocks: &[u8]) {
40+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
4041
unsafe {
4142
let mut state0 = vld1q_u32(state[0..4].as_ptr());
4243
let mut state1 = vld1q_u32(state[4..8].as_ptr());

graviola/src/low/inline_assembly_safety.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,20 @@
7171
//! For this reason, it is unsound if `ret` is called in the outer
7272
//! frame. However, our inline assembly can contain leaf internal
7373
//! functions: these may `ret` back to the outer frame.
74+
//!
75+
//! # Safety of intrinsics
76+
//!
77+
//! The above sections "Using unsupported instructions" also apply
78+
//! to intrinsics, and the same arrangements exist to avoid ever
79+
//! issuing an unsupported instruction.
80+
//!
81+
//! In general, intrinsics are less hazardous to use than inline
82+
//! assembly. However, since they are intended to be drop-in
83+
//! replacements for their counterparts in C/C++, they are less
84+
//! Rust-friendly than they could otherwise be. For example,
85+
//! an analog of `_mm_loadu_si128` could take `&[u8; 16]` as its
86+
//! argument, rather than a pointer. That would externalise the
87+
//! requirements on that function, and allow it to be safe
88+
//! (though only if `target_feature` `sse2` was statically
89+
//! guaranteed at compile-time, and would require safe-transmute
90+
//! to be available for non-byte types).

graviola/src/low/x86_64/aes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ macro_rules! expand_128 {
140140

141141
#[target_feature(enable = "aes,avx")]
142142
unsafe fn aes128_expand(key: &[u8; 16], out: &mut [__m128i; 11]) {
143+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
143144
unsafe {
144145
let mut t1 = _mm_lddqu_si128(key.as_ptr() as *const _);
145146
out[0] = t1;
@@ -195,6 +196,7 @@ macro_rules! expand_256 {
195196

196197
#[target_feature(enable = "aes,avx")]
197198
unsafe fn aes256_expand(key: &[u8; 32], out: &mut [__m128i; 15]) {
199+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
198200
unsafe {
199201
let mut t1 = _mm_lddqu_si128(key.as_ptr() as *const _);
200202
let mut t3 = _mm_lddqu_si128(key[16..].as_ptr() as *const _);
@@ -221,6 +223,7 @@ unsafe fn aes256_expand(key: &[u8; 32], out: &mut [__m128i; 15]) {
221223

222224
#[target_feature(enable = "aes,avx")]
223225
unsafe fn aes128_block(round_keys: &[__m128i; 11], block_inout: &mut [u8]) {
226+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
224227
unsafe {
225228
let block = _mm_lddqu_si128(block_inout.as_ptr() as *const _);
226229
let block = _mm_xor_si128(block, round_keys[0]);
@@ -240,6 +243,7 @@ unsafe fn aes128_block(round_keys: &[__m128i; 11], block_inout: &mut [u8]) {
240243

241244
#[target_feature(enable = "aes,avx")]
242245
unsafe fn aes256_block(round_keys: &[__m128i; 15], block_inout: &mut [u8]) {
246+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
243247
unsafe {
244248
let block = _mm_lddqu_si128(block_inout.as_ptr() as *const _);
245249
let block = _mm_xor_si128(block, round_keys[0]);

graviola/src/low/x86_64/aes_gcm.rs

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ unsafe fn _cipher<const ENC: bool>(
3939
aad: &[u8],
4040
cipher_inout: &mut [u8],
4141
) {
42-
unsafe {
43-
ghash.add(aad);
42+
ghash.add(aad);
4443

45-
let (rk_first, rks, rk_last) = key.round_keys();
44+
let (rk_first, rks, rk_last) = key.round_keys();
4645

47-
let mut counter = Counter::new(initial_counter);
48-
let mut by8_iter = cipher_inout.chunks_exact_mut(128);
46+
let mut counter = Counter::new(initial_counter);
47+
let mut by8_iter = cipher_inout.chunks_exact_mut(128);
4948

50-
for blocks in by8_iter.by_ref() {
49+
for blocks in by8_iter.by_ref() {
50+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
51+
unsafe {
5152
// prefetch to avoid any stall later
5253
_mm_prefetch(blocks.as_ptr().add(0) as *const _, _MM_HINT_T0);
5354
_mm_prefetch(blocks.as_ptr().add(64) as *const _, _MM_HINT_T0);
@@ -135,18 +136,21 @@ unsafe fn _cipher<const ENC: bool>(
135136
let a1 = _mm_xor_si128(ghash.current, a1);
136137
ghash.current = ghash::_mul8(ghash.table, a1, a2, a3, a4, a5, a6, a7, a8);
137138
}
139+
}
138140

139-
let cipher_inout = by8_iter.into_remainder();
141+
let cipher_inout = by8_iter.into_remainder();
140142

141-
if !ENC {
142-
ghash.add(cipher_inout);
143-
}
143+
if !ENC {
144+
ghash.add(cipher_inout);
145+
}
144146

145-
{
146-
let mut blocks_iter = cipher_inout.chunks_exact_mut(16);
147-
for block in blocks_iter.by_ref() {
148-
let c1 = counter.next();
147+
{
148+
let mut blocks_iter = cipher_inout.chunks_exact_mut(16);
149+
for block in blocks_iter.by_ref() {
150+
let c1 = counter.next();
149151

152+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
153+
unsafe {
150154
let mut c1 = _mm_xor_si128(c1, rk_first);
151155

152156
for rk in rks {
@@ -159,16 +163,19 @@ unsafe fn _cipher<const ENC: bool>(
159163

160164
_mm_storeu_si128(block.as_mut_ptr() as *mut _, c1);
161165
}
166+
}
162167

163-
let cipher_inout = blocks_iter.into_remainder();
164-
if !cipher_inout.is_empty() {
165-
let mut block = [0u8; 16];
166-
let len = cipher_inout.len();
167-
debug_assert!(len < 16);
168-
block[..len].copy_from_slice(cipher_inout);
168+
let cipher_inout = blocks_iter.into_remainder();
169+
if !cipher_inout.is_empty() {
170+
let mut block = [0u8; 16];
171+
let len = cipher_inout.len();
172+
debug_assert!(len < 16);
173+
block[..len].copy_from_slice(cipher_inout);
169174

170-
let c1 = counter.next();
175+
let c1 = counter.next();
171176

177+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
178+
unsafe {
172179
let mut c1 = _mm_xor_si128(c1, rk_first);
173180

174181
for rk in rks {
@@ -181,15 +188,15 @@ unsafe fn _cipher<const ENC: bool>(
181188
let c1 = _mm_xor_si128(c1, p1);
182189

183190
_mm_storeu_si128(block.as_mut_ptr() as *mut _, c1);
184-
185-
cipher_inout.copy_from_slice(&block[..len]);
186191
}
187-
}
188192

189-
if ENC {
190-
ghash.add(cipher_inout);
193+
cipher_inout.copy_from_slice(&block[..len]);
191194
}
192195
}
196+
197+
if ENC {
198+
ghash.add(cipher_inout);
199+
}
193200
}
194201

195202
/// This stores the next counter value, in big endian.

graviola/src/low/x86_64/bignum_copy_row_from_table_16_avx2.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(crate) fn bignum_copy_row_from_table_16_avx2(
1818

1919
#[target_feature(enable = "avx,avx2")]
2020
unsafe fn _bignum_copy_row_from_table_16_avx2(z: &mut [u64], table: &[u64], index: u64) {
21+
// SAFETY: intrinsics. see [crate::low::inline_assembly_safety#safety-of-intrinsics] for safety info.
2122
unsafe {
2223
// SAFETY: prefetches do not fault and are not architecturally visible
2324
_mm_prefetch(table.as_ptr().cast(), _MM_HINT_T0);
@@ -41,7 +42,7 @@ unsafe fn _bignum_copy_row_from_table_16_avx2(z: &mut [u64], table: &[u64], inde
4142
let mask = _mm256_cmpeq_epi64(index, desired_index);
4243
index = _mm256_add_epi64(index, ones);
4344

44-
// SAFETY: `row` is exactly 16 words; `loadu` does relaxes 256-bit alignment req.
45+
// SAFETY: `row` is exactly 16 words; `loadu` relaxes 256-bit alignment req.
4546
let row0 = _mm256_loadu_si256(row.as_ptr().add(0).cast());
4647
let row1 = _mm256_loadu_si256(row.as_ptr().add(4).cast());
4748
let row2 = _mm256_loadu_si256(row.as_ptr().add(8).cast());

0 commit comments

Comments
 (0)