pem_import.c
Go to the documentation of this file.
1 /**
2  * @file pem_import.c
3  * @brief PEM file import 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_import.h"
37 #include "pkix/pem_decrypt.h"
38 #include "pkix/pkcs5_decrypt.h"
39 #include "pkix/pkcs8_key_parse.h"
40 #include "pkix/x509_key_parse.h"
41 #include "encoding/asn1.h"
42 #include "encoding/oid.h"
43 #include "mpi/mpi.h"
44 #include "debug.h"
45 
46 //Check crypto library configuration
47 #if (PEM_SUPPORT == ENABLED)
48 
49 
50 /**
51  * @brief Decode a PEM file containing a certificate
52  * @param[in] input Pointer to the PEM encoding
53  * @param[in] inputLen Length of the PEM structure
54  * @param[out] output Pointer to the DER-encoded certificate
55  * @param[out] outputLen Length of the DER-encoded certificate, in bytes
56  * @param[out] consumed Total number of characters that have been consumed
57  * (optional parameter)
58  * @return Error code
59  **/
60 
61 error_t pemImportCertificate(const char_t *input, size_t inputLen,
62  uint8_t *output, size_t *outputLen, size_t *consumed)
63 {
64  error_t error;
65 
66  //Check parameters
67  if(input == NULL && inputLen != 0)
69  if(outputLen == NULL)
71 
72  //X.509 certificates are encoded using the "CERTIFICATE" label
73  error = pemDecodeFile(input, inputLen, "CERTIFICATE", output, outputLen,
74  NULL, consumed);
75 
76  //Return status code
77  return error;
78 }
79 
80 
81 /**
82  * @brief Decode a PEM file containing a certificate revocation list
83  * @param[in] input Pointer to the PEM encoding
84  * @param[in] inputLen Length of the PEM structure
85  * @param[out] output Pointer to the DER-encoded CRL
86  * @param[out] outputLen Length of the DER-encoded CRL, in bytes
87  * @param[out] consumed Total number of characters that have been consumed
88  * (optional parameter)
89  * @return Error code
90  **/
91 
92 error_t pemImportCrl(const char_t *input, size_t inputLen,
93  uint8_t *output, size_t *outputLen, size_t *consumed)
94 {
95  error_t error;
96 
97  //Check parameters
98  if(input == NULL && inputLen != 0)
100  if(outputLen == NULL)
102 
103  //CRLs are encoded using the "X509 CRL" label
104  error = pemDecodeFile(input, inputLen, "X509 CRL", output, outputLen,
105  NULL, consumed);
106 
107  //Return status code
108  return error;
109 }
110 
111 
112 /**
113  * @brief Decode a PEM file containing a certification signing request
114  * @param[in] input Pointer to the PEM encoding
115  * @param[in] inputLen Length of the PEM structure
116  * @param[out] output Pointer to the DER-encoded CSR
117  * @param[out] outputLen Length of the DER-encoded CSR, in bytes
118  * @return Error code
119  **/
120 
121 error_t pemImportCsr(const char_t *input, size_t inputLen,
122  uint8_t *output, size_t *outputLen)
123 {
124  error_t error;
125 
126  //Check parameters
127  if(input == NULL && inputLen != 0)
129  if(outputLen == NULL)
131 
132  //CSRs are encoded using the "CERTIFICATE REQUEST" label
133  error = pemDecodeFile(input, inputLen, "CERTIFICATE REQUEST", output,
134  outputLen, NULL, NULL);
135 
136  //Return status code
137  return error;
138 }
139 
140 
141 /**
142  * @brief Decode a PEM file containing Diffie-Hellman parameters
143  * @param[in] input Pointer to the PEM encoding
144  * @param[in] length Length of the PEM encoding
145  * @param[out] params Diffie-Hellman parameters resulting from the parsing process
146  * @return Error code
147  **/
148 
150  DhParameters *params)
151 {
152 #if (DH_SUPPORT == ENABLED)
153  error_t error;
154  size_t n;
155  uint8_t *buffer;
156  const uint8_t *p;
157  Asn1Tag tag;
158 
159  //Check parameters
160  if(input == NULL && length != 0)
162  if(params == NULL)
164 
165  //Initialize variables
166  p = NULL;
167  n = 0;
168 
169  //Diffie-Hellman parameters are encoded using the "DH PARAMETERS" label
170  error = pemDecodeFile(input, length, "DH PARAMETERS", NULL, &n, NULL, NULL);
171 
172  //Check status code
173  if(!error)
174  {
175  //Allocate a memory buffer to hold the ASN.1 data
176  buffer = cryptoAllocMem(n);
177 
178  //Successful memory allocation?
179  if(buffer != NULL)
180  {
181  //Decode the content of the PEM container
182  error = pemDecodeFile(input, length, "DH PARAMETERS", buffer, &n,
183  NULL, NULL);
184 
185  //Check status code
186  if(!error)
187  {
188  //The Diffie-Hellman parameters are encapsulated within a sequence
189  error = asn1ReadSequence(buffer, n, &tag);
190  }
191 
192  //Check status code
193  if(!error)
194  {
195  //Point to the first field of the sequence
196  p = tag.value;
197  n = tag.length;
198 
199  //Read the prime modulus
200  error = asn1ReadMpi(p, n, &tag, &params->p);
201  }
202 
203  //Check status code
204  if(!error)
205  {
206  //Point to the next field
207  p += tag.totalLength;
208  n -= tag.totalLength;
209 
210  //Read the generator
211  error = asn1ReadMpi(p, n, &tag, &params->g);
212  }
213 
214  //Check status code
215  if(!error)
216  {
217  //Debug message
218  TRACE_DEBUG("Diffie-Hellman parameters:\r\n");
219  TRACE_DEBUG(" Prime modulus:\r\n");
220  TRACE_DEBUG_MPI(" ", &params->p);
221  TRACE_DEBUG(" Generator:\r\n");
222  TRACE_DEBUG_MPI(" ", &params->g);
223  }
224 
225  //Release previously allocated memory
226  cryptoFreeMem(buffer);
227  }
228  else
229  {
230  //Failed to allocate memory
231  error = ERROR_OUT_OF_MEMORY;
232  }
233  }
234 
235  //Any error to report?
236  if(error)
237  {
238  //Clean up side effects
239  mpiFree(&params->p);
240  mpiFree(&params->g);
241  }
242 
243  //Return status code
244  return error;
245 #else
246  //Not implemented
247  return ERROR_NOT_IMPLEMENTED;
248 #endif
249 }
250 
251 
252 /**
253  * @brief Decode a PEM file containing an RSA public key
254  * @param[in] input Pointer to the PEM encoding
255  * @param[in] length Length of the PEM encoding
256  * @param[out] publicKey RSA public key resulting from the parsing process
257  * @return Error code
258  **/
259 
261  RsaPublicKey *publicKey)
262 {
263 #if (RSA_SUPPORT == ENABLED)
264  error_t error;
265  size_t n;
266  uint8_t *buffer;
267  X509SubjectPublicKeyInfo publicKeyInfo;
268 
269  //Check parameters
270  if(input == NULL && length != 0)
272  if(publicKey == NULL)
274 
275  //Clear the SubjectPublicKeyInfo structure
276  osMemset(&publicKeyInfo, 0, sizeof(X509SubjectPublicKeyInfo));
277 
278  //The type of data encoded is labeled depending on the type label in
279  //the "-----BEGIN " line (refer to RFC 7468, section 2)
280  if(pemDecodeFile(input, length, "RSA PUBLIC KEY", NULL, &n, NULL,
281  NULL) == NO_ERROR)
282  {
283  //Allocate a memory buffer to hold the ASN.1 data
284  buffer = cryptoAllocMem(n);
285 
286  //Successful memory allocation?
287  if(buffer != NULL)
288  {
289  //Decode the content of the PEM container
290  error = pemDecodeFile(input, length, "RSA PUBLIC KEY", buffer, &n,
291  NULL, NULL);
292 
293  //Check status code
294  if(!error)
295  {
296  //Read RSAPublicKey structure
297  error = x509ParseRsaPublicKey(buffer, n, &publicKeyInfo.rsaPublicKey);
298  }
299 
300  //Check status code
301  if(!error)
302  {
303  //Set public key algorithm identifier
304  publicKeyInfo.oid.value = RSA_ENCRYPTION_OID;
305  publicKeyInfo.oid.length = sizeof(RSA_ENCRYPTION_OID);
306 
307  //Import the RSA public key
308  error = x509ImportRsaPublicKey(&publicKeyInfo, publicKey);
309  }
310 
311  //Release previously allocated memory
312  cryptoFreeMem(buffer);
313  }
314  else
315  {
316  //Failed to allocate memory
317  error = ERROR_OUT_OF_MEMORY;
318  }
319  }
320  else if(pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL,
321  NULL) == NO_ERROR)
322  {
323  //Allocate a memory buffer to hold the ASN.1 data
324  buffer = cryptoAllocMem(n);
325 
326  //Successful memory allocation?
327  if(buffer != NULL)
328  {
329  //Decode the content of the PEM container
330  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n,
331  NULL, NULL);
332 
333  //Check status code
334  if(!error)
335  {
336  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
337  //structure (refer to RFC 7468, section 13)
338  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
339  }
340 
341  //Check status code
342  if(!error)
343  {
344  //Import the RSA public key
345  error = x509ImportRsaPublicKey(&publicKeyInfo, publicKey);
346  }
347 
348  //Release previously allocated memory
349  cryptoFreeMem(buffer);
350  }
351  else
352  {
353  //Failed to allocate memory
354  error = ERROR_OUT_OF_MEMORY;
355  }
356  }
357  else
358  {
359  //The PEM file does not contain a valid public key
360  error = ERROR_END_OF_FILE;
361  }
362 
363  //Any error to report?
364  if(error)
365  {
366  //Clean up side effects
367  rsaFreePublicKey(publicKey);
368  }
369 
370  //Return status code
371  return error;
372 #else
373  //Not implemented
374  return ERROR_NOT_IMPLEMENTED;
375 #endif
376 }
377 
378 
379 /**
380  * @brief Decode a PEM file containing an RSA private key
381  * @param[in] input Pointer to the PEM encoding
382  * @param[in] length Length of the PEM encoding
383  * @param[in] password NULL-terminated string containing the password. This
384  * parameter is required if the private key is encrypted
385  * @param[out] privateKey RSA private key resulting from the parsing process
386  * @return Error code
387  **/
388 
390  const char_t *password, RsaPrivateKey *privateKey)
391 {
392 #if (RSA_SUPPORT == ENABLED)
393  error_t error;
394  size_t n;
395  uint8_t *buffer;
396  PemHeader header;
397  Pkcs8PrivateKeyInfo privateKeyInfo;
398 
399  //Check parameters
400  if(input == NULL && length != 0)
402  if(privateKey == NULL)
404 
405  //Clear the PrivateKeyInfo structure
406  osMemset(&privateKeyInfo, 0, sizeof(Pkcs8PrivateKeyInfo));
407 
408  //The type of data encoded is labeled depending on the type label in
409  //the "-----BEGIN " line (refer to RFC 7468, section 2)
410  if(pemDecodeFile(input, length, "RSA PRIVATE KEY", NULL, &n, NULL,
411  NULL) == NO_ERROR)
412  {
413  //Allocate a memory buffer to hold the ASN.1 data
414  buffer = cryptoAllocMem(n);
415 
416  //Successful memory allocation?
417  if(buffer != NULL)
418  {
419  //Decode the content of the PEM container
420  error = pemDecodeFile(input, length, "RSA PRIVATE KEY", buffer, &n,
421  &header, NULL);
422 
423  //Check status code
424  if(!error)
425  {
426  //Check whether the PEM file is encrypted
427  if(pemCompareString(&header.procType.type, "ENCRYPTED"))
428  {
429  //Perform decryption
430  error = pemDecryptMessage(&header, password, buffer, n,
431  buffer, &n);
432  }
433  }
434 
435  //Check status code
436  if(!error)
437  {
438  //Read RSAPrivateKey structure
439  error = pkcs8ParseRsaPrivateKey(buffer, n,
440  &privateKeyInfo.rsaPrivateKey);
441  }
442 
443  //Check status code
444  if(!error)
445  {
446  //Set private key algorithm identifier
447  privateKeyInfo.oid.value = RSA_ENCRYPTION_OID;
448  privateKeyInfo.oid.length = sizeof(RSA_ENCRYPTION_OID);
449 
450  //Import the RSA private key
451  error = pkcs8ImportRsaPrivateKey(&privateKeyInfo, privateKey);
452  }
453 
454  //Release previously allocated memory
455  cryptoFreeMem(buffer);
456  }
457  else
458  {
459  //Failed to allocate memory
460  error = ERROR_OUT_OF_MEMORY;
461  }
462  }
463  else if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
464  NULL) == NO_ERROR)
465  {
466  //Allocate a memory buffer to hold the ASN.1 data
467  buffer = cryptoAllocMem(n);
468 
469  //Successful memory allocation?
470  if(buffer != NULL)
471  {
472  //Decode the content of the PEM container
473  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
474  NULL, NULL);
475 
476  //Check status code
477  if(!error)
478  {
479  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
480  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
481  }
482 
483  //Check status code
484  if(!error)
485  {
486  //Import the RSA private key
487  error = pkcs8ImportRsaPrivateKey(&privateKeyInfo, privateKey);
488  }
489 
490  //Release previously allocated memory
491  cryptoFreeMem(buffer);
492  }
493  else
494  {
495  //Failed to allocate memory
496  error = ERROR_OUT_OF_MEMORY;
497  }
498  }
499  else if(pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", NULL, &n, NULL,
500  NULL) == NO_ERROR)
501  {
502 #if (PEM_ENCRYPTED_KEY_SUPPORT == ENABLED)
503  //Allocate a memory buffer to hold the ASN.1 data
504  buffer = cryptoAllocMem(n);
505 
506  //Successful memory allocation?
507  if(buffer != NULL)
508  {
509  uint8_t *data;
510  Pkcs8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
511 
512  //Decode the content of the PEM container
513  error = pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", buffer,
514  &n, NULL, NULL);
515 
516  //Check status code
517  if(!error)
518  {
519  //Read the EncryptedPrivateKeyInfo structure (refer to RFC 5208,
520  //section 6)
521  error = pkcs8ParseEncryptedPrivateKeyInfo(buffer, n,
522  &encryptedPrivateKeyInfo);
523  }
524 
525  //Check status code
526  if(!error)
527  {
528  //Point to the encrypted data
529  data = (uint8_t *) encryptedPrivateKeyInfo.encryptedData.value;
530  n = encryptedPrivateKeyInfo.encryptedData.length;
531 
532  //Decrypt the private key information
533  error = pkcs5Decrypt(&encryptedPrivateKeyInfo.encryptionAlgo,
534  password, data, n, data, &n);
535  }
536 
537  //Check status code
538  if(!error)
539  {
540  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
541  error = pkcs8ParsePrivateKeyInfo(data, n, &privateKeyInfo);
542  }
543 
544  //Check status code
545  if(!error)
546  {
547  //Import the RSA private key
548  error = pkcs8ImportRsaPrivateKey(&privateKeyInfo, privateKey);
549  }
550 
551  //Release previously allocated memory
552  cryptoFreeMem(buffer);
553  }
554  else
555  {
556  //Failed to allocate memory
557  error = ERROR_OUT_OF_MEMORY;
558  }
559 #else
560  //The PEM file contains an encrypted private key
561  error = ERROR_DECRYPTION_FAILED;
562 #endif
563  }
564  else
565  {
566  //The PEM file does not contain a valid private key
567  error = ERROR_END_OF_FILE;
568  }
569 
570  //Any error to report?
571  if(error)
572  {
573  //Clean up side effects
574  rsaFreePrivateKey(privateKey);
575  }
576 
577  //Return status code
578  return error;
579 #else
580  //Not implemented
581  return ERROR_NOT_IMPLEMENTED;
582 #endif
583 }
584 
585 
586 /**
587  * @brief Decode a PEM file containing a DSA public key
588  * @param[in] input Pointer to the PEM encoding
589  * @param[in] length Length of the PEM encoding
590  * @param[out] publicKey DSA public key resulting from the parsing process
591  * @return Error code
592  **/
593 
595  DsaPublicKey *publicKey)
596 {
597 #if (DSA_SUPPORT == ENABLED)
598  error_t error;
599  size_t n;
600  uint8_t *buffer;
601  X509SubjectPublicKeyInfo publicKeyInfo;
602 
603  //Check parameters
604  if(input == NULL && length != 0)
606  if(publicKey == NULL)
608 
609  //Public keys are encoded using the "PUBLIC KEY" label
610  error = pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL, NULL);
611 
612  //Check status code
613  if(!error)
614  {
615  //Allocate a memory buffer to hold the ASN.1 data
616  buffer = cryptoAllocMem(n);
617 
618  //Successful memory allocation?
619  if(buffer != NULL)
620  {
621  //Decode the content of the PEM container
622  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n, NULL,
623  NULL);
624 
625  //Check status code
626  if(!error)
627  {
628  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
629  //structure (refer to RFC 7468, section 13)
630  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
631  }
632 
633  //Check status code
634  if(!error)
635  {
636  //Import the DSA public key
637  error = x509ImportDsaPublicKey(&publicKeyInfo, publicKey);
638  }
639 
640  //Release previously allocated memory
641  cryptoFreeMem(buffer);
642  }
643  else
644  {
645  //Failed to allocate memory
646  error = ERROR_OUT_OF_MEMORY;
647  }
648  }
649 
650  //Any error to report?
651  if(error)
652  {
653  //Clean up side effects
654  dsaFreePublicKey(publicKey);
655  }
656 
657  //Return status code
658  return error;
659 #else
660  //Not implemented
661  return ERROR_NOT_IMPLEMENTED;
662 #endif
663 }
664 
665 
666 /**
667  * @brief Decode a PEM file containing a DSA private key
668  * @param[in] input Pointer to the PEM encoding
669  * @param[in] length Length of the PEM encoding
670  * @param[in] password NULL-terminated string containing the password. This
671  * parameter is required if the private key is encrypted
672  * @param[out] privateKey DSA private key resulting from the parsing process
673  * @return Error code
674  **/
675 
677  const char_t *password, DsaPrivateKey *privateKey)
678 {
679 #if (DSA_SUPPORT == ENABLED)
680  error_t error;
681  size_t n;
682  uint8_t *buffer;
683  PemHeader header;
684  Pkcs8PrivateKeyInfo privateKeyInfo;
685 
686  //Check parameters
687  if(input == NULL && length != 0)
689  if(privateKey == NULL)
691 
692  //Clear the PrivateKeyInfo structure
693  osMemset(&privateKeyInfo, 0, sizeof(Pkcs8PrivateKeyInfo));
694 
695  //The type of data encoded is labeled depending on the type label in
696  //the "-----BEGIN " line (refer to RFC 7468, section 2)
697  if(pemDecodeFile(input, length, "DSA PRIVATE KEY", NULL, &n, NULL,
698  NULL) == NO_ERROR)
699  {
700  //Allocate a memory buffer to hold the ASN.1 data
701  buffer = cryptoAllocMem(n);
702 
703  //Successful memory allocation?
704  if(buffer != NULL)
705  {
706  //Decode the content of the PEM container
707  error = pemDecodeFile(input, length, "DSA PRIVATE KEY", buffer, &n,
708  &header, NULL);
709 
710  //Check status code
711  if(!error)
712  {
713  //Check whether the PEM file is encrypted
714  if(pemCompareString(&header.procType.type, "ENCRYPTED"))
715  {
716  //Perform decryption
717  error = pemDecryptMessage(&header, password, buffer, n,
718  buffer, &n);
719  }
720  }
721 
722  //Check status code
723  if(!error)
724  {
725  //Read DSAPrivateKey structure
726  error = pkcs8ParseDsaPrivateKey(buffer, n, &privateKeyInfo.dsaParams,
727  &privateKeyInfo.dsaPrivateKey);
728  }
729 
730  //Check status code
731  if(!error)
732  {
733  //Set private key algorithm identifier
734  privateKeyInfo.oid.value = DSA_OID;
735  privateKeyInfo.oid.length = sizeof(DSA_OID);
736 
737  //Import the DSA private key
738  error = pkcs8ImportDsaPrivateKey(&privateKeyInfo, privateKey);
739  }
740 
741  //Release previously allocated memory
742  cryptoFreeMem(buffer);
743  }
744  else
745  {
746  //Failed to allocate memory
747  error = ERROR_OUT_OF_MEMORY;
748  }
749  }
750  else if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
751  NULL) == NO_ERROR)
752  {
753  //Allocate a memory buffer to hold the ASN.1 data
754  buffer = cryptoAllocMem(n);
755 
756  //Successful memory allocation?
757  if(buffer != NULL)
758  {
759  //Decode the content of the PEM container
760  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
761  NULL, NULL);
762 
763  //Check status code
764  if(!error)
765  {
766  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
767  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
768  }
769 
770  //Check status code
771  if(!error)
772  {
773  //Import the DSA private key
774  error = pkcs8ImportDsaPrivateKey(&privateKeyInfo, privateKey);
775  }
776 
777  //Release previously allocated memory
778  cryptoFreeMem(buffer);
779  }
780  else
781  {
782  //Failed to allocate memory
783  error = ERROR_OUT_OF_MEMORY;
784  }
785  }
786  else if(pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", NULL, &n, NULL,
787  NULL) == NO_ERROR)
788  {
789 #if (PEM_ENCRYPTED_KEY_SUPPORT == ENABLED)
790  //Allocate a memory buffer to hold the ASN.1 data
791  buffer = cryptoAllocMem(n);
792 
793  //Successful memory allocation?
794  if(buffer != NULL)
795  {
796  uint8_t *data;
797  Pkcs8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
798 
799  //Decode the content of the PEM container
800  error = pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", buffer,
801  &n, NULL, NULL);
802 
803  //Check status code
804  if(!error)
805  {
806  //Read the EncryptedPrivateKeyInfo structure (refer to RFC 5208,
807  //section 6)
808  error = pkcs8ParseEncryptedPrivateKeyInfo(buffer, n,
809  &encryptedPrivateKeyInfo);
810  }
811 
812  //Check status code
813  if(!error)
814  {
815  //Point to the encrypted data
816  data = (uint8_t *) encryptedPrivateKeyInfo.encryptedData.value;
817  n = encryptedPrivateKeyInfo.encryptedData.length;
818 
819  //Decrypt the private key information
820  error = pkcs5Decrypt(&encryptedPrivateKeyInfo.encryptionAlgo,
821  password, data, n, data, &n);
822  }
823 
824  //Check status code
825  if(!error)
826  {
827  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
828  error = pkcs8ParsePrivateKeyInfo(data, n, &privateKeyInfo);
829  }
830 
831  //Check status code
832  if(!error)
833  {
834  //Import the DSA private key
835  error = pkcs8ImportDsaPrivateKey(&privateKeyInfo, privateKey);
836  }
837 
838  //Release previously allocated memory
839  cryptoFreeMem(buffer);
840  }
841  else
842  {
843  //Failed to allocate memory
844  error = ERROR_OUT_OF_MEMORY;
845  }
846 #else
847  //The PEM file contains an encrypted private key
848  error = ERROR_DECRYPTION_FAILED;
849 #endif
850  }
851  else
852  {
853  //The PEM file does not contain a valid private key
854  error = ERROR_END_OF_FILE;
855  }
856 
857  //Any error to report?
858  if(error)
859  {
860  //Clean up side effects
861  dsaFreePrivateKey(privateKey);
862  }
863 
864  //Return status code
865  return error;
866 #else
867  //Not implemented
868  return ERROR_NOT_IMPLEMENTED;
869 #endif
870 }
871 
872 
873 /**
874  * @brief Decode a PEM file containing EC domain parameters
875  * @param[in] input Pointer to the PEM encoding
876  * @param[in] length Length of the PEM encoding
877  * @param[out] params EC domain parameters
878  * @return Error code
879  **/
880 
882  EcDomainParameters *params)
883 {
884 #if (EC_SUPPORT == ENABLED)
885  error_t error;
886  size_t n;
887  uint8_t *buffer;
888 
889  //Check parameters
890  if(input == NULL && length != 0)
892  if(params == NULL)
894 
895  //The type of data encoded is labeled depending on the type label in
896  //the "-----BEGIN " line (refer to RFC 7468, section 2)
897  if(pemDecodeFile(input, length, "EC PARAMETERS", NULL, &n, NULL,
898  NULL) == NO_ERROR)
899  {
900  X509EcParameters ecParams;
901 
902  //Allocate a memory buffer to hold the ASN.1 data
903  buffer = cryptoAllocMem(n);
904 
905  //Successful memory allocation?
906  if(buffer != NULL)
907  {
908  //Decode the content of the PEM container
909  error = pemDecodeFile(input, length, "EC PARAMETERS", buffer, &n,
910  NULL, NULL);
911 
912  //Check status code
913  if(!error)
914  {
915  //Parse ECParameters structure
916  error = x509ParseEcParameters(buffer, n, &ecParams);
917  }
918 
919  //Check status code
920  if(!error)
921  {
922  //Import the EC domain parameters
923  error = x509ImportEcParameters(&ecParams, params);
924  }
925 
926  //Release previously allocated memory
927  cryptoFreeMem(buffer);
928  }
929  else
930  {
931  //Failed to allocate memory
932  error = ERROR_OUT_OF_MEMORY;
933  }
934  }
935  else if(pemDecodeFile(input, length, "EC PRIVATE KEY", NULL, &n, NULL,
936  NULL) == NO_ERROR)
937  {
938  Pkcs8PrivateKeyInfo privateKeyInfo;
939 
940  //Allocate a memory buffer to hold the ASN.1 data
941  buffer = cryptoAllocMem(n);
942 
943  //Successful memory allocation?
944  if(buffer != NULL)
945  {
946  //Decode the content of the PEM container
947  error = pemDecodeFile(input, length, "EC PRIVATE KEY", buffer, &n,
948  NULL, NULL);
949 
950  //Check status code
951  if(!error)
952  {
953  //Read ECPrivateKey structure
954  error = pkcs8ParseEcPrivateKey(buffer, n, &privateKeyInfo.ecParams,
955  &privateKeyInfo.ecPrivateKey);
956  }
957 
958  //Check status code
959  if(!error)
960  {
961  //Import the EC domain parameters
962  error = x509ImportEcParameters(&privateKeyInfo.ecParams, params);
963  }
964 
965  //Release previously allocated memory
966  cryptoFreeMem(buffer);
967  }
968  else
969  {
970  //Failed to allocate memory
971  error = ERROR_OUT_OF_MEMORY;
972  }
973  }
974  else if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
975  NULL) == NO_ERROR)
976  {
977  Pkcs8PrivateKeyInfo privateKeyInfo;
978 
979  //Allocate a memory buffer to hold the ASN.1 data
980  buffer = cryptoAllocMem(n);
981 
982  //Successful memory allocation?
983  if(buffer != NULL)
984  {
985  //Decode the content of the PEM container
986  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
987  NULL, NULL);
988 
989  //Check status code
990  if(!error)
991  {
992  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
993  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
994  }
995 
996  //Check status code
997  if(!error)
998  {
999  //Import the EC domain parameters
1000  error = x509ImportEcParameters(&privateKeyInfo.ecParams, params);
1001  }
1002 
1003  //Release previously allocated memory
1004  cryptoFreeMem(buffer);
1005  }
1006  else
1007  {
1008  //Failed to allocate memory
1009  error = ERROR_OUT_OF_MEMORY;
1010  }
1011  }
1012  else if(pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL,
1013  NULL) == NO_ERROR)
1014  {
1015  X509SubjectPublicKeyInfo publicKeyInfo;
1016 
1017  //Allocate a memory buffer to hold the ASN.1 data
1018  buffer = cryptoAllocMem(n);
1019 
1020  //Successful memory allocation?
1021  if(buffer != NULL)
1022  {
1023  //Decode the content of the PEM container
1024  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n,
1025  NULL, NULL);
1026 
1027  //Check status code
1028  if(!error)
1029  {
1030  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
1031  //structure (refer to RFC 7468, section 13)
1032  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
1033  }
1034 
1035  //Check status code
1036  if(!error)
1037  {
1038  //Import the EC domain parameters
1039  error = x509ImportEcParameters(&publicKeyInfo.ecParams, params);
1040  }
1041 
1042  //Release previously allocated memory
1043  cryptoFreeMem(buffer);
1044  }
1045  else
1046  {
1047  //Failed to allocate memory
1048  error = ERROR_OUT_OF_MEMORY;
1049  }
1050  }
1051  else
1052  {
1053  //The PEM file does not contain valid EC domain parameters
1054  error = ERROR_END_OF_FILE;
1055  }
1056 
1057  //Any error to report?
1058  if(error)
1059  {
1060  //Clean up side effects
1061  ecFreeDomainParameters(params);
1062  }
1063 
1064  //Return status code
1065  return error;
1066 #else
1067  //Not implemented
1068  return ERROR_NOT_IMPLEMENTED;
1069 #endif
1070 }
1071 
1072 
1073 /**
1074  * @brief Decode a PEM file containing an EC public key
1075  * @param[in] input Pointer to the PEM encoding
1076  * @param[in] length Length of the PEM encoding
1077  * @param[out] publicKey EC public key resulting from the parsing process
1078  * @return Error code
1079  **/
1080 
1082  EcPublicKey *publicKey)
1083 {
1084 #if (EC_SUPPORT == ENABLED)
1085  error_t error;
1086  size_t n;
1087  uint8_t *buffer;
1088  X509SubjectPublicKeyInfo publicKeyInfo;
1089 
1090  //Check parameters
1091  if(input == NULL && length != 0)
1092  return ERROR_INVALID_PARAMETER;
1093  if(publicKey == NULL)
1094  return ERROR_INVALID_PARAMETER;
1095 
1096  //Public keys are encoded using the "PUBLIC KEY" label
1097  error = pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL, NULL);
1098 
1099  //Check status code
1100  if(!error)
1101  {
1102  //Allocate a memory buffer to hold the ASN.1 data
1103  buffer = cryptoAllocMem(n);
1104 
1105  //Successful memory allocation?
1106  if(buffer != NULL)
1107  {
1108  //Decode the content of the PEM container
1109  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n, NULL,
1110  NULL);
1111 
1112  //Check status code
1113  if(!error)
1114  {
1115  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
1116  //structure (refer to RFC 7468, section 13)
1117  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
1118  }
1119 
1120  //Check status code
1121  if(!error)
1122  {
1123  //Import the EC public key
1124  error = x509ImportEcPublicKey(&publicKeyInfo, publicKey);
1125  }
1126 
1127  //Release previously allocated memory
1128  cryptoFreeMem(buffer);
1129  }
1130  else
1131  {
1132  //Failed to allocate memory
1133  error = ERROR_OUT_OF_MEMORY;
1134  }
1135  }
1136 
1137  //Any error to report?
1138  if(error)
1139  {
1140  //Clean up side effects
1141  ecFreePublicKey(publicKey);
1142  }
1143 
1144  //Return status code
1145  return error;
1146 #else
1147  //Not implemented
1148  return ERROR_NOT_IMPLEMENTED;
1149 #endif
1150 }
1151 
1152 
1153 /**
1154  * @brief Decode a PEM file containing an EC private key
1155  * @param[in] input Pointer to the PEM encoding
1156  * @param[in] length Length of the PEM encoding
1157  * @param[in] password NULL-terminated string containing the password. This
1158  * parameter is required if the private key is encrypted
1159  * @param[out] privateKey EC private key resulting from the parsing process
1160  * @return Error code
1161  **/
1162 
1164  const char_t *password, EcPrivateKey *privateKey)
1165 {
1166 #if (EC_SUPPORT == ENABLED)
1167  error_t error;
1168  size_t n;
1169  uint8_t *buffer;
1170  PemHeader header;
1171  Pkcs8PrivateKeyInfo privateKeyInfo;
1172 
1173  //Check parameters
1174  if(input == NULL && length != 0)
1175  return ERROR_INVALID_PARAMETER;
1176  if(privateKey == NULL)
1177  return ERROR_INVALID_PARAMETER;
1178 
1179  //Clear the PrivateKeyInfo structure
1180  osMemset(&privateKeyInfo, 0, sizeof(Pkcs8PrivateKeyInfo));
1181 
1182  //The type of data encoded is labeled depending on the type label in
1183  //the "-----BEGIN " line (refer to RFC 7468, section 2)
1184  if(pemDecodeFile(input, length, "EC PRIVATE KEY", NULL, &n, NULL,
1185  NULL) == NO_ERROR)
1186  {
1187  //Allocate a memory buffer to hold the ASN.1 data
1188  buffer = cryptoAllocMem(n);
1189 
1190  //Successful memory allocation?
1191  if(buffer != NULL)
1192  {
1193  //Decode the content of the PEM container
1194  error = pemDecodeFile(input, length, "EC PRIVATE KEY", buffer, &n,
1195  &header, NULL);
1196 
1197  //Check status code
1198  if(!error)
1199  {
1200  //Check whether the PEM file is encrypted
1201  if(pemCompareString(&header.procType.type, "ENCRYPTED"))
1202  {
1203  //Perform decryption
1204  error = pemDecryptMessage(&header, password, buffer, n,
1205  buffer, &n);
1206  }
1207  }
1208 
1209  //Check status code
1210  if(!error)
1211  {
1212  //Read ECPrivateKey structure
1213  error = pkcs8ParseEcPrivateKey(buffer, n, &privateKeyInfo.ecParams,
1214  &privateKeyInfo.ecPrivateKey);
1215  }
1216 
1217  //Check status code
1218  if(!error)
1219  {
1220  //Set public key algorithm identifier
1221  privateKeyInfo.oid.value = EC_PUBLIC_KEY_OID;
1222  privateKeyInfo.oid.length = sizeof(EC_PUBLIC_KEY_OID);
1223 
1224  //Import the EC private key
1225  error = pkcs8ImportEcPrivateKey(&privateKeyInfo, privateKey);
1226  }
1227 
1228  //Release previously allocated memory
1229  cryptoFreeMem(buffer);
1230  }
1231  else
1232  {
1233  //Failed to allocate memory
1234  error = ERROR_OUT_OF_MEMORY;
1235  }
1236  }
1237  else if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
1238  NULL) == NO_ERROR)
1239  {
1240  //Allocate a memory buffer to hold the ASN.1 data
1241  buffer = cryptoAllocMem(n);
1242 
1243  //Successful memory allocation?
1244  if(buffer != NULL)
1245  {
1246  //Decode the content of the PEM container
1247  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
1248  NULL, NULL);
1249 
1250  //Check status code
1251  if(!error)
1252  {
1253  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
1254  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
1255  }
1256 
1257  //Check status code
1258  if(!error)
1259  {
1260  //Import the EC private key
1261  error = pkcs8ImportEcPrivateKey(&privateKeyInfo, privateKey);
1262  }
1263 
1264  //Release previously allocated memory
1265  cryptoFreeMem(buffer);
1266  }
1267  else
1268  {
1269  //Failed to allocate memory
1270  error = ERROR_OUT_OF_MEMORY;
1271  }
1272  }
1273  else if(pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", NULL, &n, NULL,
1274  NULL) == NO_ERROR)
1275  {
1276 #if (PEM_ENCRYPTED_KEY_SUPPORT == ENABLED)
1277  //Allocate a memory buffer to hold the ASN.1 data
1278  buffer = cryptoAllocMem(n);
1279 
1280  //Successful memory allocation?
1281  if(buffer != NULL)
1282  {
1283  uint8_t *data;
1284  Pkcs8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
1285 
1286  //Decode the content of the PEM container
1287  error = pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", buffer, &n,
1288  NULL, NULL);
1289 
1290  //Check status code
1291  if(!error)
1292  {
1293  //Read the EncryptedPrivateKeyInfo structure (refer to RFC 5208,
1294  //section 6)
1295  error = pkcs8ParseEncryptedPrivateKeyInfo(buffer, n,
1296  &encryptedPrivateKeyInfo);
1297  }
1298 
1299  //Check status code
1300  if(!error)
1301  {
1302  //Point to the encrypted data
1303  data = (uint8_t *) encryptedPrivateKeyInfo.encryptedData.value;
1304  n = encryptedPrivateKeyInfo.encryptedData.length;
1305 
1306  //Decrypt the private key information
1307  error = pkcs5Decrypt(&encryptedPrivateKeyInfo.encryptionAlgo,
1308  password, data, n, data, &n);
1309  }
1310 
1311  //Check status code
1312  if(!error)
1313  {
1314  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
1315  error = pkcs8ParsePrivateKeyInfo(data, n, &privateKeyInfo);
1316  }
1317 
1318  //Check status code
1319  if(!error)
1320  {
1321  //Import the EC private key
1322  error = pkcs8ImportEcPrivateKey(&privateKeyInfo, privateKey);
1323  }
1324 
1325  //Release previously allocated memory
1326  cryptoFreeMem(buffer);
1327  }
1328  else
1329  {
1330  //Failed to allocate memory
1331  error = ERROR_OUT_OF_MEMORY;
1332  }
1333 #else
1334  //The PEM file contains an encrypted private key
1335  error = ERROR_DECRYPTION_FAILED;
1336 #endif
1337  }
1338  else
1339  {
1340  //The PEM file does not contain a valid private key
1341  error = ERROR_END_OF_FILE;
1342  }
1343 
1344  //Any error to report?
1345  if(error)
1346  {
1347  //Clean up side effects
1348  ecFreePrivateKey(privateKey);
1349  }
1350 
1351  //Return status code
1352  return error;
1353 #else
1354  //Not implemented
1355  return ERROR_NOT_IMPLEMENTED;
1356 #endif
1357 }
1358 
1359 
1360 /**
1361  * @brief Decode a PEM file containing a EdDSA public key
1362  * @param[in] input Pointer to the PEM encoding
1363  * @param[in] length Length of the PEM encoding
1364  * @param[out] publicKey EdDSA public key resulting from the parsing process
1365  * @return Error code
1366  **/
1367 
1369  EddsaPublicKey *publicKey)
1370 {
1371 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
1372  error_t error;
1373  size_t n;
1374  uint8_t *buffer;
1375  X509SubjectPublicKeyInfo publicKeyInfo;
1376 
1377  //Check parameters
1378  if(input == NULL && length != 0)
1379  return ERROR_INVALID_PARAMETER;
1380  if(publicKey == NULL)
1381  return ERROR_INVALID_PARAMETER;
1382 
1383  //Public keys are encoded using the "PUBLIC KEY" label
1384  error = pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL, NULL);
1385 
1386  //Check status code
1387  if(!error)
1388  {
1389  //Allocate a memory buffer to hold the ASN.1 data
1390  buffer = cryptoAllocMem(n);
1391 
1392  //Successful memory allocation?
1393  if(buffer != NULL)
1394  {
1395  //Decode the content of the PEM container
1396  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n, NULL,
1397  NULL);
1398 
1399  //Check status code
1400  if(!error)
1401  {
1402  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
1403  //structure (refer to RFC 7468, section 13)
1404  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
1405  }
1406 
1407  //Check status code
1408  if(!error)
1409  {
1410  //Import the EdDSA public key
1411  error = x509ImportEddsaPublicKey(&publicKeyInfo, publicKey);
1412  }
1413 
1414  //Release previously allocated memory
1415  cryptoFreeMem(buffer);
1416  }
1417  else
1418  {
1419  //Failed to allocate memory
1420  error = ERROR_OUT_OF_MEMORY;
1421  }
1422  }
1423 
1424  //Any error to report?
1425  if(error)
1426  {
1427  //Clean up side effects
1428  eddsaFreePublicKey(publicKey);
1429  }
1430 
1431  //Return status code
1432  return error;
1433 #else
1434  //Not implemented
1435  return ERROR_NOT_IMPLEMENTED;
1436 #endif
1437 }
1438 
1439 
1440 /**
1441  * @brief Decode a PEM file containing a EdDSA private key
1442  * @param[in] input Pointer to the PEM encoding
1443  * @param[in] length Length of the PEM encoding
1444  * @param[in] password NULL-terminated string containing the password. This
1445  * parameter is required if the private key is encrypted
1446  * @param[out] privateKey EdDSA private key resulting from the parsing process
1447  * @return Error code
1448  **/
1449 
1451  const char_t *password, EddsaPrivateKey *privateKey)
1452 {
1453 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
1454  error_t error;
1455  size_t n;
1456  uint8_t *buffer;
1457  Pkcs8PrivateKeyInfo privateKeyInfo;
1458 
1459  //Check parameters
1460  if(input == NULL && length != 0)
1461  return ERROR_INVALID_PARAMETER;
1462  if(privateKey == NULL)
1463  return ERROR_INVALID_PARAMETER;
1464 
1465  //The type of data encoded is labeled depending on the type label in
1466  //the "-----BEGIN " line (refer to RFC 7468, section 2)
1467  if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
1468  NULL) == NO_ERROR)
1469  {
1470  //Allocate a memory buffer to hold the ASN.1 data
1471  buffer = cryptoAllocMem(n);
1472 
1473  //Successful memory allocation?
1474  if(buffer != NULL)
1475  {
1476  //Decode the content of the PEM container
1477  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
1478  NULL, NULL);
1479 
1480  //Check status code
1481  if(!error)
1482  {
1483  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
1484  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
1485  }
1486 
1487  //Check status code
1488  if(!error)
1489  {
1490  //Import the EdDSA private key
1491  error = pkcs8ImportEddsaPrivateKey(&privateKeyInfo, privateKey);
1492  }
1493 
1494  //Release previously allocated memory
1495  cryptoFreeMem(buffer);
1496  }
1497  else
1498  {
1499  //Failed to allocate memory
1500  error = ERROR_OUT_OF_MEMORY;
1501  }
1502  }
1503  else if(pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", NULL, &n, NULL,
1504  NULL) == NO_ERROR)
1505  {
1506 #if (PEM_ENCRYPTED_KEY_SUPPORT == ENABLED)
1507  //Allocate a memory buffer to hold the ASN.1 data
1508  buffer = cryptoAllocMem(n);
1509 
1510  //Successful memory allocation?
1511  if(buffer != NULL)
1512  {
1513  uint8_t *data;
1514  Pkcs8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo;
1515 
1516  //Decode the content of the PEM container
1517  error = pemDecodeFile(input, length, "ENCRYPTED PRIVATE KEY", buffer, &n,
1518  NULL, NULL);
1519 
1520  //Check status code
1521  if(!error)
1522  {
1523  //Read the EncryptedPrivateKeyInfo structure (refer to RFC 5208,
1524  //section 6)
1525  error = pkcs8ParseEncryptedPrivateKeyInfo(buffer, n,
1526  &encryptedPrivateKeyInfo);
1527  }
1528 
1529  //Check status code
1530  if(!error)
1531  {
1532  //Point to the encrypted data
1533  data = (uint8_t *) encryptedPrivateKeyInfo.encryptedData.value;
1534  n = encryptedPrivateKeyInfo.encryptedData.length;
1535 
1536  //Decrypt the private key information
1537  error = pkcs5Decrypt(&encryptedPrivateKeyInfo.encryptionAlgo,
1538  password, data, n, data, &n);
1539  }
1540 
1541  //Check status code
1542  if(!error)
1543  {
1544  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
1545  error = pkcs8ParsePrivateKeyInfo(data, n, &privateKeyInfo);
1546  }
1547 
1548  //Check status code
1549  if(!error)
1550  {
1551  //Import the EdDSA private key
1552  error = pkcs8ImportEddsaPrivateKey(&privateKeyInfo, privateKey);
1553  }
1554 
1555  //Release previously allocated memory
1556  cryptoFreeMem(buffer);
1557  }
1558  else
1559  {
1560  //Failed to allocate memory
1561  error = ERROR_OUT_OF_MEMORY;
1562  }
1563 #else
1564  //The PEM file contains an encrypted private key
1565  error = ERROR_DECRYPTION_FAILED;
1566 #endif
1567  }
1568  else
1569  {
1570  //The PEM file does not contain a valid private key
1571  error = ERROR_END_OF_FILE;
1572  }
1573 
1574  //Any error to report?
1575  if(error)
1576  {
1577  //Clean up side effects
1578  eddsaFreePrivateKey(privateKey);
1579  }
1580 
1581  //Return status code
1582  return error;
1583 #else
1584  //Not implemented
1585  return ERROR_NOT_IMPLEMENTED;
1586 #endif
1587 }
1588 
1589 
1590 /**
1591  * @brief Retrieve the type of a PEM-encoded public key
1592  * @param[in] input Pointer to the PEM encoding
1593  * @param[in] length Length of the PEM encoding
1594  * @param[out] keyType Public key type
1595  * @return Error code
1596  **/
1597 
1599  X509KeyType *keyType)
1600 {
1601  error_t error;
1602  size_t n;
1603  uint8_t *buffer;
1604  X509SubjectPublicKeyInfo publicKeyInfo;
1605 
1606  //Check parameters
1607  if(input == NULL && length != 0)
1608  return ERROR_INVALID_PARAMETER;
1609  if(keyType == NULL)
1610  return ERROR_INVALID_PARAMETER;
1611 
1612  //Initialize status code
1613  error = NO_ERROR;
1614 
1615  //Default public key type
1616  *keyType = X509_KEY_TYPE_UNKNOWN;
1617 
1618 #if (RSA_SUPPORT == ENABLED)
1619  //PEM container with "RSA PUBLIC KEY" label?
1620  if(pemDecodeFile(input, length, "RSA PUBLIC KEY", NULL, &n, NULL,
1621  NULL) == NO_ERROR)
1622  {
1623  //The PEM file contains an RSA public key (PKCS #1 format)
1624  *keyType = X509_KEY_TYPE_RSA;
1625  }
1626  else
1627 #endif
1628  //PEM container with "PUBLIC KEY" label?
1629  if(pemDecodeFile(input, length, "PUBLIC KEY", NULL, &n, NULL,
1630  NULL) == NO_ERROR)
1631  {
1632  //Allocate a memory buffer to hold the ASN.1 data
1633  buffer = cryptoAllocMem(n);
1634 
1635  //Successful memory allocation?
1636  if(buffer != NULL)
1637  {
1638  //Decode the content of the PEM container
1639  error = pemDecodeFile(input, length, "PUBLIC KEY", buffer, &n,
1640  NULL, NULL);
1641 
1642  //Check status code
1643  if(!error)
1644  {
1645  //The ASN.1 encoded data of the public key is the SubjectPublicKeyInfo
1646  //structure (refer to RFC 7468, section 13)
1647  error = x509ParseSubjectPublicKeyInfo(buffer, n, &n, &publicKeyInfo);
1648  }
1649 
1650  //Check status code
1651  if(!error)
1652  {
1653  //Check public key algorithm identifier
1654  *keyType = x509GetPublicKeyType(publicKeyInfo.oid.value,
1655  publicKeyInfo.oid.length);
1656 
1657 #if (EC_SUPPORT == ENABLED)
1658  //EC public key identifier?
1659  if(*keyType == X509_KEY_TYPE_EC)
1660  {
1661  //SM2 elliptic curve?
1662  if(!oidComp(publicKeyInfo.ecParams.namedCurve.value,
1663  publicKeyInfo.ecParams.namedCurve.length, SM2_OID,
1664  sizeof(SM2_OID)))
1665  {
1666  //The PEM file contains an SM2 public key
1667  *keyType = X509_KEY_TYPE_SM2;
1668  }
1669  }
1670 #endif
1671  //Unknown algorithm identifier?
1672  if(*keyType == X509_KEY_TYPE_UNKNOWN)
1673  {
1674  //Report an error
1675  error = ERROR_WRONG_IDENTIFIER;
1676  }
1677  }
1678 
1679  //Release previously allocated memory
1680  cryptoFreeMem(buffer);
1681  }
1682  else
1683  {
1684  //Failed to allocate memory
1685  error = ERROR_OUT_OF_MEMORY;
1686  }
1687  }
1688  else
1689  {
1690  //The PEM file does not contain a valid public key
1691  error = ERROR_END_OF_FILE;
1692  }
1693 
1694  //Return status code
1695  return error;
1696 }
1697 
1698 
1699 /**
1700  * @brief Retrieve the type of a PEM-encoded private key
1701  * @param[in] input Pointer to the PEM encoding
1702  * @param[in] length Length of the PEM encoding
1703  * @param[out] keyType Private key type
1704  * @return Error code
1705  **/
1706 
1708  X509KeyType *keyType)
1709 {
1710  error_t error;
1711  size_t n;
1712  uint8_t *buffer;
1713  Pkcs8PrivateKeyInfo privateKeyInfo;
1714 
1715  //Check parameters
1716  if(input == NULL && length != 0)
1717  return ERROR_INVALID_PARAMETER;
1718  if(keyType == NULL)
1719  return ERROR_INVALID_PARAMETER;
1720 
1721  //Initialize status code
1722  error = NO_ERROR;
1723 
1724  //Default private key type
1725  *keyType = X509_KEY_TYPE_UNKNOWN;
1726 
1727 #if (RSA_SUPPORT == ENABLED)
1728  //PEM container with "RSA PRIVATE KEY" label?
1729  if(pemDecodeFile(input, length, "RSA PRIVATE KEY", NULL, &n, NULL,
1730  NULL) == NO_ERROR)
1731  {
1732  //The PEM file contains an RSA private key (PKCS #1 format)
1733  *keyType = X509_KEY_TYPE_RSA;
1734  }
1735  else
1736 #endif
1737 #if (DSA_SUPPORT == ENABLED)
1738  //PEM container with "DSA PRIVATE KEY" label?
1739  if(pemDecodeFile(input, length, "DSA PRIVATE KEY", NULL, &n, NULL,
1740  NULL) == NO_ERROR)
1741  {
1742  //The PEM file contains a DSA private key
1743  *keyType = X509_KEY_TYPE_DSA;
1744  }
1745  else
1746 #endif
1747 #if (EC_SUPPORT == ENABLED)
1748  //PEM container with "EC PRIVATE KEY" label?
1749  if(pemDecodeFile(input, length, "EC PRIVATE KEY", NULL, &n, NULL,
1750  NULL) == NO_ERROR)
1751  {
1752  //Allocate a memory buffer to hold the ASN.1 data
1753  buffer = cryptoAllocMem(n);
1754 
1755  //Successful memory allocation?
1756  if(buffer != NULL)
1757  {
1758  //Decode the content of the PEM container
1759  error = pemDecodeFile(input, length, "EC PRIVATE KEY", buffer, &n,
1760  NULL, NULL);
1761 
1762  //Check status code
1763  if(!error)
1764  {
1765  //Read ECPrivateKey structure
1766  error = pkcs8ParseEcPrivateKey(buffer, n, &privateKeyInfo.ecParams,
1767  &privateKeyInfo.ecPrivateKey);
1768  }
1769 
1770  //Check status code
1771  if(!error)
1772  {
1773  //SM2 elliptic curve?
1774  if(!oidComp(privateKeyInfo.ecParams.namedCurve.value,
1775  privateKeyInfo.ecParams.namedCurve.length, SM2_OID,
1776  sizeof(SM2_OID)))
1777  {
1778  //The PEM file contains an SM2 private key
1779  *keyType = X509_KEY_TYPE_SM2;
1780  }
1781  else
1782  {
1783  //The PEM file contains an EC private key
1784  *keyType = X509_KEY_TYPE_EC;
1785  }
1786  }
1787 
1788  //Release previously allocated memory
1789  cryptoFreeMem(buffer);
1790  }
1791  else
1792  {
1793  //Failed to allocate memory
1794  error = ERROR_OUT_OF_MEMORY;
1795  }
1796  }
1797  else
1798 #endif
1799  //PEM container with "PRIVATE KEY" label?
1800  if(pemDecodeFile(input, length, "PRIVATE KEY", NULL, &n, NULL,
1801  NULL) == NO_ERROR)
1802  {
1803  //Allocate a memory buffer to hold the ASN.1 data
1804  buffer = cryptoAllocMem(n);
1805 
1806  //Successful memory allocation?
1807  if(buffer != NULL)
1808  {
1809  //Decode the content of the PEM container
1810  error = pemDecodeFile(input, length, "PRIVATE KEY", buffer, &n,
1811  NULL, NULL);
1812 
1813  //Check status code
1814  if(!error)
1815  {
1816  //Read the PrivateKeyInfo structure (refer to RFC 5208, section 5)
1817  error = pkcs8ParsePrivateKeyInfo(buffer, n, &privateKeyInfo);
1818  }
1819 
1820  //Check status code
1821  if(!error)
1822  {
1823  //Check public key algorithm identifier
1824  *keyType = x509GetPublicKeyType(privateKeyInfo.oid.value,
1825  privateKeyInfo.oid.length);
1826 
1827 #if (EC_SUPPORT == ENABLED)
1828  //EC public key identifier?
1829  if(*keyType == X509_KEY_TYPE_EC)
1830  {
1831  //SM2 elliptic curve?
1832  if(!oidComp(privateKeyInfo.ecParams.namedCurve.value,
1833  privateKeyInfo.ecParams.namedCurve.length, SM2_OID,
1834  sizeof(SM2_OID)))
1835  {
1836  //The PEM file contains an SM2 private key
1837  *keyType = X509_KEY_TYPE_SM2;
1838  }
1839  }
1840 #endif
1841  //Unknown algorithm identifier?
1842  if(*keyType == X509_KEY_TYPE_UNKNOWN)
1843  {
1844  //Report an error
1845  error = ERROR_WRONG_IDENTIFIER;
1846  }
1847  }
1848 
1849  //Release previously allocated memory
1850  cryptoFreeMem(buffer);
1851  }
1852  else
1853  {
1854  //Failed to allocate memory
1855  error = ERROR_OUT_OF_MEMORY;
1856  }
1857  }
1858  else
1859  {
1860  //The PEM file does not contain a valid private key
1861  error = ERROR_END_OF_FILE;
1862  }
1863 
1864  //Return status code
1865  return error;
1866 }
1867 
1868 #endif
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:163
error_t asn1ReadMpi(const uint8_t *data, size_t length, Asn1Tag *tag, Mpi *value)
Read a multiple-precision integer from the input stream.
Definition: asn1.c:553
ASN.1 (Abstract Syntax Notation One)
char char_t
Definition: compiler_port.h:48
General definitions for cryptographic algorithms.
#define cryptoAllocMem(size)
Definition: crypto.h:765
#define cryptoFreeMem(p)
Definition: crypto.h:770
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:110
uint8_t n
void dsaFreePrivateKey(DsaPrivateKey *key)
Release a DSA private key.
Definition: dsa.c:150
const uint8_t DSA_OID[7]
Definition: dsa.c:51
void dsaFreePublicKey(DsaPublicKey *key)
Release a DSA public key.
Definition: dsa.c:119
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:43
void ecFreePrivateKey(EcPrivateKey *key)
Release an EdDSA private key.
Definition: ec.c:192
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:165
const uint8_t SM2_OID[8]
Definition: ec_curves.c:92
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release an EdDSA private key.
Definition: eddsa.c:89
void eddsaFreePublicKey(EddsaPublicKey *key)
Release an EdDSA public key.
Definition: eddsa.c:61
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_DECRYPTION_FAILED
Definition: error.h:241
@ ERROR_END_OF_FILE
Definition: error.h:159
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t data[]
Definition: ethernet.h:222
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64
MPI (Multiple Precision Integer Arithmetic)
uint8_t p
Definition: ndp.h:300
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
OID (Object Identifier)
#define osMemset(p, value, length)
Definition: os_port.h:135
error_t pemDecodeFile(const char_t *input, size_t inputLen, const char_t *label, uint8_t *output, size_t *outputLen, PemHeader *header, size_t *consumed)
Convert PEM container to ASN.1 format.
Definition: pem_common.c:58
bool_t pemCompareString(const PemString *string, const char_t *value)
Compare a string against the supplied value.
Definition: pem_common.c:414
error_t pemDecryptMessage(const PemHeader *header, const char_t *password, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen)
PEM message decryption.
Definition: pem_decrypt.c:361
PEM file decryption.
error_t pemImportDhParameters(const char_t *input, size_t length, DhParameters *params)
Decode a PEM file containing Diffie-Hellman parameters.
Definition: pem_import.c:149
error_t pemImportEcPrivateKey(const char_t *input, size_t length, const char_t *password, EcPrivateKey *privateKey)
Decode a PEM file containing an EC private key.
Definition: pem_import.c:1163
error_t pemImportRsaPublicKey(const char_t *input, size_t length, RsaPublicKey *publicKey)
Decode a PEM file containing an RSA public key.
Definition: pem_import.c:260
error_t pemImportCsr(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen)
Decode a PEM file containing a certification signing request.
Definition: pem_import.c:121
error_t pemImportEcParameters(const char_t *input, size_t length, EcDomainParameters *params)
Decode a PEM file containing EC domain parameters.
Definition: pem_import.c:881
error_t pemImportEddsaPrivateKey(const char_t *input, size_t length, const char_t *password, EddsaPrivateKey *privateKey)
Decode a PEM file containing a EdDSA private key.
Definition: pem_import.c:1450
error_t pemImportDsaPublicKey(const char_t *input, size_t length, DsaPublicKey *publicKey)
Decode a PEM file containing a DSA public key.
Definition: pem_import.c:594
error_t pemGetPublicKeyType(const char_t *input, size_t length, X509KeyType *keyType)
Retrieve the type of a PEM-encoded public key.
Definition: pem_import.c:1598
error_t pemImportCrl(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen, size_t *consumed)
Decode a PEM file containing a certificate revocation list.
Definition: pem_import.c:92
error_t pemGetPrivateKeyType(const char_t *input, size_t length, X509KeyType *keyType)
Retrieve the type of a PEM-encoded private key.
Definition: pem_import.c:1707
error_t pemImportEcPublicKey(const char_t *input, size_t length, EcPublicKey *publicKey)
Decode a PEM file containing an EC public key.
Definition: pem_import.c:1081
error_t pemImportEddsaPublicKey(const char_t *input, size_t length, EddsaPublicKey *publicKey)
Decode a PEM file containing a EdDSA public key.
Definition: pem_import.c:1368
error_t pemImportDsaPrivateKey(const char_t *input, size_t length, const char_t *password, DsaPrivateKey *privateKey)
Decode a PEM file containing a DSA private key.
Definition: pem_import.c:676
error_t pemImportCertificate(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen, size_t *consumed)
Decode a PEM file containing a certificate.
Definition: pem_import.c:61
error_t pemImportRsaPrivateKey(const char_t *input, size_t length, const char_t *password, RsaPrivateKey *privateKey)
Decode a PEM file containing an RSA private key.
Definition: pem_import.c:389
PEM file import functions.
error_t pkcs5Decrypt(const X509AlgoId *encryptionAlgoId, const char_t *password, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen)
PKCS #5 decryption operation.
Definition: pkcs5_decrypt.c:61
PKCS #5 decryption routines.
error_t pkcs8ImportEcPrivateKey(const Pkcs8PrivateKeyInfo *privateKeyInfo, EcPrivateKey *privateKey)
Import an EC private key.
error_t pkcs8ImportRsaPrivateKey(const Pkcs8PrivateKeyInfo *privateKeyInfo, RsaPrivateKey *privateKey)
Import an RSA private key.
error_t pkcs8ParseRsaPrivateKey(const uint8_t *data, size_t length, Pkcs8RsaPrivateKey *rsaPrivateKey)
Parse RSAPrivateKey structure.
error_t pkcs8ParseDsaPrivateKey(const uint8_t *data, size_t length, X509DsaParameters *dsaParams, Pkcs8DsaPrivateKey *dsaPrivateKey)
Parse DSAPrivateKey structure.
error_t pkcs8ParseEcPrivateKey(const uint8_t *data, size_t length, X509EcParameters *ecParams, Pkcs8EcPrivateKey *ecPrivateKey)
Parse ECPrivateKey structure.
error_t pkcs8ParseEncryptedPrivateKeyInfo(const uint8_t *data, size_t length, Pkcs8EncryptedPrivateKeyInfo *encryptedPrivateKeyInfo)
Parse EncryptedPrivateKeyInfo structure.
error_t pkcs8ImportEddsaPrivateKey(const Pkcs8PrivateKeyInfo *privateKeyInfo, EddsaPrivateKey *privateKey)
Import an EdDSA private key.
error_t pkcs8ParsePrivateKeyInfo(const uint8_t *data, size_t length, Pkcs8PrivateKeyInfo *privateKeyInfo)
Parse PrivateKeyInfo structure.
error_t pkcs8ImportDsaPrivateKey(const Pkcs8PrivateKeyInfo *privateKeyInfo, DsaPrivateKey *privateKey)
Import a DSA private key.
PKCS #8 key parsing.
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:57
void rsaFreePrivateKey(RsaPrivateKey *key)
Release an RSA private key.
Definition: rsa.c:153
void rsaFreePublicKey(RsaPublicKey *key)
Release an RSA public key.
Definition: rsa.c:118
ASN.1 tag.
Definition: asn1.h:102
size_t totalLength
Definition: asn1.h:108
const uint8_t * value
Definition: asn1.h:107
size_t length
Definition: asn1.h:106
Diffie-Hellman parameters.
Definition: dh.h:49
Mpi p
Prime modulus.
Definition: dh.h:50
Mpi g
Generator.
Definition: dh.h:51
DSA private key.
Definition: dsa.h:72
DSA public key.
Definition: dsa.h:61
EC domain parameters.
Definition: ec.h:76
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
PEM encapsulated header.
Definition: pem_common.h:130
PemProcType procType
Definition: pem_common.h:131
PemString type
Definition: pem_common.h:110
Encrypted private key information.
Private key information.
Pkcs8DsaPrivateKey dsaPrivateKey
Pkcs8RsaPrivateKey rsaPrivateKey
X509OctetString oid
X509DsaParameters dsaParams
X509EcParameters ecParams
Pkcs8EcPrivateKey ecPrivateKey
RSA private key.
Definition: rsa.h:68
RSA public key.
Definition: rsa.h:57
EC parameters.
Definition: x509_common.h:763
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
X509RsaPublicKey rsaPublicKey
Definition: x509_common.h:788
X509OctetString oid
Definition: x509_common.h:785
X509EcParameters ecParams
Definition: x509_common.h:795
uint8_t length
Definition: tcp.h:368
X509KeyType x509GetPublicKeyType(const uint8_t *oid, size_t length)
Get the public key type that matches the specified OID.
Definition: x509_common.c:829
X509KeyType
Public Key types.
Definition: x509_common.h:578
@ X509_KEY_TYPE_DSA
Definition: x509_common.h:582
@ X509_KEY_TYPE_UNKNOWN
Definition: x509_common.h:579
@ X509_KEY_TYPE_SM2
Definition: x509_common.h:584
@ X509_KEY_TYPE_RSA
Definition: x509_common.h:580
@ X509_KEY_TYPE_EC
Definition: x509_common.h:583
error_t x509ImportEcPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, EcPublicKey *publicKey)
Import an EC public key.
error_t x509ParseEcParameters(const uint8_t *data, size_t length, X509EcParameters *ecParams)
Parse ECParameters structure.
error_t x509ImportEcParameters(const X509EcParameters *ecParams, EcDomainParameters *params)
Import EC domain parameters.
error_t x509ImportRsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, RsaPublicKey *publicKey)
Import an RSA public key.
error_t x509ImportEddsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, EddsaPublicKey *publicKey)
Import an EdDSA public key.
error_t x509ParseRsaPublicKey(const uint8_t *data, size_t length, X509RsaPublicKey *rsaPublicKey)
Parse RSAPublicKey structure.
error_t x509ImportDsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, DsaPublicKey *publicKey)
Import a DSA public key.
error_t x509ParseSubjectPublicKeyInfo(const uint8_t *data, size_t length, size_t *totalLength, X509SubjectPublicKeyInfo *publicKeyInfo)
Parse SubjectPublicKeyInfo structure.
Parsing of ASN.1 encoded keys.