[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.2

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"
1.2     ! markus     36: #include <openssl/rsa.h>
        !            37: #include <openssl/dsa.h>
        !            38: #include <openssl/evp.h>
1.1       markus     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: }