ssh_decode_sequence_multi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis
  2. *
  3. * LibTomCrypt is a library that provides various cryptographic
  4. * algorithms in a highly modular and flexible manner.
  5. *
  6. * The library is free for all purposes without any express
  7. * guarantee it works.
  8. */
  9. #include "tomcrypt_private.h"
  10. #include <stdarg.h>
  11. /**
  12. @file ssh_decode_sequence_multi.c
  13. SSH data type representation as per RFC4251, Russ Williams
  14. */
  15. #ifdef LTC_SSH
  16. /**
  17. Decode a SSH sequence using a VA list
  18. @param in The input buffer
  19. @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
  20. @remark <...> is of the form <type, data*> (int, <unsigned char*,ulong32*,ulong64*>) except for string&name-list <type, data, size*> (int, void*, ulong32*)
  21. @return CRYPT_OK on success
  22. */
  23. int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...)
  24. {
  25. int err;
  26. va_list args;
  27. ssh_data_type type;
  28. void *vdata;
  29. unsigned char *cdata;
  30. char *sdata;
  31. ulong32 *u32data;
  32. ulong64 *u64data;
  33. ulong32 *bufsize;
  34. ulong32 size;
  35. unsigned long remaining;
  36. LTC_ARGCHK(in != NULL);
  37. LTC_ARGCHK(inlen != NULL);
  38. remaining = *inlen;
  39. /* Decode values from buffer */
  40. va_start(args, inlen);
  41. while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
  42. /* Size of length field */
  43. if (type == LTC_SSHDATA_STRING ||
  44. type == LTC_SSHDATA_NAMELIST ||
  45. type == LTC_SSHDATA_MPINT)
  46. {
  47. /* Check we'll not read too far */
  48. if (remaining < 4) {
  49. err = CRYPT_BUFFER_OVERFLOW;
  50. goto error;
  51. }
  52. }
  53. /* Calculate (or read) length of data */
  54. size = 0xFFFFFFFFU;
  55. switch (type) {
  56. case LTC_SSHDATA_BYTE:
  57. case LTC_SSHDATA_BOOLEAN:
  58. size = 1;
  59. break;
  60. case LTC_SSHDATA_UINT32:
  61. size = 4;
  62. break;
  63. case LTC_SSHDATA_UINT64:
  64. size = 8;
  65. break;
  66. case LTC_SSHDATA_STRING:
  67. case LTC_SSHDATA_NAMELIST:
  68. case LTC_SSHDATA_MPINT:
  69. LOAD32H(size, in);
  70. in += 4;
  71. remaining -= 4;
  72. break;
  73. case LTC_SSHDATA_EOL:
  74. /* Should never get here */
  75. err = CRYPT_INVALID_ARG;
  76. goto error;
  77. }
  78. /* Check we'll not read too far */
  79. if (remaining < size) {
  80. err = CRYPT_BUFFER_OVERFLOW;
  81. goto error;
  82. } else {
  83. remaining -= size;
  84. }
  85. vdata = va_arg(args, void*);
  86. if (vdata == NULL) {
  87. err = CRYPT_INVALID_ARG;
  88. goto error;
  89. }
  90. /* Read data */
  91. switch (type) {
  92. case LTC_SSHDATA_BYTE:
  93. cdata = vdata;
  94. *cdata = *in++;
  95. break;
  96. case LTC_SSHDATA_BOOLEAN:
  97. cdata = vdata;
  98. /*
  99. The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
  100. interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
  101. */
  102. *cdata = (*in++)?1:0;
  103. break;
  104. case LTC_SSHDATA_UINT32:
  105. u32data = vdata;
  106. LOAD32H(*u32data, in);
  107. in += 4;
  108. break;
  109. case LTC_SSHDATA_UINT64:
  110. u64data = vdata;
  111. LOAD64H(*u64data, in);
  112. in += 8;
  113. break;
  114. case LTC_SSHDATA_STRING:
  115. case LTC_SSHDATA_NAMELIST:
  116. sdata = vdata;
  117. bufsize = va_arg(args, ulong32*);
  118. if (bufsize == NULL) {
  119. err = CRYPT_INVALID_ARG;
  120. goto error;
  121. }
  122. if (size + 1 >= *bufsize) {
  123. err = CRYPT_BUFFER_OVERFLOW;
  124. goto error;
  125. }
  126. if (size > 0) {
  127. XMEMCPY(sdata, (const char *)in, size);
  128. }
  129. sdata[size] = '\0';
  130. *bufsize = size;
  131. in += size;
  132. break;
  133. case LTC_SSHDATA_MPINT:
  134. if (size == 0) {
  135. if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
  136. } else if ((in[0] & 0x80) != 0) {
  137. /* Negative number - not supported */
  138. err = CRYPT_INVALID_PACKET;
  139. goto error;
  140. } else {
  141. if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; }
  142. }
  143. in += size;
  144. break;
  145. case LTC_SSHDATA_EOL:
  146. /* Should never get here */
  147. err = CRYPT_INVALID_ARG;
  148. goto error;
  149. }
  150. }
  151. err = CRYPT_OK;
  152. *inlen -= remaining;
  153. error:
  154. va_end(args);
  155. return err;
  156. }
  157. #endif
  158. /* ref: $Format:%D$ */
  159. /* git commit: $Format:%H$ */
  160. /* commit time: $Format:%ai$ */