mimxrt1170_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file mimxrt1170_crypto_pkc.c
3  * @brief i.MX RT1170 public-key hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "fsl_device_registers.h"
36 #include "fsl_caam.h"
37 #include "core/crypto.h"
40 #include "ecc/ec.h"
41 #include "ecc/ec_misc.h"
42 #include "mpi/mpi.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (MIMXRT1170_CRYPTO_PKC_SUPPORT == ENABLED)
47 
48 //Global variables
51 
52 #if (MPI_SUPPORT == ENABLED)
53 
54 /**
55  * @brief Modular multiplication
56  * @param[out] r Resulting integer R = A * B mod P
57  * @param[in] a The first operand A
58  * @param[in] b The second operand B
59  * @param[in] p The modulus P
60  * @return Error code
61  **/
62 
63 error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
64 {
65  error_t error;
66  status_t status;
67  size_t aLen;
68  size_t bLen;
69  size_t modLen;
70  size_t resultLen;
71  caam_handle_t caamHandle;
72  Mpi ta;
73  Mpi tb;
74 
75  //Initialize multiple precision integers
76  mpiInit(&ta);
77  mpiInit(&tb);
78 
79  //Get the length of the modulus, in bytes
80  modLen = mpiGetByteLength(p);
81 
82  //The accelerator supports operand lengths up to 4096 bits
83  if(modLen <= 512)
84  {
85  //Reduce the first operand
86  error = mpiMod(&ta, a, p);
87 
88  //Check status code
89  if(!error)
90  {
91  //Reduce the second operand
92  error = mpiMod(&tb, b, p);
93  }
94 
95  //Check status code
96  if(!error)
97  {
98  //Get the length of the first operand, in bytes
99  aLen = mpiGetByteLength(&ta);
100  //Get the length of the second operand, in bytes
101  bLen = mpiGetByteLength(&tb);
102 
103  //Set CAAM job ring
104  caamHandle.jobRing = kCAAM_JobRing0;
105 
106  //Acquire exclusive access to the CAAM module
108 
109  //Copy first operand
110  mpiWriteRaw(&ta, pkhaArgs.a, aLen);
111  //Copy second operand
112  mpiWriteRaw(&tb, pkhaArgs.b, bLen);
113  //Copy modulus
114  mpiWriteRaw(p, pkhaArgs.p, modLen);
115 
116  //Perform modular multiplication
117  status = CAAM_PKHA_ModMul(CAAM, &caamHandle, pkhaArgs.a, aLen,
118  pkhaArgs.b, bLen, pkhaArgs.p, modLen, pkhaArgs.r, &resultLen,
119  kCAAM_PKHA_IntegerArith, kCAAM_PKHA_NormalValue,
120  kCAAM_PKHA_NormalValue, kCAAM_PKHA_TimingEqualized);
121 
122  //Check status code
123  if(status == kStatus_Success)
124  {
125  //Copy resulting integer
126  error = mpiReadRaw(r, pkhaArgs.r, resultLen);
127  }
128  else
129  {
130  //Report an error
131  error = ERROR_FAILURE;
132  }
133 
134  //Release exclusive access to the CAAM module
136  }
137  }
138  else
139  {
140  //Report an error
141  error = ERROR_FAILURE;
142  }
143 
144  //Release multiple precision integers
145  mpiFree(&ta);
146  mpiFree(&tb);
147 
148  //Return status code
149  return error;
150 }
151 
152 
153 /**
154  * @brief Modular exponentiation
155  * @param[out] r Resulting integer R = A ^ E mod P
156  * @param[in] a Pointer to a multiple precision integer
157  * @param[in] e Exponent
158  * @param[in] p Modulus
159  * @return Error code
160  **/
161 
162 error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
163 {
164  error_t error;
165  status_t status;
166  size_t scalarLen;
167  size_t expLen;
168  size_t modLen;
169  size_t resultLen;
170  caam_handle_t caamHandle;
171 
172  //Get the length of the exponent, in bytes
173  expLen = mpiGetByteLength(e);
174  //Get the length of the modulus, in bytes
175  modLen = mpiGetByteLength(p);
176 
177  //The accelerator supports operand lengths up to 4096 bits
178  if(modLen > 0 && modLen <= 512 && expLen > 0 && expLen <= 512)
179  {
180  //Reduce the integer first
181  error = mpiMod(r, a, p);
182 
183  //Check status code
184  if(!error)
185  {
186  //Get the length of the integer, in bytes
187  scalarLen = mpiGetByteLength(r);
188 
189  //Set CAAM job ring
190  caamHandle.jobRing = kCAAM_JobRing0;
191 
192  //Acquire exclusive access to the CAAM module
194 
195  //Copy scalar
196  mpiWriteRaw(r, pkhaArgs.a, scalarLen);
197  //Copy exponent
198  mpiWriteRaw(e, pkhaArgs.e, expLen);
199  //Copy modulus
200  mpiWriteRaw(p, pkhaArgs.p, modLen);
201 
202  //Perform modular exponentiation
203  status = CAAM_PKHA_ModExp(CAAM, &caamHandle, pkhaArgs.a, scalarLen,
204  pkhaArgs.p, modLen, pkhaArgs.e, expLen, pkhaArgs.r, &resultLen,
205  kCAAM_PKHA_IntegerArith, kCAAM_PKHA_NormalValue,
206  kCAAM_PKHA_TimingEqualized);
207 
208  //Check status code
209  if(status == kStatus_Success)
210  {
211  //Copy resulting integer
212  error = mpiReadRaw(r, pkhaArgs.r, resultLen);
213  }
214  else
215  {
216  //Report an error
217  error = ERROR_FAILURE;
218  }
219 
220  //Release exclusive access to the CAAM module
222  }
223  }
224  else
225  {
226  //Report an error
227  error = ERROR_FAILURE;
228  }
229 
230  //Return status code
231  return error;
232 }
233 
234 
235 /**
236  * @brief Test whether a number is probable prime
237  * @param[in] a Pointer to a multiple precision integer
238  * @return Error code
239  **/
240 
242 {
243  error_t error;
244  status_t status;
245  bool result;
246  size_t n;
247  uint8_t k;
248  caam_handle_t caamHandle;
249 
250  //Get the length of the input integer, in bits
251  n = mpiGetBitLength(a);
252 
253  //The accelerator supports operand lengths up to 4096 bits
254  if(n > 0 && n <= 4096)
255  {
256  //The number of repetitions controls the error probability
257  if(n >= 1300)
258  {
259  k = 2;
260  }
261  else if(n >= 850)
262  {
263  k = 3;
264  }
265  else if(n >= 650)
266  {
267  k = 4;
268  }
269  else if(n >= 550)
270  {
271  k = 5;
272  }
273  else if(n >= 450)
274  {
275  k = 6;
276  }
277  else if(n >= 400)
278  {
279  k = 7;
280  }
281  else if(n >= 350)
282  {
283  k = 8;
284  }
285  else if(n >= 300)
286  {
287  k = 9;
288  }
289  else if(n >= 250)
290  {
291  k = 12;
292  }
293  else if(n >= 200)
294  {
295  k = 15;
296  }
297  else if(n >= 150)
298  {
299  k = 18;
300  }
301  else
302  {
303  k = 27;
304  }
305 
306  //Get the length of the input integer, in bytes
307  n = (n + 7) / 8;
308 
309  //Set CAAM job ring
310  caamHandle.jobRing = kCAAM_JobRing0;
311 
312  //Acquire exclusive access to the CAAM module
314 
315  //Copy input integer
316  mpiWriteRaw(a, pkhaArgs.a, n);
317 
318  //Generate a random seed
319  status = CAAM_RNG_GetRandomData(CAAM, &caamHandle, kCAAM_RngStateHandle0,
320  pkhaArgs.r, n, kCAAM_RngDataAny, NULL);
321 
322  //Check status code
323  if(status == kStatus_Success)
324  {
325  //Clear result first
326  result = false;
327 
328  //Test candidate prime number
329  status = CAAM_PKHA_PrimalityTest(CAAM, &caamHandle, pkhaArgs.r, n,
330  &k, sizeof(k), pkhaArgs.a, n, &result);
331 
332  //Check status code
333  if(status == kStatus_Success)
334  {
335  //Check result
336  if(result)
337  {
338  //The number is probably prime
339  error = NO_ERROR;
340  }
341  else
342  {
343  //The number is not prime
344  error = ERROR_INVALID_VALUE;
345  }
346  }
347  else
348  {
349  //Report an error
350  error = ERROR_FAILURE;
351  }
352  }
353 
354  //Release exclusive access to the CAAM module
356  }
357  else
358  {
359  //Report an error
360  error = ERROR_FAILURE;
361  }
362 
363  //Return status code
364  return error;
365 }
366 
367 #endif
368 #if (EC_SUPPORT == ENABLED)
369 
370 /**
371  * @brief Scalar multiplication (fast calculation)
372  * @param[in] curve Elliptic curve parameters
373  * @param[out] r Resulting point R = d.S
374  * @param[in] d An integer d such as 0 <= d < p
375  * @param[in] s EC point
376  * @return Error code
377  **/
378 
379 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
380  const EcPoint3 *s)
381 {
382  //Compute R = d.S
383  return ecMulRegular(curve, r, d, s);
384 }
385 
386 
387 /**
388  * @brief Scalar multiplication (regular calculation)
389  * @param[in] curve Elliptic curve parameters
390  * @param[out] r Resulting point R = d.S
391  * @param[in] d An integer d such as 0 <= d < q
392  * @param[in] s EC point
393  * @return Error code
394  **/
395 
396 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
397  const EcPoint3 *s)
398 {
399  error_t error;
400  status_t status;
401  size_t modLen;
402  size_t orderLen;
403  caam_handle_t caamHandle;
404  caam_pkha_ecc_point_t input;
405  caam_pkha_ecc_point_t output;
406 
407  //Get the length of the modulus, in bytes
408  modLen = (curve->fieldSize + 7) / 8;
409  //Get the length of the order, in bytes
410  orderLen = (curve->orderSize + 7) / 8;
411 
412  //Check the length of the operands
413  if(modLen <= 66 && orderLen <= 66)
414  {
415  //Set CAAM job ring
416  caamHandle.jobRing = kCAAM_JobRing0;
417 
418  //Acquire exclusive access to the CAAM module
420 
421  //Copy domain parameters
422  ecScalarExport(curve->p, (modLen + 3) / 4, pkhaEccArgs.p, modLen,
424 
425  ecScalarExport(curve->a, (modLen + 3) / 4, pkhaEccArgs.a, modLen,
427 
428  ecScalarExport(curve->b, (modLen + 3) / 4, pkhaEccArgs.b, modLen,
430 
431  //Copy scalar
432  ecScalarExport(d, (orderLen + 3) / 4, pkhaEccArgs.d, orderLen,
434 
435  //Copy input point
436  ecScalarExport(s->x, (modLen + 3) / 4, pkhaEccArgs.gx, modLen,
438 
439  ecScalarExport(s->y, (modLen + 3) / 4, pkhaEccArgs.gy, modLen,
441 
442  input.X = pkhaEccArgs.gx;
443  input.Y = pkhaEccArgs.gy;
444 
445  //Specify the buffer where to store the output point
446  output.X = pkhaEccArgs.qx;
447  output.Y = pkhaEccArgs.qy;
448 
449  //Perform scalar multiplication
450  status = CAAM_PKHA_ECC_PointMul(CAAM, &caamHandle, &input, pkhaEccArgs.d,
451  orderLen, pkhaEccArgs.p, NULL, pkhaEccArgs.a, pkhaEccArgs.b,
452  modLen, kCAAM_PKHA_TimingEqualized, kCAAM_PKHA_IntegerArith, &output);
453 
454  //Check status code
455  if(status == kStatus_Success)
456  {
457  //Copy the x-coordinate of the result
460 
461  //Check status code
462  if(!error)
463  {
464  //Copy the y-coordinate of the result
467  }
468 
469  //Check status code
470  if(!error)
471  {
472  //Set the z-coordinate of the result
474  }
475  }
476  else
477  {
478  //Report an error
479  error = ERROR_FAILURE;
480  }
481 
482  //Release exclusive access to the CAAM module
484  }
485  else
486  {
487  //Report an error
488  error = ERROR_FAILURE;
489  }
490 
491  //Return status code
492  return error;
493 }
494 
495 
496 /**
497  * @brief Twin multiplication
498  * @param[in] curve Elliptic curve parameters
499  * @param[out] r Resulting point R = d0.S + d1.T
500  * @param[in] d0 An integer d such as 0 <= d0 < p
501  * @param[in] s EC point
502  * @param[in] d1 An integer d such as 0 <= d1 < p
503  * @param[in] t EC point
504  * @return Error code
505  **/
506 
507 error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0,
508  const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
509 {
510  error_t error;
511  EcPoint3 u;
512 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
513  EcState *state;
514 #else
515  EcState state[1];
516 #endif
517 
518 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
519  //Allocate working state
520  state = cryptoAllocMem(sizeof(EcState));
521  //Failed to allocate memory?
522  if(state == NULL)
523  return ERROR_OUT_OF_MEMORY;
524 #endif
525 
526  //Initialize working state
527  osMemset(state, 0, sizeof(EcState));
528  //Save elliptic curve parameters
529  state->curve = curve;
530 
531  //Compute d0.S
532  error = ecMulFast(curve, r, d0, s);
533 
534  //Check status code
535  if(!error)
536  {
537  //Compute d1.T
538  error = ecMulFast(curve, &u, d1, t);
539  }
540 
541  //Check status code
542  if(!error)
543  {
544  //Compute d0.S + d1.T
545  ecFullAdd(state, r, r, &u);
546  }
547 
548  //Return status code
549  return error;
550 }
551 
552 #endif
553 #endif
error_t ecScalarImport(uint32_t *r, uint_t n, const uint8_t *input, size_t length, EcScalarFormat format)
Octet string to integer conversion.
Definition: ec_misc.c:54
uint8_t b
Definition: nbns_common.h:122
uint8_t a
Definition: ndp.h:411
error_t ecScalarExport(const uint32_t *a, uint_t n, uint8_t *output, size_t length, EcScalarFormat format)
Integer to octet string conversion.
Definition: ec_misc.c:150
Arbitrary precision integer.
Definition: mpi.h:102
PKHA ECC primitive arguments.
uint8_t p
Definition: ndp.h:300
error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
uint8_t t
Definition: lldp_ext_med.h:212
void ecFullAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point addition.
Definition: ec.c:1136
OsMutex mimxrt1170CryptoMutex
uint8_t r[512]
#define mpiWriteRaw(a, data, length)
Definition: crypto_legacy.h:36
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
uint8_t a[512]
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:49
#define mpiReadRaw(r, data, length)
Definition: crypto_legacy.h:35
uint8_t r
Definition: ndp.h:346
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1589
uint8_t p[512]
error_t
Error codes.
Definition: error.h:43
uint8_t e[512]
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
Helper routines for ECC.
MPI (Multiple Precision Integer Arithmetic)
General definitions for cryptographic algorithms.
i.MX RT1170 hardware cryptographic accelerator (CAAM)
uint8_t u
Definition: lldp_ext_med.h:213
i.MX RT1170 public-key hardware accelerator
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:255
PKHA primitive arguments.
const EcCurve * curve
Definition: ec.h:446
error_t mpiCheckProbablePrime(const Mpi *a)
Test whether a number is probable prime.
@ ERROR_INVALID_VALUE
Definition: error.h:116
Working state (point addition/subtraction/doubling)
Definition: ec.h:445
uint8_t n
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
EC point (projective coordinates)
Definition: ec.h:409
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
uint8_t b[512]
error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
Modular multiplication.
error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
#define cryptoAllocMem(size)
Definition: crypto.h:961
uint8_t s
Definition: igmp_common.h:234
PkhaArgs pkhaArgs
#define EcCurve
Definition: ec.h:346
error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
Twin multiplication.
#define osMemset(p, value, length)
Definition: os_port.h:141
ECC (Elliptic Curve Cryptography)
#define EC_MAX_MODULUS_SIZE
Definition: ec.h:284
@ NO_ERROR
Success.
Definition: error.h:44
error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
Debugging facilities.
PkhaEccArgs pkhaEccArgs
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:216
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:65