1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright (c) 2000 Markus Friedl. All rights reserved. 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 5*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 6*0Sstevel@tonic-gate * are met: 7*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 8*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 9*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 10*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 11*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23*0Sstevel@tonic-gate */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate #include "includes.h" 26*0Sstevel@tonic-gate RCSID("$OpenBSD: ssh-dss.c,v 1.17 2002/07/04 10:41:47 markus Exp $"); 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <openssl/bn.h> 31*0Sstevel@tonic-gate #include <openssl/evp.h> 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include "xmalloc.h" 34*0Sstevel@tonic-gate #include "buffer.h" 35*0Sstevel@tonic-gate #include "bufaux.h" 36*0Sstevel@tonic-gate #include "compat.h" 37*0Sstevel@tonic-gate #include "log.h" 38*0Sstevel@tonic-gate #include "key.h" 39*0Sstevel@tonic-gate #include "ssh-dss.h" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #define INTBLOB_LEN 20 42*0Sstevel@tonic-gate #define SIGBLOB_LEN (2*INTBLOB_LEN) 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate int 45*0Sstevel@tonic-gate ssh_dss_sign(Key *key, u_char **sigp, u_int *lenp, 46*0Sstevel@tonic-gate u_char *data, u_int datalen) 47*0Sstevel@tonic-gate { 48*0Sstevel@tonic-gate DSA_SIG *sig; 49*0Sstevel@tonic-gate const EVP_MD *evp_md = EVP_sha1(); 50*0Sstevel@tonic-gate EVP_MD_CTX md; 51*0Sstevel@tonic-gate u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; 52*0Sstevel@tonic-gate u_int rlen, slen, len, dlen; 53*0Sstevel@tonic-gate Buffer b; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 56*0Sstevel@tonic-gate error("ssh_dss_sign: no DSA key"); 57*0Sstevel@tonic-gate return -1; 58*0Sstevel@tonic-gate } 59*0Sstevel@tonic-gate EVP_DigestInit(&md, evp_md); 60*0Sstevel@tonic-gate EVP_DigestUpdate(&md, data, datalen); 61*0Sstevel@tonic-gate EVP_DigestFinal(&md, digest, &dlen); 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate sig = DSA_do_sign(digest, dlen, key->dsa); 64*0Sstevel@tonic-gate memset(digest, 'd', sizeof(digest)); 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate if (sig == NULL) { 67*0Sstevel@tonic-gate error("ssh_dss_sign: sign failed"); 68*0Sstevel@tonic-gate return -1; 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate rlen = BN_num_bytes(sig->r); 72*0Sstevel@tonic-gate slen = BN_num_bytes(sig->s); 73*0Sstevel@tonic-gate if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 74*0Sstevel@tonic-gate error("bad sig size %u %u", rlen, slen); 75*0Sstevel@tonic-gate DSA_SIG_free(sig); 76*0Sstevel@tonic-gate return -1; 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate memset(sigblob, 0, SIGBLOB_LEN); 79*0Sstevel@tonic-gate BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 80*0Sstevel@tonic-gate BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); 81*0Sstevel@tonic-gate DSA_SIG_free(sig); 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate if (datafellows & SSH_BUG_SIGBLOB) { 84*0Sstevel@tonic-gate if (lenp != NULL) 85*0Sstevel@tonic-gate *lenp = SIGBLOB_LEN; 86*0Sstevel@tonic-gate if (sigp != NULL) { 87*0Sstevel@tonic-gate *sigp = xmalloc(SIGBLOB_LEN); 88*0Sstevel@tonic-gate memcpy(*sigp, sigblob, SIGBLOB_LEN); 89*0Sstevel@tonic-gate } 90*0Sstevel@tonic-gate } else { 91*0Sstevel@tonic-gate /* ietf-drafts */ 92*0Sstevel@tonic-gate buffer_init(&b); 93*0Sstevel@tonic-gate buffer_put_cstring(&b, "ssh-dss"); 94*0Sstevel@tonic-gate buffer_put_string(&b, sigblob, SIGBLOB_LEN); 95*0Sstevel@tonic-gate len = buffer_len(&b); 96*0Sstevel@tonic-gate if (lenp != NULL) 97*0Sstevel@tonic-gate *lenp = len; 98*0Sstevel@tonic-gate if (sigp != NULL) { 99*0Sstevel@tonic-gate *sigp = xmalloc(len); 100*0Sstevel@tonic-gate memcpy(*sigp, buffer_ptr(&b), len); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate buffer_free(&b); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate return 0; 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate int 107*0Sstevel@tonic-gate ssh_dss_verify(Key *key, u_char *signature, u_int signaturelen, 108*0Sstevel@tonic-gate u_char *data, u_int datalen) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate DSA_SIG *sig; 111*0Sstevel@tonic-gate const EVP_MD *evp_md = EVP_sha1(); 112*0Sstevel@tonic-gate EVP_MD_CTX md; 113*0Sstevel@tonic-gate u_char digest[EVP_MAX_MD_SIZE], *sigblob; 114*0Sstevel@tonic-gate u_int len, dlen; 115*0Sstevel@tonic-gate int rlen, ret; 116*0Sstevel@tonic-gate Buffer b; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { 119*0Sstevel@tonic-gate error("ssh_dss_verify: no DSA key"); 120*0Sstevel@tonic-gate return -1; 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate /* fetch signature */ 124*0Sstevel@tonic-gate if (datafellows & SSH_BUG_SIGBLOB) { 125*0Sstevel@tonic-gate sigblob = signature; 126*0Sstevel@tonic-gate len = signaturelen; 127*0Sstevel@tonic-gate } else { 128*0Sstevel@tonic-gate /* ietf-drafts */ 129*0Sstevel@tonic-gate char *ktype; 130*0Sstevel@tonic-gate buffer_init(&b); 131*0Sstevel@tonic-gate buffer_append(&b, signature, signaturelen); 132*0Sstevel@tonic-gate ktype = buffer_get_string(&b, NULL); 133*0Sstevel@tonic-gate if (strcmp("ssh-dss", ktype) != 0) { 134*0Sstevel@tonic-gate error("ssh_dss_verify: cannot handle type %s", ktype); 135*0Sstevel@tonic-gate buffer_free(&b); 136*0Sstevel@tonic-gate xfree(ktype); 137*0Sstevel@tonic-gate return -1; 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate xfree(ktype); 140*0Sstevel@tonic-gate sigblob = buffer_get_string(&b, &len); 141*0Sstevel@tonic-gate rlen = buffer_len(&b); 142*0Sstevel@tonic-gate buffer_free(&b); 143*0Sstevel@tonic-gate if (rlen != 0) { 144*0Sstevel@tonic-gate error("ssh_dss_verify: " 145*0Sstevel@tonic-gate "remaining bytes in signature %d", rlen); 146*0Sstevel@tonic-gate xfree(sigblob); 147*0Sstevel@tonic-gate return -1; 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (len != SIGBLOB_LEN) { 152*0Sstevel@tonic-gate fatal("bad sigbloblen %u != SIGBLOB_LEN", len); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* parse signature */ 156*0Sstevel@tonic-gate if ((sig = DSA_SIG_new()) == NULL) 157*0Sstevel@tonic-gate fatal("ssh_dss_verify: DSA_SIG_new failed"); 158*0Sstevel@tonic-gate if ((sig->r = BN_new()) == NULL) 159*0Sstevel@tonic-gate fatal("ssh_dss_verify: BN_new failed"); 160*0Sstevel@tonic-gate if ((sig->s = BN_new()) == NULL) 161*0Sstevel@tonic-gate fatal("ssh_dss_verify: BN_new failed"); 162*0Sstevel@tonic-gate BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); 163*0Sstevel@tonic-gate BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate if (!(datafellows & SSH_BUG_SIGBLOB)) { 166*0Sstevel@tonic-gate memset(sigblob, 0, len); 167*0Sstevel@tonic-gate xfree(sigblob); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* sha1 the data */ 171*0Sstevel@tonic-gate EVP_DigestInit(&md, evp_md); 172*0Sstevel@tonic-gate EVP_DigestUpdate(&md, data, datalen); 173*0Sstevel@tonic-gate EVP_DigestFinal(&md, digest, &dlen); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate ret = DSA_do_verify(digest, dlen, sig, key->dsa); 176*0Sstevel@tonic-gate memset(digest, 'd', sizeof(digest)); 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate DSA_SIG_free(sig); 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate debug("ssh_dss_verify: signature %s", 181*0Sstevel@tonic-gate ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); 182*0Sstevel@tonic-gate return ret; 183*0Sstevel@tonic-gate } 184