diff options
Diffstat (limited to 'other/ssharp/key.c')
| -rw-r--r-- | other/ssharp/key.c | 783 |
1 files changed, 783 insertions, 0 deletions
diff --git a/other/ssharp/key.c b/other/ssharp/key.c new file mode 100644 index 0000000..3b9f9f7 --- /dev/null +++ b/other/ssharp/key.c | |||
| @@ -0,0 +1,783 @@ | |||
| 1 | /* | ||
| 2 | * read_bignum(): | ||
| 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
| 4 | * | ||
| 5 | * As far as I am concerned, the code I have written for this software | ||
| 6 | * can be used freely for any purpose. Any derived versions of this | ||
| 7 | * software must be clearly marked as such, and if the derived work is | ||
| 8 | * incompatible with the protocol description in the RFC file, it must be | ||
| 9 | * called by a name other than "ssh" or "Secure Shell". | ||
| 10 | * | ||
| 11 | * | ||
| 12 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
| 13 | * | ||
| 14 | * Redistribution and use in source and binary forms, with or without | ||
| 15 | * modification, are permitted provided that the following conditions | ||
| 16 | * are met: | ||
| 17 | * 1. Redistributions of source code must retain the above copyright | ||
| 18 | * notice, this list of conditions and the following disclaimer. | ||
| 19 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in the | ||
| 21 | * documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
| 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
| 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
| 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | #include "includes.h" | ||
| 35 | RCSID("$OpenBSD: key.c,v 1.25 2001/04/17 10:53:24 markus Exp $"); | ||
| 36 | |||
| 37 | #include <openssl/evp.h> | ||
| 38 | |||
| 39 | #include "xmalloc.h" | ||
| 40 | #include "key.h" | ||
| 41 | #include "rsa.h" | ||
| 42 | #include "ssh-dss.h" | ||
| 43 | #include "ssh-rsa.h" | ||
| 44 | #include "uuencode.h" | ||
| 45 | #include "buffer.h" | ||
| 46 | #include "bufaux.h" | ||
| 47 | #include "log.h" | ||
| 48 | |||
| 49 | Key * | ||
| 50 | key_new(int type) | ||
| 51 | { | ||
| 52 | Key *k; | ||
| 53 | RSA *rsa; | ||
| 54 | DSA *dsa; | ||
| 55 | k = xmalloc(sizeof(*k)); | ||
| 56 | k->type = type; | ||
| 57 | k->dsa = NULL; | ||
| 58 | k->rsa = NULL; | ||
| 59 | switch (k->type) { | ||
| 60 | case KEY_RSA1: | ||
| 61 | case KEY_RSA: | ||
| 62 | rsa = RSA_new(); | ||
| 63 | rsa->n = BN_new(); | ||
| 64 | rsa->e = BN_new(); | ||
| 65 | k->rsa = rsa; | ||
| 66 | break; | ||
| 67 | case KEY_DSA: | ||
| 68 | dsa = DSA_new(); | ||
| 69 | dsa->p = BN_new(); | ||
| 70 | dsa->q = BN_new(); | ||
| 71 | dsa->g = BN_new(); | ||
| 72 | dsa->pub_key = BN_new(); | ||
| 73 | k->dsa = dsa; | ||
| 74 | break; | ||
| 75 | case KEY_UNSPEC: | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | fatal("key_new: bad key type %d", k->type); | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | return k; | ||
| 82 | } | ||
| 83 | Key * | ||
| 84 | key_new_private(int type) | ||
| 85 | { | ||
| 86 | Key *k = key_new(type); | ||
| 87 | switch (k->type) { | ||
| 88 | case KEY_RSA1: | ||
| 89 | case KEY_RSA: | ||
| 90 | k->rsa->d = BN_new(); | ||
| 91 | k->rsa->iqmp = BN_new(); | ||
| 92 | k->rsa->q = BN_new(); | ||
| 93 | k->rsa->p = BN_new(); | ||
| 94 | k->rsa->dmq1 = BN_new(); | ||
| 95 | k->rsa->dmp1 = BN_new(); | ||
| 96 | break; | ||
| 97 | case KEY_DSA: | ||
| 98 | k->dsa->priv_key = BN_new(); | ||
| 99 | break; | ||
| 100 | case KEY_UNSPEC: | ||
| 101 | break; | ||
| 102 | default: | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | return k; | ||
| 106 | } | ||
| 107 | void | ||
| 108 | key_free(Key *k) | ||
| 109 | { | ||
| 110 | switch (k->type) { | ||
| 111 | case KEY_RSA1: | ||
| 112 | case KEY_RSA: | ||
| 113 | if (k->rsa != NULL) | ||
| 114 | RSA_free(k->rsa); | ||
| 115 | k->rsa = NULL; | ||
| 116 | break; | ||
| 117 | case KEY_DSA: | ||
| 118 | if (k->dsa != NULL) | ||
| 119 | DSA_free(k->dsa); | ||
| 120 | k->dsa = NULL; | ||
| 121 | break; | ||
| 122 | case KEY_UNSPEC: | ||
| 123 | break; | ||
| 124 | default: | ||
| 125 | fatal("key_free: bad key type %d", k->type); | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | xfree(k); | ||
| 129 | } | ||
| 130 | int | ||
| 131 | key_equal(Key *a, Key *b) | ||
| 132 | { | ||
| 133 | if (a == NULL || b == NULL || a->type != b->type) | ||
| 134 | return 0; | ||
| 135 | switch (a->type) { | ||
| 136 | case KEY_RSA1: | ||
| 137 | case KEY_RSA: | ||
| 138 | return a->rsa != NULL && b->rsa != NULL && | ||
| 139 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | ||
| 140 | BN_cmp(a->rsa->n, b->rsa->n) == 0; | ||
| 141 | break; | ||
| 142 | case KEY_DSA: | ||
| 143 | return a->dsa != NULL && b->dsa != NULL && | ||
| 144 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && | ||
| 145 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && | ||
| 146 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && | ||
| 147 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; | ||
| 148 | break; | ||
| 149 | default: | ||
| 150 | fatal("key_equal: bad key type %d", a->type); | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | u_char* | ||
| 157 | key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) | ||
| 158 | { | ||
| 159 | EVP_MD *md = NULL; | ||
| 160 | EVP_MD_CTX ctx; | ||
| 161 | u_char *blob = NULL; | ||
| 162 | u_char *retval = NULL; | ||
| 163 | int len = 0; | ||
| 164 | int nlen, elen; | ||
| 165 | |||
| 166 | *dgst_raw_length = 0; | ||
| 167 | |||
| 168 | switch (dgst_type) { | ||
| 169 | case SSH_FP_MD5: | ||
| 170 | md = EVP_md5(); | ||
| 171 | break; | ||
| 172 | case SSH_FP_SHA1: | ||
| 173 | md = EVP_sha1(); | ||
| 174 | break; | ||
| 175 | default: | ||
| 176 | fatal("key_fingerprint_raw: bad digest type %d", | ||
| 177 | dgst_type); | ||
| 178 | } | ||
| 179 | switch (k->type) { | ||
| 180 | case KEY_RSA1: | ||
| 181 | nlen = BN_num_bytes(k->rsa->n); | ||
| 182 | elen = BN_num_bytes(k->rsa->e); | ||
| 183 | len = nlen + elen; | ||
| 184 | blob = xmalloc(len); | ||
| 185 | BN_bn2bin(k->rsa->n, blob); | ||
| 186 | BN_bn2bin(k->rsa->e, blob + nlen); | ||
| 187 | break; | ||
| 188 | case KEY_DSA: | ||
| 189 | case KEY_RSA: | ||
| 190 | key_to_blob(k, &blob, &len); | ||
| 191 | break; | ||
| 192 | case KEY_UNSPEC: | ||
| 193 | return retval; | ||
| 194 | break; | ||
| 195 | default: | ||
| 196 | fatal("key_fingerprint_raw: bad key type %d", k->type); | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | if (blob != NULL) { | ||
| 200 | retval = xmalloc(EVP_MAX_MD_SIZE); | ||
| 201 | EVP_DigestInit(&ctx, md); | ||
| 202 | EVP_DigestUpdate(&ctx, blob, len); | ||
| 203 | EVP_DigestFinal(&ctx, retval, NULL); | ||
| 204 | *dgst_raw_length = md->md_size; | ||
| 205 | memset(blob, 0, len); | ||
| 206 | xfree(blob); | ||
| 207 | } else { | ||
| 208 | fatal("key_fingerprint_raw: blob is null"); | ||
| 209 | } | ||
| 210 | return retval; | ||
| 211 | } | ||
| 212 | |||
| 213 | char* | ||
| 214 | key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) | ||
| 215 | { | ||
| 216 | char *retval; | ||
| 217 | int i; | ||
| 218 | |||
| 219 | retval = xmalloc(dgst_raw_len * 3 + 1); | ||
| 220 | retval[0] = '\0'; | ||
| 221 | for(i = 0; i < dgst_raw_len; i++) { | ||
| 222 | char hex[4]; | ||
| 223 | snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); | ||
| 224 | strlcat(retval, hex, dgst_raw_len * 3); | ||
| 225 | } | ||
| 226 | retval[(dgst_raw_len * 3) - 1] = '\0'; | ||
| 227 | return retval; | ||
| 228 | } | ||
| 229 | |||
| 230 | char* | ||
| 231 | key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len) | ||
| 232 | { | ||
| 233 | char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; | ||
| 234 | char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', | ||
| 235 | 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; | ||
| 236 | u_int i, j = 0, rounds, seed = 1; | ||
| 237 | char *retval; | ||
| 238 | |||
| 239 | rounds = (dgst_raw_len / 2) + 1; | ||
| 240 | retval = xmalloc(sizeof(char) * (rounds*6)); | ||
| 241 | retval[j++] = 'x'; | ||
| 242 | for (i = 0; i < rounds; i++) { | ||
| 243 | u_int idx0, idx1, idx2, idx3, idx4; | ||
| 244 | if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { | ||
| 245 | idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + | ||
| 246 | seed) % 6; | ||
| 247 | idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; | ||
| 248 | idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + | ||
| 249 | (seed / 6)) % 6; | ||
| 250 | retval[j++] = vowels[idx0]; | ||
| 251 | retval[j++] = consonants[idx1]; | ||
| 252 | retval[j++] = vowels[idx2]; | ||
| 253 | if ((i + 1) < rounds) { | ||
| 254 | idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; | ||
| 255 | idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; | ||
| 256 | retval[j++] = consonants[idx3]; | ||
| 257 | retval[j++] = '-'; | ||
| 258 | retval[j++] = consonants[idx4]; | ||
| 259 | seed = ((seed * 5) + | ||
| 260 | ((((u_int)(dgst_raw[2 * i])) * 7) + | ||
| 261 | ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; | ||
| 262 | } | ||
| 263 | } else { | ||
| 264 | idx0 = seed % 6; | ||
| 265 | idx1 = 16; | ||
| 266 | idx2 = seed / 6; | ||
| 267 | retval[j++] = vowels[idx0]; | ||
| 268 | retval[j++] = consonants[idx1]; | ||
| 269 | retval[j++] = vowels[idx2]; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | retval[j++] = 'x'; | ||
| 273 | retval[j++] = '\0'; | ||
| 274 | return retval; | ||
| 275 | } | ||
| 276 | |||
| 277 | char* | ||
| 278 | key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | ||
| 279 | { | ||
| 280 | char *retval = NULL; | ||
| 281 | u_char *dgst_raw; | ||
| 282 | size_t dgst_raw_len; | ||
| 283 | |||
| 284 | dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); | ||
| 285 | if (!dgst_raw) | ||
| 286 | fatal("key_fingerprint: null from key_fingerprint_raw()"); | ||
| 287 | switch(dgst_rep) { | ||
| 288 | case SSH_FP_HEX: | ||
| 289 | retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); | ||
| 290 | break; | ||
| 291 | case SSH_FP_BUBBLEBABBLE: | ||
| 292 | retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); | ||
| 293 | break; | ||
| 294 | default: | ||
| 295 | fatal("key_fingerprint_ex: bad digest representation %d", | ||
| 296 | dgst_rep); | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | memset(dgst_raw, 0, dgst_raw_len); | ||
| 300 | xfree(dgst_raw); | ||
| 301 | return retval; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Reads a multiple-precision integer in decimal from the buffer, and advances | ||
| 306 | * the pointer. The integer must already be initialized. This function is | ||
| 307 | * permitted to modify the buffer. This leaves *cpp to point just beyond the | ||
| 308 | * last processed (and maybe modified) character. Note that this may modify | ||
| 309 | * the buffer containing the number. | ||
| 310 | */ | ||
| 311 | int | ||
| 312 | read_bignum(char **cpp, BIGNUM * value) | ||
| 313 | { | ||
| 314 | char *cp = *cpp; | ||
| 315 | int old; | ||
| 316 | |||
| 317 | /* Skip any leading whitespace. */ | ||
| 318 | for (; *cp == ' ' || *cp == '\t'; cp++) | ||
| 319 | ; | ||
| 320 | |||
| 321 | /* Check that it begins with a decimal digit. */ | ||
| 322 | if (*cp < '0' || *cp > '9') | ||
| 323 | return 0; | ||
| 324 | |||
| 325 | /* Save starting position. */ | ||
| 326 | *cpp = cp; | ||
| 327 | |||
| 328 | /* Move forward until all decimal digits skipped. */ | ||
| 329 | for (; *cp >= '0' && *cp <= '9'; cp++) | ||
| 330 | ; | ||
| 331 | |||
| 332 | /* Save the old terminating character, and replace it by \0. */ | ||
| 333 | old = *cp; | ||
| 334 | *cp = 0; | ||
| 335 | |||
| 336 | /* Parse the number. */ | ||
| 337 | if (BN_dec2bn(&value, *cpp) == 0) | ||
| 338 | return 0; | ||
| 339 | |||
| 340 | /* Restore old terminating character. */ | ||
| 341 | *cp = old; | ||
| 342 | |||
| 343 | /* Move beyond the number and return success. */ | ||
| 344 | *cpp = cp; | ||
| 345 | return 1; | ||
| 346 | } | ||
| 347 | int | ||
| 348 | write_bignum(FILE *f, BIGNUM *num) | ||
| 349 | { | ||
| 350 | char *buf = BN_bn2dec(num); | ||
| 351 | if (buf == NULL) { | ||
| 352 | error("write_bignum: BN_bn2dec() failed"); | ||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | fprintf(f, " %s", buf); | ||
| 356 | xfree(buf); | ||
| 357 | return 1; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* returns 1 ok, -1 error, 0 type mismatch */ | ||
| 361 | int | ||
| 362 | key_read(Key *ret, char **cpp) | ||
| 363 | { | ||
| 364 | Key *k; | ||
| 365 | int success = -1; | ||
| 366 | char *cp, *space; | ||
| 367 | int len, n, type; | ||
| 368 | u_int bits; | ||
| 369 | u_char *blob; | ||
| 370 | |||
| 371 | cp = *cpp; | ||
| 372 | |||
| 373 | switch(ret->type) { | ||
| 374 | case KEY_RSA1: | ||
| 375 | /* Get number of bits. */ | ||
| 376 | if (*cp < '0' || *cp > '9') | ||
| 377 | return -1; /* Bad bit count... */ | ||
| 378 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) | ||
| 379 | bits = 10 * bits + *cp - '0'; | ||
| 380 | if (bits == 0) | ||
| 381 | return -1; | ||
| 382 | *cpp = cp; | ||
| 383 | /* Get public exponent, public modulus. */ | ||
| 384 | if (!read_bignum(cpp, ret->rsa->e)) | ||
| 385 | return -1; | ||
| 386 | if (!read_bignum(cpp, ret->rsa->n)) | ||
| 387 | return -1; | ||
| 388 | success = 1; | ||
| 389 | break; | ||
| 390 | case KEY_UNSPEC: | ||
| 391 | case KEY_RSA: | ||
| 392 | case KEY_DSA: | ||
| 393 | space = strchr(cp, ' '); | ||
| 394 | if (space == NULL) { | ||
| 395 | debug3("key_read: no space"); | ||
| 396 | return -1; | ||
| 397 | } | ||
| 398 | *space = '\0'; | ||
| 399 | type = key_type_from_name(cp); | ||
| 400 | *space = ' '; | ||
| 401 | if (type == KEY_UNSPEC) { | ||
| 402 | debug3("key_read: no key found"); | ||
| 403 | return -1; | ||
| 404 | } | ||
| 405 | cp = space+1; | ||
| 406 | if (*cp == '\0') { | ||
| 407 | debug3("key_read: short string"); | ||
| 408 | return -1; | ||
| 409 | } | ||
| 410 | if (ret->type == KEY_UNSPEC) { | ||
| 411 | ret->type = type; | ||
| 412 | } else if (ret->type != type) { | ||
| 413 | /* is a key, but different type */ | ||
| 414 | debug3("key_read: type mismatch"); | ||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | len = 2*strlen(cp); | ||
| 418 | blob = xmalloc(len); | ||
| 419 | n = uudecode(cp, blob, len); | ||
| 420 | if (n < 0) { | ||
| 421 | error("key_read: uudecode %s failed", cp); | ||
| 422 | return -1; | ||
| 423 | } | ||
| 424 | k = key_from_blob(blob, n); | ||
| 425 | if (k == NULL) { | ||
| 426 | error("key_read: key_from_blob %s failed", cp); | ||
| 427 | return -1; | ||
| 428 | } | ||
| 429 | xfree(blob); | ||
| 430 | if (k->type != type) { | ||
| 431 | error("key_read: type mismatch: encoding error"); | ||
| 432 | key_free(k); | ||
| 433 | return -1; | ||
| 434 | } | ||
| 435 | /*XXXX*/ | ||
| 436 | if (ret->type == KEY_RSA) { | ||
| 437 | if (ret->rsa != NULL) | ||
| 438 | RSA_free(ret->rsa); | ||
| 439 | ret->rsa = k->rsa; | ||
| 440 | k->rsa = NULL; | ||
| 441 | success = 1; | ||
| 442 | #ifdef DEBUG_PK | ||
| 443 | RSA_print_fp(stderr, ret->rsa, 8); | ||
| 444 | #endif | ||
| 445 | } else { | ||
| 446 | if (ret->dsa != NULL) | ||
| 447 | DSA_free(ret->dsa); | ||
| 448 | ret->dsa = k->dsa; | ||
| 449 | k->dsa = NULL; | ||
| 450 | success = 1; | ||
| 451 | #ifdef DEBUG_PK | ||
| 452 | DSA_print_fp(stderr, ret->dsa, 8); | ||
| 453 | #endif | ||
| 454 | } | ||
| 455 | /*XXXX*/ | ||
| 456 | if (success != 1) | ||
| 457 | break; | ||
| 458 | key_free(k); | ||
| 459 | /* advance cp: skip whitespace and data */ | ||
| 460 | while (*cp == ' ' || *cp == '\t') | ||
| 461 | cp++; | ||
| 462 | while (*cp != '\0' && *cp != ' ' && *cp != '\t') | ||
| 463 | cp++; | ||
| 464 | *cpp = cp; | ||
| 465 | break; | ||
| 466 | default: | ||
| 467 | fatal("key_read: bad key type: %d", ret->type); | ||
| 468 | break; | ||
| 469 | } | ||
| 470 | return success; | ||
| 471 | } | ||
| 472 | int | ||
| 473 | key_write(Key *key, FILE *f) | ||
| 474 | { | ||
| 475 | int success = 0; | ||
| 476 | u_int bits = 0; | ||
| 477 | |||
| 478 | if (key->type == KEY_RSA1 && key->rsa != NULL) { | ||
| 479 | /* size of modulus 'n' */ | ||
| 480 | bits = BN_num_bits(key->rsa->n); | ||
| 481 | fprintf(f, "%u", bits); | ||
| 482 | if (write_bignum(f, key->rsa->e) && | ||
| 483 | write_bignum(f, key->rsa->n)) { | ||
| 484 | success = 1; | ||
| 485 | } else { | ||
| 486 | error("key_write: failed for RSA key"); | ||
| 487 | } | ||
| 488 | } else if ((key->type == KEY_DSA && key->dsa != NULL) || | ||
| 489 | (key->type == KEY_RSA && key->rsa != NULL)) { | ||
| 490 | int len, n; | ||
| 491 | u_char *blob, *uu; | ||
| 492 | key_to_blob(key, &blob, &len); | ||
| 493 | uu = xmalloc(2*len); | ||
| 494 | n = uuencode(blob, len, uu, 2*len); | ||
| 495 | if (n > 0) { | ||
| 496 | fprintf(f, "%s %s", key_ssh_name(key), uu); | ||
| 497 | success = 1; | ||
| 498 | } | ||
| 499 | xfree(blob); | ||
| 500 | xfree(uu); | ||
| 501 | } | ||
| 502 | return success; | ||
| 503 | } | ||
| 504 | char * | ||
| 505 | key_type(Key *k) | ||
| 506 | { | ||
| 507 | switch (k->type) { | ||
| 508 | case KEY_RSA1: | ||
| 509 | return "RSA1"; | ||
| 510 | break; | ||
| 511 | case KEY_RSA: | ||
| 512 | return "RSA"; | ||
| 513 | break; | ||
| 514 | case KEY_DSA: | ||
| 515 | return "DSA"; | ||
| 516 | break; | ||
| 517 | } | ||
| 518 | return "unknown"; | ||
| 519 | } | ||
| 520 | char * | ||
| 521 | key_ssh_name(Key *k) | ||
| 522 | { | ||
| 523 | switch (k->type) { | ||
| 524 | case KEY_RSA: | ||
| 525 | return "ssh-rsa"; | ||
| 526 | break; | ||
| 527 | case KEY_DSA: | ||
| 528 | return "ssh-dss"; | ||
| 529 | break; | ||
| 530 | } | ||
| 531 | return "ssh-unknown"; | ||
| 532 | } | ||
| 533 | u_int | ||
| 534 | key_size(Key *k){ | ||
| 535 | switch (k->type) { | ||
| 536 | case KEY_RSA1: | ||
| 537 | case KEY_RSA: | ||
| 538 | return BN_num_bits(k->rsa->n); | ||
| 539 | break; | ||
| 540 | case KEY_DSA: | ||
| 541 | return BN_num_bits(k->dsa->p); | ||
| 542 | break; | ||
| 543 | } | ||
| 544 | return 0; | ||
| 545 | } | ||
| 546 | |||
| 547 | RSA * | ||
| 548 | rsa_generate_private_key(u_int bits) | ||
| 549 | { | ||
| 550 | RSA *private; | ||
| 551 | private = RSA_generate_key(bits, 35, NULL, NULL); | ||
| 552 | if (private == NULL) | ||
| 553 | fatal("rsa_generate_private_key: key generation failed."); | ||
| 554 | return private; | ||
| 555 | } | ||
| 556 | |||
| 557 | DSA* | ||
| 558 | dsa_generate_private_key(u_int bits) | ||
| 559 | { | ||
| 560 | DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); | ||
| 561 | if (private == NULL) | ||
| 562 | fatal("dsa_generate_private_key: DSA_generate_parameters failed"); | ||
| 563 | if (!DSA_generate_key(private)) | ||
| 564 | fatal("dsa_generate_private_key: DSA_generate_key failed."); | ||
| 565 | if (private == NULL) | ||
| 566 | fatal("dsa_generate_private_key: NULL."); | ||
| 567 | return private; | ||
| 568 | } | ||
| 569 | |||
| 570 | Key * | ||
| 571 | key_generate(int type, u_int bits) | ||
| 572 | { | ||
| 573 | Key *k = key_new(KEY_UNSPEC); | ||
| 574 | switch (type) { | ||
| 575 | case KEY_DSA: | ||
| 576 | k->dsa = dsa_generate_private_key(bits); | ||
| 577 | break; | ||
| 578 | case KEY_RSA: | ||
| 579 | case KEY_RSA1: | ||
| 580 | k->rsa = rsa_generate_private_key(bits); | ||
| 581 | break; | ||
| 582 | default: | ||
| 583 | fatal("key_generate: unknown type %d", type); | ||
| 584 | } | ||
| 585 | k->type = type; | ||
| 586 | return k; | ||
| 587 | } | ||
| 588 | |||
| 589 | Key * | ||
| 590 | key_from_private(Key *k) | ||
| 591 | { | ||
| 592 | Key *n = NULL; | ||
| 593 | switch (k->type) { | ||
| 594 | case KEY_DSA: | ||
| 595 | n = key_new(k->type); | ||
| 596 | BN_copy(n->dsa->p, k->dsa->p); | ||
| 597 | BN_copy(n->dsa->q, k->dsa->q); | ||
| 598 | BN_copy(n->dsa->g, k->dsa->g); | ||
| 599 | BN_copy(n->dsa->pub_key, k->dsa->pub_key); | ||
| 600 | break; | ||
| 601 | case KEY_RSA: | ||
| 602 | case KEY_RSA1: | ||
| 603 | n = key_new(k->type); | ||
| 604 | BN_copy(n->rsa->n, k->rsa->n); | ||
| 605 | BN_copy(n->rsa->e, k->rsa->e); | ||
| 606 | break; | ||
| 607 | default: | ||
| 608 | fatal("key_from_private: unknown type %d", k->type); | ||
| 609 | break; | ||
| 610 | } | ||
| 611 | return n; | ||
| 612 | } | ||
| 613 | |||
| 614 | int | ||
| 615 | key_type_from_name(char *name) | ||
| 616 | { | ||
| 617 | if (strcmp(name, "rsa1") == 0){ | ||
| 618 | return KEY_RSA1; | ||
| 619 | } else if (strcmp(name, "rsa") == 0){ | ||
| 620 | return KEY_RSA; | ||
| 621 | } else if (strcmp(name, "dsa") == 0){ | ||
| 622 | return KEY_DSA; | ||
| 623 | } else if (strcmp(name, "ssh-rsa") == 0){ | ||
| 624 | return KEY_RSA; | ||
| 625 | } else if (strcmp(name, "ssh-dss") == 0){ | ||
| 626 | return KEY_DSA; | ||
| 627 | } | ||
| 628 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
| 629 | return KEY_UNSPEC; | ||
| 630 | } | ||
| 631 | |||
| 632 | int | ||
| 633 | key_names_valid2(const char *names) | ||
| 634 | { | ||
| 635 | char *s, *cp, *p; | ||
| 636 | |||
| 637 | if (names == NULL || strcmp(names, "") == 0) | ||
| 638 | return 0; | ||
| 639 | s = cp = xstrdup(names); | ||
| 640 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | ||
| 641 | (p = strsep(&cp, ","))) { | ||
| 642 | switch (key_type_from_name(p)) { | ||
| 643 | case KEY_RSA1: | ||
| 644 | case KEY_UNSPEC: | ||
| 645 | xfree(s); | ||
| 646 | return 0; | ||
| 647 | } | ||
| 648 | } | ||
| 649 | debug3("key names ok: [%s]", names); | ||
| 650 | xfree(s); | ||
| 651 | return 1; | ||
| 652 | } | ||
| 653 | |||
| 654 | Key * | ||
| 655 | key_from_blob(char *blob, int blen) | ||
| 656 | { | ||
| 657 | Buffer b; | ||
| 658 | char *ktype; | ||
| 659 | int rlen, type; | ||
| 660 | Key *key = NULL; | ||
| 661 | |||
| 662 | #ifdef DEBUG_PK | ||
| 663 | dump_base64(stderr, blob, blen); | ||
| 664 | #endif | ||
| 665 | buffer_init(&b); | ||
| 666 | buffer_append(&b, blob, blen); | ||
| 667 | ktype = buffer_get_string(&b, NULL); | ||
| 668 | type = key_type_from_name(ktype); | ||
| 669 | |||
| 670 | switch(type){ | ||
| 671 | case KEY_RSA: | ||
| 672 | key = key_new(type); | ||
| 673 | buffer_get_bignum2(&b, key->rsa->e); | ||
| 674 | buffer_get_bignum2(&b, key->rsa->n); | ||
| 675 | #ifdef DEBUG_PK | ||
| 676 | RSA_print_fp(stderr, key->rsa, 8); | ||
| 677 | #endif | ||
| 678 | break; | ||
| 679 | case KEY_DSA: | ||
| 680 | key = key_new(type); | ||
| 681 | buffer_get_bignum2(&b, key->dsa->p); | ||
| 682 | buffer_get_bignum2(&b, key->dsa->q); | ||
| 683 | buffer_get_bignum2(&b, key->dsa->g); | ||
| 684 | buffer_get_bignum2(&b, key->dsa->pub_key); | ||
| 685 | #ifdef DEBUG_PK | ||
| 686 | DSA_print_fp(stderr, key->dsa, 8); | ||
| 687 | #endif | ||
| 688 | break; | ||
| 689 | case KEY_UNSPEC: | ||
| 690 | key = key_new(type); | ||
| 691 | break; | ||
| 692 | default: | ||
| 693 | error("key_from_blob: cannot handle type %s", ktype); | ||
| 694 | break; | ||
| 695 | } | ||
| 696 | rlen = buffer_len(&b); | ||
| 697 | if (key != NULL && rlen != 0) | ||
| 698 | error("key_from_blob: remaining bytes in key blob %d", rlen); | ||
| 699 | xfree(ktype); | ||
| 700 | buffer_free(&b); | ||
| 701 | return key; | ||
| 702 | } | ||
| 703 | |||
| 704 | int | ||
| 705 | key_to_blob(Key *key, u_char **blobp, u_int *lenp) | ||
| 706 | { | ||
| 707 | Buffer b; | ||
| 708 | int len; | ||
| 709 | u_char *buf; | ||
| 710 | |||
| 711 | if (key == NULL) { | ||
| 712 | error("key_to_blob: key == NULL"); | ||
| 713 | return 0; | ||
| 714 | } | ||
| 715 | buffer_init(&b); | ||
| 716 | switch(key->type){ | ||
| 717 | case KEY_DSA: | ||
| 718 | buffer_put_cstring(&b, key_ssh_name(key)); | ||
| 719 | buffer_put_bignum2(&b, key->dsa->p); | ||
| 720 | buffer_put_bignum2(&b, key->dsa->q); | ||
| 721 | buffer_put_bignum2(&b, key->dsa->g); | ||
| 722 | buffer_put_bignum2(&b, key->dsa->pub_key); | ||
| 723 | break; | ||
| 724 | case KEY_RSA: | ||
| 725 | buffer_put_cstring(&b, key_ssh_name(key)); | ||
| 726 | buffer_put_bignum2(&b, key->rsa->e); | ||
| 727 | buffer_put_bignum2(&b, key->rsa->n); | ||
| 728 | break; | ||
| 729 | default: | ||
| 730 | error("key_to_blob: illegal key type %d", key->type); | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | len = buffer_len(&b); | ||
| 734 | buf = xmalloc(len); | ||
| 735 | memcpy(buf, buffer_ptr(&b), len); | ||
| 736 | memset(buffer_ptr(&b), 0, len); | ||
| 737 | buffer_free(&b); | ||
| 738 | if (lenp != NULL) | ||
| 739 | *lenp = len; | ||
| 740 | if (blobp != NULL) | ||
| 741 | *blobp = buf; | ||
| 742 | return len; | ||
| 743 | } | ||
| 744 | |||
| 745 | int | ||
| 746 | key_sign( | ||
| 747 | Key *key, | ||
| 748 | u_char **sigp, int *lenp, | ||
| 749 | u_char *data, int datalen) | ||
| 750 | { | ||
| 751 | switch(key->type){ | ||
| 752 | case KEY_DSA: | ||
| 753 | return ssh_dss_sign(key, sigp, lenp, data, datalen); | ||
| 754 | break; | ||
| 755 | case KEY_RSA: | ||
| 756 | return ssh_rsa_sign(key, sigp, lenp, data, datalen); | ||
| 757 | break; | ||
| 758 | default: | ||
| 759 | error("key_sign: illegal key type %d", key->type); | ||
| 760 | return -1; | ||
| 761 | break; | ||
| 762 | } | ||
| 763 | } | ||
| 764 | |||
| 765 | int | ||
| 766 | key_verify( | ||
| 767 | Key *key, | ||
| 768 | u_char *signature, int signaturelen, | ||
| 769 | u_char *data, int datalen) | ||
| 770 | { | ||
| 771 | switch(key->type){ | ||
| 772 | case KEY_DSA: | ||
| 773 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); | ||
| 774 | break; | ||
| 775 | case KEY_RSA: | ||
| 776 | return ssh_rsa_verify(key, signature, signaturelen, data, datalen); | ||
| 777 | break; | ||
| 778 | default: | ||
| 779 | error("key_verify: illegal key type %d", key->type); | ||
| 780 | return -1; | ||
| 781 | break; | ||
| 782 | } | ||
| 783 | } | ||
