[BACK]Return to ssh-dss.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

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: }