diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | libsha2.h | 25 | ||||
-rw-r--r-- | libsha2.h.0 | 10 | ||||
-rw-r--r-- | libsha2_init.3 | 2 | ||||
-rw-r--r-- | libsha2_marshal.3 | 56 | ||||
-rw-r--r-- | libsha2_unmarshal.3 | 54 | ||||
-rw-r--r-- | marshal.c | 62 | ||||
-rw-r--r-- | unmarshal.c | 80 |
9 files changed, 291 insertions, 1 deletions
@@ -22,9 +22,11 @@ OBJ =\ behex_upper.o\ digest.o\ init.o\ + marshal.o\ state_output_size.o\ sum_fd.o\ unhex.o\ + unmarshal.o\ update.o\ MAN0 =\ @@ -1,3 +1,2 @@ Add HMAC support -Add marshal support Add bit support @@ -264,5 +264,30 @@ __attribute__((__leaf__, __nonnull__, __nothrow__)) #endif void libsha2_unhex(char *restrict, const char *restrict); +/** + * Marshal a state into a buffer + * + * @param state The state to marshal + * @param buf Output buffer, `NULL` to only return the required size + * @return The number of bytes marshalled to `buf` + */ +#if defined(__GNUC__) +__attribute__((__leaf__, __nonnull__(1), __nothrow__)) +#endif +size_t libsha2_marshal(const struct libsha2_state *restrict, char *restrict); + +/** + * Unmarshal a state from a buffer + * + * @param state Output parameter for the unmarshalled state + * @param buf The buffer from which the state shall be unmarshalled + * @param bufsize The maximum number of bytes that can be unmarshalled + * @return The number of read bytes, 0 on failure + */ +#if defined(__GNUC__) +__attribute__((__leaf__, __nonnull__, __nothrow__)) +#endif +size_t libsha2_unmarshal(struct libsha2_state *restrict, const char *restrict, size_t); + #endif diff --git a/libsha2.h.0 b/libsha2.h.0 index 5e79f73..a12c6ad 100644 --- a/libsha2.h.0 +++ b/libsha2.h.0 @@ -27,6 +27,8 @@ int libsha2_sum_fd(int \fIfd\fP, enum libsha2_algorithm \fIalgorithm\fP, char *r void libsha2_behex_lower(char *restrict \fIoutput\fP, const char *restrict \fIhashsum\fP, size_t \fIn\fP); void libsha2_behex_upper(char *restrict \fIoutput\fP, const char *restrict \fIhashsum\fP, size_t \fIn\fP); void libsha2_unhex(char *restrict \fIoutput\fP, const char *restrict \fIhashsum\fP); +size_t libsha2_marshal(const struct libsha2_state *restrict \fIstate\fP, char *restrict \fIbuf\fP); +size_t libsha2_unmarshal(struct libsha2_state *restrict \fIstate\fP, const char *restrict \fIbuf\fP, size_t \fIbufsize\fP); .fi .PP Link with @@ -86,6 +88,12 @@ to hexadecimal. .TP .BR libsha2_unhex (3) Convert a hexadecimal hash to binary. +.TP +.BR libsha2_marshal (3) +Marshal a hashing state. +.TP +.BR libsha2_unmarshal (3) +Unmarshal a hashing state. .SH EXAMPLES None. .SH APPLICATION USAGE @@ -104,7 +112,9 @@ None. .BR libsha2_behex_upper (3), .BR libsha2_digest (3), .BR libsha2_init (3), +.BR libsha2_marshal (3), .BR libsha2_state_output_size (3), .BR libsha2_sum_fd (3), .BR libsha2_unhex (3), +.BR libsha2_unmarshal (3), .BR libsha2_update (3) diff --git a/libsha2_init.3 b/libsha2_init.3 index 2a11f89..cfdbba7 100644 --- a/libsha2_init.3 +++ b/libsha2_init.3 @@ -60,5 +60,7 @@ None. None. .SH SEE ALSO .BR libsha2_digest (3), +.BR libsha2_marshal (3), .BR libsha2_sum_fd (3), +.BR libsha2_unmarshal (3), .BR libsha2_update (3) diff --git a/libsha2_marshal.3 b/libsha2_marshal.3 new file mode 100644 index 0000000..3742ca6 --- /dev/null +++ b/libsha2_marshal.3 @@ -0,0 +1,56 @@ +.TH LIBSHA2_MARSHAL 3 2019-02-09 libjson +.SH NAME +libsha2_marshal \- Marshal a SHA 2 hashing state +.SH SYNOPSIS +.nf +#include <libsha2.h> + +size_t libsha2_marshal(const struct libsha2_state *restrict \fIstate\fP, char *restrict \fIbuf\fP); +.fi +.PP +Link with +.IR \-lsha2 . +.SH DESCRIPTION +The +.BR libsha2_marshal () +function marshal +.I state +into the buffer +.IR buf . +If the function is called with +.I NULL +as +.IR buf , +the required size for +.I buf +is returned. +.PP +A version number is marshalled into +.IR buf , +this allows new versions of the library to +unmarshal states marshalled by older versions. +.SH RETURN VALUE +The +.BR libsha2_init () +function returns the number of marshalled +bytes (or if +.I buf +is +.IR NULL , +the number of bytes that would have been marshalled). +.SH ERRORS +None. +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsha2_unmarshal (3) diff --git a/libsha2_unmarshal.3 b/libsha2_unmarshal.3 new file mode 100644 index 0000000..52fa2d4 --- /dev/null +++ b/libsha2_unmarshal.3 @@ -0,0 +1,54 @@ +.TH LIBSHA2_UNMARSHAL 3 2019-02-09 libjson +.SH NAME +libsha2_unmarshal \- Unmarshal a SHA 2 hashing state +.SH SYNOPSIS +.nf +#include <libsha2.h> + +size_t libsha2_unmarshal(struct libsha2_state *restrict \fIstate\fP, const char *restrict \fIbuf\fP, size_t \fIbufsize\fP); +.fi +.PP +Link with +.IR \-lsha2 . +.SH DESCRIPTION +The +.BR libsha2_unmarshal () +function unmarshal +.I state +from the buffer +.IR buf . +.I bufsize +shall be the maximum number of bytes the +function may read from +.IR buf . +.SH RETURN VALUE +The +.BR libsha2_unmarshal () +function returns the number of unmarshalled +bytes (this number is always positive) upon +successful completion, otherwise 0 is returned. +.SH ERRORS +The +.BR libsha2_unmarshal () +function will fail if: +.TP +.B EINVAL +.I bufsize +is too small or the contents of +.I buf +is invalid or created with an incompatible +version of the library. +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsha2_marshal (3) diff --git a/marshal.c b/marshal.c new file mode 100644 index 0000000..21f0f79 --- /dev/null +++ b/marshal.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Marshal a state into a buffer + * + * @param state The state to marshal + * @param buf Output buffer, `NULL` to only return the required size + * @return The number of bytes marshalled to `buf` + */ +size_t +libsha2_marshal(const struct libsha2_state *restrict state, char *restrict buf) +{ + size_t off = 0; + + if (buf) + *(int *)buf = 0; /* version */ + off += sizeof(int); + if (buf) + *(enum libsha2_algorithm *)&buf[off] = state->algorithm; + off += sizeof(enum libsha2_algorithm); + if (buf) + *(size_t *)&buf[off] = state->message_size; + off += sizeof(size_t); + + switch (state->algorithm) { + case LIBSHA2_224: + case LIBSHA2_256: + if (buf) + memcpy(&buf[off], state->k.b32, sizeof(state->k.b32)); + off += sizeof(state->k.b32); + if (buf) + memcpy(&buf[off], state->w.b32, sizeof(state->w.b32)); + off += sizeof(state->w.b32); + if (buf) + memcpy(&buf[off], state->h.b32, sizeof(state->h.b32)); + off += sizeof(state->h.b32); + break; + + default: + if (buf) + memcpy(&buf[off], state->k.b64, sizeof(state->k.b64)); + off += sizeof(state->k.b64); + if (buf) + memcpy(&buf[off], state->w.b64, sizeof(state->w.b64)); + off += sizeof(state->w.b64); + if (buf) + memcpy(&buf[off], state->h.b64, sizeof(state->h.b64)); + off += sizeof(state->h.b64); + break; + } + + if (buf) + memcpy(&buf[off], state->chunk, sizeof(state->chunk)); + off += sizeof(state->chunk); + if (buf) + *(size_t *)&buf[off] = state->chunk_size; + off += sizeof(size_t); + + return off; +} diff --git a/unmarshal.c b/unmarshal.c new file mode 100644 index 0000000..2a47b92 --- /dev/null +++ b/unmarshal.c @@ -0,0 +1,80 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Unmarshal a state from a buffer + * + * @param state Output parameter for the unmarshalled state + * @param buf The buffer from which the state shall be unmarshalled + * @param bufsize The maximum number of bytes that can be unmarshalled + * @return The number of read bytes, 0 on failure + */ +size_t +libsha2_unmarshal(struct libsha2_state *restrict state, const char *restrict buf, size_t bufsize) +{ + size_t off = 0; + + if (bufsize < sizeof(int) + sizeof(enum libsha2_algorithm) + sizeof(size_t)) { + errno = EINVAL; + return 0; + } + + if (*(int *)buf) { /* version */ + errno = EINVAL; + return 0; + } + off += sizeof(int); + + state->algorithm = *(enum libsha2_algorithm *)&buf[off]; + off += sizeof(enum libsha2_algorithm); + state->message_size = *(size_t *)&buf[off]; + off += sizeof(size_t); + + switch (state->algorithm) { + case LIBSHA2_224: + case LIBSHA2_256: + if (bufsize - off < sizeof(state->k.b32) + sizeof(state->w.b32) + sizeof(state->h.b32)) { + errno = EINVAL; + return 0; + } + memcpy(state->k.b32, &buf[off], sizeof(state->k.b32)); + off += sizeof(state->k.b32); + memcpy(state->w.b32, &buf[off], sizeof(state->w.b32)); + off += sizeof(state->w.b32); + memcpy(state->h.b32, &buf[off], sizeof(state->h.b32)); + off += sizeof(state->h.b32); + break; + + case LIBSHA2_384: + case LIBSHA2_512: + case LIBSHA2_512_224: + case LIBSHA2_512_256: + if (bufsize - off < sizeof(state->k.b64) + sizeof(state->w.b64) + sizeof(state->h.b64)) { + errno = EINVAL; + return 0; + } + memcpy(state->k.b64, &buf[off], sizeof(state->k.b64)); + off += sizeof(state->k.b64); + memcpy(state->w.b64, &buf[off], sizeof(state->w.b64)); + off += sizeof(state->w.b64); + memcpy(state->h.b64, &buf[off], sizeof(state->h.b64)); + off += sizeof(state->h.b64); + break; + + default: + errno = EINVAL; + return 0; + } + + if (bufsize - off < sizeof(state->chunk) + sizeof(size_t)) { + errno = EINVAL; + return 0; + } + memcpy(state->chunk, &buf[off], sizeof(state->chunk)); + off += sizeof(state->chunk); + state->chunk_size = *(size_t *)&buf[off]; + off += sizeof(size_t); + + return off; +} |