[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.38

1.38    ! djm         1: /* $OpenBSD: ssh-dss.c,v 1.37 2018/02/07 02:06:51 jsing Exp $ */
1.1       markus      2: /*
                      3:  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  *
                     14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     15:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     16:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     17:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     18:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     19:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     20:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     21:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     22:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     23:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     24:  */
                     25:
1.23      deraadt    26: #include <sys/types.h>
1.4       markus     27:
                     28: #include <openssl/bn.h>
                     29: #include <openssl/evp.h>
1.22      stevesk    30:
                     31: #include <string.h>
1.1       markus     32:
1.32      djm        33: #include "sshbuf.h"
1.1       markus     34: #include "compat.h"
1.32      djm        35: #include "ssherr.h"
1.30      djm        36: #include "digest.h"
1.32      djm        37: #define SSHKEY_INTERNAL
                     38: #include "sshkey.h"
1.1       markus     39:
                     40: #define INTBLOB_LEN    20
                     41: #define SIGBLOB_LEN    (2*INTBLOB_LEN)
                     42:
                     43: int
1.32      djm        44: ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
                     45:     const u_char *data, size_t datalen, u_int compat)
1.1       markus     46: {
1.32      djm        47:        DSA_SIG *sig = NULL;
1.38    ! djm        48:        const BIGNUM *sig_r, *sig_s;
1.30      djm        49:        u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
1.32      djm        50:        size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
                     51:        struct sshbuf *b = NULL;
                     52:        int ret = SSH_ERR_INVALID_ARGUMENT;
                     53:
                     54:        if (lenp != NULL)
                     55:                *lenp = 0;
                     56:        if (sigp != NULL)
                     57:                *sigp = NULL;
                     58:
                     59:        if (key == NULL || key->dsa == NULL ||
                     60:            sshkey_type_plain(key->type) != KEY_DSA)
                     61:                return SSH_ERR_INVALID_ARGUMENT;
                     62:        if (dlen == 0)
                     63:                return SSH_ERR_INTERNAL_ERROR;
                     64:
                     65:        if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
                     66:            digest, sizeof(digest))) != 0)
                     67:                goto out;
                     68:
                     69:        if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) {
                     70:                ret = SSH_ERR_LIBCRYPTO_ERROR;
                     71:                goto out;
1.1       markus     72:        }
                     73:
1.38    ! djm        74:        DSA_SIG_get0(sig, &sig_r, &sig_s);
        !            75:        rlen = BN_num_bytes(sig_r);
        !            76:        slen = BN_num_bytes(sig_s);
1.1       markus     77:        if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
1.32      djm        78:                ret = SSH_ERR_INTERNAL_ERROR;
                     79:                goto out;
1.1       markus     80:        }
1.31      djm        81:        explicit_bzero(sigblob, SIGBLOB_LEN);
1.38    ! djm        82:        BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
        !            83:        BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen);
1.1       markus     84:
1.36      djm        85:        if ((b = sshbuf_new()) == NULL) {
                     86:                ret = SSH_ERR_ALLOC_FAIL;
                     87:                goto out;
                     88:        }
                     89:        if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 ||
                     90:            (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0)
                     91:                goto out;
                     92:
                     93:        len = sshbuf_len(b);
                     94:        if (sigp != NULL) {
                     95:                if ((*sigp = malloc(len)) == NULL) {
1.32      djm        96:                        ret = SSH_ERR_ALLOC_FAIL;
                     97:                        goto out;
                     98:                }
1.36      djm        99:                memcpy(*sigp, sshbuf_ptr(b), len);
1.1       markus    100:        }
1.36      djm       101:        if (lenp != NULL)
                    102:                *lenp = len;
                    103:        ret = 0;
1.32      djm       104:  out:
                    105:        explicit_bzero(digest, sizeof(digest));
1.37      jsing     106:        DSA_SIG_free(sig);
1.34      mmcc      107:        sshbuf_free(b);
1.32      djm       108:        return ret;
1.1       markus    109: }
1.32      djm       110:
1.1       markus    111: int
1.32      djm       112: ssh_dss_verify(const struct sshkey *key,
                    113:     const u_char *signature, size_t signaturelen,
                    114:     const u_char *data, size_t datalen, u_int compat)
1.1       markus    115: {
1.32      djm       116:        DSA_SIG *sig = NULL;
1.38    ! djm       117:        BIGNUM *sig_r = NULL, *sig_s = NULL;
1.32      djm       118:        u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
                    119:        size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
                    120:        int ret = SSH_ERR_INTERNAL_ERROR;
                    121:        struct sshbuf *b = NULL;
                    122:        char *ktype = NULL;
                    123:
                    124:        if (key == NULL || key->dsa == NULL ||
1.35      djm       125:            sshkey_type_plain(key->type) != KEY_DSA ||
                    126:            signature == NULL || signaturelen == 0)
1.32      djm       127:                return SSH_ERR_INVALID_ARGUMENT;
                    128:        if (dlen == 0)
                    129:                return SSH_ERR_INTERNAL_ERROR;
1.1       markus    130:
                    131:        /* fetch signature */
1.36      djm       132:        if ((b = sshbuf_from(signature, signaturelen)) == NULL)
                    133:                return SSH_ERR_ALLOC_FAIL;
                    134:        if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
                    135:            sshbuf_get_string(b, &sigblob, &len) != 0) {
                    136:                ret = SSH_ERR_INVALID_FORMAT;
                    137:                goto out;
                    138:        }
                    139:        if (strcmp("ssh-dss", ktype) != 0) {
                    140:                ret = SSH_ERR_KEY_TYPE_MISMATCH;
                    141:                goto out;
                    142:        }
                    143:        if (sshbuf_len(b) != 0) {
                    144:                ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
                    145:                goto out;
1.1       markus    146:        }
                    147:
                    148:        if (len != SIGBLOB_LEN) {
1.32      djm       149:                ret = SSH_ERR_INVALID_FORMAT;
                    150:                goto out;
1.1       markus    151:        }
                    152:
                    153:        /* parse signature */
1.32      djm       154:        if ((sig = DSA_SIG_new()) == NULL ||
1.38    ! djm       155:            (sig_r = BN_new()) == NULL ||
        !           156:            (sig_s = BN_new()) == NULL) {
1.32      djm       157:                ret = SSH_ERR_ALLOC_FAIL;
                    158:                goto out;
                    159:        }
1.38    ! djm       160:        if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) ||
        !           161:            (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) {
1.32      djm       162:                ret = SSH_ERR_LIBCRYPTO_ERROR;
                    163:                goto out;
                    164:        }
1.38    ! djm       165:        if (!DSA_SIG_set0(sig, sig_r, sig_s)) {
        !           166:                ret = SSH_ERR_LIBCRYPTO_ERROR;
        !           167:                goto out;
        !           168:        }
        !           169:        sig_r = sig_s = NULL; /* transferred */
1.5       stevesk   170:
1.1       markus    171:        /* sha1 the data */
1.32      djm       172:        if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
                    173:            digest, sizeof(digest))) != 0)
                    174:                goto out;
                    175:
                    176:        switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
                    177:        case 1:
                    178:                ret = 0;
                    179:                break;
                    180:        case 0:
                    181:                ret = SSH_ERR_SIGNATURE_INVALID;
                    182:                goto out;
                    183:        default:
                    184:                ret = SSH_ERR_LIBCRYPTO_ERROR;
                    185:                goto out;
1.30      djm       186:        }
1.1       markus    187:
1.32      djm       188:  out:
1.31      djm       189:        explicit_bzero(digest, sizeof(digest));
1.37      jsing     190:        DSA_SIG_free(sig);
1.38    ! djm       191:        BN_clear_free(sig_r);
        !           192:        BN_clear_free(sig_s);
1.34      mmcc      193:        sshbuf_free(b);
1.33      mmcc      194:        free(ktype);
1.32      djm       195:        if (sigblob != NULL) {
                    196:                explicit_bzero(sigblob, len);
                    197:                free(sigblob);
                    198:        }
1.1       markus    199:        return ret;
                    200: }