web-dev-qa-db-fra.com

Adresses privées vs publiques en Bluetooth à faible consommation d'énergie sur Android

Un appareil Bluetooth à faible consommation d'énergie est identifié de manière unique par son adresse (dans l'API Android, ils l'appellent l'adresse MAC et les désignent comme des valeurs hexadécimales séparées par des points, par exemple 11: aa: 22: bb: 33: cc).

Mais pour identifier de manière unique une adresse BLE, vous devez savoir s’il s’agit d’une adresse publique ou privée. En substance, 49 bits sont nécessaires pour identifier une adresse, pas 48.

Les adresses aléatoires peuvent être des adresses statiques aléatoires, des adresses privées non résolvables ou des adresses privées résolvables. Ces types sont séparés par un modèle de bits dans les deux octets les plus significatifs (11, 00 et 10 respectivement).

Mais je ne vois nulle part où vous pouvez séparer des adresses publiques et aléatoires simplement en regardant les 48 bits de l'adresse.

Alors, comment cela fonctionne-t-il dans l'API Android? Comment savent-ils à quel appareil se connecter quand ils ne savent pas si l'adresse que vous avez spécifiée est publique ou aléatoire?

L'API en question est par exemple la fonction getRemoteDevice . Ça dit:

Valid Bluetooth hardware addresses must be upper case, in a format such as
"00:11:22:33:AA:BB". The helper checkBluetoothAddress(String) is available
to validate a Bluetooth address.

A BluetoothDevice will always be returned for a valid hardware address,
even if this adapter has never seen that device.

Donc, vous donnez 48 bits de données à la fonction et il n’ya aucun moyen de savoir si l’adresse est publique ou privée. Cela signifie que le périphérique n'est pas identifié de manière unique.

22

Étant donné que personne d'autre ne semble avoir de réponse à proposer, j'ai commencé les tests par moi-même.

J'ai essayé de créer une application qui crée un appareil à partir de la représentation sous forme de chaîne d'une adresse et j'ai essayé de configurer mon appareil avec l'adresse 48 bits en alternant le bit public ou privé pour voir ce que fait la pile Android.

private final BluetoothGattCallback leGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.i("Fisken", "Gatt connected " + gatt.getDevice().getAddress() + " status " + status);
            if (status != BluetoothGatt.GATT_SUCCESS) {
                Log.w("Fisken", "Disconnect and close");
                gatt.disconnect();
                gatt.close();
            }
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.i("Fisken", "Gatt disconnected " + gatt.getDevice().getAddress() + " status " + status);
            if (status != BluetoothGatt.GATT_SUCCESS) {
                Log.w("Fisken", "Disconnect and close");
                gatt.disconnect();
            }
            gatt.close();
        }
    }
};

BluetoothAdapter mBluetoothAdapter = ((BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
BluetoothDevice d = mBluetoothAdapter.getRemoteDevice("FF:55:44:33:22:11");
d.connectGatt(this, false, leGattCallback);

Avec ce code, si je démarre mon périphérique BLE avec une adresse aléatoire, tout fonctionne comme prévu. Cependant, si j'essaie de l'exécuter avec la même adresse avec le bit public défini, logcat dit "Gatt connected", mais ce n'est tout simplement pas vrai. Et je ne pourrai jamais me déconnecter.

Mise à jour : J'ai fait quelques tests supplémentaires pour comprendre cela. L’événement onConnectionStateChange que j’obtiens est simplement l’expiration de la tentative de connexion. Le statut est défini sur 133 (si j'obtiens STATE_CONNECTED) ou sur 257 (si j'obtiens un STATE_DISCONNECTED) et que j'ai déjà vu les deux. Dans les deux cas, je devrais (et le faire maintenant dans l'exemple de code) annuler la tentative de connexion et fermer le client.

J'ai également découvert que si je fais un scan en premier, de sorte que le périphérique que je tente de connecter a été vu récemment et que then effectue une connexion uniquement à partir de l'adresse mac du périphérique, je suis alors en mesure de connectez-vous à des adresses aléatoires et publiques sans aucun problème.

Cela semble donc être un bug et/ou une fonctionnalité manquante dans l'API Android. Il ne vous permet pas de vous connecter à une adresse publique sans l'avoir préalablement analysée. Cela fonctionne cependant pour des adresses aléatoires.

9
Vegar Westerlund

Il est possible de deviner si l'adresse est publique ou aléatoire, mais cela ne fonctionnera pas dans tous les cas.

Comme vous le dites ci-dessus, dans le cas d'une adresse aléatoire, les deux MSB sont soit 00xx, 01xx ou 11xx ... Donc, s'il s'agit de 10xx, il s'agit alors d'une adresse publique (d'une entreprise dont le OUI commence par 8,9, A ou B)

En outre, le nombre d'identificateurs OUI enregistrés est très limité par rapport à ce qui existe déjà. Par conséquent, si vous recherchez un identificateur OUI potentiel dans la base de données IEEE, un résultat correspondant signifiera probablement une adresse publique.

Compte OUI enregistré: ~ 20500, soit 0,12% sur 2 ^ 24 bits et 0,48% sur 2 ^ 22 bits.

Sans la base de données IEEE, il est possible de s’appuyer sur le fait que le premier LSB d’une OUI est toujours égal à 0 et que le deuxième LSB est presque toujours 0 (en fait, il doit toujours être 0, car ces adresses sont administrées universellement).

En outre, une autre analyse statistique peut être utilisée: par exemple, 60% de l'OUI commencent par 00. D'autre part, une adresse privée non résolvable n'a qu'une probabilité de 1,66% pour commencer par 00 (avec générateur aléatoire uniforme).

1
calandoa

Je pense que votre «besoin de 49 bits pour distinguer les adresses publiques des adresses aléatoires» est correct. Je ne trouve rien dans l'encodage d'une adresse publique IEEE qui limite le bit de poids fort à 10, ce qui, le cas échéant, résoudrait le problème.

Ainsi, la seule chose que l'on puisse utiliser est le réglage du bit "adresse aléatoire" dans les annonces du périphérique ou le réglage du bit équivalent dans le paquet de lancement de la connexion du central. Si ces bits ne sont pas définis, l'adresse indiquée par ledit point d'extrémité est publique.

Je vais ajouter: De la spécification de base Vol. 6, partie B, section 1.3 Adresses de l’appareil: MS appelant = plus significatif

Static random address:          two MB bits of MS byte are 1 1 such that the MS byte is 11xxxxxx & with 0xC0
Non-resolvable private address: two MB bits of MS byte are 0 0 such that the MS byte is 00xxxxxx & with 0x00
Resolvable private address:     two MB bits of MS byte are 0 1 such that the MS byte is 01xxxxxx & with 0x40

Il n’existe aucun moyen de distinguer une adresse publique de l’un des types d’adresses ci-dessus sans le drapeau du type d’adresse. D'où la nécessité du bit '49ème' (le drapeau supplémentaire). L'adresse seule ne le fait pas!

0
Brian Reinhold

Que l'adresse publicitaire soit publique ou privée est défini dans l'en-tête du message publicitaire. La définition du type d'adresse dans la couche application sur public signifie que la couche liaison BLE transmettra l'adresse "MAC" réelle. Définir le type d'adresse sur résolvable statique/privé indique que la couche liaison BLE brouillera l'adresse avec une clé de résolution d'identité (IRK).

0
Freddy

Vous pouvez différencier les adresses publiques des adresses privées en consultant les 2 bits les plus significatifs. Une adresse a une longueur de 48 bits et non de 49. Voir la spécification Bluetooth centrale v4.2, Vol 6, partie B, section 1.3.

0
speedycat