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-2025 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.5.0
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 #endif
235 #if (EC_SUPPORT == ENABLED)
236 
237 /**
238  * @brief Scalar multiplication (fast calculation)
239  * @param[in] curve Elliptic curve parameters
240  * @param[out] r Resulting point R = d.S
241  * @param[in] d An integer d such as 0 <= d < p
242  * @param[in] s EC point
243  * @return Error code
244  **/
245 
246 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
247  const EcPoint3 *s)
248 {
249  //Compute R = d.S
250  return ecMulRegular(curve, r, d, s);
251 }
252 
253 
254 /**
255  * @brief Scalar multiplication (regular calculation)
256  * @param[in] curve Elliptic curve parameters
257  * @param[out] r Resulting point R = d.S
258  * @param[in] d An integer d such as 0 <= d < q
259  * @param[in] s EC point
260  * @return Error code
261  **/
262 
263 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
264  const EcPoint3 *s)
265 {
266  error_t error;
267  status_t status;
268  size_t modLen;
269  size_t orderLen;
270  caam_handle_t caamHandle;
271  caam_pkha_ecc_point_t input;
272  caam_pkha_ecc_point_t output;
273 
274  //Get the length of the modulus, in bytes
275  modLen = (curve->fieldSize + 7) / 8;
276  //Get the length of the order, in bytes
277  orderLen = (curve->orderSize + 7) / 8;
278 
279  //Check the length of the operands
280  if(modLen <= 66 && orderLen <= 66)
281  {
282  //Set CAAM job ring
283  caamHandle.jobRing = kCAAM_JobRing0;
284 
285  //Acquire exclusive access to the CAAM module
287 
288  //Copy domain parameters
289  ecScalarExport(curve->p, (modLen + 3) / 4, pkhaEccArgs.p, modLen,
291 
292  ecScalarExport(curve->a, (modLen + 3) / 4, pkhaEccArgs.a, modLen,
294 
295  ecScalarExport(curve->b, (modLen + 3) / 4, pkhaEccArgs.b, modLen,
297 
298  //Copy scalar
299  ecScalarExport(d, (orderLen + 3) / 4, pkhaEccArgs.d, orderLen,
301 
302  //Copy input point
303  ecScalarExport(s->x, (modLen + 3) / 4, pkhaEccArgs.gx, modLen,
305 
306  ecScalarExport(s->y, (modLen + 3) / 4, pkhaEccArgs.gy, modLen,
308 
309  input.X = pkhaEccArgs.gx;
310  input.Y = pkhaEccArgs.gy;
311 
312  //Specify the buffer where to store the output point
313  output.X = pkhaEccArgs.qx;
314  output.Y = pkhaEccArgs.qy;
315 
316  //Perform scalar multiplication
317  status = CAAM_PKHA_ECC_PointMul(CAAM, &caamHandle, &input, pkhaEccArgs.d,
318  orderLen, pkhaEccArgs.p, NULL, pkhaEccArgs.a, pkhaEccArgs.b,
319  modLen, kCAAM_PKHA_TimingEqualized, kCAAM_PKHA_IntegerArith, &output);
320 
321  //Check status code
322  if(status == kStatus_Success)
323  {
324  //Copy the x-coordinate of the result
327 
328  //Check status code
329  if(!error)
330  {
331  //Copy the y-coordinate of the result
334  }
335 
336  //Check status code
337  if(!error)
338  {
339  //Set the z-coordinate of the result
341  }
342  }
343  else
344  {
345  //Report an error
346  error = ERROR_FAILURE;
347  }
348 
349  //Release exclusive access to the CAAM module
351  }
352  else
353  {
354  //Report an error
355  error = ERROR_FAILURE;
356  }
357 
358  //Return status code
359  return error;
360 }
361 
362 
363 /**
364  * @brief Twin multiplication
365  * @param[in] curve Elliptic curve parameters
366  * @param[out] r Resulting point R = d0.S + d1.T
367  * @param[in] d0 An integer d such as 0 <= d0 < p
368  * @param[in] s EC point
369  * @param[in] d1 An integer d such as 0 <= d1 < p
370  * @param[in] t EC point
371  * @return Error code
372  **/
373 
374 error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0,
375  const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
376 {
377  error_t error;
378  EcPoint3 u;
379 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
380  EcState *state;
381 #else
382  EcState state[1];
383 #endif
384 
385 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
386  //Allocate working state
387  state = cryptoAllocMem(sizeof(EcState));
388  //Failed to allocate memory?
389  if(state == NULL)
390  return ERROR_OUT_OF_MEMORY;
391 #endif
392 
393  //Initialize working state
394  osMemset(state, 0, sizeof(EcState));
395  //Save elliptic curve parameters
396  state->curve = curve;
397 
398  //Compute d0.S
399  error = ecMulFast(curve, r, d0, s);
400 
401  //Check status code
402  if(!error)
403  {
404  //Compute d1.T
405  error = ecMulFast(curve, &u, d1, t);
406  }
407 
408  //Check status code
409  if(!error)
410  {
411  //Compute d0.S + d1.T
412  ecFullAdd(state, r, r, &u);
413  }
414 
415  //Return status code
416  return error;
417 }
418 
419 #endif
420 #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:104
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:1094
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:48
#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:1587
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
PKHA primitive arguments.
const EcCurve * curve
Definition: ec.h:446
Working state (point addition/subtraction/doubling)
Definition: ec.h:445
@ 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:821
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:138
ECC (Elliptic Curve Cryptography)
#define EC_MAX_MODULUS_SIZE
Definition: ec.h:284
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:215
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64