diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | ssh-rsa.c | 100 |
2 files changed, 98 insertions, 8 deletions
@@ -13,6 +13,10 @@ | |||
13 | - markus@cvs.openbsd.org 2002/08/02 21:23:41 | 13 | - markus@cvs.openbsd.org 2002/08/02 21:23:41 |
14 | [ssh-rsa.c] | 14 | [ssh-rsa.c] |
15 | diff is u_int (2x); ok deraadt/provos | 15 | diff is u_int (2x); ok deraadt/provos |
16 | - markus@cvs.openbsd.org 2002/08/02 22:20:30 | ||
17 | [ssh-rsa.c] | ||
18 | replace RSA_verify with our own version and avoid the OpenSSL ASN.1 parser | ||
19 | for authentication; ok deraadt/djm | ||
16 | 20 | ||
17 | 20020813 | 21 | 20020813 |
18 | - (tim) [configure.ac] Display OpenSSL header/library version. | 22 | - (tim) [configure.ac] Display OpenSSL header/library version. |
@@ -1510,4 +1514,4 @@ | |||
1510 | - (stevesk) entropy.c: typo in debug message | 1514 | - (stevesk) entropy.c: typo in debug message |
1511 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ | 1515 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ |
1512 | 1516 | ||
1513 | $Id: ChangeLog,v 1.2417 2002/08/20 18:39:14 mouring Exp $ | 1517 | $Id: ChangeLog,v 1.2418 2002/08/20 18:40:03 mouring Exp $ |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: ssh-rsa.c,v 1.24 2002/08/02 21:23:41 markus Exp $"); | 26 | RCSID("$OpenBSD: ssh-rsa.c,v 1.25 2002/08/02 22:20:30 markus Exp $"); |
27 | 27 | ||
28 | #include <openssl/evp.h> | 28 | #include <openssl/evp.h> |
29 | #include <openssl/err.h> | 29 | #include <openssl/err.h> |
@@ -37,6 +37,8 @@ RCSID("$OpenBSD: ssh-rsa.c,v 1.24 2002/08/02 21:23:41 markus Exp $"); | |||
37 | #include "compat.h" | 37 | #include "compat.h" |
38 | #include "ssh.h" | 38 | #include "ssh.h" |
39 | 39 | ||
40 | static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int , RSA *); | ||
41 | |||
40 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ | 42 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ |
41 | int | 43 | int |
42 | ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp, | 44 | ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp, |
@@ -167,15 +169,99 @@ ssh_rsa_verify(Key *key, u_char *signature, u_int signaturelen, | |||
167 | EVP_DigestUpdate(&md, data, datalen); | 169 | EVP_DigestUpdate(&md, data, datalen); |
168 | EVP_DigestFinal(&md, digest, &dlen); | 170 | EVP_DigestFinal(&md, digest, &dlen); |
169 | 171 | ||
170 | ret = RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); | 172 | ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); |
171 | memset(digest, 'd', sizeof(digest)); | 173 | memset(digest, 'd', sizeof(digest)); |
172 | memset(sigblob, 's', len); | 174 | memset(sigblob, 's', len); |
173 | xfree(sigblob); | 175 | xfree(sigblob); |
174 | if (ret == 0) { | ||
175 | int ecode = ERR_get_error(); | ||
176 | error("ssh_rsa_verify: RSA_verify failed: %s", | ||
177 | ERR_error_string(ecode, NULL)); | ||
178 | } | ||
179 | debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); | 176 | debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); |
180 | return ret; | 177 | return ret; |
181 | } | 178 | } |
179 | |||
180 | /* | ||
181 | * See: | ||
182 | * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ | ||
183 | * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn | ||
184 | */ | ||
185 | /* | ||
186 | * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) | ||
187 | * oiw(14) secsig(3) algorithms(2) 26 } | ||
188 | */ | ||
189 | static const u_char id_sha1[] = { | ||
190 | 0x30, 0x21, /* type Sequence, length 0x21 (33) */ | ||
191 | 0x30, 0x09, /* type Sequence, length 0x09 */ | ||
192 | 0x06, 0x05, /* type OID, length 0x05 */ | ||
193 | 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ | ||
194 | 0x05, 0x00, /* NULL */ | ||
195 | 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ | ||
196 | }; | ||
197 | /* | ||
198 | * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) | ||
199 | * rsadsi(113549) digestAlgorithm(2) 5 } | ||
200 | */ | ||
201 | static const u_char id_md5[] = { | ||
202 | 0x30, 0x20, /* type Sequence, length 0x20 (32) */ | ||
203 | 0x30, 0x0c, /* type Sequence, length 0x09 */ | ||
204 | 0x06, 0x08, /* type OID, length 0x05 */ | ||
205 | 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */ | ||
206 | 0x05, 0x00, /* NULL */ | ||
207 | 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */ | ||
208 | }; | ||
209 | |||
210 | static int | ||
211 | openssh_RSA_verify(int type, u_char *hash, u_int hashlen, | ||
212 | u_char *sigbuf, u_int siglen, RSA *rsa) | ||
213 | { | ||
214 | u_int ret, rsasize, len, oidlen = 0, hlen = 0; | ||
215 | const u_char *oid = NULL; | ||
216 | u_char *decrypted = NULL; | ||
217 | |||
218 | ret = 0; | ||
219 | switch (type) { | ||
220 | case NID_sha1: | ||
221 | oid = id_sha1; | ||
222 | oidlen = sizeof(id_sha1); | ||
223 | hlen = 20; | ||
224 | break; | ||
225 | case NID_md5: | ||
226 | oid = id_md5; | ||
227 | oidlen = sizeof(id_md5); | ||
228 | hlen = 16; | ||
229 | break; | ||
230 | default: | ||
231 | goto done; | ||
232 | break; | ||
233 | } | ||
234 | if (hashlen != hlen) { | ||
235 | error("bad hashlen"); | ||
236 | goto done; | ||
237 | } | ||
238 | rsasize = RSA_size(rsa); | ||
239 | if (siglen == 0 || siglen > rsasize) { | ||
240 | error("bad siglen"); | ||
241 | goto done; | ||
242 | } | ||
243 | decrypted = xmalloc(rsasize); | ||
244 | if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, | ||
245 | RSA_PKCS1_PADDING)) < 0) { | ||
246 | error("RSA_public_decrypt failed: %s", | ||
247 | ERR_error_string(ERR_get_error(), NULL)); | ||
248 | goto done; | ||
249 | } | ||
250 | if (len != hlen + oidlen) { | ||
251 | error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); | ||
252 | goto done; | ||
253 | } | ||
254 | if (memcmp(decrypted, oid, oidlen) != 0) { | ||
255 | error("oid mismatch"); | ||
256 | goto done; | ||
257 | } | ||
258 | if (memcmp(decrypted + oidlen, hash, hlen) != 0) { | ||
259 | error("hash mismatch"); | ||
260 | goto done; | ||
261 | } | ||
262 | ret = 1; | ||
263 | done: | ||
264 | if (decrypted) | ||
265 | xfree(decrypted); | ||
266 | return ret; | ||
267 | } | ||