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-dss.c,v 1.6 2001/02/08 19:30:52 itojun Exp $"); 27 28 #include <openssl/bn.h> 29 #include <openssl/evp.h> 30 31 #include "xmalloc.h" 32 #include "buffer.h" 33 #include "bufaux.h" 34 #include "compat.h" 35 #include "log.h" 36 #include "key.h" 37 #include "ssh-dss.h" 38 39 #define INTBLOB_LEN 20 40 #define SIGBLOB_LEN (2*INTBLOB_LEN) 41 42 int 43 ssh_dss_sign( 44 Key *key, 45 u_char **sigp, int *lenp, 46 u_char *data, int datalen) 47 { 48 u_char *digest; 49 u_char *ret; 50 DSA_SIG *sig; 51 EVP_MD *evp_md = EVP_sha1(); 52 EVP_MD_CTX md; 53 u_int rlen; 54 u_int slen; 55 u_int len, dlen; 56 u_char sigblob[SIGBLOB_LEN]; 57 Buffer b; 58 59 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 60 error("ssh_dss_sign: no DSA key"); 61 return -1; 62 } 63 dlen = evp_md->md_size; 64 digest = xmalloc(dlen); 65 EVP_DigestInit(&md, evp_md); 66 EVP_DigestUpdate(&md, data, datalen); 67 EVP_DigestFinal(&md, digest, NULL); 68 69 sig = DSA_do_sign(digest, dlen, key->dsa); 70 if (sig == NULL) { 71 fatal("ssh_dss_sign: cannot sign"); 72 } 73 memset(digest, 0, dlen); 74 xfree(digest); 75 76 rlen = BN_num_bytes(sig->r); 77 slen = BN_num_bytes(sig->s); 78 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 79 error("bad sig size %d %d", rlen, slen); 80 DSA_SIG_free(sig); 81 return -1; 82 } 83 debug("sig size %d %d", rlen, slen); 84 85 memset(sigblob, 0, SIGBLOB_LEN); 86 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 87 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); 88 DSA_SIG_free(sig); 89 90 if (datafellows & SSH_BUG_SIGBLOB) { 91 debug("datafellows"); 92 ret = xmalloc(SIGBLOB_LEN); 93 memcpy(ret, sigblob, SIGBLOB_LEN); 94 if (lenp != NULL) 95 *lenp = SIGBLOB_LEN; 96 if (sigp != NULL) 97 *sigp = ret; 98 } else { 99 /* ietf-drafts */ 100 buffer_init(&b); 101 buffer_put_cstring(&b, "ssh-dss"); 102 buffer_put_string(&b, sigblob, SIGBLOB_LEN); 103 len = buffer_len(&b); 104 ret = xmalloc(len); 105 memcpy(ret, buffer_ptr(&b), len); 106 buffer_free(&b); 107 if (lenp != NULL) 108 *lenp = len; 109 if (sigp != NULL) 110 *sigp = ret; 111 } 112 return 0; 113 } 114 int 115 ssh_dss_verify( 116 Key *key, 117 u_char *signature, int signaturelen, 118 u_char *data, int datalen) 119 { 120 Buffer b; 121 u_char *digest; 122 DSA_SIG *sig; 123 EVP_MD *evp_md = EVP_sha1(); 124 EVP_MD_CTX md; 125 u_char *sigblob; 126 char *txt; 127 u_int len, dlen; 128 int rlen; 129 int ret; 130 131 if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 132 error("ssh_dss_verify: no DSA key"); 133 return -1; 134 } 135 136 if (!(datafellows & SSH_BUG_SIGBLOB) && 137 signaturelen == SIGBLOB_LEN) { 138 datafellows |= ~SSH_BUG_SIGBLOB; 139 log("autodetect SSH_BUG_SIGBLOB"); 140 } else if ((datafellows & SSH_BUG_SIGBLOB) && 141 signaturelen != SIGBLOB_LEN) { 142 log("autoremove SSH_BUG_SIGBLOB"); 143 datafellows &= ~SSH_BUG_SIGBLOB; 144 } 145 146 debug("len %d datafellows %d", signaturelen, datafellows); 147 148 /* fetch signature */ 149 if (datafellows & SSH_BUG_SIGBLOB) { 150 sigblob = signature; 151 len = signaturelen; 152 } else { 153 /* ietf-drafts */ 154 char *ktype; 155 buffer_init(&b); 156 buffer_append(&b, (char *) signature, signaturelen); 157 ktype = buffer_get_string(&b, NULL); 158 if (strcmp("ssh-dss", ktype) != 0) { 159 error("ssh_dss_verify: cannot handle type %s", ktype); 160 buffer_free(&b); 161 return -1; 162 } 163 sigblob = (u_char *)buffer_get_string(&b, &len); 164 rlen = buffer_len(&b); 165 if(rlen != 0) { 166 error("remaining bytes in signature %d", rlen); 167 buffer_free(&b); 168 return -1; 169 } 170 buffer_free(&b); 171 xfree(ktype); 172 } 173 174 if (len != SIGBLOB_LEN) { 175 fatal("bad sigbloblen %d != SIGBLOB_LEN", len); 176 } 177 178 /* parse signature */ 179 sig = DSA_SIG_new(); 180 sig->r = BN_new(); 181 sig->s = BN_new(); 182 BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); 183 BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); 184 185 if (!(datafellows & SSH_BUG_SIGBLOB)) { 186 memset(sigblob, 0, len); 187 xfree(sigblob); 188 } 189 190 /* sha1 the data */ 191 dlen = evp_md->md_size; 192 digest = xmalloc(dlen); 193 EVP_DigestInit(&md, evp_md); 194 EVP_DigestUpdate(&md, data, datalen); 195 EVP_DigestFinal(&md, digest, NULL); 196 197 ret = DSA_do_verify(digest, dlen, sig, key->dsa); 198 199 memset(digest, 0, dlen); 200 xfree(digest); 201 DSA_SIG_free(sig); 202 203 switch (ret) { 204 case 1: 205 txt = "correct"; 206 break; 207 case 0: 208 txt = "incorrect"; 209 break; 210 case -1: 211 default: 212 txt = "error"; 213 break; 214 } 215 debug("ssh_dss_verify: signature %s", txt); 216 return ret; 217 } 218