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