1818
1919/**
2020 Decode a SSH sequence using a VA list
21- @param in Data to decode
22- @param inlen Length of buffer to decode
23- @remark <...> is of the form <type, data> (int, void* ) except for string <type, data, size>
21+ @param in The input buffer
22+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
23+ @remark <...> is of the form <type, data* > (int, <unsigned char*,ulong32*,ulong64*> ) except for string&name-list <type, data, size*> (int, void*, unsigned long*)
2424 @return CRYPT_OK on success
2525*/
26- int ssh_decode_sequence_multi (const unsigned char * in , unsigned long inlen , ...)
26+ int ssh_decode_sequence_multi (const unsigned char * in , unsigned long * inlen , ...)
2727{
2828 int err ;
2929 va_list args ;
@@ -33,11 +33,14 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
3333 char * sdata ;
3434 ulong32 * u32data ;
3535 ulong64 * u64data ;
36- unsigned long bufsize ;
36+ unsigned long * bufsize ;
3737 ulong32 size ;
38+ unsigned long remaining ;
3839
3940 LTC_ARGCHK (in != NULL );
41+ LTC_ARGCHK (inlen != NULL );
4042
43+ remaining = * inlen ;
4144 /* Decode values from buffer */
4245 va_start (args , inlen );
4346 while ((type = (ssh_data_type )va_arg (args , int )) != LTC_SSHDATA_EOL ) {
@@ -47,7 +50,7 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
4750 type == LTC_SSHDATA_MPINT )
4851 {
4952 /* Check we'll not read too far */
50- if (inlen < 4 ) {
53+ if (remaining < 4 ) {
5154 err = CRYPT_BUFFER_OVERFLOW ;
5255 goto error ;
5356 }
@@ -71,7 +74,7 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
7174 case LTC_SSHDATA_MPINT :
7275 LOAD32H (size , in );
7376 in += 4 ;
74- inlen -= 4 ;
77+ remaining -= 4 ;
7578 break ;
7679
7780 case LTC_SSHDATA_EOL :
@@ -81,55 +84,63 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
8184 }
8285
8386 /* Check we'll not read too far */
84- if (inlen < size ) {
87+ if (remaining < size ) {
8588 err = CRYPT_BUFFER_OVERFLOW ;
8689 goto error ;
8790 } else {
88- inlen -= size ;
91+ remaining -= size ;
92+ }
93+
94+ vdata = va_arg (args , void * );
95+ if (vdata == NULL ) {
96+ err = CRYPT_INVALID_ARG ;
97+ goto error ;
8998 }
9099
91100 /* Read data */
92101 switch (type ) {
93102 case LTC_SSHDATA_BYTE :
94- cdata = va_arg ( args , unsigned char * ) ;
103+ cdata = vdata ;
95104 * cdata = * in ++ ;
96105 break ;
97106 case LTC_SSHDATA_BOOLEAN :
98- cdata = va_arg ( args , unsigned char * ) ;
107+ cdata = vdata ;
99108 /*
100109 The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be
101110 interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1.
102- */
111+ */
103112 * cdata = (* in ++ )?1 :0 ;
104113 break ;
105114 case LTC_SSHDATA_UINT32 :
106- u32data = va_arg ( args , ulong32 * ) ;
115+ u32data = vdata ;
107116 LOAD32H (* u32data , in );
108117 in += 4 ;
109118 break ;
110119 case LTC_SSHDATA_UINT64 :
111- u64data = va_arg ( args , ulong64 * ) ;
120+ u64data = vdata ;
112121 LOAD64H (* u64data , in );
113122 in += 8 ;
114123 break ;
115124 case LTC_SSHDATA_STRING :
116125 case LTC_SSHDATA_NAMELIST :
117- sdata = va_arg (args , char * );
118- bufsize = va_arg (args , unsigned long );
119- if (size >= bufsize ) {
126+ sdata = vdata ;
127+ bufsize = va_arg (args , unsigned long * );
128+ if (bufsize == NULL ) {
129+ err = CRYPT_INVALID_ARG ;
130+ goto error ;
131+ }
132+ if (size + 1 >= * bufsize ) {
120133 err = CRYPT_BUFFER_OVERFLOW ;
121134 goto error ;
122135 }
123136 if (size > 0 ) {
124- XSTRNCPY (sdata , (const char * )in , size );
125- sdata [size ] = '\0' ; /* strncpy doesn't NUL-terminate */
126- } else {
127- * sdata = '\0' ;
137+ XMEMCPY (sdata , (const char * )in , size );
128138 }
139+ sdata [size ] = '\0' ;
140+ * bufsize = size ;
129141 in += size ;
130142 break ;
131143 case LTC_SSHDATA_MPINT :
132- vdata = va_arg (args , void * );
133144 if (size == 0 ) {
134145 if ((err = mp_set (vdata , 0 )) != CRYPT_OK ) { goto error ; }
135146 } else if ((in [0 ] & 0x80 ) != 0 ) {
@@ -150,6 +161,8 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
150161 }
151162 err = CRYPT_OK ;
152163
164+ * inlen -= remaining ;
165+
153166error :
154167 va_end (args );
155168 return err ;
0 commit comments