2
0

openssh-privkey.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
  2. /* SPDX-License-Identifier: Unlicense */
  3. /**
  4. @file openssh-privkey.c
  5. OpenSSH Private Key decryption demo, Steffen Jaeckel
  6. */
  7. #include <tomcrypt.h>
  8. #include <stdarg.h>
  9. #include <termios.h>
  10. #if defined(LTC_PEM_SSH)
  11. static void print_err(const char *fmt, ...)
  12. {
  13. va_list args;
  14. va_start(args, fmt);
  15. vfprintf(stderr, fmt, args);
  16. va_end(args);
  17. }
  18. static void die_(int err, int line)
  19. {
  20. print_err("%3d: LTC sez %s\n", line, error_to_string(err));
  21. exit(EXIT_FAILURE);
  22. }
  23. #define die(i) do { die_(i, __LINE__); } while(0)
  24. #define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
  25. static char* getpassword(const char *prompt, size_t maxlen)
  26. {
  27. char *wr, *end, *pass = XCALLOC(1, maxlen + 1);
  28. struct termios tio;
  29. tcflag_t c_lflag;
  30. if (pass == NULL)
  31. return NULL;
  32. wr = pass;
  33. end = pass + maxlen;
  34. tcgetattr(0, &tio);
  35. c_lflag = tio.c_lflag;
  36. tio.c_lflag &= ~ECHO;
  37. tcsetattr(0, TCSANOW, &tio);
  38. printf("%s", prompt);
  39. fflush(stdout);
  40. while (pass < end) {
  41. int c = getchar();
  42. if (c == '\r' || c == '\n' || c == -1)
  43. break;
  44. *wr++ = c;
  45. }
  46. tio.c_lflag = c_lflag;
  47. tcsetattr(0, TCSAFLUSH, &tio);
  48. printf("\n");
  49. return pass;
  50. }
  51. static int password_get(void **p, unsigned long *l, void *u)
  52. {
  53. (void)u;
  54. *p = getpassword("Enter passphrase: ", 256);
  55. *l = strlen(*p);
  56. return 0;
  57. }
  58. static void print(ltc_pka_key *k)
  59. {
  60. int err = CRYPT_OK;
  61. unsigned char buf[256];
  62. unsigned long lbuf = sizeof(buf);
  63. char pubkey[256*4/3];
  64. unsigned long lpubkey = sizeof(pubkey);
  65. void *mpint = NULL;
  66. switch (k->id) {
  67. case LTC_PKA_ED25519:
  68. ltc_mp.init(&mpint);
  69. ltc_mp.unsigned_read(mpint, k->u.ed25519.pub, sizeof(k->u.ed25519.pub));
  70. if ((err = ssh_encode_sequence_multi(buf, &lbuf,
  71. LTC_SSHDATA_STRING, "ssh-ed25519", strlen("ssh-ed25519"),
  72. LTC_SSHDATA_MPINT, mpint,
  73. 0, NULL)) != CRYPT_OK)
  74. goto errout;
  75. if ((err = base64_encode(buf, lbuf, pubkey, &lpubkey)) != CRYPT_OK)
  76. goto errout;
  77. printf("\rssh-ed25519 %s\n", pubkey);
  78. break;
  79. default:
  80. print_err("Unsupported key type: %d\n", k->id);
  81. break;
  82. }
  83. errout:
  84. if (mpint != NULL)
  85. ltc_mp.deinit(mpint);
  86. if (err != CRYPT_OK)
  87. die(err);
  88. }
  89. int main(int argc, char **argv)
  90. {
  91. int err;
  92. FILE *f = NULL;
  93. ltc_pka_key k;
  94. password_ctx pw_ctx = { .callback = password_get };
  95. if ((err = register_all_ciphers()) != CRYPT_OK) {
  96. die(err);
  97. }
  98. if ((err = register_all_hashes()) != CRYPT_OK) {
  99. die(err);
  100. }
  101. if ((err = crypt_mp_init("ltm")) != CRYPT_OK) {
  102. die(err);
  103. }
  104. if (argc > 1) f = fopen(argv[1], "r");
  105. else f = stdin;
  106. if (f == NULL) DIE("fopen sez no");
  107. if ((err = pem_decode_openssh_filehandle(f, &k, &pw_ctx))) {
  108. die(err);
  109. }
  110. print(&k);
  111. return EXIT_SUCCESS;
  112. }
  113. #else
  114. int main(void) { return EXIT_FAILURE; }
  115. #endif