x509_key_format.c
Go to the documentation of this file.
1 /**
2  * @file x509_key_format.c
3  * @brief Formatting of ASN.1 encoded keys
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/x509_key_format.h"
37 #include "encoding/asn1.h"
38 #include "encoding/oid.h"
39 #include "ecc/eddsa.h"
40 #include "hash/sha1.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (X509_SUPPORT == ENABLED || PEM_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Format SubjectPublicKeyInfo structure
49  * @param[in] publicKeyInfo Subject's public key information
50  * @param[in] publicKey Pointer to the public key (RSA, DSA, ECDSA or EdDSA)
51  * @param[out] keyId Subject's key identifier (optional parameter)
52  * @param[out] output Buffer where to format the ASN.1 structure
53  * @param[out] written Length of the resulting ASN.1 structure
54  * @return Error code
55  **/
56 
58  const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
59 {
60  error_t error;
61  size_t n;
62  size_t length;
63  uint8_t *p;
64  Asn1Tag tag;
65 
66  //Point to the buffer where to write the ASN.1 structure
67  p = output;
68  //Length of the ASN.1 structure
69  length = 0;
70 
71 #if (DSA_SUPPORT == ENABLED)
72  //Valid DSA public key?
73  if(publicKey != NULL && OID_COMP(publicKeyInfo->oid.value,
74  publicKeyInfo->oid.length, DSA_OID) == 0)
75  {
76  const DsaPublicKey *dsaPublicKey;
77 
78  //Point to the DSA public key
79  dsaPublicKey = (DsaPublicKey *) publicKey;
80 
81  //Format AlgorithmIdentifier field
82  error = x509FormatAlgoId(publicKeyInfo, &dsaPublicKey->params, p, &n);
83  }
84  else
85 #endif
86  {
87  //Format AlgorithmIdentifier field
88  error = x509FormatAlgoId(publicKeyInfo, NULL, p, &n);
89  }
90 
91  //Any error to report?
92  if(error)
93  return error;
94 
95  //Advance data pointer
97  length += n;
98 
99  //Format SubjectPublicKey field
100  error = x509FormatSubjectPublicKey(publicKeyInfo, publicKey, keyId, p, &n);
101  //Any error to report?
102  if(error)
103  return error;
104 
105  //Advance data pointer
106  ASN1_INC_POINTER(p, n);
107  length += n;
108 
109  //The SubjectPublicKeyInfo structure is encapsulated within a sequence
110  tag.constructed = TRUE;
113  tag.length = length;
114 
115  //Write the corresponding ASN.1 tag
116  error = asn1InsertHeader(&tag, output, &n);
117  //Any error to report?
118  if(error)
119  return error;
120 
121  //Total number of bytes that have been written
122  *written = length + n;
123 
124  //Successful processing
125  return NO_ERROR;
126 }
127 
128 
129 /**
130  * @brief Format AlgorithmIdentifier structure
131  * @param[in] publicKeyInfo Subject's public key information
132  * @param[in] params Pointer to the domain parameters (DSA or ECDSA)
133  * @param[out] output Buffer where to format the ASN.1 structure
134  * @param[out] written Length of the resulting ASN.1 structure
135  * @return Error code
136  **/
137 
139  const void *params, uint8_t *output, size_t *written)
140 {
141  error_t error;
142  size_t n;
143  size_t length;
144  uint8_t *p;
145  size_t oidLen;
146  const uint8_t *oid;
147  Asn1Tag tag;
148 
149  //Get the public key identifier
150  oid = publicKeyInfo->oid.value;
151  oidLen = publicKeyInfo->oid.length;
152 
153  //Point to the buffer where to write the ASN.1 structure
154  p = output;
155  //Length of the ASN.1 structure
156  length = 0;
157 
158  //Format algorithm OID
159  tag.constructed = FALSE;
162  tag.length = oidLen;
163  tag.value = oid;
164 
165  //Write the corresponding ASN.1 tag
166  error = asn1WriteTag(&tag, FALSE, p, &n);
167  //Any error to report?
168  if(error)
169  return error;
170 
171  //Advance data pointer
172  ASN1_INC_POINTER(p, n);
173  length += n;
174 
175 #if (RSA_SUPPORT == ENABLED)
176  //RSA algorithm identifier?
178  {
179  //The parameters field must have ASN.1 type NULL for this algorithm
180  //identifier (refer to RFC 3279, section 2.3.1)
181  tag.constructed = FALSE;
183  tag.objType = ASN1_TYPE_NULL;
184  tag.length = 0;
185  tag.value = NULL;
186 
187  //Write the corresponding ASN.1 tag
188  error = asn1WriteTag(&tag, FALSE, p, &n);
189  }
190  //RSA-PSS algorithm identifier?
191  else if(OID_COMP(oid, oidLen, RSASSA_PSS_OID) == 0)
192  {
193  //The parameters may be either absent or present when used as subject
194  //public key information (refer to RFC 4055, section 3.1)
195  n = 0;
196  }
197  else
198 #endif
199 #if (DSA_SUPPORT == ENABLED)
200  //DSA algorithm identifier?
201  if(OID_COMP(oid, oidLen, DSA_OID) == 0)
202  {
203  //Valid DSA domain parameters?
204  if(params != NULL)
205  {
206  //Export the DSA domain parameters to ASN.1 format
207  error = x509ExportDsaParameters(params, p, &n);
208  }
209  else
210  {
211  //Format DSAParameters structure
212  error = x509FormatDsaParameters(&publicKeyInfo->dsaParams, p, &n);
213  }
214  }
215  else
216 #endif
217 #if (EC_SUPPORT == ENABLED)
218  //EC public key identifier?
220  {
221  //Format ECParameters structure
222  error = x509FormatEcParameters(&publicKeyInfo->ecParams, p, &n);
223  }
224  else
225 #endif
226 #if (ED25519_SUPPORT == ENABLED)
227  //X25519 or Ed25519 algorithm identifier?
228  if(OID_COMP(oid, oidLen, X25519_OID) == 0 ||
229  OID_COMP(oid, oidLen, ED25519_OID) == 0)
230  {
231  //For all of the OIDs, the parameters must be absent (refer to RFC 8410,
232  //section 3)
233  n = 0;
234  }
235  else
236 #endif
237 #if (ED448_SUPPORT == ENABLED)
238  //X448 or Ed448 algorithm identifier?
239  if(OID_COMP(oid, oidLen, X448_OID) == 0 ||
240  OID_COMP(oid, oidLen, ED448_OID) == 0)
241  {
242  //For all of the OIDs, the parameters must be absent (refer to RFC 8410,
243  //section 3)
244  n = 0;
245  }
246  else
247 #endif
248  //Unknown algorithm identifier?
249  {
250  //Report an error
251  error = ERROR_INVALID_PARAMETER;
252  }
253 
254  //Any error to report?
255  if(error)
256  return error;
257 
258  //Advance data pointer
259  ASN1_INC_POINTER(p, n);
260  length += n;
261 
262  //The AlgorithmIdentifier structure is encapsulated within a sequence
263  tag.constructed = TRUE;
266  tag.length = length;
267 
268  //Write the corresponding ASN.1 tag
269  error = asn1InsertHeader(&tag, output, &n);
270  //Any error to report?
271  if(error)
272  return error;
273 
274  //Total number of bytes that have been written
275  *written = length + n;
276 
277  //Successful processing
278  return NO_ERROR;
279 }
280 
281 
282 /**
283  * @brief Format SubjectPublicKey structure
284  * @param[in] publicKeyInfo Subject's public key information
285  * @param[in] publicKey Pointer to the public key (RSA, DSA, ECDSA or EdDSA)
286  * @param[out] keyId Subject's key identifier (optional parameter)
287  * @param[out] output Buffer where to format the ASN.1 structure
288  * @param[out] written Length of the resulting ASN.1 structure
289  * @return Error code
290  **/
291 
293  const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
294 {
295  error_t error;
296  size_t n;
297  uint8_t *p;
298  size_t oidLen;
299  const uint8_t *oid;
300  Asn1Tag tag;
301 
302  //Get the public key identifier
303  oid = publicKeyInfo->oid.value;
304  oidLen = publicKeyInfo->oid.length;
305 
306  //Point to the buffer where to write the ASN.1 structure
307  p = output;
308 
309  //If the output parameter is NULL, then the function calculates the length
310  //of the ASN.1 structure without copying any data
311  if(p != NULL)
312  {
313  //The bit string shall contain an initial octet which encodes the number
314  //of unused bits in the final subsequent octet
315  p[0] = 0;
316 
317  //Advance data pointer
318  p++;
319  }
320 
321 #if (RSA_SUPPORT == ENABLED)
322  //RSA or RSA-PSS algorithm identifier?
323  if(OID_COMP(oid, oidLen, RSA_ENCRYPTION_OID) == 0 ||
325  {
326  //Valid RSA public key?
327  if(publicKey != NULL)
328  {
329  //Export the RSA public key to ASN.1 format
330  error = x509ExportRsaPublicKey(publicKey, p, &n);
331  }
332  else
333  {
334  //Format RSAPublicKey structure
335  error = x509FormatRsaPublicKey(&publicKeyInfo->rsaPublicKey, p, &n);
336  }
337  }
338  else
339 #endif
340 #if (DSA_SUPPORT == ENABLED)
341  //DSA algorithm identifier?
342  if(OID_COMP(oid, oidLen, DSA_OID) == 0)
343  {
344  //Valid DSA public key?
345  if(publicKey != NULL)
346  {
347  //Export the DSA public key to ASN.1 format
348  error = x509ExportDsaPublicKey(publicKey, p, &n);
349  }
350  else
351  {
352  //Format DSAPublicKey structure
353  error = x509FormatDsaPublicKey(&publicKeyInfo->dsaPublicKey, p, &n);
354  }
355  }
356  else
357 #endif
358 #if (EC_SUPPORT == ENABLED)
359  //EC public key identifier?
361  {
362  //Valid EC public key?
363  if(publicKey != NULL)
364  {
365  //Export the EC public key
366  error = ecExportPublicKey(publicKey, p, &n, EC_PUBLIC_KEY_FORMAT_X963);
367  }
368  else
369  {
370  //Format ECPublicKey structure
371  error = x509FormatEcPublicKey(&publicKeyInfo->ecPublicKey, p, &n);
372  }
373  }
374  else
375 #endif
376 #if (ED25519_SUPPORT == ENABLED)
377  //Ed25519 algorithm identifier?
378  if(OID_COMP(oid, oidLen, ED25519_OID) == 0)
379  {
380  //Valid EdDSA public key?
381  if(publicKey != NULL)
382  {
383  //Export the EdDSA public key
384  error = eddsaExportPublicKey(publicKey, p, &n);
385  }
386  else
387  {
388  //The SubjectPublicKey contains the byte stream of the public key
389  error = x509FormatEcPublicKey(&publicKeyInfo->ecPublicKey, p, &n);
390  }
391  }
392  else
393 #endif
394 #if (ED448_SUPPORT == ENABLED)
395  //Ed448 algorithm identifier?
396  if(OID_COMP(oid, oidLen, ED448_OID) == 0)
397  {
398  //Valid EdDSA public key?
399  if(publicKey != NULL)
400  {
401  //Export the EdDSA public key
402  error = eddsaExportPublicKey(publicKey, p, &n);
403  }
404  else
405  {
406  //The SubjectPublicKey contains the byte stream of the public key
407  error = x509FormatEcPublicKey(&publicKeyInfo->ecPublicKey, p, &n);
408  }
409  }
410  else
411 #endif
412  //Unknown algorithm identifier?
413  {
414  //Report an error
415  error = ERROR_INVALID_PARAMETER;
416  }
417 
418  //Any error to report?
419  if(error)
420  return error;
421 
422  //The keyIdentifier parameter is optional
423  if(keyId != NULL && p != NULL)
424  {
425  //The keyIdentifier is composed of the 160-bit SHA-1 hash of the value
426  //of the bit string subjectPublicKey (excluding the tag, length, and
427  //number of unused bits)
428  error = sha1Compute(p, n, keyId);
429  //Any error to report?
430  if(error)
431  return error;
432  }
433 
434  //The public key is encapsulated within a bit string
435  tag.constructed = FALSE;
438  tag.length = n + 1;
439 
440  //Write the corresponding ASN.1 tag
441  error = asn1InsertHeader(&tag, output, &n);
442  //Any error to report?
443  if(error)
444  return error;
445 
446  //Total number of bytes that have been written
447  *written = tag.totalLength;;
448 
449  //Successful processing
450  return NO_ERROR;
451 }
452 
453 
454 /**
455  * @brief Format RSAPublicKey structure
456  * @param[in] rsaPublicKey Pointer to the RSA public key
457  * @param[out] output Buffer where to format the ASN.1 structure
458  * @param[out] written Length of the resulting ASN.1 structure
459  * @return Error code
460  **/
461 
463  uint8_t *output, size_t *written)
464 {
465  error_t error;
466  size_t n;
467  size_t length;
468  uint8_t *p;
469  Asn1Tag tag;
470 
471  //Point to the buffer where to write the ASN.1 structure
472  p = output;
473  //Length of the ASN.1 structure
474  length = 0;
475 
476  //Write Modulus field
477  tag.constructed = FALSE;
480  tag.length = rsaPublicKey->n.length;
481  tag.value = rsaPublicKey->n.value;
482 
483  //Write the corresponding ASN.1 tag
484  error = asn1WriteTag(&tag, FALSE, p, &n);
485  //Any error to report?
486  if(error)
487  return error;
488 
489  //Advance data pointer
490  ASN1_INC_POINTER(p, n);
491  length += n;
492 
493  //Write PublicExponent field
494  tag.constructed = FALSE;
497  tag.length = rsaPublicKey->e.length;
498  tag.value = rsaPublicKey->e.value;
499 
500  //Write the corresponding ASN.1 tag
501  error = asn1WriteTag(&tag, FALSE, p, &n);
502  //Any error to report?
503  if(error)
504  return error;
505 
506  //Advance data pointer
507  ASN1_INC_POINTER(p, n);
508  length += n;
509 
510  //The public key is encapsulated within a sequence
511  tag.constructed = TRUE;
514  tag.length = length;
515 
516  //Write RSAPublicKey structure
517  error = asn1InsertHeader(&tag, output, &n);
518  //Any error to report?
519  if(error)
520  return error;
521 
522  //Total number of bytes that have been written
523  *written = tag.totalLength;;
524 
525  //Successful processing
526  return NO_ERROR;
527 }
528 
529 
530 /**
531  * @brief Format DSAPublicKey structure
532  * @param[in] dsaPublicKey Pointer to the DSA public key
533  * @param[out] output Buffer where to format the DSAPublicKey structure
534  * @param[out] written Length of the DSAPublicKey structure
535  * @return Error code
536  **/
537 
539  uint8_t *output, size_t *written)
540 {
541  error_t error;
542  size_t n;
543  Asn1Tag tag;
544 
545  //Write public key
546  tag.constructed = FALSE;
549  tag.length = dsaPublicKey->y.length;
550  tag.value = dsaPublicKey->y.value;
551 
552  //Write the corresponding ASN.1 tag
553  error = asn1WriteTag(&tag, FALSE, output, &n);
554  //Any error to report?
555  if(error)
556  return error;
557 
558  //Total number of bytes that have been written
559  *written = n;
560 
561  //Successful processing
562  return NO_ERROR;
563 }
564 
565 
566 /**
567  * @brief Format DSA domain parameters
568  * @param[in] dsaParams Pointer to the DSA domain parameters
569  * @param[out] output Buffer where to format the ASN.1 structure
570  * @param[out] written Length of the resulting ASN.1 structure
571  * @return Error code
572  **/
573 
575  uint8_t *output, size_t *written)
576 {
577  error_t error;
578  size_t n;
579  size_t length;
580  uint8_t *p;
581  Asn1Tag tag;
582 
583  //Point to the buffer where to write the ASN.1 structure
584  p = output;
585  //Length of the ASN.1 structure
586  length = 0;
587 
588  //Write parameter p
589  tag.constructed = FALSE;
592  tag.length = dsaParams->p.length;
593  tag.value = dsaParams->p.value;
594 
595  //Write the corresponding ASN.1 tag
596  error = asn1WriteTag(&tag, FALSE, p, &n);
597  //Any error to report?
598  if(error)
599  return error;
600 
601  //Advance data pointer
602  ASN1_INC_POINTER(p, n);
603  length += n;
604 
605  //Write parameter q
606  tag.constructed = FALSE;
609  tag.length = dsaParams->q.length;
610  tag.value = dsaParams->q.value;
611 
612  //Write the corresponding ASN.1 tag
613  error = asn1WriteTag(&tag, FALSE, p, &n);
614  //Any error to report?
615  if(error)
616  return error;
617 
618  //Advance data pointer
619  ASN1_INC_POINTER(p, n);
620  length += n;
621 
622  //Write parameter g
623  tag.constructed = FALSE;
626  tag.length = dsaParams->g.length;
627  tag.value = dsaParams->g.value;
628 
629  //Write the corresponding ASN.1 tag
630  error = asn1WriteTag(&tag, FALSE, p, &n);
631  //Any error to report?
632  if(error)
633  return error;
634 
635  //Advance data pointer
636  ASN1_INC_POINTER(p, n);
637  length += n;
638 
639  //The DSA domain parameters are encapsulated within a sequence
640  tag.constructed = TRUE;
643  tag.length = length;
644 
645  //Write DSAParameters structure
646  error = asn1InsertHeader(&tag, output, &n);
647  //Any error to report?
648  if(error)
649  return error;
650 
651  //Total number of bytes that have been written
652  *written = tag.totalLength;
653 
654  //Successful processing
655  return NO_ERROR;
656 }
657 
658 
659 /**
660  * @brief Format ECPublicKey structure
661  * @param[in] ecPublicKey Pointer to the EC public key
662  * @param[out] output Buffer where to format the ASN.1 structure
663  * @param[out] written Length of the resulting ASN.1 structure
664  * @return Error code
665  **/
666 
668  uint8_t *output, size_t *written)
669 {
670  //If the output parameter is NULL, then the function calculates the length
671  //of the octet string without copying any data
672  if(output != NULL)
673  {
674  //Copy the EC public key
675  osMemcpy(output, ecPublicKey->q.value, ecPublicKey->q.length);
676  }
677 
678  //Total number of bytes that have been written
679  *written = ecPublicKey->q.length;
680 
681  //Successful processing
682  return NO_ERROR;
683 }
684 
685 
686 /**
687  * @brief Format ECParameters structure
688  * @param[in] ecParams Pointer to the EC parameters
689  * @param[out] output Buffer where to format the ECParameters structure
690  * @param[out] written Length of the ECParameters structure
691  * @return Error code
692  **/
693 
695  uint8_t *output, size_t *written)
696 {
697  error_t error;
698  size_t n;
699  Asn1Tag tag;
700 
701  //The namedCurve field identifies all the required values for a particular
702  //set of elliptic curve domain parameters to be represented by an object
703  //identifier
704  tag.constructed = FALSE;
707  tag.length = ecParams->namedCurve.length;
708  tag.value = ecParams->namedCurve.value;
709 
710  //Write the corresponding ASN.1 tag
711  error = asn1WriteTag(&tag, FALSE, output, &n);
712  //Any error to report?
713  if(error)
714  return error;
715 
716  //Total number of bytes that have been written
717  *written = n;
718 
719  //Successful processing
720  return NO_ERROR;
721 }
722 
723 
724 /**
725  * @brief Export an RSA public key to ASN.1 format
726  * @param[in] publicKey Pointer to the RSA public key
727  * @param[out] output Buffer where to store the ASN.1 structure
728  * @param[out] written Length of the resulting ASN.1 structure
729  * @return Error code
730  **/
731 
733  uint8_t *output, size_t *written)
734 {
735  error_t error;
736  size_t n;
737  size_t length;
738  uint8_t *p;
739  Asn1Tag tag;
740 
741  //Point to the buffer where to write the ASN.1 structure
742  p = output;
743  //Length of the ASN.1 structure
744  length = 0;
745 
746  //Write Modulus field
747  error = asn1WriteMpi(&publicKey->n, FALSE, p, &n);
748  //Any error to report?
749  if(error)
750  return error;
751 
752  //Advance data pointer
753  ASN1_INC_POINTER(p, n);
754  length += n;
755 
756  //Write PublicExponent field
757  error = asn1WriteMpi(&publicKey->e, FALSE, p, &n);
758  //Any error to report?
759  if(error)
760  return error;
761 
762  //Advance data pointer
763  ASN1_INC_POINTER(p, n);
764  length += n;
765 
766  //The public key is encapsulated within a sequence
767  tag.constructed = TRUE;
770  tag.length = length;
771 
772  //Write RSAPublicKey structure
773  error = asn1InsertHeader(&tag, output, &n);
774  //Any error to report?
775  if(error)
776  return error;
777 
778  //Total number of bytes that have been written
779  *written = tag.totalLength;
780 
781  //Successful processing
782  return NO_ERROR;
783 }
784 
785 
786 /**
787  * @brief Export an RSA private key to ASN.1 format
788  * @param[in] privateKey Pointer to the RSA private key
789  * @param[out] output Buffer where to store the ASN.1 structure
790  * @param[out] written Length of the resulting ASN.1 structure
791  * @return Error code
792  **/
793 
795  uint8_t *output, size_t *written)
796 {
797  error_t error;
798  size_t n;
799  size_t length;
800  uint8_t *p;
801  Asn1Tag tag;
802 
803  //Point to the buffer where to write the ASN.1 structure
804  p = output;
805  //Length of the ASN.1 structure
806  length = 0;
807 
808  //Write Version field
809  error = asn1WriteInt32(PKCS1_VERSION_1, FALSE, p, &n);
810  //Any error to report?
811  if(error)
812  return error;
813 
814  //Advance data pointer
815  ASN1_INC_POINTER(p, n);
816  length += n;
817 
818  //Write Modulus field
819  error = asn1WriteMpi(&privateKey->n, FALSE, p, &n);
820  //Any error to report?
821  if(error)
822  return error;
823 
824  //Advance data pointer
825  ASN1_INC_POINTER(p, n);
826  length += n;
827 
828  //Write PublicExponent field
829  error = asn1WriteMpi(&privateKey->e, FALSE, p, &n);
830  //Any error to report?
831  if(error)
832  return error;
833 
834  //Advance data pointer
835  ASN1_INC_POINTER(p, n);
836  length += n;
837 
838  //Write PrivateExponent field
839  error = asn1WriteMpi(&privateKey->d, FALSE, p, &n);
840  //Any error to report?
841  if(error)
842  return error;
843 
844  //Advance data pointer
845  ASN1_INC_POINTER(p, n);
846  length += n;
847 
848  //Write Prime1 field
849  error = asn1WriteMpi(&privateKey->p, FALSE, p, &n);
850  //Any error to report?
851  if(error)
852  return error;
853 
854  //Advance data pointer
855  ASN1_INC_POINTER(p, n);
856  length += n;
857 
858  //Write Prime2 field
859  error = asn1WriteMpi(&privateKey->q, FALSE, p, &n);
860  //Any error to report?
861  if(error)
862  return error;
863 
864  //Advance data pointer
865  ASN1_INC_POINTER(p, n);
866  length += n;
867 
868  //Write Exponent1 field
869  error = asn1WriteMpi(&privateKey->dp, FALSE, p, &n);
870  //Any error to report?
871  if(error)
872  return error;
873 
874  //Advance data pointer
875  ASN1_INC_POINTER(p, n);
876  length += n;
877 
878  //Write Exponent2 field
879  error = asn1WriteMpi(&privateKey->dq, FALSE, p, &n);
880  //Any error to report?
881  if(error)
882  return error;
883 
884  //Advance data pointer
885  ASN1_INC_POINTER(p, n);
886  length += n;
887 
888  //Write Coefficient field
889  error = asn1WriteMpi(&privateKey->qinv, FALSE, p, &n);
890  //Any error to report?
891  if(error)
892  return error;
893 
894  //Advance data pointer
895  ASN1_INC_POINTER(p, n);
896  length += n;
897 
898  //The private key is encapsulated within a sequence
899  tag.constructed = TRUE;
902  tag.length = length;
903 
904  //Write RSAPrivateKey structure
905  error = asn1InsertHeader(&tag, output, &n);
906  //Any error to report?
907  if(error)
908  return error;
909 
910  //Total number of bytes that have been written
911  *written = tag.totalLength;
912 
913  //Successful processing
914  return NO_ERROR;
915 }
916 
917 
918 /**
919  * @brief Export a DSA public key to ASN.1 format
920  * @param[in] publicKey Pointer to the DSA public key
921  * @param[out] output Buffer where to store the ASN.1 structure
922  * @param[out] written Length of the resulting ASN.1 structure
923  * @return Error code
924  **/
925 
927  uint8_t *output, size_t *written)
928 {
929  error_t error;
930  size_t n;
931 
932  //Write public key
933  error = asn1WriteMpi(&publicKey->y, FALSE, output, &n);
934  //Any error to report?
935  if(error)
936  return error;
937 
938  //Total number of bytes that have been written
939  *written = n;
940 
941  //Successful processing
942  return NO_ERROR;
943 }
944 
945 
946 /**
947  * @brief Export a DSA private key to ASN.1 format
948  * @param[in] privateKey Pointer to the DSA private key
949  * @param[out] output Buffer where to store the ASN.1 structure
950  * @param[out] written Length of the resulting ASN.1 structure
951  * @return Error code
952  **/
953 
955  uint8_t *output, size_t *written)
956 {
957  error_t error;
958  size_t n;
959 
960  //Write private key
961  error = asn1WriteMpi(&privateKey->x, FALSE, output, &n);
962  //Any error to report?
963  if(error)
964  return error;
965 
966  //Total number of bytes that have been written
967  *written = n;
968 
969  //Successful processing
970  return NO_ERROR;
971 }
972 
973 
974 /**
975  * @brief Export DSA domain parameters to ASN.1 format
976  * @param[in] params Pointer to the DSA domain parameters
977  * @param[out] output Buffer where to store the ASN.1 structure
978  * @param[out] written Length of the resulting ASN.1 structure
979  * @return Error code
980  **/
981 
983  uint8_t *output, size_t *written)
984 {
985  error_t error;
986  size_t n;
987  size_t length;
988  uint8_t *p;
989  Asn1Tag tag;
990 
991  //Point to the buffer where to write the ASN.1 structure
992  p = output;
993  //Length of the ASN.1 structure
994  length = 0;
995 
996  //Write parameter p
997  error = asn1WriteMpi(&params->p, FALSE, p, &n);
998  //Any error to report?
999  if(error)
1000  return error;
1001 
1002  //Advance data pointer
1003  ASN1_INC_POINTER(p, n);
1004  length += n;
1005 
1006  //Write parameter q
1007  error = asn1WriteMpi(&params->q, FALSE, p, &n);
1008  //Any error to report?
1009  if(error)
1010  return error;
1011 
1012  //Advance data pointer
1013  ASN1_INC_POINTER(p, n);
1014  length += n;
1015 
1016  //Write parameter g
1017  error = asn1WriteMpi(&params->g, FALSE, p, &n);
1018  //Any error to report?
1019  if(error)
1020  return error;
1021 
1022  //Advance data pointer
1023  ASN1_INC_POINTER(p, n);
1024  length += n;
1025 
1026  //The DSA domain parameters are encapsulated within a sequence
1027  tag.constructed = TRUE;
1030  tag.length = length;
1031 
1032  //Write DSAParameters structure
1033  error = asn1InsertHeader(&tag, output, &n);
1034  //Any error to report?
1035  if(error)
1036  return error;
1037 
1038  //Total number of bytes that have been written
1039  *written = tag.totalLength;
1040 
1041  //Successful processing
1042  return NO_ERROR;
1043 }
1044 
1045 
1046 /**
1047  * @brief Export an EC public key to ASN.1 format
1048  * @param[in] publicKey EC public key
1049  * @param[out] output Buffer where to format the ASN.1 structure
1050  * @param[out] written Length of the resulting ASN.1 structure
1051  * @return Error code
1052  **/
1053 
1055  uint8_t *output, size_t *written)
1056 {
1057 #if (EC_SUPPORT == ENABLED)
1058  error_t error;
1059  size_t n;
1060  uint8_t *p;
1061  Asn1Tag tag;
1062 
1063  //Point to the buffer where to write the ASN.1 structure
1064  p = output;
1065 
1066  //If the output parameter is NULL, then the function calculates the length
1067  //of the ASN.1 structure without copying any data
1068  if(p != NULL)
1069  {
1070  //The bit string shall contain an initial octet which encodes the number
1071  //of unused bits in the final subsequent octet
1072  p[0] = 0;
1073 
1074  //Advance data pointer
1075  p++;
1076  }
1077 
1078  //Format ECPublicKey structure
1079  error = ecExportPublicKey(publicKey, p, &n, EC_PUBLIC_KEY_FORMAT_X963);
1080 
1081  //Check status code
1082  if(!error)
1083  {
1084  //The public key is encapsulated within a bit string
1085  tag.constructed = FALSE;
1088  tag.length = n + 1;
1089 
1090  //Write the corresponding ASN.1 tag
1091  error = asn1InsertHeader(&tag, output, &n);
1092  }
1093 
1094  //Check status code
1095  if(!error)
1096  {
1097  //Get the length of the ECPublicKey structure
1098  n = tag.totalLength;
1099 
1100  //Explicit tagging shall be used to encode the public key
1101  tag.constructed = TRUE;
1103  tag.objType = 1;
1104  tag.length = n;
1105 
1106  //Write the corresponding ASN.1 tag
1107  error = asn1InsertHeader(&tag, output, &n);
1108  }
1109 
1110  //Check status code
1111  if(!error)
1112  {
1113  //Total number of bytes that have been written
1114  *written = tag.totalLength;
1115  }
1116 
1117  //Return status code
1118  return error;
1119 #else
1120  //Not implemented
1121  return ERROR_NOT_IMPLEMENTED;
1122 #endif
1123 }
1124 
1125 
1126 /**
1127  * @brief Export an EC private key to ASN.1 format
1128  * @param[in] curve Elliptic curve parameters (optional parameter)
1129  * @param[in] privateKey Pointer to the EC private key
1130  * @param[in] publicKey Pointer to the EC public key (optional parameter)
1131  * @param[out] output Buffer where to store the ASN.1 structure
1132  * @param[out] written Length of the resulting ASN.1 structure
1133  * @return Error code
1134  **/
1135 
1137  const EcPrivateKey *privateKey, const EcPublicKey *publicKey,
1138  uint8_t *output, size_t *written)
1139 {
1140 #if (EC_SUPPORT == ENABLED)
1141  error_t error;
1142  size_t n;
1143  size_t length;
1144  uint8_t *p;
1145  Asn1Tag tag;
1146 
1147  //Point to the buffer where to write the ASN.1 structure
1148  p = output;
1149  //Length of the ASN.1 structure
1150  length = 0;
1151 
1152  //Format Version field (refer to RFC 5915, section 3)
1153  error = asn1WriteInt32(1, FALSE, p, &n);
1154  //Any error to report?
1155  if(error)
1156  return error;
1157 
1158  //Advance data pointer
1159  ASN1_INC_POINTER(p, n);
1160  length += n;
1161 
1162  //The PrivateKey field is an octet string of length ceiling (log2(n)/8)
1163  //(refer to RFC 5915, section 3)
1164  error = ecExportPrivateKey(privateKey, p, &n);
1165  //Any error to report?
1166  if(error)
1167  return error;
1168 
1169  //Format PrivateKey field
1170  tag.constructed = FALSE;
1173  tag.length = n;
1174 
1175  //Write the corresponding ASN.1 tag
1176  error = asn1InsertHeader(&tag, p, &n);
1177  //Any error to report?
1178  if(error)
1179  return error;
1180 
1181  //Get the length of the PrivateKey structure
1182  n = tag.totalLength;
1183 
1184  //Advance data pointer
1185  ASN1_INC_POINTER(p, n);
1186  length += n;
1187 
1188  //The parameters field is optional
1189  if(curve != NULL)
1190  {
1191  //Format ECParameters field
1192  error = x509ExportEcParameters(curve, p, &n);
1193  //Any error to report?
1194  if(error)
1195  return error;
1196 
1197  //Advance data pointer
1198  ASN1_INC_POINTER(p, n);
1199  length += n;
1200  }
1201 
1202  //The publicKey field is optional
1203  if(publicKey != NULL && publicKey->curve != NULL)
1204  {
1205  //Format publicKey field
1206  error = x509ExportEcPublicKey(publicKey, p, &n);
1207  //Any error to report?
1208  if(error)
1209  return error;
1210 
1211  //Advance data pointer
1212  ASN1_INC_POINTER(p, n);
1213  length += n;
1214  }
1215 
1216  //Format ECPrivateKey field
1217  tag.constructed = TRUE;
1220  tag.length = length;
1221 
1222  //Write the corresponding ASN.1 tag
1223  error = asn1InsertHeader(&tag, output, &n);
1224  //Any error to report?
1225  if(error)
1226  return error;
1227 
1228  //Total number of bytes that have been written
1229  *written = tag.totalLength;
1230 
1231  //Successful processing
1232  return NO_ERROR;
1233 #else
1234  //Not implemented
1235  return ERROR_NOT_IMPLEMENTED;
1236 #endif
1237 }
1238 
1239 
1240 /**
1241  * @brief Export EC domain parameters to ASN.1 format
1242  * @param[in] curve Elliptic curve parameters
1243  * @param[out] output Buffer where to store the ASN.1 structure
1244  * @param[out] written Length of the resulting ASN.1 structure
1245  * @return Error code
1246  **/
1247 
1248 error_t x509ExportEcParameters(const EcCurve *curve, uint8_t *output,
1249  size_t *written)
1250 {
1251 #if (EC_SUPPORT == ENABLED)
1252  error_t error;
1253  size_t n;
1254  Asn1Tag tag;
1255 
1256  //Format ECParameters field
1257  tag.constructed = FALSE;
1260  tag.length = curve->oidSize;
1261  tag.value = curve->oid;
1262 
1263  //Write the corresponding ASN.1 tag
1264  error = asn1WriteTag(&tag, FALSE, output, &n);
1265 
1266  //Check status code
1267  if(!error)
1268  {
1269  //Explicit tagging shall be used to encode the parameters
1270  tag.constructed = TRUE;
1272  tag.objType = 0;
1273  tag.length = n;
1274 
1275  //Write the corresponding ASN.1 tag
1276  error = asn1InsertHeader(&tag, output, &n);
1277  }
1278 
1279  //Check status code
1280  if(!error)
1281  {
1282  //Total number of bytes that have been written
1283  *written = tag.totalLength;
1284  }
1285 
1286  //Return status code
1287  return error;
1288 #else
1289  //Not implemented
1290  return ERROR_NOT_IMPLEMENTED;
1291 #endif
1292 }
1293 
1294 
1295 /**
1296  * @brief Export an EdDSA private key to ASN.1 format
1297  * @param[in] privateKey Pointer to the EdDSA private key
1298  * @param[out] output Buffer where to store the ASN.1 structure
1299  * @param[out] written Length of the resulting ASN.1 structure
1300  * @return Error code
1301  **/
1302 
1304  uint8_t *output, size_t *written)
1305 {
1306 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
1307  error_t error;
1308  size_t n;
1309  Asn1Tag tag;
1310 
1311  //The private key is always an opaque byte sequence
1312  error = eddsaExportPrivateKey(privateKey, output, &n);
1313 
1314  //Check status code
1315  if(!error)
1316  {
1317  //The private key is encapsulated within an octet string
1318  tag.constructed = FALSE;
1321  tag.length = n;
1322 
1323  //Write CurvePrivateKey structure
1324  error = asn1InsertHeader(&tag, output, &n);
1325  }
1326 
1327  //Check status code
1328  if(!error)
1329  {
1330  //Total number of bytes that have been written
1331  *written = tag.totalLength;
1332  }
1333 
1334  //Return status code
1335  return error;
1336 #else
1337  //Not implemented
1338  return ERROR_NOT_IMPLEMENTED;
1339 #endif
1340 }
1341 
1342 #endif
error_t x509FormatEcParameters(const X509EcParameters *ecParams, uint8_t *output, size_t *written)
Format ECParameters structure.
error_t x509ExportEddsaPrivateKey(const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export an EdDSA private key to ASN.1 format.
Mpi p
First factor.
Definition: rsa.h:72
const uint8_t X25519_OID[3]
Definition: ec_curves.c:108
X509OctetString g
Definition: x509_common.h:799
X509OctetString p
Definition: x509_common.h:797
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
X509DsaPublicKey dsaPublicKey
Definition: x509_common.h:847
OID (Object Identifier)
SHA-1 (Secure Hash Algorithm 1)
uint8_t p
Definition: ndp.h:300
Mpi q
Group order.
Definition: dsa.h:51
X509OctetString oid
Definition: x509_common.h:840
#define TRUE
Definition: os_port.h:50
error_t x509ExportEcPrivateKey(const EcCurve *curve, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, uint8_t *output, size_t *written)
Export an EC private key to ASN.1 format.
error_t asn1InsertHeader(Asn1Tag *tag, uint8_t *data, size_t *written)
Insert an ASN.1 tag header.
Definition: asn1.c:643
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:44
Mpi n
Modulus.
Definition: rsa.h:69
X509EcParameters ecParams
Definition: x509_common.h:850
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
Mpi e
Public exponent.
Definition: rsa.h:59
Mpi p
Prime modulus.
Definition: dsa.h:50
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:85
uint8_t oid[]
Definition: lldp_tlv.h:300
Mpi d
Private exponent.
Definition: rsa.h:71
Mpi n
Modulus.
Definition: rsa.h:58
X509OctetString q
Definition: x509_common.h:798
EC public key.
Definition: x509_common.h:828
error_t x509FormatSubjectPublicKeyInfo(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
Format SubjectPublicKeyInfo structure.
const uint8_t DSA_OID[7]
Definition: dsa.c:51
@ PKCS1_VERSION_1
Definition: x509_common.h:493
error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-1.
size_t totalLength
Definition: asn1.h:111
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *output, size_t *written)
Export an EdDSA public key.
Definition: eddsa.c:328
size_t length
Definition: asn1.h:109
X509OctetString y
Definition: x509_common.h:809
#define FALSE
Definition: os_port.h:46
DSA public key.
Definition: dsa.h:61
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t x509FormatDsaPublicKey(const X509DsaPublicKey *dsaPublicKey, uint8_t *output, size_t *written)
Format DSAPublicKey structure.
error_t
Error codes.
Definition: error.h:43
error_t ecExportPrivateKey(const EcPrivateKey *key, uint8_t *output, size_t *written)
Export an EC private key.
Definition: ec.c:578
Mpi g
Group generator.
Definition: dsa.h:52
error_t x509ExportDsaPublicKey(const DsaPublicKey *publicKey, uint8_t *output, size_t *written)
Export a DSA public key to ASN.1 format.
EC parameters.
Definition: x509_common.h:818
error_t x509ExportDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export a DSA private key to ASN.1 format.
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
RSA public key.
Definition: x509_common.h:785
error_t x509FormatAlgoId(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *params, uint8_t *output, size_t *written)
Format AlgorithmIdentifier structure.
ASN.1 tag.
Definition: asn1.h:105
Mpi q
Second factor.
Definition: rsa.h:73
#define ASN1_INC_POINTER(p, n)
Definition: asn1.h:58
error_t x509ExportRsaPublicKey(const RsaPublicKey *publicKey, uint8_t *output, size_t *written)
Export an RSA public key to ASN.1 format.
RSA public key.
Definition: rsa.h:57
X509RsaPublicKey rsaPublicKey
Definition: x509_common.h:843
DSA domain parameters.
Definition: dsa.h:49
EdDSA (Edwards-Curve Digital Signature Algorithm)
General definitions for cryptographic algorithms.
error_t asn1WriteMpi(const Mpi *value, bool_t reverse, uint8_t *data, size_t *written)
Write a multiple-precision integer from the output stream.
Definition: asn1.c:880
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
error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *output, size_t *written)
Export an EdDSA private key.
Definition: eddsa.c:436
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:62
DSA private key.
Definition: dsa.h:72
X509DsaParameters dsaParams
Definition: x509_common.h:846
uint_t objClass
Definition: asn1.h:107
uint8_t length
Definition: tcp.h:375
Mpi e
Public exponent.
Definition: rsa.h:70
error_t x509FormatRsaPublicKey(const X509RsaPublicKey *rsaPublicKey, uint8_t *output, size_t *written)
Format RSAPublicKey structure.
error_t x509ExportRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export an RSA private key to ASN.1 format.
X509OctetString namedCurve
Definition: x509_common.h:819
error_t x509ExportEcPublicKey(const EcPublicKey *publicKey, uint8_t *output, size_t *written)
Export an EC public key to ASN.1 format.
const uint8_t ED448_OID[3]
Definition: ec_curves.c:114
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
EdDSA private key.
Definition: eddsa.h:75
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
const uint8_t ED25519_OID[3]
Definition: ec_curves.c:112
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:54
const uint8_t X448_OID[3]
Definition: ec_curves.c:110
EC public key.
Definition: ec.h:421
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:75
@ ASN1_TYPE_INTEGER
Definition: asn1.h:73
Formatting of ASN.1 encoded keys.
error_t x509FormatEcPublicKey(const X509EcPublicKey *ecPublicKey, uint8_t *output, size_t *written)
Format ECPublicKey structure.
error_t x509ExportEcParameters(const EcCurve *curve, uint8_t *output, size_t *written)
Export EC domain parameters to ASN.1 format.
X509OctetString q
Definition: x509_common.h:829
#define OID_COMP(oid1, oidLen1, oid2)
Definition: oid.h:42
uint8_t n
RSA private key.
Definition: rsa.h:68
X509OctetString n
Definition: x509_common.h:786
X509OctetString e
Definition: x509_common.h:787
Subject Public Key Information extension.
Definition: x509_common.h:838
DSA domain parameters.
Definition: x509_common.h:796
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
error_t x509FormatDsaParameters(const X509DsaParameters *dsaParams, uint8_t *output, size_t *written)
Format DSA domain parameters.
error_t x509ExportDsaParameters(const DsaDomainParameters *params, uint8_t *output, size_t *written)
Export DSA domain parameters to ASN.1 format.
Mpi x
Secret exponent.
Definition: dsa.h:74
uint8_t oidLen
Definition: lldp_tlv.h:299
bool_t constructed
Definition: asn1.h:106
Mpi y
Public key value.
Definition: dsa.h:63
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:77
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:83
const uint8_t * value
Definition: x509_common.h:702
#define EcCurve
Definition: ec.h:346
Mpi dp
First factor's CRT exponent.
Definition: rsa.h:74
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:74
X509EcPublicKey ecPublicKey
Definition: x509_common.h:851
error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data, size_t *written)
Write a 32-bit integer to the output stream.
Definition: asn1.c:781
DSA public key.
Definition: x509_common.h:808
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
error_t x509FormatSubjectPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
Format SubjectPublicKey structure.
const uint8_t * value
Definition: asn1.h:110
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_NULL
Definition: asn1.h:76