ascon / ascon-c

Ascon - Lightweight Authenticated Encryption & Hashing
https://ascon.iaik.tugraz.at/
Creative Commons Zero v1.0 Universal
189 stars 30 forks source link

ARMv6m_lowsize: impossible constraint in ‘asm’ #17

Closed panevain closed 7 months ago

panevain commented 7 months ago

Hello,

I am attempting to build the Ascon-128a armv6m_lowsize implementation and I am encountering an issue with the assembly in round.h.

The following commands cause the issue to appear:

mkdir build && cd build
cmake .. -DALG_LIST="ascon128a" -DIMPL_LIST="armv6m_lowsize" -DTEST_LIST="getcycles"
cmake --build .

Build output:

[ 12%] Building C object CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/crypto_aead/ascon128av12/armv6m_lowsize/aead.c.o
[ 25%] Building C object CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/crypto_aead/ascon128av12/armv6m_lowsize/crypto_aead.c.o
[ 37%] Building C object CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/crypto_aead/ascon128av12/armv6m_lowsize/permutations.c.o
In file included from /**omitted**/ascon/crypto_aead/ascon128av12/armv6m_lowsize/permutations.h:11,
                 from /**omitted**/ascon/crypto_aead/ascon128av12/armv6m_lowsize/permutations.c:1:
/**omitted**/ascon/crypto_aead/ascon128av12/armv6m_lowsize/permutations.c: In function ‘P’:
/**omitted**/ascon/crypto_aead/ascon128av12/armv6m_lowsize/round.h:12:3: error: impossible constraint in ‘asm’
   12 |   __asm__ __volatile__(
      |   ^~~~~~~
gmake[2]: *** [CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/build.make:104: CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/crypto_aead/ascon128av12/armv6m_lowsize/permutations.c.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/crypto_aead_ascon128av12_armv6m_lowsize.dir/all] Error 2
gmake: *** [Makefile:101: all] Error 2

The same error arises when compiling using arm-none-eabi-g++ (from the arduino-cli tooling). I've read the GCC ASM constraints documentation and I believe that the assembly provided should work, and I'm confused why it doesn't.

Through trial and error, I've determined that having more than one output register marked with the h constraint causes compilation to fail.

Machine information:

gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04.1)
GNU Make 4.3
Ubuntu 22.04.2 LTS
Linux 6.8.4-200.fc39.x86_64

Any help/ideas would be appreciated!

Matt

mschlaeffer commented 7 months ago

The armv6m_lowsize implementation is highly optimized and forces the compiler to keep the Ascon state inside CPU registers. This results in some constraints which cannot be met all the time. A similar performant, but less constraint implementation is opt32_lowsize.

In my case, the armv6m_lowsize implementation compiles for Cortex-M0 if I add -O2 -fomit-frame-pointer to the gcc options: arm-none-eabi-gcc -mcpu=cortex-m0 -O2 -fomit-frame-pointer -Itests -Icrypto_aead/ascon128av12/armv6m_lowsize crypto_aead/ascon128av12/armv6m_lowsize/*.[cS] -c

Others work as well but -Os does not seem to work for Cortex-M0. What exact processor do you compile for?

panevain commented 7 months ago

I'm attempting to compile for the Arduino Nano 33 IoT which has a Microchip SAMD21G18A processor.

mschlaeffer commented 7 months ago

Did my command work to compile the code? Also try with -mcpu=cortex-m0 removed or -mcpu=cortex-m0plus added.

panevain commented 7 months ago

Yes, switching from -Os to -O2 allows the code to compile.

All else being equal, switching from the opt32_lowsize round function with -Os enabled to the amrv6m_lowsize round function with -O2 enabled increases the size of the binary by 78 bytes.

I'm still confused as to why the -Os flag breaks the assembly, but for now, this is a good solution.

Thank you Martin!

mschlaeffer commented 7 months ago

Yes, I'm also confused why -Os breaks the assembly.

Another option is to compile permutations.c using -O2 and the other files using -Os.

panevain commented 7 months ago

Great idea. I'll give that a run.

Closing the issue due to a workaround being found.