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  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/crypto.h"
34 #include "certificate/pem_import.h"
35 #include "encoding/asn1.h"
36 #include "encoding/oid.h"
37 #include "encoding/base64.h"
38 #include "mpi/mpi.h"
39 #include "debug.h"
40 
41 //Check crypto library configuration
42 #if (PEM_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Decode a PEM file containing Diffie-Hellman parameters
47  * @param[in] input Pointer to the PEM structure
48  * @param[in] length Length of the PEM structure
49  * @param[out] params Diffie-Hellman parameters resulting from the parsing process
50  * @return Error code
51  **/
52 
53 error_t pemImportDhParameters(const char_t *input, size_t length, DhParameters *params)
54 {
55 #if (DH_SUPPORT == ENABLED)
56  error_t error;
57  size_t i;
58  size_t j;
59  int_t k;
60  char_t *buffer;
61  const uint8_t *data;
62  Asn1Tag tag;
63 
64  //Check parameters
65  if(input == NULL && length != 0)
67  if(params == NULL)
69 
70  //Search for the beginning tag
71  k = pemSearchTag(input, length, "-----BEGIN DH PARAMETERS-----", 29);
72  //Failed to find the specified tag?
73  if(k < 0)
74  return ERROR_INVALID_SYNTAX;
75 
76  //Advance the pointer over the tag
77  input += k + 29;
78  length -= k + 29;
79 
80  //Search for the end tag
81  k = pemSearchTag(input, length, "-----END DH PARAMETERS-----", 27);
82  //Invalid PEM file?
83  if(k <= 0)
84  return ERROR_INVALID_SYNTAX;
85 
86  //Length of the PEM structure
87  length = k;
88 
89  //Allocate a memory buffer to hold the decoded data
90  buffer = cryptoAllocMem(length);
91  //Failed to allocate memory?
92  if(buffer == NULL)
93  return ERROR_OUT_OF_MEMORY;
94 
95  //Copy the contents of the PEM structure
96  cryptoMemcpy(buffer, input, length);
97 
98  //Remove carriage returns and line feeds
99  for(i = 0, j = 0; i < length; i++)
100  {
101  if(buffer[i] != '\r' && buffer[i] != '\n')
102  buffer[j++] = buffer[i];
103  }
104 
105  //Start of exception handling block
106  do
107  {
108  //The PEM file is Base64 encoded...
109  error = base64Decode(buffer, j, buffer, &length);
110  //Failed to decode the file?
111  if(error)
112  break;
113 
114  //Point to the resulting ASN.1 structure
115  data = (uint8_t *) buffer;
116 
117  //Display ASN.1 structure
118  error = asn1DumpObject(data, length, 0);
119  //Any error to report?
120  if(error)
121  break;
122 
123  //The Diffie-Hellman parameters are encapsulated within a sequence
124  error = asn1ReadSequence(data, length, &tag);
125  //Failed to decode ASN.1 tag?
126  if(error)
127  break;
128 
129  //Point to the first field of the sequence
130  data = tag.value;
131  length = tag.length;
132 
133  //Read the prime modulus
134  error = asn1ReadTag(data, length, &tag);
135  //Failed to decode ASN.1 tag?
136  if(error)
137  break;
138 
139  //Enforce encoding, class and type
141  //The tag does not match the criteria?
142  if(error)
143  break;
144 
145  //Convert the prime modulus to a multiple precision integer
146  error = mpiReadRaw(&params->p, tag.value, tag.length);
147  //Any error to report?
148  if(error)
149  break;
150 
151  //Point to the next field
152  data += tag.totalLength;
153  length -= tag.totalLength;
154 
155  //Read the generator
156  error = asn1ReadTag(data, length, &tag);
157  //Failed to decode ASN.1 tag?
158  if(error)
159  break;
160 
161  //Enforce encoding, class and type
163  //The tag does not match the criteria?
164  if(error)
165  break;
166 
167  //Convert the generator to a multiple precision integer
168  error = mpiReadRaw(&params->g, tag.value, tag.length);
169  //Any error to report?
170  if(error)
171  break;
172 
173  //Debug message
174  TRACE_DEBUG("Diffie-Hellman parameters:\r\n");
175  TRACE_DEBUG(" Prime modulus:\r\n");
176  TRACE_DEBUG_MPI(" ", &params->p);
177  TRACE_DEBUG(" Generator:\r\n");
178  TRACE_DEBUG_MPI(" ", &params->g);
179 
180  //End of exception handling block
181  } while(0);
182 
183  //Release previously allocated memory
184  cryptoFreeMem(buffer);
185 
186  //Any error to report?
187  if(error)
188  {
189  //Clean up side effects
190  mpiFree(&params->p);
191  mpiFree(&params->g);
192  }
193 
194  //Return status code
195  return error;
196 #else
197  //Not implemented
198  return ERROR_NOT_IMPLEMENTED;
199 #endif
200 }
201 
202 
203 /**
204  * @brief Decode a PEM file containing a RSA private key
205  * @param[in] input Pointer to the PEM structure
206  * @param[in] length Length of the PEM structure
207  * @param[out] key RSA private key resulting from the parsing process
208  * @return Error code
209  **/
210 
212 {
213 #if (RSA_SUPPORT == ENABLED)
214  error_t error;
215  bool_t pkcs8Format;
216  size_t i;
217  size_t j;
218  int_t k;
219  char_t *buffer;
220  const uint8_t *data;
221  Asn1Tag tag;
222 
223  //Check parameters
224  if(input == NULL && length != 0)
226  if(key == NULL)
228 
229  //PKCS #8 format?
230  if(pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27) >= 0)
231  {
232  //Search for the beginning tag
233  k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27);
234  //Failed to find the specified tag?
235  if(k < 0)
236  return ERROR_INVALID_SYNTAX;
237 
238  //Advance the pointer over the tag
239  input += k + 27;
240  length -= k + 27;
241 
242  //Search for the end tag
243  k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25);
244  //Invalid PEM file?
245  if(k <= 0)
246  return ERROR_INVALID_SYNTAX;
247 
248  //Length of the PEM structure
249  length = k;
250 
251  //The structure of the private key is described by PKCS #8
252  pkcs8Format = TRUE;
253  }
254  else
255  {
256  //Search for the beginning tag
257  k = pemSearchTag(input, length, "-----BEGIN RSA PRIVATE KEY-----", 31);
258  //Failed to find the specified tag?
259  if(k < 0)
260  return ERROR_INVALID_SYNTAX;
261 
262  //Advance the pointer over the tag
263  input += k + 31;
264  length -= k + 31;
265 
266  //Search for the end tag
267  k = pemSearchTag(input, length, "-----END RSA PRIVATE KEY-----", 29);
268  //Invalid PEM file?
269  if(k <= 0)
270  return ERROR_INVALID_SYNTAX;
271 
272  //Length of the PEM structure
273  length = k;
274 
275  //The structure of the private key is described by PKCS #1
276  pkcs8Format = FALSE;
277  }
278 
279  //Allocate a memory buffer to hold the decoded data
280  buffer = cryptoAllocMem(length);
281  //Failed to allocate memory?
282  if(buffer == NULL)
283  return ERROR_OUT_OF_MEMORY;
284 
285  //Copy the contents of the PEM structure
286  cryptoMemcpy(buffer, input, length);
287 
288  //Remove carriage returns and line feeds
289  for(i = 0, j = 0; i < length; i++)
290  {
291  if(buffer[i] != '\r' && buffer[i] != '\n')
292  buffer[j++] = buffer[i];
293  }
294 
295  //Start of exception handling block
296  do
297  {
298  //The PEM file is Base64 encoded...
299  error = base64Decode(buffer, j, buffer, &length);
300  //Failed to decode the file?
301  if(error)
302  break;
303 
304  //Point to the resulting ASN.1 structure
305  data = (uint8_t *) buffer;
306 
307  //Display ASN.1 structure
308  error = asn1DumpObject(data, length, 0);
309  //Any error to report?
310  if(error)
311  break;
312 
313  //PKCS #8 format?
314  if(pkcs8Format)
315  {
316  //PKCS #8 describes a generic syntax for encoding private keys
317  error = asn1ReadSequence(data, length, &tag);
318  //Failed to decode ASN.1 tag?
319  if(error)
320  break;
321 
322  //Point to the first field of the sequence
323  data = tag.value;
324  length = tag.length;
325 
326  //Read the version field
327  error = asn1ReadTag(data, length, &tag);
328  //Failed to decode ASN.1 tag?
329  if(error)
330  break;
331 
332  //Enforce encoding, class and type
334  //The tag does not match the criteria?
335  if(error)
336  break;
337 
338  //Skip the version field
339  data += tag.totalLength;
340  length -= tag.totalLength;
341 
342  //Read the privateKeyAlgorithm field
343  error = asn1ReadSequence(data, length, &tag);
344  //Failed to decode ASN.1 tag?
345  if(error)
346  break;
347 
348  //Save the position of the privateKey field
349  data += tag.totalLength;
350  length -= tag.totalLength;
351 
352  //Read the algorithm identifier (OID)
353  error = asn1ReadTag(tag.value, tag.length, &tag);
354  //Failed to decode ASN.1 tag?
355  if(error)
356  break;
357 
358  //Check algorithm identifier
361  {
362  //Report an error
363  error = ERROR_WRONG_IDENTIFIER;
364  break;
365  }
366 
367  //The privateKey field is encapsulated within an octet string
368  error = asn1ReadTag(data, length, &tag);
369  //Failed to decode ASN.1 tag?
370  if(error)
371  break;
372 
373  //Enforce encoding, class and type
375  //The tag does not match the criteria?
376  if(error)
377  break;
378 
379  //Display ASN.1 structure
380  error = asn1DumpObject(tag.value, tag.length, 0);
381  //Any error to report?
382  if(error)
383  break;
384 
385  //Point to the content of the privateKey structure
386  data = tag.value;
387  length = tag.length;
388  }
389 
390  //Read the contents of the privateKey structure
391  error = asn1ReadSequence(data, length, &tag);
392  //Failed to decode ASN.1 tag?
393  if(error)
394  break;
395 
396  //Point to the first field of the sequence
397  data = tag.value;
398  length = tag.length;
399 
400  //Read the version field
401  error = asn1ReadTag(data, length, &tag);
402  //Failed to decode ASN.1 tag?
403  if(error)
404  break;
405 
406  //Enforce encoding, class and type
408  //The tag does not match the criteria?
409  if(error)
410  break;
411 
412  //Skip the version field
413  data += tag.totalLength;
414  length -= tag.totalLength;
415 
416  //Read the modulus
417  error = asn1ReadTag(data, length, &tag);
418  //Failed to decode ASN.1 tag?
419  if(error)
420  break;
421 
422  //Enforce encoding, class and type
424  //The tag does not match the criteria?
425  if(error)
426  break;
427 
428  //Convert the modulus to a multiple precision integer
429  error = mpiReadRaw(&key->n, tag.value, tag.length);
430  //Any error to report?
431  if(error)
432  break;
433 
434  //Point to the next field
435  data += tag.totalLength;
436  length -= tag.totalLength;
437 
438  //Read the public exponent
439  error = asn1ReadTag(data, length, &tag);
440  //Failed to decode ASN.1 tag?
441  if(error)
442  break;
443 
444  //Enforce encoding, class and type
446  //The tag does not match the criteria?
447  if(error)
448  break;
449 
450  //Convert the public exponent to a multiple precision integer
451  error = mpiReadRaw(&key->e, tag.value, tag.length);
452  //Any error to report?
453  if(error)
454  break;
455 
456  //Point to the next field
457  data += tag.totalLength;
458  length -= tag.totalLength;
459 
460  //Read the private exponent
461  error = asn1ReadTag(data, length, &tag);
462  //Failed to decode ASN.1 tag?
463  if(error)
464  break;
465 
466  //Enforce encoding, class and type
468  //The tag does not match the criteria?
469  if(error)
470  break;
471 
472  //Convert the private exponent to a multiple precision integer
473  error = mpiReadRaw(&key->d, tag.value, tag.length);
474  //Any error to report?
475  if(error)
476  break;
477 
478  //Point to the next field
479  data += tag.totalLength;
480  length -= tag.totalLength;
481 
482  //Read the first factor
483  error = asn1ReadTag(data, length, &tag);
484  //Failed to decode ASN.1 tag?
485  if(error)
486  break;
487 
488  //Enforce encoding, class and type
490  //The tag does not match the criteria?
491  if(error)
492  break;
493 
494  //Convert the first factor to a multiple precision integer
495  error = mpiReadRaw(&key->p, tag.value, tag.length);
496  //Any error to report?
497  if(error)
498  break;
499 
500  //Point to the next field
501  data += tag.totalLength;
502  length -= tag.totalLength;
503 
504  //Read the second factor
505  error = asn1ReadTag(data, length, &tag);
506  //Failed to decode ASN.1 tag?
507  if(error)
508  break;
509 
510  //Enforce encoding, class and type
512  //The tag does not match the criteria?
513  if(error)
514  break;
515 
516  //Convert the second factor to a multiple precision integer
517  error = mpiReadRaw(&key->q, tag.value, tag.length);
518  //Any error to report?
519  if(error)
520  break;
521 
522  //Point to the next field
523  data += tag.totalLength;
524  length -= tag.totalLength;
525 
526  //Read the first exponent
527  error = asn1ReadTag(data, length, &tag);
528  //Failed to decode ASN.1 tag?
529  if(error)
530  break;
531 
532  //Enforce encoding, class and type
534  //The tag does not match the criteria?
535  if(error)
536  break;
537 
538  //Convert the first exponent to a multiple precision integer
539  error = mpiReadRaw(&key->dp, tag.value, tag.length);
540  //Any error to report?
541  if(error)
542  break;
543 
544  //Point to the next field
545  data += tag.totalLength;
546  length -= tag.totalLength;
547 
548  //Read the second exponent
549  error = asn1ReadTag(data, length, &tag);
550  //Failed to decode ASN.1 tag?
551  if(error)
552  break;
553 
554  //Enforce encoding, class and type
556  //The tag does not match the criteria?
557  if(error)
558  break;
559 
560  //Convert the second exponent to a multiple precision integer
561  error = mpiReadRaw(&key->dq, tag.value, tag.length);
562  //Any error to report?
563  if(error)
564  break;
565 
566  //Point to the next field
567  data += tag.totalLength;
568  length -= tag.totalLength;
569 
570  //Read the coefficient
571  error = asn1ReadTag(data, length, &tag);
572  //Failed to decode ASN.1 tag?
573  if(error)
574  break;
575 
576  //Enforce encoding, class and type
578  //The tag does not match the criteria?
579  if(error)
580  break;
581 
582  //Convert the coefficient to a multiple precision integer
583  error = mpiReadRaw(&key->qinv, tag.value, tag.length);
584  //Any error to report?
585  if(error)
586  break;
587 
588  //Debug message
589  TRACE_DEBUG("RSA private key:\r\n");
590  TRACE_DEBUG(" Modulus:\r\n");
591  TRACE_DEBUG_MPI(" ", &key->n);
592  TRACE_DEBUG(" Public exponent:\r\n");
593  TRACE_DEBUG_MPI(" ", &key->e);
594  TRACE_DEBUG(" Private exponent:\r\n");
595  TRACE_DEBUG_MPI(" ", &key->d);
596  TRACE_DEBUG(" Prime 1:\r\n");
597  TRACE_DEBUG_MPI(" ", &key->p);
598  TRACE_DEBUG(" Prime 2:\r\n");
599  TRACE_DEBUG_MPI(" ", &key->q);
600  TRACE_DEBUG(" Prime exponent 1:\r\n");
601  TRACE_DEBUG_MPI(" ", &key->dp);
602  TRACE_DEBUG(" Prime exponent 2:\r\n");
603  TRACE_DEBUG_MPI(" ", &key->dq);
604  TRACE_DEBUG(" Coefficient:\r\n");
605  TRACE_DEBUG_MPI(" ", &key->qinv);
606 
607  //End of exception handling block
608  } while(0);
609 
610  //Release previously allocated memory
611  cryptoFreeMem(buffer);
612 
613  //Any error to report?
614  if(error)
615  {
616  //Clean up side effects
617  rsaFreePrivateKey(key);
618  }
619 
620  //Return status code
621  return error;
622 #else
623  //Not implemented
624  return ERROR_NOT_IMPLEMENTED;
625 #endif
626 }
627 
628 
629 /**
630  * @brief Decode a PEM file containing a DSA private key
631  * @param[in] input Pointer to the PEM structure
632  * @param[in] length Length of the PEM structure
633  * @param[out] key DSA private key resulting from the parsing process
634  * @return Error code
635  **/
636 
638 {
639 #if (DSA_SUPPORT == ENABLED)
640  error_t error;
641  bool_t pkcs8Format;
642  size_t i;
643  size_t j;
644  int_t k;
645  char_t *buffer;
646  const uint8_t *data;
647  const uint8_t *privateKey;
648  size_t privateKeyLen;
649  Asn1Tag tag;
650 
651  //Check parameters
652  if(input == NULL && length != 0)
654  if(key == NULL)
656 
657  //Initialize private key
658  privateKey = NULL;
659  privateKeyLen = 0;
660 
661  //PKCS #8 format?
662  if(pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27) >= 0)
663  {
664  //Search for the beginning tag
665  k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27);
666  //Failed to find the specified tag?
667  if(k < 0)
668  return ERROR_INVALID_SYNTAX;
669 
670  //Advance the pointer over the tag
671  input += k + 27;
672  length -= k + 27;
673 
674  //Search for the end tag
675  k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25);
676  //Invalid PEM file?
677  if(k <= 0)
678  return ERROR_INVALID_SYNTAX;
679 
680  //Length of the PEM structure
681  length = k;
682 
683  //The structure of the private key is described by PKCS #8
684  pkcs8Format = TRUE;
685  }
686  else
687  {
688  //Search for the beginning tag
689  k = pemSearchTag(input, length, "-----BEGIN DSA PRIVATE KEY-----", 31);
690  //Failed to find the specified tag?
691  if(k < 0)
692  return ERROR_INVALID_SYNTAX;
693 
694  //Advance the pointer over the tag
695  input += k + 31;
696  length -= k + 31;
697 
698  //Search for the end tag
699  k = pemSearchTag(input, length, "-----END DSA PRIVATE KEY-----", 29);
700  //Invalid PEM file?
701  if(k <= 0)
702  return ERROR_INVALID_SYNTAX;
703 
704  //Length of the PEM structure
705  length = k;
706 
707  //The structure of the private key is described by RFC 4211, section 4.2.2.2
708  pkcs8Format = FALSE;
709  }
710 
711  //Allocate a memory buffer to hold the decoded data
712  buffer = cryptoAllocMem(length);
713  //Failed to allocate memory?
714  if(buffer == NULL)
715  return ERROR_OUT_OF_MEMORY;
716 
717  //Copy the contents of the PEM structure
718  cryptoMemcpy(buffer, input, length);
719 
720  //Remove carriage returns and line feeds
721  for(i = 0, j = 0; i < length; i++)
722  {
723  if(buffer[i] != '\r' && buffer[i] != '\n')
724  buffer[j++] = buffer[i];
725  }
726 
727  //Start of exception handling block
728  do
729  {
730  //The PEM file is Base64 encoded...
731  error = base64Decode(buffer, j, buffer, &length);
732  //Failed to decode the file?
733  if(error)
734  break;
735 
736  //Point to the resulting ASN.1 structure
737  data = (uint8_t *) buffer;
738 
739  //Display ASN.1 structure
740  error = asn1DumpObject(data, length, 0);
741  //Any error to report?
742  if(error)
743  break;
744 
745  //PKCS #8 format?
746  if(pkcs8Format)
747  {
748  //PKCS #8 describes a generic syntax for encoding private keys
749  error = asn1ReadSequence(data, length, &tag);
750  //Failed to decode ASN.1 tag?
751  if(error)
752  break;
753 
754  //Point to the first field of the sequence
755  data = tag.value;
756  length = tag.length;
757 
758  //Read the version field
759  error = asn1ReadTag(data, length, &tag);
760  //Failed to decode ASN.1 tag?
761  if(error)
762  break;
763 
764  //Enforce encoding, class and type
766  //The tag does not match the criteria?
767  if(error)
768  break;
769 
770  //Skip the version field
771  data += tag.totalLength;
772  length -= tag.totalLength;
773 
774  //Read the privateKeyAlgorithm field
775  error = asn1ReadSequence(data, length, &tag);
776  //Failed to decode ASN.1 tag?
777  if(error)
778  break;
779 
780  //Save the position of the privateKey field
781  privateKey = data + tag.totalLength;
782  privateKeyLen = length - tag.totalLength;
783 
784  //Point to the first field of the sequence
785  data = tag.value;
786  length = tag.length;
787 
788  //Read the algorithm identifier (OID)
789  error = asn1ReadTag(data, length, &tag);
790  //Failed to decode ASN.1 tag?
791  if(error)
792  break;
793 
794  //Check algorithm identifier
795  error = asn1CheckOid(&tag, DSA_OID, sizeof(DSA_OID));
796  //Wrong identifier?
797  if(error)
798  break;
799 
800  //Point to the next field
801  data += tag.totalLength;
802  length -= tag.totalLength;
803 
804  //The DSA parameters are encapsulated within a sequence
805  error = asn1ReadSequence(data, length, &tag);
806  //Failed to decode ASN.1 tag?
807  if(error)
808  break;
809 
810  //Point to the first field of the sequence
811  data = tag.value;
812  length = tag.length;
813  }
814  else
815  {
816  //The DSA parameters and keys are encapsulated within a sequence
817  error = asn1ReadSequence(data, length, &tag);
818  //Failed to decode ASN.1 tag?
819  if(error)
820  break;
821 
822  //Point to the first field of the sequence
823  data = tag.value;
824  length = tag.length;
825 
826  //Read the version
827  error = asn1ReadTag(data, length, &tag);
828  //Failed to decode ASN.1 tag?
829  if(error)
830  break;
831 
832  //Enforce encoding, class and type
834  //The tag does not match the criteria?
835  if(error)
836  break;
837 
838  //Skip the version field
839  data += tag.totalLength;
840  length -= tag.totalLength;
841  }
842 
843  //Read p
844  error = asn1ReadTag(data, length, &tag);
845  //Failed to decode ASN.1 tag?
846  if(error)
847  break;
848 
849  //Enforce encoding, class and type
851  //The tag does not match the criteria?
852  if(error)
853  break;
854 
855  //Convert p to a multiple precision integer
856  error = mpiReadRaw(&key->p, tag.value, tag.length);
857  //Any error to report?
858  if(error)
859  break;
860 
861  //Point to the next field
862  data += tag.totalLength;
863  length -= tag.totalLength;
864 
865  //Read q
866  error = asn1ReadTag(data, length, &tag);
867  //Failed to decode ASN.1 tag?
868  if(error)
869  break;
870 
871  //Enforce encoding, class and type
873  //The tag does not match the criteria?
874  if(error)
875  break;
876 
877  //Convert q to a multiple precision integer
878  error = mpiReadRaw(&key->q, tag.value, tag.length);
879  //Any error to report?
880  if(error)
881  break;
882 
883  //Point to the next field
884  data += tag.totalLength;
885  length -= tag.totalLength;
886 
887  //Read g
888  error = asn1ReadTag(data, length, &tag);
889  //Failed to decode ASN.1 tag?
890  if(error)
891  break;
892 
893  //Enforce encoding, class and type
895  //The tag does not match the criteria?
896  if(error)
897  break;
898 
899  //Convert g to a multiple precision integer
900  error = mpiReadRaw(&key->g, tag.value, tag.length);
901  //Any error to report?
902  if(error)
903  break;
904 
905  //Point to the next field
906  data += tag.totalLength;
907  length -= tag.totalLength;
908 
909  //PKCS #8 format?
910  if(pkcs8Format)
911  {
912  //The privateKey field is encapsulated within an octet string
913  error = asn1ReadTag(privateKey, privateKeyLen, &tag);
914  //Failed to decode ASN.1 tag?
915  if(error)
916  break;
917 
918  //Enforce encoding, class and type
920  //The tag does not match the criteria?
921  if(error)
922  break;
923 
924  //Display ASN.1 structure
925  error = asn1DumpObject(tag.value, tag.length, 0);
926  //Any error to report?
927  if(error)
928  break;
929 
930  //Point to the content of the privateKey structure
931  data = tag.value;
932  length = tag.length;
933  }
934  else
935  {
936  //Read the public value
937  error = asn1ReadTag(data, length, &tag);
938  //Failed to decode ASN.1 tag?
939  if(error)
940  break;
941 
942  //Enforce encoding, class and type
944  //The tag does not match the criteria?
945  if(error)
946  break;
947 
948  //Skip the public value
949  data += tag.totalLength;
950  length -= tag.totalLength;
951  }
952 
953  //Read the private value
954  error = asn1ReadTag(data, length, &tag);
955  //Failed to decode ASN.1 tag?
956  if(error)
957  break;
958 
959  //Enforce encoding, class and type
961  //The tag does not match the criteria?
962  if(error)
963  break;
964 
965  //Convert the private value to a multiple precision integer
966  error = mpiReadRaw(&key->x, tag.value, tag.length);
967  //Any error to report?
968  if(error)
969  break;
970 
971  //Debug message
972  TRACE_DEBUG("DSA private key:\r\n");
973  TRACE_DEBUG(" p:\r\n");
974  TRACE_DEBUG_MPI(" ", &key->p);
975  TRACE_DEBUG(" q:\r\n");
976  TRACE_DEBUG_MPI(" ", &key->q);
977  TRACE_DEBUG(" g:\r\n");
978  TRACE_DEBUG_MPI(" ", &key->g);
979  TRACE_DEBUG(" x:\r\n");
980  TRACE_DEBUG_MPI(" ", &key->x);
981 
982  //End of exception handling block
983  } while(0);
984 
985  //Release previously allocated memory
986  cryptoFreeMem(buffer);
987 
988  //Any error to report?
989  if(error)
990  {
991  //Clean up side effects
992  dsaFreePrivateKey(key);
993  }
994 
995  //Return status code
996  return error;
997 #else
998  //Not implemented
999  return ERROR_NOT_IMPLEMENTED;
1000 #endif
1001 }
1002 
1003 
1004 /**
1005  * @brief Decode a PEM file containing EC domain parameters
1006  * @param[in] input Pointer to the PEM structure
1007  * @param[in] length Length of the PEM structure
1008  * @param[out] params EC domain parameters
1009  * @return Error code
1010  **/
1011 
1013 {
1014 #if (EC_SUPPORT == ENABLED)
1015  error_t error;
1016  bool_t pkcs8Format;
1017  size_t i;
1018  size_t j;
1019  int_t k;
1020  char_t *buffer;
1021  const uint8_t *data;
1022  Asn1Tag tag;
1023  const EcCurveInfo *curveInfo;
1024 
1025  //Check parameters
1026  if(input == NULL && length != 0)
1027  return ERROR_INVALID_PARAMETER;
1028  if(params == NULL)
1029  return ERROR_INVALID_PARAMETER;
1030 
1031  //PKCS #8 format?
1032  if(pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27) >= 0)
1033  {
1034  //Search for the beginning tag
1035  k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27);
1036  //Failed to find the specified tag?
1037  if(k < 0)
1038  return ERROR_INVALID_SYNTAX;
1039 
1040  //Advance the pointer over the tag
1041  input += k + 27;
1042  length -= k + 27;
1043 
1044  //Search for the end tag
1045  k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25);
1046  //Invalid PEM file?
1047  if(k <= 0)
1048  return ERROR_INVALID_SYNTAX;
1049 
1050  //Length of the PEM structure
1051  length = k;
1052 
1053  //The structure of the private key is described by PKCS #8
1054  pkcs8Format = TRUE;
1055  }
1056  else
1057  {
1058  //Search for the beginning tag
1059  k = pemSearchTag(input, length, "-----BEGIN EC PARAMETERS-----", 29);
1060  //Failed to find the specified tag?
1061  if(k < 0)
1062  return ERROR_INVALID_SYNTAX;
1063 
1064  //Advance the pointer over the tag
1065  input += k + 29;
1066  length -= k + 29;
1067 
1068  //Search for the end tag
1069  k = pemSearchTag(input, length, "-----END EC PARAMETERS-----", 27);
1070  //Invalid PEM file?
1071  if(k <= 0)
1072  return ERROR_INVALID_SYNTAX;
1073 
1074  //Length of the PEM structure
1075  length = k;
1076 
1077  //The structure of the private key is described by RFC 5915
1078  pkcs8Format = FALSE;
1079  }
1080 
1081  //Allocate a memory buffer to hold the decoded data
1082  buffer = cryptoAllocMem(length);
1083  //Failed to allocate memory?
1084  if(buffer == NULL)
1085  return ERROR_OUT_OF_MEMORY;
1086 
1087  //Copy the contents of the PEM structure
1088  cryptoMemcpy(buffer, input, length);
1089 
1090  //Remove carriage returns and line feeds
1091  for(i = 0, j = 0; i < length; i++)
1092  {
1093  if(buffer[i] != '\r' && buffer[i] != '\n')
1094  buffer[j++] = buffer[i];
1095  }
1096 
1097  //Start of exception handling block
1098  do
1099  {
1100  //The PEM file is Base64 encoded...
1101  error = base64Decode(buffer, j, buffer, &length);
1102  //Failed to decode the file?
1103  if(error)
1104  break;
1105 
1106  //Point to the resulting ASN.1 structure
1107  data = (uint8_t *) buffer;
1108 
1109  //Display ASN.1 structure
1110  error = asn1DumpObject(data, length, 0);
1111  //Any error to report?
1112  if(error)
1113  break;
1114 
1115  //PKCS #8 format?
1116  if(pkcs8Format)
1117  {
1118  //PKCS #8 describes a generic syntax for encoding private keys
1119  error = asn1ReadSequence(data, length, &tag);
1120  //Failed to decode ASN.1 tag?
1121  if(error)
1122  break;
1123 
1124  //Point to the first field of the sequence
1125  data = tag.value;
1126  length = tag.length;
1127 
1128  //Read the version field
1129  error = asn1ReadTag(data, length, &tag);
1130  //Failed to decode ASN.1 tag?
1131  if(error)
1132  break;
1133 
1134  //Enforce encoding, class and type
1136  //The tag does not match the criteria?
1137  if(error)
1138  break;
1139 
1140  //Skip the version field
1141  data += tag.totalLength;
1142  length -= tag.totalLength;
1143 
1144  //Read the privateKeyAlgorithm field
1145  error = asn1ReadSequence(data, length, &tag);
1146  //Failed to decode ASN.1 tag?
1147  if(error)
1148  break;
1149 
1150  //Point to the first field of the sequence
1151  data = tag.value;
1152  length = tag.length;
1153 
1154  //Read the algorithm identifier (OID)
1155  error = asn1ReadTag(data, length, &tag);
1156  //Failed to decode ASN.1 tag?
1157  if(error)
1158  break;
1159 
1160  //Check algorithm identifier
1161  error = asn1CheckOid(&tag, EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID));
1162  //Wrong identifier?
1163  if(error)
1164  break;
1165 
1166  //Point to the next field
1167  data += tag.totalLength;
1168  length += tag.totalLength;
1169  }
1170 
1171  //Read the curve identifier
1172  error = asn1ReadTag(data, length, &tag);
1173  //Failed to decode ASN.1 tag?
1174  if(error)
1175  break;
1176 
1177  //Enforce encoding, class and type
1178  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
1180  //The tag does not match the criteria?
1181  if(error)
1182  break;
1183 
1184  //Retrieve EC domain parameters
1185  curveInfo = ecGetCurveInfo(tag.value, tag.length);
1186  //Make sure the specified elliptic curve is supported
1187  if(curveInfo == NULL)
1188  {
1189  //Report an error
1190  error = ERROR_ILLEGAL_PARAMETER;
1191  //Exit immediately
1192  break;
1193  }
1194 
1195  //Load EC domain parameters
1196  error = ecLoadDomainParameters(params, curveInfo);
1197  //Any error to report?
1198  if(error)
1199  break;
1200 
1201  //End of exception handling block
1202  } while(0);
1203 
1204  //Release previously allocated memory
1205  cryptoFreeMem(buffer);
1206 
1207  //Any error to report?
1208  if(error)
1209  {
1210  //Clean up side effects
1211  ecFreeDomainParameters(params);
1212  }
1213 
1214  //Return status code
1215  return error;
1216 #else
1217  //Not implemented
1218  return ERROR_NOT_IMPLEMENTED;
1219 #endif
1220 }
1221 
1222 
1223 /**
1224  * @brief Decode a PEM file containing an EC private key
1225  * @param[in] input Pointer to the PEM structure
1226  * @param[in] length Length of the PEM structure
1227  * @param[out] key EC private key resulting from the parsing process
1228  * @return Error code
1229  **/
1230 
1231 error_t pemImportEcPrivateKey(const char_t *input, size_t length, Mpi *key)
1232 {
1233 #if (EC_SUPPORT == ENABLED)
1234  error_t error;
1235  bool_t pkcs8Format;
1236  size_t i;
1237  size_t j;
1238  int_t k;
1239  char_t *buffer;
1240  const uint8_t *data;
1241  Asn1Tag tag;
1242 
1243  //Check parameters
1244  if(input == NULL && length != 0)
1245  return ERROR_INVALID_PARAMETER;
1246  if(key == NULL)
1247  return ERROR_INVALID_PARAMETER;
1248 
1249  //PKCS #8 format?
1250  if(pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27) >= 0)
1251  {
1252  //Search for the beginning tag
1253  k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27);
1254  //Failed to find the specified tag?
1255  if(k < 0)
1256  return ERROR_INVALID_SYNTAX;
1257 
1258  //Advance the pointer over the tag
1259  input += k + 27;
1260  length -= k + 27;
1261 
1262  //Search for the end tag
1263  k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25);
1264  //Invalid PEM file?
1265  if(k <= 0)
1266  return ERROR_INVALID_SYNTAX;
1267 
1268  //Length of the PEM structure
1269  length = k;
1270 
1271  //The structure of the private key is described by PKCS #8
1272  pkcs8Format = TRUE;
1273  }
1274  else
1275  {
1276  //Search for the beginning tag
1277  k = pemSearchTag(input, length, "-----BEGIN EC PRIVATE KEY-----", 30);
1278  //Failed to find the specified tag?
1279  if(k < 0)
1280  return ERROR_INVALID_SYNTAX;
1281 
1282  //Advance the pointer over the tag
1283  input += k + 30;
1284  length -= k + 30;
1285 
1286  //Search for the end tag
1287  k = pemSearchTag(input, length, "-----END EC PRIVATE KEY-----", 28);
1288  //Invalid PEM file?
1289  if(k <= 0)
1290  return ERROR_INVALID_SYNTAX;
1291 
1292  //Length of the PEM structure
1293  length = k;
1294 
1295  //The structure of the private key is described by RFC 5915
1296  pkcs8Format = FALSE;
1297  }
1298 
1299  //Allocate a memory buffer to hold the decoded data
1300  buffer = cryptoAllocMem(length);
1301  //Failed to allocate memory?
1302  if(buffer == NULL)
1303  return ERROR_OUT_OF_MEMORY;
1304 
1305  //Copy the contents of the PEM structure
1306  cryptoMemcpy(buffer, input, length);
1307 
1308  //Remove carriage returns and line feeds
1309  for(i = 0, j = 0; i < length; i++)
1310  {
1311  if(buffer[i] != '\r' && buffer[i] != '\n')
1312  buffer[j++] = buffer[i];
1313  }
1314 
1315  //Start of exception handling block
1316  do
1317  {
1318  //The PEM file is Base64 encoded...
1319  error = base64Decode(buffer, j, buffer, &length);
1320  //Failed to decode the file?
1321  if(error)
1322  break;
1323 
1324  //Point to the resulting ASN.1 structure
1325  data = (uint8_t *) buffer;
1326 
1327  //Display ASN.1 structure
1328  error = asn1DumpObject(data, length, 0);
1329  //Any error to report?
1330  if(error)
1331  break;
1332 
1333  //PKCS #8 format?
1334  if(pkcs8Format)
1335  {
1336  //PKCS #8 describes a generic syntax for encoding private keys
1337  error = asn1ReadSequence(data, length, &tag);
1338  //Failed to decode ASN.1 tag?
1339  if(error)
1340  break;
1341 
1342  //Point to the first field of the sequence
1343  data = tag.value;
1344  length = tag.length;
1345 
1346  //Read the version field
1347  error = asn1ReadTag(data, length, &tag);
1348  //Failed to decode ASN.1 tag?
1349  if(error)
1350  break;
1351 
1352  //Enforce encoding, class and type
1354  //The tag does not match the criteria?
1355  if(error)
1356  break;
1357 
1358  //Skip the version field
1359  data += tag.totalLength;
1360  length -= tag.totalLength;
1361 
1362  //Read the privateKeyAlgorithm field
1363  error = asn1ReadSequence(data, length, &tag);
1364  //Failed to decode ASN.1 tag?
1365  if(error)
1366  break;
1367 
1368  //Save the position of the privateKey field
1369  data += tag.totalLength;
1370  length -= tag.totalLength;
1371 
1372  //Read the algorithm identifier (OID)
1373  error = asn1ReadTag(tag.value, tag.length, &tag);
1374  //Failed to decode ASN.1 tag?
1375  if(error)
1376  break;
1377 
1378  //Check algorithm identifier
1379  error = asn1CheckOid(&tag, EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID));
1380  //Wrong identifier?
1381  if(error)
1382  break;
1383 
1384  //The privateKey field is encapsulated within an octet string
1385  error = asn1ReadTag(data, length, &tag);
1386  //Failed to decode ASN.1 tag?
1387  if(error)
1388  break;
1389 
1390  //Enforce encoding, class and type
1392  //The tag does not match the criteria?
1393  if(error)
1394  break;
1395 
1396  //Display ASN.1 structure
1397  error = asn1DumpObject(tag.value, tag.length, 0);
1398  //Any error to report?
1399  if(error)
1400  break;
1401 
1402  //Point to the content of the privateKey structure
1403  data = tag.value;
1404  length = tag.length;
1405  }
1406 
1407  //Read the contents of the privateKey structure
1408  error = asn1ReadSequence(data, length, &tag);
1409  //Failed to decode ASN.1 tag?
1410  if(error)
1411  break;
1412 
1413  //Point to the first field of the sequence
1414  data = tag.value;
1415  length = tag.length;
1416 
1417  //Read the version field
1418  error = asn1ReadTag(data, length, &tag);
1419  //Failed to decode ASN.1 tag?
1420  if(error)
1421  break;
1422 
1423  //Enforce encoding, class and type
1425  //The tag does not match the criteria?
1426  if(error)
1427  break;
1428 
1429  //Skip the version field
1430  data += tag.totalLength;
1431  length -= tag.totalLength;
1432 
1433  //Read the privateKey field
1434  error = asn1ReadTag(data, length, &tag);
1435  //Failed to decode ASN.1 tag?
1436  if(error)
1437  break;
1438 
1439  //Enforce encoding, class and type
1441  //The tag does not match the criteria?
1442  if(error)
1443  break;
1444 
1445  //Read the EC private key
1446  error = mpiReadRaw(key, tag.value, tag.length);
1447  //Any error to report?
1448  if(error)
1449  break;
1450 
1451  //Debug message
1452  TRACE_DEBUG("EC private key:\r\n");
1453  TRACE_DEBUG_MPI(" ", key);
1454 
1455  //End of exception handling block
1456  } while(0);
1457 
1458  //Release previously allocated memory
1459  cryptoFreeMem(buffer);
1460 
1461  //Any error to report?
1462  if(error)
1463  {
1464  //Clean up side effects
1465  mpiFree(key);
1466  }
1467 
1468  //Return status code
1469  return error;
1470 #else
1471  //Not implemented
1472  return ERROR_NOT_IMPLEMENTED;
1473 #endif
1474 }
1475 
1476 
1477 /**
1478  * @brief Decode a PEM file containing a EdDSA private key
1479  * @param[in] input Pointer to the PEM structure
1480  * @param[in] length Length of the PEM structure
1481  * @param[out] key EdDSA private key resulting from the parsing process
1482  * @return Error code
1483  **/
1484 
1486 {
1487 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
1488  error_t error;
1489  size_t i;
1490  size_t j;
1491  int_t k;
1492  char_t *buffer;
1493  const uint8_t *data;
1494  Asn1Tag tag;
1495 
1496  //Check parameters
1497  if(input == NULL && length != 0)
1498  return ERROR_INVALID_PARAMETER;
1499  if(key == NULL)
1500  return ERROR_INVALID_PARAMETER;
1501 
1502  //Search for the beginning tag
1503  k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27);
1504  //Failed to find the specified tag?
1505  if(k < 0)
1506  return ERROR_INVALID_SYNTAX;
1507 
1508  //Advance the pointer over the tag
1509  input += k + 27;
1510  length -= k + 27;
1511 
1512  //Search for the end tag
1513  k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25);
1514  //Invalid PEM file?
1515  if(k <= 0)
1516  return ERROR_INVALID_SYNTAX;
1517 
1518  //Length of the PEM structure
1519  length = k;
1520 
1521  //Allocate a memory buffer to hold the decoded data
1522  buffer = cryptoAllocMem(length);
1523  //Failed to allocate memory?
1524  if(buffer == NULL)
1525  return ERROR_OUT_OF_MEMORY;
1526 
1527  //Copy the contents of the PEM structure
1528  cryptoMemcpy(buffer, input, length);
1529 
1530  //Remove carriage returns and line feeds
1531  for(i = 0, j = 0; i < length; i++)
1532  {
1533  if(buffer[i] != '\r' && buffer[i] != '\n')
1534  buffer[j++] = buffer[i];
1535  }
1536 
1537  //Start of exception handling block
1538  do
1539  {
1540  //The PEM file is Base64 encoded...
1541  error = base64Decode(buffer, j, buffer, &length);
1542  //Failed to decode the file?
1543  if(error)
1544  break;
1545 
1546  //Point to the resulting ASN.1 structure
1547  data = (uint8_t *) buffer;
1548 
1549  //Display ASN.1 structure
1550  error = asn1DumpObject(data, length, 0);
1551  //Any error to report?
1552  if(error)
1553  break;
1554 
1555  //The EdDSA private key is encapsulated within a sequence
1556  error = asn1ReadSequence(data, length, &tag);
1557  //Failed to decode ASN.1 tag?
1558  if(error)
1559  break;
1560 
1561  //Point to the first field of the sequence
1562  data = tag.value;
1563  length = tag.length;
1564 
1565  //Read the version field
1566  error = asn1ReadTag(data, length, &tag);
1567  //Failed to decode ASN.1 tag?
1568  if(error)
1569  break;
1570 
1571  //Enforce encoding, class and type
1573  //The tag does not match the criteria?
1574  if(error)
1575  break;
1576 
1577  //Skip the version field
1578  data += tag.totalLength;
1579  length -= tag.totalLength;
1580 
1581  //Read the privateKeyAlgorithm field
1582  error = asn1ReadSequence(data, length, &tag);
1583  //Failed to decode ASN.1 tag?
1584  if(error)
1585  break;
1586 
1587  //Save the position of the privateKey field
1588  data += tag.totalLength;
1589  length -= tag.totalLength;
1590 
1591  //Read the algorithm identifier (OID)
1592  error = asn1ReadTag(tag.value, tag.length, &tag);
1593  //Failed to decode ASN.1 tag?
1594  if(error)
1595  break;
1596 
1597  //Enforce encoding, class and type
1599  //Any error to report?
1600  if(error)
1601  break;
1602 
1603  //Check algorithm identifier
1604  if(oidComp(tag.value, tag.length, ED25519_OID, sizeof(ED25519_OID)) &&
1605  oidComp(tag.value, tag.length, ED448_OID, sizeof(ED448_OID)))
1606  {
1607  error = ERROR_WRONG_IDENTIFIER;
1608  break;
1609  }
1610 
1611  //The privateKey field is encapsulated within an octet string
1612  error = asn1ReadTag(data, length, &tag);
1613  //Failed to decode ASN.1 tag?
1614  if(error)
1615  break;
1616 
1617  //Enforce encoding, class and type
1619  //The tag does not match the criteria?
1620  if(error)
1621  break;
1622 
1623  //Display ASN.1 structure
1624  error = asn1DumpObject(tag.value, tag.length, 0);
1625  //Any error to report?
1626  if(error)
1627  break;
1628 
1629  //Point to the content of the privateKey structure
1630  data = tag.value;
1631  length = tag.length;
1632 
1633  //Read the privateKey field
1634  error = asn1ReadTag(data, length, &tag);
1635  //Failed to decode ASN.1 tag?
1636  if(error)
1637  break;
1638 
1639  //Enforce encoding, class and type
1641  //The tag does not match the criteria?
1642  if(error)
1643  break;
1644 
1645  //Read the EdDSA private key
1646  error = mpiImport(&key->d, tag.value, tag.length, MPI_FORMAT_LITTLE_ENDIAN);
1647  //Any error to report?
1648  if(error)
1649  break;
1650 
1651  //Debug message
1652  TRACE_DEBUG("EdDSA private key:\r\n");
1653  TRACE_DEBUG_MPI(" ", &key->d);
1654 
1655  //End of exception handling block
1656  } while(0);
1657 
1658  //Release previously allocated memory
1659  cryptoFreeMem(buffer);
1660 
1661  //Any error to report?
1662  if(error)
1663  {
1664  //Clean up side effects
1665  eddsaFreePrivateKey(key);
1666  }
1667 
1668  //Return status code
1669  return error;
1670 #else
1671  //Not implemented
1672  return ERROR_NOT_IMPLEMENTED;
1673 #endif
1674 }
1675 
1676 
1677 /**
1678  * @brief Decode a PEM file containing a certificate
1679  * @param[in,out] input Pointer to the PEM structure
1680  * @param[in,out] inputLen Length of the PEM structure
1681  * @param[in,out] output Pointer to the DER encoded certificate
1682  * @param[in,out] outputSize Size of the memory block that holds the DER certificate
1683  * @param[out] outputLen Length of the DER encoded certificate
1684  * @return Error code
1685  **/
1686 
1687 error_t pemImportCertificate(const char_t **input, size_t *inputLen,
1688  uint8_t **output, size_t *outputSize, size_t *outputLen)
1689 {
1690  error_t error;
1691  size_t length;
1692  size_t i;
1693  size_t j;
1694  int_t k;
1695 
1696  //Check parameters
1697  if(input == NULL || inputLen == NULL)
1698  return ERROR_INVALID_PARAMETER;
1699  if(output == NULL || outputSize == NULL || outputLen == NULL)
1700  return ERROR_INVALID_PARAMETER;
1701 
1702  //Search for the beginning tag
1703  k = pemSearchTag(*input, *inputLen, "-----BEGIN CERTIFICATE-----", 27);
1704  //Failed to find the specified tag?
1705  if(k < 0)
1706  return ERROR_END_OF_FILE;
1707 
1708  //Advance the input pointer over the tag
1709  *input += k + 27;
1710  *inputLen -= k + 27;
1711 
1712  //Search for the end tag
1713  k = pemSearchTag(*input, *inputLen, "-----END CERTIFICATE-----", 25);
1714  //Invalid PEM file?
1715  if(k <= 0)
1716  return ERROR_INVALID_SYNTAX;
1717 
1718  //Length of the PEM structure
1719  length = k;
1720 
1721  //Increase buffer size?
1722  if(length > *outputSize)
1723  {
1724  //Release previously allocated buffer if necessary
1725  if(*output != NULL)
1726  {
1727  cryptoFreeMem(*output);
1728  *output = NULL;
1729  *outputSize = 0;
1730  }
1731 
1732  //Allocate a memory buffer to hold the decoded data
1733  *output = cryptoAllocMem(length);
1734  //Failed to allocate memory?
1735  if(*output == NULL)
1736  return ERROR_OUT_OF_MEMORY;
1737 
1738  //Record the size of the buffer
1739  *outputSize = length;
1740  }
1741 
1742  //Copy the contents of the PEM structure
1743  cryptoMemcpy(*output, *input, length);
1744 
1745  //Advance the input pointer over the certificate
1746  *input += length + 25;
1747  *inputLen -= length + 25;
1748 
1749  //Remove carriage returns and line feeds
1750  for(i = 0, j = 0; i < length; i++)
1751  {
1752  if((*output)[i] != '\r' && (*output)[i] != '\n')
1753  (*output)[j++] = (*output)[i];
1754  }
1755 
1756  //Start of exception handling block
1757  do
1758  {
1759  //The PEM file is Base64 encoded...
1760  error = base64Decode((char_t *) *output, j, *output, &length);
1761  //Failed to decode the file?
1762  if(error)
1763  break;
1764 
1765  //Display ASN.1 structure
1766  error = asn1DumpObject(*output, length, 0);
1767  //Any error to report?
1768  if(error)
1769  break;
1770 
1771  //End of exception handling block
1772  } while(0);
1773 
1774  //Clean up side effects
1775  if(error)
1776  {
1777  //Release previously allocated memory
1778  cryptoFreeMem(*output);
1779  *output = NULL;
1780  *outputSize = 0;
1781  }
1782 
1783  //Size of the decoded certificate
1784  *outputLen = length;
1785  //Return status code
1786  return error;
1787 }
1788 
1789 
1790 /**
1791  * @brief Search a string for a given tag
1792  * @param[in] s String to search
1793  * @param[in] sLen Length of the string to search
1794  * @param[in] tag String containing the tag to search for
1795  * @param[in] tagLen Length of the tag
1796  * @return The index of the first occurrence of the tag in the string,
1797  * or -1 if the tag does not appear in the string
1798  **/
1799 
1800 int_t pemSearchTag(const char_t *s, size_t sLen, const char_t *tag, size_t tagLen)
1801 {
1802  size_t i;
1803  size_t j;
1804 
1805  //Loop through input string
1806  for(i = 0; (i + tagLen) <= sLen; i++)
1807  {
1808  //Compare current substring with the given tag
1809  for(j = 0; j < tagLen; j++)
1810  {
1811  if(s[i + j] != tag[j])
1812  break;
1813  }
1814 
1815  //Check whether the tag has been found
1816  if(j == tagLen)
1817  return i;
1818  }
1819 
1820  //The tag does not appear in the string
1821  return -1;
1822 }
1823 
1824 #endif
error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
Display an ASN.1 data object.
Definition: asn1.c:478
EC domain parameters.
Definition: ec.h:61
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:60
Arbitrary precision integer.
Definition: mpi.h:67
char char_t
Definition: compiler_port.h:41
Mpi p
First factor.
Definition: rsa.h:62
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
#define cryptoFreeMem(p)
Definition: crypto.h:578
Debugging facilities.
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:91
Mpi d
Private exponent.
Definition: rsa.h:61
size_t totalLength
Definition: asn1.h:101
#define cryptoAllocMem(size)
Definition: crypto.h:573
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:86
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
Elliptic curve parameters.
Definition: ec_curves.h:290
error_t pemImportEcPrivateKey(const char_t *input, size_t length, Mpi *key)
Decode a PEM file containing an EC private key.
Definition: pem_import.c:1231
error_t pemImportEddsaPrivateKey(const char_t *input, size_t length, EddsaPrivateKey *key)
Decode a PEM file containing a EdDSA private key.
Definition: pem_import.c:1485
error_t base64Decode(const char_t *input, size_t inputLen, void *output, size_t *outputLen)
Base64 decoding algorithm.
Definition: base64.c:186
error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
Check ASN.1 tag against a specified OID.
Definition: asn1.c:451
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release a DSA private key.
Definition: eddsa.c:84
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:511
error_t pemImportRsaPrivateKey(const char_t *input, size_t length, RsaPrivateKey *key)
Decode a PEM file containing a RSA private key.
Definition: pem_import.c:211
OID (Object Identifier)
ASN.1 tag.
Definition: asn1.h:94
#define TRUE
Definition: os_port.h:48
Mpi g
Generator.
Definition: dh.h:49
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:101
Mpi n
Modulus.
Definition: rsa.h:59
error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass, uint_t objType)
Enforce the type of a specified tag.
Definition: asn1.c:426
Mpi q
Second factor.
Definition: rsa.h:63
void dsaFreePrivateKey(DsaPrivateKey *key)
Release a DSA private key.
Definition: dsa.c:120
int_t pemSearchTag(const char_t *s, size_t sLen, const char_t *tag, size_t tagLen)
Search a string for a given tag.
Definition: pem_import.c:1800
Mpi g
Generator of the subgroup.
Definition: dsa.h:63
ASN.1 (Abstract Syntax Notation One)
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:158
Mpi e
Public exponent.
Definition: rsa.h:60
#define mpiReadRaw(r, data, length)
Definition: crypto_legacy.h:33
signed int int_t
Definition: compiler_port.h:42
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:73
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:50
size_t length
Definition: asn1.h:99
PEM file import functions.
const uint8_t ED448_OID[3]
Definition: ec_curves.c:96
error_t pemImportEcParameters(const char_t *input, size_t length, EcDomainParameters *params)
Decode a PEM file containing EC domain parameters.
Definition: pem_import.c:1012
EdDSA private key.
Definition: eddsa.h:56
Mpi x
Private key.
Definition: dsa.h:64
error_t pemImportDsaPrivateKey(const char_t *input, size_t length, DsaPrivateKey *key)
Decode a PEM file containing a DSA private key.
Definition: pem_import.c:637
Mpi p
Prime modulus.
Definition: dsa.h:61
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:99
error_t pemImportCertificate(const char_t **input, size_t *inputLen, uint8_t **output, size_t *outputSize, size_t *outputLen)
Decode a PEM file containing a certificate.
Definition: pem_import.c:1687
uint8_t s
const uint8_t ED25519_OID[3]
Definition: ec_curves.c:94
void rsaFreePrivateKey(RsaPrivateKey *key)
Release a RSA private key.
Definition: rsa.c:145
Mpi dq
second factor&#39;s CRT exponent
Definition: rsa.h:65
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:55
error_t
Error codes.
Definition: error.h:40
MPI (Multiple Precision Integer Arithmetic)
Base64 encoding scheme.
Mpi d
Private key.
Definition: eddsa.h:58
Mpi qinv
CRT coefficient.
Definition: rsa.h:66
uint8_t data[]
Definition: dtls_misc.h:167
DSA private key.
Definition: dsa.h:59
Mpi q
<Prime divisor
Definition: dsa.h:62
Mpi dp
First factor&#39;s CRT exponent.
Definition: rsa.h:64
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:45
const EcCurveInfo * ecGetCurveInfo(const uint8_t *oid, size_t length)
Get the elliptic curve that matches the specified OID.
Definition: ec_curves.c:2170
error_t pemImportDhParameters(const char_t *input, size_t length, DhParameters *params)
Decode a PEM file containing Diffie-Hellman parameters.
Definition: pem_import.c:53
uint8_t length
Definition: dtls_misc.h:140
RSA private key.
Definition: rsa.h:57
const uint8_t DSA_OID[7]
Definition: dsa.c:49
#define FALSE
Definition: os_port.h:44
Diffie-Hellman parameters.
Definition: dh.h:46
int bool_t
Definition: compiler_port.h:47
const uint8_t * value
Definition: asn1.h:100
Mpi p
Prime modulus.
Definition: dh.h:48
#define TRACE_DEBUG(...)
Definition: debug.h:98
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:45