Tags

arm64 bit blacklistd bluepill bluetooth cu dns dovecot elf envsubst esp8266 filter freebsd ipfw lets_encrypt opensmtpd perl python shell ssh ssl stm32 template tls unbound yubikey

Powered by

blOg
maRkdown
awK
shEll

10/06/2023

[ ssh ]

202306100800 ssh

ssh possède une option assez pratique pour qui veut apporter des modifications à sa configuration sans tout casser:

 -G      Causes ssh to print its configuration after evaluating Host and
         Match blocks and exit.

Pour avoir une idée de ce qu'il est possible de configurer:

$ ssh -F /dev/null -G localhost | wc -l
81

On va donc plutôt filtrer la sortie:

$ ssh -F /dev/null -G localhost | grep -e port -e localhost
host localhost
hostname localhost
port 22
gatewayports no
nohostauthenticationforlocalhost no

AddressFamily

Cette option permet de définir l'usage d'ipv4, d'ipv6 ou des deux. Comme chez moi, le ssh ne fonctionne qu'en ipv6, je peux ajouter dans mon ~/.ssh/config:

AddressFamily inet6

Sauf que:

Je commence par identifier le problème:

$ echo 'AddressFamily inet6' > /tmp/ssh_config
$ ssh -F /tmp/ssh_config github.com
ssh: Could not resolve hostname github.com: Address family for hostname not supported
$ ssh -F /tmp/ssh_config github.com 192.168.0.1
ssh: Could not resolve hostname 192.168.0.1: Name does not resolve

Je distingue ces citoyens de seconde zone avec une directive Match:

$ cat /tmp/ssh_config 
Match host github.com,10.*,192.168.*
AddressFamily inet

Match all
AddressFamily inet6

et je teste:

$ ssh -F /tmp/ssh_config -G github.com | grep address
addressfamily inet
$ ssh -F /tmp/ssh_config -G gitlab.com | grep address
addressfamily inet6
$ ssh -F /tmp/ssh_config -G 192.168.0.1 | grep address
addressfamily inet

En cas de liste, attention à ne pas utiliser d'espace, uniquement la virgule. Pour le réseau 172.16.0.0/12, c'est un peu plus long:

$ grep 172 /tmp/ssh_config
$ Match host github.com,10.*,192.168.*,172.16.*,172.17.*,172.18.*,172.19.*,172.2?.*,172.30.*,172.31.*

Pour mon usage d'ipv4, je ne souhaite pas polluer mon .ssh/known_hosts:

$ cat /tmp/ssh_config
Match host github.com,192.168.*,10.*,172.16.*,172.17.*,172.18.*,172.19.*,172.2?.*,172.30.*,172.31.*
AddressFamily inet

Match host 1*
UserKnownHostsFile none

Match all
AddressFamily inet6

IdentityFile

J'ai une clef pour chaque serveur publique sur lequel je me connecte et j'ai la bonne idée de la nommer en fonction du serveur:

$ cat /tmp/ssh_config
Match host github.com,10.*,192.168.*,172.16.*,172.17.*,172.18.*,172.19.*,172.2?.*,172.30.*,172.31.*
AddressFamily inet

Match host 1*
UserKnownHostsFile none

Match all
AddressFamily inet6

Match host github.com,gitlab.com
IdentityFile ~/.ssh/%h

Je teste:

$ ssh -F /tmp/ssh_config -G github.com | grep -e address -e identityfile
addressfamily inet
identityfile ~/.ssh/%h
$ ssh -F /tmp/ssh_config -G gitlab.com | grep -e address -e identityfile
addressfamily inet6
identityfile ~/.ssh/%h
$ ssh -F /tmp/ssh_config -G localhost | grep -e address -e identityfile
addressfamily inet6
identityfile ~/.ssh/id_rsa
identityfile ~/.ssh/id_ecdsa
identityfile ~/.ssh/id_ecdsa_sk
identityfile ~/.ssh/id_ed25519
identityfile ~/.ssh/id_ed25519_sk
identityfile ~/.ssh/id_xmss
identityfile ~/.ssh/id_dsa

Parce que l'ordre compte

J'utilise toujours une clef sauf pour le tld .ru:

Match host github.com,10.*,192.168.*,172.16.*,172.17.*,172.18.*,172.19.*,172.2?.*,172.30.*,172.31.*
AddressFamily inet

Match host 1*
UserKnownHostsFile none

Match all
AddressFamily inet6
PreferredAuthentications publickey

Match host github.com,gitlab.com
IdentityFile ~/.ssh/%h

Match host *.ru
PreferredAuthentications password

Pas marche:

$ ssh -F /tmp/ssh_config -G fail.ru | grep -e preferredauthentications
preferredauthentications publickey

On ne peut pas redéfinir une directive, comme indiqué en début de page de manuel:

 Unless noted otherwise, for each parameter, the first obtained value will
 be used.  

Pour mon cas d'usage je peux:

Include et alias

La directive suivante définit un raccourci vers github.com

Host gh
Hostname github.com

que l'on peut placer dans un fichier dédié. Une directive Include :

$ cat /tmp/ssh_config_alias
Host gh
Hostname github.com

$ cat /tmp/ssh_config
Include /tmp/ssh_config_alias # Chemin complet car le fichier de config n'est pas un de ceux par défaut

Match host github.com,10.*,192.168.*,172.16.*,172.17.*,172.18.*,172.19.*,172.2?.*,172.30.*,172.31.*
AddressFamily inet

Match host 1*
UserKnownHostsFile none

Match all
AddressFamily inet6

Match host github.com,gitlab.com
IdentityFile ~/.ssh/%h

Match host *.ru
PreferredAuthentications password

Match all
PreferredAuthentications publickey

et le tour est joué:

$ ssh -F /tmp/ssh_config -G gh | grep -e address -e identityfile
addressfamily inet
identityfile ~/.ssh/%h

J'ai quelques machines virtuelles qui sont dans un sous-domaine dédié:

Host nbsd2?,al3?,fbsd4?
Hostname %n.xen

Mais ce n'est pas la bonne solution: le token %n n'est pas disponible dans une directive Hostname. Je vais utiliser les directives Canonicalize :

Match host nbsd2? al3? fbsd4?
CanonicalizeHostname yes
CanonicalDomains xen.bsdsx.fr # oui, le domaine complet

Si la configuration DNS est correcte alors:

$ ssh -F /tmp/ssh_config -G al30 | grep -e hostname
hostname al30.ni3.bsdsx.fr
canonicalizehostname true

Control

Quand on doit avoir plusieurs connections vers une machine, on comprend vite l'utilité des directives Control et ça ne coûte pas plus cher de l'activer par défaut:

$ cat /tmp/ssh_config_alias
ControlMaster auto
ControlPath ~/.ssh/.%r@%h:%p
...

Match vs Host

J'ai toujours utilisé la directive Host, c'est pour ce billet que je suis passé à Match. Ces deux directives ne diffèrent que par leur syntaxe:

Host *.ru *.ch
Match host *.ru,*.ch

mais seul Match permet ce genre de chose:

Match host *.prod.mon.domaine user backup localuser !production exec "id -Gn %u | grep -q admin"
PreferredAuthentications publickey
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa_backup_with_force_command

Si:

alors on utilise une clef spécifique. Oui cet exemple est plutôt capillotracté (mais aucun drosophile n'a été ... lors de la rédaction de ce billet).

Un dernier pour la route

C'est plus par principe qu'autre chose mais si il y a bien un truc que je ne supporte pas c'est tout ce qui ne sert à rien (oui, je ne supporte pas grand chose :) . Quand je vois tous les fichiers testés par

$ ssh -v ...

je me dis que ces quelques lignes ne peuvent pas faire de mal:

GlobalKnownHostsFile /dev/null # je n'ai jamais créé les fichiers de cette directive
UserKnownHostsFile ~/.ssh/known_hosts # known_hosts2 n'existe pas
# Pour ne pas tester des clefs qui n'existent pas
IdentityFile ~/.ssh/id_rsa
IdentityFile ~/.ssh/id_ecdsa_sk
AddKeysToAgent yes # ajouter les clefs à l'agent lors de leur première utilisation

Enjoy !

Commentaires: https://github.com/bsdsx/blog_posts/issues/18


Lien vers ce billet

04/03/2023

[ bit perl ]

202303040800 bit perl

Les bits

J'ai toujours eu un peu de mal à avoir la représentation binaire d'une valeur, qu'elle soit au format décimal ou hexadécimal (là j'ai vraiment beaucoup de mal). Mais jouer avec des microcontrôleurs impose tôt ou tard de se retrouver avec ce genre de chose:

RCC->APB1ENR |= 0x200000;

APB1ENR est une valeur sur 32 bits décomposés en bit (parfois en groupe de bit) et ici on active un de ces bits. Mais lequel ? Pour me simplifier la vie, je me suis donc fendu d'un script (Perl, what else ?) sans prétention qui m'affiche, pour chaque argument, sa valeur binaire:

$ perl bits.pl 0x200000
  31  30  29  28  27  26  25  24  23  22  21  20  19  18  17  16  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
--------------------------------------------------------------------------------------------------------------------------------
   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  0x200000 (2097152)

En consultant la documentation, je comprend que le bit 21 du registre APB1ENR correspond (pour une blue pill) à l'activation de I2C1. Parce que certains registres sont sur 16 bits, je peux aussi réduire le nombre de bit à afficher:

$ perl bits.pl -16 0x800
  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
----------------------------------------------------------------
   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   0  0x800 (2048)

ou modifier la largeur de chaque colonne (pas le plus simple à lire, j'en conviens):

$ perl bits.pl -8 -w 1 5 7 9
76543210
--------
00000101  5 (5)
00000111  7 (7)
00001001  9 (9)

Je peux aussi utiliser des valeurs binaires directement à des fins de comparaison:

$ perl bits.pl -8 0b00000111 0b10101010 5 0xa
   7   6   5   4   3   2   1   0
--------------------------------
   0   0   0   0   0   1   1   1  0b00000111 (7)
   1   0   1   0   1   0   1   0  0b10101010 (170)
   0   0   0   0   0   1   0   1  5 (5)
   0   0   0   0   1   0   1   0  0xa (10)

Les opérateurs et fonctions Perl

Avec l'opérateur .. je peux facilement obtenir la liste des nombres de 0 à 15:

$ perl -le 'print 0 .. 15'
0123456789101112131415

Mais pas ceux de 15 à 0:

$ perl -le 'print 15 .. 0'
<rien, nada, que dalle>

Pour afficher mes nombres dans l'ordre décroissant, il me suffit d'utiliser reverse:

$ perl -le 'print reverse 0 .. 15'
1514131211109876543210

Pour afficher une valeur sur 3 caractères j'utilise %3s. Pour formater size bits sur une largeur de width il me suffit d'utiliser l'opérateur x:

$fmt = "%${width}s" x $size-- . '%s'; // on n'oublie pas le '%s' pour le retour à la ligne

Parce que j'utilise reverse, je dois commencer par le retour chariot:

printf $fmt, reverse "\n", 0 .. $size;

Pour connaitre la valeur d'un bit à la position $pos d'une valeur $value, je dois déplacer la valeur 1 de $pos positions:

1 << $pos

faire un et avec la valeur:

$value & (1 << $pos)

et redécaler ce résultat de pos positions (les parenthèses sont nécessaires du fait de la priorité des opérateurs):

($value & (1 << $pos)) >> $pos

Pour obtenir la valeur des $size premiers bits de $register:

map { ($register & (1 << $_)) >> $_ } 0 .. $size;

map va appliquer le block ({ .. }) pour chaque valeur ($_) de la list 0 .. $size

Le script

Comme d'habitude, pour quelques lignes de code, on se trouve avec une gestion des options, de l'aide, de la vérification d'arguments ... et paf, 50 lignes:

$ cat -n bits.pl
 1  #!/usr/bin/perl
 2
 3  use strict;
 4  use warnings FATAL => 'all';
 5  use utf8;
 6
 7  use Getopt::Long;
 8
 9  sub usage {
10      print <<EOT
11  Usage: $0 [-8|-16|-32] [--width=width] [-h] number ...
12
13  Example:
14      $0 42 0xcafe 0b101
15      $0 -8 -w 1 5
16  EOT
17  ;
18      exit;
19  }
20
21  my ($size, $width, $help) = (32, 4);
22  GetOptions(
23       '8' => sub { $size =  8 },
24      '16' => sub { $size = 16 },
25      '32' => sub { $size = 32 },
26
27      'width=i' => \$width,
28      'help'    => \$help,
29  ) or usage();
30
31  if ($help || !scalar @ARGV) { usage(); }
32   
33  my $fmt;
34  sub dump_register {
35      my $register = $_[0] =~ /^0[bx]/i ? oct $_[0] : $_[0];
36      printf $fmt, reverse "  $_[0] ($register)\n", map { ($register & (1 << $_)) >> $_ } 0 .. $size;
37  }
38
39  if ($width < 2 && $size > 8) { $width = 3; } 
40  $fmt = "%${width}s" x $size-- . '%s';
41
42  printf $fmt, reverse "\n", 0 .. $size;
43  printf $fmt, (('-' x $width)) x ($size + 1) , "\n";
44
45  foreach (@ARGV) { dump_register($_); }

Pour finir

Quand je tombe sur ce genre de chose:

GPIOA->CRL &= ~(0xf << (2 * 4));
GPIOA->CRL |=   0xA << (2 * 4);

Il me suffit de rajouter en fin de script:

my $register = $ARGV[0] =~ /^0[bx]/i ? oct $ARGV[0] : $ARGV[0];
$register &= ~(0xf << (2 * 4));
dump_register($register);
$register |=   0xA << (2 * 4);
dump_register($register);

et de le lancer avec 0xffffffff (pour que tous les bits soient à 1):

$ perl bits.pl 0xffffffff
  31  30  29  28  27  26  25  24  23  22  21  20  19  18  17  16  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
--------------------------------------------------------------------------------------------------------------------------------
   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1  0xffffffff (4294967295)
   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   0   0   0   0   1   1   1   1   1   1   1   1  4294963455 (4294963455)
   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   0   1   0   1   1   1   1   1   1   1   1  4294966015 (4294966015)

La première instruction initialise à zéro le 3ème groupe de 4 bits, la seconde active les bits 1 (9) et 3 (11) de ce 3ème groupe. Et tout est plus clair !

Commentaires: https://github.com/bsdsx/blog_posts/issues/17


Lien vers ce billet

09/10/2022

[ stm32 bluepill elf ]

202210090800 stm32 bluepill elf

FreeBSD et bluepill, corrections

J'ai raconté plusieurs conneries dans mon billet FreeBSD et bluepill qu'il me faut corriger.

openocd et mon adaptateur

Quand openocd affiche le message suivant:

$ openocd -f openocd.cfg -c "init"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate

Info : clock speed 1000 kHz
Info : STLINK V2J17S4 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.137032
Warn : UNEXPECTED idcode: 0x2ba01477
Error: expected 1 of 1: 0x1ba01477

Ce n'est pas l'adaptateur qui pose problème mais bien la bluepill comme on peut le lire sur hackaday.com:

[ snip bluepill version Chang ]
...
A major difference one will quickly encounter with this chip is when programming it and getting the message "UNEXPECTED idcode: 0x2ba01477". The reason for this is that the STM32F103 MCU reports the ID 0x1ba01477, confusing the programmer.
....

core.S

Toujours depuis ce fichier assembleur, avec une nouvelle modification en provenance directe du jardin magique (merki miod@ et semarie@): utiliser le préprocesseur pour définir la valeur du registre r7:

$ fetch -o - https://raw.githubusercontent.com/WRansohoff/STM32F0_minimal/master/core.S | sed -e 's/cortex-m0/cortex-m3/' -e 's/reset_handler/Reset_Handler/g' -e 's/_estack/__end_stack/' -e 's/0xDEADBEEF/R7_REGISTER/' > core.S

On compile avec l'option -x assembler-with-cpp et la valeur:

$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -x assembler-with-cpp -DR7_REGISTER=0xDEADBEEF -c core.S -o core.o

On génère le binaire avec le linker script :

$ fetch -o stm32-base.zip https://github.com/STM32-base/STM32-base/archive/refs/heads/master.zip
$ tar xf stm32-base.zip STM32-base-master/linker
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -nostdlib -L STM32-base-master/linker -T STM32-base-master/linker/STM32F1xx/STM32F103xB.ld core.o -o core.elf

Pour vérifier la prise en compte de la valeur:

$ readelf -x .text main.elf

Hex dump of section '.text':
  0x08000000 00500020 09000008 02488546 024f0020 .P. .....H.F.O.
  0x08000010 401cfde7 00500020 efbeadde          @....P. ....

efbeadde correspond bien à la version petit boutiste de DEADBEEF.

objcopy

Partie la plus sensible qui va me jouer des tours pendant plusieurs semaines, la conversion du .elf en .bin . On peut lire un peu partout cette commande:

$ objcopy -O binary main.elf main.bin

Mais sur FreeBSD on trouve 2 objcopy:

$ ls -l /usr/bin/*objcopy
-r-xr-xr-x  2 root  wheel  4025248 May 21 09:32 /usr/bin/llvm-objcopy
-r-xr-xr-x  2 root  wheel   129560 May 21 09:32 /usr/bin/objcopy
$ file /usr/bin/*objcopy
/usr/bin/llvm-objcopy: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, FreeBSD-style, stripped
/usr/bin/objcopy:      ELF 64-bit LSB pie executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 13.1, FreeBSD-style, stripped

En partant d'un fichier source aussi simple que celui-ci:

void __libc_init_array(void) {} // startup_common.s
int integer_in_data_section = 1; // la section .data ne doit pas être vide

int
main(void) {
    int i = 0;
    while (1) {
        i += integer_in_data_section;
    }

    return i;
}

Je commence par compiler un fichier assembleur correspondant à la carte:

$ tar xf stm32-base.zip STM32-base-master/startup
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -I STM32-base-master/startup -c STM32-base-master/startup/STM32F1xx/STM32F103xB.s -o startup.o
STM32-base-master/startup/startup_common.s:24:1: warning: Reset_Handler changed binding to STB_WEAK
.weak Reset_Handler

puis mon fichier source:

$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -c main.c -o main.o
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -nostdlib -L STM32-base-master/linker -T STM32-base-master/linker/STM32F1xx/STM32F103xB.ld main.o startup.o -o main.elf
$ size main.elf
  text   data    bss    dec     hex   filename
   416      4   1536   1956   0x7a4   main.elf

que je dois convertir en .bin :

$ objcopy -O binary main.elf main.bin
$ ls -l main.bin
-rwxr-xr-x  1 dsx  wheel  402653188  2 nov.  19:39 main.bin

400 Mo pour incrémenter une variable, on dépasse un peu les bornes des limites. Avec le "bon" objcopy:

$ llvm-objcopy -O binary main.elf main.bin
$ ls -l main.bin
-rwxr-xr-x  1 dsx  wheel  420  2 nov.  19:41 main.bin

A moi (enfin !) les <blink>leds</blink> qui clignottent !

Commentaires: https://github.com/bsdsx/blog_posts/issues/16


Lien vers ce billet

09/10/2022

[ stm32 bluepill ]

202210090800 stm32 bluepill

FreeBSD et bluepill

A force de suivre les vidéos de Sieur Rancune j'ai fini par craquer pour une poignée de bluepill. Parce qu'il est conseillé sur tous les interweb d'utiliser arm-none-eabi-gcc pour programmer ces charmantes bestioles j'ai décidé d'utiliser clang/llvm livré de base.

Si allumer une led constitue le 'Hello World!' de l'électronique, j'ai découvert le niveau -1 en lisant cette série de billets: placer une valeur particulière dans un registre.

Les sources

Le fichier core.S requiert 3 modifications mineures:

$ fetch -o - https://raw.githubusercontent.com/WRansohoff/STM32F0_minimal/master/core.S | sed -e 's/cortex-m0/cortex-m3/' -e 's/reset_handler/Reset_Handler/g' -e 's/_estack/__end_stack/' > core.S
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -c core.S -o core.o

Le binaire

Pour que mon binaire final soit adapté à ma carte, je dois récupérer un 'linker script':

$ fetch https://github.com/STM32-base/STM32-base/archive/refs/heads/master.zip
$ tar xf master.zip STM32-base-master/linker
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -nostdlib -L STM32-base-master/linker -T STM32-base-master/linker/STM32F1xx/STM32F103xB.ld core.o -o main.elf

C'est pour se conformer à ce script qu'il faut modifier le fichier core.S.

Les soucis commencent

Avant d'envoyer le fichier sur la carte, il faut le convertir:

$ objcopy -O binary main.elf main.bin
$ du -Ah main.bin 
384M  main.bin

Là je crois qu'on dépasse les bornes des limites: ça fait beaucoup de méga pour placer une valeur dans un registre. Si je regarde mon fichier elf:

$ readelf -l main.elf | grep 0x
Entry point 0x8000009
  LOAD           0x010000 0x08000000 0x08000000 0x0001c 0x0001c R E 0x10000
  LOAD           0x020000 0x20000000 0x20000000 0x00600 0x00600 RW  0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0
  ARM_EXIDX      0x01001c 0x0800001c 0x0800001c 0x00000 0x00000 R   0x4

Je peux me passer de GNU_STACK avec l'option -z nognustack:

$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -z nognustack -nostdlib -L STM32-base-master/linker -T STM32-base-master/linker/STM32F1xx/STM32F103xB.ld core.o -o main.elf
$ readelf -l main.elf | grep 0x
Entry point 0x8000009
  LOAD           0x010000 0x08000000 0x08000000 0x0001c 0x0001c R E 0x10000
  LOAD           0x020000 0x20000000 0x20000000 0x00600 0x00600 RW  0x10000
  ARM_EXIDX      0x01001c 0x0800001c 0x0800001c 0x00000 0x00000 R   0x4

Mais cela ne corrige pas le problème. J'ai fini par comprendre qu'une section n'avait pas le bon type:

$ readelf -S main.elf.OK | grep ._user_heap_stack
[ 6] ._user_heap_stack NOBITS          20000000 020000 000600 00  WA  0   0  1
$ readelf -S main.elf.KO | grep ._user_heap_stack
[ 7] ._user_heap_stack PROGBITS        20000000 020000 000600 00  WA  0   0  1

La correction la plus simple que j'ai trouvé est de passer cette section en 'NOLOAD':

$ grep ._user_heap_stack STM32-base-master/linker/common.ld
._user_heap_stack (NOLOAD) : {
$ clang --target=arm-none-eabi -mcpu=cortex-m3 -mfloat-abi=soft -z nognustack -nostdlib -L STM32-base-master/linker -T STM32-base-master/linker/STM32F1xx/STM32F103xB.ld core.o -o main.elf
$ readelf -S main.elf | grep ._user_heap_stack
[ 8] ._user_heap_stack NOBITS          20000000 020000 000600 00  WA  0   0  1
$ objcopy -O binary main.elf main.bin
$ du -Ah main.bin
512B  main.bin

C'est déjà plus raisonnable.

Les soucis continuent

Il est temps de programmer la carte. J'utilise donc un adaptateur usb st link v2 et devel/openocd avec la configuration suivante:

$ cat openocd.cfg
source [find interface/stlink.cfg]
transport select hla_swd
source [ find target/stm32f1x.cfg]
reset_config none separate

Je connecte la bluepill à l'adaptateur, je branche l'adaptateur et paf:

$ openocd -f openocd.cfg -c "init"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate

Info : clock speed 1000 kHz
Info : STLINK V2J17S4 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.137032
Warn : UNEXPECTED idcode: 0x2ba01477
Error: expected 1 of 1: 0x1ba01477

Pour qu'openocd daigne utiliser mon adaptateur je dois lui dire qu'il est "de confiance" (kofkof):

$ cat openocd.cfg
set CPUTAPID 0x2ba01477
source [find interface/stlink.cfg]
transport select hla_swd
source [ find target/stm32f1x.cfg]
reset_config none separate

$ openocd -f openocd.cfg -c "init"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate

Info : clock speed 1000 kHz
Info : STLINK V2J17S4 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.138581
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Et quand y'en a plus y'en a encore

On va facilement trouver des exemples d'utilisation conjointe d'openocd et de gdb. Pas de bol pour moi, le debugger llvm n'est pas compatible, d'après https://stackoverflow.com/questions/36287351/how-to-setup-lldb-with-openocd-and-jtag-board:

"from what we were researching, it is not possible to debug remote (bare-metal!) targets with lldb without writing extra code."

Et autant dire que l'extra code en python, je passe.

Le bout du tunnel

Je vais donc utiliser l'interface "telnet" d'openocd:

$ echo 'reset halt' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> reset halt
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x1fffe61c msp: 0x20000180

$ echo 'stm32f1x mass_erase 0' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> stm32f1x mass_erase 0
device id = 0x20036410
flash size = 25616kbytes
stm32x mass erase complete

$ md5 main.bin 
MD5 (main.bin) = 09c6d874e631d40370b70a7bcc120f41

$ echo 'flash write_image erase main.bin 0x8000000' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> flash write_image erase main.bin 0x8000000
auto erase enabled
wrote 1024 bytes from file main.bin in 0.087373s (11.445 KiB/s)

$ echo 'reset run' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> reset run

$ echo 'halt' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> halt
target halted due to debug-request, current mode: Handler HardFault
xPSR: 0x00000003 pc: 0x012fff1e msp: 0xe59efff8

$ echo 'reg' | nc -N 127.0.0.1 4444
Open On-Chip Debugger
> reg
===== arm v7m registers
(0) r0 (/32): 0x008fec14
(1) r1 (/32): 0x00000000
(2) r2 (/32): 0x00000000
(3) r3 (/32): 0x00000000
(4) r4 (/32): 0x00000000
(5) r5 (/32): 0x00000000
(6) r6 (/32): 0x00000000
(7) r7 (/32): 0xdeadbeef
(8) r8 (/32): 0x00000000
(9) r9 (/32): 0x00000000
(10) r10 (/32): 0x00000000
(11) r11 (/32): 0x00000000
(12) r12 (/32): 0x00000000
(13) sp (/32): 0x20005000
(14) lr (/32): 0xffffffff
(15) pc (/32): 0x08000012
(16) xPSR (/32): 0x01000000
(17) msp (/32): 0x20005000
(18) psp (/32): 0x00000000
(20) primask (/1): 0x00
(21) basepri (/8): 0x00
(22) faultmask (/1): 0x00
(23) control (/3): 0x00
===== Cortex-M DWT registers

Pour être sûr de mon coup, j'essaie avec les valeurs suivantes:

A moi les leds qui clignottent !

Commentaires: https://github.com/bsdsx/blog_posts/issues/15


Lien vers ce billet

21/05/2022

[ yubikey ]

202205210800 yubikey

FreeBSD 13.1, OpenSSH et Yubikey

Cette nouvelle mouture de FreeBSD vient entre autre avec une mise à jour d'OpenSSH et ça cause FIDO/U2F. Il serait temps d'utiliser enfin cette Yubikey qui traine sur mon porte-clefs depuis des lustres:

$ dmesg | tail -n 6
ugen0.3: <Yubico YubiKey OTP+FIDO+CCID> at usbus0
ukbd1 on uhub0
ukbd1: <Yubico YubiKey OTP+FIDO+CCID, class 0/0, rev 2.00/5.12, addr 7> on usbus0
kbd3 at ukbd1
uhid1 on uhub0
uhid1: <Yubico YubiKey OTP+FIDO+CCID, class 0/0, rev 2.00/5.12, addr 7> on usbus0

On va s'éparger du temps et des cheveux avec ce petit paquet kivabien:

$ doas pkg install u2f-devd
$ doas service devd restart
$ doas pw groupmod u2f -m MonLogin
[ snip déco/reco pour que le nouveau groupe soit pris en compte ]
$ ssh-keygen -t ed25519-sk
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Key enrollment failed: requested feature not supported

Pas de soucis, c'est juste que le firmware de la clef est trop vieux pour utiliser ed25519-sk. Avec ecdsa-sk:

$ ssh-keygen -t ecdsa-sk
Generating public/private ecdsa-sk key pair.
You may need to touch your authenticator to authorize key generation.
[ la clef clignotte et attend une pression ]
Enter file in which to save the key (/home/MonLogin/.ssh/id_ecdsa_sk): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/MonLogin/.ssh/id_ecdsa_sk
Your public key has been saved in /home/MonLogin/.ssh/id_ecdsa_sk.pub$ ssh-keygen -t ecdsa-sk
...

Reste à déployer cette clef:

$ cat .ssh/id_ecdsa_sk.pub | ssh MonServeur "cat >> .ssh/authorized_keys"
$ unsetenv SSH_AUTH_SOCK
$ ssh -i .ssh/id_ecdsa_sk MonServeur
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
[ la clef clignotte et attend une pression ]
User presence confirmed
Last login: Sat May 21 10:07:59 2022 from dd.bsdsx.fr
...

Parfois la clef ne semble pas répondre:

$ ssh -i .ssh/id_ecdsa_sk nuc date
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
User presence confirmed
sam. 21 mai 2022 10:17:09 CEST
$ ssh -i .ssh/id_ecdsa_sk nuc date
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
User presence confirmed
sam. 21 mai 2022 10:17:14 CEST
$ ssh -i .ssh/id_ecdsa_sk nuc date
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
User presence confirmed
sam. 21 mai 2022 10:17:20 CEST
$ ssh -i .ssh/id_ecdsa_sk nuc 
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
[ la clef ne clignotte pas ]

Pas grand chose à faire:

^C
$ ssh -i .ssh/id_ecdsa_sk nuc
Confirm user presence for key ECDSA-SK SHA256:gkWxSHUxZjN5Q6svr51Mi0N+vMc051YPwXo7L1JkaQw
User presence confirmed
Last login: Sat May 21 10:14:38 2022 from dd.bsdsx.fr

Lien utile: https://cryptsus.com/blog/how-to-configure-openssh-with-yubikey-security-keys-u2f-otp-authentication-ed25519-sk-ecdsa-sk-on-ubuntu-18.04.html (anglais)

Commentaires: https://github.com/bsdsx/blog_posts/issues/14


Lien vers ce billet