6 #define GET_32BIT(cp) \
7 (((unsigned long)(unsigned char)(cp)[0] << 24) | \
8 ((unsigned long)(unsigned char)(cp)[1] << 16) | \
9 ((unsigned long)(unsigned char)(cp)[2] << 8) | \
10 ((unsigned long)(unsigned char)(cp)[3]))
12 #define PUT_32BIT(cp, value) { \
13 (cp)[0] = (unsigned char)((value) >> 24); \
14 (cp)[1] = (unsigned char)((value) >> 16); \
15 (cp)[2] = (unsigned char)((value) >> 8); \
16 (cp)[3] = (unsigned char)(value); }
18 static void getstring(char **data
, int *datalen
, char **p
, int *length
) {
22 *length
= GET_32BIT(*data
);
23 *datalen
-= 4; *data
+= 4;
24 if (*datalen
< *length
)
27 *data
+= *length
; *datalen
-= *length
;
29 static Bignum
getmp(char **data
, int *datalen
) {
34 getstring(data
, datalen
, &p
, &length
);
38 return NULL
; /* negative mp */
39 b
= newbn((length
+1)/2);
40 for (i
= 0; i
< length
; i
++) {
43 b
[j
/2+1] |= ((unsigned char)p
[i
]) << 8;
45 b
[j
/2+1] |= ((unsigned char)p
[i
]);
50 static Bignum
get160(char **data
, int *datalen
) {
56 *data
+= 20; *datalen
-= 20;
59 while (length
> 0 && !p
[0])
61 b
= newbn((length
+1)/2);
62 for (i
= 0; i
< length
; i
++) {
65 b
[j
/2+1] |= ((unsigned char)p
[i
]) << 8;
67 b
[j
/2+1] |= ((unsigned char)p
[i
]);
72 static Bignum dss_p
, dss_q
, dss_g
, dss_y
;
74 static void dss_setkey(char *data
, int len
) {
77 getstring(&data
, &len
, &p
, &slen
);
78 if (!p
|| memcmp(p
, "ssh-dss", 7)) {
82 dss_p
= getmp(&data
, &len
);
83 dss_q
= getmp(&data
, &len
);
84 dss_g
= getmp(&data
, &len
);
85 dss_y
= getmp(&data
, &len
);
88 static char *dss_fmtkey(void) {
90 int len
, i
, pos
, nibbles
;
91 static const char hex
[] = "0123456789abcdef";
94 len
= 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
95 len
+= 4 * (dss_p
[0] + dss_q
[0] + dss_g
[0] + dss_y
[0]); /* digits */
100 pos
+= sprintf(p
+pos
, "0x");
101 nibbles
= (3 + ssh1_bignum_bitcount(dss_p
))/4; if (nibbles
<1) nibbles
=1;
102 for (i
=nibbles
; i
-- ;)
103 p
[pos
++] = hex
[(bignum_byte(dss_p
, i
/2) >> (4*(i
%2))) & 0xF];
104 pos
+= sprintf(p
+pos
, ",0x");
105 nibbles
= (3 + ssh1_bignum_bitcount(dss_q
))/4; if (nibbles
<1) nibbles
=1;
106 for (i
=nibbles
; i
-- ;)
107 p
[pos
++] = hex
[(bignum_byte(dss_q
, i
/2) >> (4*(i
%2))) & 0xF];
108 pos
+= sprintf(p
+pos
, ",0x");
109 nibbles
= (3 + ssh1_bignum_bitcount(dss_g
))/4; if (nibbles
<1) nibbles
=1;
110 for (i
=nibbles
; i
-- ;)
111 p
[pos
++] = hex
[(bignum_byte(dss_g
, i
/2) >> (4*(i
%2))) & 0xF];
112 pos
+= sprintf(p
+pos
, ",0x");
113 nibbles
= (3 + ssh1_bignum_bitcount(dss_y
))/4; if (nibbles
<1) nibbles
=1;
114 for (i
=nibbles
; i
-- ;)
115 p
[pos
++] = hex
[(bignum_byte(dss_y
, i
/2) >> (4*(i
%2))) & 0xF];
120 static char *dss_fingerprint(void) {
121 struct MD5Context md5c
;
122 unsigned char digest
[16], lenbuf
[4];
123 char buffer
[16*3+40];
128 MD5Update(&md5c
, "\0\0\0\7ssh-dss", 11);
130 #define ADD_BIGNUM(bignum) \
131 numlen = (ssh1_bignum_bitcount(bignum)+8)/8; \
132 PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
133 for (i = numlen; i-- ;) { \
134 unsigned char c = bignum_byte(bignum, i); \
135 MD5Update(&md5c, &c, 1); \
143 MD5Final(digest
, &md5c
);
145 sprintf(buffer
, "%d ", ssh1_bignum_bitcount(dss_p
));
146 for (i
= 0; i
< 16; i
++)
147 sprintf(buffer
+strlen(buffer
), "%s%02x", i?
":":"", digest
[i
]);
148 ret
= malloc(strlen(buffer
)+1);
154 static int dss_verifysig(char *sig
, int siglen
, char *data
, int datalen
) {
158 Bignum qm2
, r
, s
, w
, i1
, i2
, i3
, u1
, u2
, sha
, v
;
164 getstring(&sig
, &siglen
, &p
, &slen
);
165 if (!p
|| memcmp(p
, "ssh-dss", 7)) {
168 sig
+= 4, siglen
-= 4; /* skip yet another length field */
169 r
= get160(&sig
, &siglen
);
170 s
= get160(&sig
, &siglen
);
175 * Step 1. w <- s^-1 mod q.
179 decbn(qm2
); decbn(qm2
);
180 /* Now qm2 is q-2, and by Fermat's Little Theorem, s^qm2 == s^-1 (mod q).
181 * This is a silly way to do it; may fix it later. */
182 modpow(s
, qm2
, dss_q
, w
);
185 * Step 2. u1 <- SHA(message) * w mod q.
187 u1
= newbn(dss_q
[0]);
188 SHA_Simple(data
, datalen
, hash
);
189 p
= hash
; slen
= 20; sha
= get160(&p
, &slen
);
190 modmul(sha
, w
, dss_q
, u1
);
193 * Step 3. u2 <- r * w mod q.
195 u2
= newbn(dss_q
[0]);
196 modmul(r
, w
, dss_q
, u2
);
199 * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
201 i1
= newbn(dss_p
[0]);
202 i2
= newbn(dss_p
[0]);
203 i3
= newbn(dss_p
[0]);
205 modpow(dss_g
, u1
, dss_p
, i1
);
206 modpow(dss_y
, u2
, dss_p
, i2
);
207 modmul(i1
, i2
, dss_p
, i3
);
208 modmul(i3
, One
, dss_q
, v
);
211 * Step 5. v should now be equal to r.
215 for (i
= 1; i
<= v
[0] || i
<= r
[0]; i
++) {
216 if ((i
> v
[0] && r
[i
] != 0) ||
217 (i
> r
[0] && v
[i
] != 0) ||
218 (i
<= v
[0] && i
<= r
[0] && r
[i
] != v
[i
]))
235 struct ssh_hostkey ssh_dss
= {