efm32gg11_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file efm32gg11_crypto_pkc.c
3  * @brief EFM32 Giant Gecko 11 public-key hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "em_device.h"
36 #include "em_crypto.h"
37 #include "core/crypto.h"
40 #include "ecc/ec.h"
41 #include "ecc/curve25519.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (EFM32GG11_CRYPTO_PKC_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Fast modular multiplication
50  * @param[in] params EC domain parameters
51  * @param[out] r Resulting integer R = (A * B) mod p
52  * @param[in] a An integer such as 0 <= A < p
53  * @param[in] b An integer such as 0 <= B < p
54  * @return Error code
55  **/
56 
57 error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a,
58  const Mpi *b)
59 {
60  error_t error;
61  uint_t i;
62  uint32_t temp[8];
63 
64  //Check elliptic curve
65  if(!osStrcmp(params->name, "secp256r1"))
66  {
67  //Acquire exclusive access to the CRYPTO module
69 
70  //Set wide arithmetic configuration
71  CRYPTO0->WAC = 0;
72  CRYPTO0->CTRL = 0;
73 
74  //Set CRYPTO module parameters
75  CRYPTO_ModulusSet(CRYPTO0, cryptoModulusEccP256);
76  CRYPTO_MulOperandWidthSet(CRYPTO0, cryptoMulOperandModulusBits);
77  CRYPTO_ResultWidthSet(CRYPTO0, cryptoResult256Bits);
78 
79  //Copy the first operand
80  for(i = 0; i < a->size && i < 8; i++)
81  {
82  temp[i] = a->data[i];
83  }
84 
85  while(i < 8)
86  {
87  temp[i++] = 0;
88  }
89 
90  CRYPTO_DDataWrite(&CRYPTO0->DDATA1, temp);
91 
92  //Copy the second operand
93  for(i = 0; i < b->size && i < 8; i++)
94  {
95  temp[i] = b->data[i];
96  }
97 
98  while(i < 8)
99  {
100  temp[i++] = 0;
101  }
102 
103  CRYPTO_DDataWrite(&CRYPTO0->DDATA2, temp);
104 
105  //Compute R = (A * B) mod p
106  CRYPTO_EXECUTE_2(CRYPTO0,
107  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
108  CRYPTO_CMD_INSTR_MMUL);
109 
110  //Wait for the instruction sequence to complete
111  CRYPTO_InstructionSequenceWait(CRYPTO0);
112 
113  //Copy the resulting value
114  CRYPTO_DDataRead(&CRYPTO0->DDATA0, temp);
115 
116  //Adjust the size of the integer
117  error = mpiGrow(r, 8);
118 
119  //Copy the result
120  for(i = 0; i < 8; i++)
121  {
122  r->data[i] = temp[i];
123  }
124 
125  while(i < r->size)
126  {
127  r->data[i++] = 0;
128  }
129 
130  //Set the sign of the result
131  r->sign = 1;
132 
133  //Release exclusive access to the CRYPTO module
135  }
136  else
137  {
138  //Compute R = A * B
139  error = mpiMul(r, a, b);
140 
141  //Check status code
142  if(!error)
143  {
144  //Compute R = (A * B) mod p
145  if(params->mod != NULL)
146  {
147  error = params->mod(r, &params->p);
148  }
149  else
150  {
151  error = mpiMod(r, r, &params->p);
152  }
153  }
154  }
155 
156  //Return status code
157  return error;
158 }
159 
160 
161 /**
162  * @brief Fast modular squaring
163  * @param[in] params EC domain parameters
164  * @param[out] r Resulting integer R = (A ^ 2) mod p
165  * @param[in] a An integer such as 0 <= A < p
166  * @return Error code
167  **/
168 
169 error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
170 {
171  error_t error;
172  uint_t i;
173  uint32_t temp[8];
174 
175  //Check elliptic curve
176  if(!osStrcmp(params->name, "secp256r1"))
177  {
178  //Acquire exclusive access to the CRYPTO module
180 
181  //Set wide arithmetic configuration
182  CRYPTO0->WAC = 0;
183  CRYPTO0->CTRL = 0;
184 
185  //Set CRYPTO module parameters
186  CRYPTO_ModulusSet(CRYPTO0, cryptoModulusEccP256);
187  CRYPTO_MulOperandWidthSet(CRYPTO0, cryptoMulOperandModulusBits);
188  CRYPTO_ResultWidthSet(CRYPTO0, cryptoResult256Bits);
189 
190  //Copy the operand
191  for(i = 0; i < a->size && i < 8; i++)
192  {
193  temp[i] = a->data[i];
194  }
195 
196  while(i < 8)
197  {
198  temp[i++] = 0;
199  }
200 
201  CRYPTO_DDataWrite(&CRYPTO0->DDATA1, temp);
202 
203  //Compute R = (A ^ 2) mod p
204  CRYPTO_EXECUTE_3(CRYPTO0,
205  CRYPTO_CMD_INSTR_DDATA1TODDATA2,
206  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
207  CRYPTO_CMD_INSTR_MMUL);
208 
209  //Wait for the instruction sequence to complete
210  CRYPTO_InstructionSequenceWait(CRYPTO0);
211 
212  //Copy the resulting value
213  CRYPTO_DDataRead(&CRYPTO0->DDATA0, temp);
214 
215  //Adjust the size of the integer
216  error = mpiGrow(r, 8);
217 
218  //Copy the result
219  for(i = 0; i < 8; i++)
220  {
221  r->data[i] = temp[i];
222  }
223 
224  while(i < r->size)
225  {
226  r->data[i++] = 0;
227  }
228 
229  //Set the sign of the result
230  r->sign = 1;
231 
232  //Release exclusive access to the CRYPTO module
234  }
235  else
236  {
237  //Compute R = A ^ 2
238  error = mpiMul(r, a, a);
239 
240  //Check status code
241  if(!error)
242  {
243  //Compute R = (A ^ 2) mod p
244  if(params->mod != NULL)
245  {
246  error = params->mod(r, &params->p);
247  }
248  else
249  {
250  error = mpiMod(r, r, &params->p);
251  }
252  }
253  }
254 
255  //Return status code
256  return error;
257 }
258 
259 
260 #if (X25519_SUPPORT == ENABLED || ED25519_SUPPORT == ENABLED)
261 
262 /**
263  * @brief Modular multiplication
264  * @param[out] r Resulting integer R = (A * B) mod p
265  * @param[in] a An integer such as 0 <= A < p
266  * @param[in] b An integer such as 0 <= B < p
267  **/
268 
269 void curve25519Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
270 {
271  uint_t i;
272  uint64_t temp;
273  uint32_t u[16];
274 
275  //Acquire exclusive access to the CRYPTO module
277 
278  //Set wide arithmetic configuration
279  CRYPTO0->WAC = 0;
280  CRYPTO0->CTRL = 0;
281 
282  //Set CRYPTO module parameters
283  CRYPTO_MulOperandWidthSet(CRYPTO0, cryptoMulOperand256Bits);
284  CRYPTO_ResultWidthSet(CRYPTO0, cryptoResult256Bits);
285 
286  //Copy the first operand
287  CRYPTO_DDataWrite(&CRYPTO0->DDATA1, a);
288  //Copy the second operand
289  CRYPTO_DDataWrite(&CRYPTO0->DDATA2, b);
290 
291  //Compute R = A * B
292  CRYPTO_EXECUTE_2(CRYPTO0,
293  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
294  CRYPTO_CMD_INSTR_LMUL);
295 
296  //Wait for the instruction sequence to complete
297  CRYPTO_InstructionSequenceWait(CRYPTO0);
298 
299  //Copy the resulting value
300  CRYPTO_DDataRead(&CRYPTO0->DDATA0, u);
301  CRYPTO_DDataRead(&CRYPTO0->DDATA1, u + 8);
302 
303  //Release exclusive access to the CRYPTO module
305 
306  //Reduce bit 255 (2^255 = 19 mod p)
307  temp = (u[7] >> 31) * 19;
308  //Mask the most significant bit
309  u[7] &= 0x7FFFFFFF;
310 
311  //Perform fast modular reduction (first pass)
312  for(i = 0; i < 8; i++)
313  {
314  temp += u[i];
315  temp += (uint64_t) u[i + 8] * 38;
316  u[i] = temp & 0xFFFFFFFF;
317  temp >>= 32;
318  }
319 
320  //Reduce bit 256 (2^256 = 38 mod p)
321  temp *= 38;
322  //Reduce bit 255 (2^255 = 19 mod p)
323  temp += (u[7] >> 31) * 19;
324  //Mask the most significant bit
325  u[7] &= 0x7FFFFFFF;
326 
327  //Perform fast modular reduction (second pass)
328  for(i = 0; i < 8; i++)
329  {
330  temp += u[i];
331  u[i] = temp & 0xFFFFFFFF;
332  temp >>= 32;
333  }
334 
335  //Reduce non-canonical values
336  curve25519Red(r, u);
337 }
338 
339 
340 /**
341  * @brief Modular squaring
342  * @param[out] r Resulting integer R = (A ^ 2) mod p
343  * @param[in] a An integer such as 0 <= A < p
344  **/
345 
346 void curve25519Sqr(uint32_t *r, const uint32_t *a)
347 {
348  uint_t i;
349  uint64_t temp;
350  uint32_t u[16];
351 
352  //Acquire exclusive access to the CRYPTO module
354 
355  //Set wide arithmetic configuration
356  CRYPTO0->WAC = 0;
357  CRYPTO0->CTRL = 0;
358 
359  //Set CRYPTO module parameters
360  CRYPTO_MulOperandWidthSet(CRYPTO0, cryptoMulOperand256Bits);
361  CRYPTO_ResultWidthSet(CRYPTO0, cryptoResult256Bits);
362 
363  //Copy the operand
364  CRYPTO_DDataWrite(&CRYPTO0->DDATA1, a);
365 
366  //Compute R = A ^ 2
367  CRYPTO_EXECUTE_3(CRYPTO0,
368  CRYPTO_CMD_INSTR_DDATA1TODDATA2,
369  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
370  CRYPTO_CMD_INSTR_LMUL);
371 
372  //Wait for the instruction sequence to complete
373  CRYPTO_InstructionSequenceWait(CRYPTO0);
374 
375  //Copy the resulting value
376  CRYPTO_DDataRead(&CRYPTO0->DDATA0, u);
377  CRYPTO_DDataRead(&CRYPTO0->DDATA1, u + 8);
378 
379  //Release exclusive access to the CRYPTO module
381 
382  //Reduce bit 255 (2^255 = 19 mod p)
383  temp = (u[7] >> 31) * 19;
384  //Mask the most significant bit
385  u[7] &= 0x7FFFFFFF;
386 
387  //Perform fast modular reduction (first pass)
388  for(i = 0; i < 8; i++)
389  {
390  temp += u[i];
391  temp += (uint64_t) u[i + 8] * 38;
392  u[i] = temp & 0xFFFFFFFF;
393  temp >>= 32;
394  }
395 
396  //Reduce bit 256 (2^256 = 38 mod p)
397  temp *= 38;
398  //Reduce bit 255 (2^255 = 19 mod p)
399  temp += (u[7] >> 31) * 19;
400  //Mask the most significant bit
401  u[7] &= 0x7FFFFFFF;
402 
403  //Perform fast modular reduction (second pass)
404  for(i = 0; i < 8; i++)
405  {
406  temp += u[i];
407  u[i] = temp & 0xFFFFFFFF;
408  temp >>= 32;
409  }
410 
411  //Reduce non-canonical values
412  curve25519Red(r, u);
413 }
414 
415 #endif
416 #endif
unsigned int uint_t
Definition: compiler_port.h:50
General definitions for cryptographic algorithms.
void curve25519Red(uint32_t *r, const uint32_t *a)
Modular reduction.
Definition: curve25519.c:352
Curve25519 elliptic curve (constant-time implementation)
Debugging facilities.
ECC (Elliptic Curve Cryptography)
OsMutex efm32gg11CryptoMutex
EFM32 Giant Gecko 11 hardware cryptographic accelerator.
error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular multiplication.
void curve25519Sqr(uint32_t *r, const uint32_t *a)
Modular squaring.
error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
Fast modular squaring.
void curve25519Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
EFM32 Giant Gecko 11 public-key hardware accelerator.
error_t
Error codes.
Definition: error.h:43
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
uint8_t u
Definition: lldp_ext_med.h:213
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1444
error_t mpiGrow(Mpi *r, uint_t size)
Adjust the size of multiple precision integer.
Definition: mpi.c:94
uint8_t b
Definition: nbns_common.h:104
uint8_t r
Definition: ndp.h:346
uint8_t a
Definition: ndp.h:411
#define osStrcmp(s1, s2)
Definition: os_port.h:171
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
EC domain parameters.
Definition: ec.h:76
Mpi p
Prime.
Definition: ec.h:79
const char_t * name
Curve name.
Definition: ec.h:77
EcFastModAlgo mod
Fast modular reduction.
Definition: ec.h:85
Arbitrary precision integer.
Definition: mpi.h:80