Annotation of src/usr.bin/ssh/ssh-ed25519.c, Revision 1.1
1.1 ! markus 1: /* $OpenBSD: ssh-ed25519.c,v 1.46 2013/05/17 00:13:14 djm Exp $ */
! 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: */
! 17:
! 18: #include <sys/types.h>
! 19:
! 20: #include "crypto_api.h"
! 21:
! 22: #include <string.h>
! 23: #include <stdarg.h>
! 24:
! 25: #include "xmalloc.h"
! 26: #include "log.h"
! 27: #include "buffer.h"
! 28: #include "key.h"
! 29: #include "ssh.h"
! 30:
! 31: int
! 32: ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp,
! 33: const u_char *data, u_int datalen)
! 34: {
! 35: u_char *sig;
! 36: u_int slen, len;
! 37: unsigned long long smlen;
! 38: int ret;
! 39: Buffer b;
! 40:
! 41: if (key == NULL || key_type_plain(key->type) != KEY_ED25519 ||
! 42: key->ed25519_sk == NULL) {
! 43: error("%s: no ED25519 key", __func__);
! 44: return -1;
! 45: }
! 46: smlen = slen = datalen + crypto_sign_ed25519_BYTES;
! 47: sig = xmalloc(slen);
! 48:
! 49: if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
! 50: key->ed25519_sk)) != 0 || smlen <= datalen) {
! 51: error("%s: crypto_sign_ed25519 failed: %d", __func__, ret);
! 52: free(sig);
! 53: return -1;
! 54: }
! 55: /* encode signature */
! 56: buffer_init(&b);
! 57: buffer_put_cstring(&b, "ssh-ed25519");
! 58: buffer_put_string(&b, sig, smlen - datalen);
! 59: len = buffer_len(&b);
! 60: if (lenp != NULL)
! 61: *lenp = len;
! 62: if (sigp != NULL) {
! 63: *sigp = xmalloc(len);
! 64: memcpy(*sigp, buffer_ptr(&b), len);
! 65: }
! 66: buffer_free(&b);
! 67: memset(sig, 's', slen);
! 68: free(sig);
! 69:
! 70: return 0;
! 71: }
! 72:
! 73: int
! 74: ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen,
! 75: const u_char *data, u_int datalen)
! 76: {
! 77: Buffer b;
! 78: char *ktype;
! 79: u_char *sigblob, *sm, *m;
! 80: u_int len;
! 81: unsigned long long smlen, mlen;
! 82: int rlen, ret;
! 83:
! 84: if (key == NULL || key_type_plain(key->type) != KEY_ED25519 ||
! 85: key->ed25519_pk == NULL) {
! 86: error("%s: no ED25519 key", __func__);
! 87: return -1;
! 88: }
! 89: buffer_init(&b);
! 90: buffer_append(&b, signature, signaturelen);
! 91: ktype = buffer_get_cstring(&b, NULL);
! 92: if (strcmp("ssh-ed25519", ktype) != 0) {
! 93: error("%s: cannot handle type %s", __func__, ktype);
! 94: buffer_free(&b);
! 95: free(ktype);
! 96: return -1;
! 97: }
! 98: free(ktype);
! 99: sigblob = buffer_get_string(&b, &len);
! 100: rlen = buffer_len(&b);
! 101: buffer_free(&b);
! 102: if (rlen != 0) {
! 103: error("%s: remaining bytes in signature %d", __func__, rlen);
! 104: free(sigblob);
! 105: return -1;
! 106: }
! 107: if (len > crypto_sign_ed25519_BYTES) {
! 108: error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__,
! 109: len, crypto_sign_ed25519_BYTES);
! 110: free(sigblob);
! 111: return -1;
! 112: }
! 113: smlen = len + datalen;
! 114: sm = xmalloc(smlen);
! 115: memcpy(sm, sigblob, len);
! 116: memcpy(sm+len, data, datalen);
! 117: mlen = smlen;
! 118: m = xmalloc(mlen);
! 119: if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
! 120: key->ed25519_pk)) != 0) {
! 121: debug2("%s: crypto_sign_ed25519_open failed: %d",
! 122: __func__, ret);
! 123: }
! 124: if (ret == 0 && mlen != datalen) {
! 125: debug2("%s: crypto_sign_ed25519_open "
! 126: "mlen != datalen (%llu != %u)", __func__, mlen, datalen);
! 127: ret = -1;
! 128: }
! 129: /* XXX compare 'm' and 'data' ? */
! 130:
! 131: memset(sigblob, 's', len);
! 132: memset(sm, 'S', smlen);
! 133: memset(m, 'm', smlen); /* NB. mlen may be invalid if ret != 0 */
! 134: free(sigblob);
! 135: free(sm);
! 136: free(m);
! 137: debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : "");
! 138:
! 139: /* translate return code carefully */
! 140: return (ret == 0) ? 1 : -1;
! 141: }