7 #define GET_32BIT(cp) \
8 (((unsigned long)(unsigned char)(cp)[0] << 24) | \
9 ((unsigned long)(unsigned char)(cp)[1] << 16) | \
10 ((unsigned long)(unsigned char)(cp)[2] << 8) | \
11 ((unsigned long)(unsigned char)(cp)[3]))
13 #define PUT_32BIT(cp, value) { \
14 (cp)[0] = (unsigned char)((value) >> 24); \
15 (cp)[1] = (unsigned char)((value) >> 16); \
16 (cp)[2] = (unsigned char)((value) >> 8); \
17 (cp)[3] = (unsigned char)(value); }
25 static void getstring(char **data
, int *datalen
, char **p
, int *length
)
30 *length
= GET_32BIT(*data
);
33 if (*datalen
< *length
)
39 static Bignum
getmp(char **data
, int *datalen
)
45 getstring(data
, datalen
, &p
, &length
);
49 return NULL
; /* negative mp */
50 b
= bignum_from_bytes(p
, length
);
54 static Bignum
get160(char **data
, int *datalen
)
58 b
= bignum_from_bytes(*data
, 20);
69 static void *dss_newkey(char *data
, int len
)
75 dss
= smalloc(sizeof(struct dss_key
));
78 getstring(&data
, &len
, &p
, &slen
);
84 for (i
= 0; i
< len
; i
++)
85 printf(" %02x", (unsigned char) (data
[i
]));
90 if (!p
|| memcmp(p
, "ssh-dss", 7)) {
94 dss
->p
= getmp(&data
, &len
);
95 dss
->q
= getmp(&data
, &len
);
96 dss
->g
= getmp(&data
, &len
);
97 dss
->y
= getmp(&data
, &len
);
102 static void dss_freekey(void *key
)
104 struct dss_key
*dss
= (struct dss_key
*) key
;
112 static char *dss_fmtkey(void *key
)
114 struct dss_key
*dss
= (struct dss_key
*) key
;
116 int len
, i
, pos
, nibbles
;
117 static const char hex
[] = "0123456789abcdef";
120 len
= 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
121 len
+= 4 * (bignum_bitcount(dss
->p
) + 15) / 16;
122 len
+= 4 * (bignum_bitcount(dss
->q
) + 15) / 16;
123 len
+= 4 * (bignum_bitcount(dss
->g
) + 15) / 16;
124 len
+= 4 * (bignum_bitcount(dss
->y
) + 15) / 16;
130 pos
+= sprintf(p
+ pos
, "0x");
131 nibbles
= (3 + bignum_bitcount(dss
->p
)) / 4;
134 for (i
= nibbles
; i
--;)
136 hex
[(bignum_byte(dss
->p
, i
/ 2) >> (4 * (i
% 2))) & 0xF];
137 pos
+= sprintf(p
+ pos
, ",0x");
138 nibbles
= (3 + bignum_bitcount(dss
->q
)) / 4;
141 for (i
= nibbles
; i
--;)
143 hex
[(bignum_byte(dss
->q
, i
/ 2) >> (4 * (i
% 2))) & 0xF];
144 pos
+= sprintf(p
+ pos
, ",0x");
145 nibbles
= (3 + bignum_bitcount(dss
->g
)) / 4;
148 for (i
= nibbles
; i
--;)
150 hex
[(bignum_byte(dss
->g
, i
/ 2) >> (4 * (i
% 2))) & 0xF];
151 pos
+= sprintf(p
+ pos
, ",0x");
152 nibbles
= (3 + bignum_bitcount(dss
->y
)) / 4;
155 for (i
= nibbles
; i
--;)
157 hex
[(bignum_byte(dss
->y
, i
/ 2) >> (4 * (i
% 2))) & 0xF];
162 static char *dss_fingerprint(void *key
)
164 struct dss_key
*dss
= (struct dss_key
*) key
;
165 struct MD5Context md5c
;
166 unsigned char digest
[16], lenbuf
[4];
167 char buffer
[16 * 3 + 40];
172 MD5Update(&md5c
, "\0\0\0\7ssh-dss", 11);
174 #define ADD_BIGNUM(bignum) \
175 numlen = (bignum_bitcount(bignum)+8)/8; \
176 PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
177 for (i = numlen; i-- ;) { \
178 unsigned char c = bignum_byte(bignum, i); \
179 MD5Update(&md5c, &c, 1); \
187 MD5Final(digest
, &md5c
);
189 sprintf(buffer
, "ssh-dss %d ", bignum_bitcount(dss
->p
));
190 for (i
= 0; i
< 16; i
++)
191 sprintf(buffer
+ strlen(buffer
), "%s%02x", i ?
":" : "",
193 ret
= smalloc(strlen(buffer
) + 1);
199 static int dss_verifysig(void *key
, char *sig
, int siglen
,
200 char *data
, int datalen
)
202 struct dss_key
*dss
= (struct dss_key
*) key
;
206 Bignum r
, s
, w
, gu1p
, yu2p
, gu1yu2p
, u1
, u2
, sha
, v
;
216 for (i
= 0; i
< siglen
; i
++)
217 printf(" %02x", (unsigned char) (sig
[i
]));
222 * Commercial SSH (2.0.13) and OpenSSH disagree over the format
223 * of a DSA signature. OpenSSH is in line with the IETF drafts:
224 * it uses a string "ssh-dss", followed by a 40-byte string
225 * containing two 160-bit integers end-to-end. Commercial SSH
226 * can't be bothered with the header bit, and considers a DSA
227 * signature blob to be _just_ the 40-byte string containing
228 * the two 160-bit integers. We tell them apart by measuring
229 * the length: length 40 means the commercial-SSH bug, anything
230 * else is assumed to be IETF-compliant.
232 if (siglen
!= 40) { /* bug not present; read admin fields */
233 getstring(&sig
, &siglen
, &p
, &slen
);
234 if (!p
|| slen
!= 7 || memcmp(p
, "ssh-dss", 7)) {
237 sig
+= 4, siglen
-= 4; /* skip yet another length field */
239 diagbn("p=", dss
->p
);
240 diagbn("q=", dss
->q
);
241 diagbn("g=", dss
->g
);
242 diagbn("y=", dss
->y
);
243 r
= get160(&sig
, &siglen
);
245 s
= get160(&sig
, &siglen
);
251 * Step 1. w <- s^-1 mod q.
253 w
= modinv(s
, dss
->q
);
257 * Step 2. u1 <- SHA(message) * w mod q.
259 SHA_Simple(data
, datalen
, hash
);
262 sha
= get160(&p
, &slen
);
264 u1
= modmul(sha
, w
, dss
->q
);
268 * Step 3. u2 <- r * w mod q.
270 u2
= modmul(r
, w
, dss
->q
);
274 * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
276 gu1p
= modpow(dss
->g
, u1
, dss
->p
);
277 diagbn("gu1p=", gu1p
);
278 yu2p
= modpow(dss
->y
, u2
, dss
->p
);
279 diagbn("yu2p=", yu2p
);
280 gu1yu2p
= modmul(gu1p
, yu2p
, dss
->p
);
281 diagbn("gu1yu2p=", gu1yu2p
);
282 v
= modmul(gu1yu2p
, One
, dss
->q
);
283 diagbn("gu1yu2q=v=", v
);
287 * Step 5. v should now be equal to r.
290 ret
= !bignum_cmp(v
, r
);
304 static unsigned char *dss_public_blob(void *key
, int *len
)
306 struct dss_key
*dss
= (struct dss_key
*) key
;
307 int plen
, qlen
, glen
, ylen
, bloblen
;
309 unsigned char *blob
, *p
;
311 plen
= (bignum_bitcount(dss
->p
) + 8) / 8;
312 qlen
= (bignum_bitcount(dss
->q
) + 8) / 8;
313 glen
= (bignum_bitcount(dss
->g
) + 8) / 8;
314 ylen
= (bignum_bitcount(dss
->y
) + 8) / 8;
317 * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
318 * 27 + sum of lengths. (five length fields, 20+7=27).
320 bloblen
= 27 + plen
+ qlen
+ glen
+ ylen
;
321 blob
= smalloc(bloblen
);
325 memcpy(p
, "ssh-dss", 7);
330 *p
++ = bignum_byte(dss
->p
, i
);
334 *p
++ = bignum_byte(dss
->q
, i
);
338 *p
++ = bignum_byte(dss
->g
, i
);
342 *p
++ = bignum_byte(dss
->y
, i
);
343 assert(p
== blob
+ bloblen
);
348 static unsigned char *dss_private_blob(void *key
, int *len
)
350 return NULL
; /* can't handle DSS private keys */
353 static void *dss_createkey(unsigned char *pub_blob
, int pub_len
,
354 unsigned char *priv_blob
, int priv_len
)
356 return NULL
; /* can't handle DSS private keys */
359 static void *dss_openssh_createkey(unsigned char **blob
, int *len
)
361 return NULL
; /* can't handle DSS private keys */
364 static int dss_openssh_fmtkey(void *key
, unsigned char *blob
, int len
)
366 return -1; /* can't handle DSS private keys */
369 unsigned char *dss_sign(void *key
, char *data
, int datalen
, int *siglen
)
371 return NULL
; /* can't handle DSS private keys */
374 const struct ssh_signkey ssh_dss
= {
381 dss_openssh_createkey
,