ssh_encode_sequence_multi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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_encode_sequence_multi.c
  13. SSH data type representation as per RFC4251, Russ Williams
  14. */
  15. #ifdef LTC_SSH
  16. /**
  17. Encode a SSH sequence using a VA list
  18. @param out [out] Destination for data
  19. @param outlen [in/out] Length of buffer and resulting length of output
  20. @remark <...> is of the form <type, data> (int, void*)
  21. @return CRYPT_OK on success
  22. */
  23. int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
  24. {
  25. int err;
  26. va_list args;
  27. ulong32 size;
  28. ssh_data_type type;
  29. void *vdata;
  30. const char *sdata;
  31. int idata;
  32. ulong32 u32data;
  33. ulong64 u64data;
  34. LTC_ARGCHK(out != NULL);
  35. LTC_ARGCHK(outlen != NULL);
  36. /* Check values and calculate output size */
  37. size = 0;
  38. va_start(args, outlen);
  39. while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
  40. switch (type) {
  41. case LTC_SSHDATA_BYTE:
  42. case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */
  43. LTC_UNUSED_PARAM( va_arg(args, int) );
  44. size++;
  45. break;
  46. case LTC_SSHDATA_UINT32:
  47. LTC_UNUSED_PARAM( va_arg(args, ulong32) );
  48. size += 4;
  49. break;
  50. case LTC_SSHDATA_UINT64:
  51. LTC_UNUSED_PARAM( va_arg(args, ulong64) );
  52. size += 8;
  53. break;
  54. case LTC_SSHDATA_STRING:
  55. case LTC_SSHDATA_NAMELIST:
  56. sdata = va_arg(args, char*);
  57. size += 4;
  58. size += strlen(sdata);
  59. break;
  60. case LTC_SSHDATA_MPINT:
  61. vdata = va_arg(args, void*);
  62. /* Calculate size */
  63. size += 4;
  64. if (mp_iszero(vdata) != LTC_MP_YES) {
  65. size += mp_unsigned_bin_size(vdata);
  66. if ((mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */
  67. }
  68. break;
  69. case LTC_SSHDATA_EOL: /* Should never get here */
  70. err = CRYPT_INVALID_ARG;
  71. goto error;
  72. }
  73. }
  74. va_end(args);
  75. /* Check we have sufficient space */
  76. if (*outlen < size) {
  77. *outlen = size;
  78. err = CRYPT_BUFFER_OVERFLOW;
  79. goto errornoargs;
  80. }
  81. *outlen = size;
  82. /* Encode values into buffer */
  83. va_start(args, outlen);
  84. while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
  85. switch (type) {
  86. case LTC_SSHDATA_BYTE:
  87. idata = va_arg(args, int);
  88. *out++ = (unsigned char)(idata & 255);
  89. break;
  90. case LTC_SSHDATA_BOOLEAN:
  91. idata = va_arg(args, int);
  92. /*
  93. The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
  94. interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
  95. */
  96. *out++ = (idata)?1:0;
  97. break;
  98. case LTC_SSHDATA_UINT32:
  99. u32data = va_arg(args, ulong32);
  100. STORE32H(u32data, out);
  101. out += 4;
  102. break;
  103. case LTC_SSHDATA_UINT64:
  104. u64data = va_arg(args, ulong64);
  105. STORE64H(u64data, out);
  106. out += 8;
  107. break;
  108. case LTC_SSHDATA_STRING:
  109. case LTC_SSHDATA_NAMELIST:
  110. sdata = va_arg(args, char*);
  111. size = strlen(sdata);
  112. STORE32H(size, out);
  113. out += 4;
  114. XMEMCPY(out, sdata, size);
  115. out += size;
  116. break;
  117. case LTC_SSHDATA_MPINT:
  118. vdata = va_arg(args, void*);
  119. if (mp_iszero(vdata) == LTC_MP_YES) {
  120. STORE32H(0, out);
  121. out += 4;
  122. } else {
  123. size = mp_unsigned_bin_size(vdata);
  124. if ((mp_count_bits(vdata) & 7) == 0) {
  125. /* Zero padding if high bit set */
  126. STORE32H(size+1, out);
  127. out += 4;
  128. *out++ = 0;
  129. } else {
  130. STORE32H(size, out);
  131. out += 4;
  132. }
  133. if ((err = mp_to_unsigned_bin(vdata, out)) != CRYPT_OK) {
  134. err = CRYPT_ERROR;
  135. goto error;
  136. }
  137. out += size;
  138. }
  139. break;
  140. case LTC_SSHDATA_EOL: /* Should never get here */
  141. err = CRYPT_INVALID_ARG;
  142. goto error;
  143. }
  144. }
  145. err = CRYPT_OK;
  146. error:
  147. va_end(args);
  148. errornoargs:
  149. return err;
  150. }
  151. #endif
  152. /* ref: $Format:%D$ */
  153. /* git commit: $Format:%H$ */
  154. /* commit time: $Format:%ai$ */