diff options
author | 2000-11-12 19:50:37 +0000 | |
---|---|---|
committer | 2000-11-12 19:50:37 +0000 | |
commit | 34713819b5dc9d8159a1bb9c8a84be3b251d101b (patch) | |
tree | 622ede4c7997c9ffa8a38ae41ae74bd17e74be64 /usr.bin/ssh/key.c | |
parent | Fix XFree86/console mouse transparency for serial mice. Tested with both a (diff) | |
download | wireguard-openbsd-34713819b5dc9d8159a1bb9c8a84be3b251d101b.tar.xz wireguard-openbsd-34713819b5dc9d8159a1bb9c8a84be3b251d101b.zip |
add support for RSA to SSH2. please test.
there are now 3 types of keys: RSA1 is used by ssh-1 only,
RSA and DSA are used by SSH2.
you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA
keys for SSH2 and use the RSA keys for hostkeys or for user keys.
SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before.
IdentityFile2, HostDsaKey and DSAAuthentication are obsolete.
you can use multiple IdentityFile and HostKey for all types of keys.
the option DSAAuthentication is replaced by PubkeyAuthetication.
Diffstat (limited to 'usr.bin/ssh/key.c')
-rw-r--r-- | usr.bin/ssh/key.c | 388 |
1 files changed, 353 insertions, 35 deletions
diff --git a/usr.bin/ssh/key.c b/usr.bin/ssh/key.c index f7df0bb1db4..a6b25b7ae83 100644 --- a/usr.bin/ssh/key.c +++ b/usr.bin/ssh/key.c @@ -39,12 +39,14 @@ #include <openssl/evp.h> #include "xmalloc.h" #include "key.h" -#include "dsa.h" +#include "rsa.h" +#include "ssh-dss.h" +#include "ssh-rsa.h" #include "uuencode.h" +#include "buffer.h" +#include "bufaux.h" -RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $"); - -#define SSH_DSS "ssh-dss" +RCSID("$OpenBSD: key.c,v 1.12 2000/11/12 19:50:37 markus Exp $"); Key * key_new(int type) @@ -57,6 +59,7 @@ key_new(int type) k->dsa = NULL; k->rsa = NULL; switch (k->type) { + case KEY_RSA1: case KEY_RSA: rsa = RSA_new(); rsa->n = BN_new(); @@ -71,7 +74,7 @@ key_new(int type) dsa->pub_key = BN_new(); k->dsa = dsa; break; - case KEY_EMPTY: + case KEY_UNSPEC: break; default: fatal("key_new: bad key type %d", k->type); @@ -79,10 +82,35 @@ key_new(int type) } return k; } +Key * +key_new_private(int type) +{ + Key *k = key_new(type); + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + k->rsa->d = BN_new(); + k->rsa->iqmp = BN_new(); + k->rsa->q = BN_new(); + k->rsa->p = BN_new(); + k->rsa->dmq1 = BN_new(); + k->rsa->dmp1 = BN_new(); + break; + case KEY_DSA: + k->dsa->priv_key = BN_new(); + break; + case KEY_UNSPEC: + break; + default: + break; + } + return k; +} void key_free(Key *k) { switch (k->type) { + case KEY_RSA1: case KEY_RSA: if (k->rsa != NULL) RSA_free(k->rsa); @@ -93,6 +121,8 @@ key_free(Key *k) DSA_free(k->dsa); k->dsa = NULL; break; + case KEY_UNSPEC: + break; default: fatal("key_free: bad key type %d", k->type); break; @@ -105,6 +135,7 @@ key_equal(Key *a, Key *b) if (a == NULL || b == NULL || a->type != b->type) return 0; switch (a->type) { + case KEY_RSA1: case KEY_RSA: return a->rsa != NULL && b->rsa != NULL && BN_cmp(a->rsa->e, b->rsa->e) == 0 && @@ -136,8 +167,9 @@ key_fingerprint(Key *k) int len = 0; int nlen, elen; + retval[0] = '\0'; switch (k->type) { - case KEY_RSA: + case KEY_RSA1: nlen = BN_num_bytes(k->rsa->n); elen = BN_num_bytes(k->rsa->e); len = nlen + elen; @@ -146,14 +178,16 @@ key_fingerprint(Key *k) BN_bn2bin(k->rsa->e, blob + nlen); break; case KEY_DSA: - dsa_make_key_blob(k, &blob, &len); + case KEY_RSA: + key_to_blob(k, &blob, &len); + break; + case KEY_UNSPEC: + return retval; break; default: fatal("key_fingerprint: bad key type %d", k->type); break; } - retval[0] = '\0'; - if (blob != NULL) { int i; unsigned char digest[EVP_MAX_MD_SIZE]; @@ -229,56 +263,106 @@ write_bignum(FILE *f, BIGNUM *num) free(buf); return 1; } -unsigned int + +/* returns 1 ok, -1 error, 0 type mismatch */ +int key_read(Key *ret, char **cpp) { Key *k; - unsigned int bits = 0; - char *cp; - int len, n; + int success = -1; + char *cp, *space; + int len, n, type; + u_int bits; unsigned char *blob; cp = *cpp; switch(ret->type) { - case KEY_RSA: + case KEY_RSA1: /* Get number of bits. */ if (*cp < '0' || *cp > '9') - return 0; /* Bad bit count... */ + return -1; /* Bad bit count... */ for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) bits = 10 * bits + *cp - '0'; if (bits == 0) - return 0; + return -1; *cpp = cp; /* Get public exponent, public modulus. */ if (!read_bignum(cpp, ret->rsa->e)) - return 0; + return -1; if (!read_bignum(cpp, ret->rsa->n)) - return 0; + return -1; + success = 1; break; + case KEY_UNSPEC: + case KEY_RSA: case KEY_DSA: - if (strncmp(cp, SSH_DSS " ", 7) != 0) + space = strchr(cp, ' '); + if (space == NULL) { + debug3("key_read: no space"); + return -1; + } + *space = '\0'; + type = key_type_from_name(cp); + *space = ' '; + if (type == KEY_UNSPEC) { + debug3("key_read: no key found"); + return -1; + } + cp = space+1; + if (*cp == '\0') { + debug3("key_read: short string"); + return -1; + } + if (ret->type == KEY_UNSPEC) { + ret->type = type; + } else if (ret->type != type) { + /* is a key, but different type */ + debug3("key_read: type mismatch"); return 0; - cp += 7; + } len = 2*strlen(cp); blob = xmalloc(len); n = uudecode(cp, blob, len); if (n < 0) { error("key_read: uudecode %s failed", cp); - return 0; + return -1; } - k = dsa_key_from_blob(blob, n); + k = key_from_blob(blob, n); if (k == NULL) { - error("key_read: dsa_key_from_blob %s failed", cp); - return 0; + error("key_read: key_from_blob %s failed", cp); + return -1; } xfree(blob); - if (ret->dsa != NULL) - DSA_free(ret->dsa); - ret->dsa = k->dsa; - k->dsa = NULL; + if (k->type != type) { + error("key_read: type mismatch: encoding error"); + key_free(k); + return -1; + } +/*XXXX*/ + if (ret->type == KEY_RSA) { + if (ret->rsa != NULL) + RSA_free(ret->rsa); + ret->rsa = k->rsa; + k->rsa = NULL; + success = 1; +#ifdef DEBUG_PK + RSA_print_fp(stderr, ret->rsa, 8); +#endif + } else { + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; + success = 1; +#ifdef DEBUG_PK + DSA_print_fp(stderr, ret->dsa, 8); +#endif + } +/*XXXX*/ + if (success != 1) + break; key_free(k); - bits = BN_num_bits(ret->dsa->p); /* advance cp: skip whitespace and data */ while (*cp == ' ' || *cp == '\t') cp++; @@ -290,7 +374,7 @@ key_read(Key *ret, char **cpp) fatal("key_read: bad key type: %d", ret->type); break; } - return bits; + return success; } int key_write(Key *key, FILE *f) @@ -298,7 +382,7 @@ key_write(Key *key, FILE *f) int success = 0; unsigned int bits = 0; - if (key->type == KEY_RSA && key->rsa != NULL) { + if (key->type == KEY_RSA1 && key->rsa != NULL) { /* size of modulus 'n' */ bits = BN_num_bits(key->rsa->n); fprintf(f, "%u", bits); @@ -308,14 +392,15 @@ key_write(Key *key, FILE *f) } else { error("key_write: failed for RSA key"); } - } else if (key->type == KEY_DSA && key->dsa != NULL) { + } else if ((key->type == KEY_DSA && key->dsa != NULL) || + (key->type == KEY_RSA && key->rsa != NULL)) { int len, n; unsigned char *blob, *uu; - dsa_make_key_blob(key, &blob, &len); + key_to_blob(key, &blob, &len); uu = xmalloc(2*len); n = uuencode(blob, len, uu, 2*len); if (n > 0) { - fprintf(f, "%s %s", SSH_DSS, uu); + fprintf(f, "%s %s", key_ssh_name(key), uu); success = 1; } xfree(blob); @@ -327,6 +412,9 @@ char * key_type(Key *k) { switch (k->type) { + case KEY_RSA1: + return "RSA1"; + break; case KEY_RSA: return "RSA"; break; @@ -336,9 +424,23 @@ key_type(Key *k) } return "unknown"; } -unsigned int +char * +key_ssh_name(Key *k) +{ + switch (k->type) { + case KEY_RSA: + return "ssh-rsa"; + break; + case KEY_DSA: + return "ssh-dss"; + break; + } + return "ssh-unknown"; +} +u_int key_size(Key *k){ switch (k->type) { + case KEY_RSA1: case KEY_RSA: return BN_num_bits(k->rsa->n); break; @@ -348,3 +450,219 @@ key_size(Key *k){ } return 0; } + +RSA * +rsa_generate_private_key(unsigned int bits) +{ + RSA *private; + private = RSA_generate_key(bits, 35, NULL, NULL); + if (private == NULL) + fatal("rsa_generate_private_key: key generation failed."); + return private; +} + +DSA* +dsa_generate_private_key(unsigned int bits) +{ + DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); + if (private == NULL) + fatal("dsa_generate_private_key: DSA_generate_parameters failed"); + if (!DSA_generate_key(private)) + fatal("dsa_generate_private_key: DSA_generate_key failed."); + if (private == NULL) + fatal("dsa_generate_private_key: NULL."); + return private; +} + +Key * +key_generate(int type, unsigned int bits) +{ + Key *k = key_new(KEY_UNSPEC); + switch (type) { + case KEY_DSA: + k->dsa = dsa_generate_private_key(bits); + break; + case KEY_RSA: + case KEY_RSA1: + k->rsa = rsa_generate_private_key(bits); + break; + default: + fatal("key_generate: unknown type %d", type); + } + k->type = type; + return k; +} + +Key * +key_from_private(Key *k) +{ + Key *n = NULL; + switch (k->type) { + case KEY_DSA: + n = key_new(k->type); + BN_copy(n->dsa->p, k->dsa->p); + BN_copy(n->dsa->q, k->dsa->q); + BN_copy(n->dsa->g, k->dsa->g); + BN_copy(n->dsa->pub_key, k->dsa->pub_key); + break; + case KEY_RSA: + case KEY_RSA1: + n = key_new(k->type); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + break; + default: + fatal("key_from_private: unknown type %d", k->type); + break; + } + return n; +} + +int +key_type_from_name(char *name) +{ + if (strcmp(name, "rsa1") == 0){ + return KEY_RSA1; + } else if (strcmp(name, "rsa") == 0){ + return KEY_RSA; + } else if (strcmp(name, "dsa") == 0){ + return KEY_DSA; + } else if (strcmp(name, "ssh-rsa") == 0){ + return KEY_RSA; + } else if (strcmp(name, "ssh-dss") == 0){ + return KEY_DSA; + } + debug("key_type_from_name: unknown key type '%s'", name); + return KEY_UNSPEC; +} + +Key * +key_from_blob(char *blob, int blen) +{ + Buffer b; + char *ktype; + int rlen, type; + Key *key = NULL; + +#ifdef DEBUG_PK + dump_base64(stderr, blob, blen); +#endif + buffer_init(&b); + buffer_append(&b, blob, blen); + ktype = buffer_get_string(&b, NULL); + type = key_type_from_name(ktype); + + switch(type){ + case KEY_RSA: + key = key_new(type); + buffer_get_bignum2(&b, key->rsa->n); + buffer_get_bignum2(&b, key->rsa->e); +#ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); +#endif + break; + case KEY_DSA: + key = key_new(type); + buffer_get_bignum2(&b, key->dsa->p); + buffer_get_bignum2(&b, key->dsa->q); + buffer_get_bignum2(&b, key->dsa->g); + buffer_get_bignum2(&b, key->dsa->pub_key); +#ifdef DEBUG_PK + DSA_print_fp(stderr, key->dsa, 8); +#endif + break; + case KEY_UNSPEC: + key = key_new(type); + break; + default: + error("key_from_blob: cannot handle type %s", ktype); + break; + } + rlen = buffer_len(&b); + if (key != NULL && rlen != 0) + error("key_from_blob: remaining bytes in key blob %d", rlen); + xfree(ktype); + buffer_free(&b); + return key; +} + +int +key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp) +{ + Buffer b; + int len; + unsigned char *buf; + + if (key == NULL) { + error("key_to_blob: key == NULL"); + return 0; + } + buffer_init(&b); + switch(key->type){ + case KEY_DSA: + buffer_put_cstring(&b, key_ssh_name(key)); + buffer_put_bignum2(&b, key->dsa->p); + buffer_put_bignum2(&b, key->dsa->q); + buffer_put_bignum2(&b, key->dsa->g); + buffer_put_bignum2(&b, key->dsa->pub_key); + break; + case KEY_RSA: + buffer_put_cstring(&b, key_ssh_name(key)); + buffer_put_bignum2(&b, key->rsa->n); + buffer_put_bignum2(&b, key->rsa->e); + break; + default: + error("key_to_blob: illegal key type %d", key->type); + break; + } + len = buffer_len(&b); + buf = xmalloc(len); + memcpy(buf, buffer_ptr(&b), len); + memset(buffer_ptr(&b), 0, len); + buffer_free(&b); + if (lenp != NULL) + *lenp = len; + if (blobp != NULL) + *blobp = buf; + return len; +} + +int +key_sign( + Key *key, + unsigned char **sigp, int *lenp, + unsigned char *data, int datalen) +{ + switch(key->type){ + case KEY_DSA: + return ssh_dss_sign(key, sigp, lenp, data, datalen); + break; + case KEY_RSA: + return ssh_rsa_sign(key, sigp, lenp, data, datalen); + break; + default: + error("key_sign: illegal key type %d", key->type); + return -1; + break; + } +} + +int +key_verify( + Key *key, + unsigned char *signature, int signaturelen, + unsigned char *data, int datalen) +{ + switch(key->type){ + case KEY_DSA: + return ssh_dss_verify(key, signature, signaturelen, data, datalen); + break; + case KEY_RSA: + return ssh_rsa_verify(key, signature, signaturelen, data, datalen); + break; + default: + error("key_verify: illegal key type %d", key->type); + return -1; + break; + } +} |