Skip to main content
Thomas Roell
Associate III
March 8, 2024
Solved

STM32 PKA RSA Montgomery Parameter

  • March 8, 2024
  • 9 replies
  • 3013 views

The PKA peripheral can precompte the montgomery parameter, which is documented as "R2 mod n". If I compute this offline with R being the normal (2 ^ b) [b the numbers of bits in the modulus n], I am getting a different result than what PKA computes.

 

I did see there was a "computeR2.exe" for BlueNRG-LPS (also with PKA peripheral), but no source.

 

Is there anywhere documentation or source code of how to precompute the "Montgomery Parameter" used by the PKA peripheral ?

 

 

This topic has been closed for replies.
Best answer by UgoIannu

Hello Thomas,

for both targets, you should be able to generate a valid value of R2 using the following python function:

def generateR2(n):
 n = int(n)
 k = n.bit_length()
 w = int(math.ceil(k/32))
 R = 2**(32*w)
 r2adj = 2**(w*32-k)
 Z = R - n*r2adj
 for i in range(0, w+2):
 Z = Z << 32
 MSW = (Z >> w*32) & (2**32-1)
 while (MSW != 0):
 Z = Z - (n * MSW * r2adj)
 MSW = (Z >> w*32) & (2**32-1)
 return (Z)

In the snippet, n is the modulus, and the output Z is the desired related R2 Montgomery parameter.

Please, let me know if it solves the issue or you need further support.

9 replies

Thomas Roell
Associate III
March 8, 2024

None of that is relevant.

 

The official documentation does not specify what format the montgomery parameter gets stored in. Yes, it says that you can compute the montgomery parameter directly using PKA. But that is not what I am asking for. I do want to precompute this "r2modn" offline, rather than online via the PKA periperal.

 

This here is some code using the OpenSSL bignum APIs. I use this for a software implementation to verify a rsa2048 signature. Fairly simple stuff, lifted off some 2013 google code. Code is crosschecked with OpenSSL's RSA code, so I know it works:

 N = BN_dup(rsa2048_modulus);
 Big2 = BN_new();
 Big32 = BN_new();
 R = BN_new();
 RR = BN_new();
 RRTemp = BN_new();
 NnumBits = BN_new();
 rr = BN_new();
 BN_set_word(Big2, 2L);
 BN_set_word(Big32, 32L);
 B = BN_new();
 BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */

 /* Calculate R = 2^(# of key bits) */
 BN_set_word(NnumBits, BN_num_bits(N));
 BN_exp(R, Big2, NnumBits, bn_ctx);
 /* Calculate RR = R^2 mod N */
 BN_copy(RR, R);
 BN_mul(RRTemp, RR, R, bn_ctx);
 BN_mod(RR, RRTemp, N, bn_ctx);
 /* Write R^2 as little endian array of integers. */
 for (i = 0; i < nwords; ++i) {
 uint32_t rrout;
 BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */
 rrout = BN_get_word(rr);
 printf("%08x\n", rrout);
 BN_rshift(RR, RR, 32); /* RR = RR/B */
 }

 

However the value produced here does not match the one that PKA computes as the montgomery parameter. No byte/halfbyte swapping, nor other common reordering works. N.b. that I am using the same logic to emit the modulus "n" in the proper order, which works just fine with the PKA peripheral. 

 

So either the PKA peripheral does not use the classic R^2 mod n, or it's stored in some other fashion.

 

 

 

 

Tesla DeLorean
Guru
March 9, 2024

>> However the value produced here does not match the one that PKA computes as the montgomery parameter. No byte/halfbyte swapping, nor other common reordering works. ... or it's stored in some other fashion.

Well I can certainly subscribe to that, had my own battles with SECP192R1 libraries and assorted byte/endian differences between them, and that was with only permutations of 12 bytes.. especially with the light-weight library I was able to get to build cleanly on the STM32 and MSVC

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
ST Employee
March 18, 2024

Hello Thomas,

could you please specify which is the target MCU on which you are working on?

Thomas Roell
Associate III
March 18, 2024

Ugolannu,

this is for STM32WB55 and STM32WL55.

 

UgoIannuBest answer
ST Employee
March 19, 2024

Hello Thomas,

for both targets, you should be able to generate a valid value of R2 using the following python function:

def generateR2(n):
 n = int(n)
 k = n.bit_length()
 w = int(math.ceil(k/32))
 R = 2**(32*w)
 r2adj = 2**(w*32-k)
 Z = R - n*r2adj
 for i in range(0, w+2):
 Z = Z << 32
 MSW = (Z >> w*32) & (2**32-1)
 while (MSW != 0):
 Z = Z - (n * MSW * r2adj)
 MSW = (Z >> w*32) & (2**32-1)
 return (Z)

In the snippet, n is the modulus, and the output Z is the desired related R2 Montgomery parameter.

Please, let me know if it solves the issue or you need further support.

ST Employee
March 21, 2024

Yes, it should be ok for all the 32 bit PKAs