tls_sign_generate.c
Go to the documentation of this file.
1 /**
2  * @file tls_sign_generate.c
3  * @brief RSA/DSA/ECDSA/EdDSA signature generation
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL 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.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_sign_generate.h"
37 #include "tls_sign_misc.h"
38 #include "tls_transcript_hash.h"
39 #include "tls_misc.h"
40 #include "pkix/pem_import.h"
41 #include "pkc/rsa.h"
42 #include "pkc/dsa.h"
43 #include "ecc/ecdsa.h"
44 #include "ecc/eddsa.h"
45 #include "debug.h"
46 
47 //Check TLS library configuration
48 #if (TLS_SUPPORT == ENABLED)
49 
50 
51 /**
52  * @brief Digital signature generation (TLS 1.0 or TLS 1.1)
53  * @param[in] context Pointer to the TLS context
54  * @param[out] p Buffer where to store the digitally-signed element
55  * @param[out] length Length of the digitally-signed element
56  * @return Error code
57  **/
58 
60  size_t *length)
61 {
62 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
63  error_t error;
64  size_t n;
65  TlsDigitalSignature *signature;
66 
67  //The digitally-signed element does not convey the signature algorithm
68  //to use, and hence implementations need to inspect the certificate to
69  //find out the signature algorithm to use
70  signature = (TlsDigitalSignature *) p;
71 
72 #if (TLS_RSA_SIGN_SUPPORT == ENABLED)
73  //RSA certificate?
74  if(context->cert->type == TLS_CERT_RSA_SIGN)
75  {
76  RsaPrivateKey privateKey;
77 
78  //Initialize RSA private key
79  rsaInitPrivateKey(&privateKey);
80 
81  //Digest all the handshake messages starting at ClientHello using MD5
83  context->transcriptMd5Context, "", context->clientVerifyData);
84 
85  //Check status code
86  if(!error)
87  {
88  //Digest all the handshake messages starting at ClientHello using SHA-1
90  context->transcriptSha1Context, "",
91  context->clientVerifyData + MD5_DIGEST_SIZE);
92  }
93 
94  //Check status code
95  if(!error)
96  {
97  //Decode the PEM structure that holds the RSA private key
98  error = pemImportRsaPrivateKey(context->cert->privateKey,
99  context->cert->privateKeyLen, context->cert->password, &privateKey);
100  }
101 
102  //Check status code
103  if(!error)
104  {
105  //Generate an RSA signature using the client's private key
106  error = tlsGenerateRsaSignature(&privateKey,
107  context->clientVerifyData, signature->value, &n);
108  }
109 
110  //Release previously allocated resources
111  rsaFreePrivateKey(&privateKey);
112  }
113  else
114 #endif
115 #if (TLS_DSA_SIGN_SUPPORT == ENABLED)
116  //DSA certificate?
117  if(context->cert->type == TLS_CERT_DSS_SIGN)
118  {
119  //Digest all the handshake messages starting at ClientHello
120  error = tlsFinalizeTranscriptHash(context, SHA1_HASH_ALGO,
121  context->transcriptSha1Context, "", context->clientVerifyData);
122 
123  //Check status code
124  if(!error)
125  {
126  //Generate a DSA signature using the client's private key
127  error = tlsGenerateDsaSignature(context, context->clientVerifyData,
128  SHA1_DIGEST_SIZE, signature->value, &n);
129  }
130  }
131  else
132 #endif
133 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
134  //ECDSA certificate?
135  if(context->cert->type == TLS_CERT_ECDSA_SIGN)
136  {
137  //Digest all the handshake messages starting at ClientHello
138  error = tlsFinalizeTranscriptHash(context, SHA1_HASH_ALGO,
139  context->transcriptSha1Context, "", context->clientVerifyData);
140 
141  //Check status code
142  if(!error)
143  {
144  //Generate an ECDSA signature using the client's private key
145  error = tlsGenerateEcdsaSignature(context, context->clientVerifyData,
146  SHA1_DIGEST_SIZE, signature->value, &n);
147  }
148  }
149  else
150 #endif
151  //Invalid certificate?
152  {
153  //Report an error
155  }
156 
157  //Check status code
158  if(!error)
159  {
160  //The signature is preceded by a 2-byte length field
161  signature->length = htons(n);
162  //Total length of the digitally-signed element
163  *length = sizeof(TlsDigitalSignature) + n;
164  }
165 
166  //Return status code
167  return error;
168 #else
169  //Not implemented
170  return ERROR_NOT_IMPLEMENTED;
171 #endif
172 }
173 
174 
175 /**
176  * @brief Digital signature generation (TLS 1.2)
177  * @param[in] context Pointer to the TLS context
178  * @param[out] p Buffer where to store the digitally-signed element
179  * @param[out] length Length of the digitally-signed element
180  * @return Error code
181  **/
182 
184  size_t *length)
185 {
186 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
187  error_t error;
188  size_t n;
189  Tls12DigitalSignature *signature;
190  const HashAlgo *hashAlgo;
191 
192  //Point to the digitally-signed element
193  signature = (Tls12DigitalSignature *) p;
194  //The algorithm field specifies the signature scheme
195  signature->algorithm = htons(context->signScheme);
196 
197  //Check signature scheme
198  if(TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_RSA ||
199  TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_DSA ||
200  TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_ECDSA)
201  {
202  //Retrieve the hash algorithm used for signing
203  hashAlgo = tlsGetHashAlgo(TLS_HASH_ALGO(context->signScheme));
204  }
205  else if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256 ||
206  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256)
207  {
208  //The hashing is intrinsic to the signature algorithm
210  }
211  else if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384 ||
212  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384)
213  {
214  //The hashing is intrinsic to the signature algorithm
216  }
217  else if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512 ||
218  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512)
219  {
220  //The hashing is intrinsic to the signature algorithm
222  }
223  else
224  {
225  //Unknown signature scheme
226  hashAlgo = NULL;
227  }
228 
229  //Digest all the handshake messages starting at ClientHello
230  if(hashAlgo == SHA1_HASH_ALGO)
231  {
232  //Use SHA-1 hash algorithm
233  error = tlsFinalizeTranscriptHash(context, SHA1_HASH_ALGO,
234  context->transcriptSha1Context, "", context->clientVerifyData);
235  }
236  else if(hashAlgo == context->cipherSuite.prfHashAlgo)
237  {
238  //Use PRF hash algorithm (SHA-256 or SHA-384)
239  error = tlsFinalizeTranscriptHash(context, hashAlgo,
240  context->transcriptHashContext, "", context->clientVerifyData);
241  }
242  else
243  {
244  //The specified hash algorithm is not supported
246  }
247 
248  //Handshake message hash successfully computed?
249  if(!error)
250  {
251 #if (TLS_RSA_SIGN_SUPPORT == ENABLED)
252  //RSASSA-PKCS1-v1_5 signature scheme?
253  if(TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_RSA)
254  {
255  //Generate RSA signature (RSASSA-PKCS1-v1_5 signature scheme)
256  error = tlsGenerateRsaPkcs1Signature(context, hashAlgo,
257  context->clientVerifyData, signature->value, &n);
258  }
259  else
260 #endif
261 #if (TLS_RSA_PSS_SIGN_SUPPORT == ENABLED)
262  //RSASSA-PSS signature scheme?
263  if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256 ||
264  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384 ||
265  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512 ||
266  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256 ||
267  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384 ||
268  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512)
269  {
270  //Generate RSA signature (RSASSA-PSS signature scheme)
271  error = tlsGenerateRsaPssSignature(context, hashAlgo,
272  context->clientVerifyData, signature->value, &n);
273  }
274  else
275 #endif
276 #if (TLS_DSA_SIGN_SUPPORT == ENABLED)
277  //DSA signature scheme?
278  if(TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_DSA)
279  {
280  //Generate a DSA signature using the client's private key
281  error = tlsGenerateDsaSignature(context, context->clientVerifyData,
282  hashAlgo->digestSize, signature->value, &n);
283  }
284  else
285 #endif
286 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
287  //ECDSA signature scheme?
288  if(TLS_SIGN_ALGO(context->signScheme) == TLS_SIGN_ALGO_ECDSA)
289  {
290  //Generate an ECDSA signature using the client's private key
291  error = tlsGenerateEcdsaSignature(context, context->clientVerifyData,
292  hashAlgo->digestSize, signature->value, &n);
293  }
294  else
295 #endif
296  //Invalid signature scheme?
297  {
298  //Report an error
300  }
301  }
302 
303  //Check status code
304  if(!error)
305  {
306  //The signature is preceded by a 2-byte length field
307  signature->length = htons(n);
308  //Total length of the digitally-signed element
309  *length = sizeof(Tls12DigitalSignature) + n;
310  }
311 
312  //Return status code
313  return error;
314 #else
315  //Not implemented
316  return ERROR_NOT_IMPLEMENTED;
317 #endif
318 }
319 
320 
321 /**
322  * @brief Generate RSA signature (TLS 1.0 and TLS 1.1)
323  * @param[in] key Signer's RSA private key
324  * @param[in] digest Digest of the message to be signed
325  * @param[out] signature Resulting signature
326  * @param[out] signatureLen Length of the resulting signature
327  * @return Error code
328  **/
329 
331  const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
332 {
333 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1 && \
334  TLS_RSA_SIGN_SUPPORT == ENABLED)
335  error_t error;
336  size_t k;
337  size_t paddingLen;
338  uint8_t *em;
339  Mpi m;
340  Mpi s;
341 
342  //Debug message
343  TRACE_DEBUG("RSA signature generation...\r\n");
344  TRACE_DEBUG(" Modulus:\r\n");
345  TRACE_DEBUG_MPI(" ", &key->n);
346  TRACE_DEBUG(" Public exponent:\r\n");
347  TRACE_DEBUG_MPI(" ", &key->e);
348  TRACE_DEBUG(" Private exponent:\r\n");
349  TRACE_DEBUG_MPI(" ", &key->d);
350  TRACE_DEBUG(" Prime 1:\r\n");
351  TRACE_DEBUG_MPI(" ", &key->p);
352  TRACE_DEBUG(" Prime 2:\r\n");
353  TRACE_DEBUG_MPI(" ", &key->q);
354  TRACE_DEBUG(" Prime exponent 1:\r\n");
355  TRACE_DEBUG_MPI(" ", &key->dp);
356  TRACE_DEBUG(" Prime exponent 2:\r\n");
357  TRACE_DEBUG_MPI(" ", &key->dq);
358  TRACE_DEBUG(" Coefficient:\r\n");
359  TRACE_DEBUG_MPI(" ", &key->qinv);
360  TRACE_DEBUG(" Message digest:\r\n");
362 
363  //Initialize multiple-precision integers
364  mpiInit(&m);
365  mpiInit(&s);
366 
367  //Get the length in octets of the modulus n
368  k = mpiGetByteLength(&key->n);
369 
370  //Check the length of the modulus
371  if(k < (MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE + 11))
372  return ERROR_INVALID_KEY;
373 
374  //Point to the buffer where the encoded message EM will be generated
375  em = signature;
376 
377  //The leading 0x00 octet ensures that the encoded message,
378  //converted to an integer, is less than the modulus
379  em[0] = 0x00;
380  //Block type 0x01 is used for private-key operations
381  em[1] = 0x01;
382 
383  //Compute the length of the padding string PS
384  paddingLen = k - (MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE + 3);
385  //Fill the padding string with 0xFF
386  osMemset(em + 2, 0xFF, paddingLen);
387  //Append a 0x00 octet to PS
388  em[paddingLen + 2] = 0x00;
389 
390  //Append the digest value
391  osMemcpy(em + paddingLen + 3, digest, MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE);
392 
393  //Debug message
394  TRACE_DEBUG(" Encoded message\r\n");
395  TRACE_DEBUG_ARRAY(" ", em, k);
396 
397  //Start of exception handling block
398  do
399  {
400  //Convert the encoded message EM to an integer message representative m
401  error = mpiImport(&m, em, k, MPI_FORMAT_BIG_ENDIAN);
402  //Conversion failed?
403  if(error)
404  break;
405 
406  //Apply the RSASP1 signature primitive
407  error = rsasp1(key, &m, &s);
408  //Any error to report?
409  if(error)
410  break;
411 
412  //Convert the signature representative s to a signature of length k octets
413  error = mpiExport(&s, signature, k, MPI_FORMAT_BIG_ENDIAN);
414  //Conversion failed?
415  if(error)
416  break;
417 
418  //Length of the resulting signature
419  *signatureLen = k;
420 
421  //Debug message
422  TRACE_DEBUG(" Signature:\r\n");
423  TRACE_DEBUG_ARRAY(" ", signature, *signatureLen);
424 
425  //End of exception handling block
426  } while(0);
427 
428  //Free previously allocated memory
429  mpiFree(&m);
430  mpiFree(&s);
431 
432  //Return status code
433  return error;
434 #else
435  //RSA signature algorithm is not supported
436  return ERROR_NOT_IMPLEMENTED;
437 #endif
438 }
439 
440 
441 /**
442  * @brief Generate RSA signature (TLS 1.2)
443  * @param[in] context Pointer to the TLS context
444  * @param[in] hashAlgo Hash function used to digest the message
445  * @param[in] digest Digest of the message to be signed
446  * @param[out] signature Resulting signature
447  * @param[out] signatureLen Length of the resulting signature
448  * @return Error code
449  **/
450 
452  const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature,
453  size_t *signatureLen)
454 {
455 #if (TLS_RSA_SIGN_SUPPORT == ENABLED)
456  error_t error;
457  RsaPrivateKey privateKey;
458 
459  //Initialize RSA private key
460  rsaInitPrivateKey(&privateKey);
461 
462  //Decode the PEM structure that holds the RSA private key
463  error = pemImportRsaPrivateKey(context->cert->privateKey,
464  context->cert->privateKeyLen, context->cert->password, &privateKey);
465 
466  //Check status code
467  if(!error)
468  {
469  //Generate RSA signature (RSASSA-PKCS1-v1_5 signature scheme)
470  error = rsassaPkcs1v15Sign(&privateKey, hashAlgo, digest, signature,
471  signatureLen);
472  }
473 
474  //Release previously allocated resources
475  rsaFreePrivateKey(&privateKey);
476 
477  //Return status code
478  return error;
479 #else
480  //RSA signature algorithm is not supported
481  return ERROR_NOT_IMPLEMENTED;
482 #endif
483 }
484 
485 
486 /**
487  * @brief Generate RSA-PSS signature
488  * @param[in] context Pointer to the TLS context
489  * @param[in] hashAlgo Hash function used to digest the message
490  * @param[in] digest Digest of the message to be signed
491  * @param[in] digestLen Length in octets of the digest
492  * @param[out] signature Resulting signature
493  * @param[out] signatureLen Length of the resulting signature
494  * @return Error code
495  **/
496 
498  const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature,
499  size_t *signatureLen)
500 {
501 #if (TLS_RSA_PSS_SIGN_SUPPORT == ENABLED)
502  error_t error;
503  RsaPrivateKey privateKey;
504 
505  //Initialize RSA private key
506  rsaInitPrivateKey(&privateKey);
507 
508  //Decode the PEM structure that holds the RSA private key
509  error = pemImportRsaPrivateKey(context->cert->privateKey,
510  context->cert->privateKeyLen, context->cert->password, &privateKey);
511 
512  //Check status code
513  if(!error)
514  {
515  //Generate RSA signature (RSASSA-PSS signature scheme)
516  error = rsassaPssSign(context->prngAlgo, context->prngContext,
517  &privateKey, hashAlgo, hashAlgo->digestSize,digest, signature,
518  signatureLen);
519  }
520 
521  //Release previously allocated resources
522  rsaFreePrivateKey(&privateKey);
523 
524  //Return status code
525  return error;
526 #else
527  //RSA signature algorithm is not supported
528  return ERROR_NOT_IMPLEMENTED;
529 #endif
530 }
531 
532 
533 /**
534  * @brief Generate DSA signature
535  * @param[in] context Pointer to the TLS context
536  * @param[in] digest Digest of the message to be signed
537  * @param[in] digestLen Length in octets of the digest
538  * @param[out] signature Resulting signature
539  * @param[out] signatureLen Length of the resulting signature
540  * @return Error code
541  **/
542 
543 error_t tlsGenerateDsaSignature(TlsContext *context, const uint8_t *digest,
544  size_t digestLen, uint8_t *signature, size_t *signatureLen)
545 {
546 #if (TLS_DSA_SIGN_SUPPORT == ENABLED)
547  error_t error;
548  DsaPrivateKey privateKey;
549  DsaSignature dsaSignature;
550 
551  //Initialize DSA private key
552  dsaInitPrivateKey(&privateKey);
553  //Initialize DSA signature
554  dsaInitSignature(&dsaSignature);
555 
556  //Decode the PEM structure that holds the DSA private key
557  error = pemImportDsaPrivateKey(context->cert->privateKey,
558  context->cert->privateKeyLen, context->cert->password, &privateKey);
559 
560  //Check status code
561  if(!error)
562  {
563  //Generate DSA signature
564  error = dsaGenerateSignature(context->prngAlgo, context->prngContext,
565  &privateKey, digest, digestLen, &dsaSignature);
566  }
567 
568  //Check status code
569  if(!error)
570  {
571  //Encode the resulting (R, S) integer pair using ASN.1
572  error = dsaWriteSignature(&dsaSignature, signature, signatureLen);
573  }
574 
575  //Free previously allocated resources
576  dsaFreePrivateKey(&privateKey);
577  dsaFreeSignature(&dsaSignature);
578 
579  //Return status code
580  return error;
581 #else
582  //DSA signature algorithm is not supported
583  return ERROR_NOT_IMPLEMENTED;
584 #endif
585 }
586 
587 
588 /**
589  * @brief Generate ECDSA signature
590  * @param[in] context Pointer to the TLS context
591  * @param[in] digest Digest of the message to be signed
592  * @param[in] digestLen Length in octets of the digest
593  * @param[out] signature Resulting signature
594  * @param[out] signatureLen Length of the resulting signature
595  * @return Error code
596  **/
597 
598 error_t tlsGenerateEcdsaSignature(TlsContext *context, const uint8_t *digest,
599  size_t digestLen, uint8_t *signature, size_t *signatureLen)
600 {
601 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
602  error_t error;
603  EcDomainParameters params;
604  EcPrivateKey privateKey;
605  EcdsaSignature ecdsaSignature;
606 
607  //Initialize ECDSA signature
608  ecdsaInitSignature(&ecdsaSignature);
609 
610 #if (TLS_ECC_CALLBACK_SUPPORT == ENABLED)
611  //Any registered callback?
612  if(context->ecdsaSignCallback != NULL)
613  {
614  //Invoke user callback function
615  error = context->ecdsaSignCallback(context, digest, digestLen,
616  &ecdsaSignature);
617  }
618  else
619 #endif
620  {
621  //Initialize EC domain parameters
622  ecInitDomainParameters(&params);
623  //Initialize EC private key
624  ecInitPrivateKey(&privateKey);
625 
626  //Decode the PEM structure that holds the EC domain parameters
627  error = pemImportEcParameters(context->cert->privateKey,
628  context->cert->privateKeyLen, &params);
629 
630  //Check status code
631  if(!error)
632  {
633  //Decode the PEM structure that holds the EC private key
634  error = pemImportEcPrivateKey(context->cert->privateKey,
635  context->cert->privateKeyLen, context->cert->password, &privateKey);
636  }
637 
638  //Check status code
639  if(!error)
640  {
641  //Generate ECDSA signature
642  error = ecdsaGenerateSignature(context->prngAlgo, context->prngContext,
643  &params, &privateKey, digest, digestLen, &ecdsaSignature);
644  }
645 
646  //Release previously allocated resources
647  ecFreeDomainParameters(&params);
648  ecFreePrivateKey(&privateKey);
649  }
650 
651  //Check status code
652  if(!error)
653  {
654  //Encode the resulting (R, S) integer pair using ASN.1
655  error = ecdsaWriteSignature(&ecdsaSignature, signature, signatureLen);
656  }
657 
658  //Release previously allocated resources
659  ecdsaFreeSignature(&ecdsaSignature);
660 
661  //Return status code
662  return error;
663 #else
664  //ECDSA signature algorithm is not supported
665  return ERROR_NOT_IMPLEMENTED;
666 #endif
667 }
668 
669 
670 /**
671  * @brief Generate Ed25519 signature
672  * @param[in] context Pointer to the TLS context
673  * @param[in] messageChunks Collection of chunks representing the message to
674  * be signed
675  * @param[out] signature Resulting signature
676  * @param[out] signatureLen Length of the resulting signature
677  * @return Error code
678  **/
679 
681  const EddsaMessageChunk *messageChunks, uint8_t *signature,
682  size_t *signatureLen)
683 {
684 #if (TLS_ED25519_SIGN_SUPPORT == ENABLED)
685  error_t error;
686  EddsaPrivateKey privateKey;
687  uint8_t d[ED25519_PRIVATE_KEY_LEN];
688 
689  //Initialize EdDSA private key
690  eddsaInitPrivateKey(&privateKey);
691 
692  //Decode the PEM structure that holds the EdDSA private key
693  error = pemImportEddsaPrivateKey(context->cert->privateKey,
694  context->cert->privateKeyLen, context->cert->password, &privateKey);
695 
696  //Check the length of the EdDSA private key
697  if(mpiGetByteLength(&privateKey.d) == ED25519_PRIVATE_KEY_LEN)
698  {
699  //Retrieve private key
700  error = mpiExport(&privateKey.d, d, ED25519_PRIVATE_KEY_LEN,
702 
703  //Check status code
704  if(!error)
705  {
706  //Generate Ed25519 signature (PureEdDSA mode)
707  error = ed25519GenerateSignatureEx(d, NULL, messageChunks, NULL, 0, 0,
708  signature);
709  }
710 
711  //Length of the resulting EdDSA signature
712  *signatureLen = ED25519_SIGNATURE_LEN;
713  }
714  else
715  {
716  //The length of the EdDSA private key is not valid
717  error = ERROR_INVALID_KEY;
718  }
719 
720  //Free previously allocated resources
721  eddsaFreePrivateKey(&privateKey);
722 
723  //Return status code
724  return error;
725 #else
726  //EdDSA signature algorithm is not supported
727  return ERROR_NOT_IMPLEMENTED;
728 #endif
729 }
730 
731 
732 /**
733  * @brief Generate Ed448 signature
734  * @param[in] context Pointer to the TLS context
735  * @param[in] messageChunks Collection of chunks representing the message to
736  * be signed
737  * @param[out] signature Resulting signature
738  * @param[out] signatureLen Length of the resulting signature
739  * @return Error code
740  **/
741 
743  const EddsaMessageChunk *messageChunks, uint8_t *signature,
744  size_t *signatureLen)
745 {
746 #if (TLS_ED448_SIGN_SUPPORT == ENABLED)
747  error_t error;
748  EddsaPrivateKey privateKey;
749  uint8_t d[ED448_PRIVATE_KEY_LEN];
750 
751  //Initialize EdDSA private key
752  eddsaInitPrivateKey(&privateKey);
753 
754  //Decode the PEM structure that holds the EdDSA private key
755  error = pemImportEddsaPrivateKey(context->cert->privateKey,
756  context->cert->privateKeyLen, context->cert->password, &privateKey);
757 
758  //Check the length of the EdDSA private key
759  if(mpiGetByteLength(&privateKey.d) == ED448_PRIVATE_KEY_LEN)
760  {
761  //Retrieve private key
762  error = mpiExport(&privateKey.d, d, ED448_PRIVATE_KEY_LEN,
764 
765  //Check status code
766  if(!error)
767  {
768  //Generate Ed448 signature (PureEdDSA mode)
769  error = ed448GenerateSignatureEx(d, NULL, messageChunks, NULL, 0, 0,
770  signature);
771  }
772 
773  //Length of the resulting EdDSA signature
774  *signatureLen = ED448_SIGNATURE_LEN;
775  }
776  else
777  {
778  //The length of the EdDSA private key is not valid
779  error = ERROR_INVALID_KEY;
780  }
781 
782  //Free previously allocated resources
783  eddsaFreePrivateKey(&privateKey);
784 
785  //Return status code
786  return error;
787 #else
788  //Ed448 signature algorithm is not supported
789  return ERROR_NOT_IMPLEMENTED;
790 #endif
791 }
792 
793 #endif
#define htons(value)
Definition: cpu_endian.h:413
Debugging facilities.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:110
uint8_t n
void dsaFreePrivateKey(DsaPrivateKey *key)
Release a DSA private key.
Definition: dsa.c:150
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:164
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:177
error_t dsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const DsaPrivateKey *key, const uint8_t *digest, size_t digestLen, DsaSignature *signature)
DSA signature generation.
Definition: dsa.c:484
void dsaInitPrivateKey(DsaPrivateKey *key)
Initialize a DSA private key.
Definition: dsa.c:133
error_t dsaWriteSignature(const DsaSignature *signature, uint8_t *data, size_t *length)
Encode DSA signature using ASN.1.
Definition: dsa.c:193
DSA (Digital Signature Algorithm)
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
void ecFreePrivateKey(EcPrivateKey *key)
Release an EdDSA private key.
Definition: ec.c:192
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:177
error_t ecdsaWriteSignature(const EcdsaSignature *signature, uint8_t *data, size_t *length)
Encode ECDSA signature using ASN.1.
Definition: ecdsa.c:98
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:82
__weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Definition: ecdsa.c:397
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:69
ECDSA (Elliptic Curve Digital Signature Algorithm)
error_t ed25519GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const EddsaMessageChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed25519.c:271
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
#define ED25519_PRIVATE_KEY_LEN
Definition: ed25519.h:40
error_t ed448GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const EddsaMessageChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:258
#define ED448_PRIVATE_KEY_LEN
Definition: ed448.h:40
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release an EdDSA private key.
Definition: eddsa.c:89
void eddsaInitPrivateKey(EddsaPrivateKey *key)
Initialize an EdDSA private key.
Definition: eddsa.c:73
EdDSA (Edwards-Curve Digital Signature Algorithm)
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_KEY
Definition: error.h:106
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
#define MD5_DIGEST_SIZE
Definition: md5.h:45
#define MD5_HASH_ALGO
Definition: md5.h:49
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:195
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:70
uint8_t s
Definition: ndp.h:345
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t pemImportEcPrivateKey(const char_t *input, size_t length, const char_t *password, EcPrivateKey *privateKey)
Decode a PEM file containing an EC private key.
Definition: pem_import.c:1163
error_t pemImportEcParameters(const char_t *input, size_t length, EcDomainParameters *params)
Decode a PEM file containing EC domain parameters.
Definition: pem_import.c:881
error_t pemImportEddsaPrivateKey(const char_t *input, size_t length, const char_t *password, EddsaPrivateKey *privateKey)
Decode a PEM file containing a EdDSA private key.
Definition: pem_import.c:1450
error_t pemImportDsaPrivateKey(const char_t *input, size_t length, const char_t *password, DsaPrivateKey *privateKey)
Decode a PEM file containing a DSA private key.
Definition: pem_import.c:676
error_t pemImportRsaPrivateKey(const char_t *input, size_t length, const char_t *password, RsaPrivateKey *privateKey)
Decode a PEM file containing an RSA private key.
Definition: pem_import.c:389
PEM file import functions.
void rsaFreePrivateKey(RsaPrivateKey *key)
Release an RSA private key.
Definition: rsa.c:153
error_t rsassaPssSign(const PrngAlgo *prngAlgo, void *prngContext, const RsaPrivateKey *key, const HashAlgo *hash, size_t saltLen, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
RSASSA-PSS signature generation operation.
Definition: rsa.c:959
error_t rsasp1(const RsaPrivateKey *key, const Mpi *m, Mpi *s)
RSA signature primitive.
Definition: rsa.c:1302
error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
RSASSA-PKCS1-v1_5 signature generation operation.
Definition: rsa.c:705
void rsaInitPrivateKey(RsaPrivateKey *key)
Initialize an RSA private key.
Definition: rsa.c:131
RSA public-key cryptography standard.
#define SHA1_HASH_ALGO
Definition: sha1.h:49
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
DSA private key.
Definition: dsa.h:72
DSA signature.
Definition: dsa.h:84
EC domain parameters.
Definition: ec.h:76
EC private key.
Definition: ec.h:104
ECDSA signature.
Definition: ecdsa.h:49
Message chunk descriptor.
Definition: eddsa.h:71
EdDSA private key.
Definition: eddsa.h:59
Mpi d
Private key.
Definition: eddsa.h:60
Common interface for hash algorithms.
Definition: crypto.h:1014
size_t digestSize
Definition: crypto.h:1020
Arbitrary precision integer.
Definition: mpi.h:80
RSA private key.
Definition: rsa.h:68
Mpi p
First factor.
Definition: rsa.h:72
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
Mpi e
Public exponent.
Definition: rsa.h:70
Mpi q
Second factor.
Definition: rsa.h:73
Mpi d
Private exponent.
Definition: rsa.h:71
Mpi dp
First factor's CRT exponent.
Definition: rsa.h:74
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi n
Modulus.
Definition: rsa.h:69
uint8_t length
Definition: tcp.h:368
TLS (Transport Layer Security)
Tls12DigitalSignature
Definition: tls.h:1712
TlsDigitalSignature
Definition: tls.h:1700
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256
Definition: tls.h:1239
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384
Definition: tls.h:1237
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512
Definition: tls.h:1238
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384
Definition: tls.h:1240
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512
Definition: tls.h:1241
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256
Definition: tls.h:1236
@ TLS_HASH_ALGO_SHA384
Definition: tls.h:1201
@ TLS_HASH_ALGO_SHA256
Definition: tls.h:1200
@ TLS_HASH_ALGO_SHA512
Definition: tls.h:1202
@ TLS_CERT_RSA_SIGN
Definition: tls.h:1171
@ TLS_CERT_DSS_SIGN
Definition: tls.h:1172
@ TLS_CERT_ECDSA_SIGN
Definition: tls.h:1178
@ TLS_SIGN_ALGO_ECDSA
Definition: tls.h:1217
@ TLS_SIGN_ALGO_RSA
Definition: tls.h:1215
@ TLS_SIGN_ALGO_DSA
Definition: tls.h:1216
#define TlsContext
Definition: tls.h:36
const HashAlgo * tlsGetHashAlgo(TlsHashAlgo hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1173
TLS helper functions.
error_t tlsGenerateSignature(TlsContext *context, uint8_t *p, size_t *length)
Digital signature generation (TLS 1.0 or TLS 1.1)
error_t tlsGenerateRsaPssSignature(TlsContext *context, const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
Generate RSA-PSS signature.
error_t tlsGenerateDsaSignature(TlsContext *context, const uint8_t *digest, size_t digestLen, uint8_t *signature, size_t *signatureLen)
Generate DSA signature.
error_t tlsGenerateEd448Signature(TlsContext *context, const EddsaMessageChunk *messageChunks, uint8_t *signature, size_t *signatureLen)
Generate Ed448 signature.
error_t tlsGenerateRsaPkcs1Signature(TlsContext *context, const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
Generate RSA signature (TLS 1.2)
error_t tls12GenerateSignature(TlsContext *context, uint8_t *p, size_t *length)
Digital signature generation (TLS 1.2)
error_t tlsGenerateEd25519Signature(TlsContext *context, const EddsaMessageChunk *messageChunks, uint8_t *signature, size_t *signatureLen)
Generate Ed25519 signature.
error_t tlsGenerateEcdsaSignature(TlsContext *context, const uint8_t *digest, size_t digestLen, uint8_t *signature, size_t *signatureLen)
Generate ECDSA signature.
error_t tlsGenerateRsaSignature(const RsaPrivateKey *key, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
Generate RSA signature (TLS 1.0 and TLS 1.1)
RSA/DSA/ECDSA/EdDSA signature generation.
Helper functions for signature generation and verification.
#define TLS_HASH_ALGO(signScheme)
Definition: tls_sign_misc.h:41
#define TLS_SIGN_ALGO(signScheme)
Definition: tls_sign_misc.h:38
error_t tlsFinalizeTranscriptHash(TlsContext *context, const HashAlgo *hash, const void *hashContext, const char_t *label, uint8_t *output)
Finalize hash calculation from previous handshake messages.
Transcript hash calculation.