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-2019 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 1.9.6
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 "encoding/base64.h"
42 #include "mpi/mpi.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (PEM_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Export an X.509 certificate to PEM format
51  * @param[in] cert Pointer to the DER-encoded certificate
52  * @param[in] certLen Length of the DER-encoded certificate, in bytes
53  * @param[out] output Buffer where to store the PEM encoding
54  * @param[out] written Length of the resulting PEM encoding
55  * @return Error code
56  **/
57 
58 error_t pemExportCertificate(const uint8_t *cert, size_t certLen,
59  char_t *output, size_t *written)
60 {
61  error_t error;
62  size_t n;
63 
64  //Check parameters
65  if(cert == NULL || written == NULL)
67 
68  //X.509 certificates are encoded using the "CERTIFICATE" label
69  error = pemEncodeFile(cert, certLen, "CERTIFICATE", output, &n);
70  //Any error to report?
71  if(error)
72  return error;
73 
74  //Total number of bytes that have been written
75  *written = n;
76 
77  //Successful processing
78  return NO_ERROR;
79 }
80 
81 
82 /**
83  * @brief Export a certificate revocation list to PEM format
84  * @param[in] crl Pointer to the DER-encoded CRL
85  * @param[in] crlLen Length of the DER-encoded CRL, in bytes
86  * @param[out] output Buffer where to store the PEM encoding
87  * @param[out] written Length of the resulting PEM encoding
88  * @return Error code
89  **/
90 
91 error_t pemExportCrl(const uint8_t *crl, size_t crlLen,
92  char_t *output, size_t *written)
93 {
94  error_t error;
95  size_t n;
96 
97  //Check parameters
98  if(crl == NULL || written == NULL)
100 
101  //CRLs are encoded using the "X509 CRL" label
102  error = pemEncodeFile(crl, crlLen, "X509 CRL", output, &n);
103  //Any error to report?
104  if(error)
105  return error;
106 
107  //Total number of bytes that have been written
108  *written = n;
109 
110  //Successful processing
111  return NO_ERROR;
112 }
113 
114 
115 /**
116  * @brief Export a certification signing request to PEM format
117  * @param[in] csr Pointer to the DER-encoded CSR
118  * @param[in] csrLen Length of the DER-encoded CSR, in bytes
119  * @param[out] output Buffer where to store the PEM encoding
120  * @param[out] written Length of the resulting PEM encoding
121  * @return Error code
122  **/
123 
124 error_t pemExportCsr(const uint8_t *csr, size_t csrLen,
125  char_t *output, size_t *written)
126 {
127  error_t error;
128  size_t n;
129 
130  //Check parameters
131  if(csr == NULL || written == NULL)
133 
134  //CSRs are encoded using the "CERTIFICATE REQUEST" label
135  error = pemEncodeFile(csr, csrLen, "CERTIFICATE REQUEST", output, &n);
136  //Any error to report?
137  if(error)
138  return error;
139 
140  //Total number of bytes that have been written
141  *written = n;
142 
143  //Successful processing
144  return NO_ERROR;
145 }
146 
147 
148 /**
149  * @brief Export an RSA public key to PEM format
150  * @param[in] publicKey RSA public key
151  * @param[out] output Buffer where to store the PEM encoding
152  * @param[out] written Length of the resulting PEM encoding
153  * @return Error code
154  **/
155 
157  char_t *output, size_t *written)
158 {
159 #if (RSA_SUPPORT == ENABLED)
160  error_t error;
161  size_t n;
162  X509SubjectPublicKeyInfo publicKeyInfo;
163 
164  //Check parameters
165  if(publicKey == NULL || written == NULL)
167 
168  //Clear the SubjectPublicKeyInfo structure
169  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
170 
171  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
172  //structure (refer to RFC 7468, section 13)
173  publicKeyInfo.oid = RSA_ENCRYPTION_OID;
174  publicKeyInfo.oidLen = sizeof(RSA_ENCRYPTION_OID);
175 
176  //Format the SubjectPublicKeyInfo structure
177  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
178  (uint8_t *) output, &n);
179  //Any error to report?
180  if(error)
181  return error;
182 
183  //Public keys are encoded using the "PUBLIC KEY" label
184  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
185  //Any error to report?
186  if(error)
187  return error;
188 
189  //Total number of bytes that have been written
190  *written = n;
191 
192  //Successful processing
193  return NO_ERROR;
194 #else
195  //Not implemented
196  return ERROR_NOT_IMPLEMENTED;
197 #endif
198 }
199 
200 
201 /**
202  * @brief Export an RSA private key to PEM format
203  * @param[in] privateKey RSA private key
204  * @param[out] output Buffer where to store the PEM encoding
205  * @param[out] written Length of the resulting PEM encoding
206  * @return Error code
207  **/
208 
210  char_t *output, size_t *written)
211 {
212 #if (RSA_SUPPORT == ENABLED)
213  error_t error;
214  size_t n;
215  size_t length;
216  uint8_t *p;
217  Asn1Tag tag;
218  X509SubjectPublicKeyInfo publicKeyInfo;
219 
220  //Check parameters
221  if(privateKey == NULL || written == NULL)
223 
224  //Clear the SubjectPublicKeyInfo structure
225  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
226 
227  //Point to the buffer where to write the PrivateKeyInfo structure
228  p = (uint8_t *) output;
229  //Total length of the PrivateKeyInfo structure
230  length = 0;
231 
232  //Format Version field (refer to RFC 5208, section 5)
233  error = asn1WriteInt32(0, FALSE, p, &n);
234  //Any error to report?
235  if(error)
236  return error;
237 
238  //Update the length of the PrivateKeyInfo structure
239  length += n;
240 
241  //Advance data pointer
242  if(output != NULL)
243  p += n;
244 
245  //The PrivateKeyAlgorithm identifies the private-key algorithm
246  publicKeyInfo.oid = RSA_ENCRYPTION_OID;
247  publicKeyInfo.oidLen = sizeof(RSA_ENCRYPTION_OID);
248 
249  //Format PrivateKeyAlgorithm field
250  error = x509FormatAlgorithmIdentifier(&publicKeyInfo, NULL, p, &n);
251  //Any error to report?
252  if(error)
253  return error;
254 
255  //Update the length of the PrivateKeyInfo structure
256  length += n;
257 
258  //Advance data pointer
259  if(output != NULL)
260  p += n;
261 
262  //Format PrivateKey field
263  error = pkcs8FormatRsaPrivateKey(privateKey, p, &n);
264  //Any error to report?
265  if(error)
266  return error;
267 
268  //Update the length of the PrivateKeyInfo structure
269  length += n;
270 
271  //The PrivateKeyInfo structure is encapsulated within a sequence
272  tag.constructed = TRUE;
275  tag.length = length;
276  tag.value = (uint8_t *) output;
277 
278  //Write the corresponding ASN.1 tag
279  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
280  //Any error to report?
281  if(error)
282  return error;
283 
284  //Get the length of the PrivateKeyInfo structure
285  n = tag.totalLength;
286 
287  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
288  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
289  //Any error to report?
290  if(error)
291  return error;
292 
293  //Total number of bytes that have been written
294  *written = n;
295 
296  //Successful processing
297  return NO_ERROR;
298 #else
299  //Not implemented
300  return ERROR_NOT_IMPLEMENTED;
301 #endif
302 }
303 
304 
305 /**
306  * @brief Export an RSA-PSS public key to PEM format
307  * @param[in] publicKey RSA-PSS public key
308  * @param[out] output Buffer where to store the PEM encoding
309  * @param[out] written Length of the resulting PEM encoding
310  * @return Error code
311  **/
312 
314  char_t *output, size_t *written)
315 {
316 #if (RSA_SUPPORT == ENABLED)
317  error_t error;
318  size_t n;
319  X509SubjectPublicKeyInfo publicKeyInfo;
320 
321  //Check parameters
322  if(publicKey == NULL || written == NULL)
324 
325  //Clear the SubjectPublicKeyInfo structure
326  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
327 
328  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
329  //structure (refer to RFC 7468, section 13)
330  publicKeyInfo.oid = RSASSA_PSS_OID;
331  publicKeyInfo.oidLen = sizeof(RSASSA_PSS_OID);
332 
333  //Format the SubjectPublicKeyInfo structure
334  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
335  (uint8_t *) output, &n);
336  //Any error to report?
337  if(error)
338  return error;
339 
340  //Public keys are encoded using the "PUBLIC KEY" label
341  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
342  //Any error to report?
343  if(error)
344  return error;
345 
346  //Total number of bytes that have been written
347  *written = n;
348 
349  //Successful processing
350  return NO_ERROR;
351 #else
352  //Not implemented
353  return ERROR_NOT_IMPLEMENTED;
354 #endif
355 }
356 
357 
358 /**
359  * @brief Export an RSA-PSS private key to PEM format
360  * @param[in] privateKey RSA-PSS private key
361  * @param[out] output Buffer where to store the PEM encoding
362  * @param[out] written Length of the resulting PEM encoding
363  * @return Error code
364  **/
365 
367  char_t *output, size_t *written)
368 {
369 #if (RSA_SUPPORT == ENABLED)
370  error_t error;
371  size_t n;
372  size_t length;
373  uint8_t *p;
374  Asn1Tag tag;
375  X509SubjectPublicKeyInfo publicKeyInfo;
376 
377  //Check parameters
378  if(privateKey == NULL || written == NULL)
380 
381  //Clear the SubjectPublicKeyInfo structure
382  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
383 
384  //Point to the buffer where to write the PrivateKeyInfo structure
385  p = (uint8_t *) output;
386  //Total length of the PrivateKeyInfo structure
387  length = 0;
388 
389  //Format Version field (refer to RFC 5208, section 5)
390  error = asn1WriteInt32(0, FALSE, p, &n);
391  //Any error to report?
392  if(error)
393  return error;
394 
395  //Update the length of the PrivateKeyInfo structure
396  length += n;
397 
398  //Advance data pointer
399  if(output != NULL)
400  p += n;
401 
402  //The PrivateKeyAlgorithm identifies the private-key algorithm
403  publicKeyInfo.oid = RSASSA_PSS_OID;
404  publicKeyInfo.oidLen = sizeof(RSASSA_PSS_OID);
405 
406  //Format PrivateKeyAlgorithm field
407  error = x509FormatAlgorithmIdentifier(&publicKeyInfo, NULL, p, &n);
408  //Any error to report?
409  if(error)
410  return error;
411 
412  //Update the length of the PrivateKeyInfo structure
413  length += n;
414 
415  //Advance data pointer
416  if(output != NULL)
417  p += n;
418 
419  //Format PrivateKey field
420  error = pkcs8FormatRsaPrivateKey(privateKey, p, &n);
421  //Any error to report?
422  if(error)
423  return error;
424 
425  //Update the length of the PrivateKeyInfo structure
426  length += n;
427 
428  //The PrivateKeyInfo structure is encapsulated within a sequence
429  tag.constructed = TRUE;
432  tag.length = length;
433  tag.value = (uint8_t *) output;
434 
435  //Write the corresponding ASN.1 tag
436  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
437  //Any error to report?
438  if(error)
439  return error;
440 
441  //Get the length of the PrivateKeyInfo structure
442  n = tag.totalLength;
443 
444  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
445  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
446  //Any error to report?
447  if(error)
448  return error;
449 
450  //Total number of bytes that have been written
451  *written = n;
452 
453  //Successful processing
454  return NO_ERROR;
455 #else
456  //Not implemented
457  return ERROR_NOT_IMPLEMENTED;
458 #endif
459 }
460 
461 
462 /**
463  * @brief Export a DSA public key to PEM format
464  * @param[in] publicKey DSA public key
465  * @param[out] output Buffer where to store the PEM encoding
466  * @param[out] written Length of the resulting PEM encoding
467  * @return Error code
468  **/
469 
471  char_t *output, size_t *written)
472 {
473 #if (DSA_SUPPORT == ENABLED)
474  error_t error;
475  size_t n;
476  X509SubjectPublicKeyInfo publicKeyInfo;
477 
478  //Check parameters
479  if(publicKey == NULL || written == NULL)
481 
482  //Clear the SubjectPublicKeyInfo structure
483  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
484 
485  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
486  //structure (refer to RFC 7468, section 13)
487  publicKeyInfo.oid = DSA_OID;
488  publicKeyInfo.oidLen = sizeof(DSA_OID);
489 
490  //Format the SubjectPublicKeyInfo structure
491  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
492  (uint8_t *) output, &n);
493  //Any error to report?
494  if(error)
495  return error;
496 
497  //Public keys are encoded using the "PUBLIC KEY" label
498  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
499  //Any error to report?
500  if(error)
501  return error;
502 
503  //Total number of bytes that have been written
504  *written = n;
505 
506  //Successful processing
507  return NO_ERROR;
508 #else
509  //Not implemented
510  return ERROR_NOT_IMPLEMENTED;
511 #endif
512 }
513 
514 
515 /**
516  * @brief Export a DSA private key to PEM format
517  * @param[in] privateKey DSA private key
518  * @param[out] output Buffer where to store the PEM encoding
519  * @param[out] written Length of the resulting PEM encoding
520  * @return Error code
521  **/
522 
524  char_t *output, size_t *written)
525 {
526 #if (DSA_SUPPORT == ENABLED)
527  error_t error;
528  size_t n;
529  size_t length;
530  uint8_t *p;
531  Asn1Tag tag;
532  DsaDomainParameters params;
533  X509SubjectPublicKeyInfo publicKeyInfo;
534 
535  //Check parameters
536  if(privateKey == NULL || written == NULL)
538 
539  //Clear the SubjectPublicKeyInfo structure
540  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
541 
542  //Point to the buffer where to write the PrivateKeyInfo structure
543  p = (uint8_t *) output;
544  //Total length of the PrivateKeyInfo structure
545  length = 0;
546 
547  //Format Version field (refer to RFC 5208, section 5)
548  error = asn1WriteInt32(0, FALSE, p, &n);
549  //Any error to report?
550  if(error)
551  return error;
552 
553  //Update the length of the PrivateKeyInfo structure
554  length += n;
555 
556  //Advance data pointer
557  if(output != NULL)
558  p += n;
559 
560  //Retrieve DSA domain parameters
561  params.p = privateKey->p;
562  params.q = privateKey->q;
563  params.g = privateKey->g;
564 
565  //The PrivateKeyAlgorithm identifies the private-key algorithm
566  publicKeyInfo.oid = DSA_OID;
567  publicKeyInfo.oidLen = sizeof(DSA_OID);
568 
569  //Format PrivateKeyAlgorithm field
570  error = x509FormatAlgorithmIdentifier(&publicKeyInfo, &params, p, &n);
571  //Any error to report?
572  if(error)
573  return error;
574 
575  //Update the length of the PrivateKeyInfo structure
576  length += n;
577 
578  //Advance data pointer
579  if(output != NULL)
580  p += n;
581 
582  //Format PrivateKey field
583  error = pkcs8FormatDsaPrivateKey(privateKey, p, &n);
584  //Any error to report?
585  if(error)
586  return error;
587 
588  //Update the length of the PrivateKeyInfo structure
589  length += n;
590 
591  //The PrivateKeyInfo structure is encapsulated within a sequence
592  tag.constructed = TRUE;
595  tag.length = length;
596  tag.value = (uint8_t *) output;
597 
598  //Write the corresponding ASN.1 tag
599  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
600  //Any error to report?
601  if(error)
602  return error;
603 
604  //Get the length of the PrivateKeyInfo structure
605  n = tag.totalLength;
606 
607  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
608  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
609  //Any error to report?
610  if(error)
611  return error;
612 
613  //Total number of bytes that have been written
614  *written = n;
615 
616  //Successful processing
617  return NO_ERROR;
618 #else
619  //Not implemented
620  return ERROR_NOT_IMPLEMENTED;
621 #endif
622 }
623 
624 
625 /**
626  * @brief Export EC domain parameters to PEM format
627  * @param[in] curveInfo Elliptic curve parameters
628  * @param[out] output Buffer where to store the PEM encoding
629  * @param[out] written Length of the resulting PEM encoding
630  * @return Error code
631  **/
632 
634  char_t *output, size_t *written)
635 {
636 #if (EC_SUPPORT == ENABLED)
637  error_t error;
638  size_t n;
639  Asn1Tag tag;
640 
641  //Check parameters
642  if(curveInfo == NULL || written == NULL)
644 
645  //Format ECParameters field
646  tag.constructed = FALSE;
649  tag.length = curveInfo->oidSize;
650  tag.value = curveInfo->oid;
651 
652  //Write the corresponding ASN.1 tag
653  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
654  //Any error to report?
655  if(error)
656  return error;
657 
658  //EC domain parameters are encoded using the "EC PARAMETERS" label
659  error = pemEncodeFile(output, n, "EC PARAMETERS", output, &n);
660  //Any error to report?
661  if(error)
662  return error;
663 
664  //Total number of bytes that have been written
665  *written = n;
666 
667  //Successful processing
668  return NO_ERROR;
669 #else
670  //Not implemented
671  return ERROR_NOT_IMPLEMENTED;
672 #endif
673 }
674 
675 
676 /**
677  * @brief Export an EC public key to PEM format
678  * @param[in] curveInfo Elliptic curve parameters
679  * @param[in] publicKey EC public key
680  * @param[out] output Buffer where to store the PEM encoding
681  * @param[out] written Length of the resulting PEM encoding
682  * @return Error code
683  **/
684 
686  const EcPoint *publicKey, char_t *output, size_t *written)
687 {
688 #if (EC_SUPPORT == ENABLED)
689  error_t error;
690  size_t n;
691  X509SubjectPublicKeyInfo publicKeyInfo;
692 
693  //Check parameters
694  if(curveInfo == NULL || publicKey == NULL || written == NULL)
696 
697  //Clear the SubjectPublicKeyInfo structure
698  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
699 
700  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
701  //structure (refer to RFC 7468, section 13)
702  publicKeyInfo.oid = EC_PUBLIC_KEY_OID;
703  publicKeyInfo.oidLen = sizeof(EC_PUBLIC_KEY_OID);
704  publicKeyInfo.ecParams.namedCurve = curveInfo->oid;
705  publicKeyInfo.ecParams.namedCurveLen = curveInfo->oidSize;
706 
707  //Format the SubjectPublicKeyInfo structure
708  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
709  (uint8_t *) output, &n);
710  //Any error to report?
711  if(error)
712  return error;
713 
714  //Public keys are encoded using the "PUBLIC KEY" label
715  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
716  //Any error to report?
717  if(error)
718  return error;
719 
720  //Total number of bytes that have been written
721  *written = n;
722 
723  //Successful processing
724  return NO_ERROR;
725 #else
726  //Not implemented
727  return ERROR_NOT_IMPLEMENTED;
728 #endif
729 }
730 
731 
732 /**
733  * @brief Export an EC private key to PEM format
734  * @param[in] curveInfo Elliptic curve parameters
735  * @param[in] privateKey EC private key
736  * @param[in] publicKey EC public key (optional parameter)
737  * @param[out] output Buffer where to store the PEM encoding
738  * @param[out] written Length of the resulting PEM encoding
739  * @return Error code
740  **/
741 
743  const Mpi *privateKey, const EcPoint *publicKey, char_t *output,
744  size_t *written)
745 {
746 #if (EC_SUPPORT == ENABLED)
747  error_t error;
748  size_t n;
749  size_t length;
750  uint8_t *p;
751  Asn1Tag tag;
752  X509SubjectPublicKeyInfo publicKeyInfo;
753 
754  //Check parameters
755  if(curveInfo == NULL || privateKey == NULL || written == NULL)
757 
758  //Clear the SubjectPublicKeyInfo structure
759  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
760 
761  //Point to the buffer where to write the PrivateKeyInfo structure
762  p = (uint8_t *) output;
763  //Total length of the PrivateKeyInfo structure
764  length = 0;
765 
766  //Format Version field (refer to RFC 5208, section 5)
767  error = asn1WriteInt32(0, FALSE, p, &n);
768  //Any error to report?
769  if(error)
770  return error;
771 
772  //Update the length of the PrivateKeyInfo structure
773  length += n;
774 
775  //Advance data pointer
776  if(output != NULL)
777  p += n;
778 
779  //The PrivateKeyAlgorithm identifies the private-key algorithm
780  publicKeyInfo.oid = EC_PUBLIC_KEY_OID;
781  publicKeyInfo.oidLen = sizeof(EC_PUBLIC_KEY_OID);
782  publicKeyInfo.ecParams.namedCurve = curveInfo->oid;
783  publicKeyInfo.ecParams.namedCurveLen = curveInfo->oidSize;
784 
785  //Format PrivateKeyAlgorithm field
786  error = x509FormatAlgorithmIdentifier(&publicKeyInfo, NULL, p, &n);
787  //Any error to report?
788  if(error)
789  return error;
790 
791  //Update the length of the PrivateKeyInfo structure
792  length += n;
793 
794  //Advance data pointer
795  if(output != NULL)
796  p += n;
797 
798  //Format PrivateKey field
799  error = pkcs8FormatEcPrivateKey(curveInfo, privateKey, publicKey, p, &n);
800  //Any error to report?
801  if(error)
802  return error;
803 
804  //Update the length of the PrivateKeyInfo structure
805  length += n;
806 
807  //The PrivateKeyInfo structure is encapsulated within a sequence
808  tag.constructed = TRUE;
811  tag.length = length;
812  tag.value = (uint8_t *) output;
813 
814  //Write the corresponding ASN.1 tag
815  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
816  //Any error to report?
817  if(error)
818  return error;
819 
820  //Get the length of the PrivateKeyInfo structure
821  n = tag.totalLength;
822 
823  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
824  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
825  //Any error to report?
826  if(error)
827  return error;
828 
829  //Total number of bytes that have been written
830  *written = n;
831 
832  //Successful processing
833  return NO_ERROR;
834 #else
835  //Not implemented
836  return ERROR_NOT_IMPLEMENTED;
837 #endif
838 }
839 
840 
841 /**
842  * @brief Export an EdDSA public key to PEM format
843  * @param[in] curveInfo Elliptic curve parameters
844  * @param[in] publicKey EdDSA public key
845  * @param[out] output Buffer where to store the PEM encoding
846  * @param[out] written Length of the resulting PEM encoding
847  * @return Error code
848  **/
849 
851  const EddsaPublicKey *publicKey, char_t *output, size_t *written)
852 {
853 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
854  error_t error;
855  size_t n;
856  X509SubjectPublicKeyInfo publicKeyInfo;
857 
858  //Check parameters
859  if(curveInfo == NULL || publicKey == NULL || written == NULL)
861 
862  //Clear the SubjectPublicKeyInfo structure
863  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
864 
865  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
866  //structure (refer to RFC 7468, section 13)
867  publicKeyInfo.oid = curveInfo->oid;
868  publicKeyInfo.oidLen = curveInfo->oidSize;
869 
870  //Format the SubjectPublicKeyInfo structure
871  error = x509FormatSubjectPublicKeyInfo(&publicKeyInfo, publicKey, NULL,
872  (uint8_t *) output, &n);
873  //Any error to report?
874  if(error)
875  return error;
876 
877  //Public keys are encoded using the "PUBLIC KEY" label
878  error = pemEncodeFile(output, n, "PUBLIC KEY", output, &n);
879  //Any error to report?
880  if(error)
881  return error;
882 
883  //Total number of bytes that have been written
884  *written = n;
885 
886  //Successful processing
887  return NO_ERROR;
888 #else
889  //Not implemented
890  return ERROR_NOT_IMPLEMENTED;
891 #endif
892 }
893 
894 
895 /**
896  * @brief Export an EdDSA private key to PEM format
897  * @param[in] curveInfo Elliptic curve parameters
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  const EddsaPrivateKey *privateKey, 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(curveInfo == NULL || privateKey == NULL || written == NULL)
918 
919  //Clear the SubjectPublicKeyInfo structure
920  cryptoMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
921 
922  //Point to the buffer where to write the PrivateKeyInfo structure
923  p = (uint8_t *) output;
924  //Total length of the PrivateKeyInfo structure
925  length = 0;
926 
927  //Format Version field (refer to RFC 5208, section 5)
928  error = asn1WriteInt32(0, FALSE, p, &n);
929  //Any error to report?
930  if(error)
931  return error;
932 
933  //Update the length of the PrivateKeyInfo structure
934  length += n;
935 
936  //Advance data pointer
937  if(output != NULL)
938  p += n;
939 
940  //The PrivateKeyAlgorithm identifies the private-key algorithm
941  publicKeyInfo.oid = curveInfo->oid;
942  publicKeyInfo.oidLen = curveInfo->oidSize;
943 
944  //Format PrivateKeyAlgorithm field
945  error = x509FormatAlgorithmIdentifier(&publicKeyInfo, NULL, p, &n);
946  //Any error to report?
947  if(error)
948  return error;
949 
950  //Update the length of the PrivateKeyInfo structure
951  length += n;
952 
953  //Advance data pointer
954  if(output != NULL)
955  p += n;
956 
957  //Format PrivateKey field
958  error = pkcs8FormatEddsaPrivateKey(curveInfo, privateKey, p, &n);
959  //Any error to report?
960  if(error)
961  return error;
962 
963  //Update the length of the PrivateKeyInfo structure
964  length += n;
965 
966  //The PrivateKeyInfo structure is encapsulated within a sequence
967  tag.constructed = TRUE;
970  tag.length = length;
971  tag.value = (uint8_t *) output;
972 
973  //Write the corresponding ASN.1 tag
974  error = asn1WriteTag(&tag, FALSE, (uint8_t *) output, &n);
975  //Any error to report?
976  if(error)
977  return error;
978 
979  //Get the length of the PrivateKeyInfo structure
980  n = tag.totalLength;
981 
982  //PKCS#8 private keys are encoded using the "PRIVATE KEY" label
983  error = pemEncodeFile(output, n, "PRIVATE KEY", output, &n);
984  //Any error to report?
985  if(error)
986  return error;
987 
988  //Total number of bytes that have been written
989  *written = n;
990 
991  //Successful processing
992  return NO_ERROR;
993 #else
994  //Not implemented
995  return ERROR_NOT_IMPLEMENTED;
996 #endif
997 }
998 
999 
1000 /**
1001  * @brief Convert ASN.1 data to PEM encoding
1002  * @param[in] input ASN.1 data to encode
1003  * @param[in] inputLen Length of the ASN.1 data to encode
1004  * @param[in] label Label indicating the type of data
1005  * @param[out] output PEM container (optional parameter)
1006  * @param[out] outputLen Length of the PEM container
1007  **/
1008 
1009 error_t pemEncodeFile(const void *input, size_t inputLen, const char_t *label,
1010  char_t *output, size_t *outputLen)
1011 {
1012  size_t n;
1013  size_t labelLen;
1014  char_t *p;
1015 
1016  //Check parameters
1017  if(input == NULL || label == NULL || outputLen == NULL)
1018  return ERROR_INVALID_PARAMETER;
1019 
1020  //Calculate the length of the label
1021  labelLen = cryptoStrlen(label);
1022 
1023  //Encode the ASN.1 data using Base64
1024  base64Encode(input, inputLen, output, &n);
1025 
1026  //If the output parameter is NULL, then the function calculates the
1027  //length of the resulting PEM file without copying any data
1028  if(output != NULL)
1029  {
1030  //A PEM file starts with a beginning tag
1031  p = output + cryptoStrlen("-----BEGIN -----\r\n") + labelLen;
1032 
1033  //Make room for the beginning tag
1034  cryptoMemmove(p, output, n);
1035 
1036  //The type of data encoded is labeled depending on the type label in
1037  //the "-----BEGIN " line (refer to RFC 7468, section 2)
1038  cryptoStrcpy(output, "-----BEGIN ");
1039  cryptoStrcpy(output + 11, label);
1040  cryptoStrncpy(p - 7, "-----\r\n", 7);
1041 
1042  //Generators must put the same label on the "-----END " line as the
1043  //corresponding "-----BEGIN " line
1044  cryptoStrcpy(p + n, "\r\n-----END ");
1045  cryptoStrcpy(p + n + 11, label);
1046  cryptoStrcpy(p + n + labelLen + 11, "-----\r\n");
1047  }
1048 
1049  //Consider the length of the PEM tags
1050  n += cryptoStrlen("-----BEGIN -----\r\n") + labelLen;
1051  n += cryptoStrlen("\r\n-----END -----\r\n") + labelLen;
1052 
1053  //Total number of bytes that have been written
1054  *outputLen = n;
1055 
1056  //Successful processing
1057  return NO_ERROR;
1058 }
1059 
1060 #endif
PKCS #8 key formatting.
uint8_t length
Definition: dtls_misc.h:149
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:904
const uint8_t * oid
Definition: x509_common.h:698
Arbitrary precision integer.
Definition: mpi.h:69
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:313
uint8_t p
Definition: ndp.h:298
Mpi q
Group order.
Definition: dsa.h:51
#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:523
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:47
void base64Encode(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Base64 encoding algorithm.
Definition: base64.c:78
X509EcParameters ecParams
Definition: x509_common.h:708
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_export.c:1009
error_t pkcs8FormatRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an RSA private key.
const uint8_t * oid
Object identifier.
Definition: ec_curves.h:295
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:91
Mpi p
Prime modulus.
Definition: dsa.h:50
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:88
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:104
size_t length
Definition: asn1.h:102
#define FALSE
Definition: os_port.h:46
Elliptic curve parameters.
Definition: ec_curves.h:292
DSA public key.
Definition: dsa.h:60
Invalid parameter.
Definition: error.h:47
#define cryptoStrlen(s)
Definition: crypto.h:660
X.509 certificate generation.
error_t
Error codes.
Definition: error.h:42
Mpi g
Group generator.
Definition: dsa.h:52
EdDSA public key.
Definition: eddsa.h:48
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:48
ASN.1 tag.
Definition: asn1.h:97
RSA public key.
Definition: rsa.h:48
DSA domain parameters.
Definition: dsa.h:48
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:124
MPI (Multiple Precision Integer Arithmetic)
General definitions for cryptographic algorithms.
#define cryptoMemmove(dest, src, length)
Definition: crypto.h:648
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:377
error_t pemExportRsaPrivateKey(const RsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an RSA private key to PEM format.
Definition: pem_export.c:209
Base64 encoding scheme.
DSA private key.
Definition: dsa.h:73
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:850
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:366
uint_t objClass
Definition: asn1.h:100
Elliptic curve point.
Definition: ec.h:51
size_t namedCurveLen
Definition: x509_common.h:675
Mpi p
Prime modulus.
Definition: dsa.h:75
Mpi g
Group generator.
Definition: dsa.h:77
EdDSA private key.
Definition: eddsa.h:58
PEM file export functions.
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:57
#define cryptoMemset(p, value, length)
Definition: crypto.h:636
char char_t
Definition: compiler_port.h:43
Formatting of ASN.1 encoded keys.
error_t x509FormatAlgorithmIdentifier(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *params, uint8_t *output, size_t *written)
Format AlgorithmIdentifier structure.
error_t pemExportEcParameters(const EcCurveInfo *curveInfo, char_t *output, size_t *written)
Export EC domain parameters to PEM format.
Definition: pem_export.c:633
error_t pemExportEcPublicKey(const EcCurveInfo *curveInfo, const EcPoint *publicKey, char_t *output, size_t *written)
Export an EC public key to PEM format.
Definition: pem_export.c:685
uint8_t n
RSA private key.
Definition: rsa.h:59
Subject public key information.
Definition: x509_common.h:694
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:58
#define cryptoStrncpy(s1, s2, length)
Definition: crypto.h:672
error_t pemExportEcPrivateKey(const EcCurveInfo *curveInfo, const Mpi *privateKey, const EcPoint *publicKey, char_t *output, size_t *written)
Export an EC private key to PEM format.
Definition: pem_export.c:742
bool_t constructed
Definition: asn1.h:99
error_t pkcs8FormatEcPrivateKey(const EcCurveInfo *curveInfo, const Mpi *privateKey, const EcPoint *publicKey, uint8_t *output, size_t *written)
Format an EC private key.
error_t pemExportDsaPublicKey(const DsaPublicKey *publicKey, char_t *output, size_t *written)
Export a DSA public key to PEM format.
Definition: pem_export.c:470
Mpi q
Group order.
Definition: dsa.h:76
size_t oidSize
OID size.
Definition: ec_curves.h:296
error_t pkcs8FormatEddsaPrivateKey(const EcCurveInfo *curveInfo, const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EdDSA private key.
#define cryptoStrcpy(s1, s2)
Definition: crypto.h:666
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:516
const uint8_t * namedCurve
Definition: x509_common.h:674
const uint8_t * value
Definition: asn1.h:103
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:156
Debugging facilities.
uint_t objType
Definition: asn1.h:101
ASN.1 (Abstract Syntax Notation One)