|
Lines 42-47
Link Here
|
| 42 |
#include <sys/param.h> |
42 |
#include <sys/param.h> |
| 43 |
|
43 |
|
| 44 |
#include <openssl/evp.h> |
44 |
#include <openssl/evp.h> |
|
|
45 |
#include <openssl/md5.h> |
| 45 |
#include "openbsd-compat/openssl-compat.h" |
46 |
#include "openbsd-compat/openssl-compat.h" |
| 46 |
|
47 |
|
| 47 |
#include <fcntl.h> |
48 |
#include <fcntl.h> |
|
Lines 329-334
Link Here
|
| 329 |
return (ret); |
330 |
return (ret); |
| 330 |
} |
331 |
} |
| 331 |
|
332 |
|
|
|
333 |
|
| 334 |
static int |
| 335 |
verify_key_ssh1 (AuthenticationConnection *ac, Key *key) |
| 336 |
{ |
| 337 |
|
| 338 |
int ret = 0; |
| 339 |
BIGNUM *challenge, *encrypted_challenge; |
| 340 |
u_char session_id[16], response[16], token[32], mdbuf[16]; |
| 341 |
MD5_CTX md; |
| 342 |
|
| 343 |
/* generate random session_id and token */ |
| 344 |
arc4random_buf(session_id, sizeof(session_id)); |
| 345 |
arc4random_buf(token, sizeof(token)); |
| 346 |
if ((challenge = BN_bin2bn(token, sizeof(token), NULL)) == NULL) { |
| 347 |
fprintf(stderr, "%s: BNbin2bn failed", __func__); |
| 348 |
return ret; |
| 349 |
} |
| 350 |
|
| 351 |
/* Encrypt the challenge with the public key. */ |
| 352 |
if ((encrypted_challenge = BN_new()) == NULL) { |
| 353 |
fprintf(stderr, "%s: BN_new failed", __func__); |
| 354 |
BN_clear_free(challenge); |
| 355 |
return ret; |
| 356 |
} |
| 357 |
rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); |
| 358 |
|
| 359 |
/* send challenge to agent and expect response */ |
| 360 |
ssh_decrypt_challenge(ac, key, encrypted_challenge, session_id, 1, response); |
| 361 |
|
| 362 |
MD5_Init(&md); |
| 363 |
MD5_Update(&md, token, sizeof(token)); |
| 364 |
MD5_Update(&md, session_id, sizeof(session_id)); |
| 365 |
MD5_Final(mdbuf, &md); |
| 366 |
|
| 367 |
/* Verify that the response is the original challenge. */ |
| 368 |
if (timingsafe_bcmp(response, mdbuf, sizeof(mdbuf)) == 0) { |
| 369 |
ret = 1; |
| 370 |
} |
| 371 |
|
| 372 |
BN_clear_free(encrypted_challenge); |
| 373 |
BN_clear_free(challenge); |
| 374 |
|
| 375 |
return ret; |
| 376 |
} |
| 377 |
|
| 378 |
static int |
| 379 |
verify_key_ssh2 (AuthenticationConnection *ac, Key *key) |
| 380 |
{ |
| 381 |
int ret = 0; |
| 382 |
u_char *signature, token[512]; |
| 383 |
u_int slen; |
| 384 |
|
| 385 |
arc4random_buf(token, sizeof(token)); |
| 386 |
|
| 387 |
/* let the agent sign the token */ |
| 388 |
if (ssh_agent_sign(ac, key, &signature, &slen, token, sizeof(token)) == 0 ) { |
| 389 |
/* verify signature */ |
| 390 |
if (key_verify(key, signature, slen, token, sizeof(token))) { |
| 391 |
ret = 1; |
| 392 |
} |
| 393 |
xfree(signature); |
| 394 |
} |
| 395 |
return ret; |
| 396 |
} |
| 397 |
|
| 398 |
static int |
| 399 |
verify_key(AuthenticationConnection *ac, const char *filename) |
| 400 |
{ |
| 401 |
Key *public, *key; |
| 402 |
char *comment; |
| 403 |
int version, ret = -1; |
| 404 |
|
| 405 |
/* load public key */ |
| 406 |
public = key_load_public(filename, NULL); |
| 407 |
if (public == NULL) { |
| 408 |
fprintf(stderr, "Could not read public key: %s\n", filename); |
| 409 |
return ret; |
| 410 |
} |
| 411 |
|
| 412 |
/* try to find public key in agent */ |
| 413 |
for (version = 1; version <= 2 && ret != 0; version++) { |
| 414 |
for (key = ssh_get_first_identity(ac, &comment, version); |
| 415 |
key != NULL && ret != 0; |
| 416 |
key = ssh_get_next_identity(ac, &comment, version)) { |
| 417 |
if (key_equal_public(public, key)) { |
| 418 |
if (version == 1) { |
| 419 |
if (verify_key_ssh1(ac, public)) |
| 420 |
ret = 0; |
| 421 |
} else { |
| 422 |
if (verify_key_ssh2(ac, public)) |
| 423 |
ret = 0; |
| 424 |
} |
| 425 |
} |
| 426 |
key_free(key); |
| 427 |
xfree(comment); |
| 428 |
} |
| 429 |
} |
| 430 |
|
| 431 |
key_free(public); |
| 432 |
|
| 433 |
return ret; |
| 434 |
} |
| 435 |
|
| 332 |
static int |
436 |
static int |
| 333 |
do_file(AuthenticationConnection *ac, int deleting, char *file) |
437 |
do_file(AuthenticationConnection *ac, int deleting, char *file) |
| 334 |
{ |
438 |
{ |
|
Lines 357-362
Link Here
|
| 357 |
fprintf(stderr, " -c Require confirmation to sign using identities\n"); |
461 |
fprintf(stderr, " -c Require confirmation to sign using identities\n"); |
| 358 |
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); |
462 |
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); |
| 359 |
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); |
463 |
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); |
|
|
464 |
fprintf(stderr, " -v pubkey Verify if agent can access matching private key.\n"); |
| 360 |
} |
465 |
} |
| 361 |
|
466 |
|
| 362 |
int |
467 |
int |
|
Lines 384-390
Link Here
|
| 384 |
"Could not open a connection to your authentication agent.\n"); |
489 |
"Could not open a connection to your authentication agent.\n"); |
| 385 |
exit(2); |
490 |
exit(2); |
| 386 |
} |
491 |
} |
| 387 |
while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) { |
492 |
while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:v:")) != -1) { |
| 388 |
switch (ch) { |
493 |
switch (ch) { |
| 389 |
case 'l': |
494 |
case 'l': |
| 390 |
case 'L': |
495 |
case 'L': |
|
Lines 420-425
Link Here
|
| 420 |
goto done; |
525 |
goto done; |
| 421 |
} |
526 |
} |
| 422 |
break; |
527 |
break; |
|
|
528 |
case 'v': |
| 529 |
if (verify_key(ac, optarg) == -1) |
| 530 |
ret = 1; |
| 531 |
goto done; |
| 423 |
default: |
532 |
default: |
| 424 |
usage(); |
533 |
usage(); |
| 425 |
ret = 1; |
534 |
ret = 1; |