dropbearkey.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * Dropbear - a SSH2 server
  3. *
  4. * Copyright (c) 2002,2003 Matt Johnston
  5. * All rights reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE. */
  24. /* The format of the keyfiles is basically a raw dump of the buffer. Data types
  25. * are specified in the transport rfc 4253 - string is a 32-bit len then the
  26. * non-null-terminated string, mp_int is a 32-bit len then the bignum data.
  27. * The actual functions are buf_put_rsa_priv_key() and buf_put_dss_priv_key()
  28. * RSA:
  29. * string "ssh-rsa"
  30. * mp_int e
  31. * mp_int n
  32. * mp_int d
  33. * mp_int p (newer versions only)
  34. * mp_int q (newer versions only)
  35. *
  36. * DSS:
  37. * string "ssh-dss"
  38. * mp_int p
  39. * mp_int q
  40. * mp_int g
  41. * mp_int y
  42. * mp_int x
  43. *
  44. * Ed25519:
  45. * string "ssh-ed25519"
  46. * string k (32 bytes) + A (32 bytes)
  47. *
  48. */
  49. #include "includes.h"
  50. #include "signkey.h"
  51. #include "buffer.h"
  52. #include "dbutil.h"
  53. #include "genrsa.h"
  54. #include "gendss.h"
  55. #include "gened25519.h"
  56. #include "ecdsa.h"
  57. #include "crypto_desc.h"
  58. #include "dbrandom.h"
  59. #include "gensignkey.h"
  60. static void printhelp(char * progname);
  61. static void printpubkey(sign_key * key, int keytype);
  62. static int printpubfile(const char* filename);
  63. /* Print a help message */
  64. static void printhelp(char * progname) {
  65. fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
  66. "-t type Type of key to generate. One of:\n"
  67. #if DROPBEAR_RSA
  68. " rsa\n"
  69. #endif
  70. #if DROPBEAR_DSS
  71. " dss\n"
  72. #endif
  73. #if DROPBEAR_ECDSA
  74. " ecdsa\n"
  75. #endif
  76. #if DROPBEAR_ED25519
  77. " ed25519\n"
  78. #endif
  79. "-f filename Use filename for the secret key.\n"
  80. " ~/.ssh/id_dropbear is recommended for client keys.\n"
  81. "-s bits Key size in bits, should be a multiple of 8 (optional)\n"
  82. #if DROPBEAR_DSS
  83. " DSS has a fixed size of 1024 bits\n"
  84. #endif
  85. #if DROPBEAR_ECDSA
  86. " ECDSA has sizes "
  87. #if DROPBEAR_ECC_256
  88. "256 "
  89. #endif
  90. #if DROPBEAR_ECC_384
  91. "384 "
  92. #endif
  93. #if DROPBEAR_ECC_521
  94. "521 "
  95. #endif
  96. "\n"
  97. #endif
  98. #if DROPBEAR_ED25519
  99. " Ed25519 has a fixed size of 256 bits\n"
  100. #endif
  101. "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
  102. #if DEBUG_TRACE
  103. "-v verbose\n"
  104. #endif
  105. ,progname);
  106. }
  107. /* fails fatally */
  108. static void check_signkey_bits(enum signkey_type type, int bits)
  109. {
  110. switch (type) {
  111. #if DROPBEAR_ED25519
  112. case DROPBEAR_SIGNKEY_ED25519:
  113. if (bits != 256) {
  114. dropbear_exit("Ed25519 keys have a fixed size of 256 bits\n");
  115. exit(EXIT_FAILURE);
  116. }
  117. break;
  118. #endif
  119. #if DROPBEAR_RSA
  120. case DROPBEAR_SIGNKEY_RSA:
  121. if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
  122. dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
  123. " multiple of 8\n");
  124. }
  125. break;
  126. #endif
  127. #if DROPEAR_DSS
  128. case DROPBEAR_SIGNKEY_DSS:
  129. if (bits != 1024) {
  130. dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
  131. exit(EXIT_FAILURE);
  132. }
  133. #endif
  134. default:
  135. (void)0; /* quiet, compiler. ecdsa handles checks itself */
  136. }
  137. }
  138. #if defined(DBMULTI_dropbearkey) || !DROPBEAR_MULTI
  139. #if defined(DBMULTI_dropbearkey) && DROPBEAR_MULTI
  140. int dropbearkey_main(int argc, char ** argv) {
  141. #else
  142. int main(int argc, char ** argv) {
  143. #endif
  144. int i;
  145. char ** next = NULL;
  146. char * filename = NULL;
  147. enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
  148. char * typetext = NULL;
  149. char * sizetext = NULL;
  150. unsigned int bits = 0, genbits;
  151. int printpub = 0;
  152. crypto_init();
  153. seedrandom();
  154. /* get the commandline options */
  155. for (i = 1; i < argc; i++) {
  156. if (argv[i] == NULL) {
  157. continue; /* Whack */
  158. }
  159. if (next) {
  160. *next = argv[i];
  161. next = NULL;
  162. continue;
  163. }
  164. if (argv[i][0] == '-') {
  165. switch (argv[i][1]) {
  166. case 'f':
  167. next = &filename;
  168. break;
  169. case 't':
  170. next = &typetext;
  171. break;
  172. case 's':
  173. next = &sizetext;
  174. break;
  175. case 'y':
  176. printpub = 1;
  177. break;
  178. case 'h':
  179. printhelp(argv[0]);
  180. exit(EXIT_SUCCESS);
  181. break;
  182. #if DEBUG_TRACE
  183. case 'v':
  184. debug_trace = DROPBEAR_VERBOSE_LEVEL;
  185. break;
  186. #endif
  187. default:
  188. fprintf(stderr, "Unknown argument %s\n", argv[i]);
  189. printhelp(argv[0]);
  190. exit(EXIT_FAILURE);
  191. break;
  192. }
  193. }
  194. }
  195. if (!filename) {
  196. fprintf(stderr, "Must specify a key filename\n");
  197. printhelp(argv[0]);
  198. exit(EXIT_FAILURE);
  199. }
  200. if (printpub) {
  201. int ret = printpubfile(filename);
  202. exit(ret);
  203. }
  204. /* check/parse args */
  205. if (!typetext) {
  206. fprintf(stderr, "Must specify key type\n");
  207. printhelp(argv[0]);
  208. exit(EXIT_FAILURE);
  209. }
  210. #if DROPBEAR_RSA
  211. if (strcmp(typetext, "rsa") == 0)
  212. {
  213. keytype = DROPBEAR_SIGNKEY_RSA;
  214. }
  215. #endif
  216. #if DROPBEAR_DSS
  217. if (strcmp(typetext, "dss") == 0)
  218. {
  219. keytype = DROPBEAR_SIGNKEY_DSS;
  220. }
  221. #endif
  222. #if DROPBEAR_ECDSA
  223. if (strcmp(typetext, "ecdsa") == 0)
  224. {
  225. keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
  226. }
  227. #endif
  228. #if DROPBEAR_ED25519
  229. if (strcmp(typetext, "ed25519") == 0)
  230. {
  231. keytype = DROPBEAR_SIGNKEY_ED25519;
  232. }
  233. #endif
  234. if (keytype == DROPBEAR_SIGNKEY_NONE) {
  235. fprintf(stderr, "Unknown key type '%s'\n", typetext);
  236. printhelp(argv[0]);
  237. exit(EXIT_FAILURE);
  238. }
  239. if (sizetext) {
  240. if (sscanf(sizetext, "%u", &bits) != 1) {
  241. fprintf(stderr, "Bits must be an integer\n");
  242. exit(EXIT_FAILURE);
  243. }
  244. check_signkey_bits(keytype, bits);;
  245. }
  246. genbits = signkey_generate_get_bits(keytype, bits);
  247. fprintf(stderr, "Generating %u bit %s key, this may take a while...\n", genbits, typetext);
  248. if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
  249. {
  250. dropbear_exit("Failed to generate key.\n");
  251. }
  252. printpubfile(filename);
  253. return EXIT_SUCCESS;
  254. }
  255. #endif
  256. static int printpubfile(const char* filename) {
  257. buffer *buf = NULL;
  258. sign_key *key = NULL;
  259. enum signkey_type keytype;
  260. int ret;
  261. int err = DROPBEAR_FAILURE;
  262. buf = buf_new(MAX_PRIVKEY_SIZE);
  263. ret = buf_readfile(buf, filename);
  264. if (ret != DROPBEAR_SUCCESS) {
  265. fprintf(stderr, "Failed reading '%s'\n", filename);
  266. goto out;
  267. }
  268. key = new_sign_key();
  269. keytype = DROPBEAR_SIGNKEY_ANY;
  270. buf_setpos(buf, 0);
  271. ret = buf_get_priv_key(buf, key, &keytype);
  272. if (ret == DROPBEAR_FAILURE) {
  273. fprintf(stderr, "Bad key in '%s'\n", filename);
  274. goto out;
  275. }
  276. printpubkey(key, keytype);
  277. err = DROPBEAR_SUCCESS;
  278. out:
  279. buf_burn_free(buf);
  280. buf = NULL;
  281. if (key) {
  282. sign_key_free(key);
  283. key = NULL;
  284. }
  285. return err;
  286. }
  287. static void printpubkey(sign_key * key, int keytype) {
  288. buffer * buf = NULL;
  289. unsigned char base64key[MAX_PUBKEY_SIZE*2];
  290. unsigned long base64len;
  291. int err;
  292. const char * typestring = NULL;
  293. char *fp = NULL;
  294. int len;
  295. struct passwd * pw = NULL;
  296. char * username = NULL;
  297. char hostname[100];
  298. buf = buf_new(MAX_PUBKEY_SIZE);
  299. buf_put_pub_key(buf, key, keytype);
  300. buf_setpos(buf, 4);
  301. len = buf->len - buf->pos;
  302. base64len = sizeof(base64key);
  303. err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
  304. if (err != CRYPT_OK) {
  305. dropbear_exit("base64 failed");
  306. }
  307. typestring = signkey_name_from_type(keytype, NULL);
  308. fp = sign_key_fingerprint(buf_getptr(buf, len), len);
  309. /* a user@host comment is informative */
  310. username = "";
  311. pw = getpwuid(getuid());
  312. if (pw) {
  313. username = pw->pw_name;
  314. }
  315. gethostname(hostname, sizeof(hostname));
  316. hostname[sizeof(hostname)-1] = '\0';
  317. printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
  318. typestring, base64key, username, hostname, fp);
  319. m_free(fp);
  320. buf_free(buf);
  321. }