ssh-dss.c revision 92555
11553Srgrimes/* 21553Srgrimes * Copyright (c) 2000 Markus Friedl. All rights reserved. 31553Srgrimes * 41553Srgrimes * Redistribution and use in source and binary forms, with or without 51553Srgrimes * modification, are permitted provided that the following conditions 61553Srgrimes * are met: 71553Srgrimes * 1. Redistributions of source code must retain the above copyright 81553Srgrimes * notice, this list of conditions and the following disclaimer. 91553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 101553Srgrimes * notice, this list of conditions and the following disclaimer in the 111553Srgrimes * documentation and/or other materials provided with the distribution. 121553Srgrimes * 131553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 141553Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 151553Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 161553Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 171553Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 181553Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 191553Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 201553Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 211553Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 221553Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 231553Srgrimes */ 241553Srgrimes 251553Srgrimes#include "includes.h" 261553SrgrimesRCSID("$OpenBSD: ssh-dss.c,v 1.14 2002/02/28 15:46:33 markus Exp $"); 271553Srgrimes 281553Srgrimes#include <openssl/bn.h> 291553Srgrimes#include <openssl/evp.h> 301553Srgrimes 3152007Speter#include "xmalloc.h" 321553Srgrimes#include "buffer.h" 331553Srgrimes#include "bufaux.h" 3479607Sdd#include "compat.h" 351553Srgrimes#include "log.h" 36205880Sru#include "key.h" 37264325Sasomers#include "ssh-dss.h" 386494Sbde 3916073Sphk#define INTBLOB_LEN 20 401553Srgrimes#define SIGBLOB_LEN (2*INTBLOB_LEN) 411553Srgrimes 421553Srgrimesint 4379607Sddssh_dss_sign( 4479607Sdd Key *key, 4579607Sdd u_char **sigp, u_int *lenp, 4679607Sdd u_char *data, u_int datalen) 4779607Sdd{ 4879607Sdd DSA_SIG *sig; 4979607Sdd const EVP_MD *evp_md = EVP_sha1(); 5079607Sdd EVP_MD_CTX md; 5179607Sdd u_char *ret, digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; 5279607Sdd u_int rlen, slen, len, dlen; 5379607Sdd Buffer b; 5479607Sdd 5579607Sdd if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 561553Srgrimes error("ssh_dss_sign: no DSA key"); 571553Srgrimes return -1; 581553Srgrimes } 591553Srgrimes EVP_DigestInit(&md, evp_md); 6072684Speter EVP_DigestUpdate(&md, data, datalen); 611553Srgrimes EVP_DigestFinal(&md, digest, &dlen); 621553Srgrimes 6346855Speter sig = DSA_do_sign(digest, dlen, key->dsa); 641553Srgrimes memset(digest, 'd', sizeof(digest)); 65152018Sru 661553Srgrimes if (sig == NULL) { 67141615Sdes error("ssh_dss_sign: sign failed"); 68111582Sru return -1; 69141615Sdes } 7082393Speter 7161640Speter rlen = BN_num_bytes(sig->r); 721553Srgrimes slen = BN_num_bytes(sig->s); 7352653Smarcel if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 74153063Sru error("bad sig size %d %d", rlen, slen); 751553Srgrimes DSA_SIG_free(sig); 76111582Sru return -1; 77152023Sru } 781553Srgrimes memset(sigblob, 0, SIGBLOB_LEN); 7967109Sphk BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 8048402Speter BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); 811553Srgrimes DSA_SIG_free(sig); 82111582Sru 83136429Sphk if (datafellows & SSH_BUG_SIGBLOB) { 8479607Sdd ret = xmalloc(SIGBLOB_LEN); 85129073Scognet memcpy(ret, sigblob, SIGBLOB_LEN); 861553Srgrimes if (lenp != NULL) 871553Srgrimes *lenp = SIGBLOB_LEN; 8829451Scharnier if (sigp != NULL) 8929451Scharnier *sigp = ret; 9079607Sdd } else { 9179607Sdd /* ietf-drafts */ 9261640Speter buffer_init(&b); 9398555Sjmallett buffer_put_cstring(&b, "ssh-dss"); 9498555Sjmallett buffer_put_string(&b, sigblob, SIGBLOB_LEN); 9579607Sdd len = buffer_len(&b); 9629451Scharnier ret = xmalloc(len); 97250926Sjkim memcpy(ret, buffer_ptr(&b), len); 981553Srgrimes buffer_free(&b); 99250227Sjkim if (lenp != NULL) 100250227Sjkim *lenp = len; 101250227Sjkim if (sigp != NULL) 102250227Sjkim *sigp = ret; 10346104Sluoqi } 104180922Sobrien return 0; 105134542Speter} 1061553Srgrimesint 107134542Speterssh_dss_verify( 1081553Srgrimes Key *key, 1091553Srgrimes u_char *signature, u_int signaturelen, 11046104Sluoqi u_char *data, u_int datalen) 1111553Srgrimes{ 1121553Srgrimes DSA_SIG *sig; 1136494Sbde const EVP_MD *evp_md = EVP_sha1(); 1141553Srgrimes EVP_MD_CTX md; 1151553Srgrimes u_char digest[EVP_MAX_MD_SIZE], *sigblob; 1161553Srgrimes u_int len, dlen; 1171553Srgrimes int rlen, ret; 11812772Speter Buffer b; 11946104Sluoqi 12046104Sluoqi if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 12146104Sluoqi error("ssh_dss_verify: no DSA key"); 12212772Speter return -1; 12312772Speter } 12412772Speter 1251553Srgrimes /* fetch signature */ 12646104Sluoqi if (datafellows & SSH_BUG_SIGBLOB) { 12746104Sluoqi sigblob = signature; 1286494Sbde len = signaturelen; 1291553Srgrimes } else { 1301553Srgrimes /* ietf-drafts */ 13148402Speter char *ktype; 13246104Sluoqi buffer_init(&b); 13346104Sluoqi buffer_append(&b, signature, signaturelen); 13446104Sluoqi ktype = buffer_get_string(&b, NULL); 13546104Sluoqi if (strcmp("ssh-dss", ktype) != 0) { 1361553Srgrimes error("ssh_dss_verify: cannot handle type %s", ktype); 1371553Srgrimes buffer_free(&b); 1381553Srgrimes xfree(ktype); 1391553Srgrimes return -1; 1401553Srgrimes } 1411553Srgrimes xfree(ktype); 1421553Srgrimes sigblob = buffer_get_string(&b, &len); 1431553Srgrimes rlen = buffer_len(&b); 14446104Sluoqi buffer_free(&b); 14546021Speter if (rlen != 0) { 14646021Speter error("ssh_dss_verify: " 14746021Speter "remaining bytes in signature %d", rlen); 1481553Srgrimes xfree(sigblob); 1491553Srgrimes return -1; 1501553Srgrimes } 1511553Srgrimes } 1521553Srgrimes 1531553Srgrimes if (len != SIGBLOB_LEN) { 1541553Srgrimes fatal("bad sigbloblen %d != SIGBLOB_LEN", len); 1551553Srgrimes } 1561553Srgrimes 1571553Srgrimes /* parse signature */ 1581553Srgrimes if ((sig = DSA_SIG_new()) == NULL) 1591553Srgrimes fatal("ssh_dss_verify: DSA_SIG_new failed"); 1604242Swollman if ((sig->r = BN_new()) == NULL) 1611553Srgrimes fatal("ssh_dss_verify: BN_new failed"); 1621553Srgrimes if ((sig->s = BN_new()) == NULL) 16346104Sluoqi fatal("ssh_dss_verify: BN_new failed"); 164185186Sthompsa BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); 16579607Sdd BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); 16679607Sdd 16779607Sdd if (!(datafellows & SSH_BUG_SIGBLOB)) { 16879607Sdd memset(sigblob, 0, len); 16979607Sdd xfree(sigblob); 17079607Sdd } 17179607Sdd 17279607Sdd /* sha1 the data */ 17379607Sdd EVP_DigestInit(&md, evp_md); 17479607Sdd EVP_DigestUpdate(&md, data, datalen); 175180922Sobrien EVP_DigestFinal(&md, digest, &dlen); 176180922Sobrien 177180922Sobrien ret = DSA_do_verify(digest, dlen, sig, key->dsa); 178180922Sobrien memset(digest, 'd', sizeof(digest)); 179180922Sobrien 1801553Srgrimes DSA_SIG_free(sig); 1811553Srgrimes 1821553Srgrimes debug("ssh_dss_verify: signature %s", 1831553Srgrimes ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); 1841553Srgrimes return ret; 1851553Srgrimes} 1861553Srgrimes