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

Annotation of src/usr.bin/ssh/ssh-ed25519.c, Revision 1.4

1.4     ! djm         1: /* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */
1.1       markus      2: /*
                      3:  * Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
1.4     ! djm        17: #define SSHKEY_INTERNAL
1.1       markus     18: #include <sys/types.h>
1.4     ! djm        19: #include <limits.h>
1.1       markus     20:
                     21: #include "crypto_api.h"
                     22:
                     23: #include <string.h>
                     24: #include <stdarg.h>
                     25:
                     26: #include "xmalloc.h"
                     27: #include "log.h"
                     28: #include "buffer.h"
1.4     ! djm        29: #include "sshkey.h"
        !            30: #include "ssherr.h"
1.1       markus     31: #include "ssh.h"
                     32:
                     33: int
1.4     ! djm        34: ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        !            35:     const u_char *data, size_t datalen, u_int compat)
1.1       markus     36: {
1.4     ! djm        37:        u_char *sig = NULL;
        !            38:        size_t slen = 0, len;
1.1       markus     39:        unsigned long long smlen;
1.4     ! djm        40:        int r, ret;
        !            41:        struct sshbuf *b = NULL;
1.1       markus     42:
1.4     ! djm        43:        if (lenp != NULL)
        !            44:                *lenp = 0;
        !            45:        if (sigp != NULL)
        !            46:                *sigp = NULL;
        !            47:
        !            48:        if (key == NULL ||
        !            49:            sshkey_type_plain(key->type) != KEY_ED25519 ||
        !            50:            key->ed25519_sk == NULL ||
        !            51:            datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
        !            52:                return SSH_ERR_INVALID_ARGUMENT;
1.1       markus     53:        smlen = slen = datalen + crypto_sign_ed25519_BYTES;
1.4     ! djm        54:        if ((sig = malloc(slen)) == NULL)
        !            55:                return SSH_ERR_ALLOC_FAIL;
1.1       markus     56:
                     57:        if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
                     58:            key->ed25519_sk)) != 0 || smlen <= datalen) {
1.4     ! djm        59:                r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
        !            60:                goto out;
1.1       markus     61:        }
                     62:        /* encode signature */
1.4     ! djm        63:        if ((b = sshbuf_new()) == NULL) {
        !            64:                r = SSH_ERR_ALLOC_FAIL;
        !            65:                goto out;
        !            66:        }
        !            67:        if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 ||
        !            68:            (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
        !            69:                goto out;
        !            70:        len = sshbuf_len(b);
        !            71:        if (sigp != NULL) {
        !            72:                if ((*sigp = malloc(len)) == NULL) {
        !            73:                        r = SSH_ERR_ALLOC_FAIL;
        !            74:                        goto out;
        !            75:                }
        !            76:                memcpy(*sigp, sshbuf_ptr(b), len);
        !            77:        }
1.1       markus     78:        if (lenp != NULL)
                     79:                *lenp = len;
1.4     ! djm        80:        /* success */
        !            81:        r = 0;
        !            82:  out:
        !            83:        sshbuf_free(b);
        !            84:        if (sig != NULL) {
        !            85:                explicit_bzero(sig, slen);
        !            86:                free(sig);
1.1       markus     87:        }
                     88:
1.4     ! djm        89:        return r;
1.1       markus     90: }
                     91:
                     92: int
1.4     ! djm        93: ssh_ed25519_verify(const struct sshkey *key,
        !            94:     const u_char *signature, size_t signaturelen,
        !            95:     const u_char *data, size_t datalen, u_int compat)
1.1       markus     96: {
1.4     ! djm        97:        struct sshbuf *b = NULL;
        !            98:        char *ktype = NULL;
        !            99:        const u_char *sigblob;
        !           100:        u_char *sm = NULL, *m = NULL;
        !           101:        size_t len;
        !           102:        unsigned long long smlen = 0, mlen = 0;
        !           103:        int r, ret;
        !           104:
        !           105:        if (key == NULL ||
        !           106:            sshkey_type_plain(key->type) != KEY_ED25519 ||
        !           107:            key->ed25519_pk == NULL ||
        !           108:            datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
        !           109:                return SSH_ERR_INVALID_ARGUMENT;
        !           110:
        !           111:        if ((b = sshbuf_from(signature, signaturelen)) == NULL)
        !           112:                return SSH_ERR_ALLOC_FAIL;
        !           113:        if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
        !           114:            (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
        !           115:                goto out;
1.1       markus    116:        if (strcmp("ssh-ed25519", ktype) != 0) {
1.4     ! djm       117:                r = SSH_ERR_KEY_TYPE_MISMATCH;
        !           118:                goto out;
1.1       markus    119:        }
1.4     ! djm       120:        if (sshbuf_len(b) != 0) {
        !           121:                r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
        !           122:                goto out;
1.1       markus    123:        }
                    124:        if (len > crypto_sign_ed25519_BYTES) {
1.4     ! djm       125:                r = SSH_ERR_INVALID_FORMAT;
        !           126:                goto out;
1.1       markus    127:        }
1.4     ! djm       128:        if (datalen >= SIZE_MAX - len)
        !           129:                return SSH_ERR_INVALID_ARGUMENT;
1.1       markus    130:        smlen = len + datalen;
1.4     ! djm       131:        mlen = smlen;
        !           132:        if ((sm = malloc(smlen)) == NULL || (m = xmalloc(mlen)) == NULL) {
        !           133:                r = SSH_ERR_ALLOC_FAIL;
        !           134:                goto out;
        !           135:        }
1.1       markus    136:        memcpy(sm, sigblob, len);
                    137:        memcpy(sm+len, data, datalen);
                    138:        if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
                    139:            key->ed25519_pk)) != 0) {
                    140:                debug2("%s: crypto_sign_ed25519_open failed: %d",
                    141:                    __func__, ret);
                    142:        }
1.4     ! djm       143:        if (ret != 0 || mlen != datalen) {
        !           144:                r = SSH_ERR_SIGNATURE_INVALID;
        !           145:                goto out;
1.1       markus    146:        }
                    147:        /* XXX compare 'm' and 'data' ? */
1.4     ! djm       148:        /* success */
        !           149:        r = 0;
        !           150:  out:
        !           151:        if (sm != NULL) {
        !           152:                explicit_bzero(sm, smlen);
        !           153:                free(sm);
        !           154:        }
        !           155:        if (m != NULL) {
        !           156:                explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
        !           157:                free(m);
        !           158:        }
        !           159:        sshbuf_free(b);
        !           160:        free(ktype);
        !           161:        return r;
        !           162: }
1.1       markus    163: