summaryrefslogtreecommitdiff
path: root/ssh-rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r--ssh-rsa.c106
1 files changed, 49 insertions, 57 deletions
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 30f96abc2..a2112d033 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.46 2013/05/17 00:13:14 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.50 2014/01/09 23:20:00 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -32,6 +32,7 @@
32#include "compat.h" 32#include "compat.h"
33#include "misc.h" 33#include "misc.h"
34#include "ssh.h" 34#include "ssh.h"
35#include "digest.h"
35 36
36static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); 37static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
37 38
@@ -40,26 +41,30 @@ int
40ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, 41ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
41 const u_char *data, u_int datalen) 42 const u_char *data, u_int datalen)
42{ 43{
43 const EVP_MD *evp_md; 44 int hash_alg;
44 EVP_MD_CTX md; 45 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig;
45 u_char digest[EVP_MAX_MD_SIZE], *sig;
46 u_int slen, dlen, len; 46 u_int slen, dlen, len;
47 int ok, nid; 47 int ok, nid;
48 Buffer b; 48 Buffer b;
49 49
50 if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && 50 if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
51 key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { 51 key->rsa == NULL) {
52 error("ssh_rsa_sign: no RSA key"); 52 error("%s: no RSA key", __func__);
53 return -1; 53 return -1;
54 } 54 }
55 nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; 55
56 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { 56 /* hash the data */
57 error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); 57 hash_alg = SSH_DIGEST_SHA1;
58 nid = NID_sha1;
59 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
60 error("%s: bad hash algorithm %d", __func__, hash_alg);
61 return -1;
62 }
63 if (ssh_digest_memory(hash_alg, data, datalen,
64 digest, sizeof(digest)) != 0) {
65 error("%s: ssh_digest_memory failed", __func__);
58 return -1; 66 return -1;
59 } 67 }
60 EVP_DigestInit(&md, evp_md);
61 EVP_DigestUpdate(&md, data, datalen);
62 EVP_DigestFinal(&md, digest, &dlen);
63 68
64 slen = RSA_size(key->rsa); 69 slen = RSA_size(key->rsa);
65 sig = xmalloc(slen); 70 sig = xmalloc(slen);
@@ -70,7 +75,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
70 if (ok != 1) { 75 if (ok != 1) {
71 int ecode = ERR_get_error(); 76 int ecode = ERR_get_error();
72 77
73 error("ssh_rsa_sign: RSA_sign failed: %s", 78 error("%s: RSA_sign failed: %s", __func__,
74 ERR_error_string(ecode, NULL)); 79 ERR_error_string(ecode, NULL));
75 free(sig); 80 free(sig);
76 return -1; 81 return -1;
@@ -81,7 +86,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
81 memmove(sig + diff, sig, len); 86 memmove(sig + diff, sig, len);
82 memset(sig, 0, diff); 87 memset(sig, 0, diff);
83 } else if (len > slen) { 88 } else if (len > slen) {
84 error("ssh_rsa_sign: slen %u slen2 %u", slen, len); 89 error("%s: slen %u slen2 %u", __func__, slen, len);
85 free(sig); 90 free(sig);
86 return -1; 91 return -1;
87 } 92 }
@@ -108,28 +113,29 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
108 const u_char *data, u_int datalen) 113 const u_char *data, u_int datalen)
109{ 114{
110 Buffer b; 115 Buffer b;
111 const EVP_MD *evp_md; 116 int hash_alg;
112 EVP_MD_CTX md;
113 char *ktype; 117 char *ktype;
114 u_char digest[EVP_MAX_MD_SIZE], *sigblob; 118 u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
115 u_int len, dlen, modlen; 119 u_int len, dlen, modlen;
116 int rlen, ret, nid; 120 int rlen, ret;
117 121
118 if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && 122 if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
119 key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { 123 key->rsa == NULL) {
120 error("ssh_rsa_verify: no RSA key"); 124 error("%s: no RSA key", __func__);
121 return -1; 125 return -1;
122 } 126 }
127
123 if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { 128 if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
124 error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", 129 error("%s: RSA modulus too small: %d < minimum %d bits",
125 BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); 130 __func__, BN_num_bits(key->rsa->n),
131 SSH_RSA_MINIMUM_MODULUS_SIZE);
126 return -1; 132 return -1;
127 } 133 }
128 buffer_init(&b); 134 buffer_init(&b);
129 buffer_append(&b, signature, signaturelen); 135 buffer_append(&b, signature, signaturelen);
130 ktype = buffer_get_cstring(&b, NULL); 136 ktype = buffer_get_cstring(&b, NULL);
131 if (strcmp("ssh-rsa", ktype) != 0) { 137 if (strcmp("ssh-rsa", ktype) != 0) {
132 error("ssh_rsa_verify: cannot handle type %s", ktype); 138 error("%s: cannot handle type %s", __func__, ktype);
133 buffer_free(&b); 139 buffer_free(&b);
134 free(ktype); 140 free(ktype);
135 return -1; 141 return -1;
@@ -139,40 +145,43 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
139 rlen = buffer_len(&b); 145 rlen = buffer_len(&b);
140 buffer_free(&b); 146 buffer_free(&b);
141 if (rlen != 0) { 147 if (rlen != 0) {
142 error("ssh_rsa_verify: remaining bytes in signature %d", rlen); 148 error("%s: remaining bytes in signature %d", __func__, rlen);
143 free(sigblob); 149 free(sigblob);
144 return -1; 150 return -1;
145 } 151 }
146 /* RSA_verify expects a signature of RSA_size */ 152 /* RSA_verify expects a signature of RSA_size */
147 modlen = RSA_size(key->rsa); 153 modlen = RSA_size(key->rsa);
148 if (len > modlen) { 154 if (len > modlen) {
149 error("ssh_rsa_verify: len %u > modlen %u", len, modlen); 155 error("%s: len %u > modlen %u", __func__, len, modlen);
150 free(sigblob); 156 free(sigblob);
151 return -1; 157 return -1;
152 } else if (len < modlen) { 158 } else if (len < modlen) {
153 u_int diff = modlen - len; 159 u_int diff = modlen - len;
154 debug("ssh_rsa_verify: add padding: modlen %u > len %u", 160 debug("%s: add padding: modlen %u > len %u", __func__,
155 modlen, len); 161 modlen, len);
156 sigblob = xrealloc(sigblob, 1, modlen); 162 sigblob = xrealloc(sigblob, 1, modlen);
157 memmove(sigblob + diff, sigblob, len); 163 memmove(sigblob + diff, sigblob, len);
158 memset(sigblob, 0, diff); 164 memset(sigblob, 0, diff);
159 len = modlen; 165 len = modlen;
160 } 166 }
161 nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; 167 /* hash the data */
162 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { 168 hash_alg = SSH_DIGEST_SHA1;
163 error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); 169 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
164 free(sigblob); 170 error("%s: bad hash algorithm %d", __func__, hash_alg);
171 return -1;
172 }
173 if (ssh_digest_memory(hash_alg, data, datalen,
174 digest, sizeof(digest)) != 0) {
175 error("%s: ssh_digest_memory failed", __func__);
165 return -1; 176 return -1;
166 } 177 }
167 EVP_DigestInit(&md, evp_md);
168 EVP_DigestUpdate(&md, data, datalen);
169 EVP_DigestFinal(&md, digest, &dlen);
170 178
171 ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); 179 ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
180 key->rsa);
172 memset(digest, 'd', sizeof(digest)); 181 memset(digest, 'd', sizeof(digest));
173 memset(sigblob, 's', len); 182 memset(sigblob, 's', len);
174 free(sigblob); 183 free(sigblob);
175 debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); 184 debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : "");
176 return ret; 185 return ret;
177} 186}
178 187
@@ -193,21 +202,9 @@ static const u_char id_sha1[] = {
193 0x05, 0x00, /* NULL */ 202 0x05, 0x00, /* NULL */
194 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 203 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
195}; 204};
196/*
197 * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
198 * rsadsi(113549) digestAlgorithm(2) 5 }
199 */
200static const u_char id_md5[] = {
201 0x30, 0x20, /* type Sequence, length 0x20 (32) */
202 0x30, 0x0c, /* type Sequence, length 0x09 */
203 0x06, 0x08, /* type OID, length 0x05 */
204 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
205 0x05, 0x00, /* NULL */
206 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
207};
208 205
209static int 206static int
210openssh_RSA_verify(int type, u_char *hash, u_int hashlen, 207openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen,
211 u_char *sigbuf, u_int siglen, RSA *rsa) 208 u_char *sigbuf, u_int siglen, RSA *rsa)
212{ 209{
213 u_int ret, rsasize, oidlen = 0, hlen = 0; 210 u_int ret, rsasize, oidlen = 0, hlen = 0;
@@ -216,17 +213,12 @@ openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
216 u_char *decrypted = NULL; 213 u_char *decrypted = NULL;
217 214
218 ret = 0; 215 ret = 0;
219 switch (type) { 216 switch (hash_alg) {
220 case NID_sha1: 217 case SSH_DIGEST_SHA1:
221 oid = id_sha1; 218 oid = id_sha1;
222 oidlen = sizeof(id_sha1); 219 oidlen = sizeof(id_sha1);
223 hlen = 20; 220 hlen = 20;
224 break; 221 break;
225 case NID_md5:
226 oid = id_md5;
227 oidlen = sizeof(id_md5);
228 hlen = 16;
229 break;
230 default: 222 default:
231 goto done; 223 goto done;
232 } 224 }