tls13_sign_generate.c
Go to the documentation of this file.
1 /**
2  * @file tls13_sign_generate.c
3  * @brief RSA/DSA/ECDSA/SM2/EdDSA signature generation (TLS 1.3)
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 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.5.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_transcript_hash.h"
38 #include "tls_misc.h"
39 #include "tls13_sign_generate.h"
40 #include "pkix/pem_import.h"
41 #include "debug.h"
42 
43 //Check TLS library configuration
44 #if (TLS_SUPPORT == ENABLED && TLS_MAX_VERSION >= TLS_VERSION_1_3)
45 
46 
47 /**
48  * @brief Digital signature generation (TLS 1.3)
49  * @param[in] context Pointer to the TLS context
50  * @param[out] p Buffer where to store the digitally-signed element
51  * @param[out] length Length of the digitally-signed element
52  * @return Error code
53  **/
54 
56  size_t *length)
57 {
58  error_t error;
59  size_t n;
60  uint8_t *buffer;
61  Tls13DigitalSignature *signature;
62  const HashAlgo *hashAlgo;
63 
64  //Point to the digitally-signed element
65  signature = (Tls13DigitalSignature *) p;
66  //The algorithm field specifies the signature scheme
67  signature->algorithm = htons(context->signScheme);
68 
69  //The hash function used by HKDF is the cipher suite hash algorithm
70  hashAlgo = context->cipherSuite.prfHashAlgo;
71  //Make sure the hash algorithm is valid
72  if(hashAlgo == NULL)
73  return ERROR_FAILURE;
74 
75  //Calculate the length of the content covered by the digital signature
76  n = hashAlgo->digestSize + 98;
77 
78  //Allocate a memory buffer
79  buffer = tlsAllocMem(n);
80 
81  //Successful memory allocation?
82  if(buffer != NULL)
83  {
84  //Form a string that consists of octet 32 (0x20) repeated 64 times
85  osMemset(buffer, ' ', 64);
86 
87  //Append the context string. It is used to provide separation between
88  //signatures made in different contexts, helping against potential
89  //cross-protocol attacks
90  if(context->entity == TLS_CONNECTION_END_CLIENT)
91  {
92  osMemcpy(buffer + 64, "TLS 1.3, client CertificateVerify", 33);
93  }
94  else
95  {
96  osMemcpy(buffer + 64, "TLS 1.3, server CertificateVerify", 33);
97  }
98 
99  //Append a single 0 byte which serves as the separator
100  buffer[97] = 0x00;
101 
102  //Compute the transcript hash
103  error = tlsFinalizeTranscriptHash(context, hashAlgo,
104  context->transcriptHashContext, "", buffer + 98);
105 
106  //Check status code
107  if(!error)
108  {
109 #if (TLS_RSA_PSS_SIGN_SUPPORT == ENABLED)
110  //RSA-PSS signature scheme?
111  if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256 ||
112  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384 ||
113  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512 ||
114  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256 ||
115  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384 ||
116  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512)
117  {
118  //Generate an RSA-PSS signature
119  error = tls13GenerateRsaPssSignature(context, buffer, n, signature);
120  }
121  else
122 #endif
123 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
124  //ECDSA signature scheme?
125  if(context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP256R1_SHA256 ||
126  context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP384R1_SHA384 ||
127  context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP521R1_SHA512 ||
128  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP256R1_TLS13_SHA256 ||
129  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP384R1_TLS13_SHA384 ||
130  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP512R1_TLS13_SHA512)
131  {
132  //Generate an ECDSA signature
133  error = tls13GenerateEcdsaSignature(context, buffer, n, signature);
134  }
135  else
136 #endif
137 #if (TLS_SM2_SIGN_SUPPORT == ENABLED)
138  //SM2 signature scheme?
139  if(context->signScheme == TLS_SIGN_SCHEME_SM2SIG_SM3)
140  {
141  //Generate an SM2 signature
142  error = tls13GenerateSm2Signature(context, buffer, n, signature);
143  }
144  else
145 #endif
146 #if (TLS_ED25519_SIGN_SUPPORT == ENABLED)
147  //Ed25519 signature scheme?
148  if(context->signScheme == TLS_SIGN_SCHEME_ED25519)
149  {
150  //Generate an Ed25519 signature
151  error = tls13GenerateEd25519Signature(context, buffer, n, signature);
152  }
153  else
154 #endif
155 #if (TLS_ED448_SIGN_SUPPORT == ENABLED)
156  //Ed448 signature scheme?
157  if(context->signScheme == TLS_SIGN_SCHEME_ED448)
158  {
159  //Generate an Ed448 signature
160  error = tls13GenerateEd448Signature(context, buffer, n, signature);
161  }
162  else
163 #endif
164  //Invalid signature scheme?
165  {
166  //Report an error
168  }
169  }
170 
171  //Release memory buffer
172  tlsFreeMem(buffer);
173  }
174  else
175  {
176  //Failed to allocate memory
177  error = ERROR_OUT_OF_MEMORY;
178  }
179 
180  //Check status code
181  if(!error)
182  {
183  //Total length of the digitally-signed element
184  *length = sizeof(Tls13DigitalSignature) + ntohs(signature->length);
185  }
186 
187  //Return status code
188  return error;
189 }
190 
191 
192 /**
193  * @brief RSA-PSS signature generation (TLS 1.3)
194  * @param[in] context Pointer to the TLS context
195  * @param[in] message Pointer to the message to be signed
196  * @param[in] length Length of the message, in bytes
197  * @param[out] signature Buffer where to store the digital signature
198  * @return Error code
199  **/
200 
202  size_t length, Tls13DigitalSignature *signature)
203 {
204 #if (TLS_RSA_PSS_SIGN_SUPPORT == ENABLED)
205  error_t error;
206  size_t n;
207  const HashAlgo *hashAlgo;
208 
209  //Retrieve the hash algorithm used for signing
210  if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256 ||
211  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256)
212  {
213  //Select SHA-256 hash algorithm
215  }
216  else if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384 ||
217  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384)
218  {
219  //Select SHA-384 hash algorithm
221  }
222  else if(context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512 ||
223  context->signScheme == TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512)
224  {
225  //Select SHA-512 hash algorithm
227  }
228  else
229  {
230  //Invalid signature scheme
231  hashAlgo = NULL;
232  }
233 
234  //Pre-hash the content covered by the digital signature
235  if(hashAlgo != NULL)
236  {
237  error = hashAlgo->compute(message, length, context->clientVerifyData);
238  }
239  else
240  {
242  }
243 
244  //Check status code
245  if(!error)
246  {
247  //RSA signatures must use an RSASSA-PSS algorithm, regardless of whether
248  //RSASSA-PKCS1-v1_5 algorithms appear in SignatureAlgorithms
249  error = tlsGenerateRsaPssSignature(context, hashAlgo,
250  context->clientVerifyData, signature->value, &n);
251  }
252 
253  //Check status code
254  if(!error)
255  {
256  //The signature is preceded by a 2-byte length field
257  signature->length = htons(n);
258  }
259 
260  //Return status code
261  return error;
262 #else
263  //RSA-PSS signature algorithm not implemented
264  return ERROR_NOT_IMPLEMENTED;
265 #endif
266 }
267 
268 
269 /**
270  * @brief ECDSA signature generation (TLS 1.3)
271  * @param[in] context Pointer to the TLS context
272  * @param[in] message Pointer to the message to be signed
273  * @param[in] length Length of the message, in bytes
274  * @param[out] signature Buffer where to store the digital signature
275  * @return Error code
276  **/
277 
279  size_t length, Tls13DigitalSignature *signature)
280 {
281 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
282  error_t error;
283  size_t n;
284  const HashAlgo *hashAlgo;
285 
286  //Retrieve the hash algorithm used for signing
287  if(context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP256R1_SHA256 ||
288  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP256R1_TLS13_SHA256)
289  {
290  //Select SHA-256 hash algorithm
292  }
293  else if(context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP384R1_SHA384 ||
294  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP384R1_TLS13_SHA384)
295  {
296  //Select SHA-384 hash algorithm
298  }
299  else if(context->signScheme == TLS_SIGN_SCHEME_ECDSA_SECP521R1_SHA512 ||
300  context->signScheme == TLS_SIGN_SCHEME_ECDSA_BP512R1_TLS13_SHA512)
301  {
302  //Select SHA-512 hash algorithm
304  }
305  else
306  {
307  //Invalid signature scheme
308  hashAlgo = NULL;
309  }
310 
311  //Pre-hash the content covered by the digital signature
312  if(hashAlgo != NULL)
313  {
314  error = hashAlgo->compute(message, length, context->clientVerifyData);
315  }
316  else
317  {
319  }
320 
321  //Check status code
322  if(!error)
323  {
324  //Generate an ECDSA signature
325  error = tlsGenerateEcdsaSignature(context, context->clientVerifyData,
326  hashAlgo->digestSize, signature->value, &n);
327  }
328 
329  //Check status code
330  if(!error)
331  {
332  //The signature is preceded by a 2-byte length field
333  signature->length = htons(n);
334  }
335 
336  //Return status code
337  return error;
338 #else
339  //ECDSA signature algorithm not implemented
340  return ERROR_NOT_IMPLEMENTED;
341 #endif
342 }
343 
344 
345 /**
346  * @brief SM2 signature generation (TLS 1.3)
347  * @param[in] context Pointer to the TLS context
348  * @param[in] message Pointer to the message to be signed
349  * @param[in] length Length of the message, in bytes
350  * @param[out] signature Buffer where to store the digital signature
351  * @return Error code
352  **/
353 
355  size_t length, Tls13DigitalSignature *signature)
356 {
357 #if (TLS_SM2_SIGN_SUPPORT == ENABLED)
358  error_t error;
359  size_t n;
360  EcPrivateKey privateKey;
361  EcdsaSignature sm2Signature;
362 
363  //Initialize EC private key
364  ecInitPrivateKey(&privateKey);
365  //Initialize SM2 signature
366  ecdsaInitSignature(&sm2Signature);
367 
368  //Decode the PEM structure that holds the EC private key
369  error = pemImportEcPrivateKey(&privateKey, context->cert->privateKey,
370  context->cert->privateKeyLen, context->cert->password);
371 
372  //Check status code
373  if(!error)
374  {
375  //Generate SM2 signature
376  error = sm2GenerateSignature(context->prngAlgo, context->prngContext,
378  message, length, &sm2Signature);
379  }
380 
381  //Check status code
382  if(!error)
383  {
384  //Encode the resulting (R, S) integer pair using ASN.1
385  error = ecdsaExportSignature(&sm2Signature, signature->value, &n,
387  }
388 
389  //Check status code
390  if(!error)
391  {
392  //The signature is preceded by a 2-byte length field
393  signature->length = htons(n);
394  }
395 
396  //Release previously allocated resources
397  ecFreePrivateKey(&privateKey);
398  ecdsaFreeSignature(&sm2Signature);
399 
400  //Return status code
401  return error;
402 #else
403  //SM2 signature algorithm not implemented
404  return ERROR_NOT_IMPLEMENTED;
405 #endif
406 }
407 
408 
409 /**
410  * @brief Ed25519 signature generation (TLS 1.3)
411  * @param[in] context Pointer to the TLS context
412  * @param[in] message Pointer to the message to be signed
413  * @param[in] length Length of the message, in bytes
414  * @param[out] signature Buffer where to store the digital signature
415  * @return Error code
416  **/
417 
419  size_t length, Tls13DigitalSignature *signature)
420 {
421 #if (TLS_ED25519_SIGN_SUPPORT == ENABLED)
422  error_t error;
423  size_t n;
424  DataChunk messageChunks[1];
425 
426  //Data to be signed is run through the EdDSA algorithm without pre-hashing
427  messageChunks[0].buffer = message;
428  messageChunks[0].length = length;
429 
430  //Generate Ed25519 signature in PureEdDSA mode
431  error = tlsGenerateEd25519Signature(context, messageChunks,
432  arraysize(messageChunks), signature->value, &n);
433 
434  //Check status code
435  if(!error)
436  {
437  //The signature is preceded by a 2-byte length field
438  signature->length = htons(n);
439  }
440 
441  //Return status code
442  return error;
443 #else
444  //Ed25519 signature algorithm not implemented
445  return ERROR_NOT_IMPLEMENTED;
446 #endif
447 }
448 
449 
450 /**
451  * @brief Ed448 signature generation (TLS 1.3)
452  * @param[in] context Pointer to the TLS context
453  * @param[in] message Pointer to the message to be signed
454  * @param[in] length Length of the message, in bytes
455  * @param[out] signature Buffer where to store the digital signature
456  * @return Error code
457  **/
458 
460  size_t length, Tls13DigitalSignature *signature)
461 {
462 #if (TLS_ED448_SIGN_SUPPORT == ENABLED)
463  error_t error;
464  size_t n;
465  DataChunk messageChunks[1];
466 
467  //Data to be signed is run through the EdDSA algorithm without pre-hashing
468  messageChunks[0].buffer = message;
469  messageChunks[0].length = length;
470 
471  //Generate Ed448 signature in PureEdDSA mode
472  error = tlsGenerateEd448Signature(context, messageChunks,
473  arraysize(messageChunks), signature->value, &n);
474 
475  //Check status code
476  if(!error)
477  {
478  //The signature is preceded by a 2-byte length field
479  signature->length = htons(n);
480  }
481 
482  //Return status code
483  return error;
484 #else
485  //Ed448 signature algorithm not implemented
486  return ERROR_NOT_IMPLEMENTED;
487 #endif
488 }
489 
490 #endif
#define tlsAllocMem(size)
Definition: tls.h:867
#define htons(value)
Definition: cpu_endian.h:413
ECDSA signature.
Definition: ecdsa.h:63
TLS helper functions.
@ TLS_SIGN_SCHEME_ECDSA_BP256R1_TLS13_SHA256
Definition: tls.h:1287
const HashAlgo * tlsGetHashAlgo(TlsHashAlgo hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1184
error_t tls13GenerateEd448Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
Ed448 signature generation (TLS 1.3)
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256
Definition: tls.h:1277
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
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.
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
size_t digestSize
Definition: crypto.h:1088
const void * buffer
Definition: crypto.h:1018
error_t sm2GenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const HashAlgo *hashAlgo, const char_t *id, size_t idLen, const void *message, size_t messageLen, EcdsaSignature *signature)
SM2 signature generation.
Definition: sm2.c:62
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512
Definition: tls.h:1282
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define SM3_HASH_ALGO
Definition: sm3.h:49
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA512
Definition: tls.h:1279
@ TLS_SIGN_SCHEME_ED25519
Definition: tls.h:1291
#define osStrlen(s)
Definition: os_port.h:168
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384
Definition: tls.h:1281
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA384
Definition: tls.h:1278
error_t ecdsaExportSignature(const EcdsaSignature *signature, uint8_t *data, size_t *length, EcdsaSignatureFormat format)
Export an ECDSA signature.
Definition: ecdsa.c:272
error_t tlsGenerateEcdsaSignature(TlsContext *context, const uint8_t *digest, size_t digestLen, uint8_t *signature, size_t *signatureLen)
Generate ECDSA signature.
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:86
@ TLS_HASH_ALGO_SHA512
Definition: tls.h:1243
PEM file import functions.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256
Definition: tls.h:1280
@ TLS_SIGN_SCHEME_ECDSA_SECP521R1_SHA512
Definition: tls.h:1286
HashAlgoCompute compute
Definition: crypto.h:1091
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:73
@ TLS_HASH_ALGO_SHA384
Definition: tls.h:1242
error_t pemImportEcPrivateKey(EcPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode a PEM file containing an EC private key.
Definition: pem_import.c:945
error_t tls13GenerateEcdsaSignature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
ECDSA signature generation (TLS 1.3)
@ TLS_SIGN_SCHEME_ECDSA_BP512R1_TLS13_SHA512
Definition: tls.h:1289
EC private key.
Definition: ec.h:432
@ TLS_HASH_ALGO_SHA256
Definition: tls.h:1241
error_t tls13GenerateSignature(TlsContext *context, uint8_t *p, size_t *length)
Digital signature generation (TLS 1.3)
void ecFreePrivateKey(EcPrivateKey *key)
Release an EC private key.
Definition: ec.c:100
uint8_t length
Definition: tcp.h:375
Transcript hash calculation.
RSA/DSA/ECDSA/SM2/EdDSA signature generation (TLS 1.3)
Data chunk descriptor.
Definition: crypto.h:1017
#define ntohs(value)
Definition: cpu_endian.h:421
#define SM2_TLS13_ID
Definition: sm2.h:41
@ ECDSA_SIGNATURE_FORMAT_ASN1
Definition: ecdsa.h:51
uint8_t n
@ TLS_SIGN_SCHEME_SM2SIG_SM3
Definition: tls.h:1290
@ TLS_SIGN_SCHEME_ECDSA_BP384R1_TLS13_SHA384
Definition: tls.h:1288
@ TLS_SIGN_SCHEME_ED448
Definition: tls.h:1292
@ TLS_SIGN_SCHEME_ECDSA_SECP384R1_SHA384
Definition: tls.h:1285
Tls13DigitalSignature
Definition: tls13_misc.h:298
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:80
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:990
TLS (Transport Layer Security)
error_t tls13GenerateEd25519Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
Ed25519 signature generation (TLS 1.3)
error_t tlsGenerateEd25519Signature(TlsContext *context, const DataChunk *message, uint_t messageLen, uint8_t *signature, size_t *signatureLen)
Generate Ed25519 signature.
size_t length
Definition: crypto.h:1019
Common interface for hash algorithms.
Definition: crypto.h:1082
error_t tls13GenerateSm2Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
SM2 signature generation (TLS 1.3)
@ TLS_SIGN_SCHEME_ECDSA_SECP256R1_SHA256
Definition: tls.h:1284
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
#define osMemset(p, value, length)
Definition: os_port.h:138
#define tlsFreeMem(p)
Definition: tls.h:872
error_t tls13GenerateRsaPssSignature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
RSA-PSS signature generation (TLS 1.3)
error_t tlsGenerateEd448Signature(TlsContext *context, const DataChunk *message, uint_t messageLen, uint8_t *signature, size_t *signatureLen)
Generate Ed448 signature.
error_t tlsGenerateRsaPssSignature(TlsContext *context, const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
Generate RSA-PSS signature.
RSA/DSA/ECDSA/EdDSA signature generation.
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71