X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/b35eb612b5b72c87b8e5cb93be18d7331db859e2..a96070d4a78780ec40d58924df12a934dd7768ed:/key.c diff --git a/key.c b/key.c index 27910ff0..2000c275 100644 --- a/key.c +++ b/key.c @@ -9,7 +9,7 @@ * called by a name other than "ssh" or "Secure Shell". * * - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +32,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.17 2001/02/04 15:32:24 stevesk Exp $"); +RCSID("$OpenBSD: key.c,v 1.28 2001/06/25 08:25:37 markus Exp $"); #include @@ -153,19 +153,29 @@ key_equal(Key *a, Key *b) return 0; } -/* - * Generate key fingerprint in ascii format. - * Based on ideas and code from Bjoern Groenvall - */ -char * -key_fingerprint(Key *k) +static u_char* +key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) { - static char retval[(EVP_MAX_MD_SIZE+1)*3]; + EVP_MD *md = NULL; + EVP_MD_CTX ctx; u_char *blob = NULL; + u_char *retval = NULL; int len = 0; int nlen, elen; - retval[0] = '\0'; + *dgst_raw_length = 0; + + switch (dgst_type) { + case SSH_FP_MD5: + md = EVP_md5(); + break; + case SSH_FP_SHA1: + md = EVP_sha1(); + break; + default: + fatal("key_fingerprint_raw: bad digest type %d", + dgst_type); + } switch (k->type) { case KEY_RSA1: nlen = BN_num_bytes(k->rsa->n); @@ -183,26 +193,111 @@ key_fingerprint(Key *k) return retval; break; default: - fatal("key_fingerprint: bad key type %d", k->type); + fatal("key_fingerprint_raw: bad key type %d", k->type); break; } if (blob != NULL) { - int i; - u_char digest[EVP_MAX_MD_SIZE]; - EVP_MD *md = EVP_md5(); - EVP_MD_CTX ctx; + retval = xmalloc(EVP_MAX_MD_SIZE); EVP_DigestInit(&ctx, md); EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, digest, NULL); - for(i = 0; i < md->md_size; i++) { - char hex[4]; - snprintf(hex, sizeof(hex), "%02x:", digest[i]); - strlcat(retval, hex, sizeof(retval)); - } - retval[strlen(retval) - 1] = '\0'; + EVP_DigestFinal(&ctx, retval, NULL); + *dgst_raw_length = md->md_size; memset(blob, 0, len); xfree(blob); + } else { + fatal("key_fingerprint_raw: blob is null"); + } + return retval; +} + +static char* +key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) +{ + char *retval; + int i; + + retval = xmalloc(dgst_raw_len * 3 + 1); + retval[0] = '\0'; + for(i = 0; i < dgst_raw_len; i++) { + char hex[4]; + snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); + strlcat(retval, hex, dgst_raw_len * 3); } + retval[(dgst_raw_len * 3) - 1] = '\0'; + return retval; +} + +static char* +key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len) +{ + char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; + char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', + 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; + u_int i, j = 0, rounds, seed = 1; + char *retval; + + rounds = (dgst_raw_len / 2) + 1; + retval = xmalloc(sizeof(char) * (rounds*6)); + retval[j++] = 'x'; + for (i = 0; i < rounds; i++) { + u_int idx0, idx1, idx2, idx3, idx4; + if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { + idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + + seed) % 6; + idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; + idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + + (seed / 6)) % 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + if ((i + 1) < rounds) { + idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; + idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; + retval[j++] = consonants[idx3]; + retval[j++] = '-'; + retval[j++] = consonants[idx4]; + seed = ((seed * 5) + + ((((u_int)(dgst_raw[2 * i])) * 7) + + ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; + } + } else { + idx0 = seed % 6; + idx1 = 16; + idx2 = seed / 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + } + } + retval[j++] = 'x'; + retval[j++] = '\0'; + return retval; +} + +char* +key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) +{ + char *retval = NULL; + u_char *dgst_raw; + size_t dgst_raw_len; + + dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); + if (!dgst_raw) + fatal("key_fingerprint: null from key_fingerprint_raw()"); + switch(dgst_rep) { + case SSH_FP_HEX: + retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); + break; + case SSH_FP_BUBBLEBABBLE: + retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); + break; + default: + fatal("key_fingerprint_ex: bad digest representation %d", + dgst_rep); + break; + } + memset(dgst_raw, 0, dgst_raw_len); + xfree(dgst_raw); return retval; } @@ -213,7 +308,7 @@ key_fingerprint(Key *k) * last processed (and maybe modified) character. Note that this may modify * the buffer containing the number. */ -int +static int read_bignum(char **cpp, BIGNUM * value) { char *cp = *cpp; @@ -249,7 +344,7 @@ read_bignum(char **cpp, BIGNUM * value) *cpp = cp; return 1; } -int +static int write_bignum(FILE *f, BIGNUM *num) { char *buf = BN_bn2dec(num); @@ -449,7 +544,7 @@ key_size(Key *k){ return 0; } -RSA * +static RSA * rsa_generate_private_key(u_int bits) { RSA *private; @@ -459,7 +554,7 @@ rsa_generate_private_key(u_int bits) return private; } -DSA* +static DSA* dsa_generate_private_key(u_int bits) { DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); @@ -530,10 +625,32 @@ key_type_from_name(char *name) } else if (strcmp(name, "ssh-dss") == 0){ return KEY_DSA; } - debug("key_type_from_name: unknown key type '%s'", name); + debug2("key_type_from_name: unknown key type '%s'", name); return KEY_UNSPEC; } +int +key_names_valid2(const char *names) +{ + char *s, *cp, *p; + + if (names == NULL || strcmp(names, "") == 0) + return 0; + s = cp = xstrdup(names); + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + switch (key_type_from_name(p)) { + case KEY_RSA1: + case KEY_UNSPEC: + xfree(s); + return 0; + } + } + debug3("key names ok: [%s]", names); + xfree(s); + return 1; +} + Key * key_from_blob(char *blob, int blen) { @@ -651,6 +768,9 @@ key_verify( u_char *signature, int signaturelen, u_char *data, int datalen) { + if (signaturelen == 0) + return -1; + switch(key->type){ case KEY_DSA: return ssh_dss_verify(key, signature, signaturelen, data, datalen);