Add a pointer alignment helper function.
Also use a slightly more conservative pattern. Instead of aligning the
pointer as a uintptr_t and casting back, compute the offset and advance
in pointer space. C guarantees that casting from pointer to uintptr_t
and back gives the same pointer, but general integer-to-pointer
conversions are generally implementation-defined. GCC does define it in
the useful way, but this makes fewer dependencies.
Change-Id: I70c7af735e892fe7a8333b78b39d7b1f3f1cdbef
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48405
Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/crypto/hrss/hrss.c b/crypto/hrss/hrss.c
index 67ff4c1..957e9d2 100644
--- a/crypto/hrss/hrss.c
+++ b/crypto/hrss/hrss.c
@@ -1871,9 +1871,7 @@
sizeof(struct HRSS_public_key) >= sizeof(struct public_key) + 15,
"HRSS public key too small");
- uintptr_t p = (uintptr_t)ext;
- p = (p + 15) & ~15;
- return (struct public_key *)p;
+ return align_pointer(ext->opaque, 16);
}
// private_key_from_external does the same thing as |public_key_from_external|,
@@ -1885,9 +1883,7 @@
sizeof(struct HRSS_private_key) >= sizeof(struct private_key) + 15,
"HRSS private key too small");
- uintptr_t p = (uintptr_t)ext;
- p = (p + 15) & ~15;
- return (struct private_key *)p;
+ return align_pointer(ext->opaque, 16);
}
void HRSS_generate_key(
diff --git a/crypto/internal.h b/crypto/internal.h
index 14c60e09..b288583 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -209,6 +209,9 @@
#define OPENSSL_SSE2
#endif
+
+// Pointer utility functions.
+
// buffers_alias returns one if |a| and |b| alias and zero otherwise.
static inline int buffers_alias(const uint8_t *a, size_t a_len,
const uint8_t *b, size_t b_len) {
@@ -221,6 +224,23 @@
return a_u + a_len > b_u && b_u + b_len > a_u;
}
+// align_pointer returns |ptr|, advanced to |alignment|. |alignment| must be a
+// power of two, and |ptr| must have at least |alignment - 1| bytes of scratch
+// space.
+static inline void *align_pointer(void *ptr, size_t alignment) {
+ // |alignment| must be a power of two.
+ assert(alignment != 0 && (alignment & (alignment - 1)) == 0);
+ // Instead of aligning |ptr| as a |uintptr_t| and casting back, compute the
+ // offset and advance in pointer space. C guarantees that casting from pointer
+ // to |uintptr_t| and back gives the same pointer, but general
+ // integer-to-pointer conversions are implementation-defined. GCC does define
+ // it in the useful way, but this makes fewer assumptions.
+ uintptr_t offset = (0u - (uintptr_t)ptr) & (alignment - 1);
+ ptr = (char *)ptr + offset;
+ assert(((uintptr_t)ptr & (alignment - 1)) == 0);
+ return ptr;
+}
+
// Constant-time utility functions.
//
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
index 31a567d..c07b1e9 100644
--- a/crypto/poly1305/poly1305.c
+++ b/crypto/poly1305/poly1305.c
@@ -56,7 +56,7 @@
static inline struct poly1305_state_st *poly1305_aligned_state(
poly1305_state *state) {
- return (struct poly1305_state_st *)(((uintptr_t)state + 63) & ~63);
+ return align_pointer(state, 64);
}
// poly1305_blocks updates |state| given some amount of input data. This
diff --git a/tool/speed.cc b/tool/speed.cc
index 1b89b42..264334f 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -342,12 +342,6 @@
return true;
}
-static uint8_t *align(uint8_t *in, unsigned alignment) {
- return reinterpret_cast<uint8_t *>(
- (reinterpret_cast<uintptr_t>(in) + alignment) &
- ~static_cast<size_t>(alignment - 1));
-}
-
static std::string ChunkLenSuffix(size_t chunk_len) {
char buf[32];
snprintf(buf, sizeof(buf), " (%zu byte%s)", chunk_len,
@@ -384,13 +378,17 @@
new uint8_t[overhead_len + kAlignment]);
- uint8_t *const in = align(in_storage.get(), kAlignment);
+ uint8_t *const in =
+ static_cast<uint8_t *>(align_pointer(in_storage.get(), kAlignment));
OPENSSL_memset(in, 0, chunk_len);
- uint8_t *const out = align(out_storage.get(), kAlignment);
+ uint8_t *const out =
+ static_cast<uint8_t *>(align_pointer(out_storage.get(), kAlignment));
OPENSSL_memset(out, 0, chunk_len + overhead_len);
- uint8_t *const tag = align(tag_storage.get(), kAlignment);
+ uint8_t *const tag =
+ static_cast<uint8_t *>(align_pointer(tag_storage.get(), kAlignment));
OPENSSL_memset(tag, 0, overhead_len);
- uint8_t *const in2 = align(in2_storage.get(), kAlignment);
+ uint8_t *const in2 =
+ static_cast<uint8_t *>(align_pointer(in2_storage.get(), kAlignment));
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
EVP_AEAD_DEFAULT_TAG_LENGTH,