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