void ssh_xfree(void *ptr) { #ifdef SSH_DEBUG_MALLOC if (ptr != NULL) { unsigned long size; if (SSH_GET_32BIT((unsigned char *) ptr - 4) != SSH_DEBUG_MALLOC_MAGIC_IN_USE) { if (SSH_GET_32BIT((unsigned char *) ptr - 4) == SSH_DEBUG_MALLOC_MAGIC_FREED) ssh_fatal("Freeing block that is already freed"); ssh_fatal("Freeing block that is either not mallocated, or whose magic number before the object was overwritten"); } size = SSH_GET_32BIT((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); if (SSH_GET_32BIT((unsigned char *) ptr + size) != SSH_DEBUG_MALLOC_MAGIC_AFTER) ssh_fatal("Freeing block whose magic number after the object was overwritten"); /* Mark the old block freed */ SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED); SSH_PUT_32BIT((unsigned char *) ptr + size, SSH_DEBUG_MALLOC_MAGIC_FREED); free((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); } #else /* SSH_DEBUG_MALLOC */ if (ptr != NULL) free(ptr); #endif /* SSH_DEBUG_MALLOC */ }
void gcm_update_block(void *context, const unsigned char *buf) { SshGCMCtx *ctx = (SshGCMCtx *)context; SshUInt32 *X = ctx->X; X[0] ^= SSH_GET_32BIT(buf); X[1] ^= SSH_GET_32BIT(buf + 4); X[2] ^= SSH_GET_32BIT(buf + 8); X[3] ^= SSH_GET_32BIT(buf + 12); ssh_gf2n_128_mul(X, ctx->H, ctx->mod); }
void gcm_update_block_words_table(void *context, const unsigned char *buf) { SshGCMCtx *ctx = (SshGCMCtx *)context; SshUInt32 *m = ctx->workspace; SshUInt32 *X = ctx->X; SshUInt32 t[4], i; X[0] ^= SSH_GET_32BIT(buf); X[1] ^= SSH_GET_32BIT(buf + 4); X[2] ^= SSH_GET_32BIT(buf + 8); X[3] ^= SSH_GET_32BIT(buf + 12); t[0] = t[1] = t[2] = t[3] = 0; i = 0; #ifdef MINIMAL_STACK while (i < 16) { GF2N_128_TABLE_BYTE_MUL(t, X, m, i); GF2N_128_TABLE_BYTE_MUL(t, X, m, i + 1); GF2N_128_TABLE_BYTE_MUL(t, X, m, i + 2); GF2N_128_TABLE_BYTE_MUL(t, X, m, i + 3); i += 4; } #else /* MINIMAL_STACK */ GF2N_128_TABLE_BYTE_MUL(t, X, m, 0); GF2N_128_TABLE_BYTE_MUL(t, X, m, 1); GF2N_128_TABLE_BYTE_MUL(t, X, m, 2); GF2N_128_TABLE_BYTE_MUL(t, X, m, 3); GF2N_128_TABLE_BYTE_MUL(t, X, m, 4); GF2N_128_TABLE_BYTE_MUL(t, X, m, 5); GF2N_128_TABLE_BYTE_MUL(t, X, m, 6); GF2N_128_TABLE_BYTE_MUL(t, X, m, 7); GF2N_128_TABLE_BYTE_MUL(t, X, m, 8); GF2N_128_TABLE_BYTE_MUL(t, X, m, 9); GF2N_128_TABLE_BYTE_MUL(t, X, m, 10); GF2N_128_TABLE_BYTE_MUL(t, X, m, 11); GF2N_128_TABLE_BYTE_MUL(t, X, m, 12); GF2N_128_TABLE_BYTE_MUL(t, X, m, 13); GF2N_128_TABLE_BYTE_MUL(t, X, m, 14); GF2N_128_TABLE_BYTE_MUL(t, X, m, 15); #endif /* MINIMAL_STACK */ X[0] = t[0]; X[1] = t[1]; X[2] = t[2]; X[3] = t[3]; }
/* Format time string in RFC-2550 compatible format as snprintf renderer. The datum points to the memory buffer having the 32-bit long time in seconds from the epoch in the network byte order. */ int ssh_time32buf_render(unsigned char *buf, int buf_size, int precision, void *datum) { unsigned char *ptr = datum; int len; len = ssh_time_format(buf, buf_size + 1, SSH_GET_32BIT(ptr)); if (len + 1 >= buf_size) return buf_size + 1; return len; }
SshBuffer *handler_input_cross(Handler c) { int len; unsigned char *cp; SshBuffer *packet; packet = c->incoming; if (packet == NULL) { /* No partial packet already received; initialize for receiving packet header. */ packet = ssh_buffer_allocate(); c->incoming = packet; c->incoming_offset = 0; c->incoming_len = 4; ssh_buffer_append_space(packet, &cp, c->incoming_len); } keep_reading: /* Keep reading until either entire header or entire packet received (determined by incoming_len). Space has already been allocated in the buffer. */ while (c->incoming_offset < c->incoming_len) { len = c->incoming_len - c->incoming_offset; cp = ssh_buffer_ptr(packet); cp += c->incoming_offset; len = ssh_stream_read(c->stream, cp, len); if (len < 0) return NULL; if (len == 0) ssh_fatal("%s: handler_input_cross: received unexpected eof", c->side); c->incoming_offset += len; } /* If this was the header received, read the rest of the packet if there is non-zero length payload. */ if (c->incoming_len == 4 && c->incoming_offset == 4) { cp = ssh_buffer_ptr(packet); c->incoming_len = 4 + SSH_GET_32BIT(cp); if (c->incoming_len > 4) { ssh_buffer_append_space(packet, &cp, c->incoming_len - 4); goto keep_reading; } } /* The entire packet has been received. Return it. */ c->incoming = NULL; cp = ssh_buffer_ptr(packet); return packet; }
static int ssh_appgw_http_unmarshal_int(SshBuffer buf, int *result) { if (ssh_buffer_len(buf) < 4) { *result = 0; return 0; } *result = (int)(SSH_GET_32BIT(ssh_buffer_ptr(buf))); ssh_buffer_consume(buf,4); return 1; }
void ssh_engine_tcp_init(SshEngine engine, SshEngineFlowData flow) { #ifdef SSH_IPSEC_TCP_SEQUENCE_RANDOMIZER SshUInt8 tmp[4]; #endif /* SSH_IPSEC_TCP_SEQUENCE_RANDOMIZER */ SSH_DEBUG(SSH_D_LOWOK, ("initializing tcpdata")); flow->u.tcp.state = SSH_ENGINE_TCP_INITIAL; #ifdef SSH_IPSEC_TCP_SEQUENCE_RANDOMIZER if (flow->data_flags & (SSH_ENGINE_FLOW_D_LOCAL_ENDPNT)) { SSH_DEBUG(SSH_D_MY, ("flow has local endpoint: not randomizing sequence numbers")); flow->u.tcp.delta_i_to_r = 0; flow->u.tcp.delta_r_to_i = 0; } else { SSH_DEBUG(SSH_D_MY, ("flow has remote endpoints: setting random sequence deltas")); tmp[0] = ssh_engine_random_get_byte(engine); tmp[1] = ssh_engine_random_get_byte(engine); tmp[2] = ssh_engine_random_get_byte(engine); tmp[3] = ssh_engine_random_get_byte(engine); flow->u.tcp.delta_i_to_r = SSH_GET_32BIT(tmp); tmp[0] = ssh_engine_random_get_byte(engine); tmp[1] = ssh_engine_random_get_byte(engine); tmp[2] = ssh_engine_random_get_byte(engine); tmp[3] = ssh_engine_random_get_byte(engine); flow->u.tcp.delta_r_to_i = SSH_GET_32BIT(tmp); } #endif /* SSH_IPSEC_TCP_SEQUENCE_RANDOMIZER */ }
void mp_unlinearize_msb_first(SshInt *value, const unsigned char *buf, unsigned int len) { unsigned int i; ssh_mp_set_ui(value, 0); for (i = 0; i + 4 <= len; i += 4) { unsigned long limb = SSH_GET_32BIT(buf + i); ssh_mp_mul_2exp(value, value, 32); ssh_mp_add_ui(value, value, limb); } for (; i < len; i++) { ssh_mp_mul_2exp(value, value, 8); ssh_mp_add_ui(value, value, buf[i]); } }
void ssh_buf_to_mp_lsb(SshInt *x, const unsigned char *cp, size_t len) { size_t i; unsigned long limb; ssh_mp_set_ui(x, 0); for (i = len - 3; i > 4; i -= 4) { limb = SSH_GET_32BIT(cp + i - 1); ssh_mp_mul_2exp(x, x, 32); ssh_mp_add_ui(x, x, limb); } for (; i > 0; i--) { ssh_mp_mul_2exp(x, x, 8); ssh_mp_add_ui(x, x, cp[i - 1]); } }
void ssh_buf_to_mp(SshInt *x, const unsigned char *cp, size_t len) { size_t i; unsigned long limb; ssh_mp_set_ui(x, 0); for (i = 0; i + 4 <= len; i += 4) { limb = SSH_GET_32BIT(cp + i); ssh_mp_mul_2exp(x, x, 32); ssh_mp_add_ui(x, x, limb); } for (; i < len; i++) { ssh_mp_mul_2exp(x, x, 8); ssh_mp_add_ui(x, x, cp[i]); } }
/* Generate stateless cookie based on the secret, nonce, spi_i and ip-address. */ SshIkev2Error ikev2_generate_cookie(SshIkev2Packet packet, SshIkev2Sa ike_sa, unsigned char *notify_data, size_t notify_len) { SshCryptoStatus status; unsigned char buffer[16]; SshMac mac; size_t len; SSH_DEBUG(SSH_D_LOWOK, ("Starting cookie generation for SA %p", ike_sa)); packet->ed->ike_ed->cookie_len = 4 + ssh_mac_length(IKEV2_COOKIE_MAC_ALGORITHM); packet->ed->ike_ed->cookie = ssh_obstack_alloc(packet->ed->obstack, packet->ed->ike_ed->cookie_len); if (packet->ed->ike_ed->cookie == NULL) { SSH_DEBUG(SSH_D_ERROR, ("Error: Out of memory allocating cookie")); return SSH_IKEV2_ERROR_OUT_OF_MEMORY; } if (notify_len > 4 && notify_data != NULL && SSH_GET_32BIT(notify_data) == ike_sa->server->context->cookie_version_number - 1) { ike_sa->server->context->cookie_secret_use_counter_prev++; SSH_PUT_32BIT(packet->ed->ike_ed->cookie, ike_sa->server->context->cookie_version_number - 1); status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM, ike_sa->server->context->cookie_secret_prev, IKEV2_COOKIE_SECRET_LEN, &mac); } else { ike_sa->server->context->cookie_secret_use_counter++; SSH_PUT_32BIT(packet->ed->ike_ed->cookie, ike_sa->server->context->cookie_version_number); status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM, ike_sa->server->context->cookie_secret, IKEV2_COOKIE_SECRET_LEN, &mac); } if (status != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_allocate(%s) failed: %s", IKEV2_COOKIE_MAC_ALGORITHM, ssh_crypto_status_message(status))); return SSH_IKEV2_ERROR_OUT_OF_MEMORY; } ssh_mac_reset(mac); ssh_mac_update(mac, packet->ed->nonce->nonce_data, packet->ed->nonce->nonce_size); SSH_IP_ENCODE(packet->remote_ip, buffer, len); ssh_mac_update(mac, buffer, len); ssh_mac_update(mac, packet->ike_spi_i, 8); status = ssh_mac_final(mac, packet->ed->ike_ed->cookie + 4); ssh_mac_free(mac); if (status != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_final(%s) failed: %s", IKEV2_COOKIE_MAC_ALGORITHM, ssh_crypto_status_message(status))); return SSH_IKEV2_ERROR_CRYPTO_FAIL; } #ifdef SSH_IKEV2_CRYPTO_KEY_DEBUG SSH_DEBUG_HEXDUMP(SSH_D_DATADUMP, ("Cookie generated"), packet->ed->ike_ed->cookie, packet->ed->ike_ed->cookie_len); #endif /* SSH_IKEV2_CRYPTO_KEY_DEBUG */ return SSH_IKEV2_ERROR_OK; }
Boolean ssh_packet_wrapper_input(SshPacketWrapper down) { size_t data_to_read, data_read; int ret; unsigned char *ptr; SshPacketType type; Boolean return_value = FALSE; for (;;) { /* If we cannot receive, return immediately. */ if (!down->can_receive || down->incoming_eof || down->destroy_pending || down->shortcircuit_up_stream != NULL) return return_value; /* Get length of data read so far. */ data_read = ssh_buffer_len(&down->incoming); /* Add enough space to buffer for reading either header or entire packet. This also sets `ptr' to point to the place where data should be read, and `data_to_read' to the number of bytes that should be there after reading (should read data_to_read - data_read bytes). */ if (data_read < 4) { /* Packet header not yet in buffer. Read only header. */ data_to_read = 4; ssh_buffer_append_space(&down->incoming, &ptr, 4 - data_read); } else { /* Packet header already in buffer. */ ptr = ssh_buffer_ptr(&down->incoming); data_to_read = 4 + SSH_GET_32BIT(ptr); if (data_to_read > 100000000L) ssh_fatal("ssh_packet_wrapper_input: " "invalid packet received: len %ld", (long)data_to_read); SSH_ASSERT(data_to_read > data_read); ssh_buffer_append_space(&down->incoming, &ptr, data_to_read - data_read); } /* Keep reading until entire packet read, or no more data available. */ while (data_read < data_to_read) { /* Try to read the remaining bytes. */ ptr = (unsigned char *)ssh_buffer_ptr(&down->incoming) + data_read; ret = ssh_stream_read(down->stream, ptr, data_to_read - data_read); if (ret < 0) { /* No more data available at this time. Remove allocated but unread space from end of buffer. */ ssh_buffer_consume_end(&down->incoming, data_to_read - data_read); return return_value; } if (ret == 0) { /* EOF received. */ ssh_buffer_consume_end(&down->incoming, data_to_read - data_read); down->incoming_eof = TRUE; /* Pass the EOF to the application callback. */ down->cannot_destroy = TRUE; if (down->received_eof) (*down->received_eof)(down->context); down->cannot_destroy = FALSE; if (down->destroy_requested) { ssh_packet_wrapper_destroy(down); return FALSE; } return TRUE; } if (data_read < 4 && data_read + ret >= 4) { /* Header has now been fully received. Prepare to receive rest of packet. */ data_read += ret; ptr = ssh_buffer_ptr(&down->incoming); data_to_read = 4 + SSH_GET_32BIT(ptr); if (data_to_read > 100000000L) ssh_fatal("ssh_packet_wrapper_input: " "invalid packet received: len %ld", (long)data_to_read); if (data_to_read > data_read) ssh_buffer_append_space(&down->incoming, &ptr, data_to_read - data_read); } else data_read += ret; } /* An entire packet has been received. */ SSH_ASSERT(ssh_buffer_len(&down->incoming) == data_to_read); /* Get packet type. */ ptr = ssh_buffer_ptr(&down->incoming); type = (SshPacketType)ptr[4]; /* Call the application callback if set. */ down->cannot_destroy = TRUE; if (down->received_packet) (*down->received_packet)(type, ptr + 5, data_to_read - 5, down->context); down->cannot_destroy = FALSE; if (down->destroy_requested) { ssh_packet_wrapper_destroy(down); return FALSE; } ssh_buffer_clear(&down->incoming); return_value = TRUE; } /*NOTREACHED*/ }
static Boolean ssh_engine_tcp_option_parse(SshUInt8 option_type, const unsigned char *buffer, size_t buf_len, SshTcpOption option_return) { SshUInt8 opt_len = 0; SSH_ASSERT(buffer != NULL); SSH_ASSERT(buf_len > 0); SSH_ASSERT(option_return != NULL); while (buf_len) { SshUInt8 kind = SSH_GET_8BIT(buffer); switch (kind) { case SSH_TCPOPT_EOL: goto not_found; case SSH_TCPOPT_NOP: opt_len = 1; break; case SSH_TCPOPT_MSS: if (buf_len < 4) goto invalid_len; opt_len = SSH_GET_8BIT(buffer+1); if (opt_len != 4) goto invalid_len; if (option_type == kind) { option_return->u.mss = SSH_GET_16BIT(buffer+2); SSH_DEBUG(SSH_D_MY5, ("MSS = %u", option_return->u.mss)); return TRUE; } break; case SSH_TCPOPT_WS: if (buf_len < 3) goto invalid_len; opt_len = SSH_GET_8BIT(buffer+1); if (opt_len != 3) goto invalid_len; if (option_type == kind) { option_return->u.ws = SSH_GET_8BIT(buffer+2); SSH_DEBUG(SSH_D_MY5, ("Window scale factor = %u", option_return->u.ws)); return TRUE; } break; case SSH_TCPOPT_TS: if (buf_len <= 10) goto invalid_len; opt_len = SSH_GET_8BIT(buffer+1); if (opt_len != 10) goto invalid_len; if (option_type == kind) { option_return->u.ts.ts = SSH_GET_32BIT(buffer+2); option_return->u.ts.ts_reply = SSH_GET_32BIT(buffer+6); SSH_DEBUG(SSH_D_MY5, ("Timestamp=%lu, Timestamp_reply=%ul", option_return->u.ts.ts, option_return->u.ts.ts_reply)); return TRUE; } break; default: if (buf_len < 2) /* At least 'kind' and 'len' fields */ goto invalid_len; opt_len = SSH_GET_8BIT(buffer+1); if (opt_len >= buf_len) goto invalid_len; break; } SSH_ASSERT(buf_len >= opt_len); buffer += opt_len; buf_len -= opt_len; } not_found: SSH_DEBUG(SSH_D_MY, ("TCP option (%u) not found", option_type)); return FALSE; invalid_len: SSH_DEBUG(SSH_D_NETGARB, ("Invalid TCP option length!")); return FALSE; }
void ikev2_fb_sa_handler(SshIkeNegotiation negotiation, SshIkePMPhaseQm pm_info, int number_of_sas, SshIkeIpsecSelectedSA sas, SshIkeIpsecKeymat keymat, void *sa_callback_context) { SshIkev2FbNegotiation neg; neg = SSH_IKEV2_FB_QM_GET_P1_NEGOTIATION(pm_info); if (neg == NULL) return; neg->ike_sa->last_input_stamp = ssh_time(); SSH_DEBUG(SSH_D_LOWOK, ("SA handler entered, IKE SA %p (neg %p)", pm_info->phase_i->policy_manager_data, neg)); if (number_of_sas != 1) { SSH_DEBUG(SSH_D_FAIL, ("Quick-Mode does not result in one bundle")); goto error; } if (neg->ed->callback) { int i, iproto; SshIkev2PayloadTransform *t; SshIkeIpsecSelectedProtocol p; SshIkeIpsecAttributeEncapsulationModeValues encap; /* Assert that `neg->qm_info' is set correctly. */ SSH_ASSERT(neg->qm_info == pm_info); for (i = 0; i < SSH_IKEV2_TRANSFORM_TYPE_MAX; i++) neg->ed->ipsec_ed->ipsec_sa_transforms[i] = &neg->transforms[i]; /* Fill in the selected transforms into ipsec_ed */ t = neg->ed->ipsec_ed->ipsec_sa_transforms; for (iproto = 0; iproto < sas[0].number_of_protocols; iproto++) { p = &sas[0].protocols[iproto]; if (p->protocol_id == SSH_IKE_PROTOCOL_IPSEC_ESP) { t[SSH_IKEV2_TRANSFORM_TYPE_ENCR]->id = ikev2_fb_v1_esp_id_to_v2_id(p->transform_id.generic); if (p->attributes.key_length) t[SSH_IKEV2_TRANSFORM_TYPE_ENCR]->transform_attribute = (0x800e << 16) | p->attributes.key_length; if (p->attributes.auth_algorithm) t[SSH_IKEV2_TRANSFORM_TYPE_INTEG]->id = ikev2_fb_v1_auth_id_to_v2_id(p->attributes.auth_algorithm); else t[SSH_IKEV2_TRANSFORM_TYPE_INTEG] = NULL; } else if (p->protocol_id == SSH_IKE_PROTOCOL_IPSEC_AH) { t[SSH_IKEV2_TRANSFORM_TYPE_INTEG]->id = ikev2_fb_v1_ah_id_to_v2_id(p->transform_id.generic); t[SSH_IKEV2_TRANSFORM_TYPE_ENCR] = NULL; } else if (p->protocol_id == SSH_IKE_PROTOCOL_IPCOMP) { if (p->spi_size_out == 2) { int j; for (j = 0; j < neg->ipcomp_num; j++) { if (neg->ipcomp_algs[j] == p->transform_id.ipcomp) { neg->ipcomp_num = 1; neg->ipcomp_algs[0] = p->transform_id.ipcomp; neg->ipcomp_cpi_out[0] = SSH_GET_16BIT(p->spi_out); break; } } } } if (p->attributes.group_desc) t[SSH_IKEV2_TRANSFORM_TYPE_D_H]->id = p->attributes.group_desc; else t[SSH_IKEV2_TRANSFORM_TYPE_D_H] = NULL; t[SSH_IKEV2_TRANSFORM_TYPE_ESN]->id = (p->attributes.longseq_size) ? SSH_IKEV2_TRANSFORM_ESN_ESN : SSH_IKEV2_TRANSFORM_ESN_NO_ESN; /* For initiator, notify policymanager about transport mode */ encap = p->attributes.encapsulation_mode; if (encap == IPSEC_VALUES_ENCAPSULATION_MODE_TRANSPORT || encap == IPSEC_VALUES_ENCAPSULATION_MODE_UDP_TRANSPORT || encap == IPSEC_VALUES_ENCAPSULATION_MODE_UDP_DRAFT_TRANSPORT) { (void) ikev2_fb_construct_notify(neg, 0, SSH_IKEV2_NOTIFY_USE_TRANSPORT_MODE, TRUE, 0, NULL, 0, NULL); } } if (neg->ipcomp_num > 0) { for (i = 0; i < neg->ipcomp_num; i++) { unsigned char data[3]; SSH_PUT_16BIT(data, neg->ipcomp_cpi_out[i]); data[2] = neg->ipcomp_algs[i]; (void) ikev2_fb_construct_notify(neg, 0, SSH_IKEV2_NOTIFY_IPCOMP_SUPPORTED, TRUE, 0, NULL, sizeof(data), data); } } } /* Set the outbound SPI to the IPSec exchange data */ if (sas->protocols[0].spi_size_out != 4) goto error; neg->ed->ipsec_ed->spi_outbound = SSH_GET_32BIT(sas->protocols[0].spi_out); SSH_DEBUG(SSH_D_LOWOK, ("Outbound SPI %lx", (unsigned long) neg->ed->ipsec_ed->spi_outbound)); if (!ikev2_fb_fill_keymat(neg->ed, negotiation, sas, keymat)) { SSH_DEBUG(SSH_D_FAIL, ("Cannot generate IKEv2 keying material")); goto error; } SSH_IKEV2_FB_V2_CALL(neg, ipsec_sa_install) (neg->server->sad_handle, neg->ed, ikev2_fb_ipsec_sa_install_done, neg); return; error: /* Even in the case of error, we call the IKEv2 SA installation policy call. The key material is cleared to ensure the installation will fail at the policy manager. */ ssh_free(neg->ed->ipsec_ed->ikev1_keymat); neg->ed->ipsec_ed->ikev1_keymat = NULL; neg->ed->ipsec_ed->ikev1_keymat_len = 0; SSH_IKEV2_FB_V2_CALL(neg, ipsec_sa_install) (neg->server->sad_handle, neg->ed, ikev2_fb_ipsec_sa_install_done, neg); }
int ssh_packet_impl_write(void *context, const unsigned char *buf, size_t size) { SshPacketImpl up = (SshPacketImpl)context; size_t offset, payload_len, len; unsigned char *ucp; /* If shortcircuiting, direct the write down. */ if (up->shortcircuit_stream) { SSH_ASSERT(ssh_buffer_len(&up->incoming) == 0); return ssh_stream_write(up->shortcircuit_stream, buf, size); } offset = 0; normal: while (up->can_receive && !up->incoming_eof && offset < size && !up->shortcircuit_stream) { /* If already processing a partial packet, continue it now. */ if (ssh_buffer_len(&up->incoming) > 0) goto partial; /* If only partial packet available, do special proccessing. */ if (size - offset < 4) goto partial; /* Need partial packet processing. */ payload_len = SSH_GET_32BIT(buf + offset); if (payload_len < 1) goto partial; if (size - offset < 4 + payload_len) goto partial; /* Need partial packet processing. */ /* The entire packet is available; pass it to the callback. */ if (up->received_packet) (*up->received_packet)((SshPacketType)buf[offset + 4], buf + offset + 5, payload_len - 1, up->context); offset += 4 + payload_len; } /* We cannot take more data now. If we processed some data, return the number of bytes processed. */ if (offset > 0) return offset; /* We couldn't take any data. Remember that we have returned error to the writer and must call the callback later. */ up->up_write_blocked = TRUE; return -1; partial: /* Process partial packet. First we read its header. */ len = ssh_buffer_len(&up->incoming); if (len < 4) { len = 4 - len; if (size - offset < len) len = size - offset; if (ssh_buffer_append(&up->incoming, buf + offset, len) != SSH_BUFFER_OK) { (*up->received_eof)(up->context); return 0; } offset += len; } if (ssh_buffer_len(&up->incoming) < 4) return offset; /* Get the length of the packet. */ ucp = ssh_buffer_ptr(&up->incoming); payload_len = SSH_GET_32BIT(ucp); if (payload_len < 1) { /* Received an invalid packet with length = 0, even though we should always have at least the packet type. */ (*up->received_eof)(up->context); return 0; } /* Add remaining data in the packet to the buffer. */ len = 4 + payload_len - ssh_buffer_len(&up->incoming); if (len > size - offset) len = size - offset; if (ssh_buffer_append(&up->incoming, buf + offset, len) != SSH_BUFFER_OK) { (*up->received_eof)(up->context); return 0; } offset += len; /* If some data still not available, return. */ if (ssh_buffer_len(&up->incoming) < 4 + payload_len) return offset; /* The entire packet is now in buffer. */ ucp = ssh_buffer_ptr(&up->incoming); if (up->received_packet) (*up->received_packet)((SshPacketType)ucp[4], ucp + 5, payload_len - 1, up->context); /* Clear the incoming partial packet buffer and resume normal processing. */ ssh_buffer_clear(&up->incoming); goto normal; }
SshCryptoStatus ssh_gcm_init(void *context, const unsigned char *key, size_t keylen, Boolean for_encryption, const SshCipherDefStruct *cipher_def, size_t table_size) { SshGCMCtx *created = context; SshCryptoStatus status; unsigned char encr_zero[16]; unsigned char dummy_iv[16]; int i; SSH_DEBUG(SSH_D_LOWOK, ("Entered")); memset(dummy_iv, 0, sizeof(dummy_iv)); if (cipher_def->block_length != 16) { SSH_DEBUG(SSH_D_FAIL, ("Block sizes other than 128 bits not supported")); return SSH_CRYPTO_BLOCK_SIZE_ERROR; } memset(created, 0, sizeof(*created)); created->for_encryption = (SshUInt8)for_encryption; created->cipher_def = cipher_def; created->cipher_context = (unsigned char *)created + sizeof(SshGCMCtx); status = (*created->cipher_def->init)(created->cipher_context, key, keylen, TRUE); if (status == SSH_CRYPTO_OK) { memset(encr_zero, 0, sizeof(encr_zero)); status = (*created->cipher_def->transform)(created->cipher_context, encr_zero, encr_zero, sizeof(encr_zero), dummy_iv); } if (status != SSH_CRYPTO_OK) { #ifdef KERNEL SSH_DEBUG(SSH_D_FAIL, ("Cipher initialization failed status=%u", (unsigned int)status)); #else /* !KERNEL */ SSH_DEBUG(SSH_D_FAIL, ("Cipher transform failed status=%s", ssh_crypto_status_message(status))); #endif /* KERNEL */ return status; } created->mod = (1 << 31) + (1 << 30) + (1 << 29) + (1 << 24); created->H[0] = SSH_GET_32BIT(encr_zero); created->H[1] = SSH_GET_32BIT(encr_zero + 4); created->H[2] = SSH_GET_32BIT(encr_zero + 8); created->H[3] = SSH_GET_32BIT(encr_zero + 12); switch (table_size) { case 0: created->update_block = gcm_update_block; created->workspace = NULL; break; case 65536: created->update_block = gcm_update_block_words_table; created->workspace = (unsigned char *)created + sizeof(SshGCMCtx) + (*cipher_def->ctxsize)(); for (i = 0; i < 16; i++) ssh_gf2n_128_table_byte_init((unsigned char *)created->workspace + i * 256 * sizeof(SshUInt32[4]), created->H, created->mod, i); created->table_64k = 1; break; case 8192: created->update_block = gcm_update_block_words_nibble; created->workspace = (unsigned char *)created + sizeof(SshGCMCtx) + (*cipher_def->ctxsize)(); for (i = 0; i < 32; i++) ssh_gf2n_128_table_nibble_init((unsigned char *)created->workspace + i * 16 * sizeof(SshUInt32[4]), created->H, created->mod, i); created->table_8k = 1; break; case 4096: created->update_block = gcm_update_block_shoup_8_bit; created->workspace = (unsigned char *)created + sizeof(SshGCMCtx) + (*cipher_def->ctxsize)(); ssh_gf2n_128_table_byte_init(created->workspace, created->H, created->mod, 0); created->table_4k = 1; break; case 256: created->update_block = gcm_update_block_shoup_4_bit; created->workspace = (unsigned char *)created + sizeof(SshGCMCtx) + (*cipher_def->ctxsize)(); ssh_gf2n_128_table_nibble_init(created->workspace, created->H, created->mod, 0); created->table_256 = 1; break; default: return SSH_CRYPTO_UNSUPPORTED; } return SSH_CRYPTO_OK; }
static void sha_transform(SshSHAContext *context, const unsigned char *block) { static SshUInt32 W[80]; SshUInt32 a, b, c, d, e, f; a = context->A; b = context->B; c = context->C; d = context->D; e = context->E; #if 1 /* Unroll as much as one can, removing unneccessary copying etc. What actually happens is that the compiler must interleave all these operations some efficient way. On processors with only few registers it might be better to implement the table generation before actual 'nonlinear' operations. On Intel processors that might be the case, although one never knows without trying. */ #define TABLE_IN(i) \ W[i] = SSH_GET_32BIT(block); block += 4; #define TABLE_MORE(i, t) \ t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; \ W[i] = ROLL_1(t); #define NONLINEAR1(F, a, b, c, d, e, f, i) \ TABLE_IN(i); \ f = ROLL_5(a); \ f += F(b, c, d); \ b = ROLL_30(b); \ f += e + W[i]; #define NONLINEAR2(F, a, b, c, d, e, f, i) \ TABLE_MORE(i, f); \ f = ROLL_5(a); \ f += F(b, c, d); \ b = ROLL_30(b); \ f += e + W[i]; NONLINEAR1(F1, a, b, c, d, e, f, 0); NONLINEAR1(F1, f, a, b, c, d, e, 1); NONLINEAR1(F1, e, f, a, b, c, d, 2); NONLINEAR1(F1, d, e, f, a, b, c, 3); NONLINEAR1(F1, c, d, e, f, a, b, 4); NONLINEAR1(F1, b, c, d, e, f, a, 5); NONLINEAR1(F1, a, b, c, d, e, f, 6); NONLINEAR1(F1, f, a, b, c, d, e, 7); NONLINEAR1(F1, e, f, a, b, c, d, 8); NONLINEAR1(F1, d, e, f, a, b, c, 9); NONLINEAR1(F1, c, d, e, f, a, b, 10); NONLINEAR1(F1, b, c, d, e, f, a, 11); NONLINEAR1(F1, a, b, c, d, e, f, 12); NONLINEAR1(F1, f, a, b, c, d, e, 13); NONLINEAR1(F1, e, f, a, b, c, d, 14); NONLINEAR1(F1, d, e, f, a, b, c, 15); NONLINEAR2(F1, c, d, e, f, a, b, 16); NONLINEAR2(F1, b, c, d, e, f, a, 17); NONLINEAR2(F1, a, b, c, d, e, f, 18); NONLINEAR2(F1, f, a, b, c, d, e, 19); NONLINEAR2(F2, e, f, a, b, c, d, 20); NONLINEAR2(F2, d, e, f, a, b, c, 21); NONLINEAR2(F2, c, d, e, f, a, b, 22); NONLINEAR2(F2, b, c, d, e, f, a, 23); NONLINEAR2(F2, a, b, c, d, e, f, 24); NONLINEAR2(F2, f, a, b, c, d, e, 25); NONLINEAR2(F2, e, f, a, b, c, d, 26); NONLINEAR2(F2, d, e, f, a, b, c, 27); NONLINEAR2(F2, c, d, e, f, a, b, 28); NONLINEAR2(F2, b, c, d, e, f, a, 29); NONLINEAR2(F2, a, b, c, d, e, f, 30); NONLINEAR2(F2, f, a, b, c, d, e, 31); NONLINEAR2(F2, e, f, a, b, c, d, 32); NONLINEAR2(F2, d, e, f, a, b, c, 33); NONLINEAR2(F2, c, d, e, f, a, b, 34); NONLINEAR2(F2, b, c, d, e, f, a, 35); NONLINEAR2(F2, a, b, c, d, e, f, 36); NONLINEAR2(F2, f, a, b, c, d, e, 37); NONLINEAR2(F2, e, f, a, b, c, d, 38); NONLINEAR2(F2, d, e, f, a, b, c, 39); NONLINEAR2(F3, c, d, e, f, a, b, 40); NONLINEAR2(F3, b, c, d, e, f, a, 41); NONLINEAR2(F3, a, b, c, d, e, f, 42); NONLINEAR2(F3, f, a, b, c, d, e, 43); NONLINEAR2(F3, e, f, a, b, c, d, 44); NONLINEAR2(F3, d, e, f, a, b, c, 45); NONLINEAR2(F3, c, d, e, f, a, b, 46); NONLINEAR2(F3, b, c, d, e, f, a, 47); NONLINEAR2(F3, a, b, c, d, e, f, 48); NONLINEAR2(F3, f, a, b, c, d, e, 49); NONLINEAR2(F3, e, f, a, b, c, d, 50); NONLINEAR2(F3, d, e, f, a, b, c, 51); NONLINEAR2(F3, c, d, e, f, a, b, 52); NONLINEAR2(F3, b, c, d, e, f, a, 53); NONLINEAR2(F3, a, b, c, d, e, f, 54); NONLINEAR2(F3, f, a, b, c, d, e, 55); NONLINEAR2(F3, e, f, a, b, c, d, 56); NONLINEAR2(F3, d, e, f, a, b, c, 57); NONLINEAR2(F3, c, d, e, f, a, b, 58); NONLINEAR2(F3, b, c, d, e, f, a, 59); NONLINEAR2(F4, a, b, c, d, e, f, 60); NONLINEAR2(F4, f, a, b, c, d, e, 61); NONLINEAR2(F4, e, f, a, b, c, d, 62); NONLINEAR2(F4, d, e, f, a, b, c, 63); NONLINEAR2(F4, c, d, e, f, a, b, 64); NONLINEAR2(F4, b, c, d, e, f, a, 65); NONLINEAR2(F4, a, b, c, d, e, f, 66); NONLINEAR2(F4, f, a, b, c, d, e, 67); NONLINEAR2(F4, e, f, a, b, c, d, 68); NONLINEAR2(F4, d, e, f, a, b, c, 69); NONLINEAR2(F4, c, d, e, f, a, b, 70); NONLINEAR2(F4, b, c, d, e, f, a, 71); NONLINEAR2(F4, a, b, c, d, e, f, 72); NONLINEAR2(F4, f, a, b, c, d, e, 73); NONLINEAR2(F4, e, f, a, b, c, d, 74); NONLINEAR2(F4, d, e, f, a, b, c, 75); NONLINEAR2(F4, c, d, e, f, a, b, 76); NONLINEAR2(F4, b, c, d, e, f, a, 77); NONLINEAR2(F4, a, b, c, d, e, f, 78); NONLINEAR2(F4, f, a, b, c, d, e, 79); /* Remember the correct order of rotated variables. */ context->A += e; context->B += f; context->C += a; context->D += b; context->E += c; #else /* Inefficient version (but actually not that slow, only slightly slower than the above one). */ /* t is not currently defined so you need to define that if want to use these routines. */ for (t = 0; t < 16; t++) { W[t] = SSH_GET_32BIT(block); block += 4; } for (t = 16; t < 80; t++) { f = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; W[t] = ROLL_1(f); } for (t = 0; t < 80; t++) { f = ROLL_5(a); if (t < 40) { if (t < 20) f += F1(b, c, d); else f += F2(b, c, d); } else { if (t < 60) f += F3(b, c, d); else f += F4(b, c, d); } f += e + W[t]; f &= 0xFFFFFFFFL; e = d; d = c; c = ROLL_30(b); b = a; a = f; } context->A += a; context->B += b; context->C += c; context->D += d; context->E += e; #endif /* unrolled. */ context->A &= 0xFFFFFFFFL; context->B &= 0xFFFFFFFFL; context->C &= 0xFFFFFFFFL; context->D &= 0xFFFFFFFFL; context->E &= 0xFFFFFFFFL; }
void *ssh_xrealloc(void *ptr, unsigned long new_size) { void *new_ptr; if (ptr == NULL) return ssh_xmalloc(new_size); if (new_size > XMALLOC_MAX_SIZE) ssh_fatal("ssh_xrealloc: allocation too large (allocating %ld bytes)", (long)new_size); if (new_size == 0) new_size = 1; #ifdef SSH_DEBUG_MALLOC if (SSH_GET_32BIT((unsigned char *) ptr - 4) != SSH_DEBUG_MALLOC_MAGIC_IN_USE) { if (SSH_GET_32BIT((unsigned char *) ptr - 4) == SSH_DEBUG_MALLOC_MAGIC_FREED) ssh_fatal("Reallocating block that is already freed"); ssh_fatal("Reallocating block that is either not mallocated, or whose magic number before the object was overwritten"); } else { unsigned long old_size; old_size = SSH_GET_32BIT((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); if (SSH_GET_32BIT((unsigned char *) ptr + old_size) != SSH_DEBUG_MALLOC_MAGIC_AFTER) ssh_fatal("Reallocating block whose magic number after the object was overwritten"); /* Mark the old block freed */ SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED); SSH_PUT_32BIT((unsigned char *) ptr + old_size, SSH_DEBUG_MALLOC_MAGIC_FREED); new_ptr = (void *)realloc((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE, (size_t) new_size + SSH_DEBUG_MALLOC_SIZE_BEFORE + SSH_DEBUG_MALLOC_SIZE_AFTER); if (new_ptr == NULL) ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)", (long)new_size); SSH_PUT_32BIT(new_ptr, new_size); SSH_PUT_32BIT((unsigned char *) new_ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE); SSH_PUT_32BIT((unsigned char *) new_ptr + new_size + SSH_DEBUG_MALLOC_SIZE_BEFORE, SSH_DEBUG_MALLOC_MAGIC_AFTER); new_ptr = (unsigned char *) new_ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE; } #else /* SSH_DEBUG_MALLOC */ new_ptr = (void *)realloc(ptr, (size_t) new_size); if (new_ptr == NULL) ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)", (long)new_size); #endif /* SSH_DEBUG_MALLOC */ return new_ptr; }
void gcm_update_block_shoup_4_bit(void *context, const unsigned char *buf) { SshGCMCtx *ctx = (SshGCMCtx *)context; SshUInt32 *m = ctx->workspace; SshUInt32 *X = ctx->X; SshUInt32 i, t[4]; unsigned char w; X[0] ^= SSH_GET_32BIT(buf); X[1] ^= SSH_GET_32BIT(buf + 4); X[2] ^= SSH_GET_32BIT(buf + 8); X[3] ^= SSH_GET_32BIT(buf + 12); t[0] = t[1] = t[2] = t[3] = 0; i = 0; #ifdef MINIMAL_STACK while (i < 28) { GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 31 - i); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 30 - i); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 29 - i); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 28 - i); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); i+= 4; } GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 3); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 2); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 1); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); /* No carry after the last multiplication */ GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 0); #else /* MINIMAL_STACK */ GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 31); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 30); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 29); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 28); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 27); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 26); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 25); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 24); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 23); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 22); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 21); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 20); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 19); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 18); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 17); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 16); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 15); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 14); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 13); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 12); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 11); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 10); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 9); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 8); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 7); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 6); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 5); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 4); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 3); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 2); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 1); GF2N_128_TABLE_SHOUP_4_BIT_MUL_POW(t, w); /* No carry after the last multiplication */ GF2N_128_TABLE_SHOUP_4_BIT_MUL(t, X, m, 0); #endif /* MINIMAL_STACK */ X[0] = t[0]; X[1] = t[1]; X[2] = t[2]; X[3] = t[3]; }
/* This function reads complete payload from the HTTP stream described at the context argument (also the thread running this session is identified b the context's upper context), and calls the input processing thread when done. This gets called when the CA replies to the clients message or poll. */ static void pkix_http_stream_callback(SshStreamNotification not, void *context) { int i; size_t len; SshUInt8 type_or_version; unsigned char input[256], *data; PkixHttpReadContext c = (PkixHttpReadContext)context; SshFSMThread thread = (SshFSMThread) c->upper_context; SshPkiThreadData tdata = ssh_fsm_get_tdata(thread); SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread); while (TRUE) { i = ssh_stream_read(c->http_stream, input, sizeof(input)); if (i == 0) { if ((len = ssh_buffer_len(c->input)) > 5) { data = ssh_buffer_ptr(c->input); len = SSH_GET_32BIT(data); type_or_version = data[4]; if (type_or_version < 10) { tdata->input_version = SSH_PKI_VERSION_0; tdata->input_flags = 0; tdata->input_type = type_or_version; tdata->input_len = len - 1; tdata->input = ssh_memdup(data + 5, tdata->input_len); } else { if (type_or_version == 10) { data += 4; /* skip to end of length */ tdata->input_version = SSH_PKI_VERSION_1; tdata->input_len = len - 3; tdata->input_flags = data[1]; tdata->input_type = data[2]; data += 3; tdata->input = ssh_memdup(data, tdata->input_len); } else { tdata->input_version = type_or_version; tdata->input_type = SSH_PKI_MSG_ERRORREP; } } if (tdata->input == NULL) tdata->input_type = SSH_PKI_MSG_ERRORREP; ssh_buffer_free(c->input); ssh_stream_destroy(c->http_stream); ssh_fsm_continue(gdata->input_thread); ssh_free(c); return; } else { error: tdata->input_type = SSH_PKI_MSG_ERRORREP; ssh_fsm_set_next(thread, pkix_aborted); ssh_fsm_continue(gdata->input_thread); ssh_stream_destroy(c->http_stream); ssh_buffer_free(c->input); ssh_free(c); return; } } else if (i < 0) { return; } else { if (ssh_buffer_append(c->input, input, i) != SSH_BUFFER_OK) { goto error; } } } }