/* * Some browsers use a hybrid SSLv2 "client hello" */ int process_sslv23_client_hello(SSL *ssl) { uint8_t *buf = ssl->bm_data; int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1]; int ret = SSL_OK; /* we have already read 3 extra bytes so far */ // int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3); int read_len = pbuf_copy_partial(ssl->ssl_pbuf, buf, bytes_needed - 3, 0); int cs_len = buf[1]; int id_len = buf[3]; int ch_len = buf[5]; int i, j, offset = 8; /* start at first cipher */ int random_offset = 0; DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len); add_packet(ssl, buf, read_len); /* connection has gone, so die */ if (bytes_needed < 0) { return SSL_ERROR_CONN_LOST; } /* now work out what cipher suite we are going to use */ for (j = 0; j < NUM_PROTOCOLS; j++) { for (i = 0; i < cs_len; i += 3) { if (ssl_prot_prefs[j] == buf[offset + i]) { ssl->cipher = ssl_prot_prefs[j]; goto server_hello; } } } /* ouch! protocol is not supported */ ret = SSL_ERROR_NO_CIPHER; goto error; server_hello: /* get the session id */ offset += cs_len - 2; /* we've gone 2 bytes past the end */ #ifndef CONFIG_SSL_SKELETON_MODE ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions, ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL); #endif /* get the client random data */ offset += id_len; /* random can be anywhere between 16 and 32 bytes long - so it is padded * with 0's to the left */ if (ch_len == 0x10) { random_offset += 0x10; } memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len); ret = send_server_hello_sequence(ssl); error: return ret; }
/* * Process the handshake record. */ int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) { int ret = SSL_OK; ssl->hs_status = SSL_NOT_OK; /* not connected */ /* To get here the state must be valid */ switch (handshake_type) { case HS_CLIENT_HELLO: if ((ret = process_client_hello(ssl)) == SSL_OK) ret = send_server_hello_sequence(ssl); break; #ifdef CONFIG_SSL_CERT_VERIFICATION case HS_CERTIFICATE:/* the client sends its cert */ ret = process_certificate(ssl, &ssl->x509_ctx); if (ret == SSL_OK) /* verify the cert */ { int cert_res; int pathLenConstraint = 0; cert_res = x509_verify(ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx, &pathLenConstraint); ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res); } break; case HS_CERT_VERIFY: ret = process_cert_verify(ssl); add_packet(ssl, buf, hs_len); /* needs to be done after */ break; #endif case HS_CLIENT_KEY_XCHG: ret = process_client_key_xchg(ssl); break; case HS_FINISHED: ret = process_finished(ssl, buf, hs_len); disposable_free(ssl); /* free up some memory */ break; } return ret; }