Skip to content

Commit b602da5

Browse files
committed
Initial commit of SSH+ECDSA signature format
Wrap signature format in #ifdef LTC_SSH Update docs Code review fixes Replace strcmp/memcmp with XSTRCMP/XMEMCMP for check-source Fix for check-defines XSTRCMP/XMEMCMP != 0 GCC7.3 wants only literal strings for sprintf format Code review changes Rework SSH decoding and tests Fix encoding and tests COMPARE_TESTVECTOR macro Single return point in ssh_decode_sequence_multi Actually use XSTRNCPY rather than just defining it More code review fixes Code review tweaks Ensure it's not possible to read past buffer end Keep track of size remaining, not end pointer
1 parent 838feac commit b602da5

18 files changed

+910
-184
lines changed

doc/crypt.tex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5631,6 +5631,7 @@ \subsection{Signature Formats}
56315631
\hline LTC\_ECCSIG\_ANSIX962 & ASN.1 encoded, ANSI X9.62 \\
56325632
\hline LTC\_ECCSIG\_RFC7518 & raw R, S values as defined in RFC7518 \\
56335633
\hline LTC\_ECCSIG\_ETH27 & raw R, S, V values (V has 27 added) \\
5634+
\hline LTC\_ECCSIG\_RFC5656 & SSH+ECDSA format as defined in RFC5656 \\
56345635
\hline
56355636
\end{tabular}
56365637
\end{center}
@@ -7792,7 +7793,7 @@ \subsubsection{Endianness}
77927793
There are also options you can specify from the \textit{tomcrypt\_custom.h} header file.
77937794

77947795
\subsection{X memory routines}
7795-
\index{XMALLOC}\index{XREALLOC}\index{XCALLOC}\index{XFREE}\index{XMEMSET}\index{XMEMCPY}\index{XMEMMOVE}\index{XMEMCMP}\index{XSTRCMP}
7796+
\index{XMALLOC}\index{XREALLOC}\index{XCALLOC}\index{XFREE}\index{XMEMSET}\index{XMEMCPY}\index{XMEMMOVE}\index{XMEMCMP}\index{XSTRCMP}\index{XSTRNCPY}
77967797
At the top of tomcrypt\_custom.h are a series of macros denoted as XMALLOC, XCALLOC, XREALLOC, XFREE, and so on. They resolve to
77977798
the name of the respective functions from the standard C library by default. This lets you substitute in your own memory routines.
77987799
If you substitute in your own functions they must behave like the standard C library functions in terms of what they expect as input and

helper.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ sub check_source {
5353
push @{$troubles->{unwanted_memmove}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemmove\s*\(/;
5454
push @{$troubles->{unwanted_memcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcmp\s*\(/;
5555
push @{$troubles->{unwanted_strcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcmp\s*\(/;
56+
push @{$troubles->{unwanted_strcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcpy\s*\(/;
57+
push @{$troubles->{unwanted_strncpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrncpy\s*\(/;
5658
push @{$troubles->{unwanted_clock}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bclock\s*\(/;
5759
push @{$troubles->{unwanted_qsort}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bqsort\s*\(/;
5860
push @{$troubles->{sizeof_no_brackets}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bsizeof\s*[^\(]/;

src/headers/tomcrypt_custom.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@
4343
#define XMEM_NEQ mem_neq
4444
#endif
4545
#ifndef XSTRCMP
46-
#define XSTRCMP strcmp
46+
#define XSTRCMP strcmp
47+
#endif
48+
#ifndef XSTRNCPY
49+
#define XSTRNCPY strncpy
4750
#endif
4851

4952
#ifndef XCLOCK
@@ -56,7 +59,7 @@
5659

5760
#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \
5861
defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \
59-
defined(clock) || defined(qsort) ) && !defined(LTC_NO_PROTOTYPES)
62+
defined(strncpy) || defined(clock) || defined(qsort) ) && !defined(LTC_NO_PROTOTYPES)
6063
#define LTC_NO_PROTOTYPES
6164
#endif
6265

@@ -494,6 +497,8 @@
494497

495498
#define LTC_CRC32
496499

500+
#define LTC_SSH
501+
497502
#define LTC_PADDING
498503

499504
#define LTC_PBES

src/headers/tomcrypt_misc.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,23 @@ int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded
154154
int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode);
155155
#endif /* LTC_PADDING */
156156

157+
#ifdef LTC_SSH
158+
typedef enum ssh_data_type_ {
159+
LTC_SSHDATA_BYTE,
160+
LTC_SSHDATA_BOOLEAN,
161+
LTC_SSHDATA_UINT32,
162+
LTC_SSHDATA_UINT64,
163+
LTC_SSHDATA_STRING,
164+
LTC_SSHDATA_MPINT,
165+
LTC_SSHDATA_NAMELIST,
166+
LTC_SSHDATA_EOL
167+
} ssh_data_type;
168+
169+
/* VA list handy helpers with tuples of <type, data> */
170+
int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
171+
int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
172+
#endif /* LTC_SSH */
173+
157174
int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which);
158175

159176
/* ref: $Format:%D$ */

src/headers/tomcrypt_pk.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ typedef enum ecc_signature_type_ {
251251
/* raw R, S values */
252252
LTC_ECCSIG_RFC7518 = 0x1,
253253
/* raw R, S, V (+27) values */
254-
LTC_ECCSIG_ETH27 = 0x2
254+
LTC_ECCSIG_ETH27 = 0x2,
255+
/* SSH + ECDSA signature format defined by RFC5656 */
256+
LTC_ECCSIG_RFC5656 = 0x3,
255257
} ecc_signature_type;
256258

257259
/** the ECC params provided */

src/headers/tomcrypt_private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ int ecc_copy_curve(const ecc_key *srckey, ecc_key *key);
226226
int ecc_set_curve_by_size(int size, ecc_key *key);
227227
int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key);
228228

229+
#ifdef LTC_SSH
230+
int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key);
231+
#endif
232+
229233
/* low level functions */
230234
ecc_point *ltc_ecc_new_point(void);
231235
void ltc_ecc_del_point(ecc_point *p);

src/misc/crypt/crypt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ const char *crypt_build_settings =
452452
" PBES1 "
453453
" PBES2 "
454454
#endif
455+
#if defined(LTC_SSH)
456+
" SSH "
457+
#endif
455458
#if defined(LTC_DEVRANDOM)
456459
" LTC_DEVRANDOM "
457460
#endif
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
/**
13+
@file ssh_decode_sequence_multi.c
14+
SSH data type representation as per RFC4251, Russ Williams
15+
*/
16+
17+
#ifdef LTC_SSH
18+
19+
/**
20+
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>
24+
@return CRYPT_OK on success
25+
*/
26+
int ssh_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
27+
{
28+
int err;
29+
va_list args;
30+
ssh_data_type type;
31+
void *vdata;
32+
unsigned char *cdata;
33+
char *sdata;
34+
ulong32 *u32data;
35+
ulong64 *u64data;
36+
unsigned long size, bufsize;
37+
38+
LTC_ARGCHK(in != NULL);
39+
40+
/* Decode values from buffer */
41+
va_start(args, inlen);
42+
while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) {
43+
/* Size of length field */
44+
if (type == LTC_SSHDATA_STRING ||
45+
type == LTC_SSHDATA_NAMELIST ||
46+
type == LTC_SSHDATA_MPINT)
47+
{
48+
/* Check we'll not read too far */
49+
if (inlen < 4) {
50+
err = CRYPT_BUFFER_OVERFLOW;
51+
goto error;
52+
}
53+
}
54+
55+
/* Calculate (or read) length of data */
56+
switch (type) {
57+
case LTC_SSHDATA_BYTE:
58+
case LTC_SSHDATA_BOOLEAN:
59+
size = 1;
60+
break;
61+
case LTC_SSHDATA_UINT32:
62+
size = 4;
63+
break;
64+
case LTC_SSHDATA_UINT64:
65+
size = 8;
66+
break;
67+
case LTC_SSHDATA_STRING:
68+
case LTC_SSHDATA_NAMELIST:
69+
case LTC_SSHDATA_MPINT:
70+
LOAD32H(size, in);
71+
in += 4;
72+
inlen -= 4;
73+
break;
74+
75+
case LTC_SSHDATA_EOL:
76+
/* Should never get here */
77+
err = CRYPT_INVALID_ARG;
78+
goto error;
79+
}
80+
81+
/* Check we'll not read too far */
82+
if (inlen < size) {
83+
err = CRYPT_BUFFER_OVERFLOW;
84+
goto error;
85+
} else {
86+
inlen -= size;
87+
}
88+
89+
/* Read data */
90+
switch (type) {
91+
case LTC_SSHDATA_BYTE:
92+
cdata = va_arg(args, unsigned char*);
93+
*cdata = *in++;
94+
break;
95+
case LTC_SSHDATA_BOOLEAN:
96+
cdata = va_arg(args, unsigned char*);
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+
*cdata = (*in++)?1:0;
102+
break;
103+
case LTC_SSHDATA_UINT32:
104+
u32data = va_arg(args, ulong32*);
105+
LOAD32H(*u32data, in);
106+
in += 4;
107+
break;
108+
case LTC_SSHDATA_UINT64:
109+
u64data = va_arg(args, ulong64*);
110+
LOAD64H(*u64data, in);
111+
in += 8;
112+
break;
113+
case LTC_SSHDATA_STRING:
114+
case LTC_SSHDATA_NAMELIST:
115+
sdata = va_arg(args, char*);
116+
bufsize = va_arg(args, unsigned long);
117+
if (size > 0) {
118+
if (size >= bufsize) {
119+
err = CRYPT_BUFFER_OVERFLOW;
120+
goto error;
121+
}
122+
XSTRNCPY(sdata, (const char *)in, size);
123+
sdata[size] = '\0'; /* strncpy doesn't NUL-terminate */
124+
} else {
125+
*sdata = '\0';
126+
}
127+
in += size;
128+
break;
129+
case LTC_SSHDATA_MPINT:
130+
vdata = va_arg(args, void*);
131+
if (size == 0) {
132+
if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; }
133+
} else {
134+
if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; }
135+
}
136+
in += size;
137+
break;
138+
139+
case LTC_SSHDATA_EOL:
140+
/* Should never get here */
141+
err = CRYPT_INVALID_ARG;
142+
goto error;
143+
}
144+
}
145+
err = CRYPT_OK;
146+
147+
error:
148+
va_end(args);
149+
return err;
150+
}
151+
152+
#endif
153+
154+
/* ref: $Format:%D$ */
155+
/* git commit: $Format:%H$ */
156+
/* commit time: $Format:%ai$ */

0 commit comments

Comments
 (0)