diff options
author | Mattias Andrée <maandree@kth.se> | 2019-02-09 20:44:43 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2019-02-09 20:44:43 +0100 |
commit | 8d0cea10adbe544c38ee458b9b2b67bba2c72959 (patch) | |
tree | 25cfa294cb284ca21ffb0a8c3793471dc6804543 /unmarshal.c | |
parent | Minor changes, add man pages, rename libsha2_state_initialise to libsha2_init (diff) | |
download | libsha2-8d0cea10adbe544c38ee458b9b2b67bba2c72959.tar.gz libsha2-8d0cea10adbe544c38ee458b9b2b67bba2c72959.tar.bz2 libsha2-8d0cea10adbe544c38ee458b9b2b67bba2c72959.tar.xz |
Add marshal and unmarshal functions
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r-- | unmarshal.c | 80 |
1 files changed, 80 insertions, 0 deletions
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; +} |