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