struct sexp * make_ssh_hostkey_tag(struct address_info *host) { UINT32 left = host->ip->length; UINT8 *s = host->ip->data; struct lsh_string *reversed = lsh_string_alloc(left); /* First, transform "foo.lysator.liu.se" into "se.liu.lysator.foo" */ while (left) { UINT8 *p = memchr(s, '.', left); if (!p) { memcpy(reversed->data, s, left); break; } else { UINT32 segment = p - s; left -= segment; memcpy(reversed->data + left, s, segment); reversed->data[--left] = '.'; s = p+1; } } return sexp_l(2, sexp_z("ssh-hostkey"), sexp_s(NULL, reversed), -1); }
static struct client_x11_channel * make_client_x11_channel(struct lsh_fd *fd, struct client_x11_display *display) { NEW(client_x11_channel, self); /* Use a limited window size for the setup */ init_channel_forward(&self->super, fd, X11_SETUP_MAX_LENGTH); self->display = display; self->state = 0; self->buffer = lsh_string_alloc(X11_SETUP_MAX_LENGTH); return self; }
struct sexp * spki_hash_data(struct hash_algorithm *algorithm, int algorithm_name, UINT32 length, UINT8 *data) { struct hash_instance *hash = MAKE_HASH(algorithm); struct lsh_string *out = lsh_string_alloc(hash->hash_size); HASH_UPDATE(hash, length, data); HASH_DIGEST(hash, out->data); return sexp_l(3, SA(HASH), sexp_a(algorithm_name), sexp_s(NULL, out), -1); }
static struct sexp * srp_gen(struct srp_gen_options *options) { struct lsh_string *salt; struct lsh_string *name; struct sexp *e; salt = lsh_string_alloc(SALT_SIZE); RANDOM(options->r, salt->length, salt->data); name = ssh_format("%lz", options->name); e = srp_make_verifier(options->G, options->H, salt, name, options->passwd); lsh_string_free(name); return e; }
struct lsh_string * pkcs5_derive_key(struct mac_algorithm *prf, const struct lsh_string *password, const struct lsh_string *salt, uint32_t iterations, uint32_t key_length) { struct mac_instance *m = MAKE_MAC(prf, lsh_string_length(password), lsh_string_data(password)); struct lsh_string *key = lsh_string_alloc(key_length); uint32_t left = key_length; uint32_t pos = 0; /* Set up the block counter buffer. This will never have more than * the last few bits set (using sha1, 8 bits = 5100 bytes of key) so * we only change the last byte. */ uint8_t block_count[4] = { 0, 0, 0, 1 }; struct lsh_string *digest = lsh_string_alloc(prf->mac_size); struct lsh_string *buffer = lsh_string_alloc(prf->mac_size); assert(iterations); assert(key_length <= 255 * prf->mac_size); for (;; block_count[3]++) { uint32_t i; assert(block_count[3]); /* First iterate */ MAC_UPDATE(m, lsh_string_length(salt), lsh_string_data(salt)); MAC_UPDATE(m, 4, block_count); MAC_DIGEST(m, buffer, 0); for (i = 1; i < iterations; i++) { MAC_UPDATE(m, prf->mac_size, lsh_string_data(buffer)); MAC_DIGEST(m, digest, 0); lsh_string_write_xor(buffer, 0, STRING_LD(digest)); } assert(pos + left == key_length); if (left <= prf->mac_size) { lsh_string_write(key, pos, left, lsh_string_data(buffer)); break; } else { lsh_string_write_string(key, pos, buffer); pos += prf->mac_size; left -= prf->mac_size; } } KILL(m); lsh_string_free(digest); lsh_string_free(buffer); return key; }
struct lsh_string * encrypt_packet(struct lsh_string *packet, struct compress_instance *compress, struct crypto_instance *crypt, struct mac_instance *mac, uint32_t seqno) { uint32_t block_size; uint32_t new_size; uint8_t padding_length; uint32_t padding; uint32_t mac_length; uint32_t mac_start; uint32_t length = lsh_string_length(packet); assert(length); /* Deflate, pad, mac, encrypt. */ if (compress) { struct lsh_string *n = lsh_string_alloc(SSH_MAX_PACKET + SSH_MAX_PACKET_FUZZ); length = CODEC(compress, n, 0, lsh_string_length(packet), lsh_string_data(packet)); assert(length > 0); lsh_string_trunc(n, length); lsh_string_free(packet); packet = n; } block_size = crypt ? crypt->block_size : 8; mac_length = mac ? mac->mac_size : 0; /* new_size is (length + 9) rounded up to a multiple of * block_size */ new_size = block_size * (1 + (8 + length) / block_size); padding_length = new_size - length - 5; assert(padding_length >= 4); packet = ssh_format("%i%c%lfS%lr%lr", length + padding_length + 1, padding_length, packet, padding_length, &padding, mac_length, &mac_start); assert(new_size + mac_length == lsh_string_length(packet)); lsh_string_write_random(packet, padding, padding_length); if (mac) { uint8_t s[4]; assert(new_size == mac_start); WRITE_UINT32(s, seqno); MAC_UPDATE(mac, 4, s); MAC_UPDATE(mac, new_size, lsh_string_data(packet)); MAC_DIGEST(mac, packet, mac_start); } if (crypt) CRYPT(crypt, new_size, packet, 0, packet, 0); return packet; }