123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
- #include "tomcrypt_private.h"
- #include <stdarg.h>
- /**
- @file ssh_decode_sequence_multi.c
- SSH data type representation as per RFC4251, Russ Williams
- */
- #ifdef LTC_SSH
- /**
- Decode a SSH sequence using a VA list
- @param in Data to decode
- @param inlen Length of buffer to decode
- @remark <...> is of the form <type, data> (int, void*) except for string <type, data, size> (int, void*, ulong32*)
- @return CRYPT_OK on success
- */
- int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
- {
- int err;
- va_list args;
- ssh_data_type type;
- void *vdata;
- unsigned char *cdata;
- char *sdata;
- ulong32 *u32data;
- ulong64 *u64data;
- ulong32 *bufsize;
- ulong32 size;
- LTC_ARGCHK(in != NULL);
- /* Decode values from buffer */
- va_start(args, inlen);
- while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
- /* Size of length field */
- if (type == LTC_SSHDATA_STRING ||
- type == LTC_SSHDATA_NAMELIST ||
- type == LTC_SSHDATA_MPINT)
- {
- /* Check we'll not read too far */
- if (inlen < 4) {
- err = CRYPT_BUFFER_OVERFLOW;
- goto error;
- }
- }
- /* Calculate (or read) length of data */
- size = 0xFFFFFFFFU;
- switch (type) {
- case LTC_SSHDATA_BYTE:
- case LTC_SSHDATA_BOOLEAN:
- size = 1;
- break;
- case LTC_SSHDATA_UINT32:
- size = 4;
- break;
- case LTC_SSHDATA_UINT64:
- size = 8;
- break;
- case LTC_SSHDATA_STRING:
- case LTC_SSHDATA_NAMELIST:
- case LTC_SSHDATA_MPINT:
- LOAD32H(size, in);
- in += 4;
- inlen -= 4;
- break;
- case LTC_SSHDATA_EOL:
- /* Should never get here */
- err = CRYPT_INVALID_ARG;
- goto error;
- }
- /* Check we'll not read too far */
- if (inlen < size) {
- err = CRYPT_BUFFER_OVERFLOW;
- goto error;
- } else {
- inlen -= size;
- }
- /* Read data */
- switch (type) {
- case LTC_SSHDATA_BYTE:
- cdata = va_arg(args, unsigned char*);
- *cdata = *in++;
- break;
- case LTC_SSHDATA_BOOLEAN:
- cdata = va_arg(args, unsigned char*);
- /*
- The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
- interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
- */
- *cdata = (*in++)?1:0;
- break;
- case LTC_SSHDATA_UINT32:
- u32data = va_arg(args, ulong32*);
- LOAD32H(*u32data, in);
- in += 4;
- break;
- case LTC_SSHDATA_UINT64:
- u64data = va_arg(args, ulong64*);
- LOAD64H(*u64data, in);
- in += 8;
- break;
- case LTC_SSHDATA_STRING:
- case LTC_SSHDATA_NAMELIST:
- sdata = va_arg(args, char*);
- bufsize = va_arg(args, ulong32*);
- if (bufsize == NULL) {
- err = CRYPT_INVALID_ARG;
- goto error;
- }
- if (size + 1 >= *bufsize) {
- err = CRYPT_BUFFER_OVERFLOW;
- goto error;
- }
- if (size > 0) {
- XMEMCPY(sdata, (const char *)in, size);
- }
- sdata[size] = '\0';
- *bufsize = size;
- in += size;
- break;
- case LTC_SSHDATA_MPINT:
- vdata = va_arg(args, void*);
- if (size == 0) {
- if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
- } else if ((in[0] & 0x80) != 0) {
- /* Negative number - not supported */
- err = CRYPT_INVALID_PACKET;
- goto error;
- } else {
- if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; }
- }
- in += size;
- break;
- case LTC_SSHDATA_EOL:
- /* Should never get here */
- err = CRYPT_INVALID_ARG;
- goto error;
- }
- }
- err = CRYPT_OK;
- error:
- va_end(args);
- return err;
- }
- #endif
- /* ref: $Format:%D$ */
- /* git commit: $Format:%H$ */
- /* commit time: $Format:%ai$ */
|