same54_crypto_pukcc.c
Go to the documentation of this file.
1 /**
2  * @file same54_crypto_pukcc.c
3  * @brief SAME54 PUKCC public key accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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 1.9.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "same54.h"
36 #include "pukcc/CryptoLib_typedef_pb.h"
37 #include "pukcc/CryptoLib_Headers_pb.h"
38 #include "core/crypto.h"
39 #include "hardware/same54_crypto.h"
41 #include "pkc/rsa.h"
42 #include "ecc/ec.h"
43 #include "ecc/ecdsa.h"
44 #include "mpi/mpi.h"
45 #include "debug.h"
46 
47 //Global variables
48 PPUKCL_PARAM pvPUKCLParam;
49 PUKCL_PARAM PUKCLParam;
50 
51 
52 /**
53  * @brief Initialize PUKCC public key accelerator
54  **/
55 
57 {
58  //Enable PUKCC clock
59  MCLK->AHBMASK.reg |= MCLK_AHBMASK_PUKCC;
60 
61  //Clear PUKCLParam structure
62  memset(&PUKCLParam, 0, sizeof(PUKCL_PARAM));
64 
65  //Initialize PUKCC
66  vPUKCL_Process(SelfTest, pvPUKCLParam);
67 
68  //Check status code
69  if(PUKCL(u2Status) != PUKCL_OK)
70  return ERROR_FAILURE;
71 
72  //Check version number
73  if(pvPUKCLParam->P.PUKCL_SelfTest.u4Version != PUKCL_VERSION)
74  return ERROR_FAILURE;
75 
76  //The return values from the SelfTest service must be compared against
77  //known values mentioned in the service description
78  if(pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum1 != 0x6E70DDD2)
79  return ERROR_FAILURE;
80 
81  if(pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum2 != 0x25C8D64F)
82  return ERROR_FAILURE;
83 
84  //Successful initialization
85  return NO_ERROR;
86 }
87 
88 
89 /**
90  * @brief Import byte array
91  * @param[in,out] dest Pointer to the crypto memory
92  * @param[in] array Pointer to the byte array
93  * @param[in] arrayLen Length of the array to be copied
94  * @param[in] totalLen Desired length of the area, in bytes
95  * @return Pointer to the initialized area
96  **/
97 
98 uint8_t *pukccImportArray(uint8_t **dest, const uint8_t *array,
99  size_t arrayLen, size_t totalLen)
100 {
101  size_t i;
102  uint8_t *p;
103 
104  //Point to the crypto memory
105  p = *dest;
106 
107  //Copy the byte array to the crypto memory
108  for(i = 0; i < arrayLen; i++)
109  {
110  p[i] = array[arrayLen - 1 - i];
111  }
112 
113  //Pad the data with zeroes
114  while(i < totalLen)
115  {
116  p[i++] = 0;
117  }
118 
119  //Advance data pointer
120  *dest = p + i;
121 
122  //Return a pointer to the initialized area
123  return p;
124 }
125 
126 
127 /**
128  * @brief Import multiple-precision integer
129  * @param[in,out] dest Pointer to the crypto memory
130  * @param[in] src Pointer to the multiple-precision integer
131  * @param[in] totalLen Desired length of the area, in bytes
132  * @return Pointer to the initialized area
133  **/
134 
135 uint8_t *pukccImportMpi(uint8_t **dest, const Mpi *src, size_t totalLen)
136 {
137  uint8_t *p;
138 
139  //Point to the crypto memory
140  p = *dest;
141 
142  //Copy the multiple-precision integer to the crypto memory
143  mpiExport(src, p, totalLen, MPI_FORMAT_LITTLE_ENDIAN);
144 
145  //Advance data pointer
146  *dest = p + totalLen;
147 
148  //Return a pointer to the initialized area
149  return p;
150 }
151 
152 
153 /**
154  * @brief Initialize workspace area
155  * @param[in,out] dest Pointer to the crypto memory
156  * @param[in] totalLen Desired length of the area, in bytes
157  * @return Pointer to the initialized area
158  **/
159 
160 uint8_t *pukccWorkspace(uint8_t **dest, size_t totalLen)
161 {
162  size_t i;
163  uint8_t *p;
164 
165  //Point to the crypto memory
166  p = *dest;
167 
168  //Initialize workspace area
169  for(i = 0; i < totalLen; i++)
170  {
171  p[i] = 0;
172  }
173 
174  //Advance data pointer
175  *dest = p + i;
176 
177  //Return a pointer to the initialized area
178  return p;
179 }
180 
181 
182 /**
183  * @brief Multiple precision multiplication
184  * @param[out] r Resulting integer R = A * B
185  * @param[in] a First operand A
186  * @param[in] b Second operand B
187  * @return Error code
188  **/
189 
190 error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
191 {
192  error_t error;
193  size_t m;
194  size_t n;
195  uint8_t *pos;
196  PukccFmultParams params;
197 
198  //Retrieve the length of the input integer, in bytes
199  m = mpiGetByteLength(a);
200  m = (m + 3U) & ~3U;
201 
202  //Retrieve the length of the modulus, in bytes
203  n = mpiGetByteLength(b);
204  n = (n + 3U) & ~3U;
205 
206  //Acquire exclusive access to the PUKCC accelerator
208 
209  //Point to the crypto memory
210  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
211 
212  //Copy input integer X
213  params.x = pukccImportMpi(&pos, a, m);
214  //Copy input integer Y
215  params.y = pukccImportMpi(&pos, b, n);
216 
217  //Unused parameters
218  params.z = 0;
219  params.mod = 0;
220  params.cns = 0;
221 
222  //Initialize output integer R
223  params.r = pukccWorkspace(&pos, m + n);
224 
225  //Set Fmult service parameters
226  PUKCL(u2Option) = SET_MULTIPLIEROPTION(PUKCL_FMULT_ONLY) |
227  SET_CARRYOPTION(CARRY_NONE);
228  PUKCL(Specific).CarryIn = 0;
229  PUKCL(Specific).Gf2n = 0;
230  PUKCL_Fmult(u2ModLength) = 0;
231  PUKCL_Fmult(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
232  PUKCL_Fmult(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
233  PUKCL_Fmult(u2XLength) = m;
234  PUKCL_Fmult(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
235  PUKCL_Fmult(u2YLength) = n;
236  PUKCL_Fmult(nu1YBase) = PUKCC_FAR_TO_NEAR(params.y);
237  PUKCL_Fmult(nu1ZBase) = PUKCC_FAR_TO_NEAR(params.z);
238  PUKCL_Fmult(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
239 
240  //Perform multiplication
241  vPUKCL_Process(Fmult, pvPUKCLParam);
242 
243  //Check status code
244  if(PUKCL(u2Status) == PUKCL_OK)
245  {
246  //If FMult is without reduction, R is filled with the final result
247  error = mpiImport(r, params.r, m + n, MPI_FORMAT_LITTLE_ENDIAN);
248  }
249  else
250  {
251  //Report an error
252  error = ERROR_FAILURE;
253  }
254 
255  //Release exclusive access to the PUKCC accelerator
257 
258  //Return error code
259  return error;
260 }
261 
262 
263 /**
264  * @brief Modulo operation
265  * @param[out] r Resulting integer R = A mod P
266  * @param[in] a The multiple precision integer to be reduced
267  * @param[in] p The modulus P
268  * @return Error code
269  **/
270 
271 error_t mpiMod2(Mpi *r, const Mpi *a, const Mpi *p)
272 {
273  error_t error;
274  size_t n;
275  size_t modLen;
276  uint8_t *pos;
277  PukccRedModParams params;
278 
279  //Retrieve the length of the input integer, in bytes
280  n = mpiGetByteLength(a);
281 
282  //Retrieve the length of the modulus, in bytes
283  modLen = mpiGetByteLength(p);
284  modLen = (modLen + 3U) & ~3U;
285 
286  //Check the length of the input integer
287  if(n > (2 * modLen + 4))
288  return ERROR_INVALID_LENGTH;
289 
290  //Acquire exclusive access to the PUKCC accelerator
292 
293  //Point to the crypto memory
294  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
295 
296  //Copy modulus
297  params.mod = pukccImportMpi(&pos, p, modLen + 4);
298  //Initialize workspace CNS
299  params.cns = pukccWorkspace(&pos, 68);
300  //Initialize output integer R
301  params.r = pukccWorkspace(&pos, modLen + 4);
302  //Copy input integer X
303  params.x = pukccImportMpi(&pos, a, 2 * modLen + 8);
304 
305  //Set RedMod service parameters
306  PUKCL(u2Option) = PUKCL_REDMOD_REDUCTION | PUKCL_REDMOD_USING_DIVISION;
307  PUKCL(Specific).CarryIn = 0;
308  PUKCL(Specific).Gf2n = 0;
309  PUKCL_RedMod(u2ModLength) = modLen;
310  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
311  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
312  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
313  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
314 
315  //Perform modular reduction setup
316  vPUKCL_Process(RedMod, pvPUKCLParam);
317 
318  //Check status code
319  if(PUKCL(u2Status) == PUKCL_OK)
320  {
321  //If FMult is without reduction, R is filled with the final result
322  error = mpiImport(r, params.r, modLen, MPI_FORMAT_LITTLE_ENDIAN);
323  }
324  else
325  {
326  //Report an error
327  error = ERROR_FAILURE;
328  }
329 
330  //Release exclusive access to the PUKCC accelerator
332 
333  //Return error code
334  return error;
335 }
336 
337 
338 /**
339  * @brief Modular inverse
340  * @param[out] r Resulting integer R = A^-1 mod P
341  * @param[in] a The multiple precision integer A
342  * @param[in] p The modulus P
343  * @return Error code
344  **/
345 
346 error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
347 {
348  error_t error;
349  size_t m;
350  size_t n;
351  uint8_t *pos;
352  PukccGcdParams params;
353 
354  //Retrieve the length of the input integer, in bytes
355  m = mpiGetByteLength(a);
356  //Retrieve the length of the modulus, in bytes
357  n = mpiGetByteLength(p);
358 
359  //Compute the length of the the areas X, Y, A and Z
360  n = MAX(n, m);
361  n = (n + 7U) & ~3U;
362 
363  //Acquire exclusive access to the PUKCC accelerator
365 
366  //Point to the crypto memory
367  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
368 
369  //Copy input integer
370  params.x = pukccImportMpi(&pos, a, n);
371  //Copy modulus
372  params.y = pukccImportMpi(&pos, p, n);
373  //Initialize output integer A
374  params.a = pukccWorkspace(&pos, n);
375  //Initialize output integer Z
376  params.z = pukccWorkspace(&pos, n + 4);
377  //Initialize workspace >
378  params.w = pukccWorkspace(&pos, 32);
379 
380  //Set GCD service parameters
381  PUKCL(Specific).Gf2n = 0;
382  PUKCL_GCD(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
383  PUKCL_GCD(nu1YBase) = PUKCC_FAR_TO_NEAR(params.y);
384  PUKCL_GCD(nu1ABase) = PUKCC_FAR_TO_NEAR(params.a);
385  PUKCL_GCD(nu1ZBase) = PUKCC_FAR_TO_NEAR(params.z);
386  PUKCL_GCD(nu1WorkSpace) = PUKCC_FAR_TO_NEAR(params.w);
387  PUKCL_GCD(u2Length) = n;
388 
389  //Calculate the modular inverse
390  vPUKCL_Process(GCD, pvPUKCLParam);
391 
392  //Check status code
393  if(PUKCL(u2Status) == PUKCL_OK)
394  {
395  //Copy output integer Z
396  error = mpiImport(r, params.a, n, MPI_FORMAT_LITTLE_ENDIAN);
397  }
398  else
399  {
400  //Report an error
401  error = ERROR_FAILURE;
402  }
403 
404  //Release exclusive access to the PUKCC accelerator
406 
407  //Return error code
408  return error;
409 }
410 
411 
412 /**
413  * @brief Modular exponentiation
414  * @param[out] r Resulting integer R = A ^ E mod P
415  * @param[in] a Pointer to a multiple precision integer
416  * @param[in] e Exponent
417  * @param[in] p Modulus
418  * @return Error code
419  **/
420 
421 error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
422 {
423  error_t error;
424  size_t n;
425  size_t modLen;
426  size_t expLen;
427  uint8_t *pos;
428  PukccExpModParams params;
429 
430  //Retrieve the length of the input integer, in bytes
431  n = mpiGetByteLength(a);
432 
433  //Retrieve the length of the modulus, in bytes
434  modLen = mpiGetByteLength(p);
435  modLen = (modLen + 3U) & ~3U;
436 
437  //Retrieve the length of the exponent, in bytes
438  expLen = mpiGetByteLength(e);
439  expLen = (expLen + 3U) & ~3U;
440 
441  //Check the length of the input integer
442  if(n > (2 * modLen + 4))
443  return ERROR_INVALID_LENGTH;
444 
445  //Acquire exclusive access to the PUKCC accelerator
447 
448  //Point to the crypto memory
449  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
450 
451  //Copy modulus
452  params.mod = pukccImportMpi(&pos, p, modLen + 4);
453  //Initialize reduction constant
454  params.cns = pukccWorkspace(&pos, modLen + 12);
455  //Initialize workspace R
456  params.r = pukccWorkspace(&pos, 64);
457  //Initialize workspace X
458  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
459 
460  //Set RedMod service parameters
461  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
462  PUKCL(Specific).CarryIn = 0;
463  PUKCL(Specific).Gf2n = 0;
464  PUKCL_RedMod(u2ModLength) = modLen;
465  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
466  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
467  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
468  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
469 
470  //Perform modular reduction setup
471  vPUKCL_Process(RedMod, pvPUKCLParam);
472 
473  //Check status code
474  if(PUKCL(u2Status) == PUKCL_OK)
475  {
476  //Point to the crypto memory
477  pos = params.r;
478 
479  //Copy input number
480  params.x = pukccImportMpi(&pos, a, 2 * modLen + 8);
481 
482  //Set RedMod service parameters
483  PUKCL(u2Option) = PUKCL_REDMOD_REDUCTION | PUKCL_REDMOD_USING_FASTRED;
484  PUKCL(Specific).CarryIn = 0;
485  PUKCL(Specific).Gf2n = 0;
486  PUKCL_RedMod(u2ModLength) = modLen;
487  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
488  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
489  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.x);
490  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
491 
492  //Perform fast modular reduction
493  vPUKCL_Process(RedMod, pvPUKCLParam);
494  }
495 
496  //Check status code
497  if(PUKCL(u2Status) == PUKCL_OK)
498  {
499  //Set RedMod service parameters
500  PUKCL(u2Option) = PUKCL_REDMOD_NORMALIZE;
501  PUKCL(Specific).CarryIn = 0;
502  PUKCL(Specific).Gf2n = 0;
503  PUKCL_RedMod(u2ModLength) = modLen;
504  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
505  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
506  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.x);
507  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
508 
509  //Normalize the result
510  vPUKCL_Process(RedMod, pvPUKCLParam);
511  }
512 
513  //Check status code
514  if(PUKCL(u2Status) == PUKCL_OK)
515  {
516  //The number to be exponentiated is followed by four 32-bit words
517  //that are used during the computations as a workspace
518  pos = params.x + modLen;
519  pukccWorkspace(&pos, 16);
520 
521  //The exponent must be given with a supplemental word on the LSB
522  //side (low addresses). This word shall be set to zero
523  params.exp = pukccWorkspace(&pos, 4);
524  pukccImportMpi(&pos, e, expLen);
525 
526  //Initialize workspace
527  params.w = pukccWorkspace(&pos, 3 * (modLen + 4) + 8);
528 
529  //Set ExpMod service parameters
530  PUKCL(u2Option) = PUKCL_EXPMOD_REGULARRSA | PUKCL_EXPMOD_WINDOWSIZE_1 |
531  PUKCL_EXPMOD_EXPINPUKCCRAM;
532  PUKCL_ExpMod(u2ModLength) = modLen;
533  PUKCL_ExpMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
534  PUKCL_ExpMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
535  PUKCL_ExpMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
536  PUKCL_ExpMod(nu1PrecompBase) = PUKCC_FAR_TO_NEAR(params.w);
537  PUKCL_ExpMod(u2ExpLength) = expLen;
538  PUKCL_ExpMod(pfu1ExpBase) = params.exp;
539  PUKCL_ExpMod(u1Blinding) = 0;
540 
541  //Perform modular exponentiation
542  vPUKCL_Process(ExpMod, pvPUKCLParam);
543  }
544 
545  //Check status code
546  if(PUKCL(u2Status) == PUKCL_OK)
547  {
548  //Copy resulting integer
549  error = mpiImport(r, params.x, modLen, MPI_FORMAT_LITTLE_ENDIAN);
550  }
551  else
552  {
553  //Report an error
554  error = ERROR_FAILURE;
555  }
556 
557  //Release exclusive access to the PUKCC accelerator
559 
560  //Return error code
561  return error;
562 }
563 
564 
565 /**
566  * @brief RSA decryption primitive
567  * @param[in] key RSA private key
568  * @param[in] c Ciphertext representative
569  * @param[out] m Message representative
570  * @return Error code
571  **/
572 
573 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
574 {
575  error_t error;
576 
577  //Use the Chinese remainder algorithm?
578  if(key->n.size && key->p.size && key->q.size &&
579  key->dp.size && key->dq.size && key->qinv.size)
580  {
581  size_t n;
582  size_t pLen;
583  size_t qLen;
584  size_t dpLen;
585  size_t dqLen;
586  size_t modLen;
587  size_t expLen;
588  uint8_t *pos;
589  PukccCrtParams params;
590 
591  //Retrieve the length of the ciphertext, in bytes
592  n = mpiGetByteLength(c);
593 
594  //Retrieve the length of the primes, in bytes
595  pLen = mpiGetByteLength(&key->p);
596  qLen = mpiGetByteLength(&key->q);
597  modLen = MAX(pLen, qLen);
598  modLen = MAX(modLen, 12);
599  modLen = (modLen + 3U) & ~3U;
600 
601  //Retrieve the length of the reduced exponents, in bytes
602  dpLen = mpiGetByteLength(&key->dp);
603  dqLen = mpiGetByteLength(&key->dq);
604  expLen = MAX(dpLen, dqLen);
605  expLen = (expLen + 3U) & ~3U;
606 
607  //Check the length of the ciphertext
608  if(n > (2 * modLen))
609  return ERROR_INVALID_LENGTH;
610 
611  //Acquire exclusive access to the PUKCC accelerator
613 
614  //Point to the crypto memory
615  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
616 
617  //Copy primes
618  params.q = pukccImportMpi(&pos, &key->q, modLen + 4);
619  params.p = pukccImportMpi(&pos, &key->p, modLen + 4);
620 
621  //Copy input number
622  params.x = pukccImportMpi(&pos, c, 2 * modLen + 16);
623 
624  //The reduced exponents must be given with a supplemental word on the
625  //LSB side (low addresses). This word shall be set to zero
626  params.dq = pukccWorkspace(&pos, 4);
627  pukccImportMpi(&pos, &key->dq, expLen);
628  params.dp = pukccWorkspace(&pos, 4);
629  pukccImportMpi(&pos, &key->dp, expLen);
630 
631  //Copy R value
632  params.r = pukccImportMpi(&pos, &key->qinv, modLen + 4);
633  //Initialize workspace
634  pukccWorkspace(&pos, 3 * (modLen + 4) + MAX(64, 1 * (modLen + 4)) + 8);
635 
636  //Set CRT service parameters
637  PUKCL(u2Option) = PUKCL_EXPMOD_REGULARRSA | PUKCL_EXPMOD_WINDOWSIZE_1 |
638  PUKCL_EXPMOD_EXPINPUKCCRAM;
639  PUKCL_CRT(u2ModLength) = modLen;
640  PUKCL_CRT(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.q);
641  PUKCL_CRT(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
642  PUKCL_CRT(nu1PrecompBase) = PUKCC_FAR_TO_NEAR(params.r);
643  PUKCL_CRT(u2ExpLength) = expLen;
644  PUKCL_CRT(pfu1ExpBase) = params.dq;
645  PUKCL_CRT(u1Blinding) = 0;
646 
647  //Perform modular exponentiation (with CRT)
648  vPUKCL_Process(CRT, pvPUKCLParam);
649 
650  //Check status code
651  if(PUKCL(u2Status) == PUKCL_OK)
652  {
653  //Copy resulting integer
654  error = mpiImport(m, params.x, 2 * modLen, MPI_FORMAT_LITTLE_ENDIAN);
655  }
656  else
657  {
658  //Report an error
659  error = ERROR_FAILURE;
660  }
661 
662  //Release exclusive access to the PUKCC accelerator
664  }
665  //Use modular exponentiation?
666  else if(key->n.size && key->d.size)
667  {
668  //Perform modular exponentiation (without CRT)
669  error = mpiExpMod(m, c, &key->d, &key->n);
670  }
671  //Invalid parameters?
672  else
673  {
674  //Report an error
675  error = ERROR_INVALID_PARAMETER;
676  }
677 
678  //Return status code
679  return error;
680 }
681 
682 
683 /**
684  * @brief Check whether the affine point S is on the curve
685  * @param[in] ecParams EC domain parameters
686  * @param[in] s Affine representation of the point
687  * @return TRUE if the affine point S is on the curve, else FALSE
688  **/
689 
691 {
692  bool_t valid;
693  size_t modLen;
694  uint8_t *pos;
696 
697  //Retrieve the length of the modulus, in bytes
698  modLen = mpiGetByteLength(&ecParams->p);
699  modLen = (modLen + 3U) & ~3U;
700 
701  //Acquire exclusive access to the PUKCC accelerator
703 
704  //Point to the crypto memory
705  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
706 
707  //Copy modulus
708  params.mod = pukccImportMpi(&pos, &ecParams->p, modLen + 4);
709  //Initialize reduction constant
710  params.cns = pukccWorkspace(&pos, modLen + 12);
711  //Initialize workspace R
712  params.r = pukccWorkspace(&pos, 64);
713  //Initialize workspace X
714  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
715 
716  //Set RedMod service parameters
717  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
718  PUKCL(Specific).CarryIn = 0;
719  PUKCL(Specific).Gf2n = 0;
720  PUKCL_RedMod(u2ModLength) = modLen;
721  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
722  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
723  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
724  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
725 
726  //Perform modular reduction setup
727  vPUKCL_Process(RedMod, pvPUKCLParam);
728 
729  //Check status code
730  if(PUKCL(u2Status) == PUKCL_OK)
731  {
732  //Point to the crypto memory
733  pos = params.r;
734 
735  //Copy point coordinates
736  params.point.x = pukccImportMpi(&pos, &s->x, modLen + 4);
737  params.point.y = pukccImportMpi(&pos, &s->y, modLen + 4);
738  params.point.z = pukccWorkspace(&pos, modLen + 4);
739  params.point.z[0] = 1;
740 
741  //Copy curve parameter a
742  params.a = pukccImportMpi(&pos, &ecParams->a, modLen + 4);
743  //Copy curve parameter b
744  params.b = pukccImportMpi(&pos, &ecParams->b, modLen + 4);
745  //Initialize workspace
746  params.w = pukccWorkspace(&pos, 4 * modLen + 28);
747 
748  //Set ZpEcPointIsOnCurve service parameters
749  PUKCL_ZpEcPointIsOnCurve(u2ModLength) = modLen;
750  PUKCL_ZpEcPointIsOnCurve(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
751  PUKCL_ZpEcPointIsOnCurve(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
752  PUKCL_ZpEcPointIsOnCurve(nu1PointBase) = PUKCC_FAR_TO_NEAR(params.point.x);
753  PUKCL_ZpEcPointIsOnCurve(nu1AParam) = PUKCC_FAR_TO_NEAR(params.a);
754  PUKCL_ZpEcPointIsOnCurve(nu1BParam) = PUKCC_FAR_TO_NEAR(params.b);
755  PUKCL_ZpEcPointIsOnCurve(nu1Workspace) = PUKCC_FAR_TO_NEAR(params.w);
756 
757  //Test whether the point is on the curve
758  vPUKCL_Process(ZpEcPointIsOnCurve, pvPUKCLParam);
759  }
760 
761  //Check status code
762  if(PUKCL(u2Status) == PUKCL_OK)
763  {
764  //The point S is on the elliptic curve
765  valid = TRUE;
766  }
767  else
768  {
769  //The point S is not on the elliptic curve
770  valid = FALSE;
771  }
772 
773  //Release exclusive access to the PUKCC accelerator
775 
776  //Return TRUE if the affine point S is on the curve, else FALSE
777  return valid;
778 }
779 
780 
781 /**
782  * @brief Recover affine representation
783  * @param[in] ecParams EC domain parameters
784  * @param[out] r Affine representation of the point
785  * @param[in] s Projective representation of the point
786  * @return Error code
787  **/
788 
790  const EcPoint *s)
791 {
792  error_t error;
793  size_t modLen;
794  uint8_t *pos;
796 
797  //Retrieve the length of the modulus, in bytes
798  modLen = mpiGetByteLength(&ecParams->p);
799  modLen = (modLen + 3U) & ~3U;
800 
801  //Acquire exclusive access to the PUKCC accelerator
803 
804  //Point to the crypto memory
805  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
806 
807  //Copy modulus
808  params.mod = pukccImportMpi(&pos, &ecParams->p, modLen + 4);
809  //Initialize reduction constant
810  params.cns = pukccWorkspace(&pos, modLen + 12);
811  //Initialize workspace R
812  params.r = pukccWorkspace(&pos, 64);
813  //Initialize workspace X
814  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
815 
816  //Set RedMod service parameters
817  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
818  PUKCL(Specific).CarryIn = 0;
819  PUKCL(Specific).Gf2n = 0;
820  PUKCL_RedMod(u2ModLength) = modLen;
821  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
822  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
823  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
824  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
825 
826  //Perform modular reduction setup
827  vPUKCL_Process(RedMod, pvPUKCLParam);
828 
829  //Check status code
830  if(PUKCL(u2Status) == PUKCL_OK)
831  {
832  //Point to the crypto memory
833  pos = params.r;
834 
835  //Copy point coordinates
836  params.point.x = pukccImportMpi(&pos, &s->x, modLen + 4);
837  params.point.y = pukccImportMpi(&pos, &s->y, modLen + 4);
838  params.point.z = pukccImportMpi(&pos, &s->z, modLen + 4);
839  //Initialize workspace
840  params.w = pukccWorkspace(&pos, 4 * modLen + 48);
841 
842  //Set ZpEccConvAffineToProjective service parameters
843  PUKCL_ZpEcConvProjToAffine(u2ModLength) = modLen;
844  PUKCL_ZpEcConvProjToAffine(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
845  PUKCL_ZpEcConvProjToAffine(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
846  PUKCL_ZpEcConvProjToAffine(nu1PointABase) = PUKCC_FAR_TO_NEAR(params.point.x);
847  PUKCL_ZpEcConvProjToAffine(nu1Workspace) = PUKCC_FAR_TO_NEAR(params.w);
848 
849  //Convert point coordinates from projective to affine representation
850  vPUKCL_Process(ZpEcConvProjToAffine, pvPUKCLParam);
851  }
852 
853  //Check status code
854  if(PUKCL(u2Status) == PUKCL_OK)
855  {
856  //Copy the x-coordinate of the result
857  error = mpiImport(&r->x, params.point.x, modLen,
859 
860  //Check error code
861  if(!error)
862  {
863  //Copy the y-coordinate of the result
864  error = mpiImport(&r->y, params.point.y, modLen,
866  }
867 
868  //Check error code
869  if(!error)
870  {
871  //Copy the z-coordinate of the result
872  error = mpiImport(&r->z, params.point.z, modLen,
874  }
875  }
876  else
877  {
878  //Report an error
879  error = ERROR_FAILURE;
880  }
881 
882  //Release exclusive access to the PUKCC accelerator
884 
885  //Return error code
886  return error;
887 }
888 
889 
890 /**
891  * @brief Scalar multiplication
892  * @param[in] ecParams EC domain parameters
893  * @param[out] r Resulting point R = d.S
894  * @param[in] d An integer d such as 0 <= d < p
895  * @param[in] s EC point
896  * @return Error code
897  **/
898 
899 error_t ecMult(const EcDomainParameters *ecParams, EcPoint *r, const Mpi *d,
900  const EcPoint *s)
901 {
902  error_t error;
903  size_t kLen;
904  size_t modLen;
905  uint8_t *pos;
906  PukccZpEccMulParams params;
907 
908  //Retrieve the length of the modulus, in bytes
909  modLen = mpiGetByteLength(&ecParams->p);
910  modLen = (modLen + 3U) & ~3U;
911 
912  //Retrieve the length of the scalar number
913  kLen = mpiGetByteLength(d);
914  kLen = (kLen + 3U) & ~3U;
915 
916  //Acquire exclusive access to the PUKCC accelerator
918 
919  //Point to the crypto memory
920  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
921 
922  //Copy modulus
923  params.mod = pukccImportMpi(&pos, &ecParams->p, modLen + 4);
924  //Initialize reduction constant
925  params.cns = pukccWorkspace(&pos, modLen + 12);
926  //Initialize workspace R
927  params.r = pukccWorkspace(&pos, 64);
928  //Initialize workspace X
929  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
930 
931  //Set RedMod service parameters
932  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
933  PUKCL(Specific).CarryIn = 0;
934  PUKCL(Specific).Gf2n = 0;
935  PUKCL_RedMod(u2ModLength) = modLen;
936  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
937  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
938  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
939  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
940 
941  //Perform modular reduction setup
942  vPUKCL_Process(RedMod, pvPUKCLParam);
943 
944  //Check status code
945  if(PUKCL(u2Status) == PUKCL_OK)
946  {
947  //Point to the crypto memory
948  pos = params.r;
949 
950  //Copy scalar number
951  params.k = pukccImportMpi(&pos, d, kLen + 4);
952 
953  //Copy point coordinates
954  params.point.x = pukccImportMpi(&pos, &s->x, modLen + 4);
955  params.point.y = pukccImportMpi(&pos, &s->y, modLen + 4);
956  params.point.z = pukccWorkspace(&pos, modLen + 4);
957  params.point.z[0] = 1;
958 
959  //Copy curve parameter a
960  params.a = pukccImportMpi(&pos, &ecParams->a, modLen + 4);
961  //Initialize workspace
962  params.w = pukccWorkspace(&pos, 8 * modLen + 44);
963 
964  //Set ZpEccMulFast service parameters
965  PUKCL_ZpEccMul(u2ModLength) = modLen;
966  PUKCL_ZpEccMul(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
967  PUKCL_ZpEccMul(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
968  PUKCL_ZpEccMul(u2KLength) = kLen;
969  PUKCL_ZpEccMul(nu1KBase) = PUKCC_FAR_TO_NEAR(params.k);
970  PUKCL_ZpEccMul(nu1PointBase) = PUKCC_FAR_TO_NEAR(params.point.x);
971  PUKCL_ZpEccMul(nu1ABase) = PUKCC_FAR_TO_NEAR(params.a);
972  PUKCL_ZpEccMul(nu1Workspace) = PUKCC_FAR_TO_NEAR(params.w);
973 
974  //Perform scalar multiplication over GF(p)
975  vPUKCL_Process(ZpEccMulFast, pvPUKCLParam);
976  }
977 
978  //Check status code
979  if(PUKCL(u2Status) == PUKCL_OK)
980  {
981  //Copy the x-coordinate of the result
982  error = mpiImport(&r->x, params.point.x, modLen,
984 
985  //Check error code
986  if(!error)
987  {
988  //Copy the y-coordinate of the result
989  error = mpiImport(&r->y, params.point.y, modLen,
991  }
992 
993  //Check error code
994  if(!error)
995  {
996  //Copy the z-coordinate of the result
997  error = mpiImport(&r->z, params.point.z, modLen,
999  }
1000  }
1001  else
1002  {
1003  //Report an error
1004  error = ERROR_FAILURE;
1005  }
1006 
1007  //Release exclusive access to the PUKCC accelerator
1009 
1010  //Return error code
1011  return error;
1012 }
1013 
1014 
1015 /**
1016  * @brief ECDSA signature generation
1017  * @param[in] ecParams EC domain parameters
1018  * @param[in] prngAlgo PRNG algorithm
1019  * @param[in] prngContext Pointer to the PRNG context
1020  * @param[in] privateKey Signer's ECDSA private key
1021  * @param[in] digest Digest of the message to be signed
1022  * @param[in] digestLen Length in octets of the digest
1023  * @param[out] signature (R, S) integer pair
1024  * @return Error code
1025  **/
1026 
1028  const PrngAlgo *prngAlgo, void *prngContext, const Mpi *privateKey,
1029  const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
1030 {
1031  error_t error;
1032  size_t n;
1033  size_t modLen;
1034  size_t orderLen;
1035  size_t scalarLen;
1036  uint8_t *pos;
1038  Mpi k;
1039 
1040  //Retrieve the length of the modulus, in bytes
1041  modLen = mpiGetByteLength(&ecParams->p);
1042  modLen = (modLen + 3U) & ~3U;
1043 
1044  //Retrieve the length of the base point order, in bytes
1045  orderLen = mpiGetByteLength(&ecParams->q);
1046  orderLen = (orderLen + 3U) & ~3U;
1047 
1048  //Compute the length of the scalar
1049  scalarLen = MAX(orderLen, digestLen);
1050  scalarLen = (scalarLen + 3U) & ~3U;
1051 
1052  //Initialize multiple precision integer
1053  mpiInit(&k);
1054 
1055  //Let N be the bit length of q
1056  n = mpiGetBitLength(&ecParams->q);
1057 
1058  //Generated a pseudorandom number
1059  error = mpiRand(&k, n, prngAlgo, prngContext);
1060 
1061  //Check error code
1062  if(!error)
1063  {
1064  //Make sure that 0 < k < q
1065  if(mpiComp(&k, &ecParams->q) >= 0)
1066  mpiShiftRight(&k, 1);
1067 
1068  //Debug message
1069  TRACE_DEBUG(" k:\r\n");
1070  TRACE_DEBUG_MPI(" ", &k);
1071  }
1072 
1073  //Acquire exclusive access to the PUKCC accelerator
1075 
1076  //Check error code
1077  if(!error)
1078  {
1079  //Point to the crypto memory
1080  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
1081 
1082  //Copy modulus
1083  params.mod = pukccImportMpi(&pos, &ecParams->p, modLen + 4);
1084  //Initialize reduction constant
1085  params.cns = pukccWorkspace(&pos, scalarLen + 12);
1086  //Initialize workspace R
1087  params.r = pukccWorkspace(&pos, 64);
1088  //Initialize workspace X
1089  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
1090 
1091  //Set RedMod service parameters
1092  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
1093  PUKCL(Specific).CarryIn = 0;
1094  PUKCL(Specific).Gf2n = 0;
1095  PUKCL_RedMod(u2ModLength) = modLen;
1096  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
1097  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
1098  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
1099  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
1100 
1101  //Perform modular reduction setup
1102  vPUKCL_Process(RedMod, pvPUKCLParam);
1103 
1104  //Check status code
1105  if(PUKCL(u2Status) != PUKCL_OK)
1106  error = ERROR_FAILURE;
1107  }
1108 
1109  //Check error code
1110  if(!error)
1111  {
1112  //Point to the crypto memory
1113  pos = params.r;
1114 
1115  //Copy base point coordinates
1116  params.basePoint.x = pukccImportMpi(&pos, &ecParams->g.x, modLen + 4);
1117  params.basePoint.y = pukccImportMpi(&pos, &ecParams->g.y, modLen + 4);
1118  params.basePoint.z = pukccImportMpi(&pos, &ecParams->g.z, modLen + 4);
1119 
1120  //Copy base point order
1121  params.order = pukccImportMpi(&pos, &ecParams->q, scalarLen + 4);
1122  //Copy curve parameter a
1123  params.a = pukccImportMpi(&pos, &ecParams->a, modLen + 4);
1124  //Copy private key
1125  params.privateKey = pukccImportMpi(&pos, privateKey, scalarLen + 4);
1126  //Copy random scalar
1127  params.k = pukccImportMpi(&pos, &k, scalarLen + 4);
1128  //Copy digest
1129  params.h = pukccImportArray(&pos, digest, digestLen, scalarLen + 4);
1130  //Initialize workspace
1131  params.w = pukccWorkspace(&pos, 8 * modLen + 44);
1132 
1133  //Set ZpEcDsaGenerateFast service parameters
1134  PUKCL_ZpEcDsaGenerate(u2ModLength) = modLen;
1135  PUKCL_ZpEcDsaGenerate(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
1136  PUKCL_ZpEcDsaGenerate(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
1137  PUKCL_ZpEcDsaGenerate(nu1PointABase) = PUKCC_FAR_TO_NEAR(params.basePoint.x);
1138  PUKCL_ZpEcDsaGenerate(nu1OrderPointBase) = PUKCC_FAR_TO_NEAR(params.order);
1139  PUKCL_ZpEcDsaGenerate(nu1ABase) = PUKCC_FAR_TO_NEAR(params.a);
1140  PUKCL_ZpEcDsaGenerate(nu1PrivateKey) = PUKCC_FAR_TO_NEAR(params.privateKey);
1141  PUKCL_ZpEcDsaGenerate(u2ScalarLength) = scalarLen;
1142  PUKCL_ZpEcDsaGenerate(nu1ScalarNumber) = PUKCC_FAR_TO_NEAR(params.k);
1143  PUKCL_ZpEcDsaGenerate(nu1HashBase) = PUKCC_FAR_TO_NEAR(params.h);
1144  PUKCL_ZpEcDsaGenerate(nu1Workspace) = PUKCC_FAR_TO_NEAR(params.w);
1145 
1146  //Perform ECDSA signature generation
1147  vPUKCL_Process(ZpEcDsaGenerateFast, pvPUKCLParam);
1148 
1149  //Check status code
1150  if(PUKCL(u2Status) != PUKCL_OK)
1151  error = ERROR_FAILURE;
1152  }
1153 
1154  //Check error code
1155  if(!error)
1156  {
1157  //Copy the first part of the ECDSA signature
1158  error = mpiImport(&signature->r, params.basePoint.x, scalarLen,
1160  }
1161 
1162  //Check error code
1163  if(!error)
1164  {
1165  //Copy the second part of the ECDSA signature
1166  error = mpiImport(&signature->s, params.basePoint.x + scalarLen + 4,
1167  scalarLen, MPI_FORMAT_LITTLE_ENDIAN);
1168  }
1169 
1170  //Release exclusive access to the PUKCC accelerator
1172 
1173  //Check error code
1174  if(!error)
1175  {
1176  //Dump ECDSA signature
1177  TRACE_DEBUG(" r:\r\n");
1178  TRACE_DEBUG_MPI(" ", &signature->r);
1179  TRACE_DEBUG(" s:\r\n");
1180  TRACE_DEBUG_MPI(" ", &signature->s);
1181  }
1182 
1183  //Release multiple precision integer
1184  mpiFree(&k);
1185 
1186  //Return error code
1187  return error;
1188 }
1189 
1190 
1191 /**
1192  * @brief ECDSA signature verification
1193  * @param[in] ecParams EC domain parameters
1194  * @param[in] publicKey Signer's ECDSA public key
1195  * @param[in] digest Digest of the message whose signature is to be verified
1196  * @param[in] digestLen Length in octets of the digest
1197  * @param[in] signature (R, S) integer pair
1198  * @return Error code
1199  **/
1200 
1202  const EcPoint *publicKey, const uint8_t *digest, size_t digestLen,
1203  const EcdsaSignature *signature)
1204 {
1205  error_t error;
1206  size_t modLen;
1207  size_t orderLen;
1208  size_t scalarLen;
1209  uint8_t *pos;
1210  PukccZpEcDsaVerifyParams params;
1211 
1212  //Retrieve the length of the modulus, in bytes
1213  modLen = mpiGetByteLength(&ecParams->p);
1214  modLen = (modLen + 3U) & ~3U;
1215 
1216  //Retrieve the length of the base point order, in bytes
1217  orderLen = mpiGetByteLength(&ecParams->q);
1218  orderLen = (orderLen + 3U) & ~3U;
1219 
1220  //Compute the length of the scalar
1221  scalarLen = MAX(orderLen, digestLen);
1222  scalarLen = (scalarLen + 3U) & ~3U;
1223 
1224  //Acquire exclusive access to the PUKCC accelerator
1226 
1227  //Point to the crypto memory
1228  pos = (uint8_t *) PUKCC_CRYPTO_RAM_BASE;
1229 
1230  //Copy modulus
1231  params.mod = pukccImportMpi(&pos, &ecParams->p, modLen + 4);
1232  //Initialize reduction constant
1233  params.cns = pukccWorkspace(&pos, scalarLen + 12);
1234  //Initialize workspace R
1235  params.r = pukccWorkspace(&pos, 64);
1236  //Initialize workspace X
1237  params.x = pukccWorkspace(&pos, 2 * modLen + 8);
1238 
1239  //Set RedMod service parameters
1240  PUKCL(u2Option) = PUKCL_REDMOD_SETUP;
1241  PUKCL(Specific).CarryIn = 0;
1242  PUKCL(Specific).Gf2n = 0;
1243  PUKCL_RedMod(u2ModLength) = modLen;
1244  PUKCL_RedMod(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
1245  PUKCL_RedMod(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
1246  PUKCL_RedMod(nu1RBase) = PUKCC_FAR_TO_NEAR(params.r);
1247  PUKCL_RedMod(nu1XBase) = PUKCC_FAR_TO_NEAR(params.x);
1248 
1249  //Perform modular reduction setup
1250  vPUKCL_Process(RedMod, pvPUKCLParam);
1251 
1252  //Check status code
1253  if(PUKCL(u2Status) == PUKCL_OK)
1254  {
1255  //Point to the crypto memory
1256  pos = params.r;
1257 
1258  //Copy base point coordinates
1259  params.basePoint.x = pukccImportMpi(&pos, &ecParams->g.x, modLen + 4);
1260  params.basePoint.y = pukccImportMpi(&pos, &ecParams->g.y, modLen + 4);
1261  params.basePoint.z = pukccImportMpi(&pos, &ecParams->g.z, modLen + 4);
1262 
1263  //Copy base point order
1264  params.order = pukccImportMpi(&pos, &ecParams->q, scalarLen + 4);
1265  //Copy curve parameter a
1266  params.a = pukccImportMpi(&pos, &ecParams->a, modLen + 4);
1267 
1268  //Copy public key
1269  params.publicKey.x = pukccImportMpi(&pos, &publicKey->x, modLen + 4);
1270  params.publicKey.y = pukccImportMpi(&pos, &publicKey->y, modLen + 4);
1271  params.publicKey.z = pukccWorkspace(&pos, modLen + 4);
1272  params.publicKey.z[0] = 1;
1273 
1274  //Copy digest
1275  params.h = pukccImportArray(&pos, digest, digestLen, scalarLen + 4);
1276 
1277  //Copy signature
1278  params.r = pukccImportMpi(&pos, &signature->r, scalarLen + 4);
1279  params.s = pukccImportMpi(&pos, &signature->s, scalarLen + 4);
1280 
1281  //Initialize workspace
1282  params.w = pukccWorkspace(&pos, 8 * modLen + 44);
1283 
1284  //Set ZpEcDsaVerifyFast service parameters
1285  PUKCL(u2Option) = 0;
1286  PUKCL_ZpEcDsaVerify(u2ModLength) = modLen;
1287  PUKCL_ZpEcDsaVerify(nu1ModBase) = PUKCC_FAR_TO_NEAR(params.mod);
1288  PUKCL_ZpEcDsaVerify(nu1CnsBase) = PUKCC_FAR_TO_NEAR(params.cns);
1289  PUKCL_ZpEcDsaVerify(nu1PointABase) = PUKCC_FAR_TO_NEAR(params.basePoint.x);
1290  PUKCL_ZpEcDsaVerify(nu1OrderPointBase) = PUKCC_FAR_TO_NEAR(params.order);
1291  PUKCL_ZpEcDsaVerify(nu1ABase) = PUKCC_FAR_TO_NEAR(params.a);
1292  PUKCL_ZpEcDsaVerify(nu1PointPublicKeyGen) = PUKCC_FAR_TO_NEAR(params.publicKey.x);
1293  PUKCL_ZpEcDsaVerify(u2ScalarLength) = scalarLen;
1294  PUKCL_ZpEcDsaVerify(nu1HashBase) = PUKCC_FAR_TO_NEAR(params.h);
1295  PUKCL_ZpEcDsaVerify(nu1PointSignature) = PUKCC_FAR_TO_NEAR(params.r);
1296  PUKCL_ZpEcDsaVerify(nu1Workspace) = PUKCC_FAR_TO_NEAR(params.w);
1297 
1298  //Perform ECDSA signature verification
1299  vPUKCL_Process(ZpEcDsaVerifyFast, pvPUKCLParam);
1300  }
1301 
1302  //Check status code
1303  if(PUKCL(u2Status) == PUKCL_OK)
1304  {
1305  //The ECDSA signature is valid
1306  error = NO_ERROR;
1307  }
1308  else if(PUKCL(u2Status) == PUKCL_WRONG_SIGNATURE)
1309  {
1310  //The ECDSA signature is not valid
1311  error = ERROR_INVALID_SIGNATURE;
1312  }
1313  else
1314  {
1315  //Report an error
1316  error = ERROR_FAILURE;
1317  }
1318 
1319  //Release exclusive access to the PUKCC accelerator
1321 
1322  //Return status code
1323  return error;
1324 }
error_t mpiRand(Mpi *r, uint_t length, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: mpi.c:462
ECC (Elliptic Curve Cryptography)
EC domain parameters.
Definition: ec.h:63
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:62
Arbitrary precision integer.
Definition: mpi.h:69
uint8_t c
Definition: ndp.h:512
Mpi p
First factor.
Definition: rsa.h:64
error_t pukccInit(void)
Initialize PUKCC public key accelerator.
Debugging facilities.
uint8_t p
Definition: ndp.h:297
Mpi d
Private exponent.
Definition: rsa.h:63
Generic error code.
Definition: error.h:45
ECDSA (Elliptic Curve Digital Signature Algorithm)
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:47
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:289
RedMod service parameters.
ZpEcDsaVerify service parameters.
SAME54 PUKCC public key accelerator.
error_t ecdsaGenerateSignature(const EcDomainParameters *ecParams, const PrngAlgo *prngAlgo, void *prngContext, const Mpi *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Mpi x
x-coordinate
Definition: ec.h:53
#define PUKCC_CRYPTO_RAM_BASE
error_t ecAffinify(const EcDomainParameters *ecParams, EcPoint *r, const EcPoint *s)
Recover affine representation.
uint8_t m
Definition: ndp.h:301
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:513
uint8_t a
Definition: ndp.h:409
#define MAX(a, b)
Definition: os_port.h:66
Mpi b
Curve parameter b.
Definition: ec.h:69
error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
Modular inverse.
error_t mpiMod2(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
#define TRUE
Definition: os_port.h:50
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:109
PPUKCL_PARAM pvPUKCLParam
Mpi n
Modulus.
Definition: rsa.h:61
Mpi q
Second factor.
Definition: rsa.h:65
Elliptic curve point.
Definition: ec.h:51
ECDSA signature.
Definition: ecdsa.h:48
uint8_t * pukccWorkspace(uint8_t **dest, size_t totalLen)
Initialize workspace area.
Mpi y
y-coordinate
Definition: ec.h:54
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:192
Mpi q
Order of the point G.
Definition: ec.h:71
Mpi p
Prime.
Definition: ec.h:67
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
ZpEcConvProjToAffine service parameters.
SAME54 hardware cryptography accelerator.
error_t ecdsaVerifySignature(const EcDomainParameters *ecParams, const EcPoint *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
uint8_t signature
Definition: tls.h:1363
#define PUKCC_FAR_TO_NEAR(p)
uint8_t s
EcPoint g
Base point G.
Definition: ec.h:70
Mpi dq
second factor&#39;s CRT exponent
Definition: rsa.h:67
OsMutex same54CryptoMutex
Definition: same54_crypto.c:43
Success.
Definition: error.h:44
error_t
Error codes.
Definition: error.h:42
MPI (Multiple Precision Integer Arithmetic)
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:598
RSA public-key cryptography standard.
Fmult service parameters.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Mpi qinv
CRT coefficient.
Definition: rsa.h:68
PUKCL_PARAM PUKCLParam
Common interface for pseudo-random number generators.
Definition: crypto.h:1110
ZpEcPointIsOnCurve service parameters.
uint8_t * pukccImportMpi(uint8_t **dest, const Mpi *src, size_t totalLen)
Import multiple-precision integer.
Mpi dp
First factor&#39;s CRT exponent.
Definition: rsa.h:66
uint32_t r
Definition: ndp.h:344
Mpi a
Curve parameter a.
Definition: ec.h:68
ZpEccMul service parameters.
Mpi z
z-coordinate
Definition: ec.h:55
ExpMod service parameters.
GCD service parameters.
error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
RSA decryption primitive.
uint8_t * pukccImportArray(uint8_t **dest, const uint8_t *array, size_t arrayLen, size_t totalLen)
Import byte array.
uint_t size
Definition: mpi.h:72
CRT service parameters.
uint8_t n
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
RSA private key.
Definition: rsa.h:59
ZpEcDsaGenerate service parameters.
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:156
#define FALSE
Definition: os_port.h:46
int bool_t
Definition: compiler_port.h:49
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
uint8_t b[6]
Definition: dtls_misc.h:132
error_t ecMult(const EcDomainParameters *ecParams, EcPoint *r, const Mpi *d, const EcPoint *s)
Scalar multiplication.
error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
bool_t ecIsPointAffine(const EcDomainParameters *ecParams, const EcPoint *s)
Check whether the affine point S is on the curve.
#define TRACE_DEBUG(...)
Definition: debug.h:106
error_t mpiShiftRight(Mpi *r, uint_t n)
Right shift operation.
Definition: mpi.c:1043