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; +}  | 
