diff --git a/doc/crypt.tex b/doc/crypt.tex index 34ee32e50..d57bceec7 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -7233,6 +7233,73 @@ \subsection{HKDF Extract-and-Expand} Parameters are as in \textit{hkdf\_extract()} and \textit{hkdf\_expand()}. + +\mysection{SSH} + +The library provides functions to encode and decode SSH data as specified in RFC4251 Ch. 5. + +\subsection{Data types} + +The following enum is used to indicate a specific SSH data type +(besides EOL which is an internal one that indicates the end of a sequence). + +\begin{figure}[h] +\begin{center} +\begin{small} +\begin{tabular}{|l|l|l|} +\hline \textbf{Definition} & \textbf{arg data Type} & \textbf{SSH Type} \\ +\hline LTC\_SSHDATA\_EOL & - & End of SSH data sequence. \\ +\hline LTC\_SSHDATA\_BYTE & \texttt{unsigned char} & \texttt{byte} type \\ +\hline LTC\_SSHDATA\_BOOLEAN & \texttt{unsigned char} & \texttt{boolean} type \\ +\hline LTC\_SSHDATA\_UINT32 & \texttt{ulong32} & \texttt{uint32} \\ +\hline LTC\_SSHDATA\_UINT64 & \texttt{ulong64} & \texttt{uint64} \\ +\hline LTC\_SSHDATA\_STRING & \texttt{char*} & \texttt{string} (one octet per char) \\ +\hline LTC\_SSHDATA\_MPINT & \texttt{mp\_int} & \texttt{mpint} \\ +\hline LTC\_SSHDATA\_NAMELIST & \texttt{char*} & \texttt{name-list} (which works exactly like a \texttt{string}) \\ +\hline +\end{tabular} +\caption{List of SSH Supported Types} +\index{ssh\_data\_type} +\end{small} +\end{center} +\end{figure} + +\subsection{De- and Encoding with Multiple Argument Lists} + +\index{ssh\_encode\_sequence\_multi()} +\index{ssh\_decode\_sequence\_multi()} + + +The API works similar to the ASN.1 SEQUENCE multi en- and decoders. + +They either encode or decode a sequence of the supported SSH types where the items are specified after the length parameter. + + +\begin{verbatim} +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +\end{verbatim} + +Where \texttt{out} points to the destination buffer and \texttt{outlen} points +on function invocation to the length of the destination buffer +and after returning it will be filled with the number of octets written to the buffer. + +The encoding function \texttt{ssh\_encode\_sequence\_multi()} expects its items to be a pair of \texttt{(type, data)}, +except for the \texttt{string} resp. \texttt{name-list} type, which expects the triple \texttt{(type, data, size)} +with \texttt{size} being of type \texttt{unsigned long}. + + +\begin{verbatim} +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...); +\end{verbatim} + +Where \texttt{in} points to the buffer with the sequence to decode and \texttt{inlen} points +on function invocation to the length of the sequence +and after returning it will be filled with the decoded number of octets. + +The decoding function \texttt{ssh\_decode\_sequence\_multi()} expects its items to be a pair of \texttt{(type, data*)}, +except for the \texttt{string} resp. \texttt{name-list} type, which expects the triple \texttt{(type, data, size*)} +with \texttt{size*} being of type \texttt{unsigned long*}. + \chapter{Miscellaneous} \mysection{Base64 Encoding and Decoding} The library provides functions to encode and decode a RFC 4648 Base64 coding scheme. diff --git a/src/headers/tomcrypt_misc.h b/src/headers/tomcrypt_misc.h index 4860a1b35..3fc619905 100644 --- a/src/headers/tomcrypt_misc.h +++ b/src/headers/tomcrypt_misc.h @@ -163,6 +163,7 @@ int padding_depad(const unsigned char *data, unsigned long *length, unsigned lon #ifdef LTC_SSH typedef enum ssh_data_type_ { + LTC_SSHDATA_EOL, LTC_SSHDATA_BYTE, LTC_SSHDATA_BOOLEAN, LTC_SSHDATA_UINT32, @@ -170,12 +171,11 @@ typedef enum ssh_data_type_ { LTC_SSHDATA_STRING, LTC_SSHDATA_MPINT, LTC_SSHDATA_NAMELIST, - LTC_SSHDATA_EOL } ssh_data_type; /* VA list handy helpers with tuples of */ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); -int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...); #endif /* LTC_SSH */ int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); diff --git a/src/misc/ssh/ssh_decode_sequence_multi.c b/src/misc/ssh/ssh_decode_sequence_multi.c index 5828cfbd5..a3be11ef9 100644 --- a/src/misc/ssh/ssh_decode_sequence_multi.c +++ b/src/misc/ssh/ssh_decode_sequence_multi.c @@ -18,12 +18,12 @@ /** Decode a SSH sequence using a VA list - @param in Data to decode - @param inlen Length of buffer to decode - @remark <...> is of the form (int, void*) except for string + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*) @return CRYPT_OK on success */ -int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) { int err; va_list args; @@ -33,11 +33,14 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) char *sdata; ulong32 *u32data; ulong64 *u64data; - unsigned long bufsize; + unsigned long *bufsize; ulong32 size; + unsigned long remaining; LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + remaining = *inlen; /* Decode values from buffer */ va_start(args, inlen); 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, ...) type == LTC_SSHDATA_MPINT) { /* Check we'll not read too far */ - if (inlen < 4) { + if (remaining < 4) { err = CRYPT_BUFFER_OVERFLOW; goto error; } @@ -71,7 +74,7 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) case LTC_SSHDATA_MPINT: LOAD32H(size, in); in += 4; - inlen -= 4; + remaining -= 4; break; case LTC_SSHDATA_EOL: @@ -81,55 +84,63 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) } /* Check we'll not read too far */ - if (inlen < size) { + if (remaining < size) { err = CRYPT_BUFFER_OVERFLOW; goto error; } else { - inlen -= size; + remaining -= size; + } + + vdata = va_arg(args, void*); + if (vdata == NULL) { + err = CRYPT_INVALID_ARG; + goto error; } /* Read data */ switch (type) { case LTC_SSHDATA_BYTE: - cdata = va_arg(args, unsigned char*); + cdata = vdata; *cdata = *in++; break; case LTC_SSHDATA_BOOLEAN: - cdata = va_arg(args, unsigned char*); + cdata = vdata; /* 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. - */ + */ *cdata = (*in++)?1:0; break; case LTC_SSHDATA_UINT32: - u32data = va_arg(args, ulong32*); + u32data = vdata; LOAD32H(*u32data, in); in += 4; break; case LTC_SSHDATA_UINT64: - u64data = va_arg(args, ulong64*); + u64data = vdata; LOAD64H(*u64data, in); in += 8; break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: - sdata = va_arg(args, char*); - bufsize = va_arg(args, unsigned long); - if (size >= bufsize) { + sdata = vdata; + bufsize = va_arg(args, unsigned long*); + if (bufsize == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + if (size + 1 >= *bufsize) { err = CRYPT_BUFFER_OVERFLOW; goto error; } if (size > 0) { - XSTRNCPY(sdata, (const char *)in, size); - sdata[size] = '\0'; /* strncpy doesn't NUL-terminate */ - } else { - *sdata = '\0'; + XMEMCPY(sdata, (const char *)in, size); } + sdata[size] = '\0'; + *bufsize = size; in += size; break; case LTC_SSHDATA_MPINT: - vdata = va_arg(args, void*); if (size == 0) { if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; } } else if ((in[0] & 0x80) != 0) { @@ -150,6 +161,8 @@ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) } err = CRYPT_OK; + *inlen -= remaining; + error: va_end(args); return err; diff --git a/src/misc/ssh/ssh_encode_sequence_multi.c b/src/misc/ssh/ssh_encode_sequence_multi.c index 5d8349761..ed81e9f08 100644 --- a/src/misc/ssh/ssh_encode_sequence_multi.c +++ b/src/misc/ssh/ssh_encode_sequence_multi.c @@ -20,7 +20,7 @@ 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 (int, void*) + @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long) @return CRYPT_OK on success */ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) @@ -29,8 +29,8 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) va_list args; ulong32 size; ssh_data_type type; - void *vdata; - const char *sdata; + void *vdata; + const char *sdata; int idata; ulong32 u32data; ulong64 u64data; @@ -58,9 +58,9 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: - sdata = va_arg(args, char*); + LTC_UNUSED_PARAM( va_arg(args, char*) ); + size += va_arg(args, unsigned long); size += 4; - size += strlen(sdata); break; case LTC_SSHDATA_MPINT: vdata = va_arg(args, void*); @@ -102,7 +102,7 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) /* 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: @@ -118,7 +118,7 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: sdata = va_arg(args, char*); - size = strlen(sdata); + size = va_arg(args, unsigned long); STORE32H(size, out); out += 4; XMEMCPY(out, sdata, size); diff --git a/src/pk/ecc/ecc_recover_key.c b/src/pk/ecc/ecc_recover_key.c index d3a70df7a..9b7da1102 100644 --- a/src/pk/ecc/ecc_recover_key.c +++ b/src/pk/ecc/ecc_recover_key.c @@ -114,19 +114,20 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, #ifdef LTC_SSH else if (sigformat == LTC_ECCSIG_RFC5656) { char name[64], name2[64]; - unsigned long namelen = sizeof(name2); + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); /* Decode as SSH data sequence, per RFC4251 */ - if ((err = ssh_decode_sequence_multi(sig, siglen, - LTC_SSHDATA_STRING, name, 64, + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &namelen, key)) != CRYPT_OK) { goto error; } - if (XSTRCMP(name,name2) != 0) { + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; } diff --git a/src/pk/ecc/ecc_sign_hash.c b/src/pk/ecc/ecc_sign_hash.c index c7a808d8d..bb7a2e961 100644 --- a/src/pk/ecc/ecc_sign_hash.c +++ b/src/pk/ecc/ecc_sign_hash.c @@ -164,7 +164,7 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, /* Store as SSH data sequence, per RFC4251 */ err = ssh_encode_sequence_multi(out, outlen, - LTC_SSHDATA_STRING, name, + LTC_SSHDATA_STRING, name, namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL); diff --git a/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c index 048f29d24..d29346bb6 100644 --- a/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c +++ b/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c @@ -25,8 +25,7 @@ int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key { char oidstr[64]; unsigned long oidlen = sizeof(oidstr); - unsigned long size = 0; - int err; + int err, size = 0; LTC_ARGCHK(buffer != NULL); LTC_ARGCHK(buflen != NULL); @@ -52,8 +51,11 @@ int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr); } - /* snprintf returns size that would have been written, but limits to buflen-1 chars plus terminator */ - if (size >= *buflen) { + /* snprintf returns a negative value on error + * or the size that would have been written, but limits to buflen-1 chars plus terminator */ + if (size < 0) { + err = CRYPT_ERROR; + } else if ((unsigned)size >= *buflen) { err = CRYPT_BUFFER_OVERFLOW; } else { err = CRYPT_OK; diff --git a/src/pk/ecc/ecc_verify_hash.c b/src/pk/ecc/ecc_verify_hash.c index ec9e7f101..20a89c25e 100644 --- a/src/pk/ecc/ecc_verify_hash.c +++ b/src/pk/ecc/ecc_verify_hash.c @@ -100,19 +100,20 @@ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, #ifdef LTC_SSH else if (sigformat == LTC_ECCSIG_RFC5656) { char name[64], name2[64]; - unsigned long namelen = sizeof(name2); + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); /* Decode as SSH data sequence, per RFC4251 */ - if ((err = ssh_decode_sequence_multi(sig, siglen, - LTC_SSHDATA_STRING, name, 64, + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &namelen, key)) != CRYPT_OK) { goto error; } - if (XSTRCMP(name,name2) != 0) { + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; } diff --git a/tests/common.h b/tests/common.h index 5f2ac3cc7..34bbf9086 100644 --- a/tests/common.h +++ b/tests/common.h @@ -17,10 +17,12 @@ extern prng_state yarrow_prng; #define DO(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0) #define DOX(x, str) do { fprintf(stderr, "%s - %s:\n", #x, (str)); run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0) #define SHOULD_FAIL(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSURE(x) do { fprintf(stderr, "%s:\n", #x); run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) #else #define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0) #define DOX(x, str) do { run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0) #define SHOULD_FAIL(x) do { run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSURE(x) do { run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) #endif #define COMPARE_TESTVECTOR(i, il, s, sl, wa, wi) do { DO(do_compare_testvector((i), (il), (s), (sl), (wa), (wi))); } while(0) diff --git a/tests/ssh_test.c b/tests/ssh_test.c index 5ca3ddfbd..eee977936 100644 --- a/tests/ssh_test.c +++ b/tests/ssh_test.c @@ -61,16 +61,16 @@ static int _ssh_encoding_test(void) { unsigned char buffer[BUFSIZE]; unsigned long buflen; + unsigned long len; void *v, *zero; int err; /* Buffer too short */ buflen = 3; zeromem(buffer, BUFSIZE); - err = ssh_encode_sequence_multi(buffer, &buflen, - LTC_SSHDATA_UINT32, 0x29b7f4aa, - LTC_SSHDATA_EOL, NULL); - if (err != CRYPT_BUFFER_OVERFLOW) return CRYPT_FAIL_TESTVECTOR; + SHOULD_FAIL(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_UINT32, 0x29b7f4aa, + LTC_SSHDATA_EOL, NULL)); /* byte */ @@ -125,8 +125,9 @@ static int _ssh_encoding_test(void) /* string */ buflen = BUFSIZE; zeromem(buffer, BUFSIZE); + len = strlen("testing"); DO(ssh_encode_sequence_multi(buffer, &buflen, - LTC_SSHDATA_STRING, "testing", + LTC_SSHDATA_STRING, "testing", len, LTC_SSHDATA_EOL, NULL)); COMPARE_TESTVECTOR(buffer, buflen, string, sizeof(string), "enc-string", 1); @@ -166,22 +167,25 @@ static int _ssh_encoding_test(void) /* name-list */ buflen = BUFSIZE; zeromem(buffer, BUFSIZE); + len = strlen(""); DO(ssh_encode_sequence_multi(buffer, &buflen, - LTC_SSHDATA_NAMELIST, "", + LTC_SSHDATA_NAMELIST, "", len, LTC_SSHDATA_EOL, NULL)); COMPARE_TESTVECTOR(buffer, buflen, nlist1, sizeof(nlist1), "enc-nlist", 1); buflen = BUFSIZE; zeromem(buffer, BUFSIZE); + len = strlen("zlib"); DO(ssh_encode_sequence_multi(buffer, &buflen, - LTC_SSHDATA_NAMELIST, "zlib", + LTC_SSHDATA_NAMELIST, "zlib", len, LTC_SSHDATA_EOL, NULL)); COMPARE_TESTVECTOR(buffer, buflen, nlist2, sizeof(nlist2), "enc-nlist", 2); buflen = BUFSIZE; zeromem(buffer, BUFSIZE); + len = strlen("zlib,none"); DO(ssh_encode_sequence_multi(buffer, &buflen, - LTC_SSHDATA_NAMELIST, "zlib,none", + LTC_SSHDATA_NAMELIST, "zlib,none", len, LTC_SSHDATA_EOL, NULL)); COMPARE_TESTVECTOR(buffer, buflen, nlist3, sizeof(nlist3), "enc-nlist", 3); @@ -196,93 +200,138 @@ static int _ssh_decoding_test(void) { char strbuf[BUFSIZE]; void *u, *v; + unsigned long size; ulong32 tmp32; ulong64 tmp64; unsigned char tmp8; + unsigned long len; int err; + /* Buffer longer */ + len = sizeof(strbuf); + strbuf[0] = 0; + DO(ssh_decode_sequence_multi((unsigned char*)strbuf, &len, + LTC_SSHDATA_BYTE, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x00); + ENSURE(len == 1); + + /* byte */ - DO(ssh_decode_sequence_multi(byte1, sizeof(byte1), + len = sizeof(byte1); + DO(ssh_decode_sequence_multi(byte1, &len, LTC_SSHDATA_BYTE, &tmp8, LTC_SSHDATA_EOL, NULL)); - if (tmp8 != 0x01) return CRYPT_FAIL_TESTVECTOR; + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); - DO(ssh_decode_sequence_multi(byte2, sizeof(byte2), + len = sizeof(byte2); + DO(ssh_decode_sequence_multi(byte2, &len, LTC_SSHDATA_BYTE, &tmp8, LTC_SSHDATA_EOL, NULL)); - if (tmp8 != 0x71) return CRYPT_FAIL_TESTVECTOR; + ENSURE(tmp8 == 0x71); + ENSURE(len == 1); /* boolean */ - DO(ssh_decode_sequence_multi(byte1, sizeof(byte1), + len = sizeof(byte1); + DO(ssh_decode_sequence_multi(byte1, &len, LTC_SSHDATA_BOOLEAN, &tmp8, LTC_SSHDATA_EOL, NULL)); - if (tmp8 != 0x01) return CRYPT_FAIL_TESTVECTOR; + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); - DO(ssh_decode_sequence_multi(byte2, sizeof(byte2), + len = sizeof(byte2); + DO(ssh_decode_sequence_multi(byte2, &len, LTC_SSHDATA_BOOLEAN, &tmp8, LTC_SSHDATA_EOL, NULL)); - if (tmp8 != 0x01) return CRYPT_FAIL_TESTVECTOR; + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); /* uint32 */ - DO(ssh_decode_sequence_multi(uint32, sizeof(uint32), + len = sizeof(uint32); + DO(ssh_decode_sequence_multi(uint32, &len, LTC_SSHDATA_UINT32, &tmp32, LTC_SSHDATA_EOL, NULL)); - if (tmp32 != 0x29b7f4aa) return CRYPT_FAIL_TESTVECTOR; + ENSURE(tmp32 == 0x29b7f4aa); + ENSURE(len == 4); /* uint64 */ - DO(ssh_decode_sequence_multi(uint64, sizeof(uint64), + len = sizeof(uint64); + DO(ssh_decode_sequence_multi(uint64, &len, LTC_SSHDATA_UINT64, &tmp64, LTC_SSHDATA_EOL, NULL)); if (tmp64 != CONST64(0x09a378f9b2e332a7)) return CRYPT_FAIL_TESTVECTOR; + ENSURE(len == 8); /* string */ zeromem(strbuf, BUFSIZE); - DO(ssh_decode_sequence_multi(string, sizeof(string), - LTC_SSHDATA_STRING, strbuf, BUFSIZE, + size = BUFSIZE; + len = sizeof(string); + DO(ssh_decode_sequence_multi(string, &len, + LTC_SSHDATA_STRING, strbuf, &size, LTC_SSHDATA_EOL, NULL)); - if (XSTRCMP(strbuf, "testing") != 0) return CRYPT_FAIL_TESTVECTOR; + ENSURE(strlen("testing") == size); + ENSURE(XSTRCMP(strbuf, "testing") == 0); + ENSURE(strlen("testing") + 4 == len); /* mpint */ if ((err = mp_init_multi(&u, &v, NULL)) != CRYPT_OK) { return err; } - DO(ssh_decode_sequence_multi(mpint1, sizeof(mpint1), + len = sizeof(mpint1); + DO(ssh_decode_sequence_multi(mpint1, &len, LTC_SSHDATA_MPINT, v, LTC_SSHDATA_EOL, NULL)); - if (mp_cmp_d(v, 0) != LTC_MP_EQ) return CRYPT_FAIL_TESTVECTOR; + ENSURE(mp_cmp_d(v, 0) == LTC_MP_EQ); + ENSURE(sizeof(mpint1) == len); - DO(mp_read_radix(u, "9a378f9b2e332a7", 16)); - DO(ssh_decode_sequence_multi(mpint2, sizeof(mpint2), + len = sizeof(mpint2); + DO(ssh_decode_sequence_multi(mpint2, &len, LTC_SSHDATA_MPINT, v, LTC_SSHDATA_EOL, NULL)); - if (mp_cmp(u, v) != LTC_MP_EQ) return CRYPT_FAIL_TESTVECTOR; + DO(mp_read_radix(u, "9a378f9b2e332a7", 16)); + ENSURE(mp_cmp(u, v) == LTC_MP_EQ); + ENSURE(sizeof(mpint2) == len); - DO(ssh_decode_sequence_multi(mpint3, sizeof(mpint3), + len = sizeof(mpint3); + DO(ssh_decode_sequence_multi(mpint3, &len, LTC_SSHDATA_MPINT, v, LTC_SSHDATA_EOL, NULL)); - if (mp_cmp_d(v, 0x80) != LTC_MP_EQ) return CRYPT_FAIL_TESTVECTOR; + ENSURE(mp_cmp_d(v, 0x80) == LTC_MP_EQ); + ENSURE(sizeof(mpint3) == len); mp_clear_multi(v, u, NULL); /* name-list */ zeromem(strbuf, BUFSIZE); - DO(ssh_decode_sequence_multi(nlist1, sizeof(nlist1), - LTC_SSHDATA_NAMELIST, strbuf, BUFSIZE, + size = BUFSIZE; + len = sizeof(nlist1); + DO(ssh_decode_sequence_multi(nlist1, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, LTC_SSHDATA_EOL, NULL)); - if (XSTRCMP(strbuf, "") != 0) return CRYPT_FAIL_TESTVECTOR; + ENSURE(strlen("") == size); + ENSURE(XSTRCMP(strbuf, "") == 0); zeromem(strbuf, BUFSIZE); - DO(ssh_decode_sequence_multi(nlist2, sizeof(nlist2), - LTC_SSHDATA_NAMELIST, strbuf, BUFSIZE, + size = BUFSIZE; + len = sizeof(nlist2); + DO(ssh_decode_sequence_multi(nlist2, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, LTC_SSHDATA_EOL, NULL)); - if (XSTRCMP(strbuf, "zlib") != 0) return CRYPT_FAIL_TESTVECTOR; + ENSURE(strlen("zlib") == size); + ENSURE(XSTRCMP(strbuf, "zlib") == 0); + ENSURE(strlen("zlib") + 4 == len); zeromem(strbuf, BUFSIZE); - DO(ssh_decode_sequence_multi(nlist3, sizeof(nlist3), - LTC_SSHDATA_NAMELIST, strbuf, BUFSIZE, + size = BUFSIZE; + len = sizeof(nlist3); + DO(ssh_decode_sequence_multi(nlist3, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, LTC_SSHDATA_EOL, NULL)); - if (XSTRCMP(strbuf, "zlib,none") != 0) return CRYPT_FAIL_TESTVECTOR; + ENSURE(strlen("zlib,none") == size); + ENSURE(XSTRCMP(strbuf, "zlib,none") == 0); + ENSURE(strlen("zlib,none") + 4 == len); return CRYPT_OK;