signkey.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  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. #include "includes.h"
  25. #include "dbutil.h"
  26. #include "signkey.h"
  27. #include "buffer.h"
  28. #include "ssh.h"
  29. #include "ecdsa.h"
  30. static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
  31. #ifdef DROPBEAR_RSA
  32. "ssh-rsa",
  33. #endif
  34. #ifdef DROPBEAR_DSS
  35. "ssh-dss",
  36. #endif
  37. #ifdef DROPBEAR_ECDSA
  38. "ecdsa-sha2-nistp256",
  39. "ecdsa-sha2-nistp384",
  40. "ecdsa-sha2-nistp521"
  41. #endif /* DROPBEAR_ECDSA */
  42. };
  43. /* malloc a new sign_key and set the dss and rsa keys to NULL */
  44. sign_key * new_sign_key() {
  45. sign_key * ret;
  46. ret = (sign_key*)m_malloc(sizeof(sign_key));
  47. ret->type = DROPBEAR_SIGNKEY_NONE;
  48. ret->source = SIGNKEY_SOURCE_INVALID;
  49. return ret;
  50. }
  51. /* Returns key name corresponding to the type. Exits fatally
  52. * if the type is invalid */
  53. const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen) {
  54. if (type >= DROPBEAR_SIGNKEY_NUM_NAMED) {
  55. dropbear_exit("Bad key type %d", type);
  56. }
  57. if (namelen) {
  58. *namelen = strlen(signkey_names[type]);
  59. }
  60. return signkey_names[type];
  61. }
  62. /* Returns DROPBEAR_SIGNKEY_NONE if none match */
  63. enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) {
  64. int i;
  65. for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) {
  66. const char *fixed_name = signkey_names[i];
  67. if (namelen == strlen(fixed_name)
  68. && memcmp(fixed_name, name, namelen) == 0) {
  69. #ifdef DROPBEAR_ECDSA
  70. /* Some of the ECDSA key sizes are defined even if they're not compiled in */
  71. if (0
  72. #ifndef DROPBEAR_ECC_256
  73. || i == DROPBEAR_SIGNKEY_ECDSA_NISTP256
  74. #endif
  75. #ifndef DROPBEAR_ECC_384
  76. || i == DROPBEAR_SIGNKEY_ECDSA_NISTP384
  77. #endif
  78. #ifndef DROPBEAR_ECC_521
  79. || i == DROPBEAR_SIGNKEY_ECDSA_NISTP521
  80. #endif
  81. ) {
  82. TRACE(("attempt to use ecdsa type %d not compiled in", i))
  83. return DROPBEAR_SIGNKEY_NONE;
  84. }
  85. #endif
  86. return (enum signkey_type)i;
  87. }
  88. }
  89. TRACE(("signkey_type_from_name unexpected key type."))
  90. return DROPBEAR_SIGNKEY_NONE;
  91. }
  92. /* Returns a pointer to the key part specific to "type" */
  93. void **
  94. signkey_key_ptr(sign_key *key, enum signkey_type type) {
  95. switch (type) {
  96. #ifdef DROPBEAR_ECDSA
  97. #ifdef DROPBEAR_ECC_256
  98. case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
  99. return (void**)&key->ecckey256;
  100. #endif
  101. #ifdef DROPBEAR_ECC_384
  102. case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
  103. return (void**)&key->ecckey384;
  104. #endif
  105. #ifdef DROPBEAR_ECC_521
  106. case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
  107. return (void**)&key->ecckey521;
  108. #endif
  109. #endif /* DROPBEAR_ECDSA */
  110. #ifdef DROPBEAR_RSA
  111. case DROPBEAR_SIGNKEY_RSA:
  112. return (void**)&key->rsakey;
  113. #endif
  114. #ifdef DROPBEAR_DSS
  115. case DROPBEAR_SIGNKEY_DSS:
  116. return (void**)&key->dsskey;
  117. #endif
  118. default:
  119. return NULL;
  120. }
  121. }
  122. /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail.
  123. * type should be set by the caller to specify the type to read, and
  124. * on return is set to the type read (useful when type = _ANY) */
  125. int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
  126. char *ident;
  127. unsigned int len;
  128. enum signkey_type keytype;
  129. int ret = DROPBEAR_FAILURE;
  130. TRACE2(("enter buf_get_pub_key"))
  131. ident = buf_getstring(buf, &len);
  132. keytype = signkey_type_from_name(ident, len);
  133. m_free(ident);
  134. if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
  135. TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, *type))
  136. return DROPBEAR_FAILURE;
  137. }
  138. TRACE2(("buf_get_pub_key keytype is %d", keytype))
  139. *type = keytype;
  140. /* Rewind the buffer back before "ssh-rsa" etc */
  141. buf_incrpos(buf, -len - 4);
  142. #ifdef DROPBEAR_DSS
  143. if (keytype == DROPBEAR_SIGNKEY_DSS) {
  144. dss_key_free(key->dsskey);
  145. key->dsskey = m_malloc(sizeof(*key->dsskey));
  146. ret = buf_get_dss_pub_key(buf, key->dsskey);
  147. if (ret == DROPBEAR_FAILURE) {
  148. m_free(key->dsskey);
  149. }
  150. }
  151. #endif
  152. #ifdef DROPBEAR_RSA
  153. if (keytype == DROPBEAR_SIGNKEY_RSA) {
  154. rsa_key_free(key->rsakey);
  155. key->rsakey = m_malloc(sizeof(*key->rsakey));
  156. ret = buf_get_rsa_pub_key(buf, key->rsakey);
  157. if (ret == DROPBEAR_FAILURE) {
  158. m_free(key->rsakey);
  159. }
  160. }
  161. #endif
  162. #ifdef DROPBEAR_ECDSA
  163. if (signkey_is_ecdsa(keytype)) {
  164. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
  165. if (eck) {
  166. if (*eck) {
  167. ecc_free(*eck);
  168. m_free(*eck);
  169. *eck = NULL;
  170. }
  171. *eck = buf_get_ecdsa_pub_key(buf);
  172. if (*eck) {
  173. ret = DROPBEAR_SUCCESS;
  174. }
  175. }
  176. }
  177. #endif
  178. TRACE2(("leave buf_get_pub_key"))
  179. return ret;
  180. }
  181. /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail.
  182. * type should be set by the caller to specify the type to read, and
  183. * on return is set to the type read (useful when type = _ANY) */
  184. int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
  185. char *ident;
  186. unsigned int len;
  187. enum signkey_type keytype;
  188. int ret = DROPBEAR_FAILURE;
  189. TRACE2(("enter buf_get_priv_key"))
  190. ident = buf_getstring(buf, &len);
  191. keytype = signkey_type_from_name(ident, len);
  192. m_free(ident);
  193. if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
  194. TRACE(("wrong key type: %d %d", *type, keytype))
  195. return DROPBEAR_FAILURE;
  196. }
  197. *type = keytype;
  198. /* Rewind the buffer back before "ssh-rsa" etc */
  199. buf_incrpos(buf, -len - 4);
  200. #ifdef DROPBEAR_DSS
  201. if (keytype == DROPBEAR_SIGNKEY_DSS) {
  202. dss_key_free(key->dsskey);
  203. key->dsskey = m_malloc(sizeof(*key->dsskey));
  204. ret = buf_get_dss_priv_key(buf, key->dsskey);
  205. if (ret == DROPBEAR_FAILURE) {
  206. m_free(key->dsskey);
  207. }
  208. }
  209. #endif
  210. #ifdef DROPBEAR_RSA
  211. if (keytype == DROPBEAR_SIGNKEY_RSA) {
  212. rsa_key_free(key->rsakey);
  213. key->rsakey = m_malloc(sizeof(*key->rsakey));
  214. ret = buf_get_rsa_priv_key(buf, key->rsakey);
  215. if (ret == DROPBEAR_FAILURE) {
  216. m_free(key->rsakey);
  217. }
  218. }
  219. #endif
  220. #ifdef DROPBEAR_ECDSA
  221. if (signkey_is_ecdsa(keytype)) {
  222. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
  223. if (eck) {
  224. if (*eck) {
  225. ecc_free(*eck);
  226. m_free(*eck);
  227. *eck = NULL;
  228. }
  229. *eck = buf_get_ecdsa_priv_key(buf);
  230. if (*eck) {
  231. ret = DROPBEAR_SUCCESS;
  232. }
  233. }
  234. }
  235. #endif
  236. TRACE2(("leave buf_get_priv_key"))
  237. return ret;
  238. }
  239. /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
  240. void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
  241. buffer *pubkeys;
  242. TRACE2(("enter buf_put_pub_key"))
  243. pubkeys = buf_new(MAX_PUBKEY_SIZE);
  244. #ifdef DROPBEAR_DSS
  245. if (type == DROPBEAR_SIGNKEY_DSS) {
  246. buf_put_dss_pub_key(pubkeys, key->dsskey);
  247. }
  248. #endif
  249. #ifdef DROPBEAR_RSA
  250. if (type == DROPBEAR_SIGNKEY_RSA) {
  251. buf_put_rsa_pub_key(pubkeys, key->rsakey);
  252. }
  253. #endif
  254. #ifdef DROPBEAR_ECDSA
  255. if (signkey_is_ecdsa(type)) {
  256. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
  257. if (eck) {
  258. buf_put_ecdsa_pub_key(pubkeys, *eck);
  259. }
  260. }
  261. #endif
  262. if (pubkeys->len == 0) {
  263. dropbear_exit("Bad key types in buf_put_pub_key");
  264. }
  265. buf_putbufstring(buf, pubkeys);
  266. buf_free(pubkeys);
  267. TRACE2(("leave buf_put_pub_key"))
  268. }
  269. /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
  270. void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type) {
  271. TRACE(("enter buf_put_priv_key"))
  272. TRACE(("type is %d", type))
  273. #ifdef DROPBEAR_DSS
  274. if (type == DROPBEAR_SIGNKEY_DSS) {
  275. buf_put_dss_priv_key(buf, key->dsskey);
  276. TRACE(("leave buf_put_priv_key: dss done"))
  277. return;
  278. }
  279. #endif
  280. #ifdef DROPBEAR_RSA
  281. if (type == DROPBEAR_SIGNKEY_RSA) {
  282. buf_put_rsa_priv_key(buf, key->rsakey);
  283. TRACE(("leave buf_put_priv_key: rsa done"))
  284. return;
  285. }
  286. #endif
  287. #ifdef DROPBEAR_ECDSA
  288. if (signkey_is_ecdsa(type)) {
  289. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
  290. if (eck) {
  291. buf_put_ecdsa_priv_key(buf, *eck);
  292. TRACE(("leave buf_put_priv_key: ecdsa done"))
  293. return;
  294. }
  295. }
  296. #endif
  297. dropbear_exit("Bad key types in put pub key");
  298. }
  299. void sign_key_free(sign_key *key) {
  300. TRACE2(("enter sign_key_free"))
  301. #ifdef DROPBEAR_DSS
  302. dss_key_free(key->dsskey);
  303. key->dsskey = NULL;
  304. #endif
  305. #ifdef DROPBEAR_RSA
  306. rsa_key_free(key->rsakey);
  307. key->rsakey = NULL;
  308. #endif
  309. #ifdef DROPBEAR_ECDSA
  310. #ifdef DROPBEAR_ECC_256
  311. if (key->ecckey256) {
  312. ecc_free(key->ecckey256);
  313. m_free(key->ecckey256);
  314. key->ecckey256 = NULL;
  315. }
  316. #endif
  317. #ifdef DROPBEAR_ECC_384
  318. if (key->ecckey384) {
  319. ecc_free(key->ecckey384);
  320. m_free(key->ecckey384);
  321. key->ecckey384 = NULL;
  322. }
  323. #endif
  324. #ifdef DROPBEAR_ECC_521
  325. if (key->ecckey521) {
  326. ecc_free(key->ecckey521);
  327. m_free(key->ecckey521);
  328. key->ecckey521 = NULL;
  329. }
  330. #endif
  331. #endif
  332. m_free(key->filename);
  333. m_free(key);
  334. TRACE2(("leave sign_key_free"))
  335. }
  336. static char hexdig(unsigned char x) {
  337. if (x > 0xf)
  338. return 'X';
  339. if (x < 10)
  340. return '0' + x;
  341. else
  342. return 'a' + x - 10;
  343. }
  344. /* Since we're not sure if we'll have md5 or sha1, we present both.
  345. * MD5 is used in preference, but sha1 could still be useful */
  346. #ifdef DROPBEAR_MD5_HMAC
  347. static char * sign_key_md5_fingerprint(unsigned char* keyblob,
  348. unsigned int keybloblen) {
  349. char * ret;
  350. hash_state hs;
  351. unsigned char hash[MD5_HASH_SIZE];
  352. unsigned int i;
  353. unsigned int buflen;
  354. md5_init(&hs);
  355. /* skip the size int of the string - this is a bit messy */
  356. md5_process(&hs, keyblob, keybloblen);
  357. md5_done(&hs, hash);
  358. /* "md5 hexfingerprinthere\0", each hex digit is "AB:" etc */
  359. buflen = 4 + 3*MD5_HASH_SIZE;
  360. ret = (char*)m_malloc(buflen);
  361. memset(ret, 'Z', buflen);
  362. strcpy(ret, "md5 ");
  363. for (i = 0; i < MD5_HASH_SIZE; i++) {
  364. unsigned int pos = 4 + i*3;
  365. ret[pos] = hexdig(hash[i] >> 4);
  366. ret[pos+1] = hexdig(hash[i] & 0x0f);
  367. ret[pos+2] = ':';
  368. }
  369. ret[buflen-1] = 0x0;
  370. return ret;
  371. }
  372. #else /* use SHA1 rather than MD5 for fingerprint */
  373. static char * sign_key_sha1_fingerprint(unsigned char* keyblob,
  374. unsigned int keybloblen) {
  375. char * ret;
  376. hash_state hs;
  377. unsigned char hash[SHA1_HASH_SIZE];
  378. unsigned int i;
  379. unsigned int buflen;
  380. sha1_init(&hs);
  381. /* skip the size int of the string - this is a bit messy */
  382. sha1_process(&hs, keyblob, keybloblen);
  383. sha1_done(&hs, hash);
  384. /* "sha1!! hexfingerprinthere\0", each hex digit is "AB:" etc */
  385. buflen = 7 + 3*SHA1_HASH_SIZE;
  386. ret = (char*)m_malloc(buflen);
  387. strcpy(ret, "sha1!! ");
  388. for (i = 0; i < SHA1_HASH_SIZE; i++) {
  389. unsigned int pos = 7 + 3*i;
  390. ret[pos] = hexdig(hash[i] >> 4);
  391. ret[pos+1] = hexdig(hash[i] & 0x0f);
  392. ret[pos+2] = ':';
  393. }
  394. ret[buflen-1] = 0x0;
  395. return ret;
  396. }
  397. #endif /* MD5/SHA1 switch */
  398. /* This will return a freshly malloced string, containing a fingerprint
  399. * in either sha1 or md5 */
  400. char * sign_key_fingerprint(unsigned char* keyblob, unsigned int keybloblen) {
  401. #ifdef DROPBEAR_MD5_HMAC
  402. return sign_key_md5_fingerprint(keyblob, keybloblen);
  403. #else
  404. return sign_key_sha1_fingerprint(keyblob, keybloblen);
  405. #endif
  406. }
  407. void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type,
  408. buffer *data_buf) {
  409. buffer *sigblob;
  410. sigblob = buf_new(MAX_PUBKEY_SIZE);
  411. #ifdef DROPBEAR_DSS
  412. if (type == DROPBEAR_SIGNKEY_DSS) {
  413. buf_put_dss_sign(sigblob, key->dsskey, data_buf);
  414. }
  415. #endif
  416. #ifdef DROPBEAR_RSA
  417. if (type == DROPBEAR_SIGNKEY_RSA) {
  418. buf_put_rsa_sign(sigblob, key->rsakey, data_buf);
  419. }
  420. #endif
  421. #ifdef DROPBEAR_ECDSA
  422. if (signkey_is_ecdsa(type)) {
  423. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
  424. if (eck) {
  425. buf_put_ecdsa_sign(sigblob, *eck, data_buf);
  426. }
  427. }
  428. #endif
  429. if (sigblob->len == 0) {
  430. dropbear_exit("Non-matching signing type");
  431. }
  432. buf_putbufstring(buf, sigblob);
  433. buf_free(sigblob);
  434. }
  435. #ifdef DROPBEAR_SIGNKEY_VERIFY
  436. /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
  437. * If FAILURE is returned, the position of
  438. * buf is undefined. If SUCCESS is returned, buf will be positioned after the
  439. * signature blob */
  440. int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) {
  441. char *type_name = NULL;
  442. unsigned int type_name_len = 0;
  443. enum signkey_type type;
  444. TRACE(("enter buf_verify"))
  445. buf_getint(buf); /* blob length */
  446. type_name = buf_getstring(buf, &type_name_len);
  447. type = signkey_type_from_name(type_name, type_name_len);
  448. m_free(type_name);
  449. #ifdef DROPBEAR_DSS
  450. if (type == DROPBEAR_SIGNKEY_DSS) {
  451. if (key->dsskey == NULL) {
  452. dropbear_exit("No DSS key to verify signature");
  453. }
  454. return buf_dss_verify(buf, key->dsskey, data_buf);
  455. }
  456. #endif
  457. #ifdef DROPBEAR_RSA
  458. if (type == DROPBEAR_SIGNKEY_RSA) {
  459. if (key->rsakey == NULL) {
  460. dropbear_exit("No RSA key to verify signature");
  461. }
  462. return buf_rsa_verify(buf, key->rsakey, data_buf);
  463. }
  464. #endif
  465. #ifdef DROPBEAR_ECDSA
  466. if (signkey_is_ecdsa(type)) {
  467. ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
  468. if (eck) {
  469. return buf_ecdsa_verify(buf, *eck, data_buf);
  470. }
  471. }
  472. #endif
  473. dropbear_exit("Non-matching signing type");
  474. return DROPBEAR_FAILURE;
  475. }
  476. #endif /* DROPBEAR_SIGNKEY_VERIFY */
  477. #ifdef DROPBEAR_KEY_LINES /* ie we're using authorized_keys or known_hosts */
  478. /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE when given a buffer containing
  479. * a key, a key, and a type. The buffer is positioned at the start of the
  480. * base64 data, and contains no trailing data */
  481. /* If fingerprint is non-NULL, it will be set to a malloc()ed fingerprint
  482. of the key if it is successfully decoded */
  483. int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
  484. const unsigned char* algoname, unsigned int algolen,
  485. buffer * line, char ** fingerprint) {
  486. buffer * decodekey = NULL;
  487. int ret = DROPBEAR_FAILURE;
  488. unsigned int len, filealgolen;
  489. unsigned long decodekeylen;
  490. unsigned char* filealgo = NULL;
  491. /* now we have the actual data */
  492. len = line->len - line->pos;
  493. decodekeylen = len * 2; /* big to be safe */
  494. decodekey = buf_new(decodekeylen);
  495. if (base64_decode(buf_getptr(line, len), len,
  496. buf_getwriteptr(decodekey, decodekey->size),
  497. &decodekeylen) != CRYPT_OK) {
  498. TRACE(("checkpubkey: base64 decode failed"))
  499. goto out;
  500. }
  501. TRACE(("checkpubkey: base64_decode success"))
  502. buf_incrlen(decodekey, decodekeylen);
  503. if (fingerprint) {
  504. *fingerprint = sign_key_fingerprint(buf_getptr(decodekey, decodekeylen),
  505. decodekeylen);
  506. }
  507. /* compare the keys */
  508. if ( ( decodekeylen != keybloblen )
  509. || memcmp( buf_getptr(decodekey, decodekey->len),
  510. keyblob, decodekey->len) != 0) {
  511. TRACE(("checkpubkey: compare failed"))
  512. goto out;
  513. }
  514. /* ... and also check that the algo specified and the algo in the key
  515. * itself match */
  516. filealgolen = buf_getint(decodekey);
  517. filealgo = buf_getptr(decodekey, filealgolen);
  518. if (filealgolen != algolen || memcmp(filealgo, algoname, algolen) != 0) {
  519. TRACE(("checkpubkey: algo match failed"))
  520. goto out;
  521. }
  522. /* All checks passed */
  523. ret = DROPBEAR_SUCCESS;
  524. out:
  525. buf_free(decodekey);
  526. decodekey = NULL;
  527. return ret;
  528. }
  529. #endif