dropbearkey.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. */
  45. #include "includes.h"
  46. #include "signkey.h"
  47. #include "buffer.h"
  48. #include "dbutil.h"
  49. #include "genrsa.h"
  50. #include "gendss.h"
  51. #include "ecdsa.h"
  52. #include "crypto_desc.h"
  53. #include "dbrandom.h"
  54. #include "gensignkey.h"
  55. static void printhelp(char * progname);
  56. static void printpubkey(sign_key * key, int keytype);
  57. static int printpubfile(const char* filename);
  58. /* Print a help message */
  59. static void printhelp(char * progname) {
  60. fprintf(stderr, "Usage: %s -t <type> -f <filename> [-s bits]\n"
  61. "-t type Type of key to generate. One of:\n"
  62. #ifdef DROPBEAR_RSA
  63. " rsa\n"
  64. #endif
  65. #ifdef DROPBEAR_DSS
  66. " dss\n"
  67. #endif
  68. #ifdef DROPBEAR_ECDSA
  69. " ecdsa\n"
  70. #endif
  71. "-f filename Use filename for the secret key.\n"
  72. " ~/.ssh/id_dropbear is recommended for client keys.\n"
  73. "-s bits Key size in bits, should be a multiple of 8 (optional)\n"
  74. #ifdef DROPBEAR_DSS
  75. " DSS has a fixed size of 1024 bits\n"
  76. #endif
  77. #ifdef DROPBEAR_ECDSA
  78. " ECDSA has sizes "
  79. #ifdef DROPBEAR_ECC_256
  80. "256 "
  81. #endif
  82. #ifdef DROPBEAR_ECC_384
  83. "384 "
  84. #endif
  85. #ifdef DROPBEAR_ECC_521
  86. "521 "
  87. #endif
  88. "\n"
  89. #endif
  90. "-y Just print the publickey and fingerprint for the\n private key in <filename>.\n"
  91. #ifdef DEBUG_TRACE
  92. "-v verbose\n"
  93. #endif
  94. ,progname);
  95. }
  96. /* fails fatally */
  97. static void check_signkey_bits(enum signkey_type type, int bits)
  98. {
  99. switch (type) {
  100. #ifdef DROPBEAR_RSA
  101. case DROPBEAR_SIGNKEY_RSA:
  102. if (bits < 512 || bits > 4096 || (bits % 8 != 0)) {
  103. dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
  104. " multiple of 8\n");
  105. }
  106. break;
  107. #endif
  108. #ifdef DROPEAR_DSS
  109. case DROPBEAR_SIGNKEY_DSS:
  110. if (bits != 1024) {
  111. dropbear_exit("DSS keys have a fixed size of 1024 bits\n");
  112. exit(EXIT_FAILURE);
  113. }
  114. #endif
  115. default:
  116. (void)0; /* quiet, compiler. ecdsa handles checks itself */
  117. }
  118. }
  119. #if defined(DBMULTI_dropbearkey) || !defined(DROPBEAR_MULTI)
  120. #if defined(DBMULTI_dropbearkey) && defined(DROPBEAR_MULTI)
  121. int dropbearkey_main(int argc, char ** argv) {
  122. #else
  123. int main(int argc, char ** argv) {
  124. #endif
  125. int i;
  126. char ** next = 0;
  127. char * filename = NULL;
  128. enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
  129. char * typetext = NULL;
  130. char * sizetext = NULL;
  131. unsigned int bits = 0;
  132. int printpub = 0;
  133. crypto_init();
  134. seedrandom();
  135. /* get the commandline options */
  136. for (i = 1; i < argc; i++) {
  137. if (argv[i] == NULL) {
  138. continue; /* Whack */
  139. }
  140. if (next) {
  141. *next = argv[i];
  142. next = NULL;
  143. continue;
  144. }
  145. if (argv[i][0] == '-') {
  146. switch (argv[i][1]) {
  147. case 'f':
  148. next = &filename;
  149. break;
  150. case 't':
  151. next = &typetext;
  152. break;
  153. case 's':
  154. next = &sizetext;
  155. break;
  156. case 'y':
  157. printpub = 1;
  158. break;
  159. case 'h':
  160. printhelp(argv[0]);
  161. exit(EXIT_SUCCESS);
  162. break;
  163. #ifdef DEBUG_TRACE
  164. case 'v':
  165. debug_trace = 1;
  166. break;
  167. #endif
  168. default:
  169. fprintf(stderr, "Unknown argument %s\n", argv[i]);
  170. printhelp(argv[0]);
  171. exit(EXIT_FAILURE);
  172. break;
  173. }
  174. }
  175. }
  176. if (!filename) {
  177. fprintf(stderr, "Must specify a key filename\n");
  178. printhelp(argv[0]);
  179. exit(EXIT_FAILURE);
  180. }
  181. if (printpub) {
  182. int ret = printpubfile(filename);
  183. exit(ret);
  184. }
  185. /* check/parse args */
  186. if (!typetext) {
  187. fprintf(stderr, "Must specify key type\n");
  188. printhelp(argv[0]);
  189. exit(EXIT_FAILURE);
  190. }
  191. #ifdef DROPBEAR_RSA
  192. if (strcmp(typetext, "rsa") == 0)
  193. {
  194. keytype = DROPBEAR_SIGNKEY_RSA;
  195. }
  196. #endif
  197. #ifdef DROPBEAR_DSS
  198. if (strcmp(typetext, "dss") == 0)
  199. {
  200. keytype = DROPBEAR_SIGNKEY_DSS;
  201. }
  202. #endif
  203. #ifdef DROPBEAR_ECDSA
  204. if (strcmp(typetext, "ecdsa") == 0)
  205. {
  206. keytype = DROPBEAR_SIGNKEY_ECDSA_KEYGEN;
  207. }
  208. #endif
  209. if (keytype == DROPBEAR_SIGNKEY_NONE) {
  210. fprintf(stderr, "Unknown key type '%s'\n", typetext);
  211. printhelp(argv[0]);
  212. exit(EXIT_FAILURE);
  213. }
  214. if (sizetext) {
  215. if (sscanf(sizetext, "%u", &bits) != 1) {
  216. fprintf(stderr, "Bits must be an integer\n");
  217. exit(EXIT_FAILURE);
  218. }
  219. check_signkey_bits(keytype, bits);;
  220. }
  221. fprintf(stderr, "Generating key, this may take a while...\n");
  222. if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
  223. {
  224. dropbear_exit("Failed to generate key.\n");
  225. }
  226. printpubfile(filename);
  227. return EXIT_SUCCESS;
  228. }
  229. #endif
  230. static int printpubfile(const char* filename) {
  231. buffer *buf = NULL;
  232. sign_key *key = NULL;
  233. enum signkey_type keytype;
  234. int ret;
  235. int err = DROPBEAR_FAILURE;
  236. buf = buf_new(MAX_PRIVKEY_SIZE);
  237. ret = buf_readfile(buf, filename);
  238. if (ret != DROPBEAR_SUCCESS) {
  239. fprintf(stderr, "Failed reading '%s'\n", filename);
  240. goto out;
  241. }
  242. key = new_sign_key();
  243. keytype = DROPBEAR_SIGNKEY_ANY;
  244. buf_setpos(buf, 0);
  245. ret = buf_get_priv_key(buf, key, &keytype);
  246. if (ret == DROPBEAR_FAILURE) {
  247. fprintf(stderr, "Bad key in '%s'\n", filename);
  248. goto out;
  249. }
  250. printpubkey(key, keytype);
  251. err = DROPBEAR_SUCCESS;
  252. out:
  253. buf_burn(buf);
  254. buf_free(buf);
  255. buf = NULL;
  256. if (key) {
  257. sign_key_free(key);
  258. key = NULL;
  259. }
  260. return err;
  261. }
  262. static void printpubkey(sign_key * key, int keytype) {
  263. buffer * buf = NULL;
  264. unsigned char base64key[MAX_PUBKEY_SIZE*2];
  265. unsigned long base64len;
  266. int err;
  267. const char * typestring = NULL;
  268. char *fp = NULL;
  269. int len;
  270. struct passwd * pw = NULL;
  271. char * username = NULL;
  272. char hostname[100];
  273. buf = buf_new(MAX_PUBKEY_SIZE);
  274. buf_put_pub_key(buf, key, keytype);
  275. buf_setpos(buf, 4);
  276. len = buf->len - buf->pos;
  277. base64len = sizeof(base64key);
  278. err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
  279. if (err != CRYPT_OK) {
  280. fprintf(stderr, "base64 failed");
  281. }
  282. typestring = signkey_name_from_type(keytype, NULL);
  283. fp = sign_key_fingerprint(buf_getptr(buf, len), len);
  284. /* a user@host comment is informative */
  285. username = "";
  286. pw = getpwuid(getuid());
  287. if (pw) {
  288. username = pw->pw_name;
  289. }
  290. gethostname(hostname, sizeof(hostname));
  291. hostname[sizeof(hostname)-1] = '\0';
  292. printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n",
  293. typestring, base64key, username, hostname, fp);
  294. m_free(fp);
  295. buf_free(buf);
  296. }