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-2024 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.4.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] curveInfo 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  char_t *output, 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(curveInfo == NULL || written == NULL)
638 
639  //Format ECParameters field
640  tag.constructed = FALSE;
643  tag.length = curveInfo->oidSize;
644  tag.value = curveInfo->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] curveInfo Elliptic curve parameters
673  * @param[in] publicKey EC public key
674  * @param[out] output Buffer where to store the PEM encoding
675  * @param[out] written Length of the resulting PEM encoding
676  * @return Error code
677  **/
678 
680  const EcPublicKey *publicKey, char_t *output, size_t *written)
681 {
682 #if (EC_SUPPORT == ENABLED)
683  error_t error;
684  size_t n;
685  X509SubjectPublicKeyInfo publicKeyInfo;
686 
687  //Check parameters
688  if(curveInfo == NULL || publicKey == NULL || written == NULL)
690 
691  //Clear the SubjectPublicKeyInfo structure
692  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
693 
694  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
695  //structure (refer to RFC 7468, section 13)
696  publicKeyInfo.oid.value = EC_PUBLIC_KEY_OID;
697  publicKeyInfo.oid.length = sizeof(EC_PUBLIC_KEY_OID);
698  publicKeyInfo.ecParams.namedCurve.value = curveInfo->oid;
699  publicKeyInfo.ecParams.namedCurve.length = curveInfo->oidSize;
700 
701  //Format the SubjectPublicKeyInfo structure
702  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
703  (uint8_t *) output, &n);
704  //Any error to report?
705  if(error)
706  return error;
707 
708  //Public keys are encoded using the "PUBLIC KEY" label
709  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
710  //Any error to report?
711  if(error)
712  return error;
713 
714  //Total number of bytes that have been written
715  *written = n;
716 
717  //Successful processing
718  return NO_ERROR;
719 #else
720  //Not implemented
721  return ERROR_NOT_IMPLEMENTED;
722 #endif
723 }
724 
725 
726 /**
727  * @brief Export an EC private key to PEM format
728  * @param[in] curveInfo Elliptic curve parameters
729  * @param[in] privateKey EC private key
730  * @param[in] publicKey EC public key (optional parameter)
731  * @param[out] output Buffer where to store the PEM encoding
732  * @param[out] written Length of the resulting PEM encoding
733  * @return Error code
734  **/
735 
737  const EcPrivateKey *privateKey, const EcPublicKey *publicKey,
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(curveInfo == NULL || privateKey == NULL || written == NULL)
751 
752  //Clear the SubjectPublicKeyInfo structure
753  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
754 
755  //Point to the buffer where to write the PrivateKeyInfo structure
756  p = (uint8_t *) output;
757  //Total length of the PrivateKeyInfo structure
758  length = 0;
759 
760  //Format Version field (refer to RFC 5208, section 5)
761  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
762  //Any error to report?
763  if(error)
764  return error;
765 
766  //Update the length of the PrivateKeyInfo structure
767  length += n;
768 
769  //Advance data pointer
770  if(output != NULL)
771  p += n;
772 
773  //The PrivateKeyAlgorithm identifies the private-key algorithm
774  publicKeyInfo.oid.value = EC_PUBLIC_KEY_OID;
775  publicKeyInfo.oid.length = sizeof(EC_PUBLIC_KEY_OID);
776  publicKeyInfo.ecParams.namedCurve.value = curveInfo->oid;
777  publicKeyInfo.ecParams.namedCurve.length = curveInfo->oidSize;
778 
779  //Format PrivateKeyAlgorithm field
780  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
781  //Any error to report?
782  if(error)
783  return error;
784 
785  //Update the length of the PrivateKeyInfo structure
786  length += n;
787 
788  //Advance data pointer
789  if(output != NULL)
790  p += n;
791 
792  //Format PrivateKey field
793  error = pkcs8FormatEcPrivateKey(curveInfo, privateKey, publicKey, p, &n);
794  //Any error to report?
795  if(error)
796  return error;
797 
798  //Update the length of the PrivateKeyInfo structure
799  length += n;
800 
801  //The PrivateKeyInfo structure is encapsulated within a sequence
802  tag.constructed = TRUE;
805  tag.length = length;
806  tag.value = (uint8_t *) output;
807 
808  //Write the corresponding ASN.1 tag
809  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
810  //Any error to report?
811  if(error)
812  return error;
813 
814  //Get the length of the PrivateKeyInfo structure
815  n = tag.totalLength;
816 
817  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
818  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
819  //Any error to report?
820  if(error)
821  return error;
822 
823  //Total number of bytes that have been written
824  *written = n;
825 
826  //Successful processing
827  return NO_ERROR;
828 #else
829  //Not implemented
830  return ERROR_NOT_IMPLEMENTED;
831 #endif
832 }
833 
834 
835 /**
836  * @brief Export an EdDSA public key to PEM format
837  * @param[in] curveInfo Elliptic curve parameters
838  * @param[in] publicKey EdDSA public key
839  * @param[out] output Buffer where to store the PEM encoding
840  * @param[out] written Length of the resulting PEM encoding
841  * @return Error code
842  **/
843 
845  const EddsaPublicKey *publicKey, char_t *output, size_t *written)
846 {
847 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
848  error_t error;
849  size_t n;
850  X509SubjectPublicKeyInfo publicKeyInfo;
851 
852  //Check parameters
853  if(curveInfo == NULL || publicKey == NULL || written == NULL)
855 
856  //Clear the SubjectPublicKeyInfo structure
857  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
858 
859  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
860  //structure (refer to RFC 7468, section 13)
861  publicKeyInfo.oid.value = curveInfo->oid;
862  publicKeyInfo.oid.length = curveInfo->oidSize;
863 
864  //Format the SubjectPublicKeyInfo structure
865  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
866  (uint8_t *) output, &n);
867  //Any error to report?
868  if(error)
869  return error;
870 
871  //Public keys are encoded using the "PUBLIC KEY" label
872  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
873  //Any error to report?
874  if(error)
875  return error;
876 
877  //Total number of bytes that have been written
878  *written = n;
879 
880  //Successful processing
881  return NO_ERROR;
882 #else
883  //Not implemented
884  return ERROR_NOT_IMPLEMENTED;
885 #endif
886 }
887 
888 
889 /**
890  * @brief Export an EdDSA private key to PEM format
891  * @param[in] curveInfo Elliptic curve parameters
892  * @param[in] privateKey EdDSA private key
893  * @param[out] output Buffer where to store the PEM encoding
894  * @param[out] written Length of the resulting PEM encoding
895  * @return Error code
896  **/
897 
899  const EddsaPrivateKey *privateKey, char_t *output, size_t *written)
900 {
901 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
902  error_t error;
903  size_t n;
904  size_t length;
905  uint8_t *p;
906  Asn1Tag tag;
907  X509SubjectPublicKeyInfo publicKeyInfo;
908 
909  //Check parameters
910  if(curveInfo == NULL || privateKey == NULL || written == NULL)
912 
913  //Clear the SubjectPublicKeyInfo structure
914  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
915 
916  //Point to the buffer where to write the PrivateKeyInfo structure
917  p = (uint8_t *) output;
918  //Total length of the PrivateKeyInfo structure
919  length = 0;
920 
921  //Format Version field (refer to RFC 5208, section 5)
922  error = asn1WriteInt32(PKCS8_VERSION_1, FALSE, p, &n);
923  //Any error to report?
924  if(error)
925  return error;
926 
927  //Update the length of the PrivateKeyInfo structure
928  length += n;
929 
930  //Advance data pointer
931  if(output != NULL)
932  p += n;
933 
934  //The PrivateKeyAlgorithm identifies the private-key algorithm
935  publicKeyInfo.oid.value = curveInfo->oid;
936  publicKeyInfo.oid.length = curveInfo->oidSize;
937 
938  //Format PrivateKeyAlgorithm field
939  error = x509FormatAlgoId(&publicKeyInfo, NULL, p, &n);
940  //Any error to report?
941  if(error)
942  return error;
943 
944  //Update the length of the PrivateKeyInfo structure
945  length += n;
946 
947  //Advance data pointer
948  if(output != NULL)
949  p += n;
950 
951  //Format PrivateKey field
952  error = pkcs8FormatEddsaPrivateKey(curveInfo, privateKey, p, &n);
953  //Any error to report?
954  if(error)
955  return error;
956 
957  //Update the length of the PrivateKeyInfo structure
958  length += n;
959 
960  //The PrivateKeyInfo structure is encapsulated within a sequence
961  tag.constructed = TRUE;
964  tag.length = length;
965  tag.value = (uint8_t *) output;
966 
967  //Write the corresponding ASN.1 tag
968  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
969  //Any error to report?
970  if(error)
971  return error;
972 
973  //Get the length of the PrivateKeyInfo structure
974  n = tag.totalLength;
975 
976  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
977  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
978  //Any error to report?
979  if(error)
980  return error;
981 
982  //Total number of bytes that have been written
983  *written = n;
984 
985  //Successful processing
986  return NO_ERROR;
987 #else
988  //Not implemented
989  return ERROR_NOT_IMPLEMENTED;
990 #endif
991 }
992 
993 #endif
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:495
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
char char_t
Definition: compiler_port.h:48
General definitions for cryptographic algorithms.
Debugging facilities.
uint8_t n
const uint8_t DSA_OID[7]
Definition: dsa.c:51
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:43
error_t
Error codes.
Definition: error.h:43
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
MPI (Multiple Precision Integer Arithmetic)
uint8_t p
Definition: ndp.h:300
#define osMemset(p, value, length)
Definition: os_port.h:135
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
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:118
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
error_t pemExportEcParameters(const EcCurveInfo *curveInfo, char_t *output, size_t *written)
Export EC domain parameters to PEM format.
Definition: pem_export.c:627
error_t pemExportEddsaPublicKey(const EcCurveInfo *curveInfo, const EddsaPublicKey *publicKey, char_t *output, size_t *written)
Export an EdDSA public key to PEM format.
Definition: pem_export.c:844
error_t pemExportEcPrivateKey(const EcCurveInfo *curveInfo, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, char_t *output, size_t *written)
Export an EC private key to PEM format.
Definition: pem_export.c:736
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
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
error_t pemExportEcPublicKey(const EcCurveInfo *curveInfo, const EcPublicKey *publicKey, char_t *output, size_t *written)
Export an EC public key to PEM format.
Definition: pem_export.c:679
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
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
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
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_t pemExportEddsaPrivateKey(const EcCurveInfo *curveInfo, const EddsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an EdDSA private key to PEM format.
Definition: pem_export.c:898
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
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
PEM file export functions.
error_t pkcs8FormatRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an RSA private key.
error_t pkcs8FormatEcPrivateKey(const EcCurveInfo *curveInfo, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, uint8_t *output, size_t *written)
Format an EC private key.
error_t pkcs8FormatEddsaPrivateKey(const EcCurveInfo *curveInfo, const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EdDSA private key.
error_t pkcs8FormatDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format a DSA private key.
PKCS #8 key formatting.
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:57
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:88
ASN.1 tag.
Definition: asn1.h:102
size_t totalLength
Definition: asn1.h:108
const uint8_t * value
Definition: asn1.h:107
uint_t objClass
Definition: asn1.h:104
uint_t objType
Definition: asn1.h:105
bool_t constructed
Definition: asn1.h:103
size_t length
Definition: asn1.h:106
DSA private key.
Definition: dsa.h:72
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
DSA public key.
Definition: dsa.h:61
Elliptic curve parameters.
Definition: ec_curves.h:295
size_t oidSize
OID size.
Definition: ec_curves.h:298
const uint8_t * oid
Object identifier.
Definition: ec_curves.h:297
EC private key.
Definition: ec.h:104
EC public key.
Definition: ec.h:94
EdDSA private key.
Definition: eddsa.h:59
EdDSA public key.
Definition: eddsa.h:49
RSA private key.
Definition: rsa.h:68
RSA public key.
Definition: rsa.h:57
X509OctetString namedCurve
Definition: x509_common.h:764
const uint8_t * value
Definition: x509_common.h:647
Subject Public Key Information extension.
Definition: x509_common.h:783
X509OctetString oid
Definition: x509_common.h:785
X509EcParameters ecParams
Definition: x509_common.h:795
uint8_t length
Definition: tcp.h:368
X.509 certificate generation.
@ PKCS8_VERSION_1
Definition: x509_common.h:448
error_t x509FormatAlgoId(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *params, uint8_t *output, size_t *written)
Format AlgorithmIdentifier structure.
error_t x509FormatSubjectPublicKeyInfo(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
Format SubjectPublicKeyInfo structure.
Formatting of ASN.1 encoded keys.