Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/sha512.h')
-rw-r--r--crypto/sha512.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/crypto/sha512.h b/crypto/sha512.h
new file mode 100644
index 00000000..98145558
--- /dev/null
+++ b/crypto/sha512.h
@@ -0,0 +1,131 @@
+/*
+ * Definitions likely to be helpful to multiple SHA-512 implementations.
+ */
+
+/*
+ * The 'extra' structure used by SHA-512 implementations is used to
+ * include information about how to check if a given implementation is
+ * available at run time, and whether we've already checked.
+ */
+struct sha512_extra_mutable;
+struct sha512_extra {
+ /* Pointer to the initial state (distinguishes SHA-384 from -512) */
+ const uint64_t *initial_state;
+
+ /* Function to check availability. Might be expensive, so we don't
+ * want to call it more than once. */
+ bool (*check_available)(void);
+
+ /* Point to a writable substructure. */
+ struct sha512_extra_mutable *mut;
+};
+struct sha512_extra_mutable {
+ bool checked_availability;
+ bool is_available;
+};
+static inline bool check_availability(const struct sha512_extra *extra)
+{
+ if (!extra->mut->checked_availability) {
+ extra->mut->is_available = extra->check_available();
+ extra->mut->checked_availability = true;
+ }
+
+ return extra->mut->is_available;
+}
+
+/*
+ * Macro to define a pair of SHA-{384,512} vtables together with their
+ * 'extra' structure.
+ */
+#define SHA512_VTABLES(impl_c, impl_display) \
+ static struct sha512_extra_mutable sha512_ ## impl_c ## _extra_mut; \
+ static const struct sha512_extra sha384_ ## impl_c ## _extra = { \
+ .initial_state = sha384_initial_state, \
+ .check_available = sha512_ ## impl_c ## _available, \
+ .mut = &sha512_ ## impl_c ## _extra_mut, \
+ }; \
+ static const struct sha512_extra sha512_ ## impl_c ## _extra = { \
+ .initial_state = sha512_initial_state, \
+ .check_available = sha512_ ## impl_c ## _available, \
+ .mut = &sha512_ ## impl_c ## _extra_mut, \
+ }; \
+ const ssh_hashalg ssh_sha384_ ## impl_c = { \
+ .new = sha512_ ## impl_c ## _new, \
+ .reset = sha512_ ## impl_c ## _reset, \
+ .copyfrom = sha512_ ## impl_c ## _copyfrom, \
+ .digest = sha384_ ## impl_c ## _digest, \
+ .free = sha512_ ## impl_c ## _free, \
+ .hlen = 48, \
+ .blocklen = 128, \
+ HASHALG_NAMES_ANNOTATED("SHA-384", impl_display), \
+ .extra = &sha384_ ## impl_c ## _extra, \
+ }; \
+ const ssh_hashalg ssh_sha512_ ## impl_c = { \
+ .new = sha512_ ## impl_c ## _new, \
+ .reset = sha512_ ## impl_c ## _reset, \
+ .copyfrom = sha512_ ## impl_c ## _copyfrom, \
+ .digest = sha512_ ## impl_c ## _digest, \
+ .free = sha512_ ## impl_c ## _free, \
+ .hlen = 64, \
+ .blocklen = 128, \
+ HASHALG_NAMES_ANNOTATED("SHA-512", impl_display), \
+ .extra = &sha512_ ## impl_c ## _extra, \
+ }
+
+extern const uint64_t sha512_initial_state[8];
+extern const uint64_t sha384_initial_state[8];
+extern const uint64_t sha512_round_constants[80];
+
+#define SHA512_ROUNDS 80
+
+typedef struct sha512_block sha512_block;
+struct sha512_block {
+ uint8_t block[128];
+ size_t used;
+ uint64_t lenhi, lenlo;
+};
+
+static inline void sha512_block_setup(sha512_block *blk)
+{
+ blk->used = 0;
+ blk->lenhi = blk->lenlo = 0;
+}
+
+static inline bool sha512_block_write(
+ sha512_block *blk, const void **vdata, size_t *len)
+{
+ size_t blkleft = sizeof(blk->block) - blk->used;
+ size_t chunk = *len < blkleft ? *len : blkleft;
+
+ const uint8_t *p = *vdata;
+ memcpy(blk->block + blk->used, p, chunk);
+ *vdata = p + chunk;
+ *len -= chunk;
+ blk->used += chunk;
+
+ size_t chunkbits = chunk << 3;
+
+ blk->lenlo += chunkbits;
+ blk->lenhi += (blk->lenlo < chunkbits);
+
+ if (blk->used == sizeof(blk->block)) {
+ blk->used = 0;
+ return true;
+ }
+
+ return false;
+}
+
+static inline void sha512_block_pad(sha512_block *blk, BinarySink *bs)
+{
+ uint64_t final_lenhi = blk->lenhi;
+ uint64_t final_lenlo = blk->lenlo;
+ size_t pad = 127 & (111 - blk->used);
+
+ put_byte(bs, 0x80);
+ put_padding(bs, pad, 0);
+ put_uint64(bs, final_lenhi);
+ put_uint64(bs, final_lenlo);
+
+ assert(blk->used == 0 && "Should have exactly hit a block boundary");
+}