pem_export.c
Go to the documentation of this file.
1 /**
2  * @file pem_export.c
3  * @brief PEM file export functions
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/pem_export.h"
37 #include "pkix/pkcs8_key_format.h"
38 #include "pkix/x509_cert_create.h"
39 #include "pkix/x509_key_format.h"
40 #include "encoding/asn1.h"
41 #include "mpi/mpi.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (PEM_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Export an X.509 certificate to PEM format
50  * @param[in] cert Pointer to the DER-encoded certificate
51  * @param[in] certLen Length of the DER-encoded certificate, in bytes
52  * @param[out] output Buffer where to store the PEM encoding
53  * @param[out] written Length of the resulting PEM encoding
54  * @return Error code
55  **/
56 
57 error_t pemExportCertificate(const uint8_t *cert, size_t certLen,
58  char_t *output, size_t *written)
59 {
60  error_t error;
61  size_t n;
62 
63  //Check parameters
64  if(cert == NULL || written == NULL)
66 
67  //X.509 certificates are encoded using the "CERTIFICATE" label
68  error = pemEncodeFile(cert, certLen, "CERTIFICATE", output, &n);
69  //Any error to report?
70  if(error)
71  return error;
72 
73  //Total number of bytes that have been written
74  *written = n;
75 
76  //Successful processing
77  return NO_ERROR;
78 }
79 
80 
81 /**
82  * @brief Export a certificate revocation list to PEM format
83  * @param[in] crl Pointer to the DER-encoded CRL
84  * @param[in] crlLen Length of the DER-encoded CRL, in bytes
85  * @param[out] output Buffer where to store the PEM encoding
86  * @param[out] written Length of the resulting PEM encoding
87  * @return Error code
88  **/
89 
90 error_t pemExportCrl(const uint8_t *crl, size_t crlLen,
91  char_t *output, size_t *written)
92 {
93  error_t error;
94  size_t n;
95 
96  //Check parameters
97  if(crl == NULL || written == NULL)
99 
100  //CRLs are encoded using the "X509 CRL" label
101  error = pemEncodeFile(crl, crlLen, "X509 CRL", output, &n);
102  //Any error to report?
103  if(error)
104  return error;
105 
106  //Total number of bytes that have been written
107  *written = n;
108 
109  //Successful processing
110  return NO_ERROR;
111 }
112 
113 
114 /**
115  * @brief Export a certification signing request to PEM format
116  * @param[in] csr Pointer to the DER-encoded CSR
117  * @param[in] csrLen Length of the DER-encoded CSR, in bytes
118  * @param[out] output Buffer where to store the PEM encoding
119  * @param[out] written Length of the resulting PEM encoding
120  * @return Error code
121  **/
122 
123 error_t pemExportCsr(const uint8_t *csr, size_t csrLen,
124  char_t *output, size_t *written)
125 {
126  error_t error;
127  size_t n;
128 
129  //Check parameters
130  if(csr == NULL || written == NULL)
132 
133  //CSRs are encoded using the "CERTIFICATE REQUEST" label
134  error = pemEncodeFile(csr, csrLen, "CERTIFICATE REQUEST", output, &n);
135  //Any error to report?
136  if(error)
137  return error;
138 
139  //Total number of bytes that have been written
140  *written = n;
141 
142  //Successful processing
143  return NO_ERROR;
144 }
145 
146 
147 /**
148  * @brief Export an RSA public key to PEM format
149  * @param[in] publicKey RSA public key
150  * @param[out] output Buffer where to store the PEM encoding
151  * @param[out] written Length of the resulting PEM encoding
152  * @return Error code
153  **/
154 
156  char_t *output, size_t *written)
157 {
158 #if (RSA_SUPPORT == ENABLED)
159  error_t error;
160  size_t n;
161  X509SubjectPublicKeyInfo publicKeyInfo;
162 
163  //Check parameters
164  if(publicKey == NULL || written == NULL)
166 
167  //Clear the SubjectPublicKeyInfo structure
168  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
169 
170  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
171  //structure (refer to RFC 7468, section 13)
172  publicKeyInfo.oid.value = RSA_ENCRYPTION_OID;
173  publicKeyInfo.oid.length = sizeof(RSA_ENCRYPTION_OID);
174 
175  //Format the SubjectPublicKeyInfo structure
176  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
177  (uint8_t *) output, &n);
178  //Any error to report?
179  if(error)
180  return error;
181 
182  //Public keys are encoded using the "PUBLIC KEY" label
183  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
184  //Any error to report?
185  if(error)
186  return error;
187 
188  //Total number of bytes that have been written
189  *written = n;
190 
191  //Successful processing
192  return NO_ERROR;
193 #else
194  //Not implemented
195  return ERROR_NOT_IMPLEMENTED;
196 #endif
197 }
198 
199 
200 /**
201  * @brief Export an RSA private key to PEM format
202  * @param[in] privateKey RSA private key
203  * @param[out] output Buffer where to store the PEM encoding
204  * @param[out] written Length of the resulting PEM encoding
205  * @return Error code
206  **/
207 
209  char_t *output, size_t *written)
210 {
211 #if (RSA_SUPPORT == ENABLED)
212  error_t error;
213  size_t n;
214  size_t length;
215  uint8_t *p;
216  Asn1Tag tag;
217  X509SubjectPublicKeyInfo publicKeyInfo;
218 
219  //Check parameters
220  if(privateKey == NULL || written == NULL)
222 
223  //Clear the SubjectPublicKeyInfo structure
224  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
225 
226  //Point to the buffer where to write the PrivateKeyInfo structure
227  p = (uint8_t *) output;
228  //Total length of the PrivateKeyInfo structure
229  length = 0;
230 
231  //Format Version field (refer to RFC 5208, section 5)
232  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
233  //Any error to report?
234  if(error)
235  return error;
236 
237  //Update the length of the PrivateKeyInfo structure
238  length += n;
239 
240  //Advance data pointer
241  if(output != NULL)
242  p += n;
243 
244  //The PrivateKeyAlgorithm identifies the private-key algorithm
245  publicKeyInfo.oid.value = RSA_ENCRYPTION_OID;
246  publicKeyInfo.oid.length = sizeof(RSA_ENCRYPTION_OID);
247 
248  //Format PrivateKeyAlgorithm field
249  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
250  //Any error to report?
251  if(error)
252  return error;
253 
254  //Update the length of the PrivateKeyInfo structure
255  length += n;
256 
257  //Advance data pointer
258  if(output != NULL)
259  p += n;
260 
261  //Format PrivateKey field
262  error = pkcs8FormatRsaPrivateKey(privateKey, p, &n);
263  //Any error to report?
264  if(error)
265  return error;
266 
267  //Update the length of the PrivateKeyInfo structure
268  length += n;
269 
270  //The PrivateKeyInfo structure is encapsulated within a sequence
271  tag.constructed = TRUE;
274  tag.length = length;
275  tag.value = (uint8_t *) output;
276 
277  //Write the corresponding ASN.1 tag
278  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
279  //Any error to report?
280  if(error)
281  return error;
282 
283  //Get the length of the PrivateKeyInfo structure
284  n = tag.totalLength;
285 
286  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
287  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
288  //Any error to report?
289  if(error)
290  return error;
291 
292  //Total number of bytes that have been written
293  *written = n;
294 
295  //Successful processing
296  return NO_ERROR;
297 #else
298  //Not implemented
299  return ERROR_NOT_IMPLEMENTED;
300 #endif
301 }
302 
303 
304 /**
305  * @brief Export an RSA-PSS public key to PEM format
306  * @param[in] publicKey RSA-PSS public key
307  * @param[out] output Buffer where to store the PEM encoding
308  * @param[out] written Length of the resulting PEM encoding
309  * @return Error code
310  **/
311 
313  char_t *output, size_t *written)
314 {
315 #if (RSA_SUPPORT == ENABLED)
316  error_t error;
317  size_t n;
318  X509SubjectPublicKeyInfo publicKeyInfo;
319 
320  //Check parameters
321  if(publicKey == NULL || written == NULL)
323 
324  //Clear the SubjectPublicKeyInfo structure
325  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
326 
327  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
328  //structure (refer to RFC 7468, section 13)
329  publicKeyInfo.oid.value = RSASSA_PSS_OID;
330  publicKeyInfo.oid.length = sizeof(RSASSA_PSS_OID);
331 
332  //Format the SubjectPublicKeyInfo structure
333  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
334  (uint8_t *) output, &n);
335  //Any error to report?
336  if(error)
337  return error;
338 
339  //Public keys are encoded using the "PUBLIC KEY" label
340  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
341  //Any error to report?
342  if(error)
343  return error;
344 
345  //Total number of bytes that have been written
346  *written = n;
347 
348  //Successful processing
349  return NO_ERROR;
350 #else
351  //Not implemented
352  return ERROR_NOT_IMPLEMENTED;
353 #endif
354 }
355 
356 
357 /**
358  * @brief Export an RSA-PSS private key to PEM format
359  * @param[in] privateKey RSA-PSS private key
360  * @param[out] output Buffer where to store the PEM encoding
361  * @param[out] written Length of the resulting PEM encoding
362  * @return Error code
363  **/
364 
366  char_t *output, size_t *written)
367 {
368 #if (RSA_SUPPORT == ENABLED)
369  error_t error;
370  size_t n;
371  size_t length;
372  uint8_t *p;
373  Asn1Tag tag;
374  X509SubjectPublicKeyInfo publicKeyInfo;
375 
376  //Check parameters
377  if(privateKey == NULL || written == NULL)
379 
380  //Clear the SubjectPublicKeyInfo structure
381  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
382 
383  //Point to the buffer where to write the PrivateKeyInfo structure
384  p = (uint8_t *) output;
385  //Total length of the PrivateKeyInfo structure
386  length = 0;
387 
388  //Format Version field (refer to RFC 5208, section 5)
389  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
390  //Any error to report?
391  if(error)
392  return error;
393 
394  //Update the length of the PrivateKeyInfo structure
395  length += n;
396 
397  //Advance data pointer
398  if(output != NULL)
399  p += n;
400 
401  //The PrivateKeyAlgorithm identifies the private-key algorithm
402  publicKeyInfo.oid.value = RSASSA_PSS_OID;
403  publicKeyInfo.oid.length = sizeof(RSASSA_PSS_OID);
404 
405  //Format PrivateKeyAlgorithm field
406  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
407  //Any error to report?
408  if(error)
409  return error;
410 
411  //Update the length of the PrivateKeyInfo structure
412  length += n;
413 
414  //Advance data pointer
415  if(output != NULL)
416  p += n;
417 
418  //Format PrivateKey field
419  error = pkcs8FormatRsaPrivateKey(privateKey, p, &n);
420  //Any error to report?
421  if(error)
422  return error;
423 
424  //Update the length of the PrivateKeyInfo structure
425  length += n;
426 
427  //The PrivateKeyInfo structure is encapsulated within a sequence
428  tag.constructed = TRUE;
431  tag.length = length;
432  tag.value = (uint8_t *) output;
433 
434  //Write the corresponding ASN.1 tag
435  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
436  //Any error to report?
437  if(error)
438  return error;
439 
440  //Get the length of the PrivateKeyInfo structure
441  n = tag.totalLength;
442 
443  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
444  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
445  //Any error to report?
446  if(error)
447  return error;
448 
449  //Total number of bytes that have been written
450  *written = n;
451 
452  //Successful processing
453  return NO_ERROR;
454 #else
455  //Not implemented
456  return ERROR_NOT_IMPLEMENTED;
457 #endif
458 }
459 
460 
461 /**
462  * @brief Export a DSA public key to PEM format
463  * @param[in] publicKey DSA public key
464  * @param[out] output Buffer where to store the PEM encoding
465  * @param[out] written Length of the resulting PEM encoding
466  * @return Error code
467  **/
468 
470  char_t *output, size_t *written)
471 {
472 #if (DSA_SUPPORT == ENABLED)
473  error_t error;
474  size_t n;
475  X509SubjectPublicKeyInfo publicKeyInfo;
476 
477  //Check parameters
478  if(publicKey == NULL || written == NULL)
480 
481  //Clear the SubjectPublicKeyInfo structure
482  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
483 
484  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
485  //structure (refer to RFC 7468, section 13)
486  publicKeyInfo.oid.value = DSA_OID;
487  publicKeyInfo.oid.length = sizeof(DSA_OID);
488 
489  //Format the SubjectPublicKeyInfo structure
490  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
491  (uint8_t *) output, &n);
492  //Any error to report?
493  if(error)
494  return error;
495 
496  //Public keys are encoded using the "PUBLIC KEY" label
497  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
498  //Any error to report?
499  if(error)
500  return error;
501 
502  //Total number of bytes that have been written
503  *written = n;
504 
505  //Successful processing
506  return NO_ERROR;
507 #else
508  //Not implemented
509  return ERROR_NOT_IMPLEMENTED;
510 #endif
511 }
512 
513 
514 /**
515  * @brief Export a DSA private key to PEM format
516  * @param[in] privateKey DSA private key
517  * @param[out] output Buffer where to store the PEM encoding
518  * @param[out] written Length of the resulting PEM encoding
519  * @return Error code
520  **/
521 
523  char_t *output, size_t *written)
524 {
525 #if (DSA_SUPPORT == ENABLED)
526  error_t error;
527  size_t n;
528  size_t length;
529  uint8_t *p;
530  Asn1Tag tag;
531  X509SubjectPublicKeyInfo publicKeyInfo;
532 
533  //Check parameters
534  if(privateKey == NULL || written == NULL)
536 
537  //Clear the SubjectPublicKeyInfo structure
538  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
539 
540  //Point to the buffer where to write the PrivateKeyInfo structure
541  p = (uint8_t *) output;
542  //Total length of the PrivateKeyInfo structure
543  length = 0;
544 
545  //Format Version field (refer to RFC 5208, section 5)
546  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
547  //Any error to report?
548  if(error)
549  return error;
550 
551  //Update the length of the PrivateKeyInfo structure
552  length += n;
553 
554  //Advance data pointer
555  if(output != NULL)
556  p += n;
557 
558  //The PrivateKeyAlgorithm identifies the private-key algorithm
559  publicKeyInfo.oid.value = DSA_OID;
560  publicKeyInfo.oid.length = sizeof(DSA_OID);
561 
562  //Format PrivateKeyAlgorithm field
563  error = x509FormatAlgoId(&publicKeyInfo, &privateKey->params,
564  p, &n);
565  //Any error to report?
566  if(error)
567  return error;
568 
569  //Update the length of the PrivateKeyInfo structure
570  length += n;
571 
572  //Advance data pointer
573  if(output != NULL)
574  p += n;
575 
576  //Format PrivateKey field
577  error = pkcs8FormatDsaPrivateKey(privateKey, p, &n);
578  //Any error to report?
579  if(error)
580  return error;
581 
582  //Update the length of the PrivateKeyInfo structure
583  length += n;
584 
585  //The PrivateKeyInfo structure is encapsulated within a sequence
586  tag.constructed = TRUE;
589  tag.length = length;
590  tag.value = (uint8_t *) output;
591 
592  //Write the corresponding ASN.1 tag
593  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
594  //Any error to report?
595  if(error)
596  return error;
597 
598  //Get the length of the PrivateKeyInfo structure
599  n = tag.totalLength;
600 
601  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
602  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
603  //Any error to report?
604  if(error)
605  return error;
606 
607  //Total number of bytes that have been written
608  *written = n;
609 
610  //Successful processing
611  return NO_ERROR;
612 #else
613  //Not implemented
614  return ERROR_NOT_IMPLEMENTED;
615 #endif
616 }
617 
618 
619 /**
620  * @brief Export EC domain parameters to PEM format
621  * @param[in] curve Elliptic curve parameters
622  * @param[out] output Buffer where to store the PEM encoding
623  * @param[out] written Length of the resulting PEM encoding
624  * @return Error code
625  **/
626 
628  size_t *written)
629 {
630 #if (EC_SUPPORT == ENABLED)
631  error_t error;
632  size_t n;
633  Asn1Tag tag;
634 
635  //Check parameters
636  if(curve == NULL || written == NULL)
638 
639  //Format ECParameters field
640  tag.constructed = FALSE;
643  tag.length = curve->oidSize;
644  tag.value = curve->oid;
645 
646  //Write the corresponding ASN.1 tag
647  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
648  //Any error to report?
649  if(error)
650  return error;
651 
652  //EC domain parameters are encoded using the "EC PARAMETERS" label
653  error = pemEncodeFile(output, n, "EC PARAMETERS", output, &n);
654  //Any error to report?
655  if(error)
656  return error;
657 
658  //Total number of bytes that have been written
659  *written = n;
660 
661  //Successful processing
662  return NO_ERROR;
663 #else
664  //Not implemented
665  return ERROR_NOT_IMPLEMENTED;
666 #endif
667 }
668 
669 
670 /**
671  * @brief Export an EC public key to PEM format
672  * @param[in] publicKey EC public key
673  * @param[out] output Buffer where to store the PEM encoding
674  * @param[out] written Length of the resulting PEM encoding
675  * @return Error code
676  **/
677 
679  char_t *output, size_t *written)
680 {
681 #if (EC_SUPPORT == ENABLED)
682  error_t error;
683  size_t n;
684  X509SubjectPublicKeyInfo publicKeyInfo;
685 
686  //Check parameters
687  if(publicKey == NULL || written == NULL)
689 
690  //Invalid elliptic curve?
691  if(publicKey->curve == NULL)
693 
694  //Clear the SubjectPublicKeyInfo structure
695  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
696 
697  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
698  //structure (refer to RFC 7468, section 13)
699  publicKeyInfo.oid.value = EC_PUBLIC_KEY_OID;
700  publicKeyInfo.oid.length = sizeof(EC_PUBLIC_KEY_OID);
701  publicKeyInfo.ecParams.namedCurve.value = publicKey->curve->oid;
702  publicKeyInfo.ecParams.namedCurve.length = publicKey->curve->oidSize;
703 
704  //Format the SubjectPublicKeyInfo structure
705  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
706  (uint8_t *) output, &n);
707  //Any error to report?
708  if(error)
709  return error;
710 
711  //Public keys are encoded using the "PUBLIC KEY" label
712  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
713  //Any error to report?
714  if(error)
715  return error;
716 
717  //Total number of bytes that have been written
718  *written = n;
719 
720  //Successful processing
721  return NO_ERROR;
722 #else
723  //Not implemented
724  return ERROR_NOT_IMPLEMENTED;
725 #endif
726 }
727 
728 
729 /**
730  * @brief Export an EC private key to PEM format
731  * @param[in] privateKey EC private key
732  * @param[out] output Buffer where to store the PEM encoding
733  * @param[out] written Length of the resulting PEM encoding
734  * @return Error code
735  **/
736 
738  char_t *output, size_t *written)
739 {
740 #if (EC_SUPPORT == ENABLED)
741  error_t error;
742  size_t n;
743  size_t length;
744  uint8_t *p;
745  Asn1Tag tag;
746  X509SubjectPublicKeyInfo publicKeyInfo;
747 
748  //Check parameters
749  if(privateKey == NULL || written == NULL)
751 
752  //Invalid elliptic curve?
753  if(privateKey->curve == NULL)
755 
756  //Clear the SubjectPublicKeyInfo structure
757  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
758 
759  //Point to the buffer where to write the PrivateKeyInfo structure
760  p = (uint8_t *) output;
761  //Total length of the PrivateKeyInfo structure
762  length = 0;
763 
764  //Format Version field (refer to RFC 5208, section 5)
765  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
766  //Any error to report?
767  if(error)
768  return error;
769 
770  //Update the length of the PrivateKeyInfo structure
771  length += n;
772 
773  //Advance data pointer
774  if(output != NULL)
775  p += n;
776 
777  //The PrivateKeyAlgorithm identifies the private-key algorithm
778  publicKeyInfo.oid.value = EC_PUBLIC_KEY_OID;
779  publicKeyInfo.oid.length = sizeof(EC_PUBLIC_KEY_OID);
780  publicKeyInfo.ecParams.namedCurve.value = privateKey->curve->oid;
781  publicKeyInfo.ecParams.namedCurve.length = privateKey->curve->oidSize;
782 
783  //Format PrivateKeyAlgorithm field
784  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
785  //Any error to report?
786  if(error)
787  return error;
788 
789  //Update the length of the PrivateKeyInfo structure
790  length += n;
791 
792  //Advance data pointer
793  if(output != NULL)
794  p += n;
795 
796  //Format PrivateKey field
797  error = pkcs8FormatEcPrivateKey(privateKey, p, &n);
798  //Any error to report?
799  if(error)
800  return error;
801 
802  //Update the length of the PrivateKeyInfo structure
803  length += n;
804 
805  //The PrivateKeyInfo structure is encapsulated within a sequence
806  tag.constructed = TRUE;
809  tag.length = length;
810  tag.value = (uint8_t *) output;
811 
812  //Write the corresponding ASN.1 tag
813  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
814  //Any error to report?
815  if(error)
816  return error;
817 
818  //Get the length of the PrivateKeyInfo structure
819  n = tag.totalLength;
820 
821  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
822  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
823  //Any error to report?
824  if(error)
825  return error;
826 
827  //Total number of bytes that have been written
828  *written = n;
829 
830  //Successful processing
831  return NO_ERROR;
832 #else
833  //Not implemented
834  return ERROR_NOT_IMPLEMENTED;
835 #endif
836 }
837 
838 
839 /**
840  * @brief Export an EdDSA public key to PEM format
841  * @param[in] publicKey EdDSA public key
842  * @param[out] output Buffer where to store the PEM encoding
843  * @param[out] written Length of the resulting PEM encoding
844  * @return Error code
845  **/
846 
848  char_t *output, size_t *written)
849 {
850 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
851  error_t error;
852  size_t n;
853  X509SubjectPublicKeyInfo publicKeyInfo;
854 
855  //Check parameters
856  if(publicKey == NULL || written == NULL)
858 
859  //Invalid elliptic curve?
860  if(publicKey->curve == NULL)
862 
863  //Clear the SubjectPublicKeyInfo structure
864  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
865 
866  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
867  //structure (refer to RFC 7468, section 13)
868  publicKeyInfo.oid.value = publicKey->curve->oid;
869  publicKeyInfo.oid.length = publicKey->curve->oidSize;
870 
871  //Format the SubjectPublicKeyInfo structure
872  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
873  (uint8_t *) output, &n);
874  //Any error to report?
875  if(error)
876  return error;
877 
878  //Public keys are encoded using the "PUBLIC KEY" label
879  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
880  //Any error to report?
881  if(error)
882  return error;
883 
884  //Total number of bytes that have been written
885  *written = n;
886 
887  //Successful processing
888  return NO_ERROR;
889 #else
890  //Not implemented
891  return ERROR_NOT_IMPLEMENTED;
892 #endif
893 }
894 
895 
896 /**
897  * @brief Export an EdDSA private key to PEM format
898  * @param[in] privateKey EdDSA private key
899  * @param[out] output Buffer where to store the PEM encoding
900  * @param[out] written Length of the resulting PEM encoding
901  * @return Error code
902  **/
903 
905  char_t *output, size_t *written)
906 {
907 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
908  error_t error;
909  size_t n;
910  size_t length;
911  uint8_t *p;
912  Asn1Tag tag;
913  X509SubjectPublicKeyInfo publicKeyInfo;
914 
915  //Check parameters
916  if(privateKey == NULL || written == NULL)
918 
919  //Invalid elliptic curve?
920  if(privateKey->curve == NULL)
922 
923  //Clear the SubjectPublicKeyInfo structure
924  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
925 
926  //Point to the buffer where to write the PrivateKeyInfo structure
927  p = (uint8_t *) output;
928  //Total length of the PrivateKeyInfo structure
929  length = 0;
930 
931  //Format Version field (refer to RFC 5208, section 5)
932  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
933  //Any error to report?
934  if(error)
935  return error;
936 
937  //Update the length of the PrivateKeyInfo structure
938  length += n;
939 
940  //Advance data pointer
941  if(output != NULL)
942  p += n;
943 
944  //The PrivateKeyAlgorithm identifies the private-key algorithm
945  publicKeyInfo.oid.value = privateKey->curve->oid;
946  publicKeyInfo.oid.length = privateKey->curve->oidSize;
947 
948  //Format PrivateKeyAlgorithm field
949  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
950  //Any error to report?
951  if(error)
952  return error;
953 
954  //Update the length of the PrivateKeyInfo structure
955  length += n;
956 
957  //Advance data pointer
958  if(output != NULL)
959  p += n;
960 
961  //Format PrivateKey field
962  error = pkcs8FormatEddsaPrivateKey(privateKey, p, &n);
963  //Any error to report?
964  if(error)
965  return error;
966 
967  //Update the length of the PrivateKeyInfo structure
968  length += n;
969 
970  //Advance data pointer
971  if(output != NULL)
972  p += n;
973 
974  //The public key is optional
975  if(privateKey->q.curve != NULL)
976  {
977  //Format PublicKey field
978  error = pkcs8FormatEddsaPublicKey(&privateKey->q, p, &n);
979  //Any error to report?
980  if(error)
981  return error;
982 
983  //Update the length of the PrivateKeyInfo structure
984  length += n;
985  }
986 
987  //The PrivateKeyInfo structure is encapsulated within a sequence
988  tag.constructed = TRUE;
991  tag.length = length;
992  tag.value = (uint8_t *) output;
993 
994  //Write the corresponding ASN.1 tag
995  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
996  //Any error to report?
997  if(error)
998  return error;
999 
1000  //Get the length of the PrivateKeyInfo structure
1001  n = tag.totalLength;
1002 
1003  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
1004  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
1005  //Any error to report?
1006  if(error)
1007  return error;
1008 
1009  //Total number of bytes that have been written
1010  *written = n;
1011 
1012  //Successful processing
1013  return NO_ERROR;
1014 #else
1015  //Not implemented
1016  return ERROR_NOT_IMPLEMENTED;
1017 #endif
1018 }
1019 
1020 #endif
PKCS #8 key formatting.
error_t pemExportRsaPssPublicKey(const RsaPublicKey *publicKey, char_t *output, size_t *written)
Export an RSA-PSS public key to PEM format.
Definition: pem_export.c:312
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:76
uint8_t p
Definition: ndp.h:300
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
X509OctetString oid
Definition: x509_common.h:840
#define TRUE
Definition: os_port.h:50
error_t pemExportDsaPrivateKey(const DsaPrivateKey *privateKey, char_t *output, size_t *written)
Export a DSA private key to PEM format.
Definition: pem_export.c:522
error_t pkcs8FormatEddsaPrivateKey(const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EdDSA private key.
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:44
X509EcParameters ecParams
Definition: x509_common.h:850
error_t pemExportEddsaPublicKey(const EddsaPublicKey *publicKey, char_t *output, size_t *written)
Export an EdDSA public key to PEM format.
Definition: pem_export.c:847
error_t pkcs8FormatRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an RSA private key.
error_t pemExportEcPrivateKey(const EcPrivateKey *privateKey, char_t *output, size_t *written)
Export an EC private key to PEM format.
Definition: pem_export.c:737
error_t pemExportCrl(const uint8_t *crl, size_t crlLen, char_t *output, size_t *written)
Export a certificate revocation list to PEM format.
Definition: pem_export.c:90
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:85
error_t pkcs8FormatDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format a DSA private key.
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
size_t totalLength
Definition: asn1.h:108
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
size_t length
Definition: asn1.h:106
#define FALSE
Definition: os_port.h:46
DSA public key.
Definition: dsa.h:61
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
X.509 certificate generation.
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:65
error_t
Error codes.
Definition: error.h:43
error_t pemExportEcPublicKey(const EcPublicKey *publicKey, char_t *output, size_t *written)
Export an EC public key to PEM format.
Definition: pem_export.c:678
EdDSA public key.
Definition: eddsa.h:64
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
error_t pkcs8FormatEcPrivateKey(const EcPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EC private key.
error_t x509FormatAlgoId(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *params, uint8_t *output, size_t *written)
Format AlgorithmIdentifier structure.
ASN.1 tag.
Definition: asn1.h:102
error_t pemEncodeFile(const void *input, size_t inputLen, const char_t *label, char_t *output, size_t *outputLen)
Convert ASN.1 data to PEM encoding.
Definition: pem_common.c:122
RSA public key.
Definition: rsa.h:57
error_t pemExportCsr(const uint8_t *csr, size_t csrLen, char_t *output, size_t *written)
Export a certification signing request to PEM format.
Definition: pem_export.c:123
MPI (Multiple Precision Integer Arithmetic)
General definitions for cryptographic algorithms.
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
error_t pemExportRsaPrivateKey(const RsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an RSA private key to PEM format.
Definition: pem_export.c:208
EC private key.
Definition: ec.h:432
DSA private key.
Definition: dsa.h:72
error_t pemExportRsaPssPrivateKey(const RsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an RSA-PSS private key to PEM format.
Definition: pem_export.c:365
uint_t objClass
Definition: asn1.h:104
uint8_t length
Definition: tcp.h:375
@ PKCS8_VERSION_1
Definition: x509_common.h:503
X509OctetString namedCurve
Definition: x509_common.h:819
EdDSA private key.
Definition: eddsa.h:75
PEM file export functions.
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:54
error_t pemExportEcParameters(const EcCurve *curve, char_t *output, size_t *written)
Export EC domain parameters to PEM format.
Definition: pem_export.c:627
EC public key.
Definition: ec.h:421
char char_t
Definition: compiler_port.h:55
Formatting of ASN.1 encoded keys.
uint8_t n
RSA private key.
Definition: rsa.h:68
Subject Public Key Information extension.
Definition: x509_common.h:838
error_t pemExportCertificate(const uint8_t *cert, size_t certLen, char_t *output, size_t *written)
Export an X.509 certificate to PEM format.
Definition: pem_export.c:57
bool_t constructed
Definition: asn1.h:103
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
error_t pemExportDsaPublicKey(const DsaPublicKey *publicKey, char_t *output, size_t *written)
Export a DSA public key to PEM format.
Definition: pem_export.c:469
const uint8_t * value
Definition: x509_common.h:702
#define EcCurve
Definition: ec.h:346
error_t pkcs8FormatEddsaPublicKey(const EddsaPublicKey *publicKey, uint8_t *output, size_t *written)
Format an EdDSA public key.
error_t pemExportEddsaPrivateKey(const EddsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an EdDSA private key to PEM format.
Definition: pem_export.c:904
#define osMemset(p, value, length)
Definition: os_port.h:138
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:645
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
const uint8_t * value
Definition: asn1.h:107
@ NO_ERROR
Success.
Definition: error.h:44
error_t pemExportRsaPublicKey(const RsaPublicKey *publicKey, char_t *output, size_t *written)
Export an RSA public key to PEM format.
Definition: pem_export.c:155
Debugging facilities.
uint_t objType
Definition: asn1.h:105
ASN.1 (Abstract Syntax Notation One)