Annotation of src/usr.bin/ssh/ssh-ed25519-sk.c, Revision 1.1
1.1 ! markus 1: /* $OpenBSD: ssh-ed25519.c,v 1.7 2016/04/21 06:08:02 djm Exp $ */
! 2: /*
! 3: * Copyright (c) 2019 Markus Friedl. All rights reserved.
! 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: */
! 17: #define SSHKEY_INTERNAL
! 18: #include <sys/types.h>
! 19: #include <limits.h>
! 20:
! 21: #include "crypto_api.h"
! 22:
! 23: #include <string.h>
! 24: #include <stdarg.h>
! 25:
! 26: #include "log.h"
! 27: #include "sshbuf.h"
! 28: #include "sshkey.h"
! 29: #include "ssherr.h"
! 30: #include "ssh.h"
! 31: #include "digest.h"
! 32:
! 33: int
! 34: ssh_ed25519_sk_verify(const struct sshkey *key,
! 35: const u_char *signature, size_t signaturelen,
! 36: const u_char *data, size_t datalen, u_int compat)
! 37: {
! 38: struct sshbuf *b = NULL;
! 39: struct sshbuf *sigbuf = NULL;
! 40: struct sshbuf *encoded = NULL;
! 41: char *ktype = NULL;
! 42: const u_char *sigblob;
! 43: const u_char *sm;
! 44: u_char *m = NULL;
! 45: u_char apphash[32];
! 46: u_char msghash[32];
! 47: u_char sig_flags;
! 48: u_int sig_counter;
! 49: size_t len;
! 50: unsigned long long smlen = 0, mlen = 0;
! 51: int r = SSH_ERR_INTERNAL_ERROR;
! 52: int ret;
! 53:
! 54: if (key == NULL ||
! 55: sshkey_type_plain(key->type) != KEY_ED25519_SK ||
! 56: key->ed25519_pk == NULL ||
! 57: signature == NULL || signaturelen == 0)
! 58: return SSH_ERR_INVALID_ARGUMENT;
! 59:
! 60: if ((b = sshbuf_from(signature, signaturelen)) == NULL)
! 61: return SSH_ERR_ALLOC_FAIL;
! 62: if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
! 63: sshbuf_froms(b, &sigbuf) != 0 ||
! 64: sshbuf_get_string_direct(sigbuf, &sigblob, &len) != 0 ||
! 65: sshbuf_get_u8(sigbuf, &sig_flags) != 0 ||
! 66: sshbuf_get_u32(sigbuf, &sig_counter) != 0) {
! 67: r = SSH_ERR_INVALID_FORMAT;
! 68: goto out;
! 69: }
! 70: if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
! 71: r = SSH_ERR_KEY_TYPE_MISMATCH;
! 72: goto out;
! 73: }
! 74: if (sshbuf_len(b) != 0) {
! 75: r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
! 76: goto out;
! 77: }
! 78: if (len > crypto_sign_ed25519_BYTES) {
! 79: r = SSH_ERR_INVALID_FORMAT;
! 80: goto out;
! 81: }
! 82: if (ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application,
! 83: strlen(key->sk_application), apphash, sizeof(apphash)) != 0 ||
! 84: ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
! 85: msghash, sizeof(msghash)) != 0) {
! 86: r = SSH_ERR_INVALID_ARGUMENT;
! 87: goto out;
! 88: }
! 89: if ((encoded = sshbuf_new()) == NULL) {
! 90: r = SSH_ERR_ALLOC_FAIL;
! 91: goto out;
! 92: }
! 93: if (sshbuf_put(encoded, sigblob, len) != 0 ||
! 94: sshbuf_put(encoded, apphash, sizeof(apphash)) != 0 ||
! 95: sshbuf_put_u8(encoded, sig_flags) != 0 ||
! 96: sshbuf_put_u32(encoded, sig_counter) != 0 ||
! 97: sshbuf_put(encoded, msghash, sizeof(msghash)) != 0) {
! 98: r = SSH_ERR_ALLOC_FAIL;
! 99: goto out;
! 100: }
! 101: sm = sshbuf_ptr(encoded);
! 102: smlen = sshbuf_len(encoded);
! 103: mlen = smlen;
! 104: if ((m = malloc(smlen)) == NULL) {
! 105: r = SSH_ERR_ALLOC_FAIL;
! 106: goto out;
! 107: }
! 108: if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
! 109: key->ed25519_pk)) != 0) {
! 110: debug2("%s: crypto_sign_ed25519_open failed: %d",
! 111: __func__, ret);
! 112: }
! 113: if (ret != 0 || mlen != smlen - len) {
! 114: r = SSH_ERR_SIGNATURE_INVALID;
! 115: goto out;
! 116: }
! 117: /* XXX compare 'm' and 'sm + len' ? */
! 118: /* success */
! 119: r = 0;
! 120: out:
! 121: if (m != NULL) {
! 122: explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
! 123: free(m);
! 124: }
! 125: sshbuf_free(b);
! 126: sshbuf_free(sigbuf);
! 127: sshbuf_free(encoded);
! 128: free(ktype);
! 129: return r;
! 130: }