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.0
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] data 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 *data, size_t length, EcdsaSignatureFormat format)
106 {
107  error_t error;
108  size_t n;
109 
110  //Check parameters
111  if(signature == NULL || curve == NULL || data == 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");
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(data, 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(data, 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  data = tag.value;
147  length = tag.length;
148 
149  //Read the integer R
150  error = asn1ReadTag(data, 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  data += tag.totalLength;
175  length -= tag.totalLength;
176 
177  //Read the integer S
178  error = asn1ReadTag(data, 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, data, 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,
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, data, 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, data, 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] data Pointer to the octet string
267  * @param[out] length Length of the 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 *data,
273  size_t *length, EcdsaSignatureFormat format)
274 {
275  error_t error;
276  size_t k;
277  size_t n;
278  size_t rLen;
279  size_t sLen;
280  Asn1Tag tag;
281 
282  //Check parameters
283  if(signature == NULL || data == NULL || length == NULL)
285 
286  //Invalid elliptic curve?
287  if(signature->curve == NULL)
289 
290  //Debug message
291  TRACE_DEBUG("Exporting ECDSA signature...\r\n");
292 
293  //Dump (R, S) integer pair
294  TRACE_DEBUG(" r:\r\n");
295  TRACE_DEBUG_EC_SCALAR(" ", signature->r, EC_MAX_ORDER_SIZE);
296  TRACE_DEBUG(" s:\r\n");
297  TRACE_DEBUG_EC_SCALAR(" ", signature->s, EC_MAX_ORDER_SIZE);
298 
299  //Calculate the length of R
300  rLen = ecScalarGetByteLength(signature->r, EC_MAX_ORDER_SIZE);
301  //Calculate the length of S
302  sLen = ecScalarGetByteLength(signature->s, EC_MAX_ORDER_SIZE);
303 
304  //Make sure the (R, S) integer pair is valid
305  if(rLen == 0 || sLen == 0)
306  return ERROR_INVALID_LENGTH;
307 
308  //Check the format of the ECDSA signature
309  if(format == ECDSA_SIGNATURE_FORMAT_ASN1)
310  {
311  //R and S are always encoded in the smallest possible number of octets
312  if(ecScalarGetBitValue(signature->r, (rLen * 8) - 1) != 0)
313  {
314  rLen++;
315  }
316 
317  if(ecScalarGetBitValue(signature->s, (sLen * 8) - 1) != 0)
318  {
319  sLen++;
320  }
321 
322  //The first pass computes the length of the ASN.1 sequence
323  n = 0;
324 
325  //The integer R is encapsulated within an ASN.1 structure
326  tag.constructed = FALSE;
329  tag.length = rLen;
330  tag.value = NULL;
331 
332  //Compute the length of the corresponding ASN.1 structure
333  error = asn1WriteTag(&tag, FALSE, NULL, NULL);
334  //Any error to report?
335  if(error)
336  return error;
337 
338  //Update the length of the ASN.1 sequence
339  n += tag.totalLength;
340 
341  //The integer S is encapsulated within an ASN.1 structure
342  tag.constructed = FALSE;
345  tag.length = sLen;
346  tag.value = NULL;
347 
348  //Compute the length of the corresponding ASN.1 structure
349  error = asn1WriteTag(&tag, FALSE, NULL, NULL);
350  //Any error to report?
351  if(error)
352  return error;
353 
354  //Update the length of the ASN.1 sequence
355  n += tag.totalLength;
356 
357  //The second pass encodes the ASN.1 structure
358  k = 0;
359 
360  //The (R, S) integer pair is encapsulated within a sequence
361  tag.constructed = TRUE;
364  tag.length = n;
365  tag.value = NULL;
366 
367  //Write the corresponding ASN.1 tag
368  error = asn1WriteTag(&tag, FALSE, data + k, &n);
369  //Any error to report?
370  if(error)
371  return error;
372 
373  //Advance write pointer
374  k += n;
375 
376  //Encode the integer R using ASN.1
377  tag.constructed = FALSE;
380  tag.length = rLen;
381  tag.value = NULL;
382 
383  //Write the corresponding ASN.1 tag
384  error = asn1WriteTag(&tag, FALSE, data + k, &n);
385  //Any error to report?
386  if(error)
387  return error;
388 
389  //Advance write pointer
390  k += n;
391 
392  //Convert R to an octet string
393  error = ecScalarExport(signature->r, EC_MAX_ORDER_SIZE, data + k, rLen,
395  //Any error to report?
396  if(error)
397  return error;
398 
399  //Advance write pointer
400  k += rLen;
401 
402  //Encode the integer S using ASN.1
403  tag.constructed = FALSE;
406  tag.length = sLen;
407  tag.value = NULL;
408 
409  //Write the corresponding ASN.1 tag
410  error = asn1WriteTag(&tag, FALSE, data + k, &n);
411  //Any error to report?
412  if(error)
413  return error;
414 
415  //Advance write pointer
416  k += n;
417 
418  //Convert S to an octet string
419  error = ecScalarExport(signature->s, EC_MAX_ORDER_SIZE, data + k, sLen,
421  //Any error to report?
422  if(error)
423  return error;
424 
425  //Advance write pointer
426  k += sLen;
427 
428  //Total length of the ASN.1 structure
429  *length = k;
430  }
431  else if(format == ECDSA_SIGNATURE_FORMAT_RAW)
432  {
433  //Get the length of the order, in bytes
434  n = (signature->curve->orderSize + 7) / 8;
435 
436  //Convert R to an octet string
437  error = ecScalarExport(signature->r, (n + 3) / 4, data, n,
439  //Any error to report?
440  if(error)
441  return error;
442 
443  //Convert S to an octet string
444  error = ecScalarExport(signature->s, (n + 3) / 4, data + n, n,
446  //Any error to report?
447  if(error)
448  return error;
449 
450  //Length of the resulting octet string
451  *length = 2 * n;
452  }
453  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_R)
454  {
455  //Get the length of the order, in bytes
456  n = (signature->curve->orderSize + 7) / 8;
457 
458  //Convert R to an octet string
459  error = ecScalarExport(signature->r, (n + 3) / 4, data, n,
461  //Any error to report?
462  if(error)
463  return error;
464 
465  //Length of the resulting octet string
466  *length = n;
467  }
468  else if(format == ECDSA_SIGNATURE_FORMAT_RAW_S)
469  {
470  //Get the length of the order, in bytes
471  n = (signature->curve->orderSize + 7) / 8;
472 
473  //Convert S to an octet string
474  error = ecScalarExport(signature->s, (n + 3) / 4, data, n,
476  //Any error to report?
477  if(error)
478  return error;
479 
480  //Length of the resulting octet string
481  *length = n;
482  }
483  else
484  {
485  //Invalid format
487  }
488 
489  //Dump ECDSA signature
490  TRACE_DEBUG(" signature:\r\n");
491  TRACE_DEBUG_ARRAY(" ", data, *length);
492 
493  //Successful processing
494  return NO_ERROR;
495 }
496 
497 
498 /**
499  * @brief ECDSA signature generation
500  * @param[in] prngAlgo PRNG algorithm
501  * @param[in] prngContext Pointer to the PRNG context
502  * @param[in] privateKey Signer's EC private key
503  * @param[in] digest Digest of the message to be signed
504  * @param[in] digestLen Length in octets of the digest
505  * @param[out] signature (R, S) integer pair
506  * @return Error code
507  **/
508 
509 __weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo,
510  void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest,
511  size_t digestLen, EcdsaSignature *signature)
512 {
513  error_t error;
514  uint_t n;
515  uint_t pLen;
516  uint_t qLen;
517 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
519 #else
521 #endif
522 
523  //Check parameters
524  if(privateKey == NULL || digest == NULL || signature == NULL)
526 
527  //Invalid elliptic curve?
528  if(privateKey->curve == NULL)
530 
531  //Get the length of the modulus, in words
532  pLen = (privateKey->curve->fieldSize + 31) / 32;
533  //Get the length of the order, in words
534  qLen = (privateKey->curve->orderSize + 31) / 32;
535 
536  //Debug message
537  TRACE_DEBUG("ECDSA signature generation...\r\n");
538  TRACE_DEBUG(" curve: %s\r\n", privateKey->curve->name);
539  TRACE_DEBUG(" private key:\r\n");
540  TRACE_DEBUG_EC_SCALAR(" ", privateKey->d, qLen);
541  TRACE_DEBUG(" digest:\r\n");
542  TRACE_DEBUG_ARRAY(" ", digest, digestLen);
543 
544 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
545  //Allocate working state
547  //Failed to allocate memory?
548  if(state == NULL)
549  return ERROR_OUT_OF_MEMORY;
550 #endif
551 
552  //Initialize working state
553  osMemset(state, 0, sizeof(EcdsaGenerateSignatureState));
554 
555  //Initialize (R, S) integer pair
556  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
557  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
558 
559  //Generate a random number k such as 0 < k < q - 1
560  error = ecScalarRand(privateKey->curve, state->k, prngAlgo, prngContext);
561 
562  //Check status code
563  if(!error)
564  {
565  //Debug message
566  TRACE_DEBUG(" k:\r\n");
567  TRACE_DEBUG_EC_SCALAR(" ", state->k, qLen);
568 
569  //Let N be the bit length of q
570  n = privateKey->curve->orderSize;
571  //Compute N = MIN(N, outlen)
572  n = MIN(n, digestLen * 8);
573 
574  //Convert the digest to an integer
575  error = ecScalarImport(state->z, qLen, digest, (n + 7) / 8,
577  }
578 
579  //Check status code
580  if(!error)
581  {
582  //Keep the leftmost N bits of the hash value
583  if((n % 8) != 0)
584  {
585  ecScalarShiftRight(state->z, state->z, 8 - (n % 8), qLen);
586  }
587 
588  //Debug message
589  TRACE_DEBUG(" z:\r\n");
590  TRACE_DEBUG_EC_SCALAR(" ", state->z, qLen);
591 
592  //Compute R1 = (x1, y1) = k.G
593  error = ecMulRegular(privateKey->curve, &state->r1, state->k,
594  &privateKey->curve->g);
595  }
596 
597  //Check status code
598  if(!error)
599  {
600  //Convert R1 to affine representation
601  error = ecAffinify(privateKey->curve, &state->r1, &state->r1);
602  }
603 
604  //Check status code
605  if(!error)
606  {
607  //Debug message
608  TRACE_DEBUG(" x1:\r\n");
609  TRACE_DEBUG_EC_SCALAR(" ", state->r1.x, pLen);
610  TRACE_DEBUG(" y1:\r\n");
611  TRACE_DEBUG_EC_SCALAR(" ", state->r1.y, pLen);
612 
613  //Compute r = x1 mod q
614  ecScalarMod(signature->r, state->r1.x, pLen, privateKey->curve->q, qLen);
615  //Compute k ^ -1 mod q
616  ecScalarInvMod(privateKey->curve, state->k, state->k);
617 
618  //Compute s = k ^ -1 * (z + x * r) mod q
619  ecScalarMulMod(privateKey->curve, signature->s, privateKey->d, signature->r);
620  ecScalarAddMod(privateKey->curve, signature->s, signature->s, state->z);
621  ecScalarMulMod(privateKey->curve, signature->s, signature->s, state->k);
622 
623  //Save elliptic curve parameters
624  signature->curve = privateKey->curve;
625 
626  //Debug message
627  TRACE_DEBUG(" r:\r\n");
628  TRACE_DEBUG_EC_SCALAR(" ", signature->r, qLen);
629  TRACE_DEBUG(" s:\r\n");
630  TRACE_DEBUG_EC_SCALAR(" ", signature->s, qLen);
631  }
632 
633  //Erase working state
634  osMemset(state, 0, sizeof(EcdsaGenerateSignatureState));
635 
636 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
637  //Release working state
638  cryptoFreeMem(state);
639 #endif
640 
641  //Successful processing
642  return NO_ERROR;
643 }
644 
645 
646 /**
647  * @brief ECDSA signature verification
648  * @param[in] publicKey Signer's EC public key
649  * @param[in] digest Digest of the message whose signature is to be verified
650  * @param[in] digestLen Length in octets of the digest
651  * @param[in] signature (R, S) integer pair
652  * @return Error code
653  **/
654 
655 __weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey,
656  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
657 {
658  error_t error;
659  uint_t n;
660  uint_t pLen;
661  uint_t qLen;
662 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
664 #else
665  EcdsaVerifySignatureState state[1];
666 #endif
667 
668  //Check parameters
669  if(publicKey == NULL || digest == NULL || signature == NULL)
671 
672  //Invalid elliptic curve?
673  if(publicKey->curve == NULL)
675 
676  //Get the length of the modulus, in words
677  pLen = (publicKey->curve->fieldSize + 31) / 32;
678  //Get the length of the order, in words
679  qLen = (publicKey->curve->orderSize + 31) / 32;
680 
681  //Debug message
682  TRACE_DEBUG("ECDSA signature verification...\r\n");
683  TRACE_DEBUG(" curve: %s\r\n", publicKey->curve->name);
684  TRACE_DEBUG(" public key X:\r\n");
685  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.x, pLen);
686  TRACE_DEBUG(" public key Y:\r\n");
687  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.y, pLen);
688  TRACE_DEBUG(" digest:\r\n");
689  TRACE_DEBUG_ARRAY(" ", digest, digestLen);
690  TRACE_DEBUG(" r:\r\n");
691  TRACE_DEBUG_EC_SCALAR(" ", signature->r, qLen);
692  TRACE_DEBUG(" s:\r\n");
693  TRACE_DEBUG_EC_SCALAR(" ", signature->s, qLen);
694 
695  //Verify that the public key is on the curve
696  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
697  {
699  }
700 
701  //The verifier shall check that 0 < r < q
702  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
703  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
704  {
705  //If the condition is violated, the signature shall be rejected as invalid
707  }
708 
709  //The verifier shall check that 0 < s < q
710  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
711  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
712  {
713  //If the condition is violated, the signature shall be rejected as invalid
715  }
716 
717 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
718  //Allocate working state
719  state = cryptoAllocMem(sizeof(EcdsaVerifySignatureState));
720  //Failed to allocate memory?
721  if(state == NULL)
722  return ERROR_OUT_OF_MEMORY;
723 #endif
724 
725  //Initialize working state
726  osMemset(state, 0, sizeof(EcdsaVerifySignatureState));
727 
728  //Let N be the bit length of q
729  n = publicKey->curve->orderSize;
730  //Compute N = MIN(N, outlen)
731  n = MIN(n, digestLen * 8);
732 
733  //Convert the digest to an integer
734  error = ecScalarImport(state->z, qLen, digest, (n + 7) / 8,
736 
737  //Check status code
738  if(!error)
739  {
740  //Keep the leftmost N bits of the hash value
741  if((n % 8) != 0)
742  {
743  ecScalarShiftRight(state->z, state->z, 8 - (n % 8), qLen);
744  }
745 
746  //Compute w = s ^ -1 mod q
747  ecScalarInvMod(publicKey->curve, state->w, signature->s);
748 
749  //Compute u1 = z * w mod q
750  ecScalarMulMod(publicKey->curve, state->u1, state->z, state->w);
751  //Compute u2 = r * w mod q
752  ecScalarMulMod(publicKey->curve, state->u2, signature->r, state->w);
753 
754  //Convert the public key to projective representation
755  ecProjectify(publicKey->curve, &state->v1, &publicKey->q);
756 
757  //Compute V0 = (x0, y0) = u1.G + u2.Q
758  error = ecTwinMul(publicKey->curve, &state->v0, state->u1,
759  &publicKey->curve->g, state->u2, &state->v1);
760  }
761 
762  //Check status code
763  if(!error)
764  {
765  //Convert V0 to affine representation
766  error = ecAffinify(publicKey->curve, &state->v0, &state->v0);
767  }
768 
769  //Check status code
770  if(!error)
771  {
772  //Debug message
773  TRACE_DEBUG(" x0:\r\n");
774  TRACE_DEBUG_EC_SCALAR(" ", state->v0.x, pLen);
775  TRACE_DEBUG(" y0:\r\n");
776  TRACE_DEBUG_EC_SCALAR(" ", state->v0.y, pLen);
777 
778  //Compute v = x0 mod q
779  ecScalarMod(state->v, state->v0.x, pLen, publicKey->curve->q, qLen);
780 
781  //Debug message
782  TRACE_DEBUG(" v:\r\n");
783  TRACE_DEBUG_EC_SCALAR(" ", state->v, qLen);
784 
785  //If v = r, then the signature is verified. If v does not equal r, then the
786  //message or the signature may have been modified
787  if(ecScalarComp(state->v, signature->r, qLen) == 0)
788  {
789  error = NO_ERROR;
790  }
791  else
792  {
793  error = ERROR_INVALID_SIGNATURE;
794  }
795  }
796 
797  //Erase working state
798  osMemset(state, 0, sizeof(EcdsaVerifySignatureState));
799 
800 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
801  //Release working state
802  cryptoFreeMem(state);
803 #endif
804 
805  //Return status code
806  return error;
807 }
808 
809 #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
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:509
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:749
uint_t ecScalarGetByteLength(const uint32_t *a, uint_t n)
Get the actual length in bytes.
Definition: ec_misc.c:231
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:973
ECDSA (Elliptic Curve Digital Signature Algorithm)
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdsa.h:64
uint32_t ecScalarGetBitValue(const uint32_t *a, int_t index)
Get the bit value at the specified index.
Definition: ec_misc.c:315
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
const uint8_t ECDSA_WITH_SHA3_512_OID[9]
Definition: ecdsa.c:61
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
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:856
@ 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
error_t ecdsaExportSignature(const EcdsaSignature *signature, uint8_t *data, size_t *length, EcdsaSignatureFormat format)
Export an ECDSA signature.
Definition: ecdsa.c:272
__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:1418
const uint8_t ECDSA_WITH_SHAKE256_OID[8]
Definition: ecdsa.c:65
size_t totalLength
Definition: asn1.h:108
@ 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:106
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
error_t ecdsaImportSignature(EcdsaSignature *signature, const EcCurve *curve, const uint8_t *data, size_t length, EcdsaSignatureFormat format)
Import an ECDSA signature.
Definition: ecdsa.c:104
#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:102
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
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
EC private key.
Definition: ec.h:432
uint_t objClass
Definition: asn1.h:104
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:70
#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:798
#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:826
__weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:655
void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:720
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1312
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:103
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:821
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
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:107
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:803
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:105
ASN.1 (Abstract Syntax Notation One)
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:411