ecdsa.c
Go to the documentation of this file.
1 /**
2  * @file ecdsa.c
3  * @brief ECDSA (Elliptic Curve Digital Signature Algorithm)
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.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "ecc/ecdsa.h"
37 #include "ecc/ec_misc.h"
38 #include "encoding/asn1.h"
39 #include "debug.h"
40 
41 //Check crypto library configuration
42 #if (ECDSA_SUPPORT == ENABLED)
43 
44 //ECDSA with SHA-1 OID (1.2.840.10045.4.1)
45 const uint8_t ECDSA_WITH_SHA1_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01};
46 //ECDSA with SHA-224 OID (1.2.840.10045.4.3.1)
47 const uint8_t ECDSA_WITH_SHA224_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01};
48 //ECDSA with SHA-256 OID (1.2.840.10045.4.3.2)
49 const uint8_t ECDSA_WITH_SHA256_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02};
50 //ECDSA with SHA-384 OID (1.2.840.10045.4.3.3)
51 const uint8_t ECDSA_WITH_SHA384_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03};
52 //ECDSA with SHA-512 OID (1.2.840.10045.4.3.4)
53 const uint8_t ECDSA_WITH_SHA512_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04};
54 //ECDSA with SHA-3-224 OID (2.16.840.1.101.3.4.3.9)
55 const uint8_t ECDSA_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x09};
56 //ECDSA with SHA-3-256 OID (2.16.840.1.101.3.4.3.10)
57 const uint8_t ECDSA_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0A};
58 //ECDSA with SHA-3-384 OID (2.16.840.1.101.3.4.3.11)
59 const uint8_t ECDSA_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0B};
60 //ECDSA with SHA-3-512 OID (2.16.840.1.101.3.4.3.12)
61 const uint8_t ECDSA_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0C};
62 //ECDSA with SHAKE128 OID (1.3.6.1.5.5.7.6.32)
63 const uint8_t ECDSA_WITH_SHAKE128_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x20};
64 //ECDSA with SHAKE256 OID (1.3.6.1.5.5.7.6.33)
65 const uint8_t ECDSA_WITH_SHAKE256_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x21};
66 
67 
68 /**
69  * @brief Initialize an ECDSA signature
70  * @param[in] signature Pointer to the ECDSA signature to initialize
71  **/
72 
74 {
75  //Initialize (R, S) integer pair
76  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
77  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
78 }
79 
80 
81 /**
82  * @brief Release an ECDSA signature
83  * @param[in] signature Pointer to the ECDSA signature to free
84  **/
85 
87 {
88  //Release (R, S) integer pair
89  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
90  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
91 }
92 
93 
94 /**
95  * @brief Import an ECDSA signature
96  * @param[out] signature ECDSA signature
97  * @param[in] curve Elliptic curve parameters
98  * @param[in] input Pointer to the octet string
99  * @param[in] length Length of the octet string, in bytes
100  * @param[in] format ECDSA signature format (ASN.1 or raw format)
101  * @return Error code
102  **/
103 
105  const uint8_t *input, size_t length, EcdsaSignatureFormat format)
106 {
107  error_t error;
108  size_t n;
109 
110  //Check parameters
111  if(signature == NULL || curve == NULL || input == NULL)
113 
114  //Get the length of the order, in bytes
115  n = (curve->orderSize + 7) / 8;
116 
117  //Debug message
118  TRACE_DEBUG("Importing ECDSA signature...\r\n");
119 
120  //Dump ECDSA signature
121  TRACE_DEBUG(" signature:\r\n");
122  TRACE_DEBUG_ARRAY(" ", input, length);
123 
124  //Check the format of the ECDSA signature
125  if(format == ECDSA_SIGNATURE_FORMAT_ASN1)
126  {
127  Asn1Tag tag;
128 
129  //Display ASN.1 structure
130  error = asn1DumpObject(input, length, 0);
131  //Any error to report?
132  if(error)
133  return error;
134 
135  //Read the contents of the ASN.1 structure
136  error = asn1ReadSequence(input, length, &tag);
137  //Failed to decode ASN.1 tag?
138  if(error)
139  return error;
140 
141  //Malformed ECDSA signature?
142  if(length != tag.totalLength)
143  return ERROR_INVALID_SYNTAX;
144 
145  //Point to the first field
146  input = tag.value;
147  length = tag.length;
148 
149  //Read the integer R
150  error = asn1ReadTag(input, length, &tag);
151  //Failed to decode ASN.1 tag?
152  if(error)
153  return error;
154 
155  //Enforce encoding, class and type
156  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
158  //Invalid tag?
159  if(error)
160  return error;
161 
162  //Make sure R is a positive integer
163  if(tag.length == 0 || (tag.value[0] & 0x80) != 0)
164  return ERROR_INVALID_SYNTAX;
165 
166  //Convert the octet string to an integer
167  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE, tag.value,
169  //Any error to report?
170  if(error)
171  return error;
172 
173  //Point to the next field
174  input += tag.totalLength;
175  length -= tag.totalLength;
176 
177  //Read the integer S
178  error = asn1ReadTag(input, length, &tag);
179  //Failed to decode ASN.1 tag?
180  if(error)
181  return error;
182 
183  //Enforce encoding, class and type
184  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
186  //Invalid tag?
187  if(error)
188  return error;
189 
190  //Make sure S is a positive integer
191  if(tag.length == 0 || (tag.value[0] & 0x80) != 0)
192  return ERROR_INVALID_SYNTAX;
193 
194  //Convert the octet string to an integer
195  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE, tag.value,
197  //Any error to report?
198  if(error)
199  return error;
200 
201  //Malformed ECDSA signature?
202  if(length != tag.totalLength)
203  return ERROR_INVALID_SYNTAX;
204 
205  //Dump (R, S) integer pair
206  TRACE_DEBUG(" r:\r\n");
207  TRACE_DEBUG_EC_SCALAR(" ", signature->r, EC_MAX_ORDER_SIZE);
208  TRACE_DEBUG(" s:\r\n");
209  TRACE_DEBUG_EC_SCALAR(" ", signature->s, EC_MAX_ORDER_SIZE);
210  }
211  else if(format == ECDSA_SIGNATURE_FORMAT_RAW)
212  {
213  //Check the length of the octet string
214  if(length != (n * 2))
215  return ERROR_INVALID_LENGTH;
216 
217  //Convert R to an integer
218  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE, input, n,
220  //Any error to report?
221  if(error)
222  return error;
223 
224  //Convert S to an integer
225  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE,
226  input + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
227  //Any error to report?
228  if(error)
229  return error;
230  }
231  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_R)
232  {
233  //Convert R to an integer
234  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE, input, length,
236  //Any error to report?
237  if(error)
238  return error;
239  }
240  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_S)
241  {
242  //Convert S to an integer
243  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE, input, length,
245  //Any error to report?
246  if(error)
247  return error;
248  }
249  else
250  {
251  //Invalid format
253  }
254 
255  //Save elliptic curve parameters
256  signature->curve = curve;
257 
258  //Successful processing
259  return NO_ERROR;
260 }
261 
262 
263 /**
264  * @brief Export an ECDSA signature
265  * @param[in] signature ECDSA signature
266  * @param[out] output Pointer to the octet string (optional parameter)
267  * @param[out] written Length of the resulting octet string, in bytes
268  * @param[in] format ECDSA signature format (ASN.1 or raw format)
269  * @return Error code
270  **/
271 
272 error_t ecdsaExportSignature(const EcdsaSignature *signature, uint8_t *output,
273  size_t *written, EcdsaSignatureFormat format)
274 {
275  error_t error;
276  size_t k;
277  size_t n;
278  size_t length;
279  size_t orderLen;
280  uint8_t *p;
281  Asn1Tag tag;
282 
283  //Check parameters
284  if(signature == NULL || written == NULL)
286 
287  //Invalid elliptic curve?
288  if(signature->curve == NULL)
290 
291  //Get the length of the order, in words
292  orderLen = (signature->curve->orderSize + 31) / 32;
293 
294  //Debug message
295  TRACE_DEBUG("Exporting ECDSA signature...\r\n");
296 
297  //Dump (R, S) integer pair
298  TRACE_DEBUG(" r:\r\n");
299  TRACE_DEBUG_EC_SCALAR(" ", signature->r, orderLen);
300  TRACE_DEBUG(" s:\r\n");
301  TRACE_DEBUG_EC_SCALAR(" ", signature->s, orderLen);
302 
303  //Check the format of the ECDSA signature
304  if(format == ECDSA_SIGNATURE_FORMAT_ASN1)
305  {
306  //Point to the buffer where to write the ASN.1 structure
307  p = output;
308  //Length of the ASN.1 structure
309  length = 0;
310 
311  //R is always encoded in the smallest possible number of octets
312  k = ecScalarGetBitLength(signature->r, orderLen) / 8 + 1;
313 
314  //R is represented by an integer
315  tag.constructed = FALSE;
318  tag.length = k;
319 
320  //Write the corresponding ASN.1 tag
321  error = asn1WriteHeader(&tag, FALSE, p, &n);
322  //Any error to report?
323  if(error)
324  return error;
325 
326  //Advance data pointer
327  ASN1_INC_POINTER(p, n);
328  length += n;
329 
330  //If the output parameter is NULL, then the function calculates the
331  //length of the ASN.1 structure without copying any data
332  if(p != NULL)
333  {
334  //Convert R to an octet string
335  error = ecScalarExport(signature->r, EC_MAX_ORDER_SIZE, p, k,
337  //Any error to report?
338  if(error)
339  return error;
340  }
341 
342  //Advance data pointer
343  ASN1_INC_POINTER(p, k);
344  length += k;
345 
346  //S is always encoded in the smallest possible number of octets
347  k = ecScalarGetBitLength(signature->s, orderLen) / 8 + 1;
348 
349  //S is represented by an integer
350  tag.constructed = FALSE;
353  tag.length = k;
354 
355  //Write the corresponding ASN.1 tag
356  error = asn1WriteHeader(&tag, FALSE, p, &n);
357  //Any error to report?
358  if(error)
359  return error;
360 
361  //Advance data pointer
362  ASN1_INC_POINTER(p, n);
363  length += n;
364 
365  //If the output parameter is NULL, then the function calculates the
366  //length of the ASN.1 structure without copying any data
367  if(p != NULL)
368  {
369  //Convert S to an octet string
370  error = ecScalarExport(signature->s, EC_MAX_ORDER_SIZE, p, k,
372  //Any error to report?
373  if(error)
374  return error;
375  }
376 
377  //Advance data pointer
378  ASN1_INC_POINTER(p, k);
379  length += k;
380 
381  //The (R, S) integer pair is encapsulated within a sequence
382  tag.constructed = TRUE;
385  tag.length = length;
386 
387  //Write the corresponding ASN.1 tag
388  error = asn1InsertHeader(&tag, output, &n);
389  //Any error to report?
390  if(error)
391  return error;
392 
393  //Total length of the ASN.1 structure
394  *written = length + n;
395  }
396  else if(format == ECDSA_SIGNATURE_FORMAT_RAW)
397  {
398  //Get the length of the order, in bytes
399  n = (signature->curve->orderSize + 7) / 8;
400 
401  //If the output parameter is NULL, then the function calculates the
402  //length of the octet string without copying any data
403  if(output != NULL)
404  {
405  //Convert R to an octet string
406  error = ecScalarExport(signature->r, (n + 3) / 4, output, n,
408  //Any error to report?
409  if(error)
410  return error;
411 
412  //Convert S to an octet string
413  error = ecScalarExport(signature->s, (n + 3) / 4, output + n, n,
415  //Any error to report?
416  if(error)
417  return error;
418  }
419 
420  //Length of the resulting octet string
421  *written = 2 * n;
422  }
423  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_R)
424  {
425  //Get the length of the order, in bytes
426  n = (signature->curve->orderSize + 7) / 8;
427 
428  //If the output parameter is NULL, then the function calculates the
429  //length of the octet string without copying any data
430  if(output != NULL)
431  {
432  //Convert R to an octet string
433  error = ecScalarExport(signature->r, (n + 3) / 4, output, n,
435  //Any error to report?
436  if(error)
437  return error;
438  }
439 
440  //Length of the resulting octet string
441  *written = n;
442  }
443  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_S)
444  {
445  //Get the length of the order, in bytes
446  n = (signature->curve->orderSize + 7) / 8;
447 
448  //If the output parameter is NULL, then the function calculates the
449  //length of the octet string without copying any data
450  if(output != NULL)
451  {
452  //Convert S to an octet string
453  error = ecScalarExport(signature->s, (n + 3) / 4, output, n,
455  //Any error to report?
456  if(error)
457  return error;
458  }
459 
460  //Length of the resulting octet string
461  *written = n;
462  }
463  else
464  {
465  //Invalid format
467  }
468 
469  //Dump ECDSA signature
470  if(output != NULL)
471  {
472  TRACE_DEBUG(" signature:\r\n");
473  TRACE_DEBUG_ARRAY(" ", output, *written);
474  }
475 
476  //Successful processing
477  return NO_ERROR;
478 }
479 
480 
481 /**
482  * @brief ECDSA signature generation
483  * @param[in] prngAlgo PRNG algorithm
484  * @param[in] prngContext Pointer to the PRNG context
485  * @param[in] privateKey Signer's EC private key
486  * @param[in] digest Digest of the message to be signed
487  * @param[in] digestLen Length in octets of the digest
488  * @param[out] signature (R, S) integer pair
489  * @return Error code
490  **/
491 
492 __weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo,
493  void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest,
494  size_t digestLen, EcdsaSignature *signature)
495 {
496  error_t error;
497  uint_t n;
498  uint_t pLen;
499  uint_t qLen;
500 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
502 #else
504 #endif
505 
506  //Check parameters
507  if(privateKey == NULL || digest == NULL || signature == NULL)
509 
510  //Invalid elliptic curve?
511  if(privateKey->curve == NULL)
513 
514  //Get the length of the modulus, in words
515  pLen = (privateKey->curve->fieldSize + 31) / 32;
516  //Get the length of the order, in words
517  qLen = (privateKey->curve->orderSize + 31) / 32;
518 
519  //Debug message
520  TRACE_DEBUG("ECDSA signature generation...\r\n");
521  TRACE_DEBUG(" curve: %s\r\n", privateKey->curve->name);
522  TRACE_DEBUG(" private key:\r\n");
523  TRACE_DEBUG_EC_SCALAR(" ", privateKey->d, qLen);
524  TRACE_DEBUG(" digest:\r\n");
525  TRACE_DEBUG_ARRAY(" ", digest, digestLen);
526 
527 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
528  //Allocate working state
530  //Failed to allocate memory?
531  if(state == NULL)
532  return ERROR_OUT_OF_MEMORY;
533 #endif
534 
535  //Initialize working state
536  osMemset(state, 0, sizeof(EcdsaGenerateSignatureState));
537 
538  //Initialize (R, S) integer pair
539  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
540  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
541 
542  //Generate a random number k such as 0 < k < q - 1
543  error = ecScalarRand(privateKey->curve, state->k, prngAlgo, prngContext);
544 
545  //Check status code
546  if(!error)
547  {
548  //Debug message
549  TRACE_DEBUG(" k:\r\n");
550  TRACE_DEBUG_EC_SCALAR(" ", state->k, qLen);
551 
552  //Let N be the bit length of q
553  n = privateKey->curve->orderSize;
554  //Compute N = MIN(N, outlen)
555  n = MIN(n, digestLen * 8);
556 
557  //Convert the digest to an integer
558  error = ecScalarImport(state->z, qLen, digest, (n + 7) / 8,
560  }
561 
562  //Check status code
563  if(!error)
564  {
565  //Keep the leftmost N bits of the hash value
566  if((n % 8) != 0)
567  {
568  ecScalarShiftRight(state->z, state->z, 8 - (n % 8), qLen);
569  }
570 
571  //Debug message
572  TRACE_DEBUG(" z:\r\n");
573  TRACE_DEBUG_EC_SCALAR(" ", state->z, qLen);
574 
575  //Compute R1 = (x1, y1) = k.G
576  error = ecMulRegular(privateKey->curve, &state->r1, state->k,
577  &privateKey->curve->g);
578  }
579 
580  //Check status code
581  if(!error)
582  {
583  //Convert R1 to affine representation
584  error = ecAffinify(privateKey->curve, &state->r1, &state->r1);
585  }
586 
587  //Check status code
588  if(!error)
589  {
590  //Debug message
591  TRACE_DEBUG(" x1:\r\n");
592  TRACE_DEBUG_EC_SCALAR(" ", state->r1.x, pLen);
593  TRACE_DEBUG(" y1:\r\n");
594  TRACE_DEBUG_EC_SCALAR(" ", state->r1.y, pLen);
595 
596  //Compute r = x1 mod q
597  ecScalarMod(signature->r, state->r1.x, pLen, privateKey->curve->q, qLen);
598  //Compute k ^ -1 mod q
599  ecScalarInvMod(privateKey->curve, state->k, state->k);
600 
601  //Compute s = k ^ -1 * (z + x * r) mod q
602  ecScalarMulMod(privateKey->curve, signature->s, privateKey->d, signature->r);
603  ecScalarAddMod(privateKey->curve, signature->s, signature->s, state->z);
604  ecScalarMulMod(privateKey->curve, signature->s, signature->s, state->k);
605 
606  //Save elliptic curve parameters
607  signature->curve = privateKey->curve;
608 
609  //Debug message
610  TRACE_DEBUG(" r:\r\n");
611  TRACE_DEBUG_EC_SCALAR(" ", signature->r, qLen);
612  TRACE_DEBUG(" s:\r\n");
613  TRACE_DEBUG_EC_SCALAR(" ", signature->s, qLen);
614  }
615 
616  //Erase working state
617  osMemset(state, 0, sizeof(EcdsaGenerateSignatureState));
618 
619 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
620  //Release working state
621  cryptoFreeMem(state);
622 #endif
623 
624  //Successful processing
625  return NO_ERROR;
626 }
627 
628 
629 /**
630  * @brief ECDSA signature verification
631  * @param[in] publicKey Signer's EC public key
632  * @param[in] digest Digest of the message whose signature is to be verified
633  * @param[in] digestLen Length in octets of the digest
634  * @param[in] signature (R, S) integer pair
635  * @return Error code
636  **/
637 
638 __weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey,
639  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
640 {
641  error_t error;
642  uint_t n;
643  uint_t pLen;
644  uint_t qLen;
645 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
647 #else
648  EcdsaVerifySignatureState state[1];
649 #endif
650 
651  //Check parameters
652  if(publicKey == NULL || digest == NULL || signature == NULL)
654 
655  //Invalid elliptic curve?
656  if(publicKey->curve == NULL)
658 
659  //Get the length of the modulus, in words
660  pLen = (publicKey->curve->fieldSize + 31) / 32;
661  //Get the length of the order, in words
662  qLen = (publicKey->curve->orderSize + 31) / 32;
663 
664  //Debug message
665  TRACE_DEBUG("ECDSA signature verification...\r\n");
666  TRACE_DEBUG(" curve: %s\r\n", publicKey->curve->name);
667  TRACE_DEBUG(" public key X:\r\n");
668  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.x, pLen);
669  TRACE_DEBUG(" public key Y:\r\n");
670  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.y, pLen);
671  TRACE_DEBUG(" digest:\r\n");
672  TRACE_DEBUG_ARRAY(" ", digest, digestLen);
673  TRACE_DEBUG(" r:\r\n");
674  TRACE_DEBUG_EC_SCALAR(" ", signature->r, qLen);
675  TRACE_DEBUG(" s:\r\n");
676  TRACE_DEBUG_EC_SCALAR(" ", signature->s, qLen);
677 
678  //Verify that the public key is on the curve
679  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
680  {
682  }
683 
684  //The verifier shall check that 0 < r < q
685  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
686  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
687  {
688  //If the condition is violated, the signature shall be rejected as invalid
690  }
691 
692  //The verifier shall check that 0 < s < q
693  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
694  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
695  {
696  //If the condition is violated, the signature shall be rejected as invalid
698  }
699 
700 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
701  //Allocate working state
702  state = cryptoAllocMem(sizeof(EcdsaVerifySignatureState));
703  //Failed to allocate memory?
704  if(state == NULL)
705  return ERROR_OUT_OF_MEMORY;
706 #endif
707 
708  //Initialize working state
709  osMemset(state, 0, sizeof(EcdsaVerifySignatureState));
710 
711  //Let N be the bit length of q
712  n = publicKey->curve->orderSize;
713  //Compute N = MIN(N, outlen)
714  n = MIN(n, digestLen * 8);
715 
716  //Convert the digest to an integer
717  error = ecScalarImport(state->z, qLen, digest, (n + 7) / 8,
719 
720  //Check status code
721  if(!error)
722  {
723  //Keep the leftmost N bits of the hash value
724  if((n % 8) != 0)
725  {
726  ecScalarShiftRight(state->z, state->z, 8 - (n % 8), qLen);
727  }
728 
729  //Compute w = s ^ -1 mod q
730  ecScalarInvMod(publicKey->curve, state->w, signature->s);
731 
732  //Compute u1 = z * w mod q
733  ecScalarMulMod(publicKey->curve, state->u1, state->z, state->w);
734  //Compute u2 = r * w mod q
735  ecScalarMulMod(publicKey->curve, state->u2, signature->r, state->w);
736 
737  //Convert the public key to projective representation
738  ecProjectify(publicKey->curve, &state->v1, &publicKey->q);
739 
740  //Compute V0 = (x0, y0) = u1.G + u2.Q
741  error = ecTwinMul(publicKey->curve, &state->v0, state->u1,
742  &publicKey->curve->g, state->u2, &state->v1);
743  }
744 
745  //Check status code
746  if(!error)
747  {
748  //Convert V0 to affine representation
749  error = ecAffinify(publicKey->curve, &state->v0, &state->v0);
750  }
751 
752  //Check status code
753  if(!error)
754  {
755  //Debug message
756  TRACE_DEBUG(" x0:\r\n");
757  TRACE_DEBUG_EC_SCALAR(" ", state->v0.x, pLen);
758  TRACE_DEBUG(" y0:\r\n");
759  TRACE_DEBUG_EC_SCALAR(" ", state->v0.y, pLen);
760 
761  //Compute v = x0 mod q
762  ecScalarMod(state->v, state->v0.x, pLen, publicKey->curve->q, qLen);
763 
764  //Debug message
765  TRACE_DEBUG(" v:\r\n");
766  TRACE_DEBUG_EC_SCALAR(" ", state->v, qLen);
767 
768  //If v = r, then the signature is verified. If v does not equal r, then the
769  //message or the signature may have been modified
770  if(ecScalarComp(state->v, signature->r, qLen) == 0)
771  {
772  error = NO_ERROR;
773  }
774  else
775  {
776  error = ERROR_INVALID_SIGNATURE;
777  }
778  }
779 
780  //Erase working state
781  osMemset(state, 0, sizeof(EcdsaVerifySignatureState));
782 
783 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
784  //Release working state
785  cryptoFreeMem(state);
786 #endif
787 
788  //Return status code
789  return error;
790 }
791 
792 #endif
error_t ecdsaImportSignature(EcdsaSignature *signature, const EcCurve *curve, const uint8_t *input, size_t length, EcdsaSignatureFormat format)
Import an ECDSA signature.
Definition: ecdsa.c:104
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
uint32_t u1[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:90
__weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Definition: ecdsa.c:492
ECDSA signature.
Definition: ecdsa.h:63
__weak_func error_t ecAffinify(const EcCurve *curve, EcPoint3 *r, const EcPoint3 *s)
Recover affine representation.
Definition: ec.c:791
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
#define PrngAlgo
Definition: crypto.h:980
ECDSA (Elliptic Curve Digital Signature Algorithm)
uint8_t p
Definition: ndp.h:300
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdsa.h:64
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
#define TRUE
Definition: os_port.h:50
error_t asn1WriteHeader(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag header.
Definition: asn1.c:501
error_t asn1InsertHeader(Asn1Tag *tag, uint8_t *data, size_t *written)
Insert an ASN.1 tag header.
Definition: asn1.c:643
const uint8_t ECDSA_WITH_SHA3_512_OID[9]
Definition: ecdsa.c:61
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
uint_t ecScalarGetBitLength(const uint32_t *a, uint_t n)
Get the actual length in bits.
Definition: ec_misc.c:273
const uint8_t ECDSA_WITH_SHA3_256_OID[9]
Definition: ecdsa.c:57
error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
Display an ASN.1 data object.
Definition: asn1.c:999
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define TRACE_DEBUG_EC_SCALAR(p, a, n)
Definition: debug.h:123
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:52
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
const uint8_t ECDSA_WITH_SHA256_OID[8]
Definition: ecdsa.c:49
__weak_func error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
Twin multiplication.
Definition: ec.c:1460
error_t ecdsaExportSignature(const EcdsaSignature *signature, uint8_t *output, size_t *written, EcdsaSignatureFormat format)
Export an ECDSA signature.
Definition: ecdsa.c:272
const uint8_t ECDSA_WITH_SHAKE256_OID[8]
Definition: ecdsa.c:65
size_t totalLength
Definition: asn1.h:111
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:86
size_t length
Definition: asn1.h:109
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
ASN.1 tag.
Definition: asn1.h:105
#define ASN1_INC_POINTER(p, n)
Definition: asn1.h:58
Helper routines for ECC.
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:73
const uint8_t ECDSA_WITH_SHAKE128_OID[8]
Definition: ecdsa.c:63
EcdsaSignatureFormat
ECDSA signature format.
Definition: ecdsa.h:50
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
@ ECDSA_SIGNATURE_FORMAT_RAW
Definition: ecdsa.h:52
Working state (ECDSA signature generation)
Definition: ecdsa.h:75
const uint8_t ECDSA_WITH_SHA384_OID[8]
Definition: ecdsa.c:51
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint32_t z[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:89
General definitions for cryptographic algorithms.
void ecScalarInvMod(const EcCurve *curve, uint32_t *r, const uint32_t *a)
Modular inversion.
Definition: ec_misc.c:1181
EC private key.
Definition: ec.h:432
uint_t objClass
Definition: asn1.h:107
uint8_t length
Definition: tcp.h:375
const uint8_t ECDSA_WITH_SHA3_224_OID[9]
Definition: ecdsa.c:55
#define MIN(a, b)
Definition: os_port.h:63
const uint8_t ECDSA_WITH_SHA1_OID[7]
Definition: ecdsa.c:45
const uint8_t ECDSA_WITH_SHA224_OID[8]
Definition: ecdsa.c:47
const uint8_t ECDSA_WITH_SHA512_OID[8]
Definition: ecdsa.c:53
uint32_t w[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:88
EC public key.
Definition: ec.h:421
@ ASN1_TYPE_INTEGER
Definition: asn1.h:73
#define TRACE_DEBUG(...)
Definition: debug.h:119
__weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:840
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
uint32_t z[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:77
@ ECDSA_SIGNATURE_FORMAT_ASN1
Definition: ecdsa.h:51
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
void ecScalarAddMod(const EcCurve *curve, uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular addition.
Definition: ec_misc.c:1062
uint32_t k[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:76
int_t ecScalarCompInt(const uint32_t *a, uint32_t b, uint_t n)
Compare integers.
Definition: ec_misc.c:374
const uint8_t ECDSA_WITH_SHA3_384_OID[9]
Definition: ecdsa.c:59
uint8_t n
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
@ ECDSA_SIGNATURE_FORMAT_RAW_R
Definition: ecdsa.h:53
#define cryptoFreeMem(p)
Definition: crypto.h:833
__weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:638
void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:762
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1354
EcPoint q
Public key.
Definition: ec.h:423
uint32_t s[EC_MAX_ORDER_SIZE]
Integer S.
Definition: ecdsa.h:66
bool_t constructed
Definition: asn1.h:106
void ecScalarShiftRight(uint32_t *r, const uint32_t *a, uint_t k, uint_t n)
Right shift operation.
Definition: ec_misc.c:940
error_t ecScalarRand(const EcCurve *curve, uint32_t *r, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: ec_misc.c:603
#define cryptoAllocMem(size)
Definition: crypto.h:828
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:83
uint32_t u2[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:91
#define EcCurve
Definition: ec.h:346
void ecScalarMod(uint32_t *r, const uint32_t *a, uint_t m, const uint32_t *p, uint_t n)
Modulo operation.
Definition: ec_misc.c:1009
int_t ecScalarComp(const uint32_t *a, const uint32_t *b, uint_t n)
Compare integers.
Definition: ec_misc.c:337
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
@ ECDSA_SIGNATURE_FORMAT_RAW_S
Definition: ecdsa.h:54
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:163
Working state (ECDSA signature verification)
Definition: ecdsa.h:87
uint32_t v[EC_MAX_ORDER_SIZE]
Definition: ecdsa.h:92
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
__weak_func void ecScalarMulMod(const EcCurve *curve, uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
Definition: ec_misc.c:1113
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:410
const uint8_t * value
Definition: asn1.h:110
error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass, uint_t objType)
Enforce the type of a specified tag.
Definition: asn1.c:944
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
ASN.1 (Abstract Syntax Notation One)
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:411