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

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"
1.3       markus     41: #include "dsa.h"
                     42: #include "uuencode.h"
                     43:
                     44: #define SSH_DSS "ssh-dss"
1.1       markus     45:
                     46: Key *
                     47: key_new(int type)
                     48: {
                     49:        Key *k;
                     50:        RSA *rsa;
                     51:        DSA *dsa;
                     52:        k = xmalloc(sizeof(*k));
                     53:        k->type = type;
1.3       markus     54:        k->dsa = NULL;
                     55:        k->rsa = NULL;
1.1       markus     56:        switch (k->type) {
                     57:        case KEY_RSA:
                     58:                rsa = RSA_new();
                     59:                rsa->n = BN_new();
                     60:                rsa->e = BN_new();
                     61:                k->rsa = rsa;
                     62:                break;
                     63:        case KEY_DSA:
                     64:                dsa = DSA_new();
                     65:                dsa->p = BN_new();
                     66:                dsa->q = BN_new();
                     67:                dsa->g = BN_new();
                     68:                dsa->pub_key = BN_new();
                     69:                k->dsa = dsa;
                     70:                break;
                     71:        case KEY_EMPTY:
                     72:                break;
                     73:        default:
                     74:                fatal("key_new: bad key type %d", k->type);
                     75:                break;
                     76:        }
                     77:        return k;
                     78: }
                     79: void
                     80: key_free(Key *k)
                     81: {
                     82:        switch (k->type) {
                     83:        case KEY_RSA:
                     84:                if (k->rsa != NULL)
                     85:                        RSA_free(k->rsa);
                     86:                k->rsa = NULL;
                     87:                break;
                     88:        case KEY_DSA:
                     89:                if (k->dsa != NULL)
                     90:                        DSA_free(k->dsa);
                     91:                k->dsa = NULL;
                     92:                break;
                     93:        default:
                     94:                fatal("key_free: bad key type %d", k->type);
                     95:                break;
                     96:        }
                     97:        xfree(k);
                     98: }
                     99: int
                    100: key_equal(Key *a, Key *b)
                    101: {
                    102:        if (a == NULL || b == NULL || a->type != b->type)
                    103:                return 0;
                    104:        switch (a->type) {
                    105:        case KEY_RSA:
                    106:                return a->rsa != NULL && b->rsa != NULL &&
                    107:                    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
                    108:                    BN_cmp(a->rsa->n, b->rsa->n) == 0;
                    109:                break;
                    110:        case KEY_DSA:
                    111:                return a->dsa != NULL && b->dsa != NULL &&
                    112:                    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
                    113:                    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
                    114:                    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
                    115:                    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
                    116:                break;
                    117:        default:
1.3       markus    118:                fatal("key_equal: bad key type %d", a->type);
1.1       markus    119:                break;
                    120:        }
                    121:        return 0;
                    122: }
                    123:
                    124: #define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
                    125:
                    126: /*
                    127:  * Generate key fingerprint in ascii format.
                    128:  * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
                    129:  */
                    130: char *
                    131: key_fingerprint(Key *k)
                    132: {
                    133:        static char retval[80];
1.3       markus    134:        unsigned char *blob = NULL;
1.1       markus    135:        int len = 0;
1.3       markus    136:        int nlen, elen;
1.1       markus    137:
                    138:        switch (k->type) {
                    139:        case KEY_RSA:
                    140:                nlen = BN_num_bytes(k->rsa->n);
                    141:                elen = BN_num_bytes(k->rsa->e);
                    142:                len = nlen + elen;
1.3       markus    143:                blob = xmalloc(len);
                    144:                BN_bn2bin(k->rsa->n, blob);
                    145:                BN_bn2bin(k->rsa->e, blob + nlen);
1.1       markus    146:                break;
                    147:        case KEY_DSA:
1.3       markus    148:                dsa_make_key_blob(k, &blob, &len);
1.1       markus    149:                break;
                    150:        default:
                    151:                fatal("key_fingerprint: bad key type %d", k->type);
                    152:                break;
                    153:        }
1.3       markus    154:        if (blob != NULL) {
1.1       markus    155:                unsigned char d[16];
                    156:                EVP_MD_CTX md;
                    157:                EVP_DigestInit(&md, EVP_md5());
1.3       markus    158:                EVP_DigestUpdate(&md, blob, len);
1.1       markus    159:                EVP_DigestFinal(&md, d, NULL);
                    160:                snprintf(retval, sizeof(retval), FPRINT,
                    161:                    d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
                    162:                    d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
1.3       markus    163:                memset(blob, 0, len);
                    164:                xfree(blob);
1.1       markus    165:        }
                    166:        return retval;
                    167: }
                    168:
                    169: /*
                    170:  * Reads a multiple-precision integer in decimal from the buffer, and advances
                    171:  * the pointer.  The integer must already be initialized.  This function is
                    172:  * permitted to modify the buffer.  This leaves *cpp to point just beyond the
                    173:  * last processed (and maybe modified) character.  Note that this may modify
                    174:  * the buffer containing the number.
                    175:  */
                    176: int
                    177: read_bignum(char **cpp, BIGNUM * value)
                    178: {
                    179:        char *cp = *cpp;
                    180:        int old;
                    181:
                    182:        /* Skip any leading whitespace. */
                    183:        for (; *cp == ' ' || *cp == '\t'; cp++)
                    184:                ;
                    185:
                    186:        /* Check that it begins with a decimal digit. */
                    187:        if (*cp < '0' || *cp > '9')
                    188:                return 0;
                    189:
                    190:        /* Save starting position. */
                    191:        *cpp = cp;
                    192:
                    193:        /* Move forward until all decimal digits skipped. */
                    194:        for (; *cp >= '0' && *cp <= '9'; cp++)
                    195:                ;
                    196:
                    197:        /* Save the old terminating character, and replace it by \0. */
                    198:        old = *cp;
                    199:        *cp = 0;
                    200:
                    201:        /* Parse the number. */
                    202:        if (BN_dec2bn(&value, *cpp) == 0)
                    203:                return 0;
                    204:
                    205:        /* Restore old terminating character. */
                    206:        *cp = old;
                    207:
                    208:        /* Move beyond the number and return success. */
                    209:        *cpp = cp;
                    210:        return 1;
                    211: }
                    212: int
                    213: write_bignum(FILE *f, BIGNUM *num)
                    214: {
                    215:        char *buf = BN_bn2dec(num);
                    216:        if (buf == NULL) {
                    217:                error("write_bignum: BN_bn2dec() failed");
                    218:                return 0;
                    219:        }
                    220:        fprintf(f, " %s", buf);
                    221:        free(buf);
                    222:        return 1;
                    223: }
1.3       markus    224: unsigned int
                    225: key_read(Key *ret, char **cpp)
1.1       markus    226: {
1.3       markus    227:        Key *k;
                    228:        unsigned int bits = 0;
                    229:        char *cp;
                    230:        int len, n;
                    231:        unsigned char *blob;
                    232:
                    233:        cp = *cpp;
                    234:
1.1       markus    235:        switch(ret->type) {
                    236:        case KEY_RSA:
1.3       markus    237:                /* Get number of bits. */
                    238:                if (*cp < '0' || *cp > '9')
                    239:                        return 0;       /* Bad bit count... */
                    240:                for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
                    241:                        bits = 10 * bits + *cp - '0';
1.1       markus    242:                if (bits == 0)
                    243:                        return 0;
1.3       markus    244:                *cpp = cp;
1.1       markus    245:                /* Get public exponent, public modulus. */
                    246:                if (!read_bignum(cpp, ret->rsa->e))
                    247:                        return 0;
                    248:                if (!read_bignum(cpp, ret->rsa->n))
                    249:                        return 0;
                    250:                break;
                    251:        case KEY_DSA:
1.3       markus    252:                if (strncmp(cp, SSH_DSS " ", 7) != 0)
1.1       markus    253:                        return 0;
1.3       markus    254:                cp += 7;
                    255:                len = 2*strlen(cp);
                    256:                blob = xmalloc(len);
                    257:                n = uudecode(cp, blob, len);
1.6     ! markus    258:                if (n < 0) {
        !           259:                        error("uudecode %s failed", cp);
        !           260:                        return 0;
        !           261:                }
1.3       markus    262:                k = dsa_key_from_blob(blob, n);
                    263:                if (k == NULL)
                    264:                         return 0;
                    265:                xfree(blob);
                    266:                if (ret->dsa != NULL)
                    267:                        DSA_free(ret->dsa);
                    268:                ret->dsa = k->dsa;
                    269:                k->dsa = NULL;
                    270:                key_free(k);
                    271:                bits = BN_num_bits(ret->dsa->p);
                    272:                cp = strchr(cp, '=');
                    273:                if (cp == NULL)
1.1       markus    274:                        return 0;
1.3       markus    275:                *cpp = cp + 1;
1.1       markus    276:                break;
                    277:        default:
1.3       markus    278:                fatal("key_read: bad key type: %d", ret->type);
1.1       markus    279:                break;
                    280:        }
1.3       markus    281:        return bits;
1.1       markus    282: }
                    283: int
                    284: key_write(Key *key, FILE *f)
                    285: {
                    286:        int success = 0;
                    287:        unsigned int bits = 0;
                    288:
                    289:        if (key->type == KEY_RSA && key->rsa != NULL) {
                    290:                /* size of modulus 'n' */
                    291:                bits = BN_num_bits(key->rsa->n);
                    292:                fprintf(f, "%u", bits);
                    293:                if (write_bignum(f, key->rsa->e) &&
                    294:                    write_bignum(f, key->rsa->n)) {
                    295:                        success = 1;
                    296:                } else {
                    297:                        error("key_write: failed for RSA key");
                    298:                }
                    299:        } else if (key->type == KEY_DSA && key->dsa != NULL) {
1.3       markus    300:                int len, n;
                    301:                unsigned char *blob, *uu;
                    302:                dsa_make_key_blob(key, &blob, &len);
                    303:                uu = xmalloc(2*len);
1.5       markus    304:                n = uuencode(blob, len, uu, 2*len);
                    305:                if (n > 0) {
                    306:                        fprintf(f, "%s %s", SSH_DSS, uu);
                    307:                        success = 1;
                    308:                }
1.3       markus    309:                xfree(blob);
                    310:                xfree(uu);
1.1       markus    311:        }
                    312:        return success;
                    313: }
1.4       markus    314: char *
                    315: key_type(Key *k)
                    316: {
                    317:        switch (k->type) {
                    318:        case KEY_RSA:
                    319:                return "RSA";
                    320:                break;
                    321:        case KEY_DSA:
                    322:                return "DSA";
                    323:                break;
                    324:        }
                    325:        return "unknown";
                    326: }