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

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