Meta

Browsing Android Files using Bluetooth

One of the casual uses of Bluetooth under Android, is just to pair devices with our Android (host) device, so that specific apps can use the paired (slave) device. This includes BT-headphones, and many other devices.

But then a slightly more advanced use for BT under Android could be, that we actually send files to a paired Android device. It’s casually possible to take two Android tablets, or a tablet and a phone, and to pair those with each other. After that, the way to ‘push’ a file to the paired device, from the originating device, is to open whichever app displays files – such as for example, the Gallery app, if users still have that installed, or a suitable file-manager app – and to tap on ‘Share’, and then select ‘Bluetooth’ as what to share the file to. Doing this should open a list of paired devices, one of which should be suitable to receive a pushed file in this way.

But then, some people would like to take Bluetooth file-sharing up another level. We can pair our Android device – such as our phone – with a Bluetooth-equipped, Linux computer, which may be a bit tricky in itself, because the GUI we usually use for that assumes some legacy form of pairing. But eventually, we can set up a pairing as described. What I need to do is select the option in my Linux-BT-pairing GUI, which requires me to enter the pass-code into the Linux-GUI, which my Android device next displays…

And then, a question which many users find asking themselves is, ‘Why can’t I obtain FTP-like browsing capability, from my Linux-computer, over the files on the phone? Am I not giving the correct commands, from my Linux-computer?’

Chances are high, that any user who wishes to do this, is already giving the correct commands from his or her Linux-computer…

(Updated 06/03/2018, 20h45 … )

(As of 05/31/2018 : )

I think that what mainly goes wrong with this, has to do with the security-policy of the Android phone. I can already ‘Send A File’ to the connected device – thus pushing that file – from Linux. But what Android will always want to do, is ask permission from its user, on a file-by-file basis, to receive such a file. According to Android, the fact that the devices are paired with encryption, does not provide enough security by itself, to authorize that a connecting device be able to browse the files and folders of the other device, and another layer of restrictions is typically set. So what I see on my Linux-laptop, which I name ‘Klystron’, is presently this:

So what we see is that my phone is paired, but it has no ‘colored bars’, which effectively means that no data is being exchanged, and the phone counts as ‘not connected’. But it has a little key-inset in its icon, meaning that the paring is encrypted, and it has a star, which means it’s a Linux-trusted device.

As the reader can see, ‘Send a File’ is available, but ‘Browse Device’ is ghosted. If I click on ‘Send a File’ here, a dialog opens on my Linux-laptop, from where I can choose which file to push, and once I’ve selected the file, my phone will display a noisy confirmation-window, asking whether to accept the transfer. If I tap on ‘Accept’ on my phone, the file is transferred, and I’ve tested this many times. Each time, the colored bars also appear briefly on the Linux-laptop. Actually, I’ve discovered that on my Pixel C Tablet, if I somehow fumble, and tap on ‘Refuse’, in addition to refusing one file-transfer, that tablet will next turn off my Bluetooth, because according to a certain logic, the tablet could be under some form of attack.

If the user wants to be able to browse his phone – or paired tablet – Then he must first give permission under Android ! And on some Android devices that support it, this is decided when the devices are paired. On Android devices that support it, when they display the initial dialog box, to pair, in the lower, left-hand corner, there is a check-box which many users fail to notice, and which is not checked off by default. We’re usually so hectic when trying several times to pair devices, that we may fail to notice the little check-box, that Android may show us.

If we tick this check-box, when pairing, it will give permission to the paired device, to browse some of the current device’s contents. After that, the methods used by many other Linux-users, should work.

Those methods may not use the GUI, rather the command-line, and one way to prepare the Linux-computer, is to have the package installed, which is called ‘obexfs’ (in addition to the suite of ‘bluez’ packages). Then, the following should also work:

The last line shown above, should create a mount-point within my home-directory, where I could browse my phone’s folders. BTW, since ‘obexfs’ uses the ‘fusermount’ capability, in order for this really to work, the present user needs to belong to the ‘fuse’ group. Otherwise, root permissions would be needed to carry out the mount.

And the reader should remember, that if he or she just adds the group to the user, then he or she also needs to log out, and log back in again, before the user inherits the group-membership into the new session.

NB: My ‘Samsung Galaxy S6 Phone’, which is presently running Stock Android 7.0 , does not support this, and will therefore also never show me the check-box which I’m writing about. My ‘Google Pixel C Tablet’, which is presently running Stock Android 8.1 , supports something similar, and always shows me a check-box, when I’m Bluetooth-pairing, which I habitually ignore. That check-box says, ‘Share Contacts (Information)…’ It does not actually show ‘Share Files’. And, the ability to Share Contacts in this way, can also be deactivated and reactivated, after the pairing has already been established. It just does not allow my Linux client to browse files.

What some Linux-users may prefer, is to install a 3rd-party Obex-client on their tablet or phone, and This would be an excellent example of a working, Android, Obex-client. Of course, it assumes that the paired device is running an Obex-server, and what Google Play does at present, is suppress any Obex-server software, for Android devices. But of course, on a PC or laptop, we have options.

What I find works for me, is to run the program ‘obexd’ manually, on my Linux-laptop, by typing the following command:

dirk@Klystron:~$ /usr/lib/bluetooth/obexd

Because I did not put the ampersand after this shell-command, I next get to see a blinking cursor, but that already works for testing purposes, because if I want to kill this server, I can just type <Ctrl>+C. But then what will happen next, is that I can connect to this Linux-hosted server via Bluetooth, and obtain FTP-like capability, using the Android-client mentioned above. This works 100%.

If users want this enabled 24/7, they can adapt the command-line to run as the user, as desired. One fact which may confuse some users, is where the root-directory resides on the server, which we see in our Android-BT-client. And the answer is, that ‘obexd’ will always make that directory:

~/.cache/obexd

This kind of puts Bluetooth-sharing into a convenient jail, and if we need to access that directory easily on the Linux host, we can just create a symlink to it. I do not recommend putting a symlink inside this directory, that would point directly to the user’s (Linux) home directory, as doing so would create too much of a security risk. ( :1 )

As for the question of whether this gives the Linux-based server enough security, that would be in the pairing of the Bluetooth-connected device. As Google has already observed, the user-procedure for Bluetooth-pairing has been simplified so much, that a given user could ‘Accept’ an unwanted pairing, just by tapping on the wrong icons a few times.

Also, I should point out the fact, that Bluetooth is much slower than WiFi, typically possessing speeds more-similar to the old dialup-speeds, which may limit its usefulness. And the additional fact that Bluetooth is so short-ranged, that it barely allows access to my laptop, when I’m sitting directly in front of it, also makes it perfectly feasible for me to activate the Obex-daemon manually, every time I want to use it…

Some users suggest instead, that we run:

obexpushd

As user. But, I see two disadvantages in doing so:

This would only allow the PC or laptop to receive single files that are pushed to it, much like Android devices now do. Having FTP-like capabilities is more versatile.

‘obexpushd’ gets into a conflict with ‘obex-data-server’ when run. And in my opinion, the latter of these services should in fact be running.

1: )

There is not only the question of an unwanted device being paired. There is also the question of the user doing the footwork, of establishing a secure encryption-channel, but one of the devices having hidden, malicious functionality. Simply on the basis that they’re paired, according to older assumptions, such a device would also achieve access to all the files on the other device, which is acting as the FTP-server. And such access would include the ability to delete or alter contents…

(Update 06/01/2018, 18h50 : )

The way the ‘old-fashioned’ method of Bluetooth-pairing worked, a device requesting to pair would display a PIN code, which the user was expected to enter, on the device which was receiving the pairing request. This PIN code actually formed a part of the encryption. The requesting device generated an additional field of information, consisting of pseudo-random bits, and this PIN code was effectively appended to it, so that the hash-code from the resulting, full-length field, could be used as the symmetrical encryption key. This smaller field of bits was just transmitted, while the PIN code was not.

That way, if a hypothetical eavesdropper had failed to eavesdrop on the actual pairing-procedure, the encryption was as strong as either the hash-code, or as the full-length field of bits. But, if the eavesdropper had in fact caught the pairing-procedure itself, the encryption would only be as strong, as the PIN code, since then, the eavesdropper would have intercepted everything else.

The modern encryption procedure is such, that both the requesting and the receiving device simply display a PIN code, which the user needs to Acknowledge on both devices. It’s fully plausible that this still leads to a secure pairing procedure, due to a development called “Diffie-Hellman Key Exchange“. If the reader next wonders, why then, he’s only shown a 6-digit PIN code to Acknowledge, in fact, arbitrarily-long binary numbers can be put into the modulus of (1,000,000) 999,999 , so that maximally a 6-digit decimal number results.

The part of this process which I’m not sure about, is whether modern BT-pairing derives the entire symmetrical key through Diffie-Hellman, or only a 32-bit suffix. The advantage of only using D-H to establish a 32-bit suffix, where the PIN code used to go, would be that 32-bit, unsigned multiplication is relatively cheap on modern CPUs, and even on some appliances. And unsigned multiplication can lead to modulus-exponentiation. With D-H, the modulus should be prime, and the original base a root of that modulus. Then, two 32-bit integers could be multiplied, to result in a 64-bit value, stored in two CPU registers. Next, integer division by the 32-bit modulus will yield a 32-bit remainder, which completes a modulus-multiplication. This can all happen within only a few CPU-cycles, even on a 32-bit CPU. ( :2 )

On some Linux computers like my Debian / Jessie systems, I’m under the impression that only the GUI is outdated, not the underlying Bluetooth programs. And so the way to get the Android device paired to a Linux laptop, for example, was like this:

Create the Pairing Dialog on both devices. This requires making them both visible, selecting to Set Up the Device on the laptop, and tapping on the entry corresponding to the laptop, on the Android device.

Copy the PIN code which the Android device is asking us to Acknowledge, into the field in the pairing dialog, where the laptop is showing us conventional pairing. Don’t click on anything else yet, on the laptop.

Tap the Acknowledge icon in the Android device’s dialog.

In the notification tray of the laptop, look for the notification, telling the user that a device wants to pair. Click ‘Acknowledge’, belonging to that notification.

At that point, the entry corresponding to the laptop in the Android device’s dialog should already move into the Paired Devices list.

Click the Next button, in the laptop’s pairing dialog, where the PIN code has already been typed.

And with some luck and patience, this worked for me, after the second try.

2: )

While I consider it ‘normal’, that fully-capable 32-bit CPUs include integer multiply, and 64-bit by 32-bit divide like that, it should be mentioned, that the high-level languages such as C and C++ don’t actually support that out-of-the-box. The reason for this would be, the fact that the way Math operations are prototyped in C and C++ , between two operands of ‘higher’ and ‘lower’ types, both operands are first cast to the higher of the two types.

Thus, when we multiply a 32-bit integer with a 32-bit floating-point number, C and C++ will first convert the integer to a floating-point number. Similarly, if we try to divide a 64-bit integer by a 32-bit integer in C or C++ , the 32-bit integer is first “cast” to a 64-bit integer, so that what the compiler will try to do next, is divide a 64-bit integer by a 64-bit integer. Unless we have a 64-bit CPU then, this will require subroutines that break down the operation into smaller pieces.

What some programmers need to know, is the logic with which such operations are broken down into smaller words.

Eventually, the logic needs to be solved, how to perform arithmetic on arbitrarily-long binary numbers, at least integers. The best way to visualize this, is to imagine that we’re taking grade-school Math again, and that we need to re-learn long division, or multiplication by hand. The only difference would be, that instead of working with single digits that are in Base-10, we might be assuming that our RISC-chip CPU is maximally capable of dividing a 32-bit integer by another 32-bit integer, or multiplying two 32-bit integers, to result in a 32-bit integer. So, we’d be doing the same thing, in Base-216.

I, personally find this a difficult exercise. The main reason would be such observations, as that I can perform the task intuitively, but do not know the steps my own brain is taking anymore. I think when I was younger, I would always make it a point to be aware of the small steps which my brain was taking. Thus, long division requires as a sub-task, simple division. And I can conclude in Base-10, by inspection, that the result of the following, simple division, is, (readers may need to enable scripts from ‘mathjax.org’) :

The problem with this is, that I tend to look at the most significant words of the numbers I want to divide, 19 by 9, and to guess that 19 is divisible by 9 giving a quotient of 2. But, multiplying the full-length divisor by 2 would leave an unknown word to be carried, for which reason 99 does not go twice into 197. I can solve it, but do not know the detailed steps that my brain went through, to solve this.

When writing arbitrary-precision libraries, the programmers actually need to know this. I think that the most-promising way to solve this in Base-n would be, to devise a simple division algorithm, which works roughly like this:

Accept as parameters, the dividend and divisor in full-length format.

Initialize the cumulative quotient to 0.

Multiply the full-length divisor by the cumulative quotient, replacing the cumulative remainder, with the dividend minus the product.

Extract the most-significant 2 words from the cumulative remainder (in fixed position) and the most-significant 1 word from the divisor.

Add 1 to the most-significant divisor-word.

Divide the most-significant remainder-words by the most-significant divisor word, adding the resulting quotient to the cumulative quotient.

Repeat steps (3 – 6) until the result from step (6) is a temporary quotient of zero.

If the cumulative remainder is greater than or equal to the divisor, add (1) to the cumulative quotient, and subtract the divisor from the cumulative remainder.

Thus, to divide 99 by 1 in Base-10 would yield the temporary quotients (49, 25, 12, 6, 3, 2, 1, 0), followed by the subtraction, which would seem inefficient. To divide 990 by 19 in Base-10 would yield the temporary quotients (49, 2, 1, 0), followed by no subtraction, giving a quotient of 52 and a remainder of 2. But in Base-216, the number of attempts could be made much smaller than 232 in this way, since each attempt approximately halves the remainder.

This example assumes that the divisor is maximally 1 word smaller than the dividend. If this is not the case, then long division needs to be used. ( :3 )

In the example which I raised earlier in this posting, a word-size of 32-bits was assumed, but, more importantly, all that was really required was to multiply two values, each initially 1 word long, within a 1 word modulus. And it was assumed that a 32-bit modulus, for example, would have the most-significant bit of its word set to 1, not 0. This greatly simplifies the exercise. What could then be done, is that a long multiplication could be carried out between the two 1-word operands, resulting in a 2-word original product.

Because the modulus itself was only 1 word long, it could be assumed that the most-significant word of the equivalent divisor would actually be zeroes. The most-significant word of the original product could be taken to be the temporary quotient, and it could be multiplied by the modulus, to result in a 2-word temporary product. This in turn could be subtracted from the original product, to result in a temporary remainder. And, if the temporary remainder was greater than the modulus, the modulus could be subtracted from it once, to result in the final remainder. This last step should not even be necessary, since the most-significant bit of the modulus was equal to 1, and the temporary remainder’s most-significant word is also expected to consist of zeroes.

3: )

If the reader truly wants to know, how long division can follow from the simple division which I defined above, then one fact he or she will need to take into account is that, just as it was in grade-school Math, the dividend can be broken into pieces, but the full divisor must always be used. Therefore, long division will really only help us, if the number of non-zero least-significant words in the big dividend, exceeds the corresponding number of words in the divisor, by 2 or more.

If that’s the case, and there are (n) non-zero, least-significant words in the divisor, then the first (n+1), non-zero words can be read from the big dividend, to define the small dividend, which is established as above to perform one simple division. This will result in a quotient of maximally 2 words, and a remainder, of the same length as the divisor. The quotient gets saved, and the remainder gets left-shifted by the width of 1 word, and the next word from the big dividend added / appended to it, to derive the next small dividend, to be used by the simple division. This time, the resulting quotient should not become larger than 1 word. This gets repeated, until all the words in the big dividend have been used.

Each time a small dividend is established, its most-significant word could be smaller than the most-significant word of the divisor, which might lead to a situation in which the quotient would always remain zero, especially since this would also yield a remainder, which is just equal to the dividend again. It’s therefore important that a word-width be established, such that the division of a 2-word value by a 1-word value is already defined as a primitive. And for 64-bit by 32-bit division on 32-bit CPUs, this could require using 16-bit words, if we cannot guarantee that the most-significant bit of the divisor is always 1, i.e. that the 32 bits of the divisor are actually filled.

(Update 06/03/2018, 20h45 : )

I’ve written some sample code, which shows what my theory would look like when implemented, to achieve 64-bit by 64-bit division, on a 32-bit CPU. However I must warn the reader that this code is untested:

I just presently needed to correct mistakes which I made in the same piece of code. However, until now only the Google Bot and the BingBot downloaded the code snippet, which means that the errors which those crawlers captured, cannot have inconvenienced actual readers yet. As of 20h45 this evening, I think the code to be correct, with better than 50% probability.