ssh_decode_sequence_multi.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 Data to decode
  19. @param inlen Length of buffer to decode
  20. @remark <...> is of the form <type, data> (int, void*) except for string <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. LTC_ARGCHK(in != NULL);
  36. /* Decode values from buffer */
  37. va_start(args, inlen);
  38. while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
  39. /* Size of length field */
  40. if (type == LTC_SSHDATA_STRING ||
  41. type == LTC_SSHDATA_NAMELIST ||
  42. type == LTC_SSHDATA_MPINT)
  43. {
  44. /* Check we'll not read too far */
  45. if (inlen < 4) {
  46. err = CRYPT_BUFFER_OVERFLOW;
  47. goto error;
  48. }
  49. }
  50. /* Calculate (or read) length of data */
  51. size = 0xFFFFFFFFU;
  52. switch (type) {
  53. case LTC_SSHDATA_BYTE:
  54. case LTC_SSHDATA_BOOLEAN:
  55. size = 1;
  56. break;
  57. case LTC_SSHDATA_UINT32:
  58. size = 4;
  59. break;
  60. case LTC_SSHDATA_UINT64:
  61. size = 8;
  62. break;
  63. case LTC_SSHDATA_STRING:
  64. case LTC_SSHDATA_NAMELIST:
  65. case LTC_SSHDATA_MPINT:
  66. LOAD32H(size, in);
  67. in += 4;
  68. inlen -= 4;
  69. break;
  70. case LTC_SSHDATA_EOL:
  71. /* Should never get here */
  72. err = CRYPT_INVALID_ARG;
  73. goto error;
  74. }
  75. /* Check we'll not read too far */
  76. if (inlen < size) {
  77. err = CRYPT_BUFFER_OVERFLOW;
  78. goto error;
  79. } else {
  80. inlen -= size;
  81. }
  82. /* Read data */
  83. switch (type) {
  84. case LTC_SSHDATA_BYTE:
  85. cdata = va_arg(args, unsigned char*);
  86. *cdata = *in++;
  87. break;
  88. case LTC_SSHDATA_BOOLEAN:
  89. cdata = va_arg(args, unsigned char*);
  90. /*
  91. The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
  92. interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
  93. */
  94. *cdata = (*in++)?1:0;
  95. break;
  96. case LTC_SSHDATA_UINT32:
  97. u32data = va_arg(args, ulong32*);
  98. LOAD32H(*u32data, in);
  99. in += 4;
  100. break;
  101. case LTC_SSHDATA_UINT64:
  102. u64data = va_arg(args, ulong64*);
  103. LOAD64H(*u64data, in);
  104. in += 8;
  105. break;
  106. case LTC_SSHDATA_STRING:
  107. case LTC_SSHDATA_NAMELIST:
  108. sdata = va_arg(args, char*);
  109. bufsize = va_arg(args, ulong32*);
  110. if (bufsize == NULL) {
  111. err = CRYPT_INVALID_ARG;
  112. goto error;
  113. }
  114. if (size + 1 >= *bufsize) {
  115. err = CRYPT_BUFFER_OVERFLOW;
  116. goto error;
  117. }
  118. if (size > 0) {
  119. XMEMCPY(sdata, (const char *)in, size);
  120. }
  121. sdata[size] = '\0';
  122. *bufsize = size;
  123. in += size;
  124. break;
  125. case LTC_SSHDATA_MPINT:
  126. vdata = va_arg(args, void*);
  127. if (size == 0) {
  128. if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
  129. } else if ((in[0] & 0x80) != 0) {
  130. /* Negative number - not supported */
  131. err = CRYPT_INVALID_PACKET;
  132. goto error;
  133. } else {
  134. if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; }
  135. }
  136. in += size;
  137. break;
  138. case LTC_SSHDATA_EOL:
  139. /* Should never get here */
  140. err = CRYPT_INVALID_ARG;
  141. goto error;
  142. }
  143. }
  144. err = CRYPT_OK;
  145. error:
  146. va_end(args);
  147. return err;
  148. }
  149. #endif
  150. /* ref: $Format:%D$ */
  151. /* git commit: $Format:%H$ */
  152. /* commit time: $Format:%ai$ */