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-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_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  EcDomainParameters params;
361  EcPrivateKey privateKey;
362  EcdsaSignature sm2Signature;
363 
364  //Initialize EC domain parameters
365  ecInitDomainParameters(&params);
366  //Initialize EC private key
367  ecInitPrivateKey(&privateKey);
368  //Initialize SM2 signature
369  ecdsaInitSignature(&sm2Signature);
370 
371  //Decode the PEM structure that holds the EC domain parameters
372  error = pemImportEcParameters(context->cert->privateKey,
373  context->cert->privateKeyLen, &params);
374 
375  //Check status code
376  if(!error)
377  {
378  //Decode the PEM structure that holds the EC private key
379  error = pemImportEcPrivateKey(context->cert->privateKey,
380  context->cert->privateKeyLen, context->cert->password, &privateKey);
381  }
382 
383  //Check status code
384  if(!error)
385  {
386  //Generate SM2 signature
387  error = sm2GenerateSignature(context->prngAlgo, context->prngContext,
388  &params, &privateKey, SM3_HASH_ALGO, SM2_TLS13_ID,
389  osStrlen(SM2_TLS13_ID), message, length, &sm2Signature);
390  }
391 
392  //Check status code
393  if(!error)
394  {
395  //Encode the resulting (R, S) integer pair using ASN.1
396  error = ecdsaWriteSignature(&sm2Signature, signature->value, &n);
397  }
398 
399  //Check status code
400  if(!error)
401  {
402  //The signature is preceded by a 2-byte length field
403  signature->length = htons(n);
404  }
405 
406  //Release previously allocated resources
407  ecdsaFreeSignature(&sm2Signature);
408 
409  //Return status code
410  return error;
411 #else
412  //SM2 signature algorithm not implemented
413  return ERROR_NOT_IMPLEMENTED;
414 #endif
415 }
416 
417 
418 /**
419  * @brief Ed25519 signature generation (TLS 1.3)
420  * @param[in] context Pointer to the TLS context
421  * @param[in] message Pointer to the message to be signed
422  * @param[in] length Length of the message, in bytes
423  * @param[out] signature Buffer where to store the digital signature
424  * @return Error code
425  **/
426 
428  size_t length, Tls13DigitalSignature *signature)
429 {
430 #if (TLS_ED25519_SIGN_SUPPORT == ENABLED)
431  error_t error;
432  size_t n;
433  EddsaMessageChunk messageChunks[2];
434 
435  //Data to be signed is run through the EdDSA algorithm without pre-hashing
436  messageChunks[0].buffer = message;
437  messageChunks[0].length = length;
438  messageChunks[1].buffer = NULL;
439  messageChunks[1].length = 0;
440 
441  //Generate Ed25519 signature in PureEdDSA mode
442  error = tlsGenerateEd25519Signature(context, messageChunks,
443  signature->value, &n);
444 
445  //Check status code
446  if(!error)
447  {
448  //The signature is preceded by a 2-byte length field
449  signature->length = htons(n);
450  }
451 
452  //Return status code
453  return error;
454 #else
455  //Ed25519 signature algorithm not implemented
456  return ERROR_NOT_IMPLEMENTED;
457 #endif
458 }
459 
460 
461 /**
462  * @brief Ed448 signature generation (TLS 1.3)
463  * @param[in] context Pointer to the TLS context
464  * @param[in] message Pointer to the message to be signed
465  * @param[in] length Length of the message, in bytes
466  * @param[out] signature Buffer where to store the digital signature
467  * @return Error code
468  **/
469 
471  size_t length, Tls13DigitalSignature *signature)
472 {
473 #if (TLS_ED448_SIGN_SUPPORT == ENABLED)
474  error_t error;
475  size_t n;
476  EddsaMessageChunk messageChunks[2];
477 
478  //Data to be signed is run through the EdDSA algorithm without pre-hashing
479  messageChunks[0].buffer = message;
480  messageChunks[0].length = length;
481  messageChunks[1].buffer = NULL;
482  messageChunks[1].length = 0;
483 
484  //Generate Ed448 signature in PureEdDSA mode
485  error = tlsGenerateEd448Signature(context, messageChunks,
486  signature->value, &n);
487 
488  //Check status code
489  if(!error)
490  {
491  //The signature is preceded by a 2-byte length field
492  signature->length = htons(n);
493  }
494 
495  //Return status code
496  return error;
497 #else
498  //Ed448 signature algorithm not implemented
499  return ERROR_NOT_IMPLEMENTED;
500 #endif
501 }
502 
503 #endif
uint8_t message[]
Definition: chap.h:154
#define htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
uint8_t n
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
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
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:69
error_t
Error codes.
Definition: error.h:43
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
uint8_t p
Definition: ndp.h:300
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define osStrlen(s)
Definition: os_port.h:165
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
PEM file import functions.
error_t sm2GenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, 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
#define SM2_TLS13_ID
Definition: sm2.h:40
#define SM3_HASH_ALGO
Definition: sm3.h:49
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
const void * buffer
Definition: eddsa.h:72
size_t length
Definition: eddsa.h:73
Common interface for hash algorithms.
Definition: crypto.h:1014
HashAlgoCompute compute
Definition: crypto.h:1023
size_t digestSize
Definition: crypto.h:1020
uint8_t length
Definition: tcp.h:368
Tls13DigitalSignature
Definition: tls13_misc.h:270
error_t tls13GenerateRsaPssSignature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
RSA-PSS signature generation (TLS 1.3)
error_t tls13GenerateEd25519Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
Ed25519 signature generation (TLS 1.3)
error_t tls13GenerateSignature(TlsContext *context, uint8_t *p, size_t *length)
Digital signature generation (TLS 1.3)
error_t tls13GenerateSm2Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
SM2 signature generation (TLS 1.3)
error_t tls13GenerateEcdsaSignature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
ECDSA signature generation (TLS 1.3)
error_t tls13GenerateEd448Signature(TlsContext *context, const uint8_t *message, size_t length, Tls13DigitalSignature *signature)
Ed448 signature generation (TLS 1.3)
RSA/DSA/ECDSA/SM2/EdDSA signature generation (TLS 1.3)
TLS (Transport Layer Security)
#define tlsAllocMem(size)
Definition: tls.h:846
#define tlsFreeMem(p)
Definition: tls.h:851
@ TLS_SIGN_SCHEME_ECDSA_BP384R1_TLS13_SHA384
Definition: tls.h:1247
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA256
Definition: tls.h:1239
@ TLS_SIGN_SCHEME_ECDSA_SECP521R1_SHA512
Definition: tls.h:1245
@ TLS_SIGN_SCHEME_ECDSA_SECP384R1_SHA384
Definition: tls.h:1244
@ TLS_SIGN_SCHEME_ECDSA_BP256R1_TLS13_SHA256
Definition: tls.h:1246
@ 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_ECDSA_SECP256R1_SHA256
Definition: tls.h:1243
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA384
Definition: tls.h:1240
@ TLS_SIGN_SCHEME_SM2SIG_SM3
Definition: tls.h:1249
@ TLS_SIGN_SCHEME_ED25519
Definition: tls.h:1250
@ TLS_SIGN_SCHEME_ED448
Definition: tls.h:1251
@ TLS_SIGN_SCHEME_RSA_PSS_PSS_SHA512
Definition: tls.h:1241
@ TLS_SIGN_SCHEME_RSA_PSS_RSAE_SHA256
Definition: tls.h:1236
@ TLS_SIGN_SCHEME_ECDSA_BP512R1_TLS13_SHA512
Definition: tls.h:1248
@ TLS_HASH_ALGO_SHA384
Definition: tls.h:1201
@ TLS_HASH_ALGO_SHA256
Definition: tls.h:1200
@ TLS_HASH_ALGO_SHA512
Definition: tls.h:1202
#define TlsContext
Definition: tls.h:36
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:953
const HashAlgo * tlsGetHashAlgo(TlsHashAlgo hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1173
TLS helper functions.
error_t tlsGenerateRsaPssSignature(TlsContext *context, const HashAlgo *hashAlgo, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
Generate RSA-PSS signature.
error_t tlsGenerateEd448Signature(TlsContext *context, const EddsaMessageChunk *messageChunks, uint8_t *signature, size_t *signatureLen)
Generate Ed448 signature.
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.
RSA/DSA/ECDSA/EdDSA signature generation.
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.