11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: ssh-dss.c,v 1.27 2010/08/31 09:58:37 djm Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000 Markus Friedl. All rights reserved. 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met: 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer. 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer in the 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * documentation and/or other materials provided with the distribution. 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/bn.h> 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h> 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h" 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h" 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define INTBLOB_LEN 20 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SIGBLOB_LEN (2*INTBLOB_LEN) 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const u_char *data, u_int datalen) 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_SIG *sig; 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EVP_MD *evp_md = EVP_sha1(); 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_MD_CTX md; 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int rlen, slen, len, dlen; 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer b; 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) { 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_dss_sign: no DSA key"); 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestInit(&md, evp_md); 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestUpdate(&md, data, datalen); 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestFinal(&md, digest, &dlen); 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sig = DSA_do_sign(digest, dlen, key->dsa); 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(digest, 'd', sizeof(digest)); 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sig == NULL) { 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_dss_sign: sign failed"); 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rlen = BN_num_bytes(sig->r); 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood slen = BN_num_bytes(sig->s); 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("bad sig size %u %u", rlen, slen); 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_SIG_free(sig); 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(sigblob, 0, SIGBLOB_LEN); 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_SIG_free(sig); 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (datafellows & SSH_BUG_SIGBLOB) { 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lenp != NULL) 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lenp = SIGBLOB_LEN; 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sigp != NULL) { 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *sigp = xmalloc(SIGBLOB_LEN); 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(*sigp, sigblob, SIGBLOB_LEN); 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* ietf-drafts */ 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&b); 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_cstring(&b, "ssh-dss"); 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_string(&b, sigblob, SIGBLOB_LEN); 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = buffer_len(&b); 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lenp != NULL) 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lenp = len; 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sigp != NULL) { 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *sigp = xmalloc(len); 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(*sigp, buffer_ptr(&b), len); 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&b); 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const u_char *data, u_int datalen) 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_SIG *sig; 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EVP_MD *evp_md = EVP_sha1(); 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_MD_CTX md; 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char digest[EVP_MAX_MD_SIZE], *sigblob; 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int len, dlen; 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rlen, ret; 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer b; 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) { 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_dss_verify: no DSA key"); 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* fetch signature */ 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (datafellows & SSH_BUG_SIGBLOB) { 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigblob = xmalloc(signaturelen); 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(sigblob, signature, signaturelen); 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = signaturelen; 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* ietf-drafts */ 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *ktype; 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&b); 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&b, signature, signaturelen); 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ktype = buffer_get_cstring(&b, NULL); 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcmp("ssh-dss", ktype) != 0) { 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_dss_verify: cannot handle type %s", ktype); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&b); 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(ktype); 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(ktype); 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigblob = buffer_get_string(&b, &len); 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rlen = buffer_len(&b); 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&b); 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (rlen != 0) { 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_dss_verify: " 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "remaining bytes in signature %d", rlen); 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(sigblob); 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len != SIGBLOB_LEN) { 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("bad sigbloblen %u != SIGBLOB_LEN", len); 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* parse signature */ 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((sig = DSA_SIG_new()) == NULL) 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_dss_verify: DSA_SIG_new failed"); 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((sig->r = BN_new()) == NULL) 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_dss_verify: BN_new failed"); 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((sig->s = BN_new()) == NULL) 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_dss_verify: BN_new failed"); 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_dss_verify: BN_bin2bn failed"); 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* clean up */ 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(sigblob, 0, len); 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(sigblob); 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* sha1 the data */ 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestInit(&md, evp_md); 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestUpdate(&md, data, datalen); 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_DigestFinal(&md, digest, &dlen); 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = DSA_do_verify(digest, dlen, sig, key->dsa); 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(digest, 'd', sizeof(digest)); 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood DSA_SIG_free(sig); 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("ssh_dss_verify: signature %s", 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 188