]> andersk Git - openssh.git/blob - ssh-rsa.c
b2fcc3408ad03a204b725271f2c97e4fb3d04bf0
[openssh.git] / ssh-rsa.c
1 /*
2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26 RCSID("$OpenBSD: ssh-rsa.c,v 1.17 2002/03/29 19:18:33 stevesk Exp $");
27
28 #include <openssl/evp.h>
29 #include <openssl/err.h>
30
31 #include "xmalloc.h"
32 #include "log.h"
33 #include "buffer.h"
34 #include "bufaux.h"
35 #include "key.h"
36 #include "ssh-rsa.h"
37 #include "compat.h"
38 #include "ssh.h"
39
40 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
41 int
42 ssh_rsa_sign(
43     Key *key,
44     u_char **sigp, u_int *lenp,
45     u_char *data, u_int datalen)
46 {
47         const EVP_MD *evp_md;
48         EVP_MD_CTX md;
49         u_char digest[EVP_MAX_MD_SIZE], *sig, *ret;
50         u_int slen, dlen, len;
51         int ok, nid;
52         Buffer b;
53
54         if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
55                 error("ssh_rsa_sign: no RSA key");
56                 return -1;
57         }
58         if (datafellows & SSH_BUG_SIGBLOB) {
59                 error("ssh_rsa_sign: SSH_BUG_SIGBLOB not supported");
60                 return -1;
61         }
62         nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
63         if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
64                 error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
65                 return -1;
66         }
67         EVP_DigestInit(&md, evp_md);
68         EVP_DigestUpdate(&md, data, datalen);
69         EVP_DigestFinal(&md, digest, &dlen);
70
71         slen = RSA_size(key->rsa);
72         sig = xmalloc(slen);
73
74         ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
75         memset(digest, 'd', sizeof(digest));
76
77         if (ok != 1) {
78                 int ecode = ERR_get_error();
79                 error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL));
80                 xfree(sig);
81                 return -1;
82         }
83         if (len < slen) {
84                 int diff = slen - len;
85                 debug("slen %d > len %d", slen, len);
86                 memmove(sig + diff, sig, len);
87                 memset(sig, 0, diff);
88         } else if (len > slen) {
89                 error("ssh_rsa_sign: slen %d slen2 %d", slen, len);
90                 xfree(sig);
91                 return -1;
92         }
93         /* encode signature */
94         buffer_init(&b);
95         buffer_put_cstring(&b, "ssh-rsa");
96         buffer_put_string(&b, sig, slen);
97         len = buffer_len(&b);
98         ret = xmalloc(len);
99         memcpy(ret, buffer_ptr(&b), len);
100         buffer_free(&b);
101         memset(sig, 's', slen);
102         xfree(sig);
103
104         if (lenp != NULL)
105                 *lenp = len;
106         if (sigp != NULL)
107                 *sigp = ret;
108         return 0;
109 }
110
111 int
112 ssh_rsa_verify(
113     Key *key,
114     u_char *signature, u_int signaturelen,
115     u_char *data, u_int datalen)
116 {
117         Buffer b;
118         const EVP_MD *evp_md;
119         EVP_MD_CTX md;
120         char *ktype;
121         u_char digest[EVP_MAX_MD_SIZE], *sigblob;
122         u_int len, dlen;
123         int rlen, ret, nid;
124
125         if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
126                 error("ssh_rsa_verify: no RSA key");
127                 return -1;
128         }
129         if (datafellows & SSH_BUG_SIGBLOB) {
130                 error("ssh_rsa_verify: SSH_BUG_SIGBLOB not supported");
131                 return -1;
132         }
133         if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
134                 error("ssh_rsa_verify: n too small: %d bits",
135                     BN_num_bits(key->rsa->n));
136                 return -1;
137         }
138         buffer_init(&b);
139         buffer_append(&b, signature, signaturelen);
140         ktype = buffer_get_string(&b, NULL);
141         if (strcmp("ssh-rsa", ktype) != 0) {
142                 error("ssh_rsa_verify: cannot handle type %s", ktype);
143                 buffer_free(&b);
144                 xfree(ktype);
145                 return -1;
146         }
147         xfree(ktype);
148         sigblob = buffer_get_string(&b, &len);
149         rlen = buffer_len(&b);
150         buffer_free(&b);
151         if (rlen != 0) {
152                 error("ssh_rsa_verify: remaining bytes in signature %d", rlen);
153                 xfree(sigblob);
154                 return -1;
155         }
156         nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
157         if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
158                 error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);
159                 xfree(sigblob);
160                 return -1;
161         }
162         EVP_DigestInit(&md, evp_md);
163         EVP_DigestUpdate(&md, data, datalen);
164         EVP_DigestFinal(&md, digest, &dlen);
165
166         ret = RSA_verify(nid, digest, dlen, sigblob, len, key->rsa);
167         memset(digest, 'd', sizeof(digest));
168         memset(sigblob, 's', len);
169         xfree(sigblob);
170         if (ret == 0) {
171                 int ecode = ERR_get_error();
172                 error("ssh_rsa_verify: RSA_verify failed: %s", ERR_error_string(ecode, NULL));
173         }
174         debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
175         return ret;
176 }
This page took 0.039043 seconds and 3 git commands to generate.