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