ssh2bpp.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. * Binary packet protocol for SSH-2.
  3. */
  4. #include <assert.h>
  5. #include "putty.h"
  6. #include "ssh.h"
  7. #include "sshbpp.h"
  8. #include "sshcr.h"
  9. struct ssh2_bpp_direction {
  10. unsigned long sequence;
  11. ssh2_cipher *cipher;
  12. ssh2_mac *mac;
  13. int etm_mode;
  14. const struct ssh_compress *comp;
  15. void *comp_ctx;
  16. };
  17. struct ssh2_bpp_state {
  18. int crState;
  19. long len, pad, payload, packetlen, maclen, length, maxlen;
  20. unsigned char *buf;
  21. size_t bufsize;
  22. unsigned char *data;
  23. unsigned cipherblk;
  24. PktIn *pktin;
  25. struct ssh2_bpp_direction in, out;
  26. int pending_newkeys;
  27. BinaryPacketProtocol bpp;
  28. };
  29. static void ssh2_bpp_free(BinaryPacketProtocol *bpp);
  30. static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp);
  31. static PktOut *ssh2_bpp_new_pktout(int type);
  32. static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt);
  33. const struct BinaryPacketProtocolVtable ssh2_bpp_vtable = {
  34. ssh2_bpp_free,
  35. ssh2_bpp_handle_input,
  36. ssh2_bpp_new_pktout,
  37. ssh2_bpp_format_packet,
  38. };
  39. BinaryPacketProtocol *ssh2_bpp_new(void)
  40. {
  41. struct ssh2_bpp_state *s = snew(struct ssh2_bpp_state);
  42. memset(s, 0, sizeof(*s));
  43. s->bpp.vt = &ssh2_bpp_vtable;
  44. return &s->bpp;
  45. }
  46. static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
  47. {
  48. struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
  49. sfree(s->buf);
  50. if (s->out.cipher)
  51. ssh2_cipher_free(s->out.cipher);
  52. if (s->out.mac)
  53. ssh2_mac_free(s->out.mac);
  54. if (s->out.comp_ctx)
  55. s->out.comp->compress_cleanup(s->out.comp_ctx);
  56. if (s->in.cipher)
  57. ssh2_cipher_free(s->in.cipher);
  58. if (s->in.mac)
  59. ssh2_mac_free(s->in.mac);
  60. if (s->in.comp_ctx)
  61. s->in.comp->decompress_cleanup(s->in.comp_ctx);
  62. if (s->pktin)
  63. ssh_unref_packet(s->pktin);
  64. sfree(s);
  65. }
  66. void ssh2_bpp_new_outgoing_crypto(
  67. BinaryPacketProtocol *bpp,
  68. const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
  69. const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
  70. const struct ssh_compress *compression)
  71. {
  72. struct ssh2_bpp_state *s;
  73. assert(bpp->vt == &ssh2_bpp_vtable);
  74. s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
  75. if (s->out.cipher)
  76. ssh2_cipher_free(s->out.cipher);
  77. if (s->out.mac)
  78. ssh2_mac_free(s->out.mac);
  79. if (s->out.comp_ctx)
  80. s->out.comp->compress_cleanup(s->out.comp_ctx);
  81. if (cipher) {
  82. s->out.cipher = ssh2_cipher_new(cipher);
  83. ssh2_cipher_setkey(s->out.cipher, ckey);
  84. ssh2_cipher_setiv(s->out.cipher, iv);
  85. } else {
  86. s->out.cipher = NULL;
  87. }
  88. s->out.etm_mode = etm_mode;
  89. if (mac) {
  90. s->out.mac = ssh2_mac_new(mac, s->out.cipher);
  91. mac->setkey(s->out.mac, mac_key);
  92. } else {
  93. s->out.mac = NULL;
  94. }
  95. s->out.comp = compression;
  96. /* out_comp is always non-NULL, because no compression is
  97. * indicated by ssh_comp_none. So compress_init always exists, but
  98. * it may return a null out_comp_ctx. */
  99. s->out.comp_ctx = compression->compress_init();
  100. }
  101. void ssh2_bpp_new_incoming_crypto(
  102. BinaryPacketProtocol *bpp,
  103. const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
  104. const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
  105. const struct ssh_compress *compression)
  106. {
  107. struct ssh2_bpp_state *s;
  108. assert(bpp->vt == &ssh2_bpp_vtable);
  109. s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
  110. if (s->in.cipher)
  111. ssh2_cipher_free(s->in.cipher);
  112. if (s->in.mac)
  113. ssh2_mac_free(s->in.mac);
  114. if (s->in.comp_ctx)
  115. s->in.comp->decompress_cleanup(s->in.comp_ctx);
  116. if (cipher) {
  117. s->in.cipher = ssh2_cipher_new(cipher);
  118. ssh2_cipher_setkey(s->in.cipher, ckey);
  119. ssh2_cipher_setiv(s->in.cipher, iv);
  120. } else {
  121. s->in.cipher = NULL;
  122. }
  123. s->in.etm_mode = etm_mode;
  124. if (mac) {
  125. s->in.mac = ssh2_mac_new(mac, s->in.cipher);
  126. mac->setkey(s->in.mac, mac_key);
  127. } else {
  128. s->in.mac = NULL;
  129. }
  130. s->in.comp = compression;
  131. /* in_comp is always non-NULL, because no compression is
  132. * indicated by ssh_comp_none. So compress_init always exists, but
  133. * it may return a null in_comp_ctx. */
  134. s->in.comp_ctx = compression->decompress_init();
  135. /* Clear the pending_newkeys flag, so that handle_input below will
  136. * start consuming the input data again. */
  137. s->pending_newkeys = FALSE;
  138. }
  139. static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
  140. {
  141. struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
  142. crBegin(s->crState);
  143. while (1) {
  144. s->maxlen = 0;
  145. s->length = 0;
  146. if (s->in.cipher)
  147. s->cipherblk = ssh2_cipher_alg(s->in.cipher)->blksize;
  148. else
  149. s->cipherblk = 8;
  150. if (s->cipherblk < 8)
  151. s->cipherblk = 8;
  152. s->maclen = s->in.mac ? ssh2_mac_alg(s->in.mac)->len : 0;
  153. if (s->in.cipher &&
  154. (ssh2_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
  155. s->in.mac && !s->in.etm_mode) {
  156. /*
  157. * When dealing with a CBC-mode cipher, we want to avoid the
  158. * possibility of an attacker's tweaking the ciphertext stream
  159. * so as to cause us to feed the same block to the block
  160. * cipher more than once and thus leak information
  161. * (VU#958563). The way we do this is not to take any
  162. * decisions on the basis of anything we've decrypted until
  163. * we've verified it with a MAC. That includes the packet
  164. * length, so we just read data and check the MAC repeatedly,
  165. * and when the MAC passes, see if the length we've got is
  166. * plausible.
  167. *
  168. * This defence is unnecessary in OpenSSH ETM mode, because
  169. * the whole point of ETM mode is that the attacker can't
  170. * tweak the ciphertext stream at all without the MAC
  171. * detecting it before we decrypt anything.
  172. */
  173. /*
  174. * Make sure we have buffer space for a maximum-size packet.
  175. */
  176. unsigned buflimit = OUR_V2_PACKETLIMIT + s->maclen;
  177. if (s->bufsize < buflimit) {
  178. s->bufsize = buflimit;
  179. s->buf = sresize(s->buf, s->bufsize, unsigned char);
  180. }
  181. /* Read an amount corresponding to the MAC. */
  182. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  183. s->bpp.in_raw, s->buf, s->maclen));
  184. s->packetlen = 0;
  185. ssh2_mac_start(s->in.mac);
  186. put_uint32(s->in.mac, s->in.sequence);
  187. for (;;) { /* Once around this loop per cipher block. */
  188. /* Read another cipher-block's worth, and tack it on to
  189. * the end. */
  190. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  191. s->bpp.in_raw,
  192. s->buf + (s->packetlen + s->maclen),
  193. s->cipherblk));
  194. /* Decrypt one more block (a little further back in
  195. * the stream). */
  196. ssh2_cipher_decrypt(s->in.cipher,
  197. s->buf + s->packetlen, s->cipherblk);
  198. /* Feed that block to the MAC. */
  199. put_data(s->in.mac,
  200. s->buf + s->packetlen, s->cipherblk);
  201. s->packetlen += s->cipherblk;
  202. /* See if that gives us a valid packet. */
  203. if (ssh2_mac_verresult(s->in.mac, s->buf + s->packetlen) &&
  204. ((s->len = toint(GET_32BIT(s->buf))) ==
  205. s->packetlen-4))
  206. break;
  207. if (s->packetlen >= (long)OUR_V2_PACKETLIMIT) {
  208. s->bpp.error = dupprintf(
  209. "No valid incoming packet found");
  210. crStopV;
  211. }
  212. }
  213. s->maxlen = s->packetlen + s->maclen;
  214. /*
  215. * Now transfer the data into an output packet.
  216. */
  217. s->pktin = snew_plus(PktIn, s->maxlen);
  218. s->pktin->qnode.prev = s->pktin->qnode.next = NULL;
  219. s->pktin->refcount = 1;
  220. s->pktin->type = 0;
  221. s->data = snew_plus_get_aux(s->pktin);
  222. memcpy(s->data, s->buf, s->maxlen);
  223. } else if (s->in.mac && s->in.etm_mode) {
  224. if (s->bufsize < 4) {
  225. s->bufsize = 4;
  226. s->buf = sresize(s->buf, s->bufsize, unsigned char);
  227. }
  228. /*
  229. * OpenSSH encrypt-then-MAC mode: the packet length is
  230. * unencrypted, unless the cipher supports length encryption.
  231. */
  232. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  233. s->bpp.in_raw, s->buf, 4));
  234. /* Cipher supports length decryption, so do it */
  235. if (s->in.cipher && (ssh2_cipher_alg(s->in.cipher)->flags &
  236. SSH_CIPHER_SEPARATE_LENGTH)) {
  237. /* Keep the packet the same though, so the MAC passes */
  238. unsigned char len[4];
  239. memcpy(len, s->buf, 4);
  240. ssh2_cipher_decrypt_length(
  241. s->in.cipher, len, 4, s->in.sequence);
  242. s->len = toint(GET_32BIT(len));
  243. } else {
  244. s->len = toint(GET_32BIT(s->buf));
  245. }
  246. /*
  247. * _Completely_ silly lengths should be stomped on before they
  248. * do us any more damage.
  249. */
  250. if (s->len < 0 || s->len > (long)OUR_V2_PACKETLIMIT ||
  251. s->len % s->cipherblk != 0) {
  252. s->bpp.error = dupprintf(
  253. "Incoming packet length field was garbled");
  254. crStopV;
  255. }
  256. /*
  257. * So now we can work out the total packet length.
  258. */
  259. s->packetlen = s->len + 4;
  260. /*
  261. * Allocate the packet to return, now we know its length.
  262. */
  263. s->pktin = snew_plus(PktIn, OUR_V2_PACKETLIMIT + s->maclen);
  264. s->pktin->qnode.prev = s->pktin->qnode.next = NULL;
  265. s->pktin->refcount = 1;
  266. s->pktin->type = 0;
  267. s->data = snew_plus_get_aux(s->pktin);
  268. memcpy(s->data, s->buf, 4);
  269. /*
  270. * Read the remainder of the packet.
  271. */
  272. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  273. s->bpp.in_raw, s->data + 4,
  274. s->packetlen + s->maclen - 4));
  275. /*
  276. * Check the MAC.
  277. */
  278. if (s->in.mac && !ssh2_mac_verify(
  279. s->in.mac, s->data, s->len + 4, s->in.sequence)) {
  280. s->bpp.error = dupprintf("Incorrect MAC received on packet");
  281. crStopV;
  282. }
  283. /* Decrypt everything between the length field and the MAC. */
  284. if (s->in.cipher)
  285. ssh2_cipher_decrypt(
  286. s->in.cipher, s->data + 4, s->packetlen - 4);
  287. } else {
  288. if (s->bufsize < s->cipherblk) {
  289. s->bufsize = s->cipherblk;
  290. s->buf = sresize(s->buf, s->bufsize, unsigned char);
  291. }
  292. /*
  293. * Acquire and decrypt the first block of the packet. This will
  294. * contain the length and padding details.
  295. */
  296. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  297. s->bpp.in_raw, s->buf, s->cipherblk));
  298. if (s->in.cipher)
  299. ssh2_cipher_decrypt(
  300. s->in.cipher, s->buf, s->cipherblk);
  301. /*
  302. * Now get the length figure.
  303. */
  304. s->len = toint(GET_32BIT(s->buf));
  305. /*
  306. * _Completely_ silly lengths should be stomped on before they
  307. * do us any more damage.
  308. */
  309. if (s->len < 0 || s->len > (long)OUR_V2_PACKETLIMIT ||
  310. (s->len + 4) % s->cipherblk != 0) {
  311. s->bpp.error = dupprintf(
  312. "Incoming packet was garbled on decryption");
  313. crStopV;
  314. }
  315. /*
  316. * So now we can work out the total packet length.
  317. */
  318. s->packetlen = s->len + 4;
  319. /*
  320. * Allocate the packet to return, now we know its length.
  321. */
  322. s->maxlen = s->packetlen + s->maclen;
  323. s->pktin = snew_plus(PktIn, s->maxlen);
  324. s->pktin->qnode.prev = s->pktin->qnode.next = NULL;
  325. s->pktin->refcount = 1;
  326. s->pktin->type = 0;
  327. s->data = snew_plus_get_aux(s->pktin);
  328. memcpy(s->data, s->buf, s->cipherblk);
  329. /*
  330. * Read and decrypt the remainder of the packet.
  331. */
  332. crMaybeWaitUntilV(bufchain_try_fetch_consume(
  333. s->bpp.in_raw, s->data + s->cipherblk,
  334. s->packetlen + s->maclen - s->cipherblk));
  335. /* Decrypt everything _except_ the MAC. */
  336. if (s->in.cipher)
  337. ssh2_cipher_decrypt(
  338. s->in.cipher,
  339. s->data + s->cipherblk, s->packetlen - s->cipherblk);
  340. /*
  341. * Check the MAC.
  342. */
  343. if (s->in.mac && !ssh2_mac_verify(
  344. s->in.mac, s->data, s->len + 4, s->in.sequence)) {
  345. s->bpp.error = dupprintf("Incorrect MAC received on packet");
  346. crStopV;
  347. }
  348. }
  349. /* Get and sanity-check the amount of random padding. */
  350. s->pad = s->data[4];
  351. if (s->pad < 4 || s->len - s->pad < 1) {
  352. s->bpp.error = dupprintf(
  353. "Invalid padding length on received packet");
  354. crStopV;
  355. }
  356. /*
  357. * This enables us to deduce the payload length.
  358. */
  359. s->payload = s->len - s->pad - 1;
  360. s->length = s->payload + 5;
  361. s->pktin->encrypted_len = s->packetlen;
  362. s->pktin->sequence = s->in.sequence++;
  363. s->length = s->packetlen - s->pad;
  364. assert(s->length >= 0);
  365. /*
  366. * Decompress packet payload.
  367. */
  368. {
  369. unsigned char *newpayload;
  370. int newlen;
  371. if (s->in.comp && s->in.comp->decompress(
  372. s->in.comp_ctx, s->data + 5, s->length - 5,
  373. &newpayload, &newlen)) {
  374. if (s->maxlen < newlen + 5) {
  375. PktIn *old_pktin = s->pktin;
  376. s->maxlen = newlen + 5;
  377. s->pktin = snew_plus(PktIn, s->maxlen);
  378. *s->pktin = *old_pktin; /* structure copy */
  379. s->data = snew_plus_get_aux(s->pktin);
  380. smemclr(old_pktin, s->packetlen + s->maclen);
  381. sfree(old_pktin);
  382. }
  383. s->length = 5 + newlen;
  384. memcpy(s->data + 5, newpayload, newlen);
  385. sfree(newpayload);
  386. }
  387. }
  388. /*
  389. * Now we can identify the semantic content of the packet,
  390. * and also the initial type byte.
  391. */
  392. if (s->length <= 5) { /* == 5 we hope, but robustness */
  393. /*
  394. * RFC 4253 doesn't explicitly say that completely empty
  395. * packets with no type byte are forbidden. We handle them
  396. * here by giving them a type code larger than 0xFF, which
  397. * will be picked up at the next layer and trigger
  398. * SSH_MSG_UNIMPLEMENTED.
  399. */
  400. s->pktin->type = SSH_MSG_NO_TYPE_CODE;
  401. s->length = 0;
  402. BinarySource_INIT(s->pktin, s->data + 5, 0);
  403. } else {
  404. s->pktin->type = s->data[5];
  405. s->length -= 6;
  406. BinarySource_INIT(s->pktin, s->data + 6, s->length);
  407. }
  408. if (s->bpp.logctx) {
  409. logblank_t blanks[MAX_BLANKS];
  410. int nblanks = ssh2_censor_packet(
  411. s->bpp.pls, s->pktin->type, FALSE,
  412. make_ptrlen(s->data, s->length), blanks);
  413. log_packet(s->bpp.logctx, PKT_INCOMING, s->pktin->type,
  414. ssh2_pkt_type(s->bpp.pls->kctx, s->bpp.pls->actx,
  415. s->pktin->type),
  416. get_ptr(s->pktin), get_avail(s->pktin), nblanks, blanks,
  417. &s->pktin->sequence, 0, NULL);
  418. }
  419. pq_push(s->bpp.in_pq, s->pktin);
  420. {
  421. int type = s->pktin->type;
  422. s->pktin = NULL;
  423. if (type == SSH2_MSG_DISCONNECT)
  424. s->bpp.seen_disconnect = TRUE;
  425. if (type == SSH2_MSG_NEWKEYS) {
  426. /*
  427. * Mild layer violation: in this situation we must
  428. * suspend processing of the input byte stream until
  429. * the transport layer has initialised the new keys by
  430. * calling ssh2_bpp_new_incoming_crypto above.
  431. */
  432. s->pending_newkeys = TRUE;
  433. crWaitUntilV(!s->pending_newkeys);
  434. }
  435. }
  436. }
  437. crFinishV;
  438. }
  439. static PktOut *ssh2_bpp_new_pktout(int pkt_type)
  440. {
  441. PktOut *pkt = ssh_new_packet();
  442. pkt->length = 5; /* space for packet length + padding length */
  443. pkt->minlen = 0;
  444. pkt->type = pkt_type;
  445. put_byte(pkt, pkt_type);
  446. pkt->prefix = pkt->length;
  447. return pkt;
  448. }
  449. static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
  450. {
  451. int origlen, cipherblk, maclen, padding, unencrypted_prefix, i;
  452. if (s->bpp.logctx) {
  453. ptrlen pktdata = make_ptrlen(pkt->data + pkt->prefix,
  454. pkt->length - pkt->prefix);
  455. logblank_t blanks[MAX_BLANKS];
  456. int nblanks = ssh2_censor_packet(
  457. s->bpp.pls, pkt->type, TRUE, pktdata, blanks);
  458. log_packet(s->bpp.logctx, PKT_OUTGOING, pkt->type,
  459. ssh2_pkt_type(s->bpp.pls->kctx, s->bpp.pls->actx,
  460. pkt->type),
  461. pktdata.ptr, pktdata.len, nblanks, blanks, &s->out.sequence,
  462. pkt->downstream_id, pkt->additional_log_text);
  463. }
  464. cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8;
  465. cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
  466. if (s->out.comp && s->out.comp_ctx) {
  467. unsigned char *newpayload;
  468. int minlen, newlen;
  469. /*
  470. * Compress packet payload.
  471. */
  472. minlen = pkt->minlen;
  473. if (minlen) {
  474. /*
  475. * Work out how much compressed data we need (at least) to
  476. * make the overall packet length come to pkt->minlen.
  477. */
  478. if (s->out.mac)
  479. minlen -= ssh2_mac_alg(s->out.mac)->len;
  480. minlen -= 8; /* length field + min padding */
  481. }
  482. s->out.comp->compress(s->out.comp_ctx, pkt->data + 5, pkt->length - 5,
  483. &newpayload, &newlen, minlen);
  484. pkt->length = 5;
  485. put_data(pkt, newpayload, newlen);
  486. sfree(newpayload);
  487. }
  488. /*
  489. * Add padding. At least four bytes, and must also bring total
  490. * length (minus MAC) up to a multiple of the block size.
  491. * If pkt->forcepad is set, make sure the packet is at least that size
  492. * after padding.
  493. */
  494. padding = 4;
  495. unencrypted_prefix = (s->out.mac && s->out.etm_mode) ? 4 : 0;
  496. padding +=
  497. (cipherblk - (pkt->length - unencrypted_prefix + padding) % cipherblk)
  498. % cipherblk;
  499. assert(padding <= 255);
  500. maclen = s->out.mac ? ssh2_mac_alg(s->out.mac)->len : 0;
  501. origlen = pkt->length;
  502. for (i = 0; i < padding; i++)
  503. put_byte(pkt, random_byte());
  504. pkt->data[4] = padding;
  505. PUT_32BIT(pkt->data, origlen + padding - 4);
  506. /* Encrypt length if the scheme requires it */
  507. if (s->out.cipher &&
  508. (ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) {
  509. ssh2_cipher_encrypt_length(s->out.cipher, pkt->data, 4,
  510. s->out.sequence);
  511. }
  512. put_padding(pkt, maclen, 0);
  513. if (s->out.mac && s->out.etm_mode) {
  514. /*
  515. * OpenSSH-defined encrypt-then-MAC protocol.
  516. */
  517. if (s->out.cipher)
  518. ssh2_cipher_encrypt(s->out.cipher,
  519. pkt->data + 4, origlen + padding - 4);
  520. ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
  521. s->out.sequence);
  522. } else {
  523. /*
  524. * SSH-2 standard protocol.
  525. */
  526. if (s->out.mac)
  527. ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
  528. s->out.sequence);
  529. if (s->out.cipher)
  530. ssh2_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
  531. }
  532. s->out.sequence++; /* whether or not we MACed */
  533. pkt->encrypted_len = origlen + padding;
  534. }
  535. static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
  536. {
  537. struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
  538. if (pkt->minlen > 0 && !(s->out.comp && s->out.comp_ctx)) {
  539. /*
  540. * If we've been told to pad the packet out to a given minimum
  541. * length, but we're not compressing (and hence can't get the
  542. * compression to do the padding by pointlessly opening and
  543. * closing zlib blocks), then our other strategy is to precede
  544. * this message with an SSH_MSG_IGNORE that makes it up to the
  545. * right length.
  546. *
  547. * A third option in principle, and the most obviously
  548. * sensible, would be to set the explicit padding field in the
  549. * packet to more than its minimum value. Sadly, that turns
  550. * out to break some servers (our institutional memory thinks
  551. * Cisco in particular) and so we abandoned that idea shortly
  552. * after trying it.
  553. */
  554. /*
  555. * Calculate the length we expect the real packet to have.
  556. */
  557. int block, length;
  558. PktOut *ignore_pkt;
  559. block = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 0;
  560. if (block < 8)
  561. block = 8;
  562. length = pkt->length;
  563. length += 4; /* minimum 4 byte padding */
  564. length += block-1;
  565. length -= (length % block);
  566. if (s->out.mac)
  567. length += ssh2_mac_alg(s->out.mac)->len;
  568. if (length < pkt->minlen) {
  569. /*
  570. * We need an ignore message. Calculate its length.
  571. */
  572. length = pkt->minlen - length;
  573. /*
  574. * And work backwards from that to the length of the
  575. * contained string.
  576. */
  577. if (s->out.mac)
  578. length -= ssh2_mac_alg(s->out.mac)->len;
  579. length -= 8; /* length field + min padding */
  580. length -= 5; /* type code + string length prefix */
  581. if (length < 0)
  582. length = 0;
  583. ignore_pkt = ssh2_bpp_new_pktout(SSH2_MSG_IGNORE);
  584. put_uint32(ignore_pkt, length);
  585. while (length-- > 0)
  586. put_byte(ignore_pkt, random_byte());
  587. ssh2_bpp_format_packet_inner(s, ignore_pkt);
  588. bufchain_add(s->bpp.out_raw, ignore_pkt->data, ignore_pkt->length);
  589. ssh_free_pktout(ignore_pkt);
  590. }
  591. }
  592. ssh2_bpp_format_packet_inner(s, pkt);
  593. bufchain_add(s->bpp.out_raw, pkt->data, pkt->length);
  594. ssh_free_pktout(pkt);
  595. }