[BACK]Return to key.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/key.c, Revision 1.1

1.1     ! markus      1: /*
        !             2:  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
        !             3:  *
        !             4:  * Redistribution and use in source and binary forms, with or without
        !             5:  * modification, are permitted provided that the following conditions
        !             6:  * are met:
        !             7:  * 1. Redistributions of source code must retain the above copyright
        !             8:  *    notice, this list of conditions and the following disclaimer.
        !             9:  * 2. Redistributions in binary form must reproduce the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer in the
        !            11:  *    documentation and/or other materials provided with the distribution.
        !            12:  * 3. All advertising materials mentioning features or use of this software
        !            13:  *    must display the following acknowledgement:
        !            14:  *      This product includes software developed by Markus Friedl.
        !            15:  * 4. The name of the author may not be used to endorse or promote products
        !            16:  *    derived from this software without specific prior written permission.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            27:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            28:  */
        !            29: /*
        !            30:  * read_bignum():
        !            31:  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
        !            32:  */
        !            33:
        !            34: #include "includes.h"
        !            35: #include "ssh.h"
        !            36: #include <ssl/rsa.h>
        !            37: #include <ssl/dsa.h>
        !            38: #include <ssl/evp.h>
        !            39: #include "xmalloc.h"
        !            40: #include "key.h"
        !            41:
        !            42: Key *
        !            43: key_new(int type)
        !            44: {
        !            45:        Key *k;
        !            46:        RSA *rsa;
        !            47:        DSA *dsa;
        !            48:        k = xmalloc(sizeof(*k));
        !            49:        k->type = type;
        !            50:        switch (k->type) {
        !            51:        case KEY_RSA:
        !            52:                rsa = RSA_new();
        !            53:                rsa->n = BN_new();
        !            54:                rsa->e = BN_new();
        !            55:                k->rsa = rsa;
        !            56:                break;
        !            57:        case KEY_DSA:
        !            58:                dsa = DSA_new();
        !            59:                dsa->p = BN_new();
        !            60:                dsa->q = BN_new();
        !            61:                dsa->g = BN_new();
        !            62:                dsa->pub_key = BN_new();
        !            63:                k->dsa = dsa;
        !            64:                break;
        !            65:        case KEY_EMPTY:
        !            66:                k->dsa = NULL;
        !            67:                k->rsa = NULL;
        !            68:                break;
        !            69:        default:
        !            70:                fatal("key_new: bad key type %d", k->type);
        !            71:                break;
        !            72:        }
        !            73:        return k;
        !            74: }
        !            75: void
        !            76: key_free(Key *k)
        !            77: {
        !            78:        switch (k->type) {
        !            79:        case KEY_RSA:
        !            80:                if (k->rsa != NULL)
        !            81:                        RSA_free(k->rsa);
        !            82:                k->rsa = NULL;
        !            83:                break;
        !            84:        case KEY_DSA:
        !            85:                if (k->dsa != NULL)
        !            86:                        DSA_free(k->dsa);
        !            87:                k->dsa = NULL;
        !            88:                break;
        !            89:        default:
        !            90:                fatal("key_free: bad key type %d", k->type);
        !            91:                break;
        !            92:        }
        !            93:        xfree(k);
        !            94: }
        !            95: int
        !            96: key_equal(Key *a, Key *b)
        !            97: {
        !            98:        if (a == NULL || b == NULL || a->type != b->type)
        !            99:                return 0;
        !           100:        switch (a->type) {
        !           101:        case KEY_RSA:
        !           102:                return a->rsa != NULL && b->rsa != NULL &&
        !           103:                    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
        !           104:                    BN_cmp(a->rsa->n, b->rsa->n) == 0;
        !           105:                break;
        !           106:        case KEY_DSA:
        !           107:                return a->dsa != NULL && b->dsa != NULL &&
        !           108:                    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
        !           109:                    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
        !           110:                    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
        !           111:                    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
        !           112:                break;
        !           113:        default:
        !           114:                fatal("key_free: bad key type %d", a->type);
        !           115:                break;
        !           116:        }
        !           117:        return 0;
        !           118: }
        !           119:
        !           120: #define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
        !           121:
        !           122: /*
        !           123:  * Generate key fingerprint in ascii format.
        !           124:  * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
        !           125:  */
        !           126: char *
        !           127: key_fingerprint(Key *k)
        !           128: {
        !           129:        static char retval[80];
        !           130:        unsigned char *buf = NULL;
        !           131:        int len = 0;
        !           132:        int nlen, elen, plen, qlen, glen, publen;
        !           133:
        !           134:        switch (k->type) {
        !           135:        case KEY_RSA:
        !           136:                nlen = BN_num_bytes(k->rsa->n);
        !           137:                elen = BN_num_bytes(k->rsa->e);
        !           138:                len = nlen + elen;
        !           139:                buf = xmalloc(len);
        !           140:                BN_bn2bin(k->rsa->n, buf);
        !           141:                BN_bn2bin(k->rsa->e, buf + nlen);
        !           142:                break;
        !           143:        case KEY_DSA:
        !           144:                plen = BN_num_bytes(k->dsa->p);
        !           145:                qlen = BN_num_bytes(k->dsa->q);
        !           146:                glen = BN_num_bytes(k->dsa->g);
        !           147:                publen = BN_num_bytes(k->dsa->pub_key);
        !           148:                len = qlen + qlen + glen + publen;
        !           149:                buf = xmalloc(len);
        !           150:                BN_bn2bin(k->dsa->p, buf);
        !           151:                BN_bn2bin(k->dsa->q, buf + plen);
        !           152:                BN_bn2bin(k->dsa->g, buf + plen + qlen);
        !           153:                BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen);
        !           154:                break;
        !           155:        default:
        !           156:                fatal("key_fingerprint: bad key type %d", k->type);
        !           157:                break;
        !           158:        }
        !           159:        if (buf != NULL) {
        !           160:                unsigned char d[16];
        !           161:                EVP_MD_CTX md;
        !           162:                EVP_DigestInit(&md, EVP_md5());
        !           163:                EVP_DigestUpdate(&md, buf, len);
        !           164:                EVP_DigestFinal(&md, d, NULL);
        !           165:                snprintf(retval, sizeof(retval), FPRINT,
        !           166:                    d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
        !           167:                    d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
        !           168:                memset(buf, 0, len);
        !           169:                xfree(buf);
        !           170:        }
        !           171:        return retval;
        !           172: }
        !           173:
        !           174: /*
        !           175:  * Reads a multiple-precision integer in decimal from the buffer, and advances
        !           176:  * the pointer.  The integer must already be initialized.  This function is
        !           177:  * permitted to modify the buffer.  This leaves *cpp to point just beyond the
        !           178:  * last processed (and maybe modified) character.  Note that this may modify
        !           179:  * the buffer containing the number.
        !           180:  */
        !           181: int
        !           182: read_bignum(char **cpp, BIGNUM * value)
        !           183: {
        !           184:        char *cp = *cpp;
        !           185:        int old;
        !           186:
        !           187:        /* Skip any leading whitespace. */
        !           188:        for (; *cp == ' ' || *cp == '\t'; cp++)
        !           189:                ;
        !           190:
        !           191:        /* Check that it begins with a decimal digit. */
        !           192:        if (*cp < '0' || *cp > '9')
        !           193:                return 0;
        !           194:
        !           195:        /* Save starting position. */
        !           196:        *cpp = cp;
        !           197:
        !           198:        /* Move forward until all decimal digits skipped. */
        !           199:        for (; *cp >= '0' && *cp <= '9'; cp++)
        !           200:                ;
        !           201:
        !           202:        /* Save the old terminating character, and replace it by \0. */
        !           203:        old = *cp;
        !           204:        *cp = 0;
        !           205:
        !           206:        /* Parse the number. */
        !           207:        if (BN_dec2bn(&value, *cpp) == 0)
        !           208:                return 0;
        !           209:
        !           210:        /* Restore old terminating character. */
        !           211:        *cp = old;
        !           212:
        !           213:        /* Move beyond the number and return success. */
        !           214:        *cpp = cp;
        !           215:        return 1;
        !           216: }
        !           217: int
        !           218: write_bignum(FILE *f, BIGNUM *num)
        !           219: {
        !           220:        char *buf = BN_bn2dec(num);
        !           221:        if (buf == NULL) {
        !           222:                error("write_bignum: BN_bn2dec() failed");
        !           223:                return 0;
        !           224:        }
        !           225:        fprintf(f, " %s", buf);
        !           226:        free(buf);
        !           227:        return 1;
        !           228: }
        !           229: int
        !           230: key_read(Key *ret, unsigned int bits, char **cpp)
        !           231: {
        !           232:        switch(ret->type) {
        !           233:        case KEY_RSA:
        !           234:                if (bits == 0)
        !           235:                        return 0;
        !           236:                /* Get public exponent, public modulus. */
        !           237:                if (!read_bignum(cpp, ret->rsa->e))
        !           238:                        return 0;
        !           239:                if (!read_bignum(cpp, ret->rsa->n))
        !           240:                        return 0;
        !           241:                break;
        !           242:        case KEY_DSA:
        !           243:                if (bits != 0)
        !           244:                        return 0;
        !           245:                if (!read_bignum(cpp, ret->dsa->p))
        !           246:                        return 0;
        !           247:                if (!read_bignum(cpp, ret->dsa->q))
        !           248:                        return 0;
        !           249:                if (!read_bignum(cpp, ret->dsa->g))
        !           250:                        return 0;
        !           251:                if (!read_bignum(cpp, ret->dsa->pub_key))
        !           252:                        return 0;
        !           253:                break;
        !           254:        default:
        !           255:                fatal("bad key type: %d", ret->type);
        !           256:                break;
        !           257:        }
        !           258:        return 1;
        !           259: }
        !           260: int
        !           261: key_write(Key *key, FILE *f)
        !           262: {
        !           263:        int success = 0;
        !           264:        unsigned int bits = 0;
        !           265:
        !           266:        if (key->type == KEY_RSA && key->rsa != NULL) {
        !           267:                /* size of modulus 'n' */
        !           268:                bits = BN_num_bits(key->rsa->n);
        !           269:                fprintf(f, "%u", bits);
        !           270:                if (write_bignum(f, key->rsa->e) &&
        !           271:                    write_bignum(f, key->rsa->n)) {
        !           272:                        success = 1;
        !           273:                } else {
        !           274:                        error("key_write: failed for RSA key");
        !           275:                }
        !           276:        } else if (key->type == KEY_DSA && key->dsa != NULL) {
        !           277:                /* bits == 0 means DSA key */
        !           278:                bits = 0;
        !           279:                fprintf(f, "%u", bits);
        !           280:                if (write_bignum(f, key->dsa->p) &&
        !           281:                    write_bignum(f, key->dsa->q) &&
        !           282:                    write_bignum(f, key->dsa->g) &&
        !           283:                    write_bignum(f, key->dsa->pub_key)) {
        !           284:                        success = 1;
        !           285:                } else {
        !           286:                        error("key_write: failed for DSA key");
        !           287:                }
        !           288:        }
        !           289:        return success;
        !           290: }