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); }
24 static void getstring(char **data
, int *datalen
, char **p
, int *length
) {
28 *length
= GET_32BIT(*data
);
29 *datalen
-= 4; *data
+= 4;
30 if (*datalen
< *length
)
33 *data
+= *length
; *datalen
-= *length
;
35 static Bignum
getmp(char **data
, int *datalen
) {
40 getstring(data
, datalen
, &p
, &length
);
44 return NULL
; /* negative mp */
45 b
= bignum_from_bytes(p
, length
);
49 static Bignum
get160(char **data
, int *datalen
) {
52 b
= bignum_from_bytes(*data
, 20);
53 *data
+= 20; *datalen
-= 20;
62 static void *dss_newkey(char *data
, int len
) {
67 dss
= smalloc(sizeof(struct dss_key
));
68 if (!dss
) return NULL
;
69 getstring(&data
, &len
, &p
, &slen
);
76 printf(" %02x", (unsigned char)(data
[i
]));
81 if (!p
|| memcmp(p
, "ssh-dss", 7)) {
85 dss
->p
= getmp(&data
, &len
);
86 dss
->q
= getmp(&data
, &len
);
87 dss
->g
= getmp(&data
, &len
);
88 dss
->y
= getmp(&data
, &len
);
93 static void dss_freekey(void *key
) {
94 struct dss_key
*dss
= (struct dss_key
*)key
;
102 static char *dss_fmtkey(void *key
) {
103 struct dss_key
*dss
= (struct dss_key
*)key
;
105 int len
, i
, pos
, nibbles
;
106 static const char hex
[] = "0123456789abcdef";
109 len
= 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
110 len
+= 4 * (ssh1_bignum_bitcount(dss
->p
)+15)/16;
111 len
+= 4 * (ssh1_bignum_bitcount(dss
->q
)+15)/16;
112 len
+= 4 * (ssh1_bignum_bitcount(dss
->g
)+15)/16;
113 len
+= 4 * (ssh1_bignum_bitcount(dss
->y
)+15)/16;
118 pos
+= sprintf(p
+pos
, "0x");
119 nibbles
= (3 + ssh1_bignum_bitcount(dss
->p
))/4; if (nibbles
<1) nibbles
=1;
120 for (i
=nibbles
; i
-- ;)
121 p
[pos
++] = hex
[(bignum_byte(dss
->p
, i
/2) >> (4*(i
%2))) & 0xF];
122 pos
+= sprintf(p
+pos
, ",0x");
123 nibbles
= (3 + ssh1_bignum_bitcount(dss
->q
))/4; if (nibbles
<1) nibbles
=1;
124 for (i
=nibbles
; i
-- ;)
125 p
[pos
++] = hex
[(bignum_byte(dss
->q
, i
/2) >> (4*(i
%2))) & 0xF];
126 pos
+= sprintf(p
+pos
, ",0x");
127 nibbles
= (3 + ssh1_bignum_bitcount(dss
->g
))/4; if (nibbles
<1) nibbles
=1;
128 for (i
=nibbles
; i
-- ;)
129 p
[pos
++] = hex
[(bignum_byte(dss
->g
, i
/2) >> (4*(i
%2))) & 0xF];
130 pos
+= sprintf(p
+pos
, ",0x");
131 nibbles
= (3 + ssh1_bignum_bitcount(dss
->y
))/4; if (nibbles
<1) nibbles
=1;
132 for (i
=nibbles
; i
-- ;)
133 p
[pos
++] = hex
[(bignum_byte(dss
->y
, i
/2) >> (4*(i
%2))) & 0xF];
138 static char *dss_fingerprint(void *key
) {
139 struct dss_key
*dss
= (struct dss_key
*)key
;
140 struct MD5Context md5c
;
141 unsigned char digest
[16], lenbuf
[4];
142 char buffer
[16*3+40];
147 MD5Update(&md5c
, "\0\0\0\7ssh-dss", 11);
149 #define ADD_BIGNUM(bignum) \
150 numlen = (ssh1_bignum_bitcount(bignum)+8)/8; \
151 PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
152 for (i = numlen; i-- ;) { \
153 unsigned char c = bignum_byte(bignum, i); \
154 MD5Update(&md5c, &c, 1); \
162 MD5Final(digest
, &md5c
);
164 sprintf(buffer
, "%d ", ssh1_bignum_bitcount(dss
->p
));
165 for (i
= 0; i
< 16; i
++)
166 sprintf(buffer
+strlen(buffer
), "%s%02x", i?
":":"", digest
[i
]);
167 ret
= smalloc(strlen(buffer
)+1);
173 static int dss_verifysig(void *key
, char *sig
, int siglen
,
174 char *data
, int datalen
) {
175 struct dss_key
*dss
= (struct dss_key
*)key
;
179 Bignum r
, s
, w
, gu1p
, yu2p
, gu1yu2p
, u1
, u2
, sha
, v
;
189 for (i
=0;i
<siglen
;i
++)
190 printf(" %02x", (unsigned char)(sig
[i
]));
195 * Commercial SSH (2.0.13) and OpenSSH disagree over the format
196 * of a DSA signature. OpenSSH is in line with the IETF drafts:
197 * it uses a string "ssh-dss", followed by a 40-byte string
198 * containing two 160-bit integers end-to-end. Commercial SSH
199 * can't be bothered with the header bit, and considers a DSA
200 * signature blob to be _just_ the 40-byte string containing
201 * the two 160-bit integers. We tell them apart by measuring
202 * the length: length 40 means the commercial-SSH bug, anything
203 * else is assumed to be IETF-compliant.
205 if (siglen
!= 40) { /* bug not present; read admin fields */
206 getstring(&sig
, &siglen
, &p
, &slen
);
207 if (!p
|| slen
!= 7 || memcmp(p
, "ssh-dss", 7)) {
210 sig
+= 4, siglen
-= 4; /* skip yet another length field */
212 diagbn("p=", dss
->p
);
213 diagbn("q=", dss
->q
);
214 diagbn("g=", dss
->g
);
215 diagbn("y=", dss
->y
);
216 r
= get160(&sig
, &siglen
);
218 s
= get160(&sig
, &siglen
);
224 * Step 1. w <- s^-1 mod q.
226 w
= modinv(s
, dss
->q
);
230 * Step 2. u1 <- SHA(message) * w mod q.
232 SHA_Simple(data
, datalen
, hash
);
233 p
= hash
; slen
= 20; sha
= get160(&p
, &slen
);
235 u1
= modmul(sha
, w
, dss
->q
);
239 * Step 3. u2 <- r * w mod q.
241 u2
= modmul(r
, w
, dss
->q
);
245 * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
247 gu1p
= modpow(dss
->g
, u1
, dss
->p
);
248 diagbn("gu1p=", gu1p
);
249 yu2p
= modpow(dss
->y
, u2
, dss
->p
);
250 diagbn("yu2p=", yu2p
);
251 gu1yu2p
= modmul(gu1p
, yu2p
, dss
->p
);
252 diagbn("gu1yu2p=", gu1yu2p
);
253 v
= modmul(gu1yu2p
, One
, dss
->q
);
254 diagbn("gu1yu2q=v=", v
);
258 * Step 5. v should now be equal to r.
261 ret
= !bignum_cmp(v
, r
);
275 int dss_sign(void *key
, char *sig
, int siglen
,
276 char *data
, int datalen
) {
277 return 0; /* do nothing */
280 struct ssh_signkey ssh_dss
= {